]>
git.proxmox.com Git - mirror_frr.git/blob - nhrpd/znl.c
1 /* Netlink helpers for zbuf
2 * Copyright (c) 2014-2015 Timo Teräs
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <linux/netlink.h>
21 #include <linux/rtnetlink.h>
25 #define ZNL_ALIGN(len) (((len)+3) & ~3)
27 void *znl_push(struct zbuf
*zb
, size_t n
)
29 return zbuf_pushn(zb
, ZNL_ALIGN(n
));
32 void *znl_pull(struct zbuf
*zb
, size_t n
)
34 return zbuf_pulln(zb
, ZNL_ALIGN(n
));
37 struct nlmsghdr
*znl_nlmsg_push(struct zbuf
*zb
, uint16_t type
, uint16_t flags
)
41 n
= znl_push(zb
, sizeof(*n
));
45 *n
= (struct nlmsghdr
){
46 .nlmsg_type
= type
, .nlmsg_flags
= flags
,
51 void znl_nlmsg_complete(struct zbuf
*zb
, struct nlmsghdr
*n
)
53 n
->nlmsg_len
= zb
->tail
- (uint8_t *)n
;
56 struct nlmsghdr
*znl_nlmsg_pull(struct zbuf
*zb
, struct zbuf
*payload
)
61 n
= znl_pull(zb
, sizeof(*n
));
65 plen
= n
->nlmsg_len
- sizeof(*n
);
66 zbuf_init(payload
, znl_pull(zb
, plen
), plen
, plen
);
67 zbuf_may_pulln(zb
, ZNL_ALIGN(plen
) - plen
);
72 struct rtattr
*znl_rta_push(struct zbuf
*zb
, uint16_t type
, const void *val
,
78 rta
= znl_push(zb
, ZNL_ALIGN(sizeof(*rta
)) + ZNL_ALIGN(len
));
82 *rta
= (struct rtattr
){
83 .rta_type
= type
, .rta_len
= ZNL_ALIGN(sizeof(*rta
)) + len
,
86 dst
= (uint8_t *)(rta
+ 1);
87 memcpy(dst
, val
, len
);
88 memset(dst
+ len
, 0, ZNL_ALIGN(len
) - len
);
93 struct rtattr
*znl_rta_push_u32(struct zbuf
*zb
, uint16_t type
, uint32_t val
)
95 return znl_rta_push(zb
, type
, &val
, sizeof(val
));
98 struct rtattr
*znl_rta_nested_push(struct zbuf
*zb
, uint16_t type
)
102 rta
= znl_push(zb
, sizeof(*rta
));
106 *rta
= (struct rtattr
){
112 void znl_rta_nested_complete(struct zbuf
*zb
, struct rtattr
*rta
)
114 size_t len
= zb
->tail
- (uint8_t *)rta
;
115 size_t align
= ZNL_ALIGN(len
) - len
;
118 void *dst
= zbuf_pushn(zb
, align
);
120 memset(dst
, 0, align
);
125 struct rtattr
*znl_rta_pull(struct zbuf
*zb
, struct zbuf
*payload
)
130 rta
= znl_pull(zb
, sizeof(*rta
));
134 if (rta
->rta_len
> sizeof(*rta
)) {
135 plen
= rta
->rta_len
- sizeof(*rta
);
136 zbuf_init(payload
, znl_pull(zb
, plen
), plen
, plen
);
138 zbuf_init(payload
, NULL
, 0, 0);
144 int znl_open(int protocol
, int groups
)
146 struct sockaddr_nl addr
;
147 int fd
, buf
= 128 * 1024;
149 fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
153 if (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
, 0) | O_NONBLOCK
) < 0)
155 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) < 0)
157 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &buf
, sizeof(buf
)) < 0)
160 memset(&addr
, 0, sizeof(addr
));
161 addr
.nl_family
= AF_NETLINK
;
162 addr
.nl_groups
= groups
;
163 if (bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)