]>
git.proxmox.com Git - mirror_iproute2.git/blob - lib/libnetlink.c
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>
26 #include "libnetlink.h"
28 void rtnl_close(struct rtnl_handle
*rth
)
33 int rtnl_open(struct rtnl_handle
*rth
, unsigned subscriptions
)
37 memset(rth
, 0, sizeof(rth
));
39 rth
->fd
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
41 perror("Cannot open netlink socket");
45 memset(&rth
->local
, 0, sizeof(rth
->local
));
46 rth
->local
.nl_family
= AF_NETLINK
;
47 rth
->local
.nl_groups
= subscriptions
;
49 if (bind(rth
->fd
, (struct sockaddr
*)&rth
->local
, sizeof(rth
->local
)) < 0) {
50 perror("Cannot bind netlink socket");
53 addr_len
= sizeof(rth
->local
);
54 if (getsockname(rth
->fd
, (struct sockaddr
*)&rth
->local
, &addr_len
) < 0) {
55 perror("Cannot getsockname");
58 if (addr_len
!= sizeof(rth
->local
)) {
59 fprintf(stderr
, "Wrong address length %d\n", addr_len
);
62 if (rth
->local
.nl_family
!= AF_NETLINK
) {
63 fprintf(stderr
, "Wrong address family %d\n", rth
->local
.nl_family
);
66 rth
->seq
= time(NULL
);
70 int rtnl_wilddump_request(struct rtnl_handle
*rth
, int family
, int type
)
76 struct sockaddr_nl nladdr
;
78 memset(&nladdr
, 0, sizeof(nladdr
));
79 nladdr
.nl_family
= AF_NETLINK
;
81 req
.nlh
.nlmsg_len
= sizeof(req
);
82 req
.nlh
.nlmsg_type
= type
;
83 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
84 req
.nlh
.nlmsg_pid
= 0;
85 req
.nlh
.nlmsg_seq
= rth
->dump
= ++rth
->seq
;
86 req
.g
.rtgen_family
= family
;
88 return sendto(rth
->fd
, (void*)&req
, sizeof(req
), 0, (struct sockaddr
*)&nladdr
, sizeof(nladdr
));
91 int rtnl_send(struct rtnl_handle
*rth
, char *buf
, int len
)
93 struct sockaddr_nl nladdr
;
95 memset(&nladdr
, 0, sizeof(nladdr
));
96 nladdr
.nl_family
= AF_NETLINK
;
98 return sendto(rth
->fd
, buf
, len
, 0, (struct sockaddr
*)&nladdr
, sizeof(nladdr
));
101 int rtnl_dump_request(struct rtnl_handle
*rth
, int type
, void *req
, int len
)
104 struct sockaddr_nl nladdr
;
105 struct iovec iov
[2] = { { &nlh
, sizeof(nlh
) }, { req
, len
} };
106 struct msghdr msg
= {
107 (void*)&nladdr
, sizeof(nladdr
),
113 memset(&nladdr
, 0, sizeof(nladdr
));
114 nladdr
.nl_family
= AF_NETLINK
;
116 nlh
.nlmsg_len
= NLMSG_LENGTH(len
);
117 nlh
.nlmsg_type
= type
;
118 nlh
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
120 nlh
.nlmsg_seq
= rth
->dump
= ++rth
->seq
;
122 return sendmsg(rth
->fd
, &msg
, 0);
125 int rtnl_dump_filter(struct rtnl_handle
*rth
,
126 int (*filter
)(struct sockaddr_nl
*, struct nlmsghdr
*n
, void *),
128 int (*junk
)(struct sockaddr_nl
*,struct nlmsghdr
*n
, void *),
132 struct sockaddr_nl nladdr
;
133 struct iovec iov
= { buf
, sizeof(buf
) };
139 struct msghdr msg
= {
140 (void*)&nladdr
, sizeof(nladdr
),
146 status
= recvmsg(rth
->fd
, &msg
, 0);
155 fprintf(stderr
, "EOF on netlink\n");
158 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
159 fprintf(stderr
, "sender address length == %d\n", msg
.msg_namelen
);
163 h
= (struct nlmsghdr
*)buf
;
164 while (NLMSG_OK(h
, status
)) {
167 if (h
->nlmsg_pid
!= rth
->local
.nl_pid
||
168 h
->nlmsg_seq
!= rth
->dump
) {
170 err
= junk(&nladdr
, h
, arg2
);
177 if (h
->nlmsg_type
== NLMSG_DONE
)
179 if (h
->nlmsg_type
== NLMSG_ERROR
) {
180 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
181 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
))) {
182 fprintf(stderr
, "ERROR truncated\n");
185 perror("RTNETLINK answers");
189 err
= filter(&nladdr
, h
, arg1
);
194 h
= NLMSG_NEXT(h
, status
);
196 if (msg
.msg_flags
& MSG_TRUNC
) {
197 fprintf(stderr
, "Message truncated\n");
201 fprintf(stderr
, "!!!Remnant of size %d\n", status
);
207 int rtnl_talk(struct rtnl_handle
*rtnl
, struct nlmsghdr
*n
, pid_t peer
,
208 unsigned groups
, struct nlmsghdr
*answer
,
209 int (*junk
)(struct sockaddr_nl
*,struct nlmsghdr
*n
, void *),
215 struct sockaddr_nl nladdr
;
216 struct iovec iov
= { (void*)n
, n
->nlmsg_len
};
218 struct msghdr msg
= {
219 (void*)&nladdr
, sizeof(nladdr
),
225 memset(&nladdr
, 0, sizeof(nladdr
));
226 nladdr
.nl_family
= AF_NETLINK
;
227 nladdr
.nl_pid
= peer
;
228 nladdr
.nl_groups
= groups
;
230 n
->nlmsg_seq
= seq
= ++rtnl
->seq
;
232 n
->nlmsg_flags
|= NLM_F_ACK
;
234 status
= sendmsg(rtnl
->fd
, &msg
, 0);
237 perror("Cannot talk to rtnetlink");
244 iov
.iov_len
= sizeof(buf
);
245 status
= recvmsg(rtnl
->fd
, &msg
, 0);
254 fprintf(stderr
, "EOF on netlink\n");
257 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
258 fprintf(stderr
, "sender address length == %d\n", msg
.msg_namelen
);
261 for (h
= (struct nlmsghdr
*)buf
; status
>= sizeof(*h
); ) {
263 int len
= h
->nlmsg_len
;
264 int l
= len
- sizeof(*h
);
266 if (l
<0 || len
>status
) {
267 if (msg
.msg_flags
& MSG_TRUNC
) {
268 fprintf(stderr
, "Truncated message\n");
271 fprintf(stderr
, "!!!malformed message: len=%d\n", len
);
275 if (h
->nlmsg_pid
!= rtnl
->local
.nl_pid
||
276 h
->nlmsg_seq
!= seq
) {
278 err
= junk(&nladdr
, h
, jarg
);
285 if (h
->nlmsg_type
== NLMSG_ERROR
) {
286 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
287 if (l
< sizeof(struct nlmsgerr
)) {
288 fprintf(stderr
, "ERROR truncated\n");
293 memcpy(answer
, h
, h
->nlmsg_len
);
296 perror("RTNETLINK answers");
301 memcpy(answer
, h
, h
->nlmsg_len
);
305 fprintf(stderr
, "Unexpected reply!!!\n");
307 status
-= NLMSG_ALIGN(len
);
308 h
= (struct nlmsghdr
*)((char*)h
+ NLMSG_ALIGN(len
));
310 if (msg
.msg_flags
& MSG_TRUNC
) {
311 fprintf(stderr
, "Message truncated\n");
315 fprintf(stderr
, "!!!Remnant of size %d\n", status
);
321 int rtnl_listen(struct rtnl_handle
*rtnl
,
322 int (*handler
)(struct sockaddr_nl
*,struct nlmsghdr
*n
, void *),
327 struct sockaddr_nl nladdr
;
330 struct msghdr msg
= {
331 (void*)&nladdr
, sizeof(nladdr
),
337 memset(&nladdr
, 0, sizeof(nladdr
));
338 nladdr
.nl_family
= AF_NETLINK
;
340 nladdr
.nl_groups
= 0;
346 iov
.iov_len
= sizeof(buf
);
347 status
= recvmsg(rtnl
->fd
, &msg
, 0);
356 fprintf(stderr
, "EOF on netlink\n");
359 if (msg
.msg_namelen
!= sizeof(nladdr
)) {
360 fprintf(stderr
, "Sender address length == %d\n", msg
.msg_namelen
);
363 for (h
= (struct nlmsghdr
*)buf
; status
>= sizeof(*h
); ) {
365 int len
= h
->nlmsg_len
;
366 int l
= len
- sizeof(*h
);
368 if (l
<0 || len
>status
) {
369 if (msg
.msg_flags
& MSG_TRUNC
) {
370 fprintf(stderr
, "Truncated message\n");
373 fprintf(stderr
, "!!!malformed message: len=%d\n", len
);
377 err
= handler(&nladdr
, h
, jarg
);
381 status
-= NLMSG_ALIGN(len
);
382 h
= (struct nlmsghdr
*)((char*)h
+ NLMSG_ALIGN(len
));
384 if (msg
.msg_flags
& MSG_TRUNC
) {
385 fprintf(stderr
, "Message truncated\n");
389 fprintf(stderr
, "!!!Remnant of size %d\n", status
);
395 int rtnl_from_file(FILE *rtnl
,
396 int (*handler
)(struct sockaddr_nl
*,struct nlmsghdr
*n
, void *),
400 struct sockaddr_nl nladdr
;
402 struct nlmsghdr
*h
= (void*)buf
;
404 memset(&nladdr
, 0, sizeof(nladdr
));
405 nladdr
.nl_family
= AF_NETLINK
;
407 nladdr
.nl_groups
= 0;
413 status
= fread(&buf
, 1, sizeof(*h
), rtnl
);
418 perror("rtnl_from_file: fread");
426 l
= len
- sizeof(*h
);
428 if (l
<0 || len
>sizeof(buf
)) {
429 fprintf(stderr
, "!!!malformed message: len=%d @%lu\n",
434 status
= fread(NLMSG_DATA(h
), 1, NLMSG_ALIGN(l
), rtnl
);
437 perror("rtnl_from_file: fread");
441 fprintf(stderr
, "rtnl-from_file: truncated message\n");
445 err
= handler(&nladdr
, h
, jarg
);
451 int addattr32(struct nlmsghdr
*n
, int maxlen
, int type
, __u32 data
)
453 int len
= RTA_LENGTH(4);
455 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
)
457 rta
= (struct rtattr
*)(((char*)n
) + NLMSG_ALIGN(n
->nlmsg_len
));
458 rta
->rta_type
= type
;
460 memcpy(RTA_DATA(rta
), &data
, 4);
461 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + len
;
465 int addattr_l(struct nlmsghdr
*n
, int maxlen
, int type
, void *data
, int alen
)
467 int len
= RTA_LENGTH(alen
);
470 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
)
472 rta
= (struct rtattr
*)(((char*)n
) + NLMSG_ALIGN(n
->nlmsg_len
));
473 rta
->rta_type
= type
;
475 memcpy(RTA_DATA(rta
), data
, alen
);
476 n
->nlmsg_len
= NLMSG_ALIGN(n
->nlmsg_len
) + len
;
480 int rta_addattr32(struct rtattr
*rta
, int maxlen
, int type
, __u32 data
)
482 int len
= RTA_LENGTH(4);
483 struct rtattr
*subrta
;
485 if (RTA_ALIGN(rta
->rta_len
) + len
> maxlen
)
487 subrta
= (struct rtattr
*)(((char*)rta
) + RTA_ALIGN(rta
->rta_len
));
488 subrta
->rta_type
= type
;
489 subrta
->rta_len
= len
;
490 memcpy(RTA_DATA(subrta
), &data
, 4);
491 rta
->rta_len
= NLMSG_ALIGN(rta
->rta_len
) + len
;
495 int rta_addattr_l(struct rtattr
*rta
, int maxlen
, int type
, void *data
, int alen
)
497 struct rtattr
*subrta
;
498 int len
= RTA_LENGTH(alen
);
500 if (RTA_ALIGN(rta
->rta_len
) + len
> maxlen
)
502 subrta
= (struct rtattr
*)(((char*)rta
) + RTA_ALIGN(rta
->rta_len
));
503 subrta
->rta_type
= type
;
504 subrta
->rta_len
= len
;
505 memcpy(RTA_DATA(subrta
), data
, alen
);
506 rta
->rta_len
= NLMSG_ALIGN(rta
->rta_len
) + len
;
511 int parse_rtattr(struct rtattr
*tb
[], int max
, struct rtattr
*rta
, int len
)
513 while (RTA_OK(rta
, len
)) {
514 if (rta
->rta_type
<= max
)
515 tb
[rta
->rta_type
] = rta
;
516 rta
= RTA_NEXT(rta
,len
);
519 fprintf(stderr
, "!!!Deficit %d, rta_len=%d\n", len
, rta
->rta_len
);