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 256 * 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
;
52 memset(rth
, 0, sizeof(*rth
));
54 rth
->fd
= socket(AF_NETLINK
, SOCK_RAW
, protocol
);
56 ERROR("Cannot open netlink socket");
60 if (setsockopt(rth
->fd
, SOL_SOCKET
, SO_SNDBUF
, &sndbuf
, sizeof(sndbuf
))
66 if (setsockopt(rth
->fd
, SOL_SOCKET
, SO_RCVBUF
, &rcvbuf
, sizeof(rcvbuf
))
72 memset(&rth
->local
, 0, sizeof(rth
->local
));
73 rth
->local
.nl_family
= AF_NETLINK
;
74 rth
->local
.nl_groups
= subscriptions
;
76 if (bind(rth
->fd
, (struct sockaddr
*)&rth
->local
, sizeof(rth
->local
)) <
78 ERROR("Cannot bind netlink socket");
81 addr_len
= sizeof(rth
->local
);
82 if (getsockname(rth
->fd
, (struct sockaddr
*)&rth
->local
, &addr_len
) < 0) {
83 ERROR("Cannot getsockname");
86 if (addr_len
!= sizeof(rth
->local
)) {
87 ERROR("Wrong address length %d\n", addr_len
);
90 if (rth
->local
.nl_family
!= AF_NETLINK
) {
91 ERROR("Wrong address family %d\n",
92 rth
->local
.nl_family
);
95 rth
->seq
= time(NULL
);
99 int rtnl_open(struct rtnl_handle
*rth
, unsigned subscriptions
)
101 return rtnl_open_byproto(rth
, subscriptions
, NETLINK_ROUTE
);
104 int rtnl_wilddump_request(struct rtnl_handle
*rth
, int family
, int type
)
110 struct sockaddr_nl nladdr
;
112 memset(&nladdr
, 0, sizeof(nladdr
));
113 nladdr
.nl_family
= AF_NETLINK
;
115 memset(&req
, 0, sizeof(req
));
116 req
.nlh
.nlmsg_len
= sizeof(req
);
117 req
.nlh
.nlmsg_type
= type
;
118 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
;
119 req
.nlh
.nlmsg_pid
= 0;
120 req
.nlh
.nlmsg_seq
= rth
->dump
= ++rth
->seq
;
121 req
.g
.rtgen_family
= family
;
123 return sendto(rth
->fd
, (void *)&req
, sizeof(req
), 0,
124 (struct sockaddr
*)&nladdr
, sizeof(nladdr
));
127 int rtnl_send(struct rtnl_handle
*rth
, const char *buf
, int len
)
129 struct sockaddr_nl nladdr
;
131 memset(&nladdr
, 0, sizeof(nladdr
));
132 nladdr
.nl_family
= AF_NETLINK
;
134 return sendto(rth
->fd
, buf
, len
, 0, (struct sockaddr
*)&nladdr
,
138 int rtnl_dump_request(struct rtnl_handle
*rth
, int type
, void *req
, int len
)
141 struct sockaddr_nl nladdr
;
142 struct iovec iov
[2] = {
143 {.iov_base
= &nlh
,.iov_len
= sizeof(nlh
)}
145 {.iov_base
= req
,.iov_len
= len
}
147 struct msghdr msg
= {
149 .msg_namelen
= sizeof(nladdr
),
154 memset(&nladdr
, 0, sizeof(nladdr
));
155 nladdr
.nl_family
= AF_NETLINK
;
157 nlh
.nlmsg_len
= NLMSG_LENGTH(len
);
158 nlh
.nlmsg_type
= type
;
159 nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
;
161 nlh
.nlmsg_seq
= rth
->dump
= ++rth
->seq
;
163 return sendmsg(rth
->fd
, &msg
, 0);
166 int rtnl_dump_filter(struct rtnl_handle
*rth
,
167 rtnl_filter_t filter
,
168 void *arg1
, rtnl_filter_t junk
, void *arg2
)
170 struct sockaddr_nl nladdr
;
172 struct msghdr msg
= {
174 .msg_namelen
= sizeof(nladdr
),
185 iov
.iov_len
= sizeof(buf
);
186 status
= recvmsg(rth
->fd
, &msg
, 0);
196 ERROR("EOF on netlink\n");
200 h
= (struct nlmsghdr
*)buf
;
201 while (NLMSG_OK(h
, status
)) {
204 if (nladdr
.nl_pid
!= 0 ||
205 h
->nlmsg_pid
!= rth
->local
.nl_pid
||
206 h
->nlmsg_seq
!= rth
->dump
) {
208 err
= junk(&nladdr
, h
, arg2
);
215 if (h
->nlmsg_type
== NLMSG_DONE
)
217 if (h
->nlmsg_type
== NLMSG_ERROR
) {
218 struct nlmsgerr
*err
=
219 (struct nlmsgerr
*)NLMSG_DATA(h
);
221 NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
222 ERROR("ERROR truncated\n");
225 INFO("RTNETLINK answers");
229 err
= filter(&nladdr
, h
, arg1
);
234 h
= NLMSG_NEXT(h
, status
);
236 if (msg
.msg_flags
& MSG_TRUNC
) {
237 ERROR("Message truncated\n");
241 ERROR("!!!Remnant of size %d\n", status
);
247 int rtnl_talk(struct rtnl_handle
*rtnl
, struct nlmsghdr
*n
, pid_t peer
,
248 unsigned groups
, struct nlmsghdr
*answer
,
249 rtnl_filter_t junk
, void *jarg
)
254 struct sockaddr_nl nladdr
;
256 .iov_base
= (void *)n
,
257 .iov_len
= n
->nlmsg_len
259 struct msghdr msg
= {
261 .msg_namelen
= sizeof(nladdr
),
267 memset(&nladdr
, 0, sizeof(nladdr
));
268 nladdr
.nl_family
= AF_NETLINK
;
269 nladdr
.nl_pid
= peer
;
270 nladdr
.nl_groups
= groups
;
272 n
->nlmsg_seq
= seq
= ++rtnl
->seq
;
275 n
->nlmsg_flags
|= NLM_F_ACK
;
277 status
= sendmsg(rtnl
->fd
, &msg
, 0);
280 ERROR("Cannot talk to rtnetlink");
284 memset(buf
, 0, sizeof(buf
));
289 iov
.iov_len
= sizeof(buf
);
290 status
= recvmsg(rtnl
->fd
, &msg
, 0);
299 ERROR("EOF on netlink\n");
302 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
303 ERROR("sender address length == %d\n",
307 for (h
= (struct nlmsghdr
*)buf
; status
>= sizeof(*h
);) {
309 int len
= h
->nlmsg_len
;
310 int l
= len
- sizeof(*h
);
312 if (l
< 0 || len
> status
) {
313 if (msg
.msg_flags
& MSG_TRUNC
) {
314 ERROR("Truncated message\n");
318 "!!!malformed message: len=%d\n", len
);
322 if (nladdr
.nl_pid
!= peer
||
323 h
->nlmsg_pid
!= rtnl
->local
.nl_pid
||
324 h
->nlmsg_seq
!= seq
) {
326 err
= junk(&nladdr
, h
, jarg
);
330 /* Don't forget to skip that message. */
331 status
-= NLMSG_ALIGN(len
);
332 h
= (struct nlmsghdr
*)((char *)h
+
337 if (h
->nlmsg_type
== NLMSG_ERROR
) {
338 struct nlmsgerr
*err
=
339 (struct nlmsgerr
*)NLMSG_DATA(h
);
340 if (l
< sizeof(struct nlmsgerr
)) {
341 ERROR("ERROR truncated\n");
350 ERROR("RTNETLINK answers");
355 memcpy(answer
, h
, h
->nlmsg_len
);
359 ERROR("Unexpected reply!!!\n");
361 status
-= NLMSG_ALIGN(len
);
362 h
= (struct nlmsghdr
*)((char *)h
+ NLMSG_ALIGN(len
));
364 if (msg
.msg_flags
& MSG_TRUNC
) {
365 ERROR("Message truncated\n");
369 ERROR("!!!Remnant of size %d\n", status
);
375 int rtnl_listen(struct rtnl_handle
*rtnl
, rtnl_filter_t handler
, void *jarg
)
379 struct sockaddr_nl nladdr
;
381 struct msghdr msg
= {
383 .msg_namelen
= sizeof(nladdr
),
389 memset(&nladdr
, 0, sizeof(nladdr
));
390 nladdr
.nl_family
= AF_NETLINK
;
392 nladdr
.nl_groups
= 0;
396 iov
.iov_len
= sizeof(buf
);
397 status
= recvmsg(rtnl
->fd
, &msg
, 0);
404 ERROR("OVERRUN: recvmsg(): error %d : %s\n", errno
, strerror(errno
));
408 ERROR("EOF on netlink\n");
411 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
412 ERROR("Sender address length == %d\n",
416 for (h
= (struct nlmsghdr
*)buf
; status
>= sizeof(*h
);) {
418 int len
= h
->nlmsg_len
;
419 int l
= len
- sizeof(*h
);
421 if (l
< 0 || len
> status
) {
422 if (msg
.msg_flags
& MSG_TRUNC
) {
423 ERROR("Truncated message\n");
427 "!!!malformed message: len=%d\n", len
);
431 err
= handler(&nladdr
, h
, jarg
);
433 ERROR("Handler returned %d\n", err
);
437 status
-= NLMSG_ALIGN(len
);
438 h
= (struct nlmsghdr
*)((char *)h
+ NLMSG_ALIGN(len
));
440 if (msg
.msg_flags
& MSG_TRUNC
) {
441 ERROR("Message truncated\n");
445 ERROR("!!!Remnant of size %d\n", status
);
451 int rtnl_from_file(FILE * rtnl
, rtnl_filter_t handler
, void *jarg
)
454 struct sockaddr_nl nladdr
;
456 struct nlmsghdr
*h
= (void *)buf
;
458 memset(&nladdr
, 0, sizeof(nladdr
));
459 nladdr
.nl_family
= AF_NETLINK
;
461 nladdr
.nl_groups
= 0;
467 status
= fread(&buf
, 1, sizeof(*h
), rtnl
);
472 ERROR("rtnl_from_file: fread");
479 l
= len
- sizeof(*h
);
481 if (l
< 0 || len
> sizeof(buf
)) {
482 ERROR("!!!malformed message: len=%d @%lu\n",
487 status
= fread(NLMSG_DATA(h
), 1, NLMSG_ALIGN(l
), rtnl
);
490 ERROR("rtnl_from_file: fread");
494 ERROR("rtnl-from_file: truncated message\n");
498 err
= handler(&nladdr
, h
, jarg
);
504 int addattr32(struct nlmsghdr
*n
, int maxlen
, int type
, __u32 data
)
506 int len
= RTA_LENGTH(4);
508 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
) {
510 "addattr32: Error! max allowed bound %d exceeded\n",
515 rta
->rta_type
= type
;
517 memcpy(RTA_DATA(rta
), &data
, 4);
518 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + len
;
522 int addattr8(struct nlmsghdr
*n
, int maxlen
, int type
, __u8 data
)
524 int len
= RTA_LENGTH(1);
526 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
) {
528 "addattr8: Error! max allowed bound %d exceeded\n",
533 rta
->rta_type
= type
;
535 memcpy(RTA_DATA(rta
), &data
, 1);
536 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + len
;
540 int addattr_l(struct nlmsghdr
*n
, int maxlen
, int type
, const void *data
,
543 int len
= RTA_LENGTH(alen
);
546 if (NLMSG_ALIGN(n
->nlmsg_len
) + RTA_ALIGN(len
) > maxlen
) {
548 "addattr_l ERROR: message exceeded bound of %d\n",
553 rta
->rta_type
= type
;
555 memcpy(RTA_DATA(rta
), data
, alen
);
556 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + RTA_ALIGN(len
);
560 int addraw_l(struct nlmsghdr
*n
, int maxlen
, const void *data
, int len
)
562 if (NLMSG_ALIGN(n
->nlmsg_len
) + NLMSG_ALIGN(len
) > maxlen
) {
564 "addraw_l ERROR: message exceeded bound of %d\n",
569 memcpy(NLMSG_TAIL(n
), data
, len
);
570 memset((void *)NLMSG_TAIL(n
) + len
, 0, NLMSG_ALIGN(len
) - len
);
571 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + NLMSG_ALIGN(len
);
575 int rta_addattr32(struct rtattr
*rta
, int maxlen
, int type
, __u32 data
)
577 int len
= RTA_LENGTH(4);
578 struct rtattr
*subrta
;
580 if (RTA_ALIGN(rta
->rta_len
) + len
> maxlen
) {
582 "rta_addattr32: Error! max allowed bound %d exceeded\n",
586 subrta
= (struct rtattr
*)(((char *)rta
) + RTA_ALIGN(rta
->rta_len
));
587 subrta
->rta_type
= type
;
588 subrta
->rta_len
= len
;
589 memcpy(RTA_DATA(subrta
), &data
, 4);
590 rta
->rta_len
= NLMSG_ALIGN(rta
->rta_len
) + len
;
594 int rta_addattr_l(struct rtattr
*rta
, int maxlen
, int type
,
595 const void *data
, int alen
)
597 struct rtattr
*subrta
;
598 int len
= RTA_LENGTH(alen
);
600 if (RTA_ALIGN(rta
->rta_len
) + RTA_ALIGN(len
) > maxlen
) {
602 "rta_addattr_l: Error! max allowed bound %d exceeded\n",
606 subrta
= (struct rtattr
*)(((char *)rta
) + RTA_ALIGN(rta
->rta_len
));
607 subrta
->rta_type
= type
;
608 subrta
->rta_len
= len
;
609 memcpy(RTA_DATA(subrta
), data
, alen
);
610 rta
->rta_len
= NLMSG_ALIGN(rta
->rta_len
) + RTA_ALIGN(len
);
614 int rta_addattr8(struct rtattr
*rta
, int maxlen
, int type
, __u8 data
)
616 return rta_addattr_l(rta
, maxlen
, type
, &data
, sizeof(__u8
));
619 int rta_addattr16(struct rtattr
*rta
, int maxlen
, int type
, __u16 data
)
621 return rta_addattr_l(rta
, maxlen
, type
, &data
, sizeof(__u16
));
624 int rta_addattr64(struct rtattr
*rta
, int maxlen
, int type
, __u64 data
)
626 return rta_addattr_l(rta
, maxlen
, type
, &data
, sizeof(__u64
));
629 struct rtattr
*rta_nest(struct rtattr
*rta
, int maxlen
, int type
)
631 struct rtattr
*nest
= RTA_TAIL(rta
);
633 rta_addattr_l(rta
, maxlen
, type
, NULL
, 0);
634 nest
->rta_type
|= NLA_F_NESTED
;
639 int rta_nest_end(struct rtattr
*rta
, struct rtattr
*nest
)
641 nest
->rta_len
= (void *)RTA_TAIL(rta
) - (void *)nest
;
646 int parse_rtattr(struct rtattr
*tb
[], int max
, struct rtattr
*rta
, int len
)
648 memset(tb
, 0, sizeof(struct rtattr
*) * (max
+ 1));
649 while (RTA_OK(rta
, len
)) {
650 if (rta
->rta_type
<= max
)
651 tb
[rta
->rta_type
] = rta
;
652 rta
= RTA_NEXT(rta
, len
);
655 ERROR("!!!Deficit %d, rta_len=%d\n", len
,
660 int parse_rtattr_byindex(struct rtattr
*tb
[], int max
, struct rtattr
*rta
,
665 memset(tb
, 0, sizeof(struct rtattr
*) * max
);
666 while (RTA_OK(rta
, len
)) {
667 if (rta
->rta_type
<= max
&& i
< max
)
669 rta
= RTA_NEXT(rta
, len
);
672 ERROR("!!!Deficit %d, rta_len=%d\n", len
,