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 <asm/types.h> /* Needed for 2.4 kernels */ 29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/types.h> 31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/socket.h> 32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/ioctl.h> 33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/param.h> 34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/if_addr.h> 36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/if_link.h> 37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/if_packet.h> 38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/filter.h> 39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/netlink.h> 40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/rtnetlink.h> 41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <arpa/inet.h> 43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if.h> 44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/if_ether.h> 45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/in_systm.h> 46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/in.h> 47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/route.h> 48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Support older kernels */ 50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef IFLA_WIRELESS 51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# define IFLA_WIRELESS (IFLA_MASTER + 1) 52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Linux has these in an enum and there is just no way to work 55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * out of they exist at compile time. Silly silly silly. */ 56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define IFLA_AF_SPEC 26 57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define IFLA_INET6_ADDR_GEN_MODE 8 58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define IN6_ADDR_GEN_MODE_NONE 1 59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* For some reason, glibc doesn't include newer flags from linux/if.h 61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * However, we cannot include linux/if.h directly as it conflicts 62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * with the glibc version. D'oh! */ 63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef IFF_LOWER_UP 64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ 65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h> 68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <fcntl.h> 69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <ctype.h> 70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stddef.h> 71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdio.h> 72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h> 73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h> 74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <time.h> 75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h> 76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h" 78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h" 79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dev.h" 80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h" 81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h" 82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv4.h" 83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv6.h" 84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv6nd.h" 85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef HAVE_NL80211_H 87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/genetlink.h> 88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <linux/nl80211.h> 89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint if_getssid_wext(const char *ifname, uint8_t *ssid); 91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define bpf_insn sock_filter 93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define BPF_SKIPTYPE 94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define BPF_ETHCOOK -ETH_HLEN 95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define BPF_WHOLEPACKET 0x0fffffff /* work around buggy LPF filters */ 96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "bpf-filter.h" 98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Broadcast address for IPoIB */ 100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic const uint8_t ipv4_bcast_addr[] = { 101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0x00, 0xff, 0xff, 0xff, 102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff 104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}; 105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define PROC_INET6 "/proc/net/if_inet6" 107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define PROC_PROMOTE "/proc/sys/net/ipv4/conf/%s/promote_secondaries" 108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define SYS_LAYER2 "/sys/class/net/%s/device/layer2" 109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic const char *mproc = 111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(__alpha__) 112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "system type" 113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__arm__) 114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "Hardware" 115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__avr32__) 116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "cpu family" 117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__bfin__) 118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "BOARD Name" 119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__cris__) 120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "cpu model" 121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__frv__) 122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "System" 123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__i386__) || defined(__x86_64__) 124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "vendor_id" 125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__ia64__) 126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "vendor" 127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__hppa__) 128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "model" 129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__m68k__) 130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "MMU" 131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__mips__) 132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "system type" 133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__powerpc__) || defined(__powerpc64__) 134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "machine" 135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__s390__) || defined(__s390x__) 136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "Manufacturer" 137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__sh__) 138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "machine" 139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(sparc) || defined(__sparc__) 140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "cpu" 141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(__vax__) 142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "cpu" 143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NULL 145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ; 147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_machinearch(char *str, size_t len) 150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan FILE *fp; 152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buf[256]; 153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (mproc == NULL) { 155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fp = fopen("/proc/cpuinfo", "r"); 160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fp == NULL) 161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (fscanf(fp, "%255s : ", buf) != EOF) { 164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (strncmp(buf, mproc, strlen(mproc)) == 0 && 165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fscanf(fp, "%255s", buf) == 1) 166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return snprintf(str, len, ":%s", buf); 169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ESRCH; 173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tancheck_proc_int(const char *path) 178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan FILE *fp; 180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int i; 181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fp = fopen(path, "r"); 183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fp == NULL) 184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fscanf(fp, "%d", &i) != 1) 186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i = -1; 187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return i; 189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic ssize_t 192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanwrite_path(const char *path, const char *val) 193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan FILE *fp; 195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t r; 196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fp = fopen(path, "w"); 198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fp == NULL) 199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = fprintf(fp, "%s\n", val); 201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_init(struct interface *ifp) 207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char path[sizeof(PROC_PROMOTE) + IF_NAMESIZE]; 209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int n; 210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We enable promote_secondaries so that we can do this 212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * add 192.168.1.2/24 213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * add 192.168.1.3/24 214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * del 192.168.1.2/24 215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * and the subnet mask moves onto 192.168.1.3/24 216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * This matches the behaviour of BSD which makes coding dhcpcd 217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * a little easier as there's just one behaviour. */ 218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), PROC_PROMOTE, ifp->name); 219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = check_proc_int(path); 220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n == -1) 221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return errno == ENOENT ? 0 : -1; 222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n == 1) 223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return write_path(path, "1") == -1 ? -1 : 0; 225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_conf(struct interface *ifp) 229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char path[sizeof(SYS_LAYER2) + IF_NAMESIZE]; 231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int n; 232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Some qeth setups require the use of the broadcast flag. */ 234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), SYS_LAYER2, ifp->name); 235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = check_proc_int(path); 236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n == -1) 237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return errno == ENOENT ? 0 : -1; 238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n == 0) 239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->options->options |= DHCPCD_BROADCAST; 240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* XXX work out Virtal Interface Masters */ 244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_vimaster(__unused const char *ifname) 246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan_open_link_socket(struct sockaddr_nl *nl, int flags, int protocol) 253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int fd; 255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SOCK_CLOEXEC 257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (flags) 258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = SOCK_CLOEXEC; 259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol); 260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fd == -1) 261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fd == -1) 265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (flags && 267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (flags = fcntl(fd, F_GETFD, 0)) == -1 || 268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) 269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(fd); 271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nl->nl_family = AF_NETLINK; 275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) { 276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(fd); 277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return fd; 280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_openlinksocket(void) 284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_nl snl; 286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&snl, 0, sizeof(snl)); 288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snl.nl_groups = RTMGRP_LINK; 289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snl.nl_groups |= RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; 292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snl.nl_groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH; 295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return _open_link_socket(&snl, 1, NETLINK_ROUTE); 298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanerr_netlink(struct nlmsghdr *nlm) 302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsgerr *err; 304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type != NLMSG_ERROR) 307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - sizeof(*nlm); 309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < sizeof(*err)) { 310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EBADMSG; 311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan err = (struct nlmsgerr *)NLMSG_DATA(nlm); 314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (err->error == 0) 315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (int)len; 316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = -err->error; 317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanget_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, int fd, int flags, 322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *)) 323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *buf = NULL, *nbuf; 325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t bytes; 326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t buflen; 327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm; 328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_nl nladdr; 329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan socklen_t nladdr_len; 330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int r; 331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan buflen = 0; 333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = -1; 334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (;;) { 335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = recv(fd, NULL, 0, 336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC); 337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes == -1) 338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((size_t)bytes == buflen) { 340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Support kernels older than 2.6.22 */ 341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes == 0) 342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = 512; 343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes *= 2; 345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (buflen < (size_t)bytes) { 347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Alloc 1 more so we work with older kernels */ 348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan buflen = (size_t)bytes + 1; 349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nbuf = realloc(buf, buflen); 350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nbuf == NULL) 351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan buf = nbuf; 353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nladdr_len = sizeof(nladdr); 355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = recvfrom(fd, buf, buflen, flags, 356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (struct sockaddr *)&nladdr, &nladdr_len); 357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes == -1 || bytes == 0) 358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Check sender */ 361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nladdr_len != sizeof(nladdr)) { 362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Ignore message if it is not from kernel */ 366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nladdr.nl_pid != 0) { 367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = 0; 368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (nlm = (struct nlmsghdr *)(void *)buf; 372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm && NLMSG_OK(nlm, (size_t)bytes); 373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm = NLMSG_NEXT(nlm, bytes)) 374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = err_netlink(nlm); 376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r == -1) 377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r) 379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (callback) { 381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = callback(ctx, ifp, nlm); 382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != 0) 383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneexit: 389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(buf); 390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm) 396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtmsg *rtm; 399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta; 400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in_addr prefsrc; 401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - sizeof(*nlm); 403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < sizeof(*rtm)) { 404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EBADMSG; 405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm = (struct rtmsg *)NLMSG_DATA(nlm); 408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET) 409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(rt, 0, sizeof(*rt)); 412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_type == RTN_UNREACHABLE) 413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->flags = RTF_REJECT; 414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_scope == RT_SCOPE_HOST) 415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->flags |= RTF_HOST; 416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan prefsrc.s_addr = INADDR_ANY; 418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = (struct rtattr *)RTM_RTA(rtm); 419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = RTM_PAYLOAD(nlm); 420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (RTA_OK(rta, len)) { 421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rta->rta_type) { 422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_DST: 423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&rt->dest.s_addr, RTA_DATA(rta), 424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(rt->dest.s_addr)); 425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_GATEWAY: 427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&rt->gate.s_addr, RTA_DATA(rta), 428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(rt->gate.s_addr)); 429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_PREFSRC: 431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&prefsrc.s_addr, RTA_DATA(rta), 432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(prefsrc.s_addr)); 433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_OIF: 435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = if_findindex(ctx->ifaces, 436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *(unsigned int *)RTA_DATA(rta)); 437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_PRIORITY: 439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->metric = *(unsigned int *)RTA_DATA(rta); 440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = RTA_NEXT(rta, len); 443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan inet_cidrtoaddr(rtm->rtm_dst_len, &rt->net); 446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->iface == NULL && prefsrc.s_addr != INADDR_ANY) { 447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ipv4_addr *ap; 448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* For some reason the default route comes back with the 450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * loopback interface in RTA_OIF? Lets find it by 451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * preferred source address */ 452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ap = ipv4_findaddr(ctx, &prefsrc))) 453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = ap->iface; 454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct nlmsghdr *nlm) 462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtmsg *rtm; 465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta; 466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - sizeof(*nlm); 468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < sizeof(*rtm)) { 469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EBADMSG; 470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm = (struct rtmsg *)NLMSG_DATA(nlm); 473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET6) 474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(rt, 0, sizeof(*rt)); 477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_type == RTN_UNREACHABLE) 478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->flags = RTF_REJECT; 479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rtm->rtm_scope == RT_SCOPE_HOST) 480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->flags |= RTF_HOST; 481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_mask(&rt->net, rtm->rtm_dst_len); 482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = (struct rtattr *)RTM_RTA(rtm); 484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = RTM_PAYLOAD(nlm); 485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (RTA_OK(rta, len)) { 486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rta->rta_type) { 487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_DST: 488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&rt->dest.s6_addr, RTA_DATA(rta), 489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(rt->dest.s6_addr)); 490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_GATEWAY: 492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&rt->gate.s6_addr, RTA_DATA(rta), 493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(rt->gate.s6_addr)); 494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_OIF: 496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->iface = if_findindex(ctx->ifaces, 497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *(unsigned int *)RTA_DATA(rta)); 498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTA_PRIORITY: 500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->metric = *(unsigned int *)RTA_DATA(rta); 501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = RTA_NEXT(rta, len); 504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Work out the maximum pid size */ 511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic inline long long 512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanget_max_pid_t() 513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sizeof(pid_t) == sizeof(short)) return SHRT_MAX; 516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sizeof(pid_t) == sizeof(int)) return INT_MAX; 517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sizeof(pid_t) == sizeof(long)) return LONG_MAX; 518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sizeof(pid_t) == sizeof(long long)) return LLONG_MAX; 519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan abort(); 520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanlink_route(struct dhcpcd_ctx *ctx, __unused struct interface *ifp, 524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtmsg *rtm; 528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int cmd; 529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt rt; 531d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 532d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 533d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt6 rt6; 534d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 535d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (nlm->nlmsg_type) { 536d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_NEWROUTE: 537d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cmd = RTM_ADD; 538d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 539d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_DELROUTE: 540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cmd = RTM_DELETE; 541d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 542d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan default: 543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 544d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 545d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 546d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - sizeof(*nlm); 547d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < sizeof(*rtm)) { 548d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EBADMSG; 549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 550d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 552d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Ignore messages generated by us. 553d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * For some reason we get messages generated by us 554d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * with a very large value in nlmsg_pid that seems to be 555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * sequentially changing. Is there a better test for this? */ 556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_pid > get_max_pid_t()) 557d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 558d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 559d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rtm = NLMSG_DATA(nlm); 560d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rtm->rtm_family) { 561d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET: 563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt(ctx, &rt, nlm) == 0) 564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_handlert(ctx, cmd, &rt); 565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET6: 569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt6(ctx, &rt6, nlm) == 0) 570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_handlert(ctx, cmd, &rt6); 571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanlink_addr(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nlmsghdr *nlm) 580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta; 583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifaddrmsg *ifa; 584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in_addr addr, net, dest; 586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_addr addr6; 589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR) 592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - sizeof(*nlm); 595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < sizeof(*ifa)) { 596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EBADMSG; 597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifa = NLMSG_DATA(nlm); 600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ifp = if_findindex(ctx->ifaces, ifa->ifa_index)) == NULL) { 601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We don't know about the interface the address is for 602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * so it's not really an error */ 603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = (struct rtattr *)IFA_RTA(ifa); 606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = NLMSG_PAYLOAD(nlm, sizeof(*ifa)); 607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (ifa->ifa_family) { 608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET: 610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan addr.s_addr = dest.s_addr = INADDR_ANY; 611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dest.s_addr = INADDR_ANY; 612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan inet_cidrtoaddr(ifa->ifa_prefixlen, &net); 613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (RTA_OK(rta, len)) { 614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rta->rta_type) { 615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFA_ADDRESS: 616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->flags & IFF_POINTOPOINT) { 617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&dest.s_addr, RTA_DATA(rta), 618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(addr.s_addr)); 619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFA_LOCAL: 622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&addr.s_addr, RTA_DATA(rta), 623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(addr.s_addr)); 624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = RTA_NEXT(rta, len); 627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name, 629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &addr, &net, &dest, ifa->ifa_flags); 630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case AF_INET6: 634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&addr6, 0, sizeof(addr6)); 635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (RTA_OK(rta, len)) { 636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rta->rta_type) { 637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFA_ADDRESS: 638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&addr6.s6_addr, RTA_DATA(rta), 639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(addr6.s6_addr)); 640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = RTA_NEXT(rta, len); 643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name, 645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &addr6, ifa->ifa_prefixlen, ifa->ifa_flags); 646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic uint8_t 653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanl2addr_len(unsigned short if_type) 654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 656d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (if_type) { 657d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case ARPHRD_ETHER: /* FALLTHROUGH */ 658d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case ARPHRD_IEEE802: /*FALLTHROUGH */ 659d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case ARPHRD_IEEE80211: 660d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 6; 661d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case ARPHRD_IEEE1394: 662d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 8; 663d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case ARPHRD_INFINIBAND: 664d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 20; 665d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 666d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 667d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Impossible */ 668d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 669d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 670d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 671d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 672d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanhandle_rename(struct dhcpcd_ctx *ctx, unsigned int ifindex, const char *ifname) 673d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 674d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct interface *ifp; 675d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 676d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(ifp, ctx->ifaces, next) { 677d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->index == ifindex && strcmp(ifp->name, ifname)) { 678d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, -1, ifp->name); 679d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Let dev announce the interface for renaming */ 680d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!dev_listening(ctx)) 681d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, 1, ifname); 682d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 683d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 684d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 685d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 686d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 687d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 688d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 689d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 690d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanlink_neigh(struct dhcpcd_ctx *ctx, __unused struct interface *ifp, 691d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 692d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 693d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ndmsg *r; 694d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta; 695d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 696d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in6_addr addr6; 697d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int flags; 698d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 699d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type != RTM_NEWNEIGH && nlm->nlmsg_type != RTM_DELNEIGH) 700d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 701d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_len < sizeof(*r)) 702d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 703d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 704d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = NLMSG_DATA(nlm); 705d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = (struct rtattr *)RTM_RTA(r); 706d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = RTM_PAYLOAD(nlm); 707d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r->ndm_family == AF_INET6) { 708d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags = 0; 709d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r->ndm_flags & NTF_ROUTER) 710d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags |= IPV6ND_ROUTER; 711d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type == RTM_NEWNEIGH && 712d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r->ndm_state & 713d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE | 714d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NUD_PERMANENT)) 715d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags |= IPV6ND_REACHABLE; 716d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&addr6, 0, sizeof(addr6)); 717d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (RTA_OK(rta, len)) { 718d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rta->rta_type) { 719d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case NDA_DST: 720d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&addr6.s6_addr, RTA_DATA(rta), 721d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(addr6.s6_addr)); 722d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 723d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 724d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = RTA_NEXT(rta, len); 725d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 726d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6nd_neighbour(ctx, &addr6, flags); 727d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 728d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 729d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 730d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 731d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 732d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 733d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 734d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanlink_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, 735d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 736d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 737d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int r; 738d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 739d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta, *hwaddr; 740d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifinfomsg *ifi; 741d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char ifn[IF_NAMESIZE + 1]; 742d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 743d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = link_route(ctx, ifp, nlm); 744d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != 0) 745d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 746d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = link_addr(ctx, ifp, nlm); 747d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != 0) 748d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 749d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 750d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = link_neigh(ctx, ifp, nlm); 751d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != 0) 752d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 753d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 754d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 755d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) 756d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 757d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - sizeof(*nlm); 758d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((size_t)len < sizeof(*ifi)) { 759d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EBADMSG; 760d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 761d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 762d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifi = NLMSG_DATA(nlm); 763d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifi->ifi_flags & IFF_LOOPBACK) 764d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 765d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = (struct rtattr *)(void *)((char *)ifi +NLMSG_ALIGN(sizeof(*ifi))); 766d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); 767d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *ifn = '\0'; 768d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hwaddr = NULL; 769d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 770d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (RTA_OK(rta, len)) { 771d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (rta->rta_type) { 772d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFLA_WIRELESS: 773d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Ignore wireless messages */ 774d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type == RTM_NEWLINK && 775d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifi->ifi_change == 0) 776d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 777d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 778d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFLA_IFNAME: 779d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); 780d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 781d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case IFLA_ADDRESS: 782d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hwaddr = rta; 783d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 784d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 785d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = RTA_NEXT(rta, len); 786d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 787d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 788d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm->nlmsg_type == RTM_DELLINK) { 789d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, -1, ifn); 790d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 791d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 792d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 793d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Virtual interfaces may not get a valid hardware address 794d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * at this point. 795d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * To trigger a valid hardware address pickup we need to pretend 796d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * that that don't exist until they have one. */ 797d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifi->ifi_flags & IFF_MASTER && !hwaddr) { 798d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, -1, ifn); 799d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 800d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 801d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 802d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Check for interface name change */ 803d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (handle_rename(ctx, (unsigned int)ifi->ifi_index, ifn)) 804d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 805d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 806d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Check for a new interface */ 807d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ifp = if_find(ctx->ifaces, ifn)) == NULL) { 808d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If are listening to a dev manager, let that announce 809d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * the interface rather than the kernel. */ 810d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dev_listening(ctx) < 1) 811d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handleinterface(ctx, 1, ifn); 812d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 813d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 814d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 815d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Re-read hardware address and friends */ 816d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!(ifi->ifi_flags & IFF_UP) && hwaddr) { 817d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t l; 818d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 819d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = l2addr_len(ifi->ifi_type); 820d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (hwaddr->rta_len == RTA_LENGTH(l)) 821d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handlehwaddr(ctx, ifn, RTA_DATA(hwaddr), l); 822d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 823d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 824d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handlecarrier(ctx, 825d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN, 826d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifi->ifi_flags, ifn); 827d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 828d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 829d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 830d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 831d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_managelink(struct dhcpcd_ctx *ctx) 832d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 833d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 834d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return get_netlink(ctx, NULL, 835d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->link_fd, MSG_DONTWAIT, &link_netlink); 836d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 837d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 838d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 839d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tansend_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, 840d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int protocol, struct nlmsghdr *hdr, 841d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *)) 842d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 843d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s, r; 844d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_nl snl; 845d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct iovec iov; 846d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct msghdr msg; 847d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan static unsigned int seq; 848d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 849d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&snl, 0, sizeof(snl)); 850d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = _open_link_socket(&snl, 0, protocol)) == -1) 851d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 852d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&iov, 0, sizeof(iov)); 853d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iov.iov_base = hdr; 854d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iov.iov_len = hdr->nlmsg_len; 855d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&msg, 0, sizeof(msg)); 856d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan msg.msg_name = &snl; 857d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan msg.msg_namelen = sizeof(snl); 858d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan msg.msg_iov = &iov; 859d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan msg.msg_iovlen = 1; 860d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Request a reply */ 861d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hdr->nlmsg_flags |= NLM_F_ACK; 862d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hdr->nlmsg_seq = ++seq; 863d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 864d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sendmsg(s, &msg, 0) != -1) 865d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = get_netlink(ctx, ifp, s, 0, callback); 866d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 867d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = -1; 868d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 869d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 870d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 871d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 872d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define NLMSG_TAIL(nmsg) \ 873d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len))) 874d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 875d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 876d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanadd_attr_l(struct nlmsghdr *n, unsigned short maxlen, unsigned short type, 877d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const void *data, unsigned short alen) 878d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 879d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short len = (unsigned short)RTA_LENGTH(alen); 880d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta; 881d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 882d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 883d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 884d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 885d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 886d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 887d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = NLMSG_TAIL(n); 888d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta->rta_type = type; 889d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta->rta_len = len; 890d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (alen) 891d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(RTA_DATA(rta), data, alen); 892d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 893d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 894d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 895d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 896d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 897d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 898d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanadd_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type, 899d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint32_t data) 900d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 901d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short len = RTA_LENGTH(sizeof(data)); 902d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *rta; 903d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 904d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 905d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 906d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 907d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 908d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 909d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta = NLMSG_TAIL(n); 910d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta->rta_type = type; 911d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta->rta_len = len; 912d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(RTA_DATA(rta), &data, sizeof(data)); 913d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 914d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 915d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 916d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 917d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 918d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef HAVE_NL80211_H 919d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic struct nlattr * 920d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tannla_next(struct nlattr *nla, size_t *rem) 921d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 922d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 923d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *rem -= NLA_ALIGN(nla->nla_len); 924d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (struct nlattr *)(void *)((char *)nla + NLA_ALIGN(nla->nla_len)); 925d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 926d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 927d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define NLA_TYPE(nla) ((nla)->nla_type & NLA_TYPE_MASK) 928d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define NLA_LEN(nla) (unsigned int)((nla)->nla_len - NLA_HDRLEN) 929d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define NLA_OK(nla, rem) \ 930d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ((rem) >= sizeof(struct nlattr) && \ 931d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (nla)->nla_len >= sizeof(struct nlattr) && \ 932d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (nla)->nla_len <= rem) 933d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define NLA_DATA(nla) ((char *)(nla) + NLA_HDRLEN) 934d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define NLA_FOR_EACH_ATTR(pos, head, len, rem) \ 935d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (pos = head, rem = len; NLA_OK(pos, rem); pos = nla_next(pos, &(rem))) 936d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 937d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct nlmg 938d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 939d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr hdr; 940d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct genlmsghdr ghdr; 941d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buffer[64]; 942d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}; 943d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 944d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 945d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tannla_put_32(struct nlmsghdr *n, unsigned short maxlen, 946d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short type, uint32_t data) 947d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 948d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short len; 949d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlattr *nla; 950d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 951d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = NLA_ALIGN(NLA_HDRLEN + sizeof(data)); 952d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 953d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 954d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 955d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 956d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 957d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla = (struct nlattr *)NLMSG_TAIL(n); 958d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla->nla_type = type; 959d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla->nla_len = len; 960d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(NLA_DATA(nla), &data, sizeof(data)); 961d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 962d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 963d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 964d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 965d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 966d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 967d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tannla_put_string(struct nlmsghdr *n, unsigned short maxlen, 968d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short type, const char *data) 969d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 970d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlattr *nla; 971d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len, sl; 972d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 973d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = strlen(data) + 1; 974d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = NLA_ALIGN(NLA_HDRLEN + sl); 975d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 976d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 977d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 978d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 979d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 980d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla = (struct nlattr *)NLMSG_TAIL(n); 981d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla->nla_type = type; 982d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla->nla_len = (unsigned short)len; 983d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(NLA_DATA(nla), data, sl); 984d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + (unsigned short)len; 985d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 986d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 987d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 988d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 989d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tangnl_parse(struct nlmsghdr *nlm, struct nlattr *tb[], int maxtype) 990d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 991d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct genlmsghdr *ghdr; 992d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlattr *head, *nla; 993d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len, rem; 994d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int type; 995d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 996d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(tb, 0, sizeof(*tb) * ((unsigned int)maxtype + 1)); 997d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ghdr = NLMSG_DATA(nlm); 998d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan head = (struct nlattr *)(void *)((char *) ghdr + GENL_HDRLEN); 999d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = nlm->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN; 1000d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NLA_FOR_EACH_ATTR(nla, head, len, rem) { 1001d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan type = NLA_TYPE(nla); 1002d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type > maxtype) 1003d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 1004d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan tb[type] = nla; 1005d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1006d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1007d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1008d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1009d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1010d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan_gnl_getfamily(__unused struct dhcpcd_ctx *ctx, __unused struct interface *ifp, 1011d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 1012d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1013d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlattr *tb[CTRL_ATTR_FAMILY_ID + 1]; 1014d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint16_t family; 1015d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1016d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (gnl_parse(nlm, tb, CTRL_ATTR_FAMILY_ID) == -1) 1017d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1018d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (tb[CTRL_ATTR_FAMILY_ID] == NULL) { 1019d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOENT; 1020d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1021d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1022d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan family = *(uint16_t *)(void *)NLA_DATA(tb[CTRL_ATTR_FAMILY_ID]); 1023d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (int)family; 1024d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1025d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1026d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1027d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tangnl_getfamily(struct dhcpcd_ctx *ctx, const char *name) 1028d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1029d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmg nlm; 1030d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1031d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1032d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr)); 1033d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = GENL_ID_CTRL; 1034d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST; 1035d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ghdr.cmd = CTRL_CMD_GETFAMILY; 1036d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ghdr.version = 1; 1037d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nla_put_string(&nlm.hdr, sizeof(nlm), 1038d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan CTRL_ATTR_FAMILY_NAME, name) == -1) 1039d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1040d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return send_netlink(ctx, NULL, NETLINK_GENERIC, &nlm.hdr, 1041d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &_gnl_getfamily); 1042d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1043d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1044d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1045d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan_if_getssid(__unused struct dhcpcd_ctx *ctx, struct interface *ifp, 1046d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 1047d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1048d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlattr *tb[NL80211_ATTR_SSID + 1]; 1049d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1050d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (gnl_parse(nlm, tb, NL80211_ATTR_SSID) == -1) 1051d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1052d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1053d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (tb[NL80211_ATTR_SSID] == NULL) { 1054d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If the SSID is not found then it means that 1055d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * we're not associated to an AP. */ 1056d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ssid_len = 0; 1057d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto out; 1058d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1059d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1060d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ssid_len = NLA_LEN(tb[NL80211_ATTR_SSID]); 1061d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->ssid_len > sizeof(ifp->ssid)) { 1062d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 1063d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ssid_len = 0; 1064d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1065d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1066d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(ifp->ssid, NLA_DATA(tb[NL80211_ATTR_SSID]), ifp->ssid_len); 1067d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1068d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanout: 1069d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ssid[ifp->ssid_len] = '\0'; 1070d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (int)ifp->ssid_len; 1071d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1072d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1073d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1074d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_getssid_nl80211(struct interface *ifp) 1075d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1076d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int family; 1077d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmg nlm; 1078d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1079d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = 0; 1080d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan family = gnl_getfamily(ifp->ctx, "nl80211"); 1081d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (family == -1) 1082d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1083d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1084d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr)); 1085d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = (unsigned short)family; 1086d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST; 1087d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ghdr.cmd = NL80211_CMD_GET_INTERFACE; 1088d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nla_put_32(&nlm.hdr, sizeof(nlm), NL80211_ATTR_IFINDEX, ifp->index); 1089d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1090d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return send_netlink(ifp->ctx, ifp, 1091d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NETLINK_GENERIC, &nlm.hdr, &_if_getssid); 1092d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1093d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1094d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1095d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1096d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_getssid(struct interface *ifp) 1097d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1098d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int r; 1099d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = if_getssid_wext(ifp->name, ifp->ssid); 1101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != -1) 1102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ssid_len = (unsigned int)r; 1103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef HAVE_NL80211_H 1104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (r == -1) 1105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = if_getssid_nl80211(ifp); 1106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return r; 1108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct nlma 1111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr hdr; 1113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifaddrmsg ifa; 1114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buffer[64]; 1115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}; 1116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct nlmr 1118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr hdr; 1120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtmsg rt; 1121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buffer[256]; 1122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}; 1123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 1125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanconst char *if_pfname = "Packet Socket"; 1126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_openrawsocket(struct interface *ifp, uint16_t protocol) 1129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int s; 1131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan union sockunion { 1132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr sa; 1133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_ll sll; 1134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_storage ss; 1135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } su; 1136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sock_fprog pf; 1137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef PACKET_AUXDATA 1138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int n; 1139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef SOCK_CLOEXEC 1142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 1143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan htons(protocol))) == -1) 1144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int flags; 1147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1) 1149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((flags = fcntl(s, F_GETFD, 0)) == -1 || 1151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1) 1152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((flags = fcntl(s, F_GETFL, 0)) == -1 || 1157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) 1158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Install the DHCP filter */ 1164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&pf, 0, sizeof(pf)); 1165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (protocol == ETHERTYPE_ARP) { 1166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.filter = UNCONST(arp_bpf_filter); 1167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.len = arp_bpf_filter_len; 1168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 1169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.filter = UNCONST(dhcp_bpf_filter); 1170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pf.len = dhcp_bpf_filter_len; 1171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) != 0) 1173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 1174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef PACKET_AUXDATA 1175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = 1; 1176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &n, sizeof(n)) != 0) { 1177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (errno != ENOPROTOOPT) 1178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 1179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&su, 0, sizeof(su)); 1183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_family = PF_PACKET; 1184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_protocol = htons(protocol); 1185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_ifindex = (int)ifp->index; 1186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bind(s, &su.sa, sizeof(su.sll)) == -1) 1187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto eexit; 1188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return s; 1189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneexit: 1191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(s); 1192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 1196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_sendrawpacket(const struct interface *ifp, uint16_t protocol, 1197f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan const void *data, size_t len, const uint8_t *dest_hw_addr) 1198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_state *state; 1200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan union sockunion { 1201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr sa; 1202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_ll sll; 1203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct sockaddr_storage ss; 1204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } su; 1205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int fd; 1206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&su, 0, sizeof(su)); 1208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_family = AF_PACKET; 1209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_protocol = htons(protocol); 1210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_ifindex = (int)ifp->index; 1211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_hatype = htons(ifp->family); 1212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan su.sll.sll_halen = (unsigned char)ifp->hwlen; 1213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->family == ARPHRD_INFINIBAND) 1214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&su.sll.sll_addr, 1215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &ipv4_bcast_addr, sizeof(ipv4_bcast_addr)); 1216f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan else { 1217f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan if (dest_hw_addr) 1218f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan memcpy(&su.sll.sll_addr, dest_hw_addr, ifp->hwlen); 1219f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan else 1220f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan memset(&su.sll.sll_addr, 0xff, ifp->hwlen); 1221f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan } 1222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_CSTATE(ifp); 1223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (protocol == ETHERTYPE_ARP) 1224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->arp_fd; 1225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->raw_fd; 1227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return sendto(fd, data, len, 0, &su.sa, sizeof(su.sll)); 1229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 1232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_readrawpacket(struct interface *ifp, uint16_t protocol, 1233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void *data, size_t len, int *flags) 1234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct iovec iov = { 1236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan .iov_base = data, 1237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan .iov_len = len, 1238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan }; 1239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct msghdr msg = { 1240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan .msg_iov = &iov, 1241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan .msg_iovlen = 1, 1242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan }; 1243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state; 1244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef PACKET_AUXDATA 1245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; 1246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct cmsghdr *cmsg; 1247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct tpacket_auxdata *aux; 1248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t bytes; 1251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int fd = -1; 1252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef PACKET_AUXDATA 1254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan msg.msg_control = cmsgbuf; 1255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan msg.msg_controllen = sizeof(cmsgbuf); 1256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_STATE(ifp); 1259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (protocol == ETHERTYPE_ARP) 1260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->arp_fd; 1261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd = state->raw_fd; 1263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = recvmsg(fd, &msg, 0); 1264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes == -1) 1265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *flags = RAW_EOF; /* We only ever read one packet */ 1267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (bytes) { 1268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef PACKET_AUXDATA 1269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (cmsg = CMSG_FIRSTHDR(&msg); 1270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cmsg; 1271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cmsg = CMSG_NXTHDR(&msg, cmsg)) 1272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmsg->cmsg_level == SOL_PACKET && 1274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cmsg->cmsg_type == PACKET_AUXDATA) { 1275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan aux = (void *)CMSG_DATA(cmsg); 1276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (aux->tp_status & TP_STATUS_CSUMNOTREADY) 1277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *flags |= RAW_PARTIALCSUM; 1278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return bytes; 1283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_address(const struct interface *iface, 1287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct in_addr *address, const struct in_addr *netmask, 1288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct in_addr *broadcast, int action) 1289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlma nlm; 1291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int retval = 0; 1292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 1295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST; 1296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action >= 0) { 1297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; 1298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWADDR; 1299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 1300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_DELADDR; 1301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_index = iface->index; 1302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_family = AF_INET; 1303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_prefixlen = inet_ntocidr(*netmask); 1304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* This creates the aliased interface */ 1305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL, 1306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan iface->alias, (unsigned short)(strlen(iface->alias) + 1)); 1307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL, 1308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &address->s_addr, sizeof(address->s_addr)); 1309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action >= 0 && broadcast) 1310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST, 1311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &broadcast->s_addr, sizeof(broadcast->s_addr)); 1312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (send_netlink(iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL) == -1) 1314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = -1; 1315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 1316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_route(unsigned char cmd, const struct rt *rt) 1320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmr nlm; 1322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int retval = 0; 1323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state; 1324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (cmd) { 1328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_CHANGE: 1329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWROUTE; 1330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE; 1331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_ADD: 1333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWROUTE; 1334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL; 1335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_DELETE: 1337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_DELROUTE; 1338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags |= NLM_F_REQUEST; 1341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_family = AF_INET; 1342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_table = RT_TABLE_MAIN; 1343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_STATE(rt->iface); 1345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_DELETE) 1346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_NOWHERE; 1347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else { 1348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We only change route metrics for kernel routes */ 1349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->dest.s_addr == 1350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (state->addr.s_addr & state->net.s_addr) && 1351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s_addr == state->net.s_addr) 1352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_protocol = RTPROT_KERNEL; 1353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_protocol = RTPROT_BOOT; 1355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->iface->flags & IFF_LOOPBACK) 1356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_HOST; 1357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (rt->gate.s_addr == INADDR_ANY || 1358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (rt->gate.s_addr == rt->dest.s_addr && 1359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s_addr == INADDR_BROADCAST)) 1360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_LINK; 1361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE; 1363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_type = RTN_UNICAST; 1364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_dst_len = inet_ntocidr(rt->net); 1367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), RTA_DST, 1368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &rt->dest.s_addr, sizeof(rt->dest.s_addr)); 1369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nlm.rt.rtm_protocol == RTPROT_KERNEL) { 1370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), RTA_PREFSRC, 1371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &state->addr.s_addr, sizeof(state->addr.s_addr)); 1372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If a host route then don't add the gateway */ 1374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 1375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rt->net.s_addr != INADDR_BROADCAST) 1376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY, 1377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &rt->gate.s_addr, sizeof(rt->gate.s_addr)); 1378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->gate.s_addr != htonl(INADDR_LOOPBACK)) 1380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index); 1381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->metric) 1382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric); 1383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (send_netlink(rt->iface->ctx, NULL, 1385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NETLINK_ROUTE, &nlm.hdr, NULL) == -1) 1386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = -1; 1387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 1388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan_if_initrt(struct dhcpcd_ctx *ctx, __unused struct interface *ifp, 1392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 1393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt rt; 1395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt(ctx, &rt, nlm) == 0) 1397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_handlert(ctx, RTM_ADD, &rt); 1398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_initrt(struct interface *ifp) 1403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmr nlm; 1405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_freerts(ifp->ctx->ipv4_kroutes); 1407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_GETROUTE; 1411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH; 1412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags |= NLM_F_REQUEST; 1413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_family = AF_INET; 1414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_table = RT_TABLE_MAIN; 1415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, ifp->index); 1416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return send_netlink(ifp->ctx, ifp, 1418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NETLINK_ROUTE, &nlm.hdr, &_if_initrt); 1419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_addrflags(__unused const struct in_addr *addr, 1423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan __unused const struct interface *ifp) 1424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Linux has no support for IPv4 address flags */ 1427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 1432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_address6(const struct ipv6_addr *ap, int action) 1434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlma nlm; 1436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifa_cacheinfo cinfo; 1437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int retval = 0; 1438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* IFA_FLAGS is not a define, but is was added at the same time 1439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IFA_F_NOPREFIXROUTE was do use that. */ 1440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR) 1441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint32_t flags = 0; 1442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 1446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST; 1447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action >= 0) { 1448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; 1449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWADDR; 1450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 1451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_DELADDR; 1452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_index = ap->iface->index; 1453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_family = AF_INET6; 1454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ap->addr_flags & IFA_F_TEMPORARY) { 1455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IFA_F_NOPREFIXROUTE 1456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags |= IFA_F_TEMPORARY; 1457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 1458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_flags |= IFA_F_TEMPORARY; 1459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IFA_F_MANAGETEMPADDR 1462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (ap->flags & IPV6_AF_AUTOCONF && 1463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ip6_use_tempaddr(ap->iface->name)) 1464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags |= IFA_F_MANAGETEMPADDR; 1465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Add as /128 if no IFA_F_NOPREFIXROUTE ? */ 1468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.ifa.ifa_prefixlen = ap->prefix_len; 1469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* This creates the aliased interface */ 1470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL, 1471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ap->iface->alias, (unsigned short)(strlen(ap->iface->alias) + 1)); 1472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL, 1473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &ap->addr.s6_addr, sizeof(ap->addr.s6_addr)); 1474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (action >= 0) { 1476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&cinfo, 0, sizeof(cinfo)); 1477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cinfo.ifa_prefered = ap->prefix_pltime; 1478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cinfo.ifa_valid = ap->prefix_vltime; 1479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), IFA_CACHEINFO, 1480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &cinfo, sizeof(cinfo)); 1481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IFA_F_NOPREFIXROUTE 1484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!IN6_IS_ADDR_LINKLOCAL(&ap->addr)) 1485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan flags |= IFA_F_NOPREFIXROUTE; 1486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR) 1488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (flags) 1489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags); 1490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 1491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (send_netlink(ap->iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr, 1493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NULL) == -1) 1494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = -1; 1495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 1496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanrta_add_attr_32(struct rtattr *rta, unsigned short maxlen, 1500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short type, uint32_t data) 1501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned short len = RTA_LENGTH(sizeof(data)); 1503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *subrta; 1504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 1506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 1507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan subrta = (struct rtattr*)(void *) 1511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (((char*)rta) + RTA_ALIGN(rta->rta_len)); 1512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan subrta->rta_type = type; 1513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan subrta->rta_len = len; 1514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(RTA_DATA(subrta), &data, sizeof(data)); 1515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len); 1516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_route6(unsigned char cmd, const struct rt6 *rt) 1521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmr nlm; 1523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int retval = 0; 1524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan switch (cmd) { 1528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_CHANGE: 1529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWROUTE; 1530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE; 1531d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1532d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_ADD: 1533d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWROUTE; 1534d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL; 1535d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1536d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan case RTM_DELETE: 1537d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_DELROUTE; 1538d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 1539d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags |= NLM_F_REQUEST; 1541d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_family = AF_INET6; 1542d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_table = RT_TABLE_MAIN; 1543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1544d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_DELETE) 1545d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_NOWHERE; 1546d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else { 1547d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* None interface subnet routes are static. */ 1548d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->iface->flags & IFF_LOOPBACK) 1549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_HOST; 1550d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) { 1551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_protocol = RTPROT_KERNEL; 1552d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_scope = RT_SCOPE_LINK; 1553d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 1554d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_protocol = RTPROT_BOOT; 1555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->flags & RTF_REJECT) 1556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_type = RTN_UNREACHABLE; 1557d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 1558d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_type = RTN_UNICAST; 1559d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1560d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1561d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_dst_len = ipv6_prefixlen(&rt->net); 1562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), RTA_DST, 1563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &rt->dest.s6_addr, sizeof(rt->dest.s6_addr)); 1564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_ADD && !IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) 1566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY, 1567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &rt->gate.s6_addr, sizeof(rt->gate.s6_addr)); 1568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!(rt->flags & RTF_REJECT)) { 1570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index); 1571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (rt->metric) 1572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), 1573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan RTA_PRIORITY, rt->metric); 1574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (cmd == RTM_ADD && rt->mtu) { 1576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char metricsbuf[32]; 1577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *metrics = (void *)metricsbuf; 1578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan metrics->rta_type = RTA_METRICS; 1580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan metrics->rta_len = RTA_LENGTH(0); 1581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu); 1582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS, 1583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan RTA_DATA(metrics), (unsigned short)RTA_PAYLOAD(metrics)); 1584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (send_netlink(rt->iface->ctx, NULL, 1587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NETLINK_ROUTE, &nlm.hdr, NULL) == -1) 1588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan retval = -1; 1589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return retval; 1590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan_if_initrt6(struct dhcpcd_ctx *ctx, __unused struct interface *ifp, 1594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr *nlm) 1595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rt6 rt; 1597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_copyrt6(ctx, &rt, nlm) == 0) 1599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_handlert(ctx, RTM_ADD, &rt); 1600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_initrt6(struct interface *ifp) 1605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmr nlm; 1607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv6_freerts(&ifp->ctx->ipv6->kroutes); 1609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_GETROUTE; 1613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH; 1614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags |= NLM_F_REQUEST; 1615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_family = AF_INET6; 1616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.rt.rtm_table = RT_TABLE_MAIN; 1617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, ifp->index); 1618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return send_netlink(ifp->ctx, ifp, 1620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NETLINK_ROUTE, &nlm.hdr, &_if_initrt6); 1621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_addrflags6(const struct in6_addr *addr, const struct interface *ifp) 1625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan FILE *fp; 1627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1]; 1628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned int ifindex; 1629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int prefix, scope, flags, i; 1630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fp = fopen(PROC_INET6, "r"); 1632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fp == NULL) 1633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p = ifaddress; 1636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0; i < (int)sizeof(addr->s6_addr); i++) { 1637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += snprintf(p, 3, "%.2x", addr->s6_addr[i]); 1638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p = '\0'; 1640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (fscanf(fp, "%32[a-f0-9] %x %x %x %x %"TOSTRING(IF_NAMESIZE)"s\n", 1642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan address, &ifindex, &prefix, &scope, &flags, name) == 6) 1643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (strlen(address) != 32) { 1645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 1646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOTSUP; 1647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (strcmp(name, ifp->name) == 0 && 1650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strcmp(ifaddress, address) == 0) 1651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 1652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 1653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return flags; 1654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1656d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1657d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 1658d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ESRCH; 1659d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1660d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1661d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1662d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1663d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_getlifetime6(__unused struct ipv6_addr *ia) 1664d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1665d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1666d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* God knows how to work out address lifetimes on Linux */ 1667d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOTSUP; 1668d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1669d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1670d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1671d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct nlml 1672d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1673d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlmsghdr hdr; 1674d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ifinfomsg i; 1675d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char buffer[32]; 1676d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}; 1677d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1678d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1679d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanadd_attr_8(struct nlmsghdr *n, unsigned short maxlen, unsigned short type, 1680d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t data) 1681d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1682d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1683d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return add_attr_l(n, maxlen, type, &data, sizeof(data)); 1684d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1685d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1686d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic struct rtattr * 1687d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanadd_attr_nest(struct nlmsghdr *n, unsigned short maxlen, unsigned short type) 1688d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1689d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *nest; 1690d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1691d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nest = NLMSG_TAIL(n); 1692d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_l(n, maxlen, type, NULL, 0); 1693d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return nest; 1694d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1695d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1696d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 1697d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanadd_attr_nest_end(struct nlmsghdr *n, struct rtattr *nest) 1698d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1699d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1700d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nest->rta_len = (unsigned short)((char *)NLMSG_TAIL(n) - (char *)nest); 1701d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1702d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1703d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 1704d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_disable_autolinklocal(struct dhcpcd_ctx *ctx, int ifindex) 1705d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1706d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct nlml nlm; 1707d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct rtattr *afs, *afs6; 1708d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1709d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&nlm, 0, sizeof(nlm)); 1710d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); 1711d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_type = RTM_NEWLINK; 1712d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.hdr.nlmsg_flags = NLM_F_REQUEST; 1713d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.i.ifi_family = AF_INET6; 1714d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nlm.i.ifi_index = ifindex; 1715d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan afs = add_attr_nest(&nlm.hdr, sizeof(nlm), IFLA_AF_SPEC); 1716d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan afs6 = add_attr_nest(&nlm.hdr, sizeof(nlm), AF_INET6); 1717d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_8(&nlm.hdr, sizeof(nlm), IFLA_INET6_ADDR_GEN_MODE, 1718d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan IN6_ADDR_GEN_MODE_NONE); 1719d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_nest_end(&nlm.hdr, afs6); 1720d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_attr_nest_end(&nlm.hdr, afs); 1721d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1722d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return send_netlink(ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL); 1723d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1724d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1725d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic const char *prefix = "/proc/sys/net/ipv6/conf"; 1726d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1727d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1728d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own) 1729d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1730d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const char *ifname; 1731d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int ra; 1732d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char path[256]; 1733d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1734d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp == NULL) 1735d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname = "all"; 1736d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (own) { 1737d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (if_disable_autolinklocal(ctx, (int)ifp->index) == -1) 1738d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_DEBUG, 1739d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: if_disable_autolinklocal: %m", ifp->name); 1740d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1741d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp) 1742d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname = ifp->name; 1743d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1744d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), "%s/%s/autoconf", prefix, ifname); 1745d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = check_proc_int(path); 1746d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ra != 1) { 1747d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!own) 1748d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_WARNING, 1749d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: IPv6 kernel autoconf disabled", ifname); 1750d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (ra != -1 && own) { 1751d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_path(path, "0") == -1) { 1752d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_ERR, "write_path: %s: %m", path); 1753d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 1754d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1755d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1756d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1757d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), "%s/%s/accept_ra", prefix, ifname); 1758d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ra = check_proc_int(path); 1759d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ra == -1) 1760d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* The sysctl probably doesn't exist, but this isn't an 1761d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * error as such so just log it and continue */ 1762d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, errno == ENOENT ? LOG_DEBUG : LOG_WARNING, 1763d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: %m", path); 1764d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (ra != 0 && own) { 1765d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_DEBUG, "%s: disabling kernel IPv6 RA support", 1766d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname); 1767d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_path(path, "0") == -1) { 1768d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_ERR, "write_path: %s: %m", path); 1769d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ra; 1770d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1771d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 1772d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 1773d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1774d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ra; 1775d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1776d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1777d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IPV6_MANAGETEMPADDR 1778d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1779d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanip6_use_tempaddr(const char *ifname) 1780d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1781d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char path[256]; 1782d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int val; 1783d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1784d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifname == NULL) 1785d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname = "all"; 1786d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), "%s/%s/use_tempaddr", prefix, ifname); 1787d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = check_proc_int(path); 1788d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val == -1 ? 0 : val; 1789d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1790d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1791d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1792d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanip6_temp_preferred_lifetime(const char *ifname) 1793d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1794d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char path[256]; 1795d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int val; 1796d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1797d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifname == NULL) 1798d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname = "all"; 1799d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), "%s/%s/temp_prefered_lft", prefix, 1800d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname); 1801d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = check_proc_int(path); 1802d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val < 0 ? TEMP_PREFERRED_LIFETIME : val; 1803d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1804d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1805d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 1806d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanip6_temp_valid_lifetime(const char *ifname) 1807d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 1808d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char path[256]; 1809d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int val; 1810d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 1811d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifname == NULL) 1812d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname = "all"; 1813d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(path, sizeof(path), "%s/%s/temp_valid_lft", prefix, ifname); 1814d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan val = check_proc_int(path); 1815d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return val < 0 ? TEMP_VALID_LIFETIME : val; 1816d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 1817d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif /* IPV6_MANAGETEMPADDR */ 1818d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif /* INET6 */ 1819