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