1 /* AirScan (a.k.a. eSCL) backend for SANE
2  *
3  * Copyright (C) 2019 and up by Alexander Pevzner (pzz@apevzner.com)
4  * See LICENSE for license terms and conditions
5  *
6  * Network interfaces addresses
7  */
8 
9 #include "airscan.h"
10 
11 #include <errno.h>
12 #include <string.h>
13 #include <unistd.h>
14 
15 #include <arpa/inet.h>
16 #include <ifaddrs.h>
17 #ifdef OS_HAVE_RTNETLINK
18 #include <linux/netlink.h>
19 #include <linux/rtnetlink.h>
20 #endif
21 #ifdef OS_HAVE_AF_ROUTE
22 #include <net/route.h>
23 #endif
24 #include <net/if.h>
25 #include <sys/socket.h>
26 
27 /* Static variables */
28 static int netif_rtnetlink_sock = -1;
29 static eloop_fdpoll *netif_rtnetlink_fdpoll;
30 static ll_head netif_notifier_list;
31 static struct ifaddrs *netif_ifaddrs;
32 
33 /* Forward declarations */
34 static netif_addr*
35 netif_addr_list_sort (netif_addr *list);
36 
37 /* Get distance to the target address
38  */
39 NETIF_DISTANCE
netif_distance_get(const struct sockaddr * addr)40 netif_distance_get (const struct sockaddr *addr)
41 {
42     struct ifaddrs         *ifa;
43     struct in_addr         addr4, ifaddr4, ifmask4;
44     struct in6_addr        addr6, ifaddr6, ifmask6;
45     static struct in6_addr zero6;
46     size_t                 i;
47     NETIF_DISTANCE         distance = NETIF_DISTANCE_ROUTED;
48 
49     for (ifa = netif_ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
50         /* Skip interface without address or netmask */
51         if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL) {
52             continue;
53         }
54 
55         /* Compare address family */
56         if (addr->sa_family != ifa->ifa_addr->sa_family) {
57             continue;
58         }
59 
60         /* Check direct reachability */
61         switch (addr->sa_family) {
62         case AF_INET:
63             addr4 = ((struct sockaddr_in*) addr)->sin_addr;
64             ifaddr4 = ((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
65             ifmask4 = ((struct sockaddr_in*) ifa->ifa_netmask)->sin_addr;
66 
67             if (addr4.s_addr == ifaddr4.s_addr) {
68                 return NETIF_DISTANCE_LOOPBACK;
69             }
70 
71             if (((addr4.s_addr ^ ifaddr4.s_addr) & ifmask4.s_addr) == 0) {
72                 distance = NETIF_DISTANCE_DIRECT;
73             }
74             break;
75 
76         case AF_INET6:
77             addr6 = ((struct sockaddr_in6*) addr)->sin6_addr;
78             ifaddr6 = ((struct sockaddr_in6*) ifa->ifa_addr)->sin6_addr;
79             ifmask6 = ((struct sockaddr_in6*) ifa->ifa_netmask)->sin6_addr;
80 
81             if (!memcmp(&addr6, &ifaddr6, sizeof(struct in6_addr))) {
82                 return NETIF_DISTANCE_LOOPBACK;
83             }
84 
85             for (i = 0; i < sizeof(struct in6_addr); i ++) {
86                 addr6.s6_addr[i] ^= ifaddr6.s6_addr[i];
87                 addr6.s6_addr[i] &= ifmask6.s6_addr[i];
88             }
89 
90             if (!memcmp(&addr6, &zero6, sizeof(struct in6_addr))) {
91                 distance = NETIF_DISTANCE_DIRECT;
92             }
93             break;
94         }
95     }
96 
97     return distance;
98 }
99 
100 /* Check that interface has non-link-local address
101  * of particular address family
102  */
103 bool
netif_has_non_link_local_addr(int af,int ifindex)104 netif_has_non_link_local_addr (int af, int ifindex)
105 {
106     struct ifaddrs *ifa;
107 
108     for (ifa = netif_ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
109         struct sockaddr *addr;
110 
111         /* Skip interface without address */
112         if ((addr = ifa->ifa_addr) == NULL) {
113             continue;
114         }
115 
116         /* Check address family against requested */
117         if (addr->sa_family != af) {
118             continue;
119         }
120 
121         /* Skip link-local addresses */
122         if (ip_sockaddr_is_linklocal(addr)) {
123             continue;
124         }
125 
126         /* Check interface index */
127         if (ifindex == (int) if_nametoindex(ifa->ifa_name)) {
128             return true;
129         }
130     }
131 
132     return false;
133 }
134 
135 /* Get list of network interfaces addresses
136  */
137 netif_addr*
netif_addr_list_get(void)138 netif_addr_list_get (void)
139 {
140     struct ifaddrs *ifa;
141     netif_addr     *list = NULL, *addr;
142 
143     for (ifa = netif_ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
144         /* Skip interface without address */
145         if (ifa->ifa_addr == NULL) {
146             continue;
147         }
148 
149         /* Skip loopback interface */
150         if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) {
151             continue;
152         }
153 
154         /* Obtain interface index. Skip address, if it failed */
155         int idx = if_nametoindex(ifa->ifa_name);
156         if (idx <= 0) {
157             continue;
158         }
159 
160         /* Translate struct ifaddrs to netif_addr */
161         addr = mem_new(netif_addr, 1);
162         addr->next = list;
163         addr->ifindex = idx;
164         strncpy(addr->ifname.text, ifa->ifa_name,
165             sizeof(addr->ifname.text) - 1);
166 
167         switch (ifa->ifa_addr->sa_family) {
168         case AF_INET:
169             addr->ip.v4 = ((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
170             inet_ntop(AF_INET, &addr->ip.v4,
171                 addr->straddr, sizeof(addr->straddr));
172             break;
173 
174         case AF_INET6:
175             addr->ipv6 = true;
176             addr->ip.v6 = ((struct sockaddr_in6*) ifa->ifa_addr)->sin6_addr;
177             inet_ntop(AF_INET6, &addr->ip.v6,
178                 addr->straddr, sizeof(addr->straddr));
179             break;
180 
181         default:
182             /* Paranoia; should not actually happen */
183             mem_free(addr);
184             addr = NULL;
185             break;
186         }
187 
188         if (addr != NULL) {
189             addr->next = list;
190             list = addr;
191         }
192     }
193 
194     return netif_addr_list_sort(list);
195 }
196 
197 /* Free a single netif_addr
198  */
199 static void
netif_addr_free_single(netif_addr * addr)200 netif_addr_free_single (netif_addr *addr)
201 {
202     mem_free(addr);
203 }
204 
205 /* Free list of network interfaces addresses
206  */
207 void
netif_addr_list_free(netif_addr * list)208 netif_addr_list_free (netif_addr *list)
209 {
210     while (list != NULL) {
211         netif_addr *next = list->next;
212         netif_addr_free_single(list);
213         list = next;
214     }
215 }
216 
217 /* Compare two netif_addr addresses, for sorting
218  */
219 static int
netif_addr_cmp(netif_addr * a1,netif_addr * a2)220 netif_addr_cmp (netif_addr *a1, netif_addr *a2)
221 {
222     bool ll1, ll2;
223 
224     /* Compare interface indices */
225     if (a1->ifindex != a2->ifindex) {
226         return a1->ifindex - a2->ifindex;
227     }
228 
229     /* Prefer normal addresses, rather that link-local */
230     ll1 = ip_is_linklocal(a1->ipv6 ? AF_INET6 : AF_INET, &a1->ip);
231     ll2 = ip_is_linklocal(a2->ipv6 ? AF_INET6 : AF_INET, &a2->ip);
232 
233     if (ll1 != ll2) {
234         return ll1 ? 1 : -1;
235     }
236 
237     /* Be in trend: prefer IPv6 addresses */
238     if (a1->ipv6 != a2->ipv6) {
239         return (int) a2->ipv6 - (int) a1->ipv6;
240     }
241 
242     /* Otherwise, sort lexicographically */
243     return strcmp(a1->straddr, a2->straddr);
244 }
245 
246 /* Revert netif_addr list
247  */
248 static netif_addr*
netif_addr_list_revert(netif_addr * list)249 netif_addr_list_revert (netif_addr *list)
250 {
251     netif_addr   *prev = NULL, *next;
252 
253     while (list != NULL) {
254         next = list->next;
255         list->next = prev;
256         prev = list;
257         list = next;
258     }
259 
260     return prev;
261 }
262 
263 /* Sort list of addresses
264  */
265 static netif_addr*
netif_addr_list_sort(netif_addr * list)266 netif_addr_list_sort (netif_addr *list)
267 {
268     netif_addr *halves[2] = {NULL, NULL};
269     int               half = 0;
270 
271     if (list == NULL || list->next == NULL) {
272         return list;
273     }
274 
275     /* Split list into halves */
276     while (list != NULL) {
277         netif_addr *next = list->next;
278 
279         list->next = halves[half];
280         halves[half] = list;
281 
282         half ^= 1;
283         list = next;
284     }
285 
286     /* Sort each half, recursively */
287     for (half = 0; half < 2; half ++) {
288         halves[half] = netif_addr_list_sort(halves[half]);
289     }
290 
291     /* Now merge the sorted halves */
292     list = NULL;
293     while (halves[0] != NULL || halves[1] != NULL) {
294         netif_addr *next;
295 
296         if (halves[0] == NULL) {
297             half = 1;
298         } else if (halves[1] == NULL) {
299             half = 0;
300         } else if (netif_addr_cmp(halves[0], halves[1]) < 0) {
301             half = 0;
302         } else {
303             half = 1;
304         }
305 
306         next = halves[half]->next;
307         halves[half]->next = list;
308         list = halves[half];
309         halves[half] = next;
310     }
311 
312     /* And revert the list, as after merging it is reverted */
313     return netif_addr_list_revert(list);
314 }
315 
316 /* Compute a difference between two lists of addresses.
317  *
318  * It works by tossing nodes between 3 output lists:
319  *   * if node is present in list2 only, it is moved
320  *     to netif_diff.added
321  *   * if node is present in list1 only, it is moved
322  *     to netif_diff.removed
323  *   * if node is present in both lists, node from
324  *     list1 is moved to preserved, and node from
325  *     list2 is released
326  *
327  * It assumes, both lists are sorted, as returned
328  * by netif_addr_get(). Returned lists are also sorted
329  */
330 netif_diff
netif_diff_compute(netif_addr * list1,netif_addr * list2)331 netif_diff_compute (netif_addr *list1, netif_addr *list2)
332 {
333     netif_diff diff = {NULL, NULL, NULL};
334 
335     while (list1 != NULL || list2 != NULL) {
336         netif_addr *addr;
337         int        cmp;
338 
339         if (list1 == NULL) {
340             cmp = 1;
341         } else if (list2 == NULL) {
342             cmp = -1;
343         } else {
344             cmp = netif_addr_cmp(list1, list2);
345         }
346 
347         if (cmp < 0) {
348             addr = list1;
349             list1 = list1->next;
350             addr->next = diff.removed;
351             diff.removed = addr;
352         } else if (cmp > 0) {
353             addr = list2;
354             list2 = list2->next;
355             addr->next = diff.added;
356             diff.added = addr;
357         } else {
358             addr = list1;
359             list1 = list1->next;
360             addr->next = diff.preserved;
361             diff.preserved = addr;
362 
363             addr = list2;
364             list2 = list2->next;
365             netif_addr_free_single(addr);
366         }
367     }
368 
369     diff.added = netif_addr_list_revert(diff.added);
370     diff.removed = netif_addr_list_revert(diff.removed);
371     diff.preserved = netif_addr_list_revert(diff.preserved);
372 
373     return diff;
374 }
375 
376 /* Merge two lists of addresses
377  *
378  * Input lists are consumed and new list is created.
379  *
380  * Input lists are assumed to be sorted, and output
381  * list will be sorted as well
382  */
383 netif_addr*
netif_addr_list_merge(netif_addr * list1,netif_addr * list2)384 netif_addr_list_merge (netif_addr *list1, netif_addr *list2)
385 {
386     netif_addr *list = NULL;
387 
388     while (list1 != NULL || list2 != NULL) {
389         netif_addr *addr;
390         int        cmp;
391 
392         if (list1 == NULL) {
393             cmp = 1;
394         } else if (list2 == NULL) {
395             cmp = -1;
396         } else {
397             cmp = netif_addr_cmp(list1, list2);
398         }
399 
400         if (cmp < 0) {
401             addr = list1;
402             list1 = list1->next;
403         } else {
404             addr = list2;
405             list2 = list2->next;
406         }
407 
408         addr->next = list;
409         list = addr;
410     }
411 
412     return netif_addr_list_revert(list);
413 }
414 
415 /* Network interfaces addresses change notifier
416  */
417 struct netif_notifier {
418     void         (*callback)(void*); /* Notification callback */
419     void         *data;              /* Callback data */
420     ll_node      list_node;          /* in the netif_notifier_list */
421 };
422 
423 /* Get a new list of network interfaces and notify the callbacks
424  */
425 static void
netif_refresh_ifaddrs(void)426 netif_refresh_ifaddrs (void)
427 {
428     struct ifaddrs  *new_ifaddrs;
429     ll_node         *node;
430     int              rc;
431 
432     rc = getifaddrs(&new_ifaddrs);
433     if (rc >= 0) {
434         if (netif_ifaddrs != NULL) {
435             freeifaddrs(netif_ifaddrs);
436         }
437 
438         netif_ifaddrs = new_ifaddrs;
439     }
440 
441     /* Call all registered callbacks */
442     for (LL_FOR_EACH(node, &netif_notifier_list)) {
443         netif_notifier *notifier;
444         notifier = OUTER_STRUCT(node, netif_notifier, list_node);
445         notifier->callback(notifier->data);
446     }
447 }
448 
449 /* netif_notifier read callback
450  */
451 static void
netif_notifier_read_callback(int fd,void * data,ELOOP_FDPOLL_MASK mask)452 netif_notifier_read_callback (int fd, void *data, ELOOP_FDPOLL_MASK mask)
453 {
454     static uint8_t  buf[16384];
455     int             rc;
456 
457     (void) fd;
458     (void) data;
459     (void) mask;
460 
461     /* Get rtnetlink message */
462     rc = read(netif_rtnetlink_sock, buf, sizeof(buf));
463     if (rc < 0) {
464         return;
465     }
466 
467 #if defined(OS_HAVE_RTNETLINK)
468     struct nlmsghdr *p;
469     size_t          sz;
470 
471     /* Parse rtnetlink message, to suppress unneeded (and relatively
472      * expensive) netif_refresh_ifaddrs() calls. We are only interested
473      * in RTM_NEWADDR/RTM_DELADDR notifications
474      */
475     sz = (size_t) rc;
476     for (p = (struct nlmsghdr*) buf;
477         sz >= sizeof(struct nlmsghdr); p = NLMSG_NEXT(p, sz)) {
478 
479         if (!NLMSG_OK(p, sz) || sz < p->nlmsg_len) {
480             return;
481         }
482 
483         switch (p->nlmsg_type) {
484         case NLMSG_DONE:
485             return;
486 
487         case RTM_NEWADDR:
488         case RTM_DELADDR:
489             netif_refresh_ifaddrs();
490             return;
491         }
492     }
493 #elif defined(OS_HAVE_AF_ROUTE)
494     /* Note, on OpenBSD we have ROUTE_MSGFILTER, but FreeBSD lacks
495      * this feature, so we have to filter received routing messages
496      * manually, to avoid relatively expensive netif_refresh_ifaddrs()
497      * calls
498      */
499     struct rt_msghdr *rtm = (struct rt_msghdr*) buf;
500     if (rc >= (int) sizeof(struct rt_msghdr)) {
501         switch (rtm->rtm_type) {
502         case RTM_NEWADDR:
503         case RTM_DELADDR:
504             netif_refresh_ifaddrs();
505             break;
506         }
507     }
508 #endif
509 }
510 
511 /* Create netif_notifier
512  */
513 netif_notifier*
netif_notifier_create(void (* callback)(void *),void * data)514 netif_notifier_create (void (*callback) (void*), void *data)
515 {
516     netif_notifier *notifier = mem_new(netif_notifier, 1);
517 
518     notifier->callback = callback;
519     notifier->data = data;
520 
521     ll_push_end(&netif_notifier_list, &notifier->list_node);
522 
523     return notifier;
524 }
525 
526 /* Destroy netif_notifier
527  */
528 void
netif_notifier_free(netif_notifier * notifier)529 netif_notifier_free (netif_notifier *notifier)
530 {
531     ll_del(&notifier->list_node);
532     mem_free(notifier);
533 }
534 
535 /* Start/stop callback
536  */
537 static void
netif_start_stop_callback(bool start)538 netif_start_stop_callback (bool start)
539 {
540     if (start) {
541         netif_rtnetlink_fdpoll = eloop_fdpoll_new(netif_rtnetlink_sock,
542             netif_notifier_read_callback, NULL);
543         eloop_fdpoll_set_mask(netif_rtnetlink_fdpoll, ELOOP_FDPOLL_READ);
544     } else {
545         eloop_fdpoll_free(netif_rtnetlink_fdpoll);
546         netif_rtnetlink_fdpoll = NULL;
547     }
548 }
549 
550 /* Initialize network interfaces monitoring
551  */
552 SANE_Status
netif_init(void)553 netif_init (void)
554 {
555     ll_init(&netif_notifier_list);
556 
557 #if defined(OS_HAVE_RTNETLINK)
558     struct sockaddr_nl addr;
559     int                rc;
560 
561     /* Create AF_NETLINK socket */
562     netif_rtnetlink_sock = socket(AF_NETLINK,
563         SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, NETLINK_ROUTE);
564 
565     if (netif_rtnetlink_sock < 0) {
566         log_debug(NULL, "can't open AF_NETLINK socket: %s", strerror(errno));
567         return SANE_STATUS_IO_ERROR;
568     }
569 
570     /* Subscribe to notifications */
571     memset(&addr, 0, sizeof(addr));
572     addr.nl_family = AF_NETLINK;
573     addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
574 
575     rc = bind(netif_rtnetlink_sock, (struct sockaddr*) &addr, sizeof(addr));
576     if (rc < 0) {
577         log_debug(NULL, "can't bind AF_NETLINK socket: %s", strerror(errno));
578         close(netif_rtnetlink_sock);
579         return SANE_STATUS_IO_ERROR;
580     }
581 #elif defined(OS_HAVE_AF_ROUTE)
582     /* Create AF_ROUTE socket */
583     netif_rtnetlink_sock = socket(AF_ROUTE,
584         SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, AF_UNSPEC);
585 
586     if (netif_rtnetlink_sock < 0) {
587         log_debug(NULL, "can't open AF_ROUTE socket: %s", strerror(errno));
588         return SANE_STATUS_IO_ERROR;
589     }
590 
591 #ifdef ROUTE_MSGFILTER
592     unsigned int rtfilter =
593         ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR);
594     if (setsockopt(netif_rtnetlink_sock, AF_ROUTE, ROUTE_MSGFILTER,
595                    &rtfilter, sizeof(rtfilter)) < 0) {
596         /* Note, this error is not fatal for us, it is enough to
597          * log it and continue
598          */
599         log_debug(NULL, "can't set ROUTE_MSGFILTER: %s", strerror(errno));
600     }
601 #endif
602 #endif
603 
604     /* Initialize netif_ifaddrs */
605     if (getifaddrs(&netif_ifaddrs) < 0) {
606         log_debug(NULL, "getifaddrs(): %s", strerror(errno));
607         close(netif_rtnetlink_sock);
608         return SANE_STATUS_IO_ERROR;
609     }
610 
611     /* Register start/stop callback */
612     eloop_add_start_stop_callback(netif_start_stop_callback);
613 
614     return SANE_STATUS_GOOD;
615 }
616 
617 /* Cleanup network interfaces monitoring
618  */
619 void
netif_cleanup(void)620 netif_cleanup (void)
621 {
622     if (netif_ifaddrs != NULL) {
623         freeifaddrs(netif_ifaddrs);
624         netif_ifaddrs = NULL;
625     }
626 
627     if (netif_rtnetlink_sock >= 0) {
628         close(netif_rtnetlink_sock);
629         netif_rtnetlink_sock = -1;
630     }
631 }
632 
633 /* vim:ts=8:sw=4:et
634  */
635