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/ioctl.h> 29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/param.h> 30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/socket.h> 31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/stat.h> 32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/sysctl.h> 33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/time.h> 34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/types.h> 35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/uio.h> 36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/utsname.h> 37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <arpa/inet.h> 39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/bpf.h> 40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if.h> 41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if_dl.h> 42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */ 43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# include <net/if_var.h> 44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if_media.h> 46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/route.h> 47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/if_ether.h> 48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/in.h> 49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/in_var.h> 50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet6/in6_var.h> 51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet6/nd6.h> 52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef __DragonFly__ 53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# include <netproto/802_11/ieee80211_ioctl.h> 54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif __APPLE__ 55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* FIXME: Add apple includes so we can work out SSID */ 56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# include <net80211/ieee80211.h> 58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# include <net80211/ieee80211_ioctl.h> 59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h> 62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <fcntl.h> 63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <fnmatch.h> 64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <paths.h> 65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stddef.h> 66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdio.h> 67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h> 68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h> 69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h> 70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(OpenBSD) && OpenBSD >= 201411 72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* OpenBSD dropped the global setting from sysctl but left the #define 73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * which causes a EPERM error when trying to use it. 74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * I think both the error and keeping the define are wrong, so we #undef it. */ 75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef IPV6CTL_ACCEPT_RTADV 76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h" 79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h" 80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h" 81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h" 82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if-options.h" 83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv4.h" 84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv6.h" 85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv6nd.h" 86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "bpf-filter.h" 88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef RT_ROUNDUP 90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define RT_ROUNDUP(a) \ 91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len)) 93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define COPYOUT(sin, sa) do { \ 96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((sa) && ((sa)->sa_family == AF_INET || (sa)->sa_family == 255)) \ 97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (sin) = ((struct sockaddr_in*)(void *)(sa))->sin_addr; \ 98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } while (0) 99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define COPYOUT6(sin, sa) do { \ 101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((sa) && ((sa)->sa_family == AF_INET6 || (sa)->sa_family == 255)) \ 102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (sin) = ((struct sockaddr_in6*)(void *)(sa))->sin6_addr; \ 103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } while (0) 104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef CLLADDR 106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen)) 107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_init(__unused struct interface *iface) 111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* BSD promotes secondary address by default */ 113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_conf(__unused struct interface *iface) 118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* No extra checks needed on BSD */ 120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_openlinksocket(void) 125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SOCK_CLOEXEC 128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); 129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, flags; 131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((flags = fcntl(s, F_GETFD, 0)) == -1 || 135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1) 136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((flags = fcntl(s, F_GETFL, 0)) == -1 || 141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) 142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return s; 147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(INET) || defined(INET6) 151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp) 153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(sdl, 0, sizeof(*sdl)); 156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl->sdl_family = AF_LINK; 157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl->sdl_len = sizeof(*sdl); 158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl->sdl_nlen = sdl->sdl_alen = sdl->sdl_slen = 0; 159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl->sdl_index = (unsigned short)ifp->index; 160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_getssid1(const char *ifname, uint8_t *ssid) 165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, retval = -1; 167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(SIOCG80211NWID) 168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifreq ifr; 169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ieee80211_nwid nwid; 170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(IEEE80211_IOC_SSID) 171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ieee80211req ireq; 172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char nwid[IEEE80211_NWID_LEN + 1]; 173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(SIOCG80211NWID) /* NetBSD */ 179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifr, 0, sizeof(ifr)); 180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nwid, 0, sizeof(nwid)); 182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifr.ifr_data = (void *)&nwid; 183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCG80211NWID, &ifr) == 0) { 184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ssid == NULL) 185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = nwid.i_len; 186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (nwid.i_len > IF_SSIDSIZE) { 187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = -1; 189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = nwid.i_len; 191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(ssid, nwid.i_nwid, nwid.i_len); 192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssid[nwid.i_len] = '\0'; 193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(IEEE80211_IOC_SSID) /* FreeBSD */ 196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ireq, 0, sizeof(ireq)); 197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); 198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ireq.i_type = IEEE80211_IOC_SSID; 199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ireq.i_val = -1; 200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(nwid, 0, sizeof(nwid)); 201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ireq.i_data = &nwid; 202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCG80211, &ireq) == 0) { 203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ssid == NULL) 204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = ireq.i_len; 205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (ireq.i_len > IF_SSIDSIZE) { 206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = -1; 208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = ireq.i_len; 210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(ssid, nwid, ireq.i_len); 211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssid[ireq.i_len] = '\0'; 212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_getssid(struct interface *ifp) 222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int r; 224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = if_getssid1(ifp->name, ifp->ssid); 226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != -1) 227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ssid_len = (unsigned int)r; 228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* 232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FreeBSD allows for Virtual Access Points 233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * We need to check if the interface is a Virtual Interface Master 234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * and if so, don't use it. 235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * This check is made by virtue of being a IEEE80211 device but 236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * returning the SSID gives an error. 237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_vimaster(const char *ifname) 240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, r; 242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifmediareq ifmr; 243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifmr, 0, sizeof(ifmr)); 247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = ioctl(s, SIOCGIFMEDIA, &ifmr); 249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r == -1) 251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifmr.ifm_status & IFM_AVALID && 253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) 254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_getssid1(ifname, NULL) == -1) 256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanget_addrs(int type, char *cp, struct sockaddr **sa) 263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int i; 265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0; i < RTAX_MAX; i++) { 267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & (1 << i)) { 268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sa[i] = (struct sockaddr *)cp; 269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan RT_ADVANCE(cp, sa[i]); 270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sa[i] = NULL; 272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(INET) || defined(INET6) 276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic struct interface * 277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_findsdl(struct dhcpcd_ctx *ctx, struct sockaddr_dl *sdl) 278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sdl->sdl_nlen) { 281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char ifname[IF_NAMESIZE]; 282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen); 283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname[sdl->sdl_nlen] = '\0'; 284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return if_find(ctx->ifaces, ifname); 285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return NULL; 287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanconst char *if_pfname = "Berkley Packet Filter"; 292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_openrawsocket(struct interface *ifp, uint16_t protocol) 295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state; 297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int fd = -1; 298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifreq ifr; 299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int ibuf_len = 0; 300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t buf_len; 301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct bpf_version pv; 302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct bpf_program pf; 303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef BIOCIMMEDIATE 304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int flags; 305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef _PATH_BPF 307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = open(_PATH_BPF, O_RDWR | O_CLOEXEC | O_NONBLOCK); 308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char device[32]; 310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int n = 0; 311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan do { 313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(device, sizeof(device), "/dev/bpf%d", n++); 314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = open(device, O_RDWR | O_CLOEXEC | O_NONBLOCK); 315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } while (fd == -1 && errno == EBUSY); 316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fd == -1) 319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_STATE(ifp); 322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&pv, 0, sizeof(pv)); 324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(fd, BIOCVERSION, &pv) == -1) 325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (pv.bv_major != BPF_MAJOR_VERSION || 327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pv.bv_minor < BPF_MINOR_VERSION) { 328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, "BPF version mismatch - recompile"); 329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifr, 0, sizeof(ifr)); 333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(fd, BIOCSETIF, &ifr) == -1) 335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Get the required BPF buffer length from the kernel. */ 338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(fd, BIOCGBLEN, &ibuf_len) == -1) 339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan buf_len = (size_t)ibuf_len; 341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->buffer_size != buf_len) { 342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(state->buffer); 343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer = malloc(buf_len); 344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->buffer == NULL) 345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_size = buf_len; 347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_len = state->buffer_pos = 0; 348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef BIOCIMMEDIATE 351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = 1; 352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(fd, BIOCIMMEDIATE, &flags) == -1) 353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Install the DHCP filter */ 357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&pf, 0, sizeof(pf)); 358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (protocol == ETHERTYPE_ARP) { 359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.bf_insns = UNCONST(arp_bpf_filter); 360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.bf_len = arp_bpf_filter_len; 361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.bf_insns = UNCONST(dhcp_bpf_filter); 363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.bf_len = dhcp_bpf_filter_len; 364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(fd, BIOCSETF, &pf) == -1) 366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return fd; 369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneexit: 371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(state->buffer); 372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer = NULL; 373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(fd); 374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_sendrawpacket(const struct interface *ifp, uint16_t protocol, 379f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan const void *data, size_t len, const uint8_t *dest_hw_addr) 380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct iovec iov[2]; 382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ether_header hw; 383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int fd; 384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_state *state; 385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&hw, 0, ETHER_HDR_LEN); 387f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan if (dest_hw_addr) 388f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan memcpy(&hw.ether_dhost, dest_hw_addr, ETHER_ADDR_LEN); 389f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan else 390f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN); 391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hw.ether_type = htons(protocol); 392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iov[0].iov_base = &hw; 393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iov[0].iov_len = ETHER_HDR_LEN; 394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iov[1].iov_base = UNCONST(data); 395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iov[1].iov_len = len; 396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_CSTATE(ifp); 397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (protocol == ETHERTYPE_ARP) 398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->arp_fd; 399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->raw_fd; 401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return writev(fd, iov, 2); 402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* BPF requires that we read the entire buffer. 405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * So we pass the buffer in the API so we can loop on >1 packet. */ 406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_readrawpacket(struct interface *ifp, uint16_t protocol, 408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void *data, size_t len, int *flags) 409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int fd; 411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct bpf_hdr packet; 412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t bytes; 413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const unsigned char *payload; 414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state; 415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_STATE(ifp); 417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (protocol == ETHERTYPE_ARP) 418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->arp_fd; 419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->raw_fd; 421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *flags = 0; 423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (;;) { 424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->buffer_len == 0) { 425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = read(fd, state->buffer, state->buffer_size); 426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes == -1 || bytes == 0) 427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return bytes; 428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_len = (size_t)bytes; 429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_pos = 0; 430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = -1; 432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&packet, state->buffer + state->buffer_pos, 433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(packet)); 434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (packet.bh_caplen != packet.bh_datalen) 435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto next; /* Incomplete packet, drop. */ 436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen > 437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_len) 438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto next; /* Packet beyond buffer, drop. */ 439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan payload = state->buffer + state->buffer_pos + 440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan packet.bh_hdrlen + ETHER_HDR_LEN; 441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = (ssize_t)packet.bh_caplen - ETHER_HDR_LEN; 442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((size_t)bytes > len) 443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = (ssize_t)len; 444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(data, payload, (size_t)bytes); 445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tannext: 446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen + 447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan packet.bh_caplen); 448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->buffer_pos >= state->buffer_len) { 449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->buffer_len = state->buffer_pos = 0; 450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *flags |= RAW_EOF; 451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes != -1) 453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return bytes; 454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_address(const struct interface *ifp, const struct in_addr *address, 459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct in_addr *netmask, const struct in_addr *broadcast, 460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int action) 461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, r; 463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in_aliasreq ifra; 464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifra, 0, sizeof(ifra)); 469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name)); 470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDADDR(var, addr) do { \ 472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (var)->sin_family = AF_INET; \ 473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (var)->sin_len = sizeof(*(var)); \ 474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (var)->sin_addr = *(addr); \ 475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } while (/*CONSTCOND*/0) 476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&ifra.ifra_addr, address); 477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&ifra.ifra_mask, netmask); 478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action >= 0 && broadcast) 479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&ifra.ifra_broadaddr, broadcast); 480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef ADDADDR 481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = ioctl(s, 483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra); 484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm) 490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *cp; 492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr *sa, *rti_info[RTAX_MAX]; 493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cp = (char *)(void *)(rtm + 1); 495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sa = (struct sockaddr *)(void *)cp; 496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sa->sa_family != AF_INET) 497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) 499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_CLONED 501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & RTF_CLONED) 502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_LOCAL 505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & RTF_LOCAL) 506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_BROADCAST 509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & RTF_BROADCAST) 510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_addrs(rtm->rtm_addrs, cp, rti_info); 514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(rt, 0, sizeof(*rt)); 515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT(rt->dest, rti_info[RTAX_DST]); 516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_addrs & RTA_NETMASK) 517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT(rt->net, rti_info[RTAX_NETMASK]); 518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s_addr = INADDR_BROADCAST; 520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]); 521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_index) 523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index); 524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (rtm->rtm_addrs & RTA_IFP) { 525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_dl *sdl; 526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP]; 528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = if_findsdl(ctx, sdl); 529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If we don't have an interface and it's a host route, it maybe 531d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * to a local ip via the loopback interface. */ 532d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->iface == NULL && 533d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY))) 534d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 535d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ipv4_addr *ia; 536d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 537d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ia = ipv4_findaddr(ctx, &rt->dest))) 538d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = ia->iface; 539d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 541d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 542d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 544d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 545d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_route(unsigned char cmd, const struct rt *rt) 546d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 547d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_state *state; 548d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan union sockunion { 549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr sa; 550d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_in sin; 551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_dl sdl; 552d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } su; 553d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtm 554d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt_msghdr hdr; 556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buffer[sizeof(su) * RTAX_MAX]; 557d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } rtm; 558d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *bp = rtm.buffer; 559d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t l; 560d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, retval; 561d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDSU { \ 566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = RT_ROUNDUP(su.sa.sa_len); \ 567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(bp, &su, l); \ 568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bp += l; \ 569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDADDR(addr) { \ 571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&su, 0, sizeof(su)); \ 572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sin.sin_family = AF_INET; \ 573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sin.sin_len = sizeof(su.sin); \ 574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (&su.sin)->sin_addr = *addr; \ 575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDSU; \ 576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd != RTM_DELETE) 579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_CSTATE(rt->iface); 580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else /* appease GCC */ 581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = NULL; 582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&rtm, 0, sizeof(rtm)); 583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_version = RTM_VERSION; 584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_seq = 1; 585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_type = cmd; 586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs = RTA_DST; 587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_ADD || cmd == RTM_CHANGE) 588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_GATEWAY; 589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags = RTF_UP; 590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_PINNED 591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd != RTM_ADD) 592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_PINNED; 593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd != RTM_DELETE) { 596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP; 597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* None interface subnet routes are static. */ 598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->gate.s_addr != INADDR_ANY || 599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s_addr != state->net.s_addr || 600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr)) 601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_STATIC; 602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else { 603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_CLONING 604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_CLONING; 605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTP_CONNECTED 607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_priority = RTP_CONNECTED; 608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->net.s_addr == htonl(INADDR_BROADCAST) && 612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->gate.s_addr == htonl(INADDR_ANY)) 613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_CLONING 615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We add a cloning network route for a single host. 616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Traffic to the host will generate a cloned route and the 617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * hardware address will resolve correctly. 618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * It might be more correct to use RTF_HOST instead of 619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * RTF_CLONING, and that does work, but some OS generate 620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * an arp warning diagnostic which we don't want to do. */ 621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_CLONING; 622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_NETMASK; 623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_HOST; 625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) && 627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s_addr == htonl(INADDR_BROADCAST)) 628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY; 630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Going via lo0 so remove the interface flags */ 631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_ADD) 632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs &= ~(RTA_IFA | RTA_IFP); 633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_NETMASK; 635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_flags & RTF_STATIC) 636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_GATEWAY; 637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan !(rtm.hdr.rtm_flags & RTF_GATEWAY)) 640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP; 641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&rt->dest); 643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_GATEWAY) { 644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_CLONING 645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((rtm.hdr.rtm_flags & (RTF_HOST | RTF_CLONING) && 646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((rtm.hdr.rtm_flags & RTF_HOST && 648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->gate.s_addr != htonl(INADDR_LOOPBACK)) || 650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan !(rtm.hdr.rtm_flags & RTF_STATIC)) 651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if_linkaddr(&su.sdl, rt->iface); 653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDSU; 654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&rt->gate); 656d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 657d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 658d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_NETMASK) 659d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&rt->net); 660d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 661d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 662d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA))) 663d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 664d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_index = (unsigned short)rt->iface->index; 665d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_IFP) { 666d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if_linkaddr(&su.sdl, rt->iface); 667d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDSU; 668d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 669d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 670d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_IFA) 671d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&state->addr); 672d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 673d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 674d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef ADDADDR 675d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef ADDSU 676d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 677d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm); 678d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0; 679d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 680d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 681d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 682d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 683d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 684d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_initrt(struct interface *ifp) 685d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 686d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt_msghdr *rtm; 687d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int mib[6]; 688d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t needed; 689d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *buf, *p, *end; 690d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt rt; 691d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 692d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_freerts(ifp->ctx->ipv4_kroutes); 693d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 694d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[0] = CTL_NET; 695d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[1] = PF_ROUTE; 696d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[2] = 0; 697d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[3] = AF_INET; 698d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[4] = NET_RT_DUMP; 699d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[5] = 0; 700d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 701d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 702d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 703d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (needed == 0) 704d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 705d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((buf = malloc(needed)) == NULL) 706d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 707d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 708d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 709d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 710d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan end = buf + needed; 711d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (p = buf; p < end; p += rtm->rtm_msglen) { 712d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm = (struct rt_msghdr *)(void *)p; 713d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt(ifp->ctx, &rt, rtm) == 0) 714d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_handlert(ifp->ctx, RTM_ADD, &rt); 715d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 716d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(buf); 717d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 718d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 719d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 720d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SIOCGIFAFLAG_IN 721d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 722d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_addrflags(const struct in_addr *addr, const struct interface *ifp) 723d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 724d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, flags; 725d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifreq ifr; 726d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_in *sin; 727d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 728d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan s = socket(PF_INET, SOCK_DGRAM, 0); 729d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = -1; 730d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (s != -1) { 731d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifr, 0, sizeof(ifr)); 732d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 733d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr; 734d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin->sin_family = AF_INET; 735d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin->sin_addr = *addr; 736d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCGIFAFLAG_IN, &ifr) != -1) 737d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = ifr.ifr_addrflags; 738d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 739d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 740d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return flags; 741d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 742d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 743d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 744d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_addrflags(__unused const struct in_addr *addr, 745d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan __unused const struct interface *ifp) 746d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 747d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 748d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOTSUP; 749d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 750d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 751d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 752d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif /* INET */ 753d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 754d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 755d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 756d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex) 757d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 758d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 759d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef __KAME__ 760d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* KAME based systems want to store the scope inside the sin6_addr 761d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * for link local addreses */ 762d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { 763d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint16_t scope = htons((uint16_t)ifindex); 764d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&sin->sin6_addr.s6_addr[2], &scope, 765d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(scope)); 766d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 767d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin->sin6_scope_id = 0; 768d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 769d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) 770d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin->sin6_scope_id = ifindex; 771d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 772d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin->sin6_scope_id = 0; 773d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 774d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 775d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 776d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef __KAME__ 777d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DESCOPE(ia6) do { \ 778d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN6_IS_ADDR_LINKLOCAL((ia6))) \ 779d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (ia6)->s6_addr[2] = (ia6)->s6_addr[3] = '\0'; \ 780d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } while (/*CONSTCOND */0) 781d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 782d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DESCOPE(ia6) 783d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 784d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 785d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 786d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_address6(const struct ipv6_addr *a, int action) 787d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 788d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, r; 789d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_aliasreq ifa; 790d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_addr mask; 791d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 792d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) 793d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 794d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 795d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifa, 0, sizeof(ifa)); 796d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name)); 797d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* 798d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * We should not set IN6_IFF_TENTATIVE as the kernel should be 799d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * able to work out if it's a new address or not. 800d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 801d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * We should set IN6_IFF_AUTOCONF, but the kernel won't let us. 802d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * This is probably a safety measure, but still it's not entirely right 803d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * either. 804d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 805d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if 0 806d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (a->autoconf) 807d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa.ifra_flags |= IN6_IFF_AUTOCONF; 808d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 809d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6_MANGETEMPADDR 810d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (a->flags & IPV6_AF_TEMPORARY) 811d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa.ifra_flags |= IN6_IFF_TEMPORARY; 812d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 813d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 814d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDADDR(v, addr) { \ 815d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (v)->sin6_family = AF_INET6; \ 816d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (v)->sin6_len = sizeof(*v); \ 817d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (v)->sin6_addr = *addr; \ 818d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 819d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 820d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&ifa.ifra_addr, &a->addr); 821d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_scope(&ifa.ifra_addr, a->iface->index); 822d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_mask(&mask, a->prefix_len); 823d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&ifa.ifra_prefixmask, &mask); 824d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime; 825d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime; 826d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef ADDADDR 827d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 828d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa); 829d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 830d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 831d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 832d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 833d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 834d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 835d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm) 836d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 837d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *cp; 838d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr *sa, *rti_info[RTAX_MAX]; 839d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 840d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cp = (char *)(void *)(rtm + 1); 841d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sa = (struct sockaddr *)(void *)cp; 842d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sa->sa_family != AF_INET6) 843d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 844d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) 845d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 846d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_CLONED 847d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & (RTF_CLONED | RTF_HOST)) 848d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 849d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 850d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & RTF_HOST) 851d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 852d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 853d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_LOCAL 854d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & RTF_LOCAL) 855d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 856d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 857d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 858d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_addrs(rtm->rtm_addrs, cp, rti_info); 859d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(rt, 0, sizeof(*rt)); 860d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->flags = (unsigned int)rtm->rtm_flags; 861d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT6(rt->dest, rti_info[RTAX_DST]); 862d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_addrs & RTA_NETMASK) { 863d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* 864d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * We need to zero out the struct beyond sin6_len and 865d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ensure it's valid. 866d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * I have no idea what the invalid data is for, could be 867d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * a kernel bug or actually used for something. 868d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Either way it needs to be zeroed out. 869d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 870d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_in6 *sin6; 871d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t e, i, len = 0, final = 0; 872d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 873d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin6 = (struct sockaddr_in6 *)(void *)rti_info[RTAX_NETMASK]; 874d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net = sin6->sin6_addr; 875d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr); 876d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e > sizeof(struct in6_addr)) 877d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = sizeof(struct in6_addr); 878d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0; i < e; i++) { 879d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rt->net.s6_addr[i] & 0xff) { 880d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xff: 881d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We don't really want the length, 882d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * just that it's valid */ 883d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len++; 884d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 885d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xfe: 886d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xfc: 887d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xf8: 888d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xf0: 889d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xe0: 890d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0xc0: 891d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 0x80: 892d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len++; 893d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan final = 1; 894d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 895d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan default: 896d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s6_addr[i] = 0x00; 897d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan final = 1; 898d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 899d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 900d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (final) 901d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 902d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 903d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len == 0) 904d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i = 0; 905d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (i < sizeof(rt->net.s6_addr)) 906d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s6_addr[i++] = 0x00; 907d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 908d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_mask(&rt->net, 128); 909d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]); 910d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 911d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_index) 912d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index); 913d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (rtm->rtm_addrs & RTA_IFP) { 914d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_dl *sdl; 915d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 916d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP]; 917d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = if_findsdl(ctx, sdl); 918d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 919d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If we don't have an interface and it's a host route, it maybe 920d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * to a local ip via the loopback interface. */ 921d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->iface == NULL && 922d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY))) 923d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 924d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ipv6_addr *ia; 925d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 926d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ia = ipv6_findaddr(ctx, &rt->dest, 0))) 927d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = ia->iface; 928d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 929d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 930d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 931d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 932d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 933d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 934d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_route6(unsigned char cmd, const struct rt6 *rt) 935d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 936d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan union sockunion { 937d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr sa; 938d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_in6 sin; 939d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_dl sdl; 940d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } su; 941d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtm 942d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 943d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt_msghdr hdr; 944d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buffer[sizeof(su) * RTAX_MAX]; 945d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } rtm; 946d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *bp = rtm.buffer; 947d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t l; 948d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, retval; 949d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 950d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 951d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 952d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 953d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDSU { \ 954d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = RT_ROUNDUP(su.sa.sa_len); \ 955d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(bp, &su, l); \ 956d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bp += l; \ 957d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 958d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDADDRS(addr, scope) { \ 959d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&su, 0, sizeof(su)); \ 960d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sin.sin6_family = AF_INET6; \ 961d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sin.sin6_len = sizeof(su.sin); \ 962d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (&su.sin)->sin6_addr = *addr; \ 963d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (scope) \ 964d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_scope(&su.sin, scope); \ 965d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDSU; \ 966d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 967d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDADDR(addr) ADDADDRS(addr, 0) 968d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 969d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&rtm, 0, sizeof(rtm)); 970d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_version = RTM_VERSION; 971d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_seq = 1; 972d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_type = cmd; 973d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags = RTF_UP | (int)rt->flags; 974d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_PINNED 975d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_type != RTM_ADD) 976d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_PINNED; 977d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 978d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK; 979d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* None interface subnet routes are static. */ 980d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) { 981d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTF_CLONING 982d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_CLONING; 983d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 984d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTP_CONNECTED 985d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_priority = RTP_CONNECTED; 986d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 987d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 988d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC; 989d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 990d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_ADD) 991d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_GATEWAY; 992d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_ADD && !(rtm.hdr.rtm_flags & RTF_REJECT)) 993d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA; 994d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 995d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&rt->dest); 996d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_GATEWAY) { 997d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) { 998d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if_linkaddr(&su.sdl, rt->iface); 999d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDSU; 1000d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 1001d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDRS(&rt->gate, rt->iface->index); 1002d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1003d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1004d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1005d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_NETMASK) 1006d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDR(&rt->net); 1007d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1008d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 1009d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA))) 1010d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1011d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_index = (unsigned short)rt->iface->index; 1012d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_IFP) { 1013d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if_linkaddr(&su.sdl, rt->iface); 1014d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDSU; 1015d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1016d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1017d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm.hdr.rtm_addrs & RTA_IFA) { 1018d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct ipv6_addr *lla; 1019d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1020d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lla = ipv6_linklocal(rt->iface); 1021d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (lla == NULL) /* unlikely */ 1022d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1023d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ADDADDRS(&lla->addr, rt->iface->index); 1024d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1025d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1026d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->mtu) { 1027d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_inits |= RTV_MTU; 1028d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu; 1029d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1030d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1031d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1032d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef ADDADDR 1033d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#undef ADDSU 1034d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1035d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm); 1036d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0; 1037d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1038d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 1039d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1040d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1041d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1042d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_initrt6(struct interface *ifp) 1043d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1044d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt_msghdr *rtm; 1045d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int mib[6]; 1046d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t needed; 1047d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *buf, *p, *end; 1048d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt6 rt; 1049d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1050d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_freerts(&ifp->ctx->ipv6->kroutes); 1051d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1052d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[0] = CTL_NET; 1053d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[1] = PF_ROUTE; 1054d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[2] = 0; 1055d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[3] = AF_INET6; 1056d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[4] = NET_RT_DUMP; 1057d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[5] = 0; 1058d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1059d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 1060d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1061d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (needed == 0) 1062d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1063d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((buf = malloc(needed)) == NULL) 1064d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1065d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 1066d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1067d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1068d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan end = buf + needed; 1069d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (p = buf; p < end; p += rtm->rtm_msglen) { 1070d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm = (struct rt_msghdr *)(void *)p; 1071d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt6(ifp->ctx, &rt, rtm) == 0) 1072d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_handlert(ifp->ctx, RTM_ADD, &rt); 1073d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1074d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(buf); 1075d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1076d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1077d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1078d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1079d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_addrflags6(const struct in6_addr *addr, const struct interface *ifp) 1080d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1081d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, flags; 1082d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_ifreq ifr6; 1083d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1084d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan s = socket(PF_INET6, SOCK_DGRAM, 0); 1085d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = -1; 1086d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (s != -1) { 1087d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifr6, 0, sizeof(ifr6)); 1088d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name)); 1089d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifr6.ifr_addr.sin6_family = AF_INET6; 1090d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifr6.ifr_addr.sin6_addr = *addr; 1091d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_scope(&ifr6.ifr_addr, ifp->index); 1092d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1) 1093d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = ifr6.ifr_ifru.ifru_flags6; 1094d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1095d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1096d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return flags; 1097d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1098d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1099d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_getlifetime6(struct ipv6_addr *ia) 1101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, r; 1103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_ifreq ifr6; 1104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan s = socket(PF_INET6, SOCK_DGRAM, 0); 1106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = -1; 1107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (s != -1) { 1108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&ifr6, 0, sizeof(ifr6)); 1109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name)); 1110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifr6.ifr_addr.sin6_family = AF_INET6; 1111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifr6.ifr_addr.sin6_addr = ia->addr; 1112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_scope(&ifr6.ifr_addr, ia->iface->index); 1113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) != -1) { 1114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan time_t t; 1115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_addrlifetime *lifetime; 1116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t = time(NULL); 1118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lifetime = &ifr6.ifr_ifru.ifru_lifetime; 1119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (lifetime->ia6t_preferred) 1121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ia->prefix_pltime = 1122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (uint32_t)(lifetime->ia6t_preferred - 1123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan MIN(t, lifetime->ia6t_preferred)); 1124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ia->prefix_pltime = ND6_INFINITE_LIFETIME; 1126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (lifetime->ia6t_expire) { 1127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ia->prefix_vltime = 1128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (uint32_t)(lifetime->ia6t_expire - 1129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan MIN(t, lifetime->ia6t_expire)); 1130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Calculate the created time */ 1131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_monotonic(&ia->created); 1132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ia->created.tv_sec -= 1133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lifetime->ia6t_vltime - ia->prefix_vltime; 1134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 1135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ia->prefix_vltime = ND6_INFINITE_LIFETIME; 1136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = 0; 1138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 1142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_managelink(struct dhcpcd_ctx *ctx) 1147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* route and ifwatchd like a msg buf size of 2048 */ 1149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char msg[2048], *p, *e, *cp; 1150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t bytes; 1151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt_msghdr *rtm; 1152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct if_announcemsghdr *ifan; 1153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct if_msghdr *ifm; 1154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifa_msghdr *ifam; 1155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr *sa, *rti_info[RTAX_MAX]; 1156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int len; 1157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_dl sdl; 1158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct interface *ifp; 1159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 1160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt rt; 1161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 1163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt6 rt6; 1164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_addr ia6, net6; 1165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_in6 *sin6; 1166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if (defined(INET) && defined(IN_IFF_TENTATIVE)) || defined(INET6) 1168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int ifa_flags; 1169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((bytes = read(ctx->link_fd, msg, sizeof(msg))) == -1) 1172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = msg + bytes; 1174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (p = msg; p < e; p += rtm->rtm_msglen) { 1175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm = (struct rt_msghdr *)(void *)p; 1176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan // Ignore messages generated by us 1177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_pid == getpid()) 1178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch(rtm->rtm_type) { 1180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTM_IFANNOUNCE 1181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_IFANNOUNCE: 1182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifan = (struct if_announcemsghdr *)(void *)p; 1183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch(ifan->ifan_what) { 1184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFAN_ARRIVAL: 1185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, 1, 1186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifan->ifan_name); 1187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFAN_DEPARTURE: 1189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, -1, 1190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifan->ifan_name); 1191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_IFINFO: 1196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifm = (struct if_msghdr *)(void *)p; 1197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp = if_findindex(ctx->ifaces, ifm->ifm_index); 1198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp == NULL) 1199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (ifm->ifm_data.ifi_link_state) { 1201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case LINK_STATE_DOWN: 1202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = LINK_DOWN; 1203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case LINK_STATE_UP: 1205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = LINK_UP; 1206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan default: 1208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* handle_carrier will re-load 1209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * the interface flags and check for 1210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IFF_RUNNING as some drivers that 1211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * don't handle link state also don't 1212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * set IFF_RUNNING when this routing 1213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * message is generated. 1214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * As such, it is a race ...*/ 1215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = LINK_UNKNOWN; 1216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handlecarrier(ctx, len, 1219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (unsigned int)ifm->ifm_flags, ifp->name); 1220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_ADD: 1222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_CHANGE: 1223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_DELETE: 1224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cp = (char *)(void *)(rtm + 1); 1225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sa = (struct sockaddr *)(void *)cp; 1226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (sa->sa_family) { 1227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 1228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET: 1229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt(ctx, &rt, rtm) == 0) 1230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_handlert(ctx, rtm->rtm_type, &rt); 1231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 1234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET6: 1235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) 1236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* 1238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * BSD caches host routes in the 1239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * routing table. 1240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * As such, we should be notified of 1241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * reachability by its existance 1242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * with a hardware address 1243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 1244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_flags & (RTF_HOST)) { 1245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_addrs(rtm->rtm_addrs, cp, rti_info); 1246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT6(ia6, rti_info[RTAX_DST]); 1247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan DESCOPE(&ia6); 1248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rti_info[RTAX_GATEWAY]->sa_family 1249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan == AF_LINK) 1250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&sdl, 1251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rti_info[RTAX_GATEWAY], 1252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(sdl)); 1253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl.sdl_alen = 0; 1255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6nd_neighbour(ctx, &ia6, 1256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm->rtm_type != RTM_DELETE && 1257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl.sdl_alen ? 1258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan IPV6ND_REACHABLE : 0); 1259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt6(ctx, &rt6, rtm) == 0) 1263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_handlert(ctx, rtm->rtm_type, &rt6); 1264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTM_CHGADDR 1269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_CHGADDR: /* FALLTHROUGH */ 1270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_DELADDR: /* FALLTHROUGH */ 1272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_NEWADDR: 1273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifam = (struct ifa_msghdr *)(void *)p; 1274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp = if_findindex(ctx->ifaces, ifam->ifam_index); 1275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp == NULL) 1276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cp = (char *)(void *)(ifam + 1); 1278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_addrs(ifam->ifam_addrs, cp, rti_info); 1279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rti_info[RTAX_IFA] == NULL) 1280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rti_info[RTAX_IFA]->sa_family) { 1282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_LINK: 1283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef RTM_CHGADDR 1284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_type != RTM_CHGADDR) 1285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_type != RTM_NEWADDR) 1288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&sdl, rti_info[RTAX_IFA], 1291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rti_info[RTAX_IFA]->sa_len); 1292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handlehwaddr(ctx, ifp->name, 1293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (const unsigned char*)CLLADDR(&sdl), 1294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sdl.sdl_alen); 1295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 1297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET: 1298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case 255: /* FIXME: Why 255? */ 1299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT(rt.dest, rti_info[RTAX_IFA]); 1300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT(rt.net, rti_info[RTAX_NETMASK]); 1301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan COPYOUT(rt.gate, rti_info[RTAX_BRD]); 1302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_type == RTM_NEWADDR) { 1303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_flags = if_addrflags(&rt.dest, ifp); 1304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifa_flags == -1) 1305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 1307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_flags = 0; 1308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_handleifa(ctx, rtm->rtm_type, 1309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NULL, ifp->name, 1310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &rt.dest, &rt.net, &rt.gate, ifa_flags); 1311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 1314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET6: 1315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin6 = (struct sockaddr_in6*)(void *) 1316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rti_info[RTAX_IFA]; 1317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ia6 = sin6->sin6_addr; 1318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan DESCOPE(&ia6); 1319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sin6 = (struct sockaddr_in6*)(void *) 1320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rti_info[RTAX_NETMASK]; 1321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan net6 = sin6->sin6_addr; 1322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan DESCOPE(&net6); 1323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_type == RTM_NEWADDR) { 1324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_flags = if_addrflags6(&ia6, ifp); 1325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifa_flags == -1) 1326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 1328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_flags = 0; 1329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_handleifa(ctx, rtm->rtm_type, NULL, 1330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name, &ia6, ipv6_prefixlen(&net6), 1331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa_flags); 1332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef SYS_NMLN /* OSX */ 1342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# define SYS_NMLN 256 1343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef HW_MACHINE_ARCH 1345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# ifdef HW_MODEL /* OpenBSD */ 1346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# define HW_MACHINE_ARCH HW_MODEL 1347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# endif 1348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_machinearch(char *str, size_t len) 1351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 1353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char march[SYS_NMLN]; 1354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t marchlen = sizeof(march); 1355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 1357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan march, &marchlen, NULL, 0) != 0) 1358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return snprintf(str, len, ":%s", march); 1360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 1363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6CTL_ACCEPT_RTADV 1364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0) 1365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1) 1366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taninet6_sysctl(int code, int val, int action) 1368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 1370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t size; 1371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan mib[3] = code; 1373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size = sizeof(val); 1374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action) { 1375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), 1376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NULL, 0, &val, size) == -1) 1377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1) 1381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val; 1383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6_MANAGETEMPADDR 1387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef IPV6CTL_TEMPVLTIME 1388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) 1389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1) 1390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taninet6_sysctlbyname(const char *name, int val, int action) 1392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t size; 1394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size = sizeof(val); 1396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action) { 1397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctlbyname(name, NULL, 0, &val, size) == -1) 1398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sysctlbyname(name, &val, &size, NULL, 0) == -1) 1402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val; 1404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanip6_use_tempaddr(__unused const char *ifname) 1409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int val; 1411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6CTL_USETEMPADDR 1413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = get_inet6_sysctl(IPV6CTL_USETEMPADDR); 1414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = get_inet6_sysctlbyname("net.inet6.ip6.use_tempaddr"); 1416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val == -1 ? 0 : val; 1418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanip6_temp_preferred_lifetime(__unused const char *ifname) 1422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int val; 1424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6CTL_TEMPPLTIME 1426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = get_inet6_sysctl(IPV6CTL_TEMPPLTIME); 1427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = get_inet6_sysctlbyname("net.inet6.ip6.temppltime"); 1429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val < 0 ? TEMP_PREFERRED_LIFETIME : val; 1431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanip6_temp_valid_lifetime(__unused const char *ifname) 1435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int val; 1437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6CTL_TEMPVLTIME 1439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = get_inet6_sysctl(IPV6CTL_TEMPVLTIME); 1440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = get_inet6_sysctlbyname("net.inet6.ip6.tempvltime"); 1442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val < 0 ? TEMP_VALID_LIFETIME : val; 1444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define del_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), -1) 1448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define get_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), 0) 1449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define set_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), 1) 1450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_nd6_flag(int s, const struct interface *ifp, unsigned int flag, int set) 1452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_ndireq nd; 1454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned int oflags; 1455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nd, 0, sizeof(nd)); 1457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname)); 1458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1) 1459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (set == 0) 1461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return nd.ndi.flags & flag ? 1 : 0; 1462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan oflags = nd.ndi.flags; 1464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (set == -1) 1465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nd.ndi.flags &= ~flag; 1466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nd.ndi.flags |= flag; 1468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (oflags == nd.ndi.flags) 1469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ioctl(s, SIOCSIFINFO_FLAGS, &nd); 1471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_raflush(int s) 1475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char dummy[IFNAMSIZ + 8]; 1477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(dummy, "lo0", sizeof(dummy)); 1479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCSRTRFLUSH_IN6, (void *)&dummy) == -1 || 1480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&dummy) == -1) 1481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SIOCIFAFATTACH 1486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanaf_attach(int s, const struct interface *ifp, int af) 1488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct if_afreq ifar; 1490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name)); 1492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifar.ifar_af = af; 1493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ioctl(s, SIOCIFAFATTACH, (void *)&ifar); 1494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SIOCGIFXFLAGS 1498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanset_ifxflags(int s, const struct interface *ifp, int own) 1500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifreq ifr; 1502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int flags; 1503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef IFXF_NOINET6 1505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* No point in removing the no inet6 flag if it doesn't 1506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * exist and we're not owning inet6. */ 1507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (! own) 1508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 1512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ioctl(s, SIOCGIFXFLAGS, (void *)&ifr) == -1) 1513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = ifr.ifr_flags; 1515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IFXF_NOINET6 1516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags &= ~IFXF_NOINET6; 1517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (own) 1519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags &= ~IFXF_AUTOCONF6; 1520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifr.ifr_flags == flags) 1521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifr.ifr_flags = flags; 1523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr); 1524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan_if_checkipv6(int s, struct dhcpcd_ctx *ctx, 1529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct interface *ifp, int own) 1530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1531d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int ra; 1532d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1533d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp) { 1534d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_OVERRIDE_RTADV 1535d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int override; 1536d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1537d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1538d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_IFDISABLED 1539d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (del_if_nd6_flag(s, ifp, ND6_IFF_IFDISABLED) == -1) { 1540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1541d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: del_if_nd6_flag: ND6_IFF_IFDISABLED: %m", 1542d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1544d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1545d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1546d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1547d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_PERFORMNUD 1548d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (set_if_nd6_flag(s, ifp, ND6_IFF_PERFORMNUD) == -1) { 1549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1550d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: set_if_nd6_flag: ND6_IFF_PERFORMNUD: %m", 1551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1552d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1553d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1554d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_AUTO_LINKLOCAL 1557d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (own) { 1558d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int all; 1559d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1560d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan all = get_if_nd6_flag(s, ifp, ND6_IFF_AUTO_LINKLOCAL); 1561d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (all == -1) 1562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: get_if_nd6_flag: " 1564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "ND6_IFF_AUTO_LINKLOCAL: %m", 1565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (all != 0) { 1567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_DEBUG, 1568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: disabling Kernel IPv6 " 1569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "auto link-local support", 1570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (del_if_nd6_flag(s, ifp, 1572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ND6_IFF_AUTO_LINKLOCAL) == -1) 1573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: del_if_nd6_flag: " 1576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "ND6_IFF_AUTO_LINKLOCAL: %m", 1577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SIOCIFAFATTACH 1585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (af_attach(s, ifp, AF_INET6) == -1) { 1586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: af_attach: %m", ifp->name); 1588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 1589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SIOCGIFXFLAGS 1593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (set_ifxflags(s, ifp, own) == -1) { 1594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: set_ifxflags: %m", ifp->name); 1596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_OVERRIDE_RTADV 1601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan override = get_if_nd6_flag(s, ifp, ND6_IFF_OVERRIDE_RTADV); 1602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (override == -1) 1603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: get_if_nd6_flag: ND6_IFF_OVERRIDE_RTADV: %m", 1605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (override == 0 && own) { 1607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (set_if_nd6_flag(s, ifp, ND6_IFF_OVERRIDE_RTADV) 1608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan == -1) 1609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: set_if_nd6_flag: " 1611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "ND6_IFF_OVERRIDE_RTADV: %m", 1612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan override = 1; 1615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_ACCEPT_RTADV 1619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = get_if_nd6_flag(s, ifp, ND6_IFF_ACCEPT_RTADV); 1620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ra == -1) 1621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: get_if_nd6_flag: ND6_IFF_ACCEPT_RTADV: %m", 1623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (ra != 0 && own) { 1625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_DEBUG, 1626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: disabling Kernel IPv6 RA support", 1627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (del_if_nd6_flag(s, ifp, ND6_IFF_ACCEPT_RTADV) 1629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan == -1) 1630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 1631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: del_if_nd6_flag: " 1632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "ND6_IFF_ACCEPT_RTADV: %m", 1633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 1634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = 0; 1636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (ra == 0 && !own) 1637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_WARNING, 1638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: IPv6 kernel autoconf disabled", ifp->name); 1639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef ND6_IFF_OVERRIDE_RTADV 1640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (override == 0 && ra) 1641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ctx->ra_global; 1642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ra; 1644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ctx->ra_global; 1646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6CTL_ACCEPT_RTADV 1650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV); 1651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ra == -1) 1652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* The sysctl probably doesn't exist, but this isn't an 1653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * error as such so just log it and continue */ 1654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, errno == ENOENT ? LOG_DEBUG : LOG_WARNING, 1655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "IPV6CTL_ACCEPT_RTADV: %m"); 1656d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (ra != 0 && own) { 1657d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_DEBUG, "disabling Kernel IPv6 RA support"); 1658d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) { 1659d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m"); 1660d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ra; 1661d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1662d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = 0; 1663d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1664d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = 0; 1665d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (own) { 1666d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1667d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Flush the kernel knowledge of advertised routers 1668d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * and prefixes so the kernel does not expire prefixes 1669d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * and default routes we are trying to own. */ 1670d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_raflush(s) == -1) 1671d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_WARNING, "if_raflush: %m"); 1672d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1673d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1674d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->ra_global = ra; 1675d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ra; 1676d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1677d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1678d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1679d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own) 1680d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1681d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, r; 1682d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1683d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) 1684d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1685d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = _if_checkipv6(s, ctx, ifp, own); 1686d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1687d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 1688d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1689d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1690