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