1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Copyright 2006-2008 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/stat.h> 33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/ioctl.h> 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/param.h> 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <arpa/inet.h> 37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <linux/netlink.h> 38f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <linux/rtnetlink.h> 39f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/ether.h> 40f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netpacket/packet.h> 41f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stddef.h> 44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h> 45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h> 47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 48f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* Support older kernels */ 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifndef IFLA_WIRELESS 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project# define IFLA_WIRELSSS (IFLFA_MASTER + 1) 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h" 56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define BUFFERLEN 256 60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 62f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectopen_link_socket(struct interface *iface) 63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 65f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_nl nl; 66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) 68f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 69f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&nl, 0, sizeof(nl)); 70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nl.nl_family = AF_NETLINK; 71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nl.nl_groups = RTMGRP_LINK; 72f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1) 73f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 74f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project set_cloexec(fd); 75f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (iface->link_fd != -1) 76f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(iface->link_fd); 77f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->link_fd = fd; 78f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 79f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 80f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 81f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 82f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_netlink(int fd, int flags, 83f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int (*callback)(struct nlmsghdr *, const char *), 84f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const char *ifname) 85f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 86f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *buffer = NULL; 87f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes; 88f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsghdr *nlm; 89f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int r = -1; 90f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 91f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project buffer = xzalloc(sizeof(char) * BUFFERLEN); 92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (;;) { 93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = recv(fd, buffer, BUFFERLEN, flags); 94f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bytes == -1) { 95f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == EAGAIN) { 96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = 0; 97f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 98f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == EINTR) 100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (nlm = (struct nlmsghdr *)buffer; 104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project NLMSG_OK(nlm, (size_t)bytes); 105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm = NLMSG_NEXT(nlm, bytes)) 106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = callback(nlm, ifname); 108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (r != 0) 109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto eexit; 110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecteexit: 114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(buffer); 115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return r; 116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecterr_netlink(struct nlmsghdr *nlm, _unused const char *ifname) 120f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsgerr *err; 122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int l; 123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (nlm->nlmsg_type != NLMSG_ERROR) 125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 126f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = nlm->nlmsg_len - sizeof(*nlm); 127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((size_t)l < sizeof(*err)) { 128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EBADMSG; 129f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 131f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project err = (struct nlmsgerr *)NLMSG_DATA(nlm); 132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (err->error == 0) 133f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return l; 134f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = -err->error; 135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 137f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 139f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectlink_netlink(struct nlmsghdr *nlm, const char *ifname) 140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len; 142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtattr *rta; 143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifinfomsg *ifi; 144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char ifn[IF_NAMESIZE + 1]; 145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) 147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len = nlm->nlmsg_len - sizeof(*nlm); 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((size_t)len < sizeof(*ifi)) { 150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EBADMSG; 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ifi = NLMSG_DATA(nlm); 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ifi->ifi_flags & IFF_LOOPBACK) 155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi))); 157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); 158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *ifn = '\0'; 159f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (RTA_OK(rta, len)) { 160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (rta->rta_type) { 161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case IFLA_WIRELESS: 162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ignore wireless messages */ 163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (nlm->nlmsg_type == RTM_NEWLINK && 164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ifi->ifi_change == 0) 165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case IFLA_IFNAME: 168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); 169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = RTA_NEXT(rta, len); 172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (strncmp(ifname, ifn, sizeof(ifn)) == 0) 175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 1; 176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 178f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 179f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectlink_changed(struct interface *iface) 181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return get_netlink(iface->link_fd, MSG_DONTWAIT, 183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project &link_netlink, iface->name); 184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectsend_netlink(struct nlmsghdr *hdr) 188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd, r; 190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct sockaddr_nl nl; 191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct iovec iov; 192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct msghdr msg; 193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project static unsigned int seq; 194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) 196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&nl, 0, sizeof(nl)); 198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nl.nl_family = AF_NETLINK; 199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1) { 200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&iov, 0, sizeof(iov)); 204f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iov.iov_base = hdr; 205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iov.iov_len = hdr->nlmsg_len; 206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(&msg, 0, sizeof(msg)); 207f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project msg.msg_name = &nl; 208f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project msg.msg_namelen = sizeof(nl); 209f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project msg.msg_iov = &iov; 210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project msg.msg_iovlen = 1; 211f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Request a reply */ 212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hdr->nlmsg_flags |= NLM_F_ACK; 213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hdr->nlmsg_seq = ++seq; 214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (sendmsg(fd, &msg, 0) != -1) 216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = get_netlink(fd, 0, &err_netlink, NULL); 217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = -1; 219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return r; 221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define NLMSG_TAIL(nmsg) \ 224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len))) 225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectadd_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type, 228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const void *data, int alen) 229f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 230f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len = RTA_LENGTH(alen); 231f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtattr *rta; 232f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 233f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 234f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 235f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 236f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 237f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 238f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = NLMSG_TAIL(n); 239f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_type = type; 240f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_len = len; 241f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(RTA_DATA(rta), data, alen); 242f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 245f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 247f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 248f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectadd_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data) 249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 250f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len = RTA_LENGTH(sizeof(data)); 251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtattr *rta; 252f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 258f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta = NLMSG_TAIL(n); 259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_type = type; 260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rta->rta_len = len; 261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(RTA_DATA(rta), &data, sizeof(data)); 262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 266f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct nlma 268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsghdr hdr; 270f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct ifaddrmsg ifa; 271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char buffer[64]; 272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct nlmr 275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmsghdr hdr; 277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rtmsg rt; 278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char buffer[256]; 279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 280f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectif_address(const char *ifname, 283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct in_addr *address, const struct in_addr *netmask, 284f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct in_addr *broadcast, int action) 285f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 286f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlma *nlm; 287f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval = 0; 288f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 289f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm = xzalloc(sizeof(*nlm)); 290f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 291f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags = NLM_F_REQUEST; 292f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action >= 0) { 293f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; 294f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_NEWADDR; 295f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_DELADDR; 297f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!(nlm->ifa.ifa_index = if_nametoindex(ifname))) { 298f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(nlm); 299f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENODEV; 300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->ifa.ifa_family = AF_INET; 303f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask); 304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* This creates the aliased interface */ 305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, 306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ifname, strlen(ifname) + 1); 307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, 308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project &address->s_addr, sizeof(address->s_addr)); 309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action >= 0) 310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST, 311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project &broadcast->s_addr, sizeof(broadcast->s_addr)); 312f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (send_netlink(&nlm->hdr) == -1) 314f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = -1; 315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(nlm); 316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 318f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 319f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 320938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtif_route(const struct interface *iface, 321f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct in_addr *destination, const struct in_addr *netmask, 322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct in_addr *gateway, int metric, int action) 323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct nlmr *nlm; 325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned int ifindex; 326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval = 0; 327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 328938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (!(ifindex = if_nametoindex(iface->name))) { 329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENODEV; 330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm = xzalloc(sizeof(*nlm)); 334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_NEWROUTE; 336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (action == 0) 337938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt nlm->hdr.nlmsg_flags = NLM_F_REPLACE; 338938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else if (action == 1) 339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* 340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ers@google: 341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * commented out NLM_F_EXCL here and below. We 342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * sometimes keep one interface up while we are 343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * configuring the other one, and this flag 344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * causes route addition to fail. 345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags = NLM_F_CREATE /* | NLM_F_EXCL */; 347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_type = RTM_DELROUTE; 349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; 350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_family = AF_INET; 351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_table = RT_TABLE_MAIN; 352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 353938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (action == -1 || action == -2) 354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; 355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/; 357938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* We only change route metrics for kernel routes */ 358938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (destination->s_addr == 359938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt (iface->addr.s_addr & iface->net.s_addr) && 360938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt netmask->s_addr == iface->net.s_addr) 361938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt nlm->rt.rtm_protocol = RTPROT_KERNEL; 362938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else 363938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt nlm->rt.rtm_protocol = RTPROT_BOOT; 364938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (gateway->s_addr == INADDR_ANY || 365938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt (gateway->s_addr == destination->s_addr && 366938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt netmask->s_addr == INADDR_BROADCAST)) 367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_scope = RT_SCOPE_LINK; 368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; 370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_type = RTN_UNICAST; 371f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 372f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 373f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nlm->rt.rtm_dst_len = inet_ntocidr(*netmask); 374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, 375f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project &destination->s_addr, sizeof(destination->s_addr)); 376938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (nlm->rt.rtm_protocol == RTPROT_KERNEL) { 377938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC, 378938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt &iface->addr.s_addr, sizeof(iface->addr.s_addr)); 379938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 380938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* If destination == gateway then don't add the gateway */ 381938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (destination->s_addr != gateway->s_addr || 382938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt netmask->s_addr != INADDR_BROADCAST) 383938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, 384938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt &gateway->s_addr, sizeof(gateway->s_addr)); 385f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex); 387f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, metric); 388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 389f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (send_netlink(&nlm->hdr) == -1) 390f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = -1; 391f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(nlm); 392f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 393f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 394