2 * libnetlink.c RTnetlink service routines.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
18 #include <net/if_arp.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
27 #include "libnetlink.h"
29 #ifndef DEFAULT_RTNL_BUFSIZE
30 #define DEFAULT_RTNL_BUFSIZE 4 * 1024 * 1024
33 #ifndef RTNL_SND_BUFSIZE
34 #define RTNL_SND_BUFSIZE DEFAULT_RTNL_BUFSIZE
36 #ifndef RTNL_RCV_BUFSIZE
37 #define RTNL_RCV_BUFSIZE DEFAULT_RTNL_BUFSIZE
40 void rtnl_close(struct rtnl_handle
*rth
)
45 int rtnl_open_byproto(struct rtnl_handle
*rth
, unsigned subscriptions
,
49 int sndbuf
= RTNL_SND_BUFSIZE
;
50 int rcvbuf
= RTNL_RCV_BUFSIZE
;
53 memset(rth
, 0, sizeof(*rth
));
55 rth
->fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
57 ERROR("Cannot open netlink socket");
61 if (setsockopt(rth
->fd
, SOL_SOCKET
, SO_SNDBUF
, &sndbuf
, sizeof(sndbuf
))
67 if (setsockopt(rth
->fd
, SOL_SOCKET
, SO_RCVBUF
, &rcvbuf
, sizeof(rcvbuf
))
73 if (setsockopt(rth
->fd
, SOL_NETLINK
, NETLINK_NO_ENOBUFS
, &yes
, sizeof(yes
)) < 0)
74 ERROR("NETLINK_NO_EBUFS");
76 memset(&rth
->local
, 0, sizeof(rth
->local
));
77 rth
->local
.nl_family
= AF_NETLINK
;
78 rth
->local
.nl_groups
= subscriptions
;
80 if (bind(rth
->fd
, (struct sockaddr
*)&rth
->local
, sizeof(rth
->local
)) <
82 ERROR("Cannot bind netlink socket");
85 addr_len
= sizeof(rth
->local
);
86 if (getsockname(rth
->fd
, (struct sockaddr
*)&rth
->local
, &addr_len
) < 0) {
87 ERROR("Cannot getsockname");
90 if (addr_len
!= sizeof(rth
->local
)) {
91 ERROR("Wrong address length %d\n", addr_len
);
94 if (rth
->local
.nl_family
!= AF_NETLINK
) {
95 ERROR("Wrong address family %d\n",
96 rth
->local
.nl_family
);
99 rth
->seq
= time(NULL
);
103 int rtnl_open(struct rtnl_handle
*rth
, unsigned subscriptions
)
105 return rtnl_open_byproto(rth
, subscriptions
, NETLINK_ROUTE
);
108 int rtnl_wilddump_request(struct rtnl_handle
*rth
, int family
, int type
)
114 struct sockaddr_nl nladdr
;
116 memset(&nladdr
, 0, sizeof(nladdr
));
117 nladdr
.nl_family
= AF_NETLINK
;
119 memset(&req
, 0, sizeof(req
));
120 req
.nlh
.nlmsg_len
= sizeof(req
);
121 req
.nlh
.nlmsg_type
= type
;
122 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
;
123 req
.nlh
.nlmsg_pid
= 0;
124 req
.nlh
.nlmsg_seq
= rth
->dump
= ++rth
->seq
;
125 req
.g
.rtgen_family
= family
;
127 return sendto(rth
->fd
, (void *)&req
, sizeof(req
), 0,
128 (struct sockaddr
*)&nladdr
, sizeof(nladdr
));
131 int rtnl_send(struct rtnl_handle
*rth
, const char *buf
, int len
)
133 struct sockaddr_nl nladdr
;
135 memset(&nladdr
, 0, sizeof(nladdr
));
136 nladdr
.nl_family
= AF_NETLINK
;
138 return sendto(rth
->fd
, buf
, len
, 0, (struct sockaddr
*)&nladdr
,
142 int rtnl_dump_request(struct rtnl_handle
*rth
, int type
, void *req
, int len
)
145 struct sockaddr_nl nladdr
;
146 struct iovec iov
[2] = {
147 {.iov_base
= &nlh
,.iov_len
= sizeof(nlh
)}
149 {.iov_base
= req
,.iov_len
= len
}
151 struct msghdr msg
= {
153 .msg_namelen
= sizeof(nladdr
),
158 memset(&nladdr
, 0, sizeof(nladdr
));
159 nladdr
.nl_family
= AF_NETLINK
;
161 nlh
.nlmsg_len
= NLMSG_LENGTH(len
);
162 nlh
.nlmsg_type
= type
;
163 nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
;
165 nlh
.nlmsg_seq
= rth
->dump
= ++rth
->seq
;
167 return sendmsg(rth
->fd
, &msg
, 0);
170 int rtnl_dump_filter(struct rtnl_handle
*rth
,
171 rtnl_filter_t filter
,
172 void *arg1
, rtnl_filter_t junk
, void *arg2
)
174 struct sockaddr_nl nladdr
;
176 struct msghdr msg
= {
178 .msg_namelen
= sizeof(nladdr
),
189 iov
.iov_len
= sizeof(buf
);
190 status
= recvmsg(rth
->fd
, &msg
, 0);
200 ERROR("EOF on netlink\n");
204 h
= (struct nlmsghdr
*)buf
;
205 while (NLMSG_OK(h
, status
)) {
208 if (nladdr
.nl_pid
!= 0 ||
209 h
->nlmsg_pid
!= rth
->local
.nl_pid
||
210 h
->nlmsg_seq
!= rth
->dump
) {
212 err
= junk(&nladdr
, h
, arg2
);
219 if (h
->nlmsg_type
== NLMSG_DONE
)
221 if (h
->nlmsg_type
== NLMSG_ERROR
) {
222 struct nlmsgerr
*err
=
223 (struct nlmsgerr
*)NLMSG_DATA(h
);
225 NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
226 ERROR("ERROR truncated\n");
229 INFO("RTNETLINK answers");
233 err
= filter(&nladdr
, h
, arg1
);
238 h
= NLMSG_NEXT(h
, status
);
240 if (msg
.msg_flags
& MSG_TRUNC
) {
241 ERROR("Message truncated\n");
245 ERROR("!!!Remnant of size %d\n", status
);
251 int rtnl_talk(struct rtnl_handle
*rtnl
, struct nlmsghdr
*n
, pid_t peer
,
252 unsigned groups
, struct nlmsghdr
*answer
,
253 rtnl_filter_t junk
, void *jarg
)
258 struct sockaddr_nl nladdr
;
260 .iov_base
= (void *)n
,
261 .iov_len
= n
->nlmsg_len
263 struct msghdr msg
= {
265 .msg_namelen
= sizeof(nladdr
),
271 memset(&nladdr
, 0, sizeof(nladdr
));
272 nladdr
.nl_family
= AF_NETLINK
;
273 nladdr
.nl_pid
= peer
;
274 nladdr
.nl_groups
= groups
;
276 n
->nlmsg_seq
= seq
= ++rtnl
->seq
;
279 n
->nlmsg_flags
|= NLM_F_ACK
;
281 status
= sendmsg(rtnl
->fd
, &msg
, 0);
284 ERROR("Cannot talk to rtnetlink");
288 memset(buf
, 0, sizeof(buf
));
293 iov
.iov_len
= sizeof(buf
);
294 status
= recvmsg(rtnl
->fd
, &msg
, 0);
303 ERROR("EOF on netlink\n");
306 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
307 ERROR("sender address length == %d\n",
311 for (h
= (struct nlmsghdr
*)buf
; status
>= sizeof(*h
);) {
313 int len
= h
->nlmsg_len
;
314 int l
= len
- sizeof(*h
);
316 if (l
< 0 || len
> status
) {
317 if (msg
.msg_flags
& MSG_TRUNC
) {
318 ERROR("Truncated message\n");
322 "!!!malformed message: len=%d\n", len
);
326 if (nladdr
.nl_pid
!= peer
||
327 h
->nlmsg_pid
!= rtnl
->local
.nl_pid
||
328 h
->nlmsg_seq
!= seq
) {
330 err
= junk(&nladdr
, h
, jarg
);
334 /* Don't forget to skip that message. */
335 status
-= NLMSG_ALIGN(len
);
336 h
= (struct nlmsghdr
*)((char *)h
+
341 if (h
->nlmsg_type
== NLMSG_ERROR
) {
342 struct nlmsgerr
*err
=
343 (struct nlmsgerr
*)NLMSG_DATA(h
);
344 if (l
< sizeof(struct nlmsgerr
)) {
345 ERROR("ERROR truncated\n");
354 ERROR("RTNETLINK answers");
359 memcpy(answer
, h
, h
->nlmsg_len
);
363 ERROR("Unexpected reply!!!\n");
365 status
-= NLMSG_ALIGN(len
);
366 h
= (struct nlmsghdr
*)((char *)h
+ NLMSG_ALIGN(len
));
368 if (msg
.msg_flags
& MSG_TRUNC
) {
369 ERROR("Message truncated\n");
373 ERROR("!!!Remnant of size %d\n", status
);
379 int rtnl_listen(struct rtnl_handle
*rtnl
, rtnl_filter_t handler
, void *jarg
)
383 struct sockaddr_nl nladdr
;
385 struct msghdr msg
= {
387 .msg_namelen
= sizeof(nladdr
),
393 memset(&nladdr
, 0, sizeof(nladdr
));
394 nladdr
.nl_family
= AF_NETLINK
;
396 nladdr
.nl_groups
= 0;
400 iov
.iov_len
= sizeof(buf
);
401 status
= recvmsg(rtnl
->fd
, &msg
, 0);
408 ERROR("OVERRUN: recvmsg(): error %d : %s\n", errno
, strerror(errno
));
412 ERROR("EOF on netlink\n");
415 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
416 ERROR("Sender address length == %d\n",
420 for (h
= (struct nlmsghdr
*)buf
; status
>= sizeof(*h
);) {
422 int len
= h
->nlmsg_len
;
423 int l
= len
- sizeof(*h
);
425 if (l
< 0 || len
> status
) {
426 if (msg
.msg_flags
& MSG_TRUNC
) {
427 ERROR("Truncated message\n");
431 "!!!malformed message: len=%d\n", len
);
435 err
= handler(&nladdr
, h
, jarg
);
437 ERROR("Handler returned %d\n", err
);
441 status
-= NLMSG_ALIGN(len
);
442 h
= (struct nlmsghdr
*)((char *)h
+ NLMSG_ALIGN(len
));
444 if (msg
.msg_flags
& MSG_TRUNC
) {
445 ERROR("Message truncated\n");
449 ERROR("!!!Remnant of size %d\n", status
);
455 int rtnl_from_file(FILE * rtnl
, rtnl_filter_t handler
, void *jarg
)
458 struct sockaddr_nl nladdr
;
460 struct nlmsghdr
*h
= (void *)buf
;
462 memset(&nladdr
, 0, sizeof(nladdr
));
463 nladdr
.nl_family
= AF_NETLINK
;
465 nladdr
.nl_groups
= 0;
471 status
= fread(&buf
, 1, sizeof(*h
), rtnl
);
476 ERROR("rtnl_from_file: fread");
483 l
= len
- sizeof(*h
);
485 if (l
< 0 || len
> sizeof(buf
)) {
486 ERROR("!!!malformed message: len=%d @%lu\n",
491 status
= fread(NLMSG_DATA(h
), 1, NLMSG_ALIGN(l
), rtnl
);
494 ERROR("rtnl_from_file: fread");
498 ERROR("rtnl-from_file: truncated message\n");
502 err
= handler(&nladdr
, h
, jarg
);
508 int addattr32(struct nlmsghdr
*n
, int maxlen
, int type
, __u32 data
)
510 int len
= RTA_LENGTH(4);
512 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
) {
514 "addattr32: Error! max allowed bound %d exceeded\n",
519 rta
->rta_type
= type
;
521 memcpy(RTA_DATA(rta
), &data
, 4);
522 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + len
;
526 int addattr8(struct nlmsghdr
*n
, int maxlen
, int type
, __u8 data
)
528 int len
= RTA_LENGTH(1);
530 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
) {
532 "addattr8: Error! max allowed bound %d exceeded\n",
537 rta
->rta_type
= type
;
539 memcpy(RTA_DATA(rta
), &data
, 1);
540 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + len
;
544 int addattr_l(struct nlmsghdr
*n
, int maxlen
, int type
, const void *data
,
547 int len
= RTA_LENGTH(alen
);
550 if (NLMSG_ALIGN(n
->nlmsg_len
) + RTA_ALIGN(len
) > maxlen
) {
552 "addattr_l ERROR: message exceeded bound of %d\n",
557 rta
->rta_type
= type
;
559 memcpy(RTA_DATA(rta
), data
, alen
);
560 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + RTA_ALIGN(len
);
564 int addraw_l(struct nlmsghdr
*n
, int maxlen
, const void *data
, int len
)
566 if (NLMSG_ALIGN(n
->nlmsg_len
) + NLMSG_ALIGN(len
) > maxlen
) {
568 "addraw_l ERROR: message exceeded bound of %d\n",
573 memcpy(NLMSG_TAIL(n
), data
, len
);
574 memset((void *)NLMSG_TAIL(n
) + len
, 0, NLMSG_ALIGN(len
) - len
);
575 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + NLMSG_ALIGN(len
);
579 int rta_addattr32(struct rtattr
*rta
, int maxlen
, int type
, __u32 data
)
581 int len
= RTA_LENGTH(4);
582 struct rtattr
*subrta
;
584 if (RTA_ALIGN(rta
->rta_len
) + len
> maxlen
) {
586 "rta_addattr32: Error! max allowed bound %d exceeded\n",
590 subrta
= (struct rtattr
*)(((char *)rta
) + RTA_ALIGN(rta
->rta_len
));
591 subrta
->rta_type
= type
;
592 subrta
->rta_len
= len
;
593 memcpy(RTA_DATA(subrta
), &data
, 4);
594 rta
->rta_len
= NLMSG_ALIGN(rta
->rta_len
) + len
;
598 int rta_addattr_l(struct rtattr
*rta
, int maxlen
, int type
,
599 const void *data
, int alen
)
601 struct rtattr
*subrta
;
602 int len
= RTA_LENGTH(alen
);
604 if (RTA_ALIGN(rta
->rta_len
) + RTA_ALIGN(len
) > maxlen
) {
606 "rta_addattr_l: Error! max allowed bound %d exceeded\n",
610 subrta
= (struct rtattr
*)(((char *)rta
) + RTA_ALIGN(rta
->rta_len
));
611 subrta
->rta_type
= type
;
612 subrta
->rta_len
= len
;
613 memcpy(RTA_DATA(subrta
), data
, alen
);
614 rta
->rta_len
= NLMSG_ALIGN(rta
->rta_len
) + RTA_ALIGN(len
);
618 int rta_addattr8(struct rtattr
*rta
, int maxlen
, int type
, __u8 data
)
620 return rta_addattr_l(rta
, maxlen
, type
, &data
, sizeof(__u8
));
623 int rta_addattr16(struct rtattr
*rta
, int maxlen
, int type
, __u16 data
)
625 return rta_addattr_l(rta
, maxlen
, type
, &data
, sizeof(__u16
));
628 int rta_addattr64(struct rtattr
*rta
, int maxlen
, int type
, __u64 data
)
630 return rta_addattr_l(rta
, maxlen
, type
, &data
, sizeof(__u64
));
633 struct rtattr
*rta_nest(struct rtattr
*rta
, int maxlen
, int type
)
635 struct rtattr
*nest
= RTA_TAIL(rta
);
637 rta_addattr_l(rta
, maxlen
, type
, NULL
, 0);
638 nest
->rta_type
|= NLA_F_NESTED
;
643 int rta_nest_end(struct rtattr
*rta
, struct rtattr
*nest
)
645 nest
->rta_len
= (void *)RTA_TAIL(rta
) - (void *)nest
;
650 int parse_rtattr(struct rtattr
*tb
[], int max
, struct rtattr
*rta
, int len
)
652 memset(tb
, 0, sizeof(struct rtattr
*) * (max
+ 1));
653 while (RTA_OK(rta
, len
)) {
654 if (rta
->rta_type
<= max
)
655 tb
[rta
->rta_type
] = rta
;
656 rta
= RTA_NEXT(rta
, len
);
659 ERROR("!!!Deficit %d, rta_len=%d\n", len
,
664 int parse_rtattr_byindex(struct rtattr
*tb
[], int max
, struct rtattr
*rta
,
669 memset(tb
, 0, sizeof(struct rtattr
*) * max
);
670 while (RTA_OK(rta
, len
)) {
671 if (rta
->rta_type
<= max
&& i
< max
)
673 rta
= RTA_NEXT(rta
, len
);
676 ERROR("!!!Deficit %d, rta_len=%d\n", len
,