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