1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Copyright (c) 2006-2010 Roy Marples <roy@marples.name> 4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * All rights reserved 5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Redistribution and use in source and binary forms, with or without 7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * modification, are permitted provided that the following conditions 8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * are met: 9f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 10f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer. 11f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 12f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * documentation and/or other materials provided with the distribution. 14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * SUCH DAMAGE. 26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/stat.h> 29e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/uio.h> 30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/wait.h> 31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/in.h> 33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <arpa/inet.h> 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <ctype.h> 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <signal.h> 38f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <string.h> 40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 41f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h" 45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "configure.h" 46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h" 48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-pref.h" 49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "signals.h" 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Some systems have route metrics */ 55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef HAVE_ROUTE_METRIC 56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# ifdef __linux__ 57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# define HAVE_ROUTE_METRIC 1 58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# endif 59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# ifndef HAVE_ROUTE_METRIC 60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# define HAVE_ROUTE_METRIC 0 61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# endif 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt *routes; 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 68f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectexec_script(char *const *argv, char *const *env) 69f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project pid_t pid; 71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sigset_t full; 72f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sigset_t old; 73f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 74f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* OK, we need to block signals */ 75f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sigfillset(&full); 76f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sigprocmask(SIG_SETMASK, &full, &old); 77f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project signal_reset(); 78f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 79f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (pid = vfork()) { 80f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case -1: 81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "vfork: %m"); 82f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 83f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 0: 84f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sigprocmask(SIG_SETMASK, &old, NULL); 85f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project execve(argv[0], argv, env); 86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: %m", argv[0]); 87f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project _exit(127); 88f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* NOTREACHED */ 89f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 90f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 91f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Restore our signals */ 92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project signal_setup(); 93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sigprocmask(SIG_SETMASK, &old, NULL); 94f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return pid; 95f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char * 98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmake_var(const char *prefix, const char *var) 99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t len; 101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *v; 102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = strlen(prefix) + strlen(var) + 2; 104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt v = xmalloc(len); 105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(v, len, "%s_%s", prefix, var); 106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return v; 107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtappend_config(char ***env, ssize_t *len, 112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char *prefix, const char *const *config) 113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t i, j, e1; 115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char **ne, *eq; 116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (config == NULL) 118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ne = *env; 121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; config[i] != NULL; i++) { 122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt eq = strchr(config[i], '='); 123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e1 = eq - config[i] + 1; 124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (j = 0; j < *len; j++) { 125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strncmp(ne[j] + strlen(prefix) + 1, 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt config[i], e1) == 0) 127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ne[j]); 129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ne[j] = make_var(prefix, config[i]); 130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (j == *len) { 134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt j++; 135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ne = xrealloc(ne, sizeof(char *) * (j + 1)); 136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ne[j - 1] = make_var(prefix, config[i]); 137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *len = j; 138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *env = ne; 141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic size_t 144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtarraytostr(const char *const *argv, char **s) 145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char *const *ap; 147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *p; 148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t len, l; 149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = 0; 151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ap = argv; 152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (*ap) 153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len += strlen(*ap++) + 1; 154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *s = p = xmalloc(len); 155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ap = argv; 156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (*ap) { 157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = strlen(*ap) + 1; 158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, *ap, l); 159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += l; 160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ap++; 161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return len; 163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic ssize_t 166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmake_env(const struct interface *iface, char ***argv) 167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char **env, *p; 169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t e, elen, l; 170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct if_options *ifo = iface->state->options; 171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct interface *ifp; 172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Make our env */ 174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen = 8; 175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xmalloc(sizeof(char *) * (elen + 1)); 176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("interface") + strlen(iface->name) + 2; 177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[0] = xmalloc(e); 178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[0], e, "interface=%s", iface->name); 179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("reason") + strlen(iface->state->reason) + 2; 180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[1] = xmalloc(e); 181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[1], e, "reason=%s", iface->state->reason); 182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = 20; 183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[2] = xmalloc(e); 184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[2], e, "pid=%d", getpid()); 185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[3] = xmalloc(e); 186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[3], e, "ifmetric=%d", iface->metric); 187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[4] = xmalloc(e); 188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[4], e, "ifwireless=%d", iface->wireless); 189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[5] = xmalloc(e); 190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[5], e, "ifflags=%u", iface->flags); 191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[6] = xmalloc(e); 192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[6], e, "ifmtu=%d", get_mtu(iface->name)); 193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = e = strlen("interface_order="); 194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e += strlen(ifp->name) + 1; 196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = env[7] = xmalloc(e); 197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(p, "interface_order=", e); 198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e -= l; 199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += l; 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) { 201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = strlcpy(p, ifp->name, e); 202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += l; 203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e -= l; 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = ' '; 205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e--; 206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *--p = '\0'; 208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (*iface->state->profile) { 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("profile=") + strlen(iface->state->profile) + 2; 210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen++], e, "profile=%s", iface->state->profile); 212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->wireless) { 214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("new_ssid=") + strlen(iface->ssid) + 2; 215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->new != NULL || 216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strcmp(iface->state->reason, "CARRIER") == 0) 217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + 2)); 219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen++], e, "new_ssid=%s", iface->ssid); 221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->old != NULL || 223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strcmp(iface->state->reason, "NOCARRIER") == 0) 224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + 2)); 226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen++], e, "old_ssid=%s", iface->ssid); 228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->old) { 231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = configure_env(NULL, NULL, iface->state->old, ifo); 232f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (e > 0) { 233f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen += configure_env(env + elen, "old", 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->old, ifo); 236f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt append_config(&env, &elen, "old", 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (const char *const *)ifo->config); 239f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->new) { 241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = configure_env(NULL, NULL, iface->state->new, ifo); 242f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (e > 0) { 243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen += configure_env(env + elen, "new", 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new, ifo); 246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt append_config(&env, &elen, "new", 248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (const char *const *)ifo->config); 249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Add our base environment */ 252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->environ) { 253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = 0; 254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (ifo->environ[e++]) 255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ; 256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = 0; 258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (ifo->environ[e]) { 259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen + e] = xstrdup(ifo->environ[e]); 260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project elen += e; 263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[elen] = '\0'; 265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *argv = env; 267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return elen; 268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_interface(int fd, const struct interface *iface) 272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char **env, **ep, *s; 274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t elen; 275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct iovec iov[2]; 276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int retval; 277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = 0; 279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt make_env(iface, &env); 280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen = arraytostr((const char *const *)env, &s); 281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_base = &elen; 282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_len = sizeof(ssize_t); 283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_base = s; 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_len = elen; 285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = writev(fd, iov, 2); 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ep = env; 287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (*ep) 288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(*ep++); 289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(env); 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(s); 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return retval; 292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtrun_script(const struct interface *iface) 296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *const argv[2] = { UNCONST(iface->state->options->script), NULL }; 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char **env = NULL, **ep; 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *path, *bigenv; 300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t e, elen = 0; 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pid_t pid; 302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int status = 0; 303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct fd_list *fd; 304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct iovec iov[2]; 305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: executing `%s', reason %s", 307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, argv[0], iface->state->reason); 308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Make our env */ 310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen = make_env(iface, &env); 311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + 2)); 312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Add path to it */ 313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt path = getenv("PATH"); 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (path) { 315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("PATH") + strlen(path) + 2; 316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen], e, "PATH=%s", path); 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xstrdup(DEFAULT_PATH); 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[++elen] = '\0'; 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project pid = exec_script(argv, env); 323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (pid == -1) 324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project status = -1; 325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else if (pid != 0) { 326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Wait for the script to finish */ 327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (waitpid(pid, &status, 0) == -1) { 328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno != EINTR) { 329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "waitpid: %m"); 330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project status = -1; 331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Send to our listeners */ 337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bigenv = NULL; 338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (fd = fds; fd != NULL; fd = fd->next) { 339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd->listener) { 340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bigenv == NULL) { 341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen = arraytostr((const char *const *)env, 342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &bigenv); 343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_base = &elen; 344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_len = sizeof(ssize_t); 345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_base = bigenv; 346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_len = elen; 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (writev(fd->fd, iov, 2) == -1) 349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "writev: %m"); 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(bigenv); 353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Cleanup */ 355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ep = env; 356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (*ep) 357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(*ep++); 358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(env); 359f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return status; 360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic struct rt * 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfind_route(struct rt *rts, const struct rt *r, struct rt **lrt, 364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct rt *srt) 365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *rt; 367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lrt) 369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *lrt = NULL; 370e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = rts; rt; rt = rt->next) { 371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->dest.s_addr == r->dest.s_addr && 372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#if HAVE_ROUTE_METRIC 373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (srt || (!rt->iface || 374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->iface->metric == r->iface->metric)) && 375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (!srt || srt != rt) && 377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == r->net.s_addr) 378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lrt) 380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *lrt = rt; 381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdesc_route(const char *cmd, const struct rt *rt, const char *ifname) 387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char addr[sizeof("000.000.000.000") + 1]; 389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(addr, inet_ntoa(rt->dest), sizeof(addr)); 391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->gate.s_addr == INADDR_ANY) 392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s route to %s/%d", ifname, cmd, 393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr, inet_ntocidr(rt->net)); 394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (rt->gate.s_addr == rt->dest.s_addr && 395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == INADDR_BROADCAST) 396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s host route to %s", ifname, cmd, 397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr); 398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (rt->dest.s_addr == INADDR_ANY && rt->net.s_addr == INADDR_ANY) 399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s default route via %s", ifname, cmd, 400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntoa(rt->gate)); 401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s route to %s/%d via %s", ifname, cmd, 403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate)); 404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* If something other than dhcpcd removes a route, 407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we need to remove it from our internal table. */ 408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtroute_deleted(const struct rt *rt) 410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *f, *l; 412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt f = find_route(routes, rt, &l, NULL); 414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (f == NULL) 415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 416e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt desc_route("removing", f, f->iface->name); 417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (l) 418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l->next = f->next; 419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt routes = f->next; 421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(f); 422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 423e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtn_route(struct rt *rt, const struct interface *iface) 427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Don't set default routes if not asked to */ 429e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->dest.s_addr == 0 && 430e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == 0 && 431e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(iface->state->options->options & DHCPCD_GATEWAY)) 432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt desc_route("adding", rt, iface->name); 435e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!add_route(iface, &rt->dest, &rt->net, &rt->gate, iface->metric)) 436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno == EEXIST) { 438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Pretend we added the subnet route */ 439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->dest.s_addr == (iface->addr.s_addr & iface->net.s_addr) && 440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == iface->net.s_addr && 441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->gate.s_addr == 0) 442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: add_route: %m", iface->name); 447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtc_route(struct rt *ort, struct rt *nrt, const struct interface *iface) 452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Don't set default routes if not asked to */ 454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nrt->dest.s_addr == 0 && 455e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nrt->net.s_addr == 0 && 456e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(iface->state->options->options & DHCPCD_GATEWAY)) 457e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 459e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt desc_route("changing", nrt, iface->name); 460e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We delete and add the route so that we can change metric. 461e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This also has the nice side effect of flushing ARP entries so 462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we don't have to do that manually. */ 463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt del_route(ort->iface, &ort->dest, &ort->net, &ort->gate, 464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ort->iface->metric); 465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!add_route(iface, &nrt->dest, &nrt->net, &nrt->gate, 466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->metric)) 467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: add_route: %m", iface->name); 469e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtd_route(struct rt *rt, const struct interface *iface, int metric) 474f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 475f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval; 476f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt desc_route("deleting", rt, iface->name); 478f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project retval = del_route(iface, &rt->dest, &rt->net, &rt->gate, metric); 479f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (retval != 0 && errno != ENOENT && errno != ESRCH) 480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR,"%s: del_route: %m", iface->name); 481f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 482f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 483f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_subnet_route(struct dhcp_message *dhcp) 486f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt in_addr_t addr; 488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr net; 489f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *rt; 490f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = dhcp->yiaddr; 492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (addr == 0) 493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = dhcp->ciaddr; 494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure we have all the needed values */ 495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) 496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt net.s_addr = get_netmask(addr); 497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (net.s_addr == INADDR_BROADCAST || net.s_addr == INADDR_ANY) 498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt = malloc(sizeof(*rt)); 500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->dest.s_addr = addr & net.s_addr; 501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr = net.s_addr; 502e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->gate.s_addr = 0; 503e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 504e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 505f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 506e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 507e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_subnet_route(struct rt *rt, const struct interface *iface) 508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *r; 510e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->net.s_addr == INADDR_BROADCAST || 512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr == INADDR_ANY || 513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (iface->state->options->options & 514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (DHCPCD_INFORM | DHCPCD_STATIC) && 515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options->req_addr.s_addr == INADDR_ANY)) 516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = xmalloc(sizeof(*r)); 519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->dest.s_addr = iface->addr.s_addr & iface->net.s_addr; 520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->net.s_addr = iface->net.s_addr; 521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->gate.s_addr = 0; 522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = rt; 523e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return r; 524f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 526e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 527e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_routes(const struct interface *iface) 528f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 529e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *rt, *nrt = NULL, *r = NULL; 530e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->options->routes != NULL) { 532e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = iface->state->options->routes; 533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt != NULL; 534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt = rt->next) 535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->gate.s_addr == 0) 537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r == NULL) 539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = nrt = xmalloc(sizeof(*r)); 540e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = xmalloc(sizeof(*r)); 542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = r->next; 543e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(r, rt, sizeof(*r)); 545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = NULL; 546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return nrt; 548f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return get_option_routes(iface->state->new, 551e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, &iface->state->options->options); 552f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 553f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Some DHCP servers add set host routes by setting the gateway 555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * to the assinged IP address. This differs from our notion of a host route 556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * where the gateway is the destination address, so we fix it. */ 557e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmassage_host_routes(struct rt *rt, const struct interface *iface) 559f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *r; 561f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 562e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (r = rt; r; r = r->next) 563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r->gate.s_addr == iface->addr.s_addr && 564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->net.s_addr == INADDR_BROADCAST) 565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->gate.s_addr = r->dest.s_addr; 566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 568f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_destination_route(struct rt *rt, const struct interface *iface) 571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *r; 573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(iface->flags & IFF_POINTOPOINT) || 575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !has_option_mask(iface->state->options->dstmask, DHO_ROUTER)) 576e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 577e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = xmalloc(sizeof(*r)); 578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->dest.s_addr = INADDR_ANY; 579e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->net.s_addr = INADDR_ANY; 580e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->gate.s_addr = iface->dst.s_addr; 581e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = rt; 582e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return r; 583e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 584e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 585e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* We should check to ensure the routers are on the same subnet 586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR supply a host route. If not, warn and add a host route. */ 587e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_router_host_route(struct rt *rt, const struct interface *ifp) 589e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *rtp, *rtl, *rtn; 591e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char *cp, *cp2, *cp3, *cplim; 592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 593e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rtp = rt, rtl = NULL; rtp; rtl = rtp, rtp = rtp->next) { 594e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtp->dest.s_addr != INADDR_ANY) 595e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 596e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Scan for a route to match */ 597e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rtn = rt; rtn != rtp; rtn = rtn->next) { 598e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* match host */ 599e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtn->dest.s_addr == rtp->gate.s_addr) 600e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 601e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* match subnet */ 602e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp = (const char *)&rtp->gate.s_addr; 603e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp2 = (const char *)&rtn->dest.s_addr; 604e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp3 = (const char *)&rtn->net.s_addr; 605e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cplim = cp3 + sizeof(rtn->net.s_addr); 606e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (cp3 < cplim) { 607e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((*cp++ ^ *cp2++) & *cp3++) 608e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 609e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 610e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (cp3 == cplim) 611f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 612f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 613e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtn != rtp) 614e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 615e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->flags & IFF_NOARP) { 616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 617e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: forcing router %s through interface", 618e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->name, inet_ntoa(rtp->gate)); 619e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtp->gate.s_addr = 0; 620e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 621f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 622e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, "%s: router %s requires a host route", 623e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->name, inet_ntoa(rtp->gate)); 624e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn = xmalloc(sizeof(*rtn)); 625e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->dest.s_addr = rtp->gate.s_addr; 626e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->net.s_addr = INADDR_BROADCAST; 627e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->gate.s_addr = rtp->gate.s_addr; 628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->next = rtp; 629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtl == NULL) 630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt = rtn; 631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtl->next = rtn; 633f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 634e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 635e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 636f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 637e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 638e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtbuild_routes(void) 639e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 640e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *nrs = NULL, *dnr, *or, *rt, *rtn, *rtl, *lrt = NULL; 641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct interface *ifp; 642f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6430d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (avoid_routes) return; 6440d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync 645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) { 646e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->state->new == NULL) 647e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 648e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = get_routes(ifp); 649e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = massage_host_routes(dnr, ifp); 650e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = add_subnet_route(dnr, ifp); 651e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = add_router_host_route(dnr, ifp); 652e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = add_destination_route(dnr, ifp); 653e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = dnr; rt && (rtn = rt->next, 1); lrt = rt, rt = rtn) { 654e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->iface = ifp; 655e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Is this route already in our table? */ 656e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((find_route(nrs, rt, NULL, NULL)) != NULL) 657e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 658e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Do we already manage it? */ 659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((or = find_route(routes, rt, &rtl, NULL))) { 660e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (or->iface != ifp || 661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->gate.s_addr != or->gate.s_addr) 662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (c_route(or, rt, ifp) != 0) 664e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtl != NULL) 667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtl->next = or->next; 668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 669e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt routes = or->next; 670e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(or); 671f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 672e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (n_route(rt, ifp) != 0) 673e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 674f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 675e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dnr == rt) 676e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = rtn; 677e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (lrt) 678e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lrt->next = rtn; 679e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->next = nrs; 680e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nrs = rt; 681f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 682e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_routes(dnr); 683f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 684e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 685e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Remove old routes we used to manage */ 686e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = routes; rt; rt = rt->next) { 687e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (find_route(nrs, rt, NULL, NULL) == NULL) 688e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt d_route(rt, rt->iface, rt->iface->metric); 689e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 690e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 691e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_routes(routes); 692e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt routes = nrs; 693f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 694f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 695f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 696f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdelete_address(struct interface *iface) 697f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 698f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval; 699e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 700e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 701e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = iface->state->options; 702e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_INFORM || 703e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0)) 704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 705e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: deleting IP address %s/%d", 706e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, 707e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntoa(iface->addr), 708e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntocidr(iface->net)); 709e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = del_address(iface, &iface->addr, &iface->net); 710f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (retval == -1 && errno != EADDRNOTAVAIL) 711e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "del_address: %m"); 712f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->addr.s_addr = 0; 713f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->net.s_addr = 0; 714f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 715f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 716f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 717f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 718e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconfigure(struct interface *iface) 719f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 720e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp = iface->state->new; 721e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_lease *lease = &iface->state->lease; 722e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = iface->state->options; 723e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *rt; 724f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 725e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* As we are now adjusting an interface, we need to ensure 726e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we have them in the right order for routing and configuration. */ 727e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sort_interfaces(); 728f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 729e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp == NULL) { 730e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & DHCPCD_PERSISTENT)) { 731e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt build_routes(); 732e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->addr.s_addr != 0) 733e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_address(iface); 734e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 735f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 736f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 737f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 738f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 739f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* This also changes netmask */ 740e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & DHCPCD_INFORM) || 741e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !has_address(iface->name, &lease->addr, &lease->net)) 742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 743e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: adding IP address %s/%d", 744e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(lease->addr), 745e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntocidr(lease->net)); 746e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (add_address(iface, 747e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &lease->addr, &lease->net, &lease->brd) == -1 && 748f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno != EEXIST) 749f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 750e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "add_address: %m"); 751f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 752f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 753f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 754f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 755f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Now delete the old address if different */ 756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->addr.s_addr != lease->addr.s_addr && 757f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->addr.s_addr != 0) 758f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project delete_address(iface); 759f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 760e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr = lease->addr.s_addr; 761e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr = lease->net.s_addr; 762e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 7630d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (!avoid_routes) { 7640d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync /* We need to delete the subnet route to have our metric or 7650d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync * prefer the interface. */ 7660d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync rt = get_subnet_route(dhcp); 7670d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (rt != NULL) { 7680d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync rt->iface = iface; 7690d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (!find_route(routes, rt, NULL, NULL)) 7700d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync del_route(iface, &rt->dest, &rt->net, &rt->gate, 0); 7710d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync free(rt); 7720d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync } 7730d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync 7740d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync build_routes(); 775f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 776f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 777e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!iface->state->lease.frominfo && 778e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) 779f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (write_lease(iface, dhcp) == -1) 780e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "write_lease: %m"); 781e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 782f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 783f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 784