• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/mdnsd/interface.c

  1 /*
  2  * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  3  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU Lesser General Public License version 2.1
  7  * as published by the Free Software Foundation
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  */
 14 
 15 #define _GNU_SOURCE
 16 #include <sys/socket.h>
 17 #include <sys/ioctl.h>
 18 #include <sys/types.h>
 19 #include <sys/stat.h>
 20 #include <sys/utsname.h>
 21 #include <net/if.h>
 22 #include <netinet/in.h>
 23 #include <arpa/inet.h>
 24 #include <sys/types.h>
 25 
 26 #include <ifaddrs.h>
 27 #include <stdlib.h>
 28 #include <string.h>
 29 #include <unistd.h>
 30 #include <stdio.h>
 31 #include <errno.h>
 32 
 33 #include <libubox/usock.h>
 34 #include <libubox/uloop.h>
 35 #include <libubox/avl-cmp.h>
 36 #include <libubox/utils.h>
 37 #include "cache.h"
 38 #include "interface.h"
 39 #include "util.h"
 40 #include "dns.h"
 41 #include "announce.h"
 42 #include "service.h"
 43 
 44 static struct uloop_fd ufd[] = {
 45         [SOCK_UC_IPV4] = { .fd = -1 },
 46         [SOCK_UC_IPV6] = { .fd = -1 },
 47         [SOCK_MC_IPV4] = { .fd = -1 },
 48         [SOCK_MC_IPV6] = { .fd = -1 },
 49 };
 50 
 51 static int
 52 interface_send_packet4(struct interface *iface, struct sockaddr_in *to, struct iovec *iov, int iov_len)
 53 {
 54         static size_t cmsg_data[( CMSG_SPACE(sizeof(struct in_pktinfo)) / sizeof(size_t)) + 1];
 55         static struct sockaddr_in a = {};
 56         static struct msghdr m = {
 57                 .msg_name = (struct sockaddr *) &a,
 58                 .msg_namelen = sizeof(a),
 59                 .msg_control = cmsg_data,
 60                 .msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo)),
 61         };
 62         struct in_pktinfo *pkti;
 63         struct cmsghdr *cmsg;
 64         int fd;
 65 
 66         a.sin_family = AF_INET;
 67         a.sin_port = htons(MCAST_PORT);
 68         m.msg_iov = iov;
 69         m.msg_iovlen = iov_len;
 70 
 71         memset(cmsg_data, 0, sizeof(cmsg_data));
 72         cmsg = CMSG_FIRSTHDR(&m);
 73         cmsg->cmsg_len = m.msg_controllen;
 74         cmsg->cmsg_level = IPPROTO_IP;
 75         cmsg->cmsg_type = IP_PKTINFO;
 76 
 77         pkti = (struct in_pktinfo*) CMSG_DATA(cmsg);
 78         pkti->ipi_ifindex = iface->ifindex;
 79 
 80         fd = ufd[iface->type].fd;
 81         if (interface_multicast(iface)) {
 82                 a.sin_addr.s_addr = inet_addr(MCAST_ADDR);
 83                 if (to)
 84                         fprintf(stderr, "Ignoring IPv4 address for multicast interface\n");
 85         } else {
 86                 a.sin_addr.s_addr = to->sin_addr.s_addr;
 87         }
 88 
 89         return sendmsg(fd, &m, 0);
 90 }
 91 
 92 static int
 93 interface_send_packet6(struct interface *iface, struct sockaddr_in6 *to, struct iovec *iov, int iov_len)
 94 {
 95         static size_t cmsg_data[( CMSG_SPACE(sizeof(struct in6_pktinfo)) / sizeof(size_t)) + 1];
 96         static struct sockaddr_in6 a = {};
 97         static struct msghdr m = {
 98                 .msg_name = (struct sockaddr *) &a,
 99                 .msg_namelen = sizeof(a),
100                 .msg_control = cmsg_data,
101                 .msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo)),
102         };
103         struct in6_pktinfo *pkti;
104         struct cmsghdr *cmsg;
105         int fd;
106 
107         a.sin6_family = AF_INET6;
108         a.sin6_port = htons(MCAST_PORT);
109         a.sin6_scope_id = iface->ifindex;
110         m.msg_iov = iov;
111         m.msg_iovlen = iov_len;
112 
113         memset(cmsg_data, 0, sizeof(cmsg_data));
114         cmsg = CMSG_FIRSTHDR(&m);
115         cmsg->cmsg_len = m.msg_controllen;
116         cmsg->cmsg_level = IPPROTO_IPV6;
117         cmsg->cmsg_type = IPV6_PKTINFO;
118 
119         pkti = (struct in6_pktinfo*) CMSG_DATA(cmsg);
120         pkti->ipi6_ifindex = iface->ifindex;
121 
122         fd = ufd[iface->type].fd;
123         if (interface_multicast(iface)) {
124                 inet_pton(AF_INET6, MCAST_ADDR6, &a.sin6_addr);
125                 if (to)
126                         fprintf(stderr, "Ignoring IPv6 address for multicast interface\n");
127         } else {
128                 a.sin6_addr = to->sin6_addr;
129         }
130 
131         return sendmsg(fd, &m, 0);
132 }
133 
134 int
135 interface_send_packet(struct interface *iface, struct sockaddr *to, struct iovec *iov, int iov_len)
136 {
137         if (!interface_multicast(iface) && !to) {
138                 fprintf(stderr, "No IP address specified for unicast interface\n");
139                 errno = EINVAL;
140                 return -1;
141         }
142 
143         if (debug > 1) {
144                 fprintf(stderr, "TX ipv%d: %s\n", interface_ipv6(iface) ? 6 : 4, iface->name);
145                 fprintf(stderr, "  multicast: %d\n", interface_multicast(iface));
146         }
147 
148         if (interface_ipv6(iface))
149                 return interface_send_packet6(iface, (struct sockaddr_in6 *)to, iov, iov_len);
150 
151         return interface_send_packet4(iface, (struct sockaddr_in *)to, iov, iov_len);
152 }
153 
154 static struct interface *interface_lookup(unsigned int ifindex, enum umdns_socket_type type)
155 {
156         struct interface *iface;
157 
158         vlist_for_each_element(&interfaces, iface, node)
159                 if (iface->ifindex == ifindex && iface->type == type)
160                         return iface;
161 
162         return NULL;
163 }
164 
165 static void interface_free(struct interface *iface)
166 {
167         cache_cleanup(iface);
168         announce_free(iface);
169         free(iface->addrs.v4);
170         free(iface);
171 }
172 
173 static int
174 interface_valid_src(void *ip1, void *mask, void *ip2, int len)
175 {
176         uint8_t *i1 = ip1;
177         uint8_t *i2 = ip2;
178         uint8_t *m = mask;
179         int i;
180 
181         if (cfg_no_subnet)
182                 return 0;
183 
184         for (i = 0; i < len; i++, i1++, i2++, m++) {
185                 if ((*i1 & *m) != (*i2 & *m))
186                         return -1;
187         }
188 
189         return 0;
190 }
191 
192 static void
193 read_socket4(struct uloop_fd *u, unsigned int events)
194 {
195         enum umdns_socket_type type = (enum umdns_socket_type)(u - ufd);
196         struct interface *iface;
197         static uint8_t buffer[8 * 1024];
198         struct iovec iov[1];
199         char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(int)) + 1];
200         struct cmsghdr *cmsgptr;
201         struct msghdr msg;
202         socklen_t len;
203         struct sockaddr_in from;
204         int flags = 0;
205         uint8_t ttl = 0;
206         struct in_pktinfo *inp = NULL;
207         bool valid_src = false;
208 
209         if (u->eof) {
210                 uloop_end();
211                 return;
212         }
213 
214         iov[0].iov_base = buffer;
215         iov[0].iov_len = sizeof(buffer);
216 
217         memset(&msg, 0, sizeof(msg));
218         msg.msg_name = (struct sockaddr *) &from;
219         msg.msg_namelen = sizeof(struct sockaddr_in);
220         msg.msg_iov = iov;
221         msg.msg_iovlen = 1;
222         msg.msg_control = &cmsg;
223         msg.msg_controllen = sizeof(cmsg);
224 
225         len = recvmsg(u->fd, &msg, flags);
226         if (len == -1) {
227                 perror("read failed");
228                 return;
229         }
230         for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
231                 void *c = CMSG_DATA(cmsgptr);
232 
233                 switch (cmsgptr->cmsg_type) {
234                 case IP_PKTINFO:
235                         inp = ((struct in_pktinfo *) c);
236                         break;
237 
238                 case IP_TTL:
239                         ttl = (uint8_t) *((int *) c);
240                         break;
241 
242                 default:
243                         fprintf(stderr, "unknown cmsg %x\n", cmsgptr->cmsg_type);
244                         return;
245                 }
246         }
247 
248         if (!inp)
249                 return;
250 
251         iface = interface_lookup(inp->ipi_ifindex, type);
252         if (!iface)
253                 return;
254 
255         if (debug > 1) {
256                 char buf[256];
257 
258                 fprintf(stderr, "RX ipv4: %s\n", iface->name);
259                 fprintf(stderr, "  multicast: %d\n", interface_multicast(iface));
260                 inet_ntop(AF_INET, &from.sin_addr, buf, 256);
261                 fprintf(stderr, "  src %s:%d\n", buf, ntohs(from.sin_port));
262                 inet_ntop(AF_INET, &inp->ipi_spec_dst, buf, 256);
263                 fprintf(stderr, "  dst %s\n", buf);
264                 inet_ntop(AF_INET, &inp->ipi_addr, buf, 256);
265                 fprintf(stderr, "  real %s\n", buf);
266                 fprintf(stderr, "  ttl %u\n", ttl);
267         }
268 
269         for (size_t i = 0; i < iface->addrs.n_addr; i++) {
270                 if (!interface_valid_src((void *)&iface->addrs.v4[i].addr,
271                                          (void *)&iface->addrs.v4[i].mask,
272                                          (void *) &from.sin_addr, 4)) {
273                         valid_src = true;
274                         break;
275                 }
276         }
277 
278         if (!valid_src)
279                 return;
280 
281         dns_handle_packet(iface, (struct sockaddr *) &from, ntohs(from.sin_port), buffer, len);
282 }
283 
284 static void
285 read_socket6(struct uloop_fd *u, unsigned int events)
286 {
287         enum umdns_socket_type type = (enum umdns_socket_type)(u - ufd);
288         struct interface *iface;
289         static uint8_t buffer[8 * 1024];
290         struct iovec iov[1];
291         char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + 1];
292         struct cmsghdr *cmsgptr;
293         struct msghdr msg;
294         socklen_t len;
295         struct sockaddr_in6 from;
296         int flags = 0;
297         int ttl = 0;
298         struct in6_pktinfo *inp = NULL;
299         bool valid_src = false;
300 
301         if (u->eof) {
302                 uloop_end();
303                 return;
304         }
305 
306         iov[0].iov_base = buffer;
307         iov[0].iov_len = sizeof(buffer);
308 
309         memset(&msg, 0, sizeof(msg));
310         msg.msg_name = (struct sockaddr *) &from;
311         msg.msg_namelen = sizeof(struct sockaddr_in6);
312         msg.msg_iov = iov;
313         msg.msg_iovlen = 1;
314         msg.msg_control = &cmsg6;
315         msg.msg_controllen = sizeof(cmsg6);
316 
317         len = recvmsg(u->fd, &msg, flags);
318         if (len == -1) {
319                 perror("read failed");
320                 return;
321         }
322         for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
323                 void *c = CMSG_DATA(cmsgptr);
324 
325                 switch (cmsgptr->cmsg_type) {
326                 case IPV6_PKTINFO:
327                         inp = ((struct in6_pktinfo *) c);
328                         break;
329 
330                 case IPV6_HOPLIMIT:
331                         ttl = (uint8_t) *((int *) c);
332                         break;
333 
334                 default:
335                         fprintf(stderr, "unknown cmsg %x\n", cmsgptr->cmsg_type);
336                         return;
337                 }
338         }
339 
340         if (!inp)
341                 return;
342 
343         iface = interface_lookup(inp->ipi6_ifindex, type);
344         if (!iface)
345                 return;
346 
347         if (debug > 1) {
348                 char buf[256];
349 
350                 fprintf(stderr, "RX ipv6: %s\n", iface->name);
351                 fprintf(stderr, "  multicast: %d\n", interface_multicast(iface));
352                 inet_ntop(AF_INET6, &from.sin6_addr, buf, 256);
353                 fprintf(stderr, "  src %s:%d\n", buf, ntohs(from.sin6_port));
354                 inet_ntop(AF_INET6, &inp->ipi6_addr, buf, 256);
355                 fprintf(stderr, "  dst %s\n", buf);
356                 fprintf(stderr, "  ttl %u\n", ttl);
357         }
358 
359         for (size_t i = 0; i < iface->addrs.n_addr; i++) {
360                 if (!interface_valid_src((void *)&iface->addrs.v6[i].addr,
361                                          (void *)&iface->addrs.v6[i].mask,
362                                          (void *)&from.sin6_addr, 6)) {
363                         valid_src = true;
364                         break;
365                 }
366         }
367 
368         if (!valid_src)
369                 return;
370 
371         dns_handle_packet(iface, (struct sockaddr *) &from, ntohs(from.sin6_port), buffer, len);
372 }
373 
374 static int
375 interface_mcast_setup4(struct interface *iface)
376 {
377         struct ip_mreqn mreq;
378         struct sockaddr_in sa = {};
379         int fd = ufd[SOCK_MC_IPV4].fd;
380 
381         sa.sin_family = AF_INET;
382         sa.sin_port = htons(MCAST_PORT);
383         inet_pton(AF_INET, MCAST_ADDR, &sa.sin_addr);
384 
385         memset(&mreq, 0, sizeof(mreq));
386         mreq.imr_multiaddr = sa.sin_addr;
387         mreq.imr_ifindex = iface->ifindex;
388         mreq.imr_address.s_addr = iface->addrs.v4[0].addr.s_addr;
389 
390         /* Some network drivers have issues with dropping membership of
391          * mcast groups when the iface is down, but don't allow rejoining
392          * when it comes back up. This is an ugly workaround
393          * -- this was copied from avahi --
394          */
395         setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
396         setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
397 
398         return 0;
399 }
400 
401 static int
402 interface_mcast_setup6(struct interface *iface)
403 {
404         struct ipv6_mreq mreq;
405         struct sockaddr_in6 sa = {};
406         int fd = ufd[SOCK_MC_IPV6].fd;
407 
408         sa.sin6_family = AF_INET6;
409         sa.sin6_port = htons(MCAST_PORT);
410         inet_pton(AF_INET6, MCAST_ADDR6, &sa.sin6_addr);
411 
412         memset(&mreq, 0, sizeof(mreq));
413         mreq.ipv6mr_multiaddr = sa.sin6_addr;
414         mreq.ipv6mr_interface = iface->ifindex;
415 
416         setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq));
417         setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
418 
419         return 0;
420 }
421 
422 static void interface_start(struct interface *iface)
423 {
424         if (iface->type & SOCKTYPE_BIT_UNICAST)
425                 return;
426 
427         if (iface->type & SOCKTYPE_BIT_IPV6)
428                 interface_mcast_setup6(iface);
429         else
430                 interface_mcast_setup4(iface);
431 
432         dns_send_question(iface, NULL, C_DNS_SD, TYPE_PTR, 0);
433         announce_init(iface);
434 }
435 
436 static bool
437 iface_equal(struct interface *if_old, struct interface *if_new)
438 {
439         size_t addr_size;
440 
441         if (if_old->ifindex != if_new->ifindex ||
442             if_old->addrs.n_addr != if_new->addrs.n_addr)
443                 return false;
444 
445         if (if_old->type & SOCKTYPE_BIT_IPV6)
446                 addr_size = sizeof(*if_old->addrs.v6);
447         else
448                 addr_size = sizeof(*if_old->addrs.v4);
449         addr_size *= if_old->addrs.n_addr;
450         if (memcmp(if_old->addrs.v4, if_new->addrs.v4, addr_size) != 0)
451                 return false;
452 
453         return true;
454 }
455 
456 static void
457 iface_update_cb(struct vlist_tree *tree, struct vlist_node *node_new,
458                 struct vlist_node *node_old)
459 {
460         struct interface *if_old = container_of_safe(node_old, struct interface, node);
461         struct interface *if_new = container_of_safe(node_new, struct interface, node);
462 
463         if (if_old && if_new) {
464                 if (!iface_equal(if_old, if_new))
465                         cache_cleanup(if_old);
466                 free(if_old->addrs.v4);
467                 if_old->addrs = if_new->addrs;
468                 if_old->ifindex = if_new->ifindex;
469                 free(if_new);
470                 return;
471         }
472 
473         if (if_old)
474                 interface_free(if_old);
475 
476         if (if_new)
477                 interface_start(if_new);
478 }
479 
480 static int interface_init_socket(enum umdns_socket_type type)
481 {
482         struct sockaddr_in6 local6 = {
483                 .sin6_family = AF_INET6
484         };
485         struct sockaddr_in local = {
486                 .sin_family = AF_INET
487         };
488         uint8_t ttl = 255;
489         int ittl = 255;
490         int yes = 1;
491         int no = 0;
492         int fd;
493         int af = (type & SOCKTYPE_BIT_IPV6) ? AF_INET6 : AF_INET;
494 
495         if (ufd[type].fd >= 0)
496                 return 0;
497 
498         ufd[type].fd = fd = socket(af, SOCK_DGRAM, 0);
499         if (fd < 0)
500                 return -1;
501 
502         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
503 #ifdef SO_REUSEPORT
504         setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
505 #endif
506 
507         switch (type) {
508         case SOCK_UC_IPV4:
509         case SOCK_UC_IPV6:
510                 break;
511         case SOCK_MC_IPV4:
512                 setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
513                 setsockopt(fd, IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl));
514                 setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, sizeof(no));
515                 local.sin_port = htons(MCAST_PORT);
516                 break;
517         case SOCK_MC_IPV6:
518                 setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
519                 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
520                 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes));
521                 setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no, sizeof(no));
522                 local6.sin6_port = htons(MCAST_PORT);
523                 break;
524         }
525 
526         if (type & SOCKTYPE_BIT_IPV6) {
527                 ufd[type].cb = read_socket6;
528                 if (bind(fd, (struct sockaddr *)&local6, sizeof(local6)) < 0)
529                         goto error;
530 
531                 setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &yes, sizeof(yes));
532                 setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &yes, sizeof(yes));
533         } else {
534                 ufd[type].cb = read_socket4;
535                 if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0)
536                         goto error;
537 
538                 setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes));
539                 setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes));
540         }
541 
542         uloop_fd_add(&ufd[type], ULOOP_READ);
543 
544         return 0;
545 
546 error:
547         close(ufd[type].fd);
548         return -1;
549 }
550 
551 static void
552 __interface_add(const char *name, enum umdns_socket_type type,
553                                 struct interface_addr_list *list)
554 {
555         struct interface *iface;
556         unsigned int ifindex;
557         char *id_buf;
558 
559         if (interface_init_socket(type))
560                 goto error;
561 
562         ifindex = if_nametoindex(name);
563         if (!ifindex)
564                 goto error;
565 
566         iface = calloc_a(sizeof(*iface),
567                 &id_buf, strlen(name) + 3);
568 
569         sprintf(id_buf, "%d_%s", type, name);
570         iface->name = id_buf + 2;
571         iface->ifindex = ifindex;
572         iface->type = type;
573         iface->addrs = *list;
574 
575         vlist_add(&interfaces, &iface->node, id_buf);
576         return;
577 
578 error:
579         free(list->v4);
580 }
581 
582 int interface_add(const char *name)
583 {
584         struct ifaddrs *ifap, *ifa;
585         struct interface_addr_list addr4 = {}, addr6 = {};
586 
587         getifaddrs(&ifap);
588 
589         for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
590                 if (strcmp(ifa->ifa_name, name))
591                         continue;
592                 if (ifa->ifa_addr->sa_family == AF_INET) {
593                         struct sockaddr_in *sin;
594 
595                         if (cfg_proto && (cfg_proto != 4))
596                                 continue;
597 
598                         addr4.v4 = realloc(addr4.v4, (addr4.n_addr + 1) * sizeof(*addr4.v4));
599                         sin = (struct sockaddr_in *) ifa->ifa_addr;
600                         addr4.v4[addr4.n_addr].addr = sin->sin_addr;
601                         sin = (struct sockaddr_in *) ifa->ifa_netmask;
602                         addr4.v4[addr4.n_addr++].mask = sin->sin_addr;
603                 }
604 
605                 if (ifa->ifa_addr->sa_family == AF_INET6) {
606                         uint8_t ll_prefix[] = {0xfe, 0x80 };
607                         struct sockaddr_in6 *sin6;
608 
609                         if (cfg_proto && (cfg_proto != 6))
610                                 continue;
611 
612                         sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
613                         if (memcmp(&sin6->sin6_addr, &ll_prefix, 2))
614                                 continue;
615 
616                         addr6.v6 = realloc(addr6.v6, (addr6.n_addr + 1) * sizeof(*addr6.v6));
617                         sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
618                         addr6.v6[addr6.n_addr].addr = sin6->sin6_addr;
619                         sin6 = (struct sockaddr_in6 *) ifa->ifa_netmask;
620                         addr6.v6[addr6.n_addr++].mask = sin6->sin6_addr;
621                 }
622         }
623 
624         freeifaddrs(ifap);
625 
626         if (addr4.n_addr) {
627                 size_t addr_size = addr4.n_addr * sizeof(*addr4.v4);
628                 void *addr_dup = malloc(addr_size);
629 
630                 memcpy(addr_dup, addr4.v4, addr_size);
631                 __interface_add(name, SOCK_UC_IPV4, &addr4);
632                 addr4.v4 = addr_dup;
633                 __interface_add(name, SOCK_MC_IPV4, &addr4);
634         }
635 
636         if (addr6.n_addr) {
637                 size_t addr_size = addr6.n_addr * sizeof(*addr6.v6);
638                 void *addr_dup = malloc(addr_size);
639 
640                 memcpy(addr_dup, addr6.v6, addr_size);
641                 __interface_add(name, SOCK_UC_IPV6, &addr6);
642                 addr6.v6 = addr_dup;
643                 __interface_add(name, SOCK_MC_IPV6, &addr6);
644         }
645 
646         return !addr4.n_addr && !addr6.n_addr;
647 }
648 
649 void interface_shutdown(void)
650 {
651         struct interface *iface;
652 
653         vlist_for_each_element(&interfaces, iface, node)
654                 if (interface_multicast(iface)) {
655                         dns_reply_a(iface, NULL, 0, NULL);
656                         dns_reply_a_additional(iface, NULL, 0);
657                         service_announce_services(iface, NULL, 0);
658                 }
659 
660         for (size_t i = 0; i < ARRAY_SIZE(ufd); i++) {
661                 uloop_fd_delete(&ufd[i]);
662                 close(ufd[i].fd);
663                 ufd[i].fd = -1;
664         }
665 }
666 
667 struct interface *interface_get(const char *name, enum umdns_socket_type type)
668 {
669         char id_buf[32];
670         snprintf(id_buf, sizeof(id_buf), "%d_%s", type, name);
671         struct interface *iface = vlist_find(&interfaces, id_buf, iface, node);
672         return iface;
673 }
674 
675 VLIST_TREE(interfaces, avl_strcmp, iface_update_cb, true, false);
676 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt