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 <asm/types.h> /* Needed for 2.4 kernels */ 29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/types.h> 31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/socket.h> 32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/ioctl.h> 33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/param.h> 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <linux/netlink.h> 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <linux/rtnetlink.h> 37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Support older kernels */ 39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef IFLA_WIRELESS 40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# define IFLA_WIRELESS (IFLA_MASTER + 1) 41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 43a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt/* For some reason, glibc doesn't include newer flags from linux/if.h 44a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * However, we cannot include linux/if.h directly as it conflicts 45a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * with the glibc version. D'oh! */ 46a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#ifndef IFF_LOWER_UP 47a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ 48a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif 49a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <ctype.h> 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stddef.h> 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h> 54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h> 56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h" 60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "configure.h" 61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 62f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int sock_fd; 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct sockaddr_nl sock_nl; 66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_init(struct interface *iface) 69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char path[PATH_MAX]; 71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt FILE *fp; 72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int n; 73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We enable promote_secondaries so that we can do this 75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * add 192.168.1.2/24 76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * add 192.168.1.3/24 77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * del 192.168.1.2/24 78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * and the subnet mask moves onto 192.168.1.3/24 79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This matches the behaviour of BSD which makes coding dhcpcd 80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * a little easier as there's just one behaviour. */ 81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(path, sizeof(path), 82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "/proc/sys/net/ipv4/conf/%s/promote_secondaries", 83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fp = fopen(path, "w"); 86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fp == NULL) 87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return errno == ENOENT ? 0 : -1; 88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt n = fprintf(fp, "1"); 89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fclose(fp); 90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return n == -1 ? -1 : 0; 91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_conf(struct interface *iface) 95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char path[PATH_MAX], buf[1]; 97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt FILE *fp; 98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Some qeth setups require the use of the broadcast flag. */ 100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(path, sizeof(path), 101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "/sys/class/net/%s/device/layer2", 102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fp = fopen(path, "r"); 105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fp == NULL) 106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return errno == ENOENT ? 0 : -1; 107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fgets(buf, sizeof(buf), fp) != NULL && buf[0] == '0') 108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options->options |= DHCPCD_BROADCAST; 109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fclose(fp); 110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt_open_link_socket(struct sockaddr_nl *nl) 115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) 119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nl->nl_family = AF_NETLINK; 121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) 122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project set_cloexec(fd); 124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return fd; 125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtinit_sockets(void) 129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt set_cloexec(socket_afnet); 133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sock_fd = _open_link_socket(&sock_nl); 134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt set_cloexec(sock_fd); 135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return sock_fd; 136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtopen_link_socket(void) 140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct sockaddr_nl snl; 142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(&snl, 0, sizeof(snl)); 144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; 145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return _open_link_socket(&snl); 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_netlink(int fd, int flags, 150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int (*callback)(struct nlmsghdr *)) 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *buf = NULL, *nbuf; 153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t buflen = 0, bytes; 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsghdr *nlm; 155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int r = -1; 156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (;;) { 158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes = recv(fd, NULL, 0, 159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC); 160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bytes == -1) { 161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == EAGAIN) { 162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = 0; 163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == EINTR) 166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (bytes == buflen) { 169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Support kernels older than 2.6.22 */ 170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bytes == 0) 171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes = 512; 172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes *= 2; 174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (buflen < bytes) { 176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Alloc 1 more so we work with older kernels */ 177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt buflen = bytes + 1; 178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nbuf = realloc(buf, buflen); 179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nbuf == NULL) 180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto eexit; 181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt buf = nbuf; 182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes = recv(fd, buf, buflen, flags); 184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bytes == -1) { 185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno == EAGAIN) { 186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = 0; 187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto eexit; 188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno == EINTR) 190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto eexit; 192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (nlm = (struct nlmsghdr *)buf; 194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project NLMSG_OK(nlm, (size_t)bytes); 195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm = NLMSG_NEXT(nlm, bytes)) 196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = callback(nlm); 198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (r != 0) 199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecteexit: 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(buf); 205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return r; 206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 207f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 208f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidterr_netlink(struct nlmsghdr *nlm) 210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 211f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsgerr *err; 212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int l; 213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (nlm->nlmsg_type != NLMSG_ERROR) 215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = nlm->nlmsg_len - sizeof(*nlm); 217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((size_t)l < sizeof(*err)) { 218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EBADMSG; 219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project err = (struct nlmsgerr *)NLMSG_DATA(nlm); 222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (err->error == 0) 223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return l; 224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = -err->error; 225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtlink_route(struct nlmsghdr *nlm) 230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int len, idx, metric; 232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rtattr *rta; 233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rtmsg *rtm; 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt rt; 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char ifn[IF_NAMESIZE + 1]; 236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nlm->nlmsg_type != RTM_DELROUTE) 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = nlm->nlmsg_len - sizeof(*nlm); 241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((size_t)len < sizeof(*rtm)) { 242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = EBADMSG; 243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtm = NLMSG_DATA(nlm); 246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtm->rtm_type != RTN_UNICAST || 247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtm->rtm_table != RT_TABLE_MAIN || 248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtm->rtm_family != AF_INET || 249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nlm->nlmsg_pid == (uint32_t)getpid()) 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rta = (struct rtattr *) ((char *)rtm + NLMSG_ALIGN(sizeof(*rtm))); 252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = NLMSG_PAYLOAD(nlm, sizeof(*rtm)); 253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.iface = NULL; 254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.dest.s_addr = INADDR_ANY; 255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.net.s_addr = INADDR_ANY; 256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.gate.s_addr = INADDR_ANY; 257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.next = NULL; 258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt metric = 0; 259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (RTA_OK(rta, len)) { 260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (rta->rta_type) { 261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTA_DST: 262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&rt.dest.s_addr, RTA_DATA(rta), 263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(rt.dest.s_addr)); 264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTA_GATEWAY: 266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&rt.gate.s_addr, RTA_DATA(rta), 267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(rt.gate.s_addr)); 268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTA_OIF: 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt idx = *(int *)RTA_DATA(rta); 271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (if_indextoname(idx, ifn)) 272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt.iface = find_interface(ifn); 273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTA_PRIORITY: 275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt metric = *(int *)RTA_DATA(rta); 276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rta = RTA_NEXT(rta, len); 279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt.iface != NULL) { 281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (metric == rt.iface->metric) { 282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net); 283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt route_deleted(&rt); 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtlink_addr(struct nlmsghdr *nlm) 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int len; 293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rtattr *rta; 294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct ifaddrmsg *ifa; 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr addr, net, dest; 296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char ifn[IF_NAMESIZE + 1]; 297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface; 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR) 300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = nlm->nlmsg_len - sizeof(*nlm); 303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((size_t)len < sizeof(*ifa)) { 304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = EBADMSG; 305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nlm->nlmsg_pid == (uint32_t)getpid()) 308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifa = NLMSG_DATA(nlm); 310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (if_indextoname(ifa->ifa_index, ifn) == NULL) 311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface = find_interface(ifn); 313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface == NULL) 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rta = (struct rtattr *) IFA_RTA(ifa); 316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = NLMSG_PAYLOAD(nlm, sizeof(*ifa)); 317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr.s_addr = dest.s_addr = INADDR_ANY; 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dest.s_addr = INADDR_ANY; 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_cidrtoaddr(ifa->ifa_prefixlen, &net); 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (RTA_OK(rta, len)) { 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (rta->rta_type) { 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case IFA_ADDRESS: 323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->flags & IFF_POINTOPOINT) { 324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&dest.s_addr, RTA_DATA(rta), 325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(addr.s_addr)); 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case IFA_LOCAL: 329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&addr.s_addr, RTA_DATA(rta), 330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(addr.s_addr)); 331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rta = RTA_NEXT(rta, len); 334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_ifa(nlm->nlmsg_type, ifn, &addr, &net, &dest); 336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtlink_netlink(struct nlmsghdr *nlm) 341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len; 343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtattr *rta; 344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifinfomsg *ifi; 345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char ifn[IF_NAMESIZE + 1]; 346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = link_route(nlm); 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len != 0) 349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return len; 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = link_addr(nlm); 351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len != 0) 352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return len; 353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) 355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len = nlm->nlmsg_len - sizeof(*nlm); 357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((size_t)len < sizeof(*ifi)) { 358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EBADMSG; 359f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ifi = NLMSG_DATA(nlm); 362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ifi->ifi_flags & IFF_LOOPBACK) 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 364f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi))); 365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); 366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *ifn = '\0'; 367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (RTA_OK(rta, len)) { 368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (rta->rta_type) { 369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case IFLA_WIRELESS: 370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ignore wireless messages */ 371f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (nlm->nlmsg_type == RTM_NEWLINK && 372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifi->ifi_change == 0) 373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 375f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case IFLA_IFNAME: 376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); 377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = RTA_NEXT(rta, len); 380f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 381a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 382a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (nlm->nlmsg_type == RTM_DELLINK) { 383a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt handle_interface(-1, ifn); 384a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return 1; 385a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 386a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 387a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt /* Bridge interfaces set IFF_LOWER_UP when they have a valid 388a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * hardware address. To trigger a valid hardware address pickup 389a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * we need to pretend that that don't exist until they have 390a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * IFF_LOWER_UP set. */ 391a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (ifi->ifi_flags & IFF_MASTER && !(ifi->ifi_flags & IFF_LOWER_UP)) { 392a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt handle_interface(-1, ifn); 393a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return 1; 394a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 395a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 396a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt handle_carrier(ifi->ifi_flags & IFF_RUNNING ? 1 : -1, 397a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifi->ifi_flags, ifn); 398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 399f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 400f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 401f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmanage_link(int fd) 403f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return get_netlink(fd, MSG_DONTWAIT, &link_netlink); 405f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectsend_netlink(struct nlmsghdr *hdr) 409f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int r; 411f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct iovec iov; 412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct msghdr msg; 413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project static unsigned int seq; 414f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 415f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&iov, 0, sizeof(iov)); 416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iov.iov_base = hdr; 417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iov.iov_len = hdr->nlmsg_len; 418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&msg, 0, sizeof(msg)); 419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt msg.msg_name = &sock_nl; 420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt msg.msg_namelen = sizeof(sock_nl); 421f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project msg.msg_iov = &iov; 422f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project msg.msg_iovlen = 1; 423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Request a reply */ 424f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hdr->nlmsg_flags |= NLM_F_ACK; 425f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hdr->nlmsg_seq = ++seq; 426f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (sendmsg(sock_fd, &msg, 0) != -1) 428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = get_netlink(sock_fd, 0, &err_netlink); 429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 430f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = -1; 431f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return r; 432f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 433f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define NLMSG_TAIL(nmsg) \ 435f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len))) 436f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 437f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 438f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectadd_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type, 439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const void *data, int alen) 440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 441f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len = RTA_LENGTH(alen); 442f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtattr *rta; 443f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 444f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 446f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 447f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = NLMSG_TAIL(n); 450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_type = type; 451f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_len = len; 452f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(RTA_DATA(rta), data, alen); 453f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 454f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 458f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectadd_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data) 460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 461f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len = RTA_LENGTH(sizeof(data)); 462f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtattr *rta; 463f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 464f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 465f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 466f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 467f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 468f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 469f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = NLMSG_TAIL(n); 470f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_type = type; 471f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_len = len; 472f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(RTA_DATA(rta), &data, sizeof(data)); 473f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 474f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 475f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 476f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 477f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 478f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct nlma 479f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 480f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsghdr hdr; 481f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifaddrmsg ifa; 482f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char buffer[64]; 483f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 484f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 485f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct nlmr 486f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 487f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsghdr hdr; 488f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtmsg rt; 489f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char buffer[256]; 490f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 491f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 492f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_address(const struct interface *iface, 494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct in_addr *address, const struct in_addr *netmask, 495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct in_addr *broadcast, int action) 496f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 497f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlma *nlm; 498f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval = 0; 499f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 500f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm = xzalloc(sizeof(*nlm)); 501f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 502f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags = NLM_F_REQUEST; 503f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action >= 0) { 504f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; 505f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_NEWADDR; 506f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 507f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_DELADDR; 508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(nlm->ifa.ifa_index = if_nametoindex(iface->name))) { 509f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(nlm); 510f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENODEV; 511f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 512f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 513f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->ifa.ifa_family = AF_INET; 514f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask); 515f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* This creates the aliased interface */ 516f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, 517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, strlen(iface->name) + 1); 518f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, 519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &address->s_addr, sizeof(address->s_addr)); 520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (action >= 0 && broadcast) 521f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST, 522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &broadcast->s_addr, sizeof(broadcast->s_addr)); 523f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 524f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (send_netlink(&nlm->hdr) == -1) 525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = -1; 526f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(nlm); 527f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 528f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 529f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 530f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 531a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtif_route(const struct rt *rt, int action) 532f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 533f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmr *nlm; 534f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned int ifindex; 535f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval = 0; 536f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 537a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (!(ifindex = if_nametoindex(rt->iface->name))) { 538f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENODEV; 539f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 540f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 541f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 542f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm = xzalloc(sizeof(*nlm)); 543f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 544f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_NEWROUTE; 545f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action == 0) 546938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt nlm->hdr.nlmsg_flags = NLM_F_REPLACE; 547938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else if (action == 1) 5480545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt nlm->hdr.nlmsg_flags = NLM_F_CREATE /*| NLM_F_EXCL*/; 549f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 550f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_DELROUTE; 551f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; 552f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_family = AF_INET; 553f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_table = RT_TABLE_MAIN; 554f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 555938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (action == -1 || action == -2) 556f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; 557f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 5580545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/; 559938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* We only change route metrics for kernel routes */ 560a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (rt->dest.s_addr == 561a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt (rt->iface->addr.s_addr & rt->iface->net.s_addr) && 562a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->net.s_addr == rt->iface->net.s_addr) 563938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt nlm->rt.rtm_protocol = RTPROT_KERNEL; 564938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else 565938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt nlm->rt.rtm_protocol = RTPROT_BOOT; 566a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (rt->gate.s_addr == INADDR_ANY || 567a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt (rt->gate.s_addr == rt->dest.s_addr && 568a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->net.s_addr == INADDR_BROADCAST)) 569f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_scope = RT_SCOPE_LINK; 570f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 571f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; 572f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_type = RTN_UNICAST; 573f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 574f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 575a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt nlm->rt.rtm_dst_len = inet_ntocidr(rt->net); 576f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, 577a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt &rt->dest.s_addr, sizeof(rt->dest.s_addr)); 578938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (nlm->rt.rtm_protocol == RTPROT_KERNEL) { 579938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC, 580a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt &rt->iface->addr.s_addr, sizeof(rt->iface->addr.s_addr)); 581938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 582938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* If destination == gateway then don't add the gateway */ 583a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (rt->dest.s_addr != rt->gate.s_addr || 584a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->net.s_addr != INADDR_BROADCAST) 585938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, 586a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt &rt->gate.s_addr, sizeof(rt->gate.s_addr)); 587f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 588f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex); 589a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric); 590f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 591f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (send_netlink(&nlm->hdr) == -1) 592f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = -1; 593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(nlm); 594f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 596