]>
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
));
40 *n
= (struct nlmsghdr
) {
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
));
60 plen
= n
->nlmsg_len
- sizeof(*n
);
61 zbuf_init(payload
, znl_pull(zb
, plen
), plen
, plen
);
62 zbuf_may_pulln(zb
, ZNL_ALIGN(plen
) - plen
);
67 struct rtattr
*znl_rta_push(struct zbuf
*zb
, uint16_t type
, const void *val
, size_t len
)
72 rta
= znl_push(zb
, ZNL_ALIGN(sizeof(*rta
)) + ZNL_ALIGN(len
));
73 if (!rta
) return NULL
;
75 *rta
= (struct rtattr
) {
77 .rta_len
= ZNL_ALIGN(sizeof(*rta
)) + len
,
80 dst
= (uint8_t *)(rta
+1);
81 memcpy(dst
, val
, len
);
82 memset(dst
+len
, 0, ZNL_ALIGN(len
) - len
);
87 struct rtattr
*znl_rta_push_u32(struct zbuf
*zb
, uint16_t type
, uint32_t val
)
89 return znl_rta_push(zb
, type
, &val
, sizeof(val
));
92 struct rtattr
*znl_rta_nested_push(struct zbuf
*zb
, uint16_t type
)
96 rta
= znl_push(zb
, sizeof(*rta
));
97 if (!rta
) return NULL
;
99 *rta
= (struct rtattr
) {
105 void znl_rta_nested_complete(struct zbuf
*zb
, struct rtattr
*rta
)
107 size_t len
= zb
->tail
- (uint8_t*) rta
;
108 size_t align
= ZNL_ALIGN(len
) - len
;
111 void *dst
= zbuf_pushn(zb
, align
);
112 if (dst
) memset(dst
, 0, align
);
117 struct rtattr
*znl_rta_pull(struct zbuf
*zb
, struct zbuf
*payload
)
122 rta
= znl_pull(zb
, sizeof(*rta
));
123 if (!rta
) return NULL
;
125 if (rta
->rta_len
> sizeof(*rta
)) {
126 plen
= rta
->rta_len
- sizeof(*rta
);
127 zbuf_init(payload
, znl_pull(zb
, plen
), plen
, plen
);
129 zbuf_init(payload
, NULL
, 0, 0);
135 int znl_open(int protocol
, int groups
)
137 struct sockaddr_nl addr
;
138 int fd
, buf
= 128 * 1024;
140 fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
144 if (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
, 0) | O_NONBLOCK
) < 0)
146 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) < 0)
148 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &buf
, sizeof(buf
)) < 0)
151 memset(&addr
, 0, sizeof(addr
));
152 addr
.nl_family
= AF_NETLINK
;
153 addr
.nl_groups
= groups
;
154 if (bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0)