1 #include <sys/cdefs.h>
2 __RCSID("$NetBSD: if.c,v 1.16 2015/09/04 12:25:01 roy Exp $");
3
4 /*
5 * dhcpcd - DHCP client daemon
6 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
7 * All rights reserved
8
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35
36 #include <net/if.h>
37 #include <net/if_arp.h>
38 #include <netinet/in.h>
39 #ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
40 # include <net/if_var.h>
41 #endif
42 #ifdef AF_LINK
43 # include <net/if_dl.h>
44 # include <net/if_types.h>
45 # include <netinet/in_var.h>
46 #endif
47 #ifdef AF_PACKET
48 # include <netpacket/packet.h>
49 #endif
50 #ifdef SIOCGIFMEDIA
51 # include <net/if_media.h>
52 #endif
53 #include <net/route.h>
54
55 #include <ctype.h>
56 #include <errno.h>
57 #include <ifaddrs.h>
58 #include <fnmatch.h>
59 #include <stddef.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <fcntl.h>
65
66 #include "config.h"
67 #include "common.h"
68 #include "dev.h"
69 #include "dhcp.h"
70 #include "dhcp6.h"
71 #include "if.h"
72 #include "if-options.h"
73 #include "ipv4.h"
74 #include "ipv4ll.h"
75 #include "ipv6nd.h"
76
77 void
if_free(struct interface * ifp)78 if_free(struct interface *ifp)
79 {
80
81 if (ifp == NULL)
82 return;
83 ipv4ll_free(ifp);
84 dhcp_free(ifp);
85 ipv4_free(ifp);
86 dhcp6_free(ifp);
87 ipv6nd_free(ifp);
88 ipv6_free(ifp);
89 free_options(ifp->options);
90 free(ifp);
91 }
92
93 int
if_opensockets(struct dhcpcd_ctx * ctx)94 if_opensockets(struct dhcpcd_ctx *ctx)
95 {
96
97 if ((ctx->link_fd = if_openlinksocket()) == -1)
98 return -1;
99
100 ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC);
101 if (ctx->pf_inet_fd == -1)
102 return -1;
103
104 #if defined(INET6) && defined(BSD)
105 ctx->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC);
106 if (ctx->pf_inet6_fd == -1)
107 return -1;
108 #endif
109
110 #ifdef IFLR_ACTIVE
111 ctx->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0, O_CLOEXEC);
112 if (ctx->pf_link_fd == -1)
113 return -1;
114 #endif
115
116 return 0;
117 }
118
119 int
if_carrier(struct interface * ifp)120 if_carrier(struct interface *ifp)
121 {
122 int r;
123 struct ifreq ifr;
124 #ifdef SIOCGIFMEDIA
125 struct ifmediareq ifmr;
126 #endif
127
128 memset(&ifr, 0, sizeof(ifr));
129 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
130 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
131 return LINK_UNKNOWN;
132 ifp->flags = (unsigned int)ifr.ifr_flags;
133
134 #ifdef SIOCGIFMEDIA
135 memset(&ifmr, 0, sizeof(ifmr));
136 strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
137 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) != -1 &&
138 ifmr.ifm_status & IFM_AVALID)
139 r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
140 else
141 r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN;
142 #else
143 r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
144 #endif
145 return r;
146 }
147
148 int
if_setflag(struct interface * ifp,short flag)149 if_setflag(struct interface *ifp, short flag)
150 {
151 struct ifreq ifr;
152 int r;
153
154 memset(&ifr, 0, sizeof(ifr));
155 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
156 r = -1;
157 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == 0) {
158 if (flag == 0 || (ifr.ifr_flags & flag) == flag)
159 r = 0;
160 else {
161 ifr.ifr_flags |= flag;
162 if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0)
163 r = 0;
164 }
165 ifp->flags = (unsigned int)ifr.ifr_flags;
166 }
167 return r;
168 }
169
170 static int
if_hasconf(struct dhcpcd_ctx * ctx,const char * ifname)171 if_hasconf(struct dhcpcd_ctx *ctx, const char *ifname)
172 {
173 int i;
174
175 for (i = 0; i < ctx->ifcc; i++) {
176 if (strcmp(ctx->ifcv[i], ifname) == 0)
177 return 1;
178 }
179 return 0;
180 }
181
if_learnaddrs1(struct dhcpcd_ctx * ctx,struct if_head * ifs,struct ifaddrs * ifaddrs)182 static void if_learnaddrs1(struct dhcpcd_ctx *ctx, struct if_head *ifs,
183 struct ifaddrs *ifaddrs)
184 {
185 struct ifaddrs *ifa;
186 struct interface *ifp;
187 #ifdef INET
188 const struct sockaddr_in *addr, *net, *dst;
189 #endif
190 #ifdef INET6
191 struct sockaddr_in6 *sin6, *net6;
192 #endif
193 int ifa_flags;
194
195
196 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
197 if (ifa->ifa_addr == NULL)
198 continue;
199 if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL)
200 continue;
201 switch(ifa->ifa_addr->sa_family) {
202 #ifdef INET
203 case AF_INET:
204 addr = (const struct sockaddr_in *)
205 (void *)ifa->ifa_addr;
206 net = (const struct sockaddr_in *)
207 (void *)ifa->ifa_netmask;
208 if (ifa->ifa_flags & IFF_POINTOPOINT)
209 dst = (const struct sockaddr_in *)
210 (void *)ifa->ifa_dstaddr;
211 else
212 dst = NULL;
213 ifa_flags = if_addrflags(&addr->sin_addr, ifp);
214 ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
215 &addr->sin_addr,
216 &net->sin_addr,
217 dst ? &dst->sin_addr : NULL, ifa_flags);
218 break;
219 #endif
220 #ifdef INET6
221 case AF_INET6:
222 sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
223 net6 = (struct sockaddr_in6 *)(void *)ifa->ifa_netmask;
224 #ifdef __KAME__
225 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
226 /* Remove the scope from the address */
227 sin6->sin6_addr.s6_addr[2] =
228 sin6->sin6_addr.s6_addr[3] = '\0';
229 #endif
230 ifa_flags = if_addrflags6(&sin6->sin6_addr, ifp);
231 if (ifa_flags != -1)
232 ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
233 ifa->ifa_name,
234 &sin6->sin6_addr,
235 ipv6_prefixlen(&net6->sin6_addr),
236 ifa_flags);
237 break;
238 #endif
239 }
240 }
241 }
242
243 struct if_head *
if_discover(struct dhcpcd_ctx * ctx,int argc,char * const * argv)244 if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
245 {
246 struct ifaddrs *ifaddrs, *ifa;
247 char *p;
248 int i;
249 struct if_head *ifs;
250 struct interface *ifp;
251 #ifdef __linux__
252 char ifn[IF_NAMESIZE];
253 #endif
254 #ifdef AF_LINK
255 const struct sockaddr_dl *sdl;
256 #ifdef SIOCGIFPRIORITY
257 struct ifreq ifr;
258 #endif
259 #ifdef IFLR_ACTIVE
260 struct if_laddrreq iflr;
261 #endif
262
263 #ifdef IFLR_ACTIVE
264 memset(&iflr, 0, sizeof(iflr));
265 #endif
266 #elif AF_PACKET
267 const struct sockaddr_ll *sll;
268 #endif
269
270 if (getifaddrs(&ifaddrs) == -1)
271 return NULL;
272 ifs = malloc(sizeof(*ifs));
273 if (ifs == NULL)
274 return NULL;
275 TAILQ_INIT(ifs);
276
277 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
278 if (ifa->ifa_addr != NULL) {
279 #ifdef AF_LINK
280 if (ifa->ifa_addr->sa_family != AF_LINK)
281 continue;
282 #elif AF_PACKET
283 if (ifa->ifa_addr->sa_family != AF_PACKET)
284 continue;
285 #endif
286 }
287
288 /* It's possible for an interface to have >1 AF_LINK.
289 * For our purposes, we use the first one. */
290 TAILQ_FOREACH(ifp, ifs, next) {
291 if (strcmp(ifp->name, ifa->ifa_name) == 0)
292 break;
293 }
294 if (ifp)
295 continue;
296
297 if (argc > 0) {
298 for (i = 0; i < argc; i++) {
299 #ifdef __linux__
300 /* Check the real interface name */
301 strlcpy(ifn, argv[i], sizeof(ifn));
302 p = strchr(ifn, ':');
303 if (p)
304 *p = '\0';
305 if (strcmp(ifn, ifa->ifa_name) == 0)
306 break;
307 #else
308 if (strcmp(argv[i], ifa->ifa_name) == 0)
309 break;
310 #endif
311 }
312 if (i == argc)
313 continue;
314 p = argv[i];
315 } else {
316 p = ifa->ifa_name;
317 #ifdef __linux__
318 strlcpy(ifn, ifa->ifa_name, sizeof(ifn));
319 #endif
320 /* -1 means we're discovering against a specific
321 * interface, but we still need the below rules
322 * to apply. */
323 if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0)
324 continue;
325 }
326 for (i = 0; i < ctx->ifdc; i++)
327 if (!fnmatch(ctx->ifdv[i], p, 0))
328 break;
329 if (i < ctx->ifdc)
330 continue;
331 for (i = 0; i < ctx->ifac; i++)
332 if (!fnmatch(ctx->ifav[i], p, 0))
333 break;
334 if (ctx->ifac && i == ctx->ifac)
335 continue;
336
337 /* Ensure that the interface name has settled */
338 if (!dev_initialized(ctx, p))
339 continue;
340
341 /* Don't allow loopback or pointopoint unless explicit */
342 if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
343 if ((argc == 0 || argc == -1) &&
344 ctx->ifac == 0 && !if_hasconf(ctx, p))
345 continue;
346 }
347
348 if (if_vimaster(ctx, p) == 1) {
349 logger(ctx, argc ? LOG_ERR : LOG_DEBUG,
350 "%s: is a Virtual Interface Master, skipping", p);
351 continue;
352 }
353
354 ifp = calloc(1, sizeof(*ifp));
355 if (ifp == NULL) {
356 logger(ctx, LOG_ERR, "%s: %m", __func__);
357 break;
358 }
359 ifp->ctx = ctx;
360 #ifdef __linux__
361 strlcpy(ifp->name, ifn, sizeof(ifp->name));
362 strlcpy(ifp->alias, p, sizeof(ifp->alias));
363 #else
364 strlcpy(ifp->name, p, sizeof(ifp->name));
365 #endif
366 ifp->flags = ifa->ifa_flags;
367 ifp->carrier = if_carrier(ifp);
368
369 if (ifa->ifa_addr != NULL) {
370 #ifdef AF_LINK
371 sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr;
372
373 #ifdef IFLR_ACTIVE
374 /* We need to check for active address */
375 strlcpy(iflr.iflr_name, ifp->name,
376 sizeof(iflr.iflr_name));
377 memcpy(&iflr.addr, ifa->ifa_addr,
378 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
379 iflr.flags = IFLR_PREFIX;
380 iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY;
381 if (ioctl(ctx->pf_link_fd, SIOCGLIFADDR, &iflr) == -1 ||
382 !(iflr.flags & IFLR_ACTIVE))
383 {
384 if_free(ifp);
385 continue;
386 }
387 #endif
388
389 ifp->index = sdl->sdl_index;
390 switch(sdl->sdl_type) {
391 #ifdef IFT_BRIDGE
392 case IFT_BRIDGE: /* FALLTHROUGH */
393 #endif
394 #ifdef IFT_PPP
395 case IFT_PPP: /* FALLTHROUGH */
396 #endif
397 #ifdef IFT_PROPVIRTUAL
398 case IFT_PROPVIRTUAL: /* FALLTHROUGH */
399 #endif
400 #if defined(IFT_BRIDGE) || defined(IFT_PPP) || defined(IFT_PROPVIRTUAL)
401 /* Don't allow unless explicit */
402 if ((argc == 0 || argc == -1) &&
403 ctx->ifac == 0 &&
404 !if_hasconf(ctx, ifp->name))
405 {
406 logger(ifp->ctx, LOG_DEBUG,
407 "%s: ignoring due to"
408 " interface type and"
409 " no config",
410 ifp->name);
411 if_free(ifp);
412 continue;
413 }
414 /* FALLTHROUGH */
415 #endif
416 #ifdef IFT_L2VLAN
417 case IFT_L2VLAN: /* FALLTHROUGH */
418 #endif
419 #ifdef IFT_L3IPVLAN
420 case IFT_L3IPVLAN: /* FALLTHROUGH */
421 #endif
422 case IFT_ETHER:
423 ifp->family = ARPHRD_ETHER;
424 break;
425 #ifdef IFT_IEEE1394
426 case IFT_IEEE1394:
427 ifp->family = ARPHRD_IEEE1394;
428 break;
429 #endif
430 #ifdef IFT_INFINIBAND
431 case IFT_INFINIBAND:
432 ifp->family = ARPHRD_INFINIBAND;
433 break;
434 #endif
435 default:
436 /* Don't allow unless explicit */
437 if ((argc == 0 || argc == -1) &&
438 ctx->ifac == 0 &&
439 !if_hasconf(ctx, ifp->name))
440 {
441 if_free(ifp);
442 continue;
443 }
444 logger(ifp->ctx, LOG_WARNING,
445 "%s: unsupported interface type %.2x",
446 ifp->name, sdl->sdl_type);
447 /* Pretend it's ethernet */
448 ifp->family = ARPHRD_ETHER;
449 break;
450 }
451 ifp->hwlen = sdl->sdl_alen;
452 #ifndef CLLADDR
453 # define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
454 #endif
455 memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
456 #elif AF_PACKET
457 sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr;
458 ifp->index = (unsigned int)sll->sll_ifindex;
459 ifp->family = sll->sll_hatype;
460 ifp->hwlen = sll->sll_halen;
461 if (ifp->hwlen != 0)
462 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
463 #endif
464 }
465 #ifdef __linux__
466 /* PPP addresses on Linux don't have hardware addresses */
467 else
468 ifp->index = if_nametoindex(ifp->name);
469 #endif
470
471 /* We only work on ethernet by default */
472 if (ifp->family != ARPHRD_ETHER) {
473 if ((argc == 0 || argc == -1) &&
474 ctx->ifac == 0 && !if_hasconf(ctx, ifp->name))
475 {
476 if_free(ifp);
477 continue;
478 }
479 switch (ifp->family) {
480 case ARPHRD_IEEE1394:
481 case ARPHRD_INFINIBAND:
482 #ifdef ARPHRD_LOOPBACK
483 case ARPHRD_LOOPBACK:
484 #endif
485 #ifdef ARPHRD_PPP
486 case ARPHRD_PPP:
487 #endif
488 /* We don't warn for supported families */
489 break;
490
491 /* IFT already checked */
492 #ifndef AF_LINK
493 default:
494 logger(ifp->ctx, LOG_WARNING,
495 "%s: unsupported interface family %.2x",
496 ifp->name, ifp->family);
497 break;
498 #endif
499 }
500 }
501
502 if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) {
503 /* Handle any platform init for the interface */
504 if (if_init(ifp) == -1) {
505 logger(ifp->ctx, LOG_ERR, "%s: if_init: %m", p);
506 if_free(ifp);
507 continue;
508 }
509
510 /* Ensure that the MTU is big enough for DHCP */
511 if (if_getmtu(ifp) < MTU_MIN &&
512 if_setmtu(ifp, MTU_MIN) == -1)
513 {
514 logger(ifp->ctx, LOG_ERR,
515 "%s: if_setmtu: %m", p);
516 if_free(ifp);
517 continue;
518 }
519 }
520
521 #ifdef SIOCGIFPRIORITY
522 /* Respect the interface priority */
523 memset(&ifr, 0, sizeof(ifr));
524 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
525 if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0)
526 ifp->metric = ifr.ifr_metric;
527 #else
528 /* We reserve the 100 range for virtual interfaces, if and when
529 * we can work them out. */
530 ifp->metric = 200 + ifp->index;
531 if (if_getssid(ifp) != -1) {
532 ifp->wireless = 1;
533 ifp->metric += 100;
534 }
535 #endif
536
537 TAILQ_INSERT_TAIL(ifs, ifp, next);
538 }
539
540 if_learnaddrs1(ctx, ifs, ifaddrs);
541 freeifaddrs(ifaddrs);
542
543 return ifs;
544 }
545
546 static struct interface *
if_findindexname(struct if_head * ifaces,unsigned int idx,const char * name)547 if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name)
548 {
549
550 if (ifaces != NULL) {
551 struct interface *ifp;
552
553 TAILQ_FOREACH(ifp, ifaces, next) {
554 if ((name && strcmp(ifp->name, name) == 0) ||
555 #ifdef __linux__
556 (name && strcmp(ifp->alias, name) == 0) ||
557 #endif
558 (!name && ifp->index == idx))
559 return ifp;
560 }
561 }
562
563 errno = ESRCH;
564 return NULL;
565 }
566
567 struct interface *
if_find(struct if_head * ifaces,const char * name)568 if_find(struct if_head *ifaces, const char *name)
569 {
570
571 return if_findindexname(ifaces, 0, name);
572 }
573
574 struct interface *
if_findindex(struct if_head * ifaces,unsigned int idx)575 if_findindex(struct if_head *ifaces, unsigned int idx)
576 {
577
578 return if_findindexname(ifaces, idx, NULL);
579 }
580
581 int
if_domtu(const struct interface * ifp,short int mtu)582 if_domtu(const struct interface *ifp, short int mtu)
583 {
584 int r;
585 struct ifreq ifr;
586
587 memset(&ifr, 0, sizeof(ifr));
588 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
589 ifr.ifr_mtu = mtu;
590 r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
591 if (r == -1)
592 return -1;
593 return ifr.ifr_mtu;
594 }
595
596 /* Interface comparer for working out ordering. */
597 static int
if_cmp(const struct interface * si,const struct interface * ti)598 if_cmp(const struct interface *si, const struct interface *ti)
599 {
600 #ifdef INET
601 int r;
602 #endif
603
604 /* Check carrier status first */
605 if (si->carrier > ti->carrier)
606 return -1;
607 if (si->carrier < ti->carrier)
608 return 1;
609
610 if (D_STATE_RUNNING(si) && !D_STATE_RUNNING(ti))
611 return -1;
612 if (!D_STATE_RUNNING(si) && D_STATE_RUNNING(ti))
613 return 1;
614 if (RS_STATE_RUNNING(si) && !RS_STATE_RUNNING(ti))
615 return -1;
616 if (!RS_STATE_RUNNING(si) && RS_STATE_RUNNING(ti))
617 return 1;
618 if (D6_STATE_RUNNING(si) && !D6_STATE_RUNNING(ti))
619 return -1;
620 if (!D6_STATE_RUNNING(si) && D6_STATE_RUNNING(ti))
621 return 1;
622
623 #ifdef INET
624 /* Special attention needed here due to states and IPv4LL. */
625 if ((r = ipv4_ifcmp(si, ti)) != 0)
626 return r;
627 #endif
628
629 /* Finally, metric */
630 if (si->metric < ti->metric)
631 return -1;
632 if (si->metric > ti->metric)
633 return 1;
634 return 0;
635 }
636
637 /* Sort the interfaces into a preferred order - best first, worst last. */
638 void
if_sortinterfaces(struct dhcpcd_ctx * ctx)639 if_sortinterfaces(struct dhcpcd_ctx *ctx)
640 {
641 struct if_head sorted;
642 struct interface *ifp, *ift;
643
644 if (ctx->ifaces == NULL ||
645 (ifp = TAILQ_FIRST(ctx->ifaces)) == NULL ||
646 TAILQ_NEXT(ifp, next) == NULL)
647 return;
648
649 TAILQ_INIT(&sorted);
650 TAILQ_REMOVE(ctx->ifaces, ifp, next);
651 TAILQ_INSERT_HEAD(&sorted, ifp, next);
652 while ((ifp = TAILQ_FIRST(ctx->ifaces))) {
653 TAILQ_REMOVE(ctx->ifaces, ifp, next);
654 TAILQ_FOREACH(ift, &sorted, next) {
655 if (if_cmp(ifp, ift) == -1) {
656 TAILQ_INSERT_BEFORE(ift, ifp, next);
657 break;
658 }
659 }
660 if (ift == NULL)
661 TAILQ_INSERT_TAIL(&sorted, ifp, next);
662 }
663 TAILQ_CONCAT(ctx->ifaces, &sorted, next);
664 }
665
666 int
xsocket(int domain,int type,int protocol,int flags)667 xsocket(int domain, int type, int protocol, int flags)
668 {
669 #ifdef SOCK_CLOEXEC
670 if (flags & O_CLOEXEC)
671 type |= SOCK_CLOEXEC;
672 if (flags & O_NONBLOCK)
673 type |= SOCK_NONBLOCK;
674
675 return socket(domain, type, protocol);
676 #else
677 int s, xflags;
678
679 if ((s = socket(domain, type, protocol)) == -1)
680 return -1;
681 if ((flags & O_CLOEXEC) && (xflags = fcntl(s, F_GETFD, 0)) == -1 ||
682 fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1)
683 goto out;
684 if ((flags & O_NONBLOCK) && (xflags = fcntl(s, F_GETFL, 0)) == -1 ||
685 fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)
686 goto out;
687 return s;
688 out:
689 close(s);
690 return -1;
691 #endif
692 }
693