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