1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Copyright (c) 2006-2010 Roy Marples <roy@marples.name> 4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * All rights reserved 5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Redistribution and use in source and binary forms, with or without 7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * modification, are permitted provided that the following conditions 8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * are met: 9f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 10f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer. 11f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 12f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * documentation and/or other materials provided with the distribution. 14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * SUCH DAMAGE. 26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/ioctl.h> 29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/param.h> 30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/socket.h> 31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/stat.h> 32e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/sysctl.h> 33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/types.h> 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <arpa/inet.h> 36e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <net/if.h> 37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <net/if_dl.h> 38f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <net/route.h> 39f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/in.h> 40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __DragonFly__ 41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <netproto/802_11/ieee80211_ioctl.h> 42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif __APPLE__ 43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* FIXME: Add apple includes so we can work out SSID */ 44e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#else 45e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <net80211/ieee80211_ioctl.h> 46e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 48f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 49e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <fnmatch.h> 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stddef.h> 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h> 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h> 54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h" 59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "configure.h" 60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h" 62f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define ROUNDUP(a) \ 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* FIXME: Why do we need to check for sa_family 255 */ 69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define COPYOUT(sin, sa) \ 70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.s_addr = ((sa) != NULL) ? \ 71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0 72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int r_fd = -1; 74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char *link_buf; 75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic ssize_t link_buflen; 76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_init(_unused struct interface *iface) 79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* BSD promotes secondary address by default */ 81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_conf(_unused struct interface *iface) 86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* No extra checks needed on BSD */ 88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtinit_sockets(void) 93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt set_cloexec(socket_afnet); 97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt set_cloexec(r_fd); 100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtgetifssid(const char *ifname, char *ssid) 105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int retval = -1; 107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#if defined(SIOCG80211NWID) 108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifreq ifr; 109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ieee80211_nwid nwid; 110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif defined(IEEE80211_IOC_SSID) 111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ieee80211req ireq; 112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char nwid[IEEE80211_NWID_LEN + 1]; 113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#if defined(SIOCG80211NWID) /* NetBSD */ 116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&nwid, 0, sizeof(nwid)); 119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifr.ifr_data = (void *)&nwid; 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) { 121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = nwid.i_len; 122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(ssid, nwid.i_nwid, nwid.i_len); 123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssid[nwid.i_len] = '\0'; 124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif defined(IEEE80211_IOC_SSID) /* FreeBSD */ 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&ireq, 0, sizeof(ireq)); 127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); 128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ireq.i_type = IEEE80211_IOC_SSID; 129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ireq.i_val = -1; 130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ireq.i_data = &nwid; 131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) { 132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = ireq.i_len; 133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(ssid, nwid, ireq.i_len); 134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssid[ireq.i_len] = '\0'; 135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return retval; 138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_address(const struct interface *iface, const struct in_addr *address, 142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct in_addr *netmask, const struct in_addr *broadcast, 143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int action) 144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval; 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifaliasreq ifa; 147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project union { 148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr *sa; 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_in *sin; 150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } _s; 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&ifa, 0, sizeof(ifa)); 153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name)); 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define ADDADDR(_var, _addr) { \ 156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt _s.sa = &_var; \ 157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt _s.sin->sin_family = AF_INET; \ 158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt _s.sin->sin_len = sizeof(*_s.sin); \ 159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr)); \ 160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ADDADDR(ifa.ifra_addr, address); 163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ADDADDR(ifa.ifra_mask, netmask); 164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (action >= 0 && broadcast) { 165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ADDADDR(ifa.ifra_broadaddr, broadcast); 166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#undef ADDADDR 168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action < 0) 170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = ioctl(socket_afnet, SIOCDIFADDR, &ifa); 171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = ioctl(socket_afnet, SIOCAIFADDR, &ifa); 173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED4 */ 177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 178938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtif_route(const struct interface *iface, const struct in_addr *dest, 179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct in_addr *net, const struct in_addr *gate, 180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt _unused int metric, int action) 181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project union sockunion { 183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr sa; 184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_in sin; 185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef INET6 186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_in6 sin6; 187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_dl sdl; 189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_storage ss; 190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } su; 191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtm 192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt_msghdr hdr; 194938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt char buffer[sizeof(su) * 4]; 195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } rtm; 196938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt char *bp = rtm.buffer, *p; 197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project size_t l; 198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval = 0; 199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define ADDSU(_su) { \ 201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = ROUNDUP(_su.sa.sa_len); \ 202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(bp, &(_su), l); \ 203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bp += l; \ 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define ADDADDR(_a) { \ 206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset (&su, 0, sizeof(su)); \ 207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt su.sin.sin_family = AF_INET; \ 208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt su.sin.sin_len = sizeof(su.sin); \ 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr)); \ 210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ADDSU(su); \ 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&rtm, 0, sizeof(rtm)); 214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rtm.hdr.rtm_version = RTM_VERSION; 215938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_seq = 1; 216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action == 0) 217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rtm.hdr.rtm_type = RTM_CHANGE; 218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else if (action > 0) 219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rtm.hdr.rtm_type = RTM_ADD; 220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rtm.hdr.rtm_type = RTM_DELETE; 222938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_flags = RTF_UP; 223938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* None interface subnet routes are static. */ 224938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (gate->s_addr != INADDR_ANY || 225938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt net->s_addr != iface->net.s_addr || 226938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt dest->s_addr != (iface->addr.s_addr & iface->net.s_addr)) 227938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_flags |= RTF_STATIC; 228938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 229938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST) 230f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rtm.hdr.rtm_flags |= RTF_HOST; 231938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else { 232938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_addrs |= RTA_NETMASK; 233938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (rtm.hdr.rtm_flags & RTF_STATIC) 234938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_flags |= RTF_GATEWAY; 235938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (action >= 0) 236938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt rtm.hdr.rtm_addrs |= RTA_IFA; 237938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 238f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 239938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt ADDADDR(dest); 240938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (rtm.hdr.rtm_flags & RTF_HOST || 241938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt !(rtm.hdr.rtm_flags & RTF_STATIC)) 242938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 243938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* Make us a link layer socket for the host gateway */ 244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&su, 0, sizeof(su)); 245938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt su.sdl.sdl_len = sizeof(struct sockaddr_dl); 246938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt link_addr(iface->name, &su.sdl); 247938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt ADDSU(su); 248938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } else 249938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt ADDADDR(gate); 250938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 251938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (rtm.hdr.rtm_addrs & RTA_NETMASK) { 252938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* Ensure that netmask is set correctly */ 253938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memset(&su, 0, sizeof(su)); 254938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt su.sin.sin_family = AF_INET; 255938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt su.sin.sin_len = sizeof(su.sin); 256938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(&su.sin.sin_addr, &net->s_addr, sizeof(su.sin.sin_addr)); 257938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p = su.sa.sa_len + (char *)&su; 258938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt for (su.sa.sa_len = 0; p > (char *)&su;) 259938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*--p != 0) { 260938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt su.sa.sa_len = 1 + p - (char *)&su; 261938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt break; 262938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 263938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt ADDSU(su); 264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 266938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (rtm.hdr.rtm_addrs & RTA_IFA) 267938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt ADDADDR(&iface->addr); 268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rtm.hdr.rtm_msglen = l = bp - (char *)&rtm; 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (write(r_fd, &rtm, l) == -1) 271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = -1; 272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtopen_link_socket(void) 277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 280f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fd = socket(PF_ROUTE, SOCK_RAW, 0); 281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd != -1) { 282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt set_cloexec(fd); 283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt set_nonblock(fd); 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return fd; 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_addrs(int type, char *cp, struct sockaddr **sa) 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int i; 292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < RTAX_MAX; i++) { 294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type & (1 << i)) { 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sa[i] = (struct sockaddr *)cp; 296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG 297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt printf ("got %d %d %s\n", i, sa[i]->sa_family, 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntoa(((struct sockaddr_in *)sa[i])-> 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin_addr)); 300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ADVANCE(cp, sa[i]); 302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sa[i] = NULL; 304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmanage_link(int fd) 309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *p, *e, *cp; 311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char ifname[IF_NAMESIZE]; 312f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes; 313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt_msghdr *rtm; 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_announcemsghdr *ifan; 315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct if_msghdr *ifm; 316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifa_msghdr *ifam; 317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt rt; 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct sockaddr *sa, *rti_info[RTAX_MAX]; 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int len; 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef RTM_CHGADDR 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct sockaddr_dl sdl; 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unsigned char *hwaddr; 323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (;;) { 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(fd, FIONREAD, &len) == -1) 327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (link_buflen < len) { 329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = realloc(link_buf, len); 330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (p == NULL) 331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt link_buf = p; 333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt link_buflen = len; 334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes = read(fd, link_buf, link_buflen); 336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bytes == -1) { 337f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == EAGAIN) 338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == EINTR) 340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = link_buf + bytes; 344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (p = link_buf; p < e; p += rtm->rtm_msglen) { 345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtm = (struct rt_msghdr *)(void *)p; 346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch(rtm->rtm_type) { 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef RTM_IFANNOUNCE 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_IFANNOUNCE: 349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifan = (struct if_announcemsghdr *)(void *)p; 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch(ifan->ifan_what) { 351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case IFAN_ARRIVAL: 352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_interface(1, ifan->ifan_name); 353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case IFAN_DEPARTURE: 355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_interface(-1, ifan->ifan_name); 356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_IFINFO: 361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifm = (struct if_msghdr *)(void *)p; 362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(ifname, 0, sizeof(ifname)); 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (if_indextoname(ifm->ifm_index, ifname)) 364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_interface(0, ifname); 365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_DELETE: 367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(rtm->rtm_addrs & RTA_DST) || 368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(rtm->rtm_addrs & RTA_GATEWAY) || 369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(rtm->rtm_addrs & RTA_NETMASK)) 370e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtm->rtm_pid == getpid()) 372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp = (char *)(void *)(rtm + 1); 374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sa = (struct sockaddr *)(void *)cp; 375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (sa->sa_family != AF_INET) 376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_addrs(rtm->rtm_addrs, cp, rti_info); 378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.iface = NULL; 379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.next = NULL; 380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt COPYOUT(rt.dest, rti_info[RTAX_DST]); 381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt COPYOUT(rt.net, rti_info[RTAX_NETMASK]); 382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]); 383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt route_deleted(&rt); 384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef RTM_CHGADDR 386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_CHGADDR: /* FALLTHROUGH */ 387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_DELADDR: /* FALLTHROUGH */ 389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_NEWADDR: 390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifam = (struct ifa_msghdr *)(void *)p; 391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!if_indextoname(ifam->ifam_index, ifname)) 392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp = (char *)(void *)(ifam + 1); 394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_addrs(ifam->ifam_addrs, cp, rti_info); 395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rti_info[RTAX_IFA] == NULL) 396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (rti_info[RTAX_IFA]->sa_family) { 398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef RTM_CHGADDR 399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case AF_LINK: 400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtm->rtm_type != RTM_CHGADDR) 401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&sdl, rti_info[RTAX_IFA], 403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rti_info[RTAX_IFA]->sa_len); 404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hwaddr = xmalloc(sdl.sdl_alen); 405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(hwaddr, LLADDR(&sdl), 406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sdl.sdl_alen); 407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_hwaddr(ifname, hwaddr, 408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sdl.sdl_alen); 409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case AF_INET: 412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 255: /* FIXME: Why 255? */ 413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt COPYOUT(rt.dest, rti_info[RTAX_IFA]); 414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt COPYOUT(rt.net, rti_info[RTAX_NETMASK]); 415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt COPYOUT(rt.gate, rti_info[RTAX_BRD]); 416e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_ifa(rtm->rtm_type, ifname, 417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &rt.dest, &rt.net, &rt.gate); 418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 422f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 424f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 425