18d36e1dfSRoy Marples /* SPDX-License-Identifier: BSD-2-Clause */ 27827cba2SAaron LI /* 37827cba2SAaron LI * dhcpcd - DHCP client daemon 4*80aa9461SRoy Marples * Copyright (c) 2006-2023 Roy Marples <roy@marples.name> 57827cba2SAaron LI * All rights reserved 67827cba2SAaron LI 77827cba2SAaron LI * Redistribution and use in source and binary forms, with or without 87827cba2SAaron LI * modification, are permitted provided that the following conditions 97827cba2SAaron LI * are met: 107827cba2SAaron LI * 1. Redistributions of source code must retain the above copyright 117827cba2SAaron LI * notice, this list of conditions and the following disclaimer. 127827cba2SAaron LI * 2. Redistributions in binary form must reproduce the above copyright 137827cba2SAaron LI * notice, this list of conditions and the following disclaimer in the 147827cba2SAaron LI * documentation and/or other materials provided with the distribution. 157827cba2SAaron LI * 167827cba2SAaron LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 177827cba2SAaron LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 187827cba2SAaron LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 197827cba2SAaron LI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 207827cba2SAaron LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 217827cba2SAaron LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 227827cba2SAaron LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 237827cba2SAaron LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 247827cba2SAaron LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 257827cba2SAaron LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267827cba2SAaron LI * SUCH DAMAGE. 277827cba2SAaron LI */ 287827cba2SAaron LI 297827cba2SAaron LI #ifndef INTERFACE_H 307827cba2SAaron LI #define INTERFACE_H 317827cba2SAaron LI 327827cba2SAaron LI #include <net/if.h> 337827cba2SAaron LI #include <net/route.h> /* for RTM_ADD et all */ 347827cba2SAaron LI #include <netinet/in.h> 357827cba2SAaron LI #ifdef BSD 367827cba2SAaron LI #include <netinet/in_var.h> /* for IN_IFF_TENTATIVE et all */ 377827cba2SAaron LI #endif 387827cba2SAaron LI 397827cba2SAaron LI #include <ifaddrs.h> 407827cba2SAaron LI 41cc34ba0cSRoy Marples /* If the interface does not support carrier status (ie PPP), 42cc34ba0cSRoy Marples * dhcpcd can poll it for the relevant flags periodically */ 43cc34ba0cSRoy Marples #define IF_POLL_UP 100 /* milliseconds */ 44cc34ba0cSRoy Marples 457827cba2SAaron LI /* 467827cba2SAaron LI * Systems which handle 1 address per alias. 477827cba2SAaron LI * Currenly this is just Solaris. 487827cba2SAaron LI * While Linux can do aliased addresses, it is only useful for their 497827cba2SAaron LI * legacy ifconfig(8) tool which cannot display >1 IPv4 address 507827cba2SAaron LI * (it can display many IPv6 addresses which makes the limitation odd). 517827cba2SAaron LI * Linux has ip(8) which is a more feature rich tool, without the above 527827cba2SAaron LI * restriction. 537827cba2SAaron LI */ 547827cba2SAaron LI #ifndef ALIAS_ADDR 557827cba2SAaron LI # ifdef __sun 567827cba2SAaron LI # define ALIAS_ADDR 577827cba2SAaron LI # endif 587827cba2SAaron LI #endif 597827cba2SAaron LI 607827cba2SAaron LI #include "config.h" 616e63cc1fSRoy Marples 626e63cc1fSRoy Marples /* POSIX defines ioctl request as an int, which Solaris and musl use. 636e63cc1fSRoy Marples * Everyone else use an unsigned long, which happens to be the bigger one 646e63cc1fSRoy Marples * so we use that in our on wire API. */ 656e63cc1fSRoy Marples #ifdef IOCTL_REQUEST_TYPE 666e63cc1fSRoy Marples typedef IOCTL_REQUEST_TYPE ioctl_request_t; 676e63cc1fSRoy Marples #else 686e63cc1fSRoy Marples typedef unsigned long ioctl_request_t; 696e63cc1fSRoy Marples #endif 706e63cc1fSRoy Marples 717827cba2SAaron LI #include "dhcpcd.h" 727827cba2SAaron LI #include "ipv4.h" 737827cba2SAaron LI #include "ipv6.h" 747827cba2SAaron LI #include "route.h" 757827cba2SAaron LI 767827cba2SAaron LI #define EUI64_ADDR_LEN 8 777827cba2SAaron LI #define INFINIBAND_ADDR_LEN 20 787827cba2SAaron LI 797827cba2SAaron LI /* Linux 2.4 doesn't define this */ 807827cba2SAaron LI #ifndef ARPHRD_IEEE1394 817827cba2SAaron LI # define ARPHRD_IEEE1394 24 827827cba2SAaron LI #endif 837827cba2SAaron LI 847827cba2SAaron LI /* The BSD's don't define this yet */ 857827cba2SAaron LI #ifndef ARPHRD_INFINIBAND 867827cba2SAaron LI # define ARPHRD_INFINIBAND 32 877827cba2SAaron LI #endif 887827cba2SAaron LI 896e63cc1fSRoy Marples /* Maximum frame length. 906e63cc1fSRoy Marples * Support jumbo frames and some extra. */ 916e63cc1fSRoy Marples #define FRAMEHDRLEN_MAX 14 /* only ethernet support */ 926e63cc1fSRoy Marples #define FRAMELEN_MAX (FRAMEHDRLEN_MAX + 9216) 936e63cc1fSRoy Marples 94d4fb1e02SRoy Marples #define UDPLEN_MAX 64 * 1024 95d4fb1e02SRoy Marples 967827cba2SAaron LI /* Work out if we have a private address or not 977827cba2SAaron LI * 10/8 987827cba2SAaron LI * 172.16/12 997827cba2SAaron LI * 192.168/16 1007827cba2SAaron LI */ 1017827cba2SAaron LI #ifndef IN_PRIVATE 1027827cba2SAaron LI # define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \ 1037827cba2SAaron LI ((addr & 0xfff00000) == 0xac100000) || \ 1047827cba2SAaron LI ((addr & IN_CLASSB_NET) == 0xc0a80000)) 1057827cba2SAaron LI #endif 1067827cba2SAaron LI 1077827cba2SAaron LI #ifndef CLLADDR 1087827cba2SAaron LI #ifdef AF_LINK 1097827cba2SAaron LI # define CLLADDR(sdl) (const void *)((sdl)->sdl_data + (sdl)->sdl_nlen) 1107827cba2SAaron LI #endif 1117827cba2SAaron LI #endif 1127827cba2SAaron LI 1137827cba2SAaron LI #ifdef __sun 1147827cba2SAaron LI /* Solaris stupidly defines this for compat with BSD 1157827cba2SAaron LI * but then ignores it. */ 1167827cba2SAaron LI #undef RTF_CLONING 1177827cba2SAaron LI 118d4fb1e02SRoy Marples /* This interface is busted on DilOS at least. 119d4fb1e02SRoy Marples * It used to work, but lukily Solaris can fall back to 120d4fb1e02SRoy Marples * IP_PKTINFO. */ 121d4fb1e02SRoy Marples #undef IP_RECVIF 122*80aa9461SRoy Marples #endif 123d4fb1e02SRoy Marples 124*80aa9461SRoy Marples /* Private structures specific to an OS */ 125*80aa9461SRoy Marples #ifdef BSD 126*80aa9461SRoy Marples struct priv { 127*80aa9461SRoy Marples #ifdef INET6 128*80aa9461SRoy Marples int pf_inet6_fd; 129*80aa9461SRoy Marples #endif 130*80aa9461SRoy Marples #if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */ 131*80aa9461SRoy Marples int pf_link_fd; 132*80aa9461SRoy Marples #endif 133*80aa9461SRoy Marples }; 134*80aa9461SRoy Marples #endif 135*80aa9461SRoy Marples #ifdef __linux__ 136*80aa9461SRoy Marples struct priv { 137*80aa9461SRoy Marples int route_fd; 138*80aa9461SRoy Marples int generic_fd; 139*80aa9461SRoy Marples uint32_t route_pid; 140*80aa9461SRoy Marples }; 141*80aa9461SRoy Marples #endif 142*80aa9461SRoy Marples #ifdef __sun 143*80aa9461SRoy Marples struct priv { 144*80aa9461SRoy Marples #ifdef INET6 145*80aa9461SRoy Marples int pf_inet6_fd; 146*80aa9461SRoy Marples #endif 147*80aa9461SRoy Marples }; 148*80aa9461SRoy Marples #endif 149*80aa9461SRoy Marples 150*80aa9461SRoy Marples #ifdef __sun 1517827cba2SAaron LI /* Solaris getifaddrs is very un-suitable for dhcpcd. 1527827cba2SAaron LI * See if-sun.c for details why. */ 1537827cba2SAaron LI struct ifaddrs; 1547827cba2SAaron LI int if_getifaddrs(struct ifaddrs **); 1557827cba2SAaron LI #define getifaddrs if_getifaddrs 1568d36e1dfSRoy Marples int if_getsubnet(struct dhcpcd_ctx *, const char *, int, void *, size_t); 1577827cba2SAaron LI #endif 1587827cba2SAaron LI 1596e63cc1fSRoy Marples int if_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t); 160d4fb1e02SRoy Marples #ifdef HAVE_PLEDGE 161d4fb1e02SRoy Marples #define pioctl(ctx, req, data, len) if_ioctl((ctx), (req), (data), (len)) 162d4fb1e02SRoy Marples #else 163d4fb1e02SRoy Marples #define pioctl(ctx, req, data, len) ioctl((ctx)->pf_inet_fd, (req),(data),(len)) 164d4fb1e02SRoy Marples #endif 1656e63cc1fSRoy Marples int if_getflags(struct interface *); 1666e63cc1fSRoy Marples int if_setflag(struct interface *, short, short); 1676e63cc1fSRoy Marples #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0) 1686e63cc1fSRoy Marples #define if_down(ifp) if_setflag((ifp), 0, IFF_UP); 16993ddca5eSRoy Marples bool if_is_link_up(const struct interface *); 1707827cba2SAaron LI bool if_valid_hwaddr(const uint8_t *, size_t); 1717827cba2SAaron LI struct if_head *if_discover(struct dhcpcd_ctx *, struct ifaddrs **, 1727827cba2SAaron LI int, char * const *); 173*80aa9461SRoy Marples void if_freeifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **); 1747827cba2SAaron LI void if_markaddrsstale(struct if_head *); 1757827cba2SAaron LI void if_learnaddrs(struct dhcpcd_ctx *, struct if_head *, struct ifaddrs **); 1767827cba2SAaron LI void if_deletestaleaddrs(struct if_head *); 1777827cba2SAaron LI struct interface *if_find(struct if_head *, const char *); 1787827cba2SAaron LI struct interface *if_findindex(struct if_head *, unsigned int); 1797827cba2SAaron LI struct interface *if_loopback(struct dhcpcd_ctx *); 1807827cba2SAaron LI void if_free(struct interface *); 1817827cba2SAaron LI int if_domtu(const struct interface *, short int); 1827827cba2SAaron LI #define if_getmtu(ifp) if_domtu((ifp), 0) 1837827cba2SAaron LI #define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu)) 184a0d9933aSRoy Marples int if_carrier(struct interface *, const void *); 1850aaf6155SRoy Marples bool if_roaming(struct interface *); 1867827cba2SAaron LI 1878d36e1dfSRoy Marples #ifdef ALIAS_ADDR 1888d36e1dfSRoy Marples int if_makealias(char *, size_t, const char *, int); 1898d36e1dfSRoy Marples #endif 1908d36e1dfSRoy Marples 1918d36e1dfSRoy Marples int if_mtu_os(const struct interface *); 1928d36e1dfSRoy Marples 1937827cba2SAaron LI /* 1947827cba2SAaron LI * Helper to decode an interface name of bge0:1 to 1957827cba2SAaron LI * devname = bge0, drvname = bge0, ppa = 0, lun = 1. 1967827cba2SAaron LI * If ppa or lun are invalid they are set to -1. 1977827cba2SAaron LI */ 1987827cba2SAaron LI struct if_spec { 1997827cba2SAaron LI char ifname[IF_NAMESIZE]; 2007827cba2SAaron LI char devname[IF_NAMESIZE]; 2017827cba2SAaron LI char drvname[IF_NAMESIZE]; 2027827cba2SAaron LI int ppa; 2036e63cc1fSRoy Marples int vlid; 2047827cba2SAaron LI int lun; 2057827cba2SAaron LI }; 2067827cba2SAaron LI int if_nametospec(const char *, struct if_spec *); 2077827cba2SAaron LI 2087827cba2SAaron LI /* The below functions are provided by if-KERNEL.c */ 209a0d9933aSRoy Marples int os_init(void); 2107827cba2SAaron LI int if_conf(struct interface *); 2117827cba2SAaron LI int if_init(struct interface *); 2127827cba2SAaron LI int if_getssid(struct interface *); 2137f8103cdSRoy Marples int if_ignoregroup(int, const char *); 2141b3b16a2SRoy Marples bool if_ignore(struct dhcpcd_ctx *, const char *); 215d4fb1e02SRoy Marples int if_vimaster(struct dhcpcd_ctx *ctx, const char *); 2167827cba2SAaron LI unsigned short if_vlanid(const struct interface *); 217a0d9933aSRoy Marples char * if_getnetworknamespace(char *, size_t); 2187827cba2SAaron LI int if_opensockets(struct dhcpcd_ctx *); 2197827cba2SAaron LI int if_opensockets_os(struct dhcpcd_ctx *); 2207827cba2SAaron LI void if_closesockets(struct dhcpcd_ctx *); 2217827cba2SAaron LI void if_closesockets_os(struct dhcpcd_ctx *); 2227827cba2SAaron LI int if_handlelink(struct dhcpcd_ctx *); 2236e63cc1fSRoy Marples int if_randomisemac(struct interface *); 2246e63cc1fSRoy Marples int if_setmac(struct interface *ifp, void *, uint8_t); 2257827cba2SAaron LI 2267827cba2SAaron LI /* dhcpcd uses the same routing flags as BSD. 2277827cba2SAaron LI * If the platform doesn't use these flags, 2287827cba2SAaron LI * map them in the platform interace file. */ 2297827cba2SAaron LI #ifndef RTM_ADD 2307827cba2SAaron LI #define RTM_ADD 0x1 /* Add Route */ 2317827cba2SAaron LI #define RTM_DELETE 0x2 /* Delete Route */ 2327827cba2SAaron LI #define RTM_CHANGE 0x3 /* Change Metrics or flags */ 2337827cba2SAaron LI #define RTM_GET 0x4 /* Report Metrics */ 2347827cba2SAaron LI #endif 2357827cba2SAaron LI 2367827cba2SAaron LI /* Define SOCK_CLOEXEC and SOCK_NONBLOCK for systems that lack it. 2377827cba2SAaron LI * xsocket() in if.c will map them to fctnl FD_CLOEXEC and O_NONBLOCK. */ 2387827cba2SAaron LI #ifdef SOCK_CLOEXEC 2397827cba2SAaron LI # define HAVE_SOCK_CLOEXEC 2407827cba2SAaron LI #else 2417827cba2SAaron LI # define SOCK_CLOEXEC 0x10000000 2427827cba2SAaron LI #endif 2437827cba2SAaron LI #ifdef SOCK_NONBLOCK 2447827cba2SAaron LI # define HAVE_SOCK_NONBLOCK 2457827cba2SAaron LI #else 2467827cba2SAaron LI # define SOCK_NONBLOCK 0x20000000 2477827cba2SAaron LI #endif 248d4fb1e02SRoy Marples #ifndef SOCK_CXNB 249d4fb1e02SRoy Marples #define SOCK_CXNB SOCK_CLOEXEC | SOCK_NONBLOCK 250d4fb1e02SRoy Marples #endif 251b8b69544SRoy Marples int xsocket(int, int, int); 252b8b69544SRoy Marples int xsocketpair(int, int, int, int[2]); 2537827cba2SAaron LI 2547827cba2SAaron LI int if_route(unsigned char, const struct rt *rt); 2558d36e1dfSRoy Marples int if_initrt(struct dhcpcd_ctx *, rb_tree_t *, int); 2567827cba2SAaron LI 2576e63cc1fSRoy Marples int if_missfilter(struct interface *, struct sockaddr *); 2586e63cc1fSRoy Marples int if_missfilter_apply(struct dhcpcd_ctx *); 2596e63cc1fSRoy Marples 2607827cba2SAaron LI #ifdef INET 2617827cba2SAaron LI int if_address(unsigned char, const struct ipv4_addr *); 2627827cba2SAaron LI int if_addrflags(const struct interface *, const struct in_addr *, 2637827cba2SAaron LI const char *); 2647827cba2SAaron LI 2657827cba2SAaron LI #endif 2667827cba2SAaron LI 2677827cba2SAaron LI #ifdef INET6 268b9ccd228SRoy Marples void if_disable_rtadv(void); 2697827cba2SAaron LI void if_setup_inet6(const struct interface *); 2708d36e1dfSRoy Marples int ip6_forwarding(const char *ifname); 2717827cba2SAaron LI 2726e63cc1fSRoy Marples struct ra; 2736e63cc1fSRoy Marples struct ipv6_addr; 2746e63cc1fSRoy Marples 275b9ccd228SRoy Marples int if_applyra(const struct ra *); 2767827cba2SAaron LI int if_address6(unsigned char, const struct ipv6_addr *); 2777827cba2SAaron LI int if_addrflags6(const struct interface *, const struct in6_addr *, 2787827cba2SAaron LI const char *); 2797827cba2SAaron LI int if_getlifetime6(struct ipv6_addr *); 2807827cba2SAaron LI 2817827cba2SAaron LI #else 2827827cba2SAaron LI #define if_checkipv6(a, b, c) (-1) 2837827cba2SAaron LI #endif 2847827cba2SAaron LI 2857827cba2SAaron LI int if_machinearch(char *, size_t); 2868d36e1dfSRoy Marples struct interface *if_findifpfromcmsg(struct dhcpcd_ctx *, 2878d36e1dfSRoy Marples struct msghdr *, int *); 2886e63cc1fSRoy Marples 2896e63cc1fSRoy Marples #ifdef __linux__ 290d4fb1e02SRoy Marples int if_linksocket(struct sockaddr_nl *, int, int); 2916e63cc1fSRoy Marples int if_getnetlink(struct dhcpcd_ctx *, struct iovec *, int, int, 2926e63cc1fSRoy Marples int (*)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *); 2936e63cc1fSRoy Marples #endif 2947827cba2SAaron LI #endif 295