10d34b412Sroy /* SPDX-License-Identifier: BSD-2-Clause */ 24e3ebfccSroy /* 34e3ebfccSroy * dhcpcd - DHCP client daemon 4*3ee74c9aSroy * Copyright (c) 2006-2023 Roy Marples <roy@marples.name> 54e3ebfccSroy * All rights reserved 64e3ebfccSroy 74e3ebfccSroy * Redistribution and use in source and binary forms, with or without 84e3ebfccSroy * modification, are permitted provided that the following conditions 94e3ebfccSroy * are met: 104e3ebfccSroy * 1. Redistributions of source code must retain the above copyright 114e3ebfccSroy * notice, this list of conditions and the following disclaimer. 124e3ebfccSroy * 2. Redistributions in binary form must reproduce the above copyright 134e3ebfccSroy * notice, this list of conditions and the following disclaimer in the 144e3ebfccSroy * documentation and/or other materials provided with the distribution. 154e3ebfccSroy * 164e3ebfccSroy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 174e3ebfccSroy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 184e3ebfccSroy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 194e3ebfccSroy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 204e3ebfccSroy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 214e3ebfccSroy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 224e3ebfccSroy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 234e3ebfccSroy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 244e3ebfccSroy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 254e3ebfccSroy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 264e3ebfccSroy * SUCH DAMAGE. 274e3ebfccSroy */ 284e3ebfccSroy 294e3ebfccSroy #ifndef INTERFACE_H 304e3ebfccSroy #define INTERFACE_H 314e3ebfccSroy 324e3ebfccSroy #include <net/if.h> 334e3ebfccSroy #include <net/route.h> /* for RTM_ADD et all */ 344e3ebfccSroy #include <netinet/in.h> 354e3ebfccSroy #ifdef BSD 364e3ebfccSroy #include <netinet/in_var.h> /* for IN_IFF_TENTATIVE et all */ 374e3ebfccSroy #endif 384e3ebfccSroy 39e86140c7Sroy #include <ifaddrs.h> 40e86140c7Sroy 410c09469fSroy /* If the interface does not support carrier status (ie PPP), 420c09469fSroy * dhcpcd can poll it for the relevant flags periodically */ 430c09469fSroy #define IF_POLL_UP 100 /* milliseconds */ 440c09469fSroy 454e3ebfccSroy /* 464e3ebfccSroy * Systems which handle 1 address per alias. 474e3ebfccSroy * Currenly this is just Solaris. 484e3ebfccSroy * While Linux can do aliased addresses, it is only useful for their 494e3ebfccSroy * legacy ifconfig(8) tool which cannot display >1 IPv4 address 504e3ebfccSroy * (it can display many IPv6 addresses which makes the limitation odd). 514e3ebfccSroy * Linux has ip(8) which is a more feature rich tool, without the above 524e3ebfccSroy * restriction. 534e3ebfccSroy */ 544e3ebfccSroy #ifndef ALIAS_ADDR 554e3ebfccSroy # ifdef __sun 564e3ebfccSroy # define ALIAS_ADDR 574e3ebfccSroy # endif 584e3ebfccSroy #endif 594e3ebfccSroy 604e3ebfccSroy #include "config.h" 6122f7cecaSroy 6222f7cecaSroy /* POSIX defines ioctl request as an int, which Solaris and musl use. 6322f7cecaSroy * Everyone else use an unsigned long, which happens to be the bigger one 6422f7cecaSroy * so we use that in our on wire API. */ 6522f7cecaSroy #ifdef IOCTL_REQUEST_TYPE 6622f7cecaSroy typedef IOCTL_REQUEST_TYPE ioctl_request_t; 6722f7cecaSroy #else 6822f7cecaSroy typedef unsigned long ioctl_request_t; 6922f7cecaSroy #endif 7022f7cecaSroy 714e3ebfccSroy #include "dhcpcd.h" 724e3ebfccSroy #include "ipv4.h" 734e3ebfccSroy #include "ipv6.h" 744e3ebfccSroy #include "route.h" 754e3ebfccSroy 764e3ebfccSroy #define EUI64_ADDR_LEN 8 774e3ebfccSroy #define INFINIBAND_ADDR_LEN 20 784e3ebfccSroy 794e3ebfccSroy /* Linux 2.4 doesn't define this */ 804e3ebfccSroy #ifndef ARPHRD_IEEE1394 814e3ebfccSroy # define ARPHRD_IEEE1394 24 824e3ebfccSroy #endif 834e3ebfccSroy 844e3ebfccSroy /* The BSD's don't define this yet */ 854e3ebfccSroy #ifndef ARPHRD_INFINIBAND 864e3ebfccSroy # define ARPHRD_INFINIBAND 32 874e3ebfccSroy #endif 884e3ebfccSroy 8922f7cecaSroy /* Maximum frame length. 9022f7cecaSroy * Support jumbo frames and some extra. */ 9122f7cecaSroy #define FRAMEHDRLEN_MAX 14 /* only ethernet support */ 9222f7cecaSroy #define FRAMELEN_MAX (FRAMEHDRLEN_MAX + 9216) 9322f7cecaSroy 9454b96bebSroy #define UDPLEN_MAX 64 * 1024 9554b96bebSroy 964e3ebfccSroy /* Work out if we have a private address or not 974e3ebfccSroy * 10/8 984e3ebfccSroy * 172.16/12 994e3ebfccSroy * 192.168/16 1004e3ebfccSroy */ 1014e3ebfccSroy #ifndef IN_PRIVATE 1024e3ebfccSroy # define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \ 1034e3ebfccSroy ((addr & 0xfff00000) == 0xac100000) || \ 1044e3ebfccSroy ((addr & IN_CLASSB_NET) == 0xc0a80000)) 1054e3ebfccSroy #endif 1064e3ebfccSroy 1074e3ebfccSroy #ifndef CLLADDR 1084e3ebfccSroy #ifdef AF_LINK 1094e3ebfccSroy # define CLLADDR(sdl) (const void *)((sdl)->sdl_data + (sdl)->sdl_nlen) 1104e3ebfccSroy #endif 1114e3ebfccSroy #endif 1124e3ebfccSroy 1134e3ebfccSroy #ifdef __sun 1144e3ebfccSroy /* Solaris stupidly defines this for compat with BSD 1154e3ebfccSroy * but then ignores it. */ 1164e3ebfccSroy #undef RTF_CLONING 1174e3ebfccSroy 11854b96bebSroy /* This interface is busted on DilOS at least. 11954b96bebSroy * It used to work, but lukily Solaris can fall back to 12054b96bebSroy * IP_PKTINFO. */ 12154b96bebSroy #undef IP_RECVIF 122*3ee74c9aSroy #endif 12354b96bebSroy 124*3ee74c9aSroy /* Private structures specific to an OS */ 125*3ee74c9aSroy #ifdef BSD 126*3ee74c9aSroy struct priv { 127*3ee74c9aSroy #ifdef INET6 128*3ee74c9aSroy int pf_inet6_fd; 129*3ee74c9aSroy #endif 130*3ee74c9aSroy #if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */ 131*3ee74c9aSroy int pf_link_fd; 132*3ee74c9aSroy #endif 133*3ee74c9aSroy }; 134*3ee74c9aSroy #endif 135*3ee74c9aSroy #ifdef __linux__ 136*3ee74c9aSroy struct priv { 137*3ee74c9aSroy int route_fd; 138*3ee74c9aSroy int generic_fd; 139*3ee74c9aSroy uint32_t route_pid; 140*3ee74c9aSroy }; 141*3ee74c9aSroy #endif 142*3ee74c9aSroy #ifdef __sun 143*3ee74c9aSroy struct priv { 144*3ee74c9aSroy #ifdef INET6 145*3ee74c9aSroy int pf_inet6_fd; 146*3ee74c9aSroy #endif 147*3ee74c9aSroy }; 148*3ee74c9aSroy #endif 149*3ee74c9aSroy 150*3ee74c9aSroy #ifdef __sun 1514e3ebfccSroy /* Solaris getifaddrs is very un-suitable for dhcpcd. 1524e3ebfccSroy * See if-sun.c for details why. */ 1534e3ebfccSroy struct ifaddrs; 1544e3ebfccSroy int if_getifaddrs(struct ifaddrs **); 1554e3ebfccSroy #define getifaddrs if_getifaddrs 1560e276282Sroy int if_getsubnet(struct dhcpcd_ctx *, const char *, int, void *, size_t); 1574e3ebfccSroy #endif 1584e3ebfccSroy 15922f7cecaSroy int if_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t); 16054b96bebSroy #ifdef HAVE_PLEDGE 16154b96bebSroy #define pioctl(ctx, req, data, len) if_ioctl((ctx), (req), (data), (len)) 16254b96bebSroy #else 16354b96bebSroy #define pioctl(ctx, req, data, len) ioctl((ctx)->pf_inet_fd, (req),(data),(len)) 16454b96bebSroy #endif 16522f7cecaSroy int if_getflags(struct interface *); 16622f7cecaSroy int if_setflag(struct interface *, short, short); 16722f7cecaSroy #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0) 16822f7cecaSroy #define if_down(ifp) if_setflag((ifp), 0, IFF_UP); 16962451a3fSroy bool if_is_link_up(const struct interface *); 17052de4619Sroy bool if_valid_hwaddr(const uint8_t *, size_t); 171e86140c7Sroy struct if_head *if_discover(struct dhcpcd_ctx *, struct ifaddrs **, 172e86140c7Sroy int, char * const *); 173*3ee74c9aSroy void if_freeifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **); 1745021de5dSroy void if_markaddrsstale(struct if_head *); 175e86140c7Sroy void if_learnaddrs(struct dhcpcd_ctx *, struct if_head *, struct ifaddrs **); 1765021de5dSroy void if_deletestaleaddrs(struct if_head *); 1774e3ebfccSroy struct interface *if_find(struct if_head *, const char *); 1784e3ebfccSroy struct interface *if_findindex(struct if_head *, unsigned int); 1794e3ebfccSroy struct interface *if_loopback(struct dhcpcd_ctx *); 1804e3ebfccSroy void if_free(struct interface *); 1814e3ebfccSroy int if_domtu(const struct interface *, short int); 1824e3ebfccSroy #define if_getmtu(ifp) if_domtu((ifp), 0) 1834e3ebfccSroy #define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu)) 184c73d34bfSroy int if_carrier(struct interface *, const void *); 185ff6d9aefSroy bool if_roaming(struct interface *); 1864e3ebfccSroy 187f04bcf37Sroy #ifdef ALIAS_ADDR 188f04bcf37Sroy int if_makealias(char *, size_t, const char *, int); 189f04bcf37Sroy #endif 190f04bcf37Sroy 191f04bcf37Sroy int if_mtu_os(const struct interface *); 192f04bcf37Sroy 1934e3ebfccSroy /* 1944e3ebfccSroy * Helper to decode an interface name of bge0:1 to 1954e3ebfccSroy * devname = bge0, drvname = bge0, ppa = 0, lun = 1. 1964e3ebfccSroy * If ppa or lun are invalid they are set to -1. 1974e3ebfccSroy */ 1984e3ebfccSroy struct if_spec { 1994e3ebfccSroy char ifname[IF_NAMESIZE]; 2004e3ebfccSroy char devname[IF_NAMESIZE]; 2014e3ebfccSroy char drvname[IF_NAMESIZE]; 2024e3ebfccSroy int ppa; 20322f7cecaSroy int vlid; 2044e3ebfccSroy int lun; 2054e3ebfccSroy }; 2064e3ebfccSroy int if_nametospec(const char *, struct if_spec *); 2074e3ebfccSroy 2084e3ebfccSroy /* The below functions are provided by if-KERNEL.c */ 209c73d34bfSroy int os_init(void); 2104e3ebfccSroy int if_conf(struct interface *); 2114e3ebfccSroy int if_init(struct interface *); 2124e3ebfccSroy int if_getssid(struct interface *); 213708ac11bSroy int if_ignoregroup(int, const char *); 21429025585Sroy bool if_ignore(struct dhcpcd_ctx *, const char *); 21554b96bebSroy int if_vimaster(struct dhcpcd_ctx *ctx, const char *); 2165fed7375Sroy unsigned short if_vlanid(const struct interface *); 217c73d34bfSroy char * if_getnetworknamespace(char *, size_t); 2184e3ebfccSroy int if_opensockets(struct dhcpcd_ctx *); 2194e3ebfccSroy int if_opensockets_os(struct dhcpcd_ctx *); 2204e3ebfccSroy void if_closesockets(struct dhcpcd_ctx *); 2214e3ebfccSroy void if_closesockets_os(struct dhcpcd_ctx *); 2224e3ebfccSroy int if_handlelink(struct dhcpcd_ctx *); 22322f7cecaSroy int if_randomisemac(struct interface *); 22422f7cecaSroy int if_setmac(struct interface *ifp, void *, uint8_t); 2254e3ebfccSroy 2264e3ebfccSroy /* dhcpcd uses the same routing flags as BSD. 2274e3ebfccSroy * If the platform doesn't use these flags, 2284e3ebfccSroy * map them in the platform interace file. */ 2294e3ebfccSroy #ifndef RTM_ADD 2304e3ebfccSroy #define RTM_ADD 0x1 /* Add Route */ 2314e3ebfccSroy #define RTM_DELETE 0x2 /* Delete Route */ 2324e3ebfccSroy #define RTM_CHANGE 0x3 /* Change Metrics or flags */ 2334e3ebfccSroy #define RTM_GET 0x4 /* Report Metrics */ 2344e3ebfccSroy #endif 2354e3ebfccSroy 2364e3ebfccSroy /* Define SOCK_CLOEXEC and SOCK_NONBLOCK for systems that lack it. 2374e3ebfccSroy * xsocket() in if.c will map them to fctnl FD_CLOEXEC and O_NONBLOCK. */ 2384e3ebfccSroy #ifdef SOCK_CLOEXEC 2394e3ebfccSroy # define HAVE_SOCK_CLOEXEC 2404e3ebfccSroy #else 2414e3ebfccSroy # define SOCK_CLOEXEC 0x10000000 2424e3ebfccSroy #endif 2434e3ebfccSroy #ifdef SOCK_NONBLOCK 2444e3ebfccSroy # define HAVE_SOCK_NONBLOCK 2454e3ebfccSroy #else 2464e3ebfccSroy # define SOCK_NONBLOCK 0x20000000 2474e3ebfccSroy #endif 24854b96bebSroy #ifndef SOCK_CXNB 24954b96bebSroy #define SOCK_CXNB SOCK_CLOEXEC | SOCK_NONBLOCK 25054b96bebSroy #endif 251e2db0f19Sroy int xsocket(int, int, int); 252e2db0f19Sroy int xsocketpair(int, int, int, int[2]); 2534e3ebfccSroy 2544e3ebfccSroy int if_route(unsigned char, const struct rt *rt); 2550d34b412Sroy int if_initrt(struct dhcpcd_ctx *, rb_tree_t *, int); 2564e3ebfccSroy 25722f7cecaSroy int if_missfilter(struct interface *, struct sockaddr *); 25822f7cecaSroy int if_missfilter_apply(struct dhcpcd_ctx *); 25922f7cecaSroy 2604e3ebfccSroy #ifdef INET 2614e3ebfccSroy int if_address(unsigned char, const struct ipv4_addr *); 2624e3ebfccSroy int if_addrflags(const struct interface *, const struct in_addr *, 2634e3ebfccSroy const char *); 2644e3ebfccSroy 2654e3ebfccSroy #endif 2664e3ebfccSroy 2674e3ebfccSroy #ifdef INET6 268a5ecc274Sroy void if_disable_rtadv(void); 2695021de5dSroy void if_setup_inet6(const struct interface *); 2702b9a0e7aSroy int ip6_forwarding(const char *ifname); 2714e3ebfccSroy 27222f7cecaSroy struct ra; 27322f7cecaSroy struct ipv6_addr; 27422f7cecaSroy 275a5ecc274Sroy int if_applyra(const struct ra *); 2764e3ebfccSroy int if_address6(unsigned char, const struct ipv6_addr *); 2774e3ebfccSroy int if_addrflags6(const struct interface *, const struct in6_addr *, 2784e3ebfccSroy const char *); 2794e3ebfccSroy int if_getlifetime6(struct ipv6_addr *); 2804e3ebfccSroy 2814e3ebfccSroy #else 2824e3ebfccSroy #define if_checkipv6(a, b, c) (-1) 2834e3ebfccSroy #endif 2844e3ebfccSroy 2854e3ebfccSroy int if_machinearch(char *, size_t); 286f04bcf37Sroy struct interface *if_findifpfromcmsg(struct dhcpcd_ctx *, 287f04bcf37Sroy struct msghdr *, int *); 28822f7cecaSroy 28922f7cecaSroy #ifdef __linux__ 29054b96bebSroy int if_linksocket(struct sockaddr_nl *, int, int); 29122f7cecaSroy int if_getnetlink(struct dhcpcd_ctx *, struct iovec *, int, int, 29222f7cecaSroy int (*)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *); 29322f7cecaSroy #endif 2944e3ebfccSroy #endif 295