26 #ifdef HAVE_LINUX_RTNETLINK_H 35 #define RTNL_BUFSIZE 8192 38 static int io_rtnl_getattr_func(
struct ifinfomsg *ifi,
struct rtattr *rta,
39 unsigned short rtalen,
void *data);
41 static int io_rtnl_recv(
int fd,
int (*func)(
struct nlmsghdr *nlh,
void *data),
43 static int io_rtnl_recv_ack(
int fd);
44 static int io_rtnl_recv_newlink(
46 static int io_rtnl_recv_newlink_func(
struct nlmsghdr *nlh,
void *data);
48 static ssize_t io_rtnl_send(
int fd,
struct iovec *iov,
int iovlen);
49 static ssize_t io_rtnl_send_getlink(
int fd, __u32 seq, __u32 pid);
50 static ssize_t io_rtnl_send_newlink(
int fd, __u32 seq, __u32 pid,
int ifi_index,
51 unsigned int ifi_flags,
struct rtattr *rta,
59 int fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
65 struct sockaddr_nl addr = {
66 .nl_family = AF_NETLINK, .nl_pid = pid, .nl_groups = groups
70 if (
__unlikely(bind(fd, (
struct sockaddr *)&addr,
sizeof(addr))
88 unsigned int ifi_flags,
struct rtattr *rta,
89 unsigned short rtalen)
92 if (
__unlikely(io_rtnl_send_newlink(fd, seq, pid, ifi_index, ifi_flags,
96 return io_rtnl_recv_ack(fd);
103 if (
__unlikely(io_rtnl_send_getlink(fd, seq, pid) == -1))
105 return io_rtnl_recv_newlink(fd, func, data);
110 unsigned int *pifi_flags,
unsigned short type,
void *data,
111 unsigned short payload)
113 assert(data || !payload);
122 unsigned int *pifi_flags;
125 unsigned short payload;
126 } args = { ifi_index, pifi_flags, type, data, payload };
145 io_rtnl_getattr_func(
struct ifinfomsg *ifi,
struct rtattr *rta,
146 unsigned short rtalen,
void *data)
152 unsigned int *pifi_flags;
155 unsigned short payload;
162 if (!pargs->ifi_index || pargs->ifi_index != ifi->ifi_index)
164 pargs->ifi_index = 0;
166 if (pargs->pifi_flags)
167 *pargs->pifi_flags = ifi->ifi_flags;
175 unsigned short payload = RTA_PAYLOAD(rta);
177 memcpy(pargs->data, RTA_DATA(rta),
178 MIN(pargs->payload, payload));
179 pargs->payload = payload;
186 unsigned int ifi_flags,
unsigned short type,
const void *data,
187 unsigned short payload)
189 assert(data || !payload);
191 char buf[RTA_SPACE(payload)];
193 struct rtattr *rta = (
struct rtattr *)buf;
194 *rta = (
struct rtattr){ .rta_len = RTA_LENGTH(payload),
197 memcpy(RTA_DATA(rta), data, payload);
200 fd, seq, pid, ifi_index, ifi_flags, rta, rta->rta_len);
204 io_rtnl_recv(
int fd,
int (*func)(
struct nlmsghdr *nlh,
void *data),
void *data)
206 char buf[RTNL_BUFSIZE] = { 0 };
216 len = recv(fd, buf,
sizeof(buf), 0);
217 }
while (
__unlikely(len == -1 && errno == EINTR));
226 struct nlmsghdr *nlh = (
struct nlmsghdr *)buf;
227 for (; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
228 if (nlh->nlmsg_type == NLMSG_DONE
229 || !(nlh->nlmsg_flags & NLM_F_MULTI))
231 if (nlh->nlmsg_type == NLMSG_ERROR) {
232 struct nlmsgerr *err = NLMSG_DATA(nlh);
238 if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
240 if (
__unlikely(func && func(nlh, data) && !result)) {
252 io_rtnl_recv_ack(
int fd)
254 return io_rtnl_recv(fd, NULL, NULL);
263 } args = { func, data };
265 return io_rtnl_recv(fd, &io_rtnl_recv_newlink_func, &args);
269 io_rtnl_recv_newlink_func(
struct nlmsghdr *nlh,
void *data)
278 if (nlh->nlmsg_type != RTM_NEWLINK)
284 return pargs->func(NLMSG_DATA(nlh), IFLA_RTA(NLMSG_DATA(nlh)),
285 IFLA_PAYLOAD(nlh), pargs->data);
289 io_rtnl_send(
int fd,
struct iovec *iov,
int iovlen)
291 struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
293 struct msghdr msg = { .msg_name = &addr,
294 .msg_namelen =
sizeof(addr),
296 .msg_iovlen = iovlen };
302 result = sendmsg(fd, &msg, 0);
303 }
while (
__unlikely(result == -1 && errno == EINTR));
308 io_rtnl_send_getlink(
int fd, __u32 seq, __u32 pid)
310 char buf[NLMSG_SPACE(
sizeof(
struct rtgenmsg))] = { 0 };
312 struct nlmsghdr *nlh = (
struct nlmsghdr *)buf;
314 *nlh = (
struct nlmsghdr){
315 .nlmsg_len = NLMSG_SPACE(
sizeof(
struct rtgenmsg)),
316 .nlmsg_type = RTM_GETLINK,
317 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
322 struct rtgenmsg *rtgen = NLMSG_DATA(nlh);
323 *rtgen = (
struct rtgenmsg){ .rtgen_family = AF_UNSPEC };
325 struct iovec iov[] = { { buf,
sizeof(buf) } };
326 return io_rtnl_send(fd, iov,
sizeof(iov) /
sizeof(*iov));
330 io_rtnl_send_newlink(
int fd, __u32 seq, __u32 pid,
int ifi_index,
331 unsigned int ifi_flags,
struct rtattr *rta,
unsigned int rtalen)
333 assert(rta || !rtalen);
335 char buf[NLMSG_SPACE(
sizeof(
struct ifinfomsg))] = { 0 };
337 struct nlmsghdr *nlh = (
struct nlmsghdr *)buf;
338 *nlh = (
struct nlmsghdr){
339 .nlmsg_len = NLMSG_SPACE(
sizeof(
struct ifinfomsg)) + rtalen,
340 .nlmsg_type = RTM_NEWLINK,
341 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
346 struct ifinfomsg *ifi = NLMSG_DATA(nlh);
347 *ifi = (
struct ifinfomsg){ .ifi_family = AF_UNSPEC,
348 .ifi_index = ifi_index,
349 .ifi_flags = ifi_flags,
350 .ifi_change = 0xffffffffu };
352 struct iovec iov[] = { { buf,
sizeof(buf) }, { rta, rtalen } };
353 return io_rtnl_send(fd, iov,
sizeof(iov) /
sizeof(*iov));
356 #endif // #HAVE_LINUX_RTNETLINK_H int io_rtnl_setattr(int fd, __u32 seq, __u32 pid, int ifi_index, unsigned int ifi_flags, unsigned short type, const void *data, unsigned short payload)
Invokes io_rtnl_newlink() to set at most one attribute of the specified network interface.
int io_rtnl_getlink(int fd, __u32 seq, __u32 pid, io_rtnl_newlink_func_t *func, void *data)
Sends an RTM_GETLINK request and invokes the specified callback function for each received network in...
This header file is part of the C11 and POSIX compatibility library; it includes <string.h> and defines any missing functionality.
static struct rtattr * io_rta_find(struct rtattr *rta, unsigned short len, unsigned short type)
Finds an attribute in a list of attributes.
int io_rtnl_socket(__u32 pid, __u32 groups)
Opens an rtnetlink socket.
#define MIN(a, b)
Returns the minimum of a and b.
int io_rtnl_newlink(int fd, __u32 seq, __u32 pid, int ifi_index, unsigned int ifi_flags, struct rtattr *rta, unsigned short rtalen)
Sends an RTM_NEWLINK request and waits until the acknowledgment is received.
int io_rtnl_newlink_func_t(struct ifinfomsg *ifi, struct rtattr *rta, unsigned short rtalen, void *data)
The type of a callback function invoked when an RTM_NEWLINK response is received. ...
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
This is the internal header file of the I/O library.
int io_rtnl_getattr(int fd, __u32 seq, __u32 pid, int ifi_index, unsigned int *pifi_flags, unsigned short type, void *data, unsigned short payload)
Invokes io_rtnl_getlink() and retrieves a single attribute of the specified network interface...
int fd
The native file descriptor.
This is the internal header file of the rtnetlink declarations.