1 /*
2 Copyright 2007-2010 by Grégoire Henry, Julien Cristau and Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <time.h>
30
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <net/route.h>
35 #include <net/if.h>
36 #include <arpa/inet.h>
37
38 #include <asm/types.h>
39 #include <sys/socket.h>
40 #include <linux/netlink.h>
41 #include <linux/rtnetlink.h>
42 #include <linux/fib_rules.h>
43 #include <net/if_arp.h>
44
45 /* From <linux/if_bridge.h> */
46 #ifndef BRCTL_GET_BRIDGES
47 #define BRCTL_GET_BRIDGES 1
48 #endif
49
50 #if(__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 5)
51 #define RTA_TABLE 15
52 #endif
53
54 #include "babeld.h"
55 #include "kernel.h"
56 #include "util.h"
57 #include "interface.h"
58 #include "configuration.h"
59
60 #ifndef MAX_INTERFACES
61 #define MAX_INTERFACES 1024
62 #endif
63
64 #define GET_PLEN(p, v4) (v4) ? (p) + 96 : (p)
65 #define COPY_ADDR(d, rta, v4) \
66 do { \
67 if(UNLIKELY(RTA_PAYLOAD(rta) < (v4 ? 4 : 16))) { \
68 fprintf(stderr, "truncated message."); \
69 return -1; \
70 } \
71 if(v4) \
72 v4tov6(d, RTA_DATA(rta)); \
73 else \
74 memcpy(d, RTA_DATA(rta), 16); \
75 } while(0)
76
77 int export_table = -1, import_tables[MAX_IMPORT_TABLES], import_table_count = 0;
78
79 struct sysctl_setting {
80 char *name;
81 int want;
82 int was;
83 };
84 #define NUM_SYSCTLS 4
85
86 static struct sysctl_setting sysctl_settings[NUM_SYSCTLS] = {
87 {"/proc/sys/net/ipv6/conf/all/forwarding", 1, -1},
88 {"/proc/sys/net/ipv4/conf/all/forwarding", 1, -1},
89 {"/proc/sys/net/ipv6/conf/all/accept_redirects", 0, -1},
90 {"/proc/sys/net/ipv4/conf/all/rp_filter", 0, -1},
91 };
92
93 struct old_if {
94 char *ifname;
95 int rp_filter;
96 };
97
98 static struct old_if *old_if = NULL;
99 static int num_old_if = 0;
100 static int max_old_if = 0;
101
102 static int dgram_socket = -1;
103
104 #ifndef ARPHRD_ETHER
105 #warning ARPHRD_ETHER not defined, we might not support exotic link layers
106 #define ARPHRD_ETHER 1
107 #define NO_ARPHRD
108 #endif
109
110 static int filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter);
111
112
113 /* Determine an interface's hardware address, in modified EUI-64 format */
114 int
if_eui64(char * ifname,int ifindex,unsigned char * eui)115 if_eui64(char *ifname, int ifindex, unsigned char *eui)
116 {
117 int s, rc;
118 struct ifreq ifr;
119
120 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
121 if(s < 0) return -1;
122 memset(&ifr, 0, sizeof(ifr));
123 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
124 rc = ioctl(s, SIOCGIFHWADDR, &ifr);
125 if(rc < 0) {
126 int saved_errno = errno;
127 close(s);
128 errno = saved_errno;
129 return -1;
130 }
131 close(s);
132
133 switch(ifr.ifr_hwaddr.sa_family) {
134 case ARPHRD_ETHER:
135 #ifndef NO_ARPHRD
136 case ARPHRD_FDDI:
137 case ARPHRD_IEEE802_TR:
138 case ARPHRD_IEEE802:
139 #endif
140 {
141 unsigned char *mac;
142 mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;
143 /* Check for null address and group and global bits */
144 if(memcmp(mac, zeroes, 6) == 0 ||
145 (mac[0] & 1) != 0 || (mac[0] & 2) != 0) {
146 errno = ENOENT;
147 return -1;
148 }
149 memcpy(eui, mac, 3);
150 eui[3] = 0xFF;
151 eui[4] = 0xFE;
152 memcpy(eui + 5, mac + 3, 3);
153 eui[0] ^= 2;
154 return 1;
155 }
156 #ifndef NO_ARPHRD
157 case ARPHRD_EUI64:
158 case ARPHRD_IEEE1394:
159 case ARPHRD_INFINIBAND: {
160 unsigned char *mac;
161 mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;
162 if(memcmp(mac, zeroes, 8) == 0 ||
163 (mac[0] & 1) != 0 || (mac[0] & 2) != 0) {
164 errno = ENOENT;
165 return -1;
166 }
167 memcpy(eui, mac, 8);
168 eui[0] ^= 2;
169 return 1;
170 }
171 #endif
172 default:
173 errno = ENOENT;
174 return -1;
175 }
176 }
177
178 static int
read_proc(char * filename)179 read_proc(char *filename)
180 {
181 char buf[100];
182 int fd, rc;
183 fd = open(filename, O_RDONLY);
184 if(fd < 0)
185 return -1;
186 rc = read(fd, buf, 99);
187 if(rc < 0) {
188 int saved_errno = errno;
189 close(fd);
190 errno = saved_errno;
191 return -1;
192 }
193 close(fd);
194
195 if(rc == 0)
196 return -1;
197
198 buf[rc] = '\0';
199 return atoi(buf);
200 }
201
202 static int
write_proc(char * filename,int value)203 write_proc(char *filename, int value)
204 {
205 char buf[100];
206 int fd, rc, n;
207 n = snprintf(buf, 100, "%d", value);
208
209 fd = open(filename, O_WRONLY);
210 if(fd < 0)
211 return -1;
212
213 rc = write(fd, buf, n);
214 if(rc < n) {
215 int saved_errno = errno;
216 close(fd);
217 errno = saved_errno;
218 return -1;
219 }
220
221 close(fd);
222 return 1;
223 }
224
225 struct netlink {
226 unsigned short seqno;
227 int sock;
228 struct sockaddr_nl sockaddr;
229 socklen_t socklen;
230 };
231
232 static struct netlink nl_command = { 0, -1, {0}, 0 };
233 static struct netlink nl_listen = { 0, -1, {0}, 0 };
234 static int nl_setup = 0;
235
236 static int
netlink_socket(struct netlink * nl,uint32_t groups)237 netlink_socket(struct netlink *nl, uint32_t groups)
238 {
239 int rc;
240 int rcvsize = 512 * 1024;
241
242 nl->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
243 if(nl->sock < 0)
244 return -1;
245
246 memset(&nl->sockaddr, 0, sizeof(nl->sockaddr));
247 nl->sockaddr.nl_family = AF_NETLINK;
248 nl->sockaddr.nl_groups = groups;
249 nl->socklen = sizeof(nl->sockaddr);
250
251 nl->seqno = time(NULL);
252
253 rc = fcntl(nl->sock, F_GETFL, 0);
254 if(rc < 0)
255 goto fail;
256
257 rc = fcntl(nl->sock, F_SETFL, (rc | O_NONBLOCK));
258 if(rc < 0)
259 goto fail;
260
261 #ifdef SO_RCVBUFFORCE
262 rc = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE,
263 &rcvsize, sizeof(rcvsize));
264 #else
265 rc = -1;
266 #endif
267 if(rc < 0) {
268 rc = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF,
269 &rcvsize, sizeof(rcvsize));
270 if(rc < 0) {
271 perror("setsockopt(SO_RCVBUF)");
272 }
273 }
274
275 rc = bind(nl->sock, (struct sockaddr *)&nl->sockaddr, nl->socklen);
276 if(rc < 0)
277 goto fail;
278
279 rc = getsockname(nl->sock, (struct sockaddr *)&nl->sockaddr, &nl->socklen);
280 if(rc < 0)
281 goto fail;
282
283 return 0;
284
285 fail:
286 {
287 int saved_errno = errno;
288 close(nl->sock);
289 nl->sock = -1;
290 errno = saved_errno;
291 return -1;
292 }
293 }
294
295 static int
netlink_read(struct netlink * nl,struct netlink * nl_ignore,int answer,struct kernel_filter * filter)296 netlink_read(struct netlink *nl, struct netlink *nl_ignore, int answer,
297 struct kernel_filter *filter)
298 {
299
300 /* 'answer' must be true when we just have send a request on 'nl_socket' */
301
302 /* 'nl_ignore' is used in kernel_callback to ignore message originating */
303 /* from 'nl_command' while reading 'nl_listen' */
304
305 /* Return code : */
306 /* -1 : error */
307 /* 0 : success */
308
309 int err;
310 struct msghdr msg;
311 struct sockaddr_nl nladdr;
312 struct iovec iov;
313 struct nlmsghdr *nh;
314 int len;
315 int done = 0;
316 int skip = 0;
317
318 struct nlmsghdr buf[8192/sizeof(struct nlmsghdr)];
319
320 memset(&nladdr, 0, sizeof(nladdr));
321 nladdr.nl_family = AF_NETLINK;
322
323 memset(&msg, 0, sizeof(msg));
324 msg.msg_name = &nladdr;
325 msg.msg_namelen = sizeof(nladdr);
326 msg.msg_iov = &iov;
327 msg.msg_iovlen = 1;
328
329 iov.iov_base = &buf;
330
331 do {
332 iov.iov_len = sizeof(buf);
333 len = recvmsg(nl->sock, &msg, 0);
334
335 if(len < 0 && (errno == EAGAIN || errno == EINTR)) {
336 int rc;
337 rc = wait_for_fd(0, nl->sock, 100);
338 if(rc <= 0) {
339 if(rc == 0)
340 errno = EAGAIN;
341 } else {
342 len = recvmsg(nl->sock, &msg, 0);
343 }
344 }
345
346 if(len < 0) {
347 perror("netlink_read: recvmsg()");
348 return -1;
349 } else if(len == 0) {
350 fprintf(stderr, "netlink_read: EOF\n");
351 goto socket_error;
352 } else if(msg.msg_namelen != nl->socklen) {
353 fprintf(stderr,
354 "netlink_read: unexpected sender address length (%d)\n",
355 msg.msg_namelen);
356 goto socket_error;
357 } else if(nladdr.nl_pid != 0) {
358 kdebugf("netlink_read: message not sent by kernel.\n");
359 return -1;
360 }
361
362 kdebugf("Netlink message: ");
363
364 for(nh = (struct nlmsghdr *)buf;
365 NLMSG_OK(nh, len);
366 nh = NLMSG_NEXT(nh, len)) {
367 kdebugf("%s{seq:%d}", (nh->nlmsg_flags & NLM_F_MULTI) ? "[multi] " : "",
368 nh->nlmsg_seq);
369 if(!answer)
370 done = 1;
371 if(nl_ignore && nh->nlmsg_pid == nl_ignore->sockaddr.nl_pid) {
372 kdebugf("(ignore), ");
373 continue;
374 } else if(answer && (nh->nlmsg_pid != nl->sockaddr.nl_pid ||
375 nh->nlmsg_seq != nl->seqno)) {
376 kdebugf("(wrong seqno %d %d /pid %d %d), ",
377 nh->nlmsg_seq, nl->seqno,
378 nh->nlmsg_pid, nl->sockaddr.nl_pid);
379 continue;
380 } else if(nh->nlmsg_type == NLMSG_DONE) {
381 kdebugf("(done)\n");
382 done = 1;
383 break;
384 } else if(nh->nlmsg_type == NLMSG_ERROR) {
385 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
386 if(err->error == 0) {
387 kdebugf("(ACK)\n");
388 return 0;
389 } else {
390 kdebugf("netlink_read: %s\n", strerror(-err->error));
391 errno = -err->error;
392 return -1;
393 }
394 } else if(nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK ) {
395 kdebugf("detected an interface change via netlink - triggering babeld interface check\n");
396 check_interfaces();
397 } else if(skip) {
398 kdebugf("(skip)");
399 } if(filter) {
400 kdebugf("(msg -> \"");
401 err = filter_netlink(nh, filter);
402 kdebugf("\" %d), ", err);
403 if(err < 0) skip = 1;
404 continue;
405 }
406 kdebugf(", ");
407 }
408 kdebugf("\n");
409
410 if(msg.msg_flags & MSG_TRUNC)
411 fprintf(stderr, "netlink_read: message truncated\n");
412
413 } while(!done);
414
415 return 0;
416
417 socket_error:
418 close(nl->sock);
419 nl->sock = -1;
420 errno = EIO;
421 return -1;
422 }
423
424 static int
netlink_talk(struct nlmsghdr * nh)425 netlink_talk(struct nlmsghdr *nh)
426 {
427
428 int rc;
429 struct sockaddr_nl nladdr;
430 struct msghdr msg;
431 struct iovec iov;
432
433 memset(&nladdr, 0, sizeof(nladdr));
434 nladdr.nl_family = AF_NETLINK;
435 nladdr.nl_pid = 0;
436
437 memset(&msg, 0, sizeof(msg));
438 msg.msg_name = &nladdr;
439 msg.msg_namelen = sizeof(nladdr);
440 msg.msg_iov = &iov;
441 msg.msg_iovlen = 1;
442
443 iov.iov_base = nh;
444 iov.iov_len = nh->nlmsg_len;
445
446 nh->nlmsg_flags |= NLM_F_ACK;
447 nh->nlmsg_seq = ++nl_command.seqno;
448
449 kdebugf("Sending seqno %d from address %p (talk)\n",
450 nl_command.seqno, (void*)&nl_command.seqno);
451
452 rc = sendmsg(nl_command.sock, &msg, 0);
453 if(rc < 0 && (errno == EAGAIN || errno == EINTR)) {
454 rc = wait_for_fd(1, nl_command.sock, 100);
455 if(rc <= 0) {
456 if(rc == 0)
457 errno = EAGAIN;
458 } else {
459 rc = sendmsg(nl_command.sock, &msg, 0);
460 }
461 }
462
463 if(rc < nh->nlmsg_len) {
464 int saved_errno = errno;
465 perror("sendmsg");
466 errno = saved_errno;
467 return -1;
468 }
469
470 rc = netlink_read(&nl_command, NULL, 1, NULL); /* ACK */
471
472 return rc;
473 }
474
475 static int
netlink_send_dump(int type,void * data,int len)476 netlink_send_dump(int type, void *data, int len) {
477
478 struct sockaddr_nl nladdr;
479 struct msghdr msg;
480 struct iovec iov[2];
481 union {
482 char raw[NLMSG_ALIGN(sizeof(struct nlmsghdr))];
483 struct nlmsghdr nh;
484 } buf;
485 int rc;
486
487 /* At least we should send an 'struct rtgenmsg' */
488 if(data == NULL || len == 0) {
489 errno = EIO;
490 return -1;
491 }
492
493 /* And more : using anything else that 'struct rtgenmsg' is currently */
494 /* ignored by the linux kernel (today: 2.6.21) because NLM_F_MATCH is */
495 /* not yet implemented */
496
497 memset(&nladdr, 0, sizeof(nladdr));
498 nladdr.nl_family = AF_NETLINK;
499
500 memset(&msg, 0, sizeof(msg));
501 msg.msg_name = &nladdr;
502 msg.msg_namelen = sizeof(nladdr);
503 msg.msg_iov = iov;
504 msg.msg_iovlen = 2;
505
506 iov[0].iov_base = buf.raw;
507 iov[0].iov_len = sizeof(buf.raw);
508 iov[1].iov_base = data;
509 iov[1].iov_len = len;
510
511 memset(&buf, 0, sizeof(buf));
512 buf.nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
513 buf.nh.nlmsg_type = type;
514 buf.nh.nlmsg_seq = ++nl_command.seqno;
515 buf.nh.nlmsg_len = NLMSG_LENGTH(len);
516
517 kdebugf("Sending seqno %d from address %p (dump)\n",
518 nl_command.seqno, (void*)&nl_command.seqno);
519
520 rc = sendmsg(nl_command.sock, &msg, 0);
521 if(rc < buf.nh.nlmsg_len) {
522 int saved_errno = errno;
523 perror("sendmsg");
524 errno = saved_errno;
525 return -1;
526 }
527
528 return 0;
529 }
530
531
532 int
kernel_setup(int setup)533 kernel_setup(int setup)
534 {
535 struct sysctl_setting *s;
536 int i, rc;
537
538 if(setup) {
539 if(export_table < 0)
540 export_table = RT_TABLE_MAIN;
541
542 if(import_table_count < 1)
543 import_tables[import_table_count++] = RT_TABLE_MAIN;
544
545 dgram_socket = socket(PF_INET, SOCK_DGRAM, 0);
546 if(dgram_socket < 0)
547 return -1;
548
549 rc = netlink_socket(&nl_command, 0);
550 if(rc < 0) {
551 perror("netlink_socket(0)");
552 return -1;
553 }
554 nl_setup = 1;
555
556 if(skip_kernel_setup)
557 return 1;
558
559 for(i=0; i<NUM_SYSCTLS; i++) {
560 s = &sysctl_settings[i];
561 s->was = read_proc(s->name);
562 if(s->was < 0) {
563 perror("Couldn't read sysctl");
564 return -1;
565 }
566 if(s->was != s->want) {
567 rc = write_proc(s->name, s->want);
568 if(rc < 0) {
569 perror("Couldn't write sysctl");
570 return -1;
571 }
572 }
573 }
574
575 return 1;
576 } else {
577 close(dgram_socket);
578 dgram_socket = -1;
579
580 close(nl_command.sock);
581 nl_command.sock = -1;
582 nl_setup = 0;
583
584 if(old_if != NULL) {
585 for(i = 0; i < num_old_if; i++)
586 free(old_if[i].ifname);
587 free(old_if);
588 old_if = NULL;
589 num_old_if = max_old_if = 0;
590 }
591
592 if(skip_kernel_setup) return 1;
593
594 for(i=0; i<NUM_SYSCTLS; i++) {
595 s = &sysctl_settings[i];
596 if(s->was >= 0 && s->was != s->want) {
597 rc = write_proc(s->name,s->was);
598 if(rc < 0) {
599 perror("Couldn't write sysctl");
600 return -1;
601 }
602 }
603 }
604
605 return 1;
606
607 }
608 }
609
610 static inline unsigned int
rtnlgrp_to_mask(unsigned int grp)611 rtnlgrp_to_mask(unsigned int grp)
612 {
613 return grp ? 1 << (grp - 1) : 0;
614 }
615
616 int
kernel_setup_socket(int setup)617 kernel_setup_socket(int setup)
618 {
619 int rc;
620
621 if(setup) {
622 rc = netlink_socket(&nl_listen,
623 rtnlgrp_to_mask(RTNLGRP_IPV6_ROUTE)
624 | rtnlgrp_to_mask(RTNLGRP_IPV4_ROUTE)
625 | rtnlgrp_to_mask(RTNLGRP_LINK)
626 | rtnlgrp_to_mask(RTNLGRP_IPV4_IFADDR)
627 | rtnlgrp_to_mask(RTNLGRP_IPV6_IFADDR)
628 /* We monitor rules, because it can be change by third parties. For example
629 a /etc/init.d/network restart on OpenWRT flush the rules. */
630 | rtnlgrp_to_mask(RTNLGRP_IPV4_RULE)
631 | rtnlgrp_to_mask(RTNLGRP_IPV6_RULE));
632 if(rc < 0) {
633 perror("netlink_socket(_ROUTE | _LINK | _IFADDR | _RULE)");
634 kernel_socket = -1;
635 return -1;
636 }
637
638 kernel_socket = nl_listen.sock;
639
640 return 1;
641
642 } else {
643
644 close(nl_listen.sock);
645 nl_listen.sock = -1;
646 kernel_socket = -1;
647
648 return 1;
649
650 }
651 }
652
653 static int
get_old_if(const char * ifname)654 get_old_if(const char *ifname)
655 {
656 int i;
657 for(i = 0; i < num_old_if; i++)
658 if(strcmp(old_if[i].ifname, ifname) == 0)
659 return i;
660 if(num_old_if >= MAX_INTERFACES)
661 return -1;
662 if(num_old_if >= max_old_if) {
663 int n = max_old_if == 0 ? 4 : 2 * max_old_if;
664 struct old_if *new =
665 realloc(old_if, n * sizeof(struct old_if));
666 if(new != NULL) {
667 old_if = new;
668 max_old_if = n;
669 }
670 }
671 if(num_old_if >= max_old_if)
672 return -1;
673
674 old_if[num_old_if].ifname = strdup(ifname);
675 if(old_if[num_old_if].ifname == NULL)
676 return -1;
677 old_if[num_old_if].rp_filter = -1;
678 return num_old_if++;
679 }
680
681 int
kernel_setup_interface(int setup,const char * ifname,int ifindex)682 kernel_setup_interface(int setup, const char *ifname, int ifindex)
683 {
684 if(skip_kernel_setup) return 1;
685
686 char buf[100];
687 int i, rc;
688
689 /* rp_filter has weird semantics: both all/rp_filter and ifname/rp_filter
690 must be set to 0 for the rp_filter to be disabled. Deal with it. */
691
692 rc = snprintf(buf, 100, "/proc/sys/net/ipv4/conf/%s/rp_filter", ifname);
693 if(rc < 0 || rc >= 100)
694 return -1;
695
696 i = get_old_if(ifname);
697 if(setup) {
698 if(i >= 0)
699 old_if[i].rp_filter = read_proc(buf);
700 if(i < 0 || old_if[i].rp_filter < 0)
701 fprintf(stderr,
702 "Warning: cannot save old configuration for %s.\n",
703 ifname);
704 if(old_if[i].rp_filter) {
705 rc = write_proc(buf, 0);
706 if(rc < 0)
707 return -1;
708 }
709 } else {
710 if(i >= 0 && old_if[i].rp_filter > 0)
711 rc = write_proc(buf, old_if[i].rp_filter);
712 else if(i < 0)
713 rc = -1;
714 else
715 rc = 1;
716
717 if(rc < 0)
718 fprintf(stderr,
719 "Warning: cannot restore old configuration for %s.\n",
720 ifname);
721 }
722
723 return 1;
724 }
725
726 int
kernel_interface_operational(const char * ifname,int ifindex)727 kernel_interface_operational(const char *ifname, int ifindex)
728 {
729 struct ifreq req;
730 int rc;
731 int flags = link_detect ? (IFF_UP | IFF_RUNNING) : IFF_UP;
732
733 memset(&req, 0, sizeof(req));
734 strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
735 rc = ioctl(dgram_socket, SIOCGIFFLAGS, &req);
736 if(rc < 0)
737 return -1;
738 return ((req.ifr_flags & flags) == flags);
739 }
740
741 int
kernel_interface_ipv4(const char * ifname,int ifindex,unsigned char * addr_r)742 kernel_interface_ipv4(const char *ifname, int ifindex, unsigned char *addr_r)
743 {
744 struct ifreq req;
745 int rc;
746
747 memset(&req, 0, sizeof(req));
748 strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
749 req.ifr_addr.sa_family = AF_INET;
750 rc = ioctl(dgram_socket, SIOCGIFADDR, &req);
751 if(rc < 0)
752 return -1;
753
754 memcpy(addr_r, &((struct sockaddr_in*)&req.ifr_addr)->sin_addr, 4);
755 return 1;
756 }
757
758 int
kernel_interface_mtu(const char * ifname,int ifindex)759 kernel_interface_mtu(const char *ifname, int ifindex)
760 {
761 struct ifreq req;
762 int rc;
763
764 memset(&req, 0, sizeof(req));
765 strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
766 rc = ioctl(dgram_socket, SIOCGIFMTU, &req);
767 if(rc < 0)
768 return -1;
769
770 return req.ifr_mtu;
771 }
772
773 static int
isbridge(const char * ifname,int ifindex)774 isbridge(const char *ifname, int ifindex)
775 {
776 char buf[256];
777 int rc, i;
778 unsigned long args[3];
779 int indices[256];
780
781 rc = snprintf(buf, 256, "/sys/class/net/%s", ifname);
782 if(rc < 0 || rc >= 256)
783 goto fallback;
784
785 if(access(buf, R_OK) < 0)
786 goto fallback;
787
788 rc = snprintf(buf, 256, "/sys/class/net/%s/bridge", ifname);
789 if(rc < 0 || rc >= 256)
790 goto fallback;
791
792 if(access(buf, F_OK) >= 0)
793 return 1;
794 else if(errno == ENOENT)
795 return 0;
796
797 fallback:
798 args[0] = BRCTL_GET_BRIDGES;
799 args[1] = (unsigned long)indices;
800 args[2] = 256;
801
802 rc = ioctl(dgram_socket, SIOCGIFBR, args);
803 if(rc < 0) {
804 if(errno == ENOPKG)
805 return 0;
806 else
807 return -1;
808 }
809
810 for(i = 0; i < rc; i++) {
811 if(indices[i] == ifindex)
812 return 1;
813 }
814
815 return 0;
816 }
817
818 static int
isbatman(const char * ifname,int ifindex)819 isbatman(const char *ifname, int ifindex)
820 {
821 char buf[256];
822 int rc;
823
824 rc = snprintf(buf, 256, "/sys/devices/virtual/net/%s/mesh", ifname);
825 if(rc < 0 || rc >= 256)
826 return -1;
827
828 if(access(buf, F_OK) >= 0)
829 return 1;
830
831 if(errno != ENOENT)
832 return -1;
833
834 return 0;
835 }
836
837 int
kernel_interface_wireless(const char * ifname,int ifindex)838 kernel_interface_wireless(const char *ifname, int ifindex)
839 {
840 #ifndef SIOCGIWNAME
841 #define SIOCGIWNAME 0x8B01
842 #endif
843 struct ifreq req;
844 int rc;
845
846 if(isbridge(ifname, ifindex) != 0 || isbatman(ifname, ifindex) != 0)
847 return -1;
848
849 memset(&req, 0, sizeof(req));
850 strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
851 rc = ioctl(dgram_socket, SIOCGIWNAME, &req);
852 if(rc < 0) {
853 if(errno == EOPNOTSUPP || errno == EINVAL)
854 rc = 0;
855 else {
856 perror("ioctl(SIOCGIWNAME)");
857 rc = -1;
858 }
859 } else {
860 rc = 1;
861 }
862 return rc;
863 }
864
865 /* Sorry for that, but I haven't managed to get <linux/wireless.h>
866 to include cleanly. */
867
868 #define SIOCGIWFREQ 0x8B05
869
870 struct iw_freq {
871 int m;
872 short e;
873 unsigned char i;
874 unsigned char flags;
875 };
876
877 struct iwreq_subset {
878 union {
879 char ifrn_name[IFNAMSIZ];
880 } ifr_ifrn;
881
882 union {
883 struct iw_freq freq;
884 } u;
885 };
886
887 static int
freq_to_chan(struct iw_freq * freq)888 freq_to_chan(struct iw_freq *freq)
889 {
890 int m = freq->m, e = freq->e;
891
892 /* If exponent is 0, assume the channel is encoded directly in m. */
893 if(e == 0 && m > 0 && m < 254)
894 return m;
895
896 if(e <= 6) {
897 int mega, step, c, i;
898
899 /* This encodes 1 MHz */
900 mega = 1000000;
901 for(i = 0; i < e; i++)
902 mega /= 10;
903
904 /* Channels 1 through 13 are 5 MHz apart, with channel 1 at 2412. */
905 step = 5 * mega;
906 c = 1 + (m - 2412 * mega + step / 2) / step;
907 if(c >= 1 && c <= 13)
908 return c;
909
910 /* Channel 14 is at 2484 MHz */
911 if(c >= 14 && m < 2484 * mega + step / 2)
912 return 14;
913
914 /* 802.11a channel 36 is at 5180 MHz */
915 c = 36 + (m - 5180 * mega + step / 2) / step;
916 if(c >= 34 && c <= 165)
917 return c;
918 }
919
920 errno = ENOENT;
921 return -1;
922 }
923
924 int
kernel_interface_channel(const char * ifname,int ifindex)925 kernel_interface_channel(const char *ifname, int ifindex)
926 {
927 struct iwreq_subset iwreq;
928 int rc;
929
930 memset(&iwreq, 0, sizeof(iwreq));
931 strncpy(iwreq.ifr_ifrn.ifrn_name, ifname, IFNAMSIZ);
932
933 rc = ioctl(dgram_socket, SIOCGIWFREQ, &iwreq);
934 if(rc >= 0)
935 return freq_to_chan(&iwreq.u.freq);
936 else
937 return -1;
938 }
939
940 int
kernel_has_ipv6_subtrees(void)941 kernel_has_ipv6_subtrees(void)
942 {
943 return (kernel_older_than("Linux", 3, 11) == 0);
944 }
945
946 int
kernel_route(int operation,int table,const unsigned char * dest,unsigned short plen,const unsigned char * src,unsigned short src_plen,const unsigned char * pref_src,const unsigned char * gate,int ifindex,unsigned int metric,const unsigned char * newgate,int newifindex,unsigned int newmetric,int newtable)947 kernel_route(int operation, int table,
948 const unsigned char *dest, unsigned short plen,
949 const unsigned char *src, unsigned short src_plen,
950 const unsigned char *pref_src,
951 const unsigned char *gate, int ifindex, unsigned int metric,
952 const unsigned char *newgate, int newifindex,
953 unsigned int newmetric, int newtable)
954 {
955 union { char raw[1024]; struct nlmsghdr nh; } buf;
956 struct rtmsg *rtm;
957 struct rtattr *rta;
958 int len = sizeof(buf.raw);
959 int rc, ipv4, use_src = 0;
960
961 if(!nl_setup) {
962 fprintf(stderr,"kernel_route: netlink not initialized.\n");
963 errno = EIO;
964 return -1;
965 }
966
967 /* if the socket has been closed after an IO error, */
968 /* we try to re-open it. */
969 if(nl_command.sock < 0) {
970 rc = netlink_socket(&nl_command, 0);
971 if(rc < 0) {
972 int olderrno = errno;
973 perror("kernel_route: netlink_socket()");
974 errno = olderrno;
975 return -1;
976 }
977 }
978
979 /* Check that the protocol family is consistent. */
980 if(plen >= 96 && v4mapped(dest)) {
981 if(!v4mapped(gate) ||
982 !v4mapped(src)) {
983 errno = EINVAL;
984 return -1;
985 }
986 } else {
987 if(v4mapped(gate) || v4mapped(src)) {
988 errno = EINVAL;
989 return -1;
990 }
991 }
992
993 if(operation == ROUTE_MODIFY) {
994 if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
995 newifindex == ifindex)
996 return 0;
997 /* It would be better to add the new route before removing the
998 old one, to avoid losing packets. However, this causes
999 problems with non-multipath kernels, which sometimes
1000 silently fail the request, causing "stuck" routes. Let's
1001 stick with the naive approach, and hope that the window is
1002 small enough to be negligible. */
1003 kernel_route(ROUTE_FLUSH, table, dest, plen,
1004 src, src_plen, pref_src,
1005 gate, ifindex, metric,
1006 NULL, 0, 0, 0);
1007 rc = kernel_route(ROUTE_ADD, newtable, dest, plen,
1008 src, src_plen, pref_src,
1009 newgate, newifindex, newmetric,
1010 NULL, 0, 0, 0);
1011 if(rc < 0) {
1012 if(errno == EEXIST)
1013 rc = 1;
1014 /* Should we try to re-install the flushed route on failure?
1015 Error handling is hard. */
1016 }
1017 return rc;
1018 }
1019
1020
1021 ipv4 = v4mapped(gate);
1022 use_src = !is_default(src, src_plen);
1023 if(use_src) {
1024 if(ipv4 || !has_ipv6_subtrees) {
1025 errno = ENOSYS;
1026 return -1;
1027 }
1028 }
1029
1030 kdebugf("kernel_route: %s %s from %s "
1031 "table %d metric %d dev %d nexthop %s\n",
1032 operation == ROUTE_ADD ? "add" :
1033 operation == ROUTE_FLUSH ? "flush" : "???",
1034 format_prefix(dest, plen), format_prefix(src, src_plen),
1035 table, metric, ifindex, format_address(gate));
1036
1037 /* Unreachable default routes cause all sort of weird interactions;
1038 ignore them. */
1039 if(metric >= KERNEL_INFINITY && (plen == 0 || (ipv4 && plen == 96)))
1040 return 0;
1041
1042 memset(&buf, 0, sizeof(buf));
1043 if(operation == ROUTE_ADD) {
1044 buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
1045 buf.nh.nlmsg_type = RTM_NEWROUTE;
1046 } else {
1047 buf.nh.nlmsg_flags = NLM_F_REQUEST;
1048 buf.nh.nlmsg_type = RTM_DELROUTE;
1049 }
1050
1051 rtm = NLMSG_DATA(&buf.nh);
1052 rtm->rtm_family = ipv4 ? AF_INET : AF_INET6;
1053 rtm->rtm_dst_len = ipv4 ? plen - 96 : plen;
1054 if(use_src)
1055 rtm->rtm_src_len = src_plen;
1056 rtm->rtm_table = table;
1057 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
1058 if(metric < KERNEL_INFINITY) {
1059 rtm->rtm_type = RTN_UNICAST;
1060 rtm->rtm_flags |= RTNH_F_ONLINK;
1061 } else
1062 rtm->rtm_type = RTN_UNREACHABLE;
1063
1064 rtm->rtm_protocol = RTPROT_BABEL;
1065
1066 rta = RTM_RTA(rtm);
1067
1068 if(ipv4) {
1069 rta = RTA_NEXT(rta, len);
1070 rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
1071 rta->rta_type = RTA_DST;
1072 memcpy(RTA_DATA(rta), dest + 12, sizeof(struct in_addr));
1073 } else {
1074 rta = RTA_NEXT(rta, len);
1075 rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
1076 rta->rta_type = RTA_DST;
1077 memcpy(RTA_DATA(rta), dest, sizeof(struct in6_addr));
1078 if(use_src) {
1079 rta = RTA_NEXT(rta, len);
1080 rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
1081 rta->rta_type = RTA_SRC;
1082 memcpy(RTA_DATA(rta), src, sizeof(struct in6_addr));
1083 }
1084 }
1085
1086 rta = RTA_NEXT(rta, len);
1087 rta->rta_len = RTA_LENGTH(sizeof(int));
1088 rta->rta_type = RTA_PRIORITY;
1089
1090 if(metric < KERNEL_INFINITY) {
1091 *(int*)RTA_DATA(rta) = metric;
1092 rta = RTA_NEXT(rta, len);
1093 rta->rta_len = RTA_LENGTH(sizeof(int));
1094 rta->rta_type = RTA_OIF;
1095 *(int*)RTA_DATA(rta) = ifindex;
1096
1097 #define ADD_IPARG(type, addr) \
1098 do if(ipv4) { \
1099 rta = RTA_NEXT(rta, len); \
1100 rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); \
1101 rta->rta_type = type; \
1102 memcpy(RTA_DATA(rta), addr + 12, sizeof(struct in_addr)); \
1103 } else { \
1104 rta = RTA_NEXT(rta, len); \
1105 rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); \
1106 rta->rta_type = type; \
1107 memcpy(RTA_DATA(rta), addr, sizeof(struct in6_addr)); \
1108 } while (0)
1109
1110 ADD_IPARG(RTA_GATEWAY, gate);
1111 if(pref_src)
1112 ADD_IPARG(RTA_PREFSRC, pref_src);
1113
1114 #undef ADD_IPARG
1115 } else {
1116 *(int*)RTA_DATA(rta) = -1;
1117 }
1118 buf.nh.nlmsg_len = (char*)rta + rta->rta_len - buf.raw;
1119
1120 return netlink_talk(&buf.nh);
1121 }
1122
1123 static int
parse_kernel_route_rta(struct rtmsg * rtm,int len,struct kernel_route * route)1124 parse_kernel_route_rta(struct rtmsg *rtm, int len, struct kernel_route *route)
1125 {
1126 int table = rtm->rtm_table;
1127 struct rtattr *rta = RTM_RTA(rtm);
1128 int i, is_v4;
1129
1130 len -= NLMSG_ALIGN(sizeof(*rtm));
1131
1132 memset(route, 0, sizeof(struct kernel_route));
1133 if(rtm->rtm_family == AF_INET) {
1134 /* if RTA_DST is not a TLV, that's a default destination */
1135 const unsigned char zeroes[4] = {0, 0, 0, 0};
1136 v4tov6(route->prefix, zeroes);
1137 v4tov6(route->src_prefix, zeroes);
1138 route->plen = 96;
1139 route->src_plen = 96;
1140 }
1141 route->proto = rtm->rtm_protocol;
1142
1143 is_v4 = rtm->rtm_family == AF_INET;
1144
1145 while(RTA_OK(rta, len)) {
1146 switch(rta->rta_type) {
1147 case RTA_DST:
1148 route->plen = GET_PLEN(rtm->rtm_dst_len, is_v4);
1149 COPY_ADDR(route->prefix, rta, is_v4);
1150 break;
1151 case RTA_SRC:
1152 route->src_plen = GET_PLEN(rtm->rtm_src_len, is_v4);
1153 COPY_ADDR(route->src_prefix, rta, is_v4);
1154 break;
1155 case RTA_GATEWAY:
1156 COPY_ADDR(route->gw, rta, is_v4);
1157 break;
1158 case RTA_OIF:
1159 route->ifindex = *(int*)RTA_DATA(rta);
1160 break;
1161 case RTA_PRIORITY:
1162 route->metric = *(int*)RTA_DATA(rta);
1163 if(route->metric < 0 || route->metric > KERNEL_INFINITY)
1164 route->metric = KERNEL_INFINITY;
1165 break;
1166 case RTA_TABLE:
1167 table = *(int*)RTA_DATA(rta);
1168 break;
1169 default:
1170 break;
1171 }
1172 rta = RTA_NEXT(rta, len);
1173 }
1174
1175 for(i = 0; i < import_table_count; i++)
1176 if(table == import_tables[i])
1177 return 0;
1178
1179 return -1;
1180 }
1181
1182 static void
print_kernel_route(int add,int protocol,int type,struct kernel_route * route)1183 print_kernel_route(int add, int protocol, int type,
1184 struct kernel_route *route)
1185 {
1186 char ifname[IFNAMSIZ];
1187 char addr_prefix[INET6_ADDRSTRLEN];
1188 char src_addr_prefix[INET6_ADDRSTRLEN];
1189 char addr_gw[INET6_ADDRSTRLEN];
1190
1191 if(!inet_ntop(AF_INET6, route->prefix,
1192 addr_prefix, sizeof(addr_prefix)) ||
1193 !inet_ntop(AF_INET6,route->gw, addr_gw, sizeof(addr_gw)) ||
1194 !if_indextoname(route->ifindex, ifname)) {
1195 kdebugf("Couldn't format kernel route for printing.");
1196 return;
1197 }
1198
1199 if(route->src_plen >= 0) {
1200 if(!inet_ntop(AF_INET6, route->src_prefix,
1201 src_addr_prefix, sizeof(src_addr_prefix))) {
1202 kdebugf("Couldn't format kernel route for printing.");
1203 return;
1204 }
1205
1206 kdebugf("%s kernel route: dest: %s/%d gw: %s metric: %d if: %s "
1207 "(proto: %d, type: %d, from: %s/%d)",
1208 add == RTM_NEWROUTE ? "Add" : "Delete",
1209 addr_prefix, route->plen, addr_gw, route->metric, ifname,
1210 protocol, type, src_addr_prefix, route->src_plen);
1211 return;
1212 }
1213
1214 kdebugf("%s kernel route: dest: %s/%d gw: %s metric: %d if: %s "
1215 "(proto: %d, type: %d)",
1216 add == RTM_NEWROUTE ? "Add" : "Delete",
1217 addr_prefix, route->plen, addr_gw, route->metric, ifname,
1218 protocol, type);
1219 }
1220
1221 static int
filter_kernel_routes(struct nlmsghdr * nh,struct kernel_route * route)1222 filter_kernel_routes(struct nlmsghdr *nh, struct kernel_route *route)
1223 {
1224 int rc, len;
1225 struct rtmsg *rtm;
1226
1227 len = nh->nlmsg_len;
1228
1229 if(nh->nlmsg_type != RTM_NEWROUTE &&
1230 nh->nlmsg_type != RTM_DELROUTE)
1231 return 0;
1232
1233 rtm = (struct rtmsg*)NLMSG_DATA(nh);
1234 len -= NLMSG_LENGTH(0);
1235
1236 if(rtm->rtm_protocol == RTPROT_BABEL)
1237 return 0;
1238
1239 /* Ignore cached routes, advertised by some kernels (linux 3.x). */
1240 if(rtm->rtm_flags & RTM_F_CLONED)
1241 return 0;
1242
1243 rc = parse_kernel_route_rta(rtm, len, route);
1244 if(rc < 0)
1245 return 0;
1246
1247 /* Ignore default unreachable routes; no idea where they come from. */
1248 if(route->plen == 0 && route->metric >= KERNEL_INFINITY)
1249 return 0;
1250
1251 if(debug >= 2) {
1252 if(rc >= 0) {
1253 print_kernel_route(nh->nlmsg_type, rtm->rtm_protocol,
1254 rtm->rtm_type, route);
1255 }
1256 }
1257
1258 return 1;
1259
1260 }
1261
1262 /* This function should not return routes installed by us. */
1263 int
kernel_dump(int operation,struct kernel_filter * filter)1264 kernel_dump(int operation, struct kernel_filter *filter)
1265 {
1266 int i, rc;
1267 int families[2] = { AF_INET6, AF_INET };
1268 struct rtgenmsg g;
1269
1270 if(!nl_setup) {
1271 fprintf(stderr,"kernel_dump: netlink not initialized.\n");
1272 errno = EIO;
1273 return -1;
1274 }
1275
1276 if(nl_command.sock < 0) {
1277 rc = netlink_socket(&nl_command, 0);
1278 if(rc < 0) {
1279 int save = errno;
1280 perror("kernel_dump: netlink_socket()");
1281 errno = save;
1282 return -1;
1283 }
1284 }
1285
1286 for(i = 0; i < 2; i++) {
1287 memset(&g, 0, sizeof(g));
1288 g.rtgen_family = families[i];
1289 if(operation & CHANGE_ROUTE) {
1290 rc = netlink_send_dump(RTM_GETROUTE, &g, sizeof(g));
1291 if(rc < 0)
1292 return -1;
1293
1294 rc = netlink_read(&nl_command, NULL, 1, filter);
1295 if(rc < 0)
1296 return -1;
1297 }
1298
1299 memset(&g, 0, sizeof(g));
1300 g.rtgen_family = families[i];
1301 if(operation & CHANGE_RULE) {
1302 rc = netlink_send_dump(RTM_GETRULE, &g, sizeof(g));
1303 if(rc < 0)
1304 return -1;
1305
1306 rc = netlink_read(&nl_command, NULL, 1, filter);
1307 if(rc < 0)
1308 return -1;
1309 }
1310 }
1311
1312 if(operation & CHANGE_ADDR) {
1313 memset(&g, 0, sizeof(g));
1314 g.rtgen_family = AF_UNSPEC;
1315 rc = netlink_send_dump(RTM_GETADDR, &g, sizeof(g));
1316 if(rc < 0)
1317 return -1;
1318
1319 rc = netlink_read(&nl_command, NULL, 1, filter);
1320 if(rc < 0)
1321 return -1;
1322 }
1323
1324 return 0;
1325 }
1326
1327 static char *
parse_ifname_rta(struct ifinfomsg * info,int len)1328 parse_ifname_rta(struct ifinfomsg *info, int len)
1329 {
1330 struct rtattr *rta = IFLA_RTA(info);
1331 char *ifname = NULL;
1332
1333 len -= NLMSG_ALIGN(sizeof(*info));
1334
1335 while(RTA_OK(rta, len)) {
1336 switch(rta->rta_type) {
1337 case IFLA_IFNAME:
1338 ifname = RTA_DATA(rta);
1339 break;
1340 default:
1341 break;
1342 }
1343 rta = RTA_NEXT(rta, len);
1344 }
1345 return ifname;
1346 }
1347
1348 static int
parse_addr_rta(struct ifaddrmsg * addr,int len,struct in6_addr * res)1349 parse_addr_rta(struct ifaddrmsg *addr, int len, struct in6_addr *res)
1350 {
1351 struct rtattr *rta;
1352 int is_local = 0;
1353 len -= NLMSG_ALIGN(sizeof(*addr));
1354 rta = IFA_RTA(addr);
1355
1356 while(RTA_OK(rta, len)) {
1357 switch(rta->rta_type) {
1358 case IFA_LOCAL:
1359 /* On some point-to-point technologies, there's both _LOCAL
1360 and _ADDRESS, and _ADDRESS is apparently the peer address
1361 while _LOCAL is the one we want. */
1362 is_local = 1;
1363 /* fallthrough */
1364 case IFA_ADDRESS:
1365 switch(addr->ifa_family) {
1366 case AF_INET:
1367 if(res)
1368 v4tov6(res->s6_addr, RTA_DATA(rta));
1369 break;
1370 case AF_INET6:
1371 if(res)
1372 memcpy(res->s6_addr, RTA_DATA(rta), 16);
1373 break;
1374 default:
1375 kdebugf("ifaddr: unexpected address family %d\n",
1376 addr->ifa_family);
1377 return -1;
1378 break;
1379 }
1380 if(is_local)
1381 return 0;
1382 break;
1383 default:
1384 break;
1385 }
1386 rta = RTA_NEXT(rta, len);
1387 }
1388 return 0;
1389 }
1390
1391 static int
filter_link(struct nlmsghdr * nh,struct kernel_link * link)1392 filter_link(struct nlmsghdr *nh, struct kernel_link *link)
1393 {
1394 struct ifinfomsg *info;
1395 int len;
1396 int ifindex;
1397 unsigned int ifflags;
1398
1399 len = nh->nlmsg_len;
1400
1401 if(nh->nlmsg_type != RTM_NEWLINK && nh->nlmsg_type != RTM_DELLINK)
1402 return 0;
1403
1404 info = (struct ifinfomsg*)NLMSG_DATA(nh);
1405 len -= NLMSG_LENGTH(0);
1406
1407 ifindex = info->ifi_index;
1408 ifflags = info->ifi_flags;
1409
1410 link->ifname = parse_ifname_rta(info, len);
1411 if(link->ifname == NULL)
1412 return 0;
1413 kdebugf("filter_interfaces: link change on if %s(%d): 0x%x\n",
1414 link->ifname, ifindex, (unsigned)ifflags);
1415 return 1;
1416 }
1417
1418 /* If data is null, takes all addresses. If data is not null, takes
1419 either link-local or global addresses depending of the value of
1420 data[4]. */
1421
1422 static int
filter_addresses(struct nlmsghdr * nh,struct kernel_addr * addr)1423 filter_addresses(struct nlmsghdr *nh, struct kernel_addr *addr)
1424 {
1425 int rc;
1426 int len;
1427 struct ifaddrmsg *ifa;
1428 char ifname[IFNAMSIZ];
1429
1430 len = nh->nlmsg_len;
1431
1432 if(nh->nlmsg_type != RTM_NEWADDR &&
1433 nh->nlmsg_type != RTM_DELADDR)
1434 return 0;
1435
1436 ifa = (struct ifaddrmsg *)NLMSG_DATA(nh);
1437 len -= NLMSG_LENGTH(0);
1438
1439 rc = parse_addr_rta(ifa, len, &addr->addr);
1440 if(rc < 0)
1441 return 0;
1442 addr->ifindex = ifa->ifa_index;
1443
1444 kdebugf("found address on interface %s(%d): %s\n",
1445 if_indextoname(ifa->ifa_index, ifname), ifa->ifa_index,
1446 format_address(addr->addr.s6_addr));
1447
1448 return 1;
1449 }
1450
1451 static int
filter_netlink(struct nlmsghdr * nh,struct kernel_filter * filter)1452 filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter)
1453 {
1454 int rc;
1455 union {
1456 struct kernel_route route;
1457 struct kernel_addr addr;
1458 struct kernel_link link;
1459 } u;
1460
1461 switch(nh->nlmsg_type) {
1462 case RTM_NEWROUTE:
1463 case RTM_DELROUTE:
1464 if(!filter->route) break;
1465 rc = filter_kernel_routes(nh, &u.route);
1466 if(rc <= 0) break;
1467 return filter->route(&u.route, filter->route_closure);
1468 case RTM_NEWLINK:
1469 case RTM_DELLINK:
1470 if(!filter->link) break;
1471 rc = filter_link(nh, &u.link);
1472 if(rc <= 0) break;
1473 return filter->link(&u.link, filter->link_closure);
1474 case RTM_NEWADDR:
1475 case RTM_DELADDR:
1476 if(!filter->addr) break;
1477 rc = filter_addresses(nh, &u.addr);
1478 if(rc <= 0) break;
1479 return filter->addr(&u.addr, filter->addr_closure);
1480 default:
1481 kdebugf("filter_netlink: unexpected message type %d\n",
1482 nh->nlmsg_type);
1483 break;
1484 }
1485 return 0;
1486 }
1487
1488 int
kernel_callback(struct kernel_filter * filter)1489 kernel_callback(struct kernel_filter *filter)
1490 {
1491 int rc;
1492
1493 kdebugf("\nReceived changes in kernel tables.\n");
1494
1495 if(nl_listen.sock < 0) {
1496 rc = kernel_setup_socket(1);
1497 if(rc < 0) {
1498 perror("kernel_callback: kernel_setup_socket(1)");
1499 return -1;
1500 }
1501 }
1502 rc = netlink_read(&nl_listen, &nl_command, 0, filter);
1503
1504 if(rc < 0 && nl_listen.sock < 0)
1505 kernel_setup_socket(1);
1506
1507 return 0;
1508 }
1509