1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * Copyright (c) 2006-2011 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/types.h> 29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/ioctl.h> 30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/param.h> 31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/socket.h> 32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/time.h> 33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <arpa/inet.h> 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <net/if.h> 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <net/if_arp.h> 37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK 38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <net/if_dl.h> 39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <net/if_types.h> 40f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <netinet/in_systm.h> 42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/in.h> 43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/ip.h> 44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */ 45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/udp.h> 46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#undef __FAVOR_BSD 47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_PACKET 48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <netpacket/packet.h> 49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA 51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <net/if_media.h> 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <ctype.h> 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <ifaddrs.h> 57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <fnmatch.h> 58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stddef.h> 59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h> 60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h> 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 65f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h" 67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h" 69a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#include "ipv6rs.h" 70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "signals.h" 72f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char hwaddr_buffer[(HWADDR_LEN * 3) + 1]; 74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint socket_afnet = -1; 76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 77a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#if defined(__FreeBSD__) && defined(DEBUG_MEMORY) 78a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt/* FreeBSD does not zero the struct, causing valgrind errors */ 79a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtunsigned int 80a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtif_nametoindex(const char *ifname) 81a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{ 82a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt struct ifreq ifr; 83a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 84a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 85a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 86a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (ioctl(socket_afnet, SIOCGIFINDEX, &ifr) != -1) 87a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return ifr.ifr_index; 88a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return 0; 89a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt} 90a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif 91a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectinet_ntocidr(struct in_addr address) 94f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 95f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int cidr = 0; 96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t mask = htonl(address.s_addr); 97f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 98f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (mask) { 99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project cidr++; 100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project mask <<= 1; 101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return cidr; 103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectinet_cidrtoaddr(int cidr, struct in_addr *addr) 107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int ocets; 109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (cidr < 1 || cidr > 32) { 111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ocets = (cidr + 7) / 8; 115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr->s_addr = 0; 117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ocets > 0) { 118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&addr->s_addr, 255, (size_t)ocets - 1); 119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset((unsigned char *)&addr->s_addr + (ocets - 1), 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (256 - (1 << (32 - cidr) % 8)), 1); 121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 126f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectuint32_t 127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_netmask(uint32_t addr) 128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 129f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t dst; 130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 131f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (addr == 0) 132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 133f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 134f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dst = htonl(addr); 135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSA(dst)) 136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ntohl(IN_CLASSA_NET); 137938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (IN_CLASSB(dst)) 138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ntohl(IN_CLASSB_NET); 139938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (IN_CLASSC(dst)) 140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ntohl(IN_CLASSC_NET); 141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectchar * 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecthwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen) 147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *p = hwaddr_buffer; 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project size_t i; 150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (i = 0; i < hwlen && i < HWADDR_LEN; i++) { 152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (i > 0) 153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p ++= ':'; 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += snprintf(p, 3, "%.2x", hwaddr[i]); 155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p ++= '\0'; 158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return hwaddr_buffer; 160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectsize_t 163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecthwaddr_aton(unsigned char *buffer, const char *addr) 164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char c[3]; 166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const char *p = addr; 167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned char *bp = buffer; 168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project size_t len = 0; 169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project c[2] = '\0'; 171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (*p) { 172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project c[0] = *p++; 173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project c[1] = *p++; 174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ensure that digits are hex */ 175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (isxdigit((unsigned char)c[0]) == 0 || 176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project isxdigit((unsigned char)c[1]) == 0) 177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 178f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 179f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* We should have at least two entries 00:01 */ 182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len == 0 && *p == '\0') { 183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ensure that next data is EOL or a seperator with data */ 187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) { 188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*p) 192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p++; 193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bp) 194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *bp++ = (unsigned char)strtol(c, NULL, 16); 195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len++; 196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return len; 198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct interface * 201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtinit_interface(const char *ifname) 202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifreq ifr; 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = NULL; 205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1) 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto eexit; 210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface = xzalloc(sizeof(*iface)); 212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(iface->name, ifname, sizeof(iface->name)); 213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->flags = ifr.ifr_flags; 214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We reserve the 100 range for virtual interfaces, if and when 215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we can work them out. */ 216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->metric = 200 + if_nametoindex(iface->name); 217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (getifssid(ifname, iface->ssid) != -1) { 218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->wireless = 1; 219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->metric += 100; 220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCGIFMTU, &ifr) == -1) 223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto eexit; 224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure that the MTU is big enough for DHCP */ 225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifr.ifr_mtu < MTU_MIN) { 226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifr.ifr_mtu = MTU_MIN; 227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCSIFMTU, &ifr) == -1) 229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto eexit; 230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 231f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(iface->leasefile, sizeof(iface->leasefile), 233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt LEASEFILE, ifname); 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* 0 is a valid fd, so init to -1 */ 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->raw_fd = -1; 236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->udp_fd = -1; 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->arp_fd = -1; 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto exit; 239f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidteexit: 241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface); 242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface = NULL; 243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtexit: 244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return iface; 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfree_interface(struct interface *iface) 249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!iface) 251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 252a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6rs_free(iface); 253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state) { 254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_options(iface->state->options); 255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->old); 256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->new); 257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state); 259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 260a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt free(iface->buffer); 261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->clientid); 262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface); 263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtcarrier_status(struct interface *iface) 267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int ret; 269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifreq ifr; 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA 271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifmediareq ifmr; 272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__ 274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *p; 275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&ifr, 0, sizeof(ifr)); 278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__ 280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We can only test the real interface up */ 281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((p = strchr(ifr.ifr_name, ':'))) 282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p = '\0'; 283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1) 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->flags = ifr.ifr_flags; 288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ret = -1; 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&ifmr, 0, sizeof(ifmr)); 292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name)); 293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCGIFMEDIA, &ifmr) != -1 && 294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifmr.ifm_status & IFM_AVALID) 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ret = (ifmr.ifm_status & IFM_ACTIVE) ? 1 : 0; 296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ret == -1) 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ret = (ifr.ifr_flags & IFF_RUNNING) ? 1 : 0; 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return ret; 300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtup_interface(struct interface *iface) 304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifreq ifr; 306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval = -1; 307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__ 308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *p; 309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&ifr, 0, sizeof(ifr)); 312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__ 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We can only bring the real interface up */ 315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((p = strchr(ifr.ifr_name, ':'))) 316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p = '\0'; 317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == 0) { 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((ifr.ifr_flags & IFF_UP)) 320f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = 0; 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifr.ifr_flags |= IFF_UP; 323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_afnet, SIOCSIFFLAGS, &ifr) == 0) 324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = 0; 325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->flags = ifr.ifr_flags; 327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct interface * 332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdiscover_interfaces(int argc, char * const *argv) 333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifaddrs *ifaddrs, *ifa; 335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *p; 336a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt int i, sdl_type; 337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp, *ifs, *ifl; 338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __linux__ 339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char ifn[IF_NAMESIZE]; 340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK 342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct sockaddr_dl *sdl; 343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef IFLR_ACTIVE 344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_laddrreq iflr; 345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int socket_aflink; 346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt socket_aflink = socket(AF_LINK, SOCK_DGRAM, 0); 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (socket_aflink == -1) 349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&iflr, 0, sizeof(iflr)); 351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif AF_PACKET 353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct sockaddr_ll *sll; 354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (getifaddrs(&ifaddrs) == -1) 357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs = ifl = NULL; 360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifa->ifa_addr != NULL) { 362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifa->ifa_addr->sa_family != AF_LINK) 364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif AF_PACKET 366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifa->ifa_addr->sa_family != AF_PACKET) 367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* It's possible for an interface to have >1 AF_LINK. 372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * For our purposes, we use the first one. */ 373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifs; ifp; ifp = ifp->next) 374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifp->name, ifa->ifa_name) == 0) 375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp) 377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (argc > 0) { 379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < argc; i++) { 380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __linux__ 381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Check the real interface name */ 382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(ifn, argv[i], sizeof(ifn)); 383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = strchr(ifn, ':'); 384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (p) 385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p = '\0'; 386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifn, ifa->ifa_name) == 0) 387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#else 389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(argv[i], ifa->ifa_name) == 0) 390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i == argc) 394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = argv[i]; 396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* -1 means we're discovering against a specific 398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * interface, but we still need the below rules 399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * to apply. */ 400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0) 401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifdc; i++) 403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!fnmatch(ifdv[i], ifa->ifa_name, 0)) 404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i < ifdc) 406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifac; i++) 408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!fnmatch(ifav[i], ifa->ifa_name, 0)) 409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifac && i == ifac) 411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = ifa->ifa_name; 413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((ifp = init_interface(p)) == NULL) 415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Bring the interface up if not already */ 418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifp->flags & IFF_UP) 419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA 420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt && carrier_status(ifp) != -1 421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ) 423e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (up_interface(ifp) == 0) 425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_WAITUP; 426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: up_interface: %m", ifp->name); 428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 430a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt sdl_type = 0; 431e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Don't allow loopback unless explicit */ 432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->flags & IFF_LOOPBACK) { 433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (argc == 0 && ifac == 0) { 434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(ifp); 435e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (ifa->ifa_addr != NULL) { 438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK 439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr; 440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef IFLR_ACTIVE 442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We need to check for active address */ 443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(iflr.iflr_name, ifp->name, 444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(iflr.iflr_name)); 445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&iflr.addr, ifa->ifa_addr, 446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); 447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iflr.flags = IFLR_PREFIX; 448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iflr.prefixlen = sdl->sdl_alen * NBBY; 449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ioctl(socket_aflink, SIOCGLIFADDR, &iflr) == -1 || 450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(iflr.flags & IFLR_ACTIVE)) 451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(ifp); 453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 457a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt sdl_type = sdl->sdl_type; 458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch(sdl->sdl_type) { 459a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case IFT_BRIDGE: /* FALLTHROUGH */ 460a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case IFT_L2VLAN: /* FALLTHOUGH */ 461a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case IFT_L3IPVLAN: /* FALLTHROUGH */ 462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case IFT_ETHER: 463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->family = ARPHRD_ETHER; 464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case IFT_IEEE1394: 466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->family = ARPHRD_IEEE1394; 467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 468a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#ifdef IFT_INFINIBAND 469a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case IFT_INFINIBAND: 470a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifp->family = ARPHRD_INFINIBAND; 471a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt break; 472a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif 473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->hwlen = sdl->sdl_alen; 475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef CLLADDR 476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen)) 477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); 479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif AF_PACKET 480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr; 481a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifp->family = sdl_type = sll->sll_hatype; 482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->hwlen = sll->sll_halen; 483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->hwlen != 0) 484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); 485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 487f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We only work on ethernet by default */ 489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifp->flags & IFF_POINTOPOINT) && 490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->family != ARPHRD_ETHER) 491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (argc == 0 && ifac == 0) { 493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(ifp); 494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (ifp->family) { 497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case ARPHRD_IEEE1394: /* FALLTHROUGH */ 498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case ARPHRD_INFINIBAND: 499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We don't warn for supported families */ 500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt default: 502e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 503a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%s: unsupported interface type %.2x" 504a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ", falling back to ethernet", 505a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifp->name, sdl_type); 506a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifp->family = ARPHRD_ETHER; 507a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt break; 508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 510e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Handle any platform init for the interface */ 512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (if_init(ifp) == -1) { 513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: if_init: %m", p); 514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(ifp); 515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifl) 519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl->next = ifp; 520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs = ifp; 522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifp; 523f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt freeifaddrs(ifaddrs); 525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 526e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef IFLR_ACTIVE 527e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(socket_aflink); 528e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 529f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 530e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return ifs; 531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 532f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdo_address(const char *ifname, 535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act) 536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifaddrs *ifaddrs, *ifa; 538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct sockaddr_in *a, *n, *d; 539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int retval; 540f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (getifaddrs(&ifaddrs) == -1) 542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 543f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = 0; 545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifa->ifa_addr == NULL || 547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifa->ifa_addr->sa_family != AF_INET || 548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strcmp(ifa->ifa_name, ifname) != 0) 549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt a = (const struct sockaddr_in *)(void *)ifa->ifa_addr; 551e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask; 552e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifa->ifa_flags & IFF_POINTOPOINT) 553e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt d = (const struct sockaddr_in *)(void *) 554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifa->ifa_dstaddr; 555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt d = NULL; 557e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (act == 1) { 558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr->s_addr = a->sin_addr.s_addr; 559e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt net->s_addr = n->sin_addr.s_addr; 560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dst) { 56149b71a9ee5f83c49125fd6aff49701524be7a618Dmitry Shmidt /* TODO: Fix getifaddrs() */ 56249b71a9ee5f83c49125fd6aff49701524be7a618Dmitry Shmidt if ((ifa->ifa_flags & IFF_POINTOPOINT) && d) 563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dst->s_addr = d->sin_addr.s_addr; 564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dst->s_addr = INADDR_ANY; 566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = 1; 568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (addr->s_addr == a->sin_addr.s_addr && 571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (net == NULL || net->s_addr == n->sin_addr.s_addr)) 572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = 1; 574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 576e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 577e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt freeifaddrs(ifaddrs); 578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return retval; 579f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 580f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 581f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 582f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdo_mtu(const char *ifname, short int mtu) 583f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 584f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifreq ifr; 585f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int r; 586f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 587f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&ifr, 0, sizeof(ifr)); 588f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 589f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ifr.ifr_mtu = mtu; 590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = ioctl(socket_afnet, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 591f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (r == -1) 592f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ifr.ifr_mtu; 594f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 596f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid 597f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectfree_routes(struct rt *routes) 598f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 599f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *r; 600f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 601f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (routes) { 602f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = routes->next; 603f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(routes); 604f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = r; 605f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 606f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 607f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 608f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 609f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectopen_udp_socket(struct interface *iface) 610f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 611f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int s; 612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct sockaddr_in sin; 613f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int n; 614f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef SO_BINDTODEVICE 615f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifreq ifr; 616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *p; 617f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 618f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 619f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 620f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 621f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 622f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n = 1; 623f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) 624f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 625f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef SO_BINDTODEVICE 626f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&ifr, 0, sizeof(ifr)); 627f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We can only bind to the real device */ 629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = strchr(ifr.ifr_name, ':'); 630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (p) 631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p = '\0'; 632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, 633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(ifr)) == -1) 634f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 635f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 636f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* As we don't use this socket for receiving, set the 637f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * receive buffer to 1 */ 638f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n = 1; 639f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) 640f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&sin, 0, sizeof(sin)); 642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.sin_family = AF_INET; 643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.sin_port = htons(DHCP_CLIENT_PORT); 644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.sin_addr.s_addr = iface->addr.s_addr; 645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) 646f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 647f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 648f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->udp_fd = s; 649f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project set_cloexec(s); 650f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 651f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 652f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecteexit: 653f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(s); 654f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 655f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 656f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 657f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 658f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectsend_packet(const struct interface *iface, struct in_addr to, 659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const uint8_t *data, ssize_t len) 660f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct sockaddr_in sin; 662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&sin, 0, sizeof(sin)); 664e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.sin_family = AF_INET; 665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.sin_addr.s_addr = to.s_addr; 666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sin.sin_port = htons(DHCP_SERVER_PORT); 667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return sendto(iface->udp_fd, data, len, 0, 668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (struct sockaddr *)&sin, sizeof(sin)); 669f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 670f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 671f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct udp_dhcp_packet 672f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 673f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ip ip; 674f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct udphdr udp; 675f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message dhcp; 676f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 677f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectconst size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet); 678f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 679f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic uint16_t 680f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectchecksum(const void *data, uint16_t len) 681f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 682f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *addr = data; 683f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t sum = 0; 684f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 685f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (len > 1) { 686f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sum += addr[0] * 256 + addr[1]; 687f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr += 2; 688f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= 2; 689f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 690f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 691f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len == 1) 692f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sum += *addr * 256; 693f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 694f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sum = (sum >> 16) + (sum & 0xffff); 695f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sum += (sum >> 16); 696f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 697f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sum = htons(sum); 698f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 699f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ~sum; 700f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 701f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 702f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 703f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectmake_udp_packet(uint8_t **packet, const uint8_t *data, size_t length, 704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr source, struct in_addr dest) 705f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 706f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct udp_dhcp_packet *udpp; 707f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ip *ip; 708f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct udphdr *udp; 709f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 710f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project udpp = xzalloc(sizeof(*udpp)); 711f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip = &udpp->ip; 712f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project udp = &udpp->udp; 713f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 714f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* OK, this is important :) 715f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * We copy the data to our packet and then create a small part of the 716f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ip structure and an invalid ip_len (basically udp length). 717f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * We then fill the udp structure and put the checksum 718f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * of the whole packet into the udp checksum. 719f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Finally we complete the ip structure and ip checksum. 720f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * If we don't do the ordering like so then the udp checksum will be 721f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * broken, so find another way of doing it! */ 722f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 723f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&udpp->dhcp, data, length); 724f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 725f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_p = IPPROTO_UDP; 726f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_src.s_addr = source.s_addr; 727f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dest.s_addr == 0) 728f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_dst.s_addr = INADDR_BROADCAST; 729f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 730f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_dst.s_addr = dest.s_addr; 731f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 732f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project udp->uh_sport = htons(DHCP_CLIENT_PORT); 733f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project udp->uh_dport = htons(DHCP_SERVER_PORT); 734f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project udp->uh_ulen = htons(sizeof(*udp) + length); 735f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_len = udp->uh_ulen; 736f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project udp->uh_sum = checksum(udpp, sizeof(*udpp)); 737f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 738f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_v = IPVERSION; 739e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ip->ip_hl = sizeof(*ip) >> 2; 740e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ip->ip_id = arc4random() & UINT16_MAX; 741f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_ttl = IPDEFTTL; 742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length); 743f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ip->ip_sum = checksum(ip, sizeof(*ip)); 744f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 745f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *packet = (uint8_t *)udpp; 746f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return sizeof(*ip) + sizeof(*udp) + length; 747f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 748f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 749f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 750f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_udp_data(const uint8_t **data, const uint8_t *udp) 751f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 752f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct udp_dhcp_packet packet; 753f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 754f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&packet, udp, sizeof(packet)); 755f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *data = udp + offsetof(struct udp_dhcp_packet, dhcp); 756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return ntohs(packet.ip.ip_len) - 757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(packet.ip) - 758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(packet.udp); 759f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 760f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 761f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 762a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtvalid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from, 763a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt int noudpcsum) 764f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 765f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct udp_dhcp_packet packet; 766938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt uint16_t bytes, udpsum; 767f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 768e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (data_len < sizeof(packet.ip)) { 769e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (from) 770e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt from->s_addr = INADDR_ANY; 771e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = EINVAL; 772e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 773e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 774e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&packet, data, MIN(data_len, sizeof(packet))); 775e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (from) 776e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt from->s_addr = packet.ip.ip_src.s_addr; 777938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (data_len > sizeof(packet)) { 778938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt errno = EINVAL; 779938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt return -1; 780938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 781938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (checksum(&packet.ip, sizeof(packet.ip)) != 0) { 782f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 783f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 784f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 785f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 786938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt bytes = ntohs(packet.ip.ip_len); 787938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (data_len < bytes) { 788938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt errno = EINVAL; 789938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt return -1; 790938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 791a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 792a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (noudpcsum == 0) { 793a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt udpsum = packet.udp.uh_sum; 794a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.udp.uh_sum = 0; 795a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_hl = 0; 796a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_v = 0; 797a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_tos = 0; 798a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_len = packet.udp.uh_ulen; 799a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_id = 0; 800a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_off = 0; 801a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_ttl = 0; 802a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt packet.ip.ip_sum = 0; 803a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (udpsum && checksum(&packet, bytes) != udpsum) { 804a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt errno = EINVAL; 805a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return -1; 806a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 807f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 808f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 809938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt return 0; 810f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 811