]>
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.
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <linux/netlink.h>
17 #include <linux/rtnetlink.h>
21 #define ZNL_ALIGN(len) (((len)+3) & ~3)
23 void *znl_push(struct zbuf
*zb
, size_t n
)
25 return zbuf_pushn(zb
, ZNL_ALIGN(n
));
28 void *znl_pull(struct zbuf
*zb
, size_t n
)
30 return zbuf_pulln(zb
, ZNL_ALIGN(n
));
33 struct nlmsghdr
*znl_nlmsg_push(struct zbuf
*zb
, uint16_t type
, uint16_t flags
)
37 n
= znl_push(zb
, sizeof(*n
));
41 *n
= (struct nlmsghdr
){
42 .nlmsg_type
= type
, .nlmsg_flags
= flags
,
47 void znl_nlmsg_complete(struct zbuf
*zb
, struct nlmsghdr
*n
)
49 n
->nlmsg_len
= zb
->tail
- (uint8_t *)n
;
52 struct nlmsghdr
*znl_nlmsg_pull(struct zbuf
*zb
, struct zbuf
*payload
)
57 n
= znl_pull(zb
, sizeof(*n
));
61 plen
= n
->nlmsg_len
- sizeof(*n
);
62 zbuf_init(payload
, znl_pull(zb
, plen
), plen
, plen
);
63 zbuf_may_pulln(zb
, ZNL_ALIGN(plen
) - plen
);
68 struct rtattr
*znl_rta_push(struct zbuf
*zb
, uint16_t type
, const void *val
,
74 rta
= znl_push(zb
, ZNL_ALIGN(sizeof(*rta
)) + ZNL_ALIGN(len
));
78 *rta
= (struct rtattr
){
79 .rta_type
= type
, .rta_len
= ZNL_ALIGN(sizeof(*rta
)) + len
,
82 dst
= (uint8_t *)(rta
+ 1);
83 memcpy(dst
, val
, len
);
84 memset(dst
+ len
, 0, ZNL_ALIGN(len
) - len
);
89 struct rtattr
*znl_rta_push_u32(struct zbuf
*zb
, uint16_t type
, uint32_t val
)
91 return znl_rta_push(zb
, type
, &val
, sizeof(val
));
94 struct rtattr
*znl_rta_nested_push(struct zbuf
*zb
, uint16_t type
)
98 rta
= znl_push(zb
, sizeof(*rta
));
102 *rta
= (struct rtattr
){
108 void znl_rta_nested_complete(struct zbuf
*zb
, struct rtattr
*rta
)
110 size_t len
= zb
->tail
- (uint8_t *)rta
;
111 size_t align
= ZNL_ALIGN(len
) - len
;
114 void *dst
= zbuf_pushn(zb
, align
);
116 memset(dst
, 0, align
);
121 struct rtattr
*znl_rta_pull(struct zbuf
*zb
, struct zbuf
*payload
)
126 rta
= znl_pull(zb
, sizeof(*rta
));
130 if (rta
->rta_len
> sizeof(*rta
)) {
131 plen
= rta
->rta_len
- sizeof(*rta
);
132 zbuf_init(payload
, znl_pull(zb
, plen
), plen
, plen
);
134 zbuf_init(payload
, NULL
, 0, 0);
140 int znl_open(int protocol
, int groups
)
142 struct sockaddr_nl addr
;
143 int fd
, buf
= 128 * 1024;
145 fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
149 if (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
, 0) | O_NONBLOCK
) < 0)
151 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) < 0)
153 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &buf
, sizeof(buf
)) < 0)
156 memset(&addr
, 0, sizeof(addr
));
157 addr
.nl_family
= AF_NETLINK
;
158 addr
.nl_groups
= groups
;
159 if (bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)