if.c revision 24aa62eefd9284fb94820093f6088607d42c4249
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