1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * Copyright (c) 2006-2012 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" 49a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#include "ipv6rs.h" 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "signals.h" 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" 54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Some systems have route metrics */ 56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef HAVE_ROUTE_METRIC 57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# ifdef __linux__ 58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# define HAVE_ROUTE_METRIC 1 59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# endif 60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# ifndef HAVE_ROUTE_METRIC 61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# define HAVE_ROUTE_METRIC 0 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# endif 63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt *routes; 66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 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 166a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtmake_env(const struct interface *iface, const char *reason, 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; 172a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt int dhcp, ra; 173a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 174a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt dhcp = ra = 0; 175a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (strcmp(reason, "ROUTERADVERT") == 0) 176a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ra = 1; 177a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt else 178a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt dhcp = 1; 179a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 180a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt /* When dumping the lease, we only want to report interface and 181a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt reason - the other interface variables are meaningless */ 182a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (options & DHCPCD_DUMPLEASE) 183a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt elen = 2; 184a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt else 185a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt elen = 10; 186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Make our env */ 188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xmalloc(sizeof(char *) * (elen + 1)); 189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("interface") + strlen(iface->name) + 2; 190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[0] = xmalloc(e); 191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[0], e, "interface=%s", iface->name); 192a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt e = strlen("reason") + strlen(reason) + 2; 193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[1] = xmalloc(e); 194a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt snprintf(env[1], e, "reason=%s", reason); 195a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (options & DHCPCD_DUMPLEASE) 196a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt goto dumplease; 197a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 198a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt e = 20; 199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[2] = xmalloc(e); 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[2], e, "pid=%d", getpid()); 201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[3] = xmalloc(e); 202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[3], e, "ifmetric=%d", iface->metric); 203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[4] = xmalloc(e); 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[4], e, "ifwireless=%d", iface->wireless); 205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[5] = xmalloc(e); 206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[5], e, "ifflags=%u", iface->flags); 207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[6] = xmalloc(e); 208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[6], e, "ifmtu=%d", get_mtu(iface->name)); 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = e = strlen("interface_order="); 210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e += strlen(ifp->name) + 1; 212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = env[7] = xmalloc(e); 213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(p, "interface_order=", e); 214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e -= l; 215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += l; 216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) { 217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = strlcpy(p, ifp->name, e); 218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += l; 219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e -= l; 220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = ' '; 221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e--; 222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *--p = '\0'; 224a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if ((dhcp && iface->state->new) || (ra && iface->ras)) { 225a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt env[8] = strdup("if_up=true"); 226a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt env[9] = strdup("if_down=false"); 227a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } else { 228a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt env[8] = strdup("if_up=false"); 229a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt env[9] = strdup("if_down=true"); 230a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (*iface->state->profile) { 232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("profile=") + strlen(iface->state->profile) + 2; 233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen++], e, "profile=%s", iface->state->profile); 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->wireless) { 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("new_ssid=") + strlen(iface->ssid) + 2; 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->new != NULL || 239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strcmp(iface->state->reason, "CARRIER") == 0) 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + 2)); 242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen++], e, "new_ssid=%s", iface->ssid); 244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->old != NULL || 246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strcmp(iface->state->reason, "NOCARRIER") == 0) 247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + 2)); 249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen++], e, "old_ssid=%s", iface->ssid); 251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 253a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (dhcp && iface->state->old) { 254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = configure_env(NULL, NULL, iface->state->old, ifo); 255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (e > 0) { 256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen += configure_env(env + elen, "old", 258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->old, ifo); 259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt append_config(&env, &elen, "old", 261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (const char *const *)ifo->config); 262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 263a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 264a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtdumplease: 265a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (dhcp && iface->state->new) { 266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = configure_env(NULL, NULL, iface->state->new, ifo); 267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (e > 0) { 268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen += configure_env(env + elen, "new", 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new, ifo); 271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt append_config(&env, &elen, "new", 273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (const char *const *)ifo->config); 274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 275a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (ra) { 276a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt e = ipv6rs_env(NULL, NULL, iface); 277a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (e > 0) { 278a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 279a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt elen += ipv6rs_env(env + elen, NULL, iface); 280a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 281a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Add our base environment */ 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->environ) { 285f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = 0; 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (ifo->environ[e++]) 287f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ; 288f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 289f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = 0; 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (ifo->environ[e]) { 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen + e] = xstrdup(ifo->environ[e]); 292f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 293f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 294f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project elen += e; 295f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project env[elen] = '\0'; 297f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *argv = env; 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return elen; 300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 302a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic int 303a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtsend_interface1(int fd, const struct interface *iface, const char *reason) 304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char **env, **ep, *s; 306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t elen; 307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct iovec iov[2]; 308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int retval; 309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = 0; 311a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt make_env(iface, reason, &env); 312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen = arraytostr((const char *const *)env, &s); 313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_base = &elen; 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_len = sizeof(ssize_t); 315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_base = s; 316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_len = elen; 317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = writev(fd, iov, 2); 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ep = env; 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (*ep) 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(*ep++); 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(env); 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(s); 323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return retval; 324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 327a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtsend_interface(int fd, const struct interface *iface) 328a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{ 329a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt int retval = 0; 330a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (send_interface1(fd, iface, iface->state->reason) == -1) 331a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt retval = -1; 332a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (iface->ras) { 333a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (send_interface1(fd, iface, "ROUTERADVERT") == -1) 334a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt retval = -1; 335a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 336a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return retval; 337a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt} 338a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 339a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtint 340a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtrun_script_reason(const struct interface *iface, const char *reason) 341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *const argv[2] = { UNCONST(iface->state->options->script), NULL }; 343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char **env = NULL, **ep; 344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *path, *bigenv; 345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t e, elen = 0; 346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pid_t pid; 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int status = 0; 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct fd_list *fd; 349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct iovec iov[2]; 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 351a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (iface->state->options->script == NULL || 352a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt iface->state->options->script[0] == '\0' || 353a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt strcmp(iface->state->options->script, "/dev/null") == 0) 354a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return 0; 355a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 356a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (reason == NULL) 357a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt reason = iface->state->reason; 358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: executing `%s', reason %s", 359a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt iface->name, argv[0], reason); 360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Make our env */ 362a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt elen = make_env(iface, reason, &env); 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env = xrealloc(env, sizeof(char *) * (elen + 2)); 364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Add path to it */ 365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt path = getenv("PATH"); 366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (path) { 367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = strlen("PATH") + strlen(path) + 2; 368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xmalloc(e); 369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(env[elen], e, "PATH=%s", path); 370e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[elen] = xstrdup(DEFAULT_PATH); 372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt env[++elen] = '\0'; 373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project pid = exec_script(argv, env); 375f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (pid == -1) 376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project status = -1; 377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else if (pid != 0) { 378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Wait for the script to finish */ 379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (waitpid(pid, &status, 0) == -1) { 380f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno != EINTR) { 381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "waitpid: %m"); 382f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project status = -1; 383f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 384f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 385f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 387f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Send to our listeners */ 389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bigenv = NULL; 390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (fd = fds; fd != NULL; fd = fd->next) { 391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd->listener) { 392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bigenv == NULL) { 393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt elen = arraytostr((const char *const *)env, 394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &bigenv); 395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_base = &elen; 396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_len = sizeof(ssize_t); 397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_base = bigenv; 398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_len = elen; 399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (writev(fd->fd, iov, 2) == -1) 401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "writev: %m"); 402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(bigenv); 405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Cleanup */ 407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ep = env; 408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (*ep) 409f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(*ep++); 410f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(env); 411f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return status; 412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 414f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic struct rt * 415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfind_route(struct rt *rts, const struct rt *r, struct rt **lrt, 416e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct rt *srt) 417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *rt; 419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lrt) 421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *lrt = NULL; 422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = rts; rt; rt = rt->next) { 423e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->dest.s_addr == r->dest.s_addr && 424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#if HAVE_ROUTE_METRIC 425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (srt || (!rt->iface || 426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->iface->metric == r->iface->metric)) && 427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (!srt || srt != rt) && 429e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == r->net.s_addr) 430e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 431e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lrt) 432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *lrt = rt; 433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 435e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 438a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtdesc_route(const char *cmd, const struct rt *rt) 439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char addr[sizeof("000.000.000.000") + 1]; 441a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt const char *ifname = rt->iface->name; 442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(addr, inet_ntoa(rt->dest), sizeof(addr)); 444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->gate.s_addr == INADDR_ANY) 445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s route to %s/%d", ifname, cmd, 446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr, inet_ntocidr(rt->net)); 447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (rt->gate.s_addr == rt->dest.s_addr && 448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == INADDR_BROADCAST) 449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s host route to %s", ifname, cmd, 450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr); 451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (rt->dest.s_addr == INADDR_ANY && rt->net.s_addr == INADDR_ANY) 452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s default route via %s", ifname, cmd, 453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntoa(rt->gate)); 454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 455e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: %s route to %s/%d via %s", ifname, cmd, 456e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate)); 457e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 459e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* If something other than dhcpcd removes a route, 460e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we need to remove it from our internal table. */ 461e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtroute_deleted(const struct rt *rt) 463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *f, *l; 465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt f = find_route(routes, rt, &l, NULL); 467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (f == NULL) 468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 469a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt desc_route("removing", f); 470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (l) 471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l->next = f->next; 472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt routes = f->next; 474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(f); 475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 479a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtn_route(struct rt *rt) 480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 481e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Don't set default routes if not asked to */ 482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->dest.s_addr == 0 && 483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr == 0 && 484a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt !(rt->iface->state->options->options & DHCPCD_GATEWAY)) 485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 487a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt desc_route("adding", rt); 488a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (!add_route(rt)) 489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno == EEXIST) { 491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Pretend we added the subnet route */ 492a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (rt->dest.s_addr == 493a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt (rt->iface->addr.s_addr & rt->iface->net.s_addr) && 494a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->net.s_addr == rt->iface->net.s_addr && 495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->gate.s_addr == 0) 496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 499f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 500a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt syslog(LOG_ERR, "%s: add_route: %m", rt->iface->name); 501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 502f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 503f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 504f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 505a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtc_route(struct rt *ort, struct rt *nrt) 506e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 507e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Don't set default routes if not asked to */ 508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nrt->dest.s_addr == 0 && 509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nrt->net.s_addr == 0 && 510a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt !(nrt->iface->state->options->options & DHCPCD_GATEWAY)) 511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 513a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt desc_route("changing", nrt); 514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We delete and add the route so that we can change metric. 515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This also has the nice side effect of flushing ARP entries so 516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we don't have to do that manually. */ 517a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt del_route(ort); 518a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (!add_route(nrt)) 519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 520a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt syslog(LOG_ERR, "%s: add_route: %m", nrt->iface->name); 521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 523e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 525a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtd_route(struct rt *rt) 526f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 527f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval; 528f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 529a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt desc_route("deleting", rt); 530a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt retval = del_route(rt); 531f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (retval != 0 && errno != ENOENT && errno != ESRCH) 532a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt syslog(LOG_ERR,"%s: del_route: %m", rt->iface->name); 533f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 534f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 535f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_subnet_route(struct dhcp_message *dhcp) 538f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt in_addr_t addr; 540e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr net; 541f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *rt; 542f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 543e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = dhcp->yiaddr; 544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (addr == 0) 545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = dhcp->ciaddr; 546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure we have all the needed values */ 547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) 548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt net.s_addr = get_netmask(addr); 549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (net.s_addr == INADDR_BROADCAST || net.s_addr == INADDR_ANY) 550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 551e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt = malloc(sizeof(*rt)); 552e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->dest.s_addr = addr & net.s_addr; 553e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr = net.s_addr; 554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->gate.s_addr = 0; 555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 557f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 559e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_subnet_route(struct rt *rt, const struct interface *iface) 560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 561e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *r; 562e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->net.s_addr == INADDR_BROADCAST || 564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr == INADDR_ANY || 565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (iface->state->options->options & 566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (DHCPCD_INFORM | DHCPCD_STATIC) && 567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options->req_addr.s_addr == INADDR_ANY)) 568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = xmalloc(sizeof(*r)); 571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->dest.s_addr = iface->addr.s_addr & iface->net.s_addr; 572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->net.s_addr = iface->net.s_addr; 573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->gate.s_addr = 0; 574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = rt; 575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return r; 576f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 577f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 579e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_routes(const struct interface *iface) 580f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 581e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *rt, *nrt = NULL, *r = NULL; 582e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 583e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->options->routes != NULL) { 584e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = iface->state->options->routes; 585e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt != NULL; 586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt = rt->next) 587e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rt->gate.s_addr == 0) 589e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r == NULL) 591e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = nrt = xmalloc(sizeof(*r)); 592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 593e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = xmalloc(sizeof(*r)); 594e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = r->next; 595e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 596e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(r, rt, sizeof(*r)); 597e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = NULL; 598e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 599e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return nrt; 600f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 601e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 602e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return get_option_routes(iface->state->new, 603e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, &iface->state->options->options); 604f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 605f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 606e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Some DHCP servers add set host routes by setting the gateway 607e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * to the assinged IP address. This differs from our notion of a host route 608e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * where the gateway is the destination address, so we fix it. */ 609e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 610e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmassage_host_routes(struct rt *rt, const struct interface *iface) 611f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *r; 613f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 614e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (r = rt; r; r = r->next) 615e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r->gate.s_addr == iface->addr.s_addr && 616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->net.s_addr == INADDR_BROADCAST) 617e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->gate.s_addr = r->dest.s_addr; 618e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 619e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 620f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 621e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 622e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_destination_route(struct rt *rt, const struct interface *iface) 623e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 624e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *r; 625e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 626e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(iface->flags & IFF_POINTOPOINT) || 627e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !has_option_mask(iface->state->options->dstmask, DHO_ROUTER)) 628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = xmalloc(sizeof(*r)); 630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->dest.s_addr = INADDR_ANY; 631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->net.s_addr = INADDR_ANY; 632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->gate.s_addr = iface->dst.s_addr; 633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r->next = rt; 634e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return r; 635e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 636e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 637e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* We should check to ensure the routers are on the same subnet 638e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR supply a host route. If not, warn and add a host route. */ 639e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct rt * 640e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_router_host_route(struct rt *rt, const struct interface *ifp) 641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *rtp, *rtl, *rtn; 643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char *cp, *cp2, *cp3, *cplim; 644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rtp = rt, rtl = NULL; rtp; rtl = rtp, rtp = rtp->next) { 646e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtp->dest.s_addr != INADDR_ANY) 647e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 648e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Scan for a route to match */ 649e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rtn = rt; rtn != rtp; rtn = rtn->next) { 650e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* match host */ 651e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtn->dest.s_addr == rtp->gate.s_addr) 652e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 653e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* match subnet */ 654e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp = (const char *)&rtp->gate.s_addr; 655e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp2 = (const char *)&rtn->dest.s_addr; 656e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cp3 = (const char *)&rtn->net.s_addr; 657e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cplim = cp3 + sizeof(rtn->net.s_addr); 658e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (cp3 < cplim) { 659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((*cp++ ^ *cp2++) & *cp3++) 660e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (cp3 == cplim) 663f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 664f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtn != rtp) 666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->flags & IFF_NOARP) { 668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 669e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: forcing router %s through interface", 670e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->name, inet_ntoa(rtp->gate)); 671e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtp->gate.s_addr = 0; 672e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 673f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 674e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, "%s: router %s requires a host route", 675e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->name, inet_ntoa(rtp->gate)); 676e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn = xmalloc(sizeof(*rtn)); 677e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->dest.s_addr = rtp->gate.s_addr; 678e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->net.s_addr = INADDR_BROADCAST; 679e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->gate.s_addr = rtp->gate.s_addr; 680e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtn->next = rtp; 681e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtl == NULL) 682e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt = rtn; 683e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 684e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtl->next = rtn; 685f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 686e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return rt; 687e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 688f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 689e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 690e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtbuild_routes(void) 691e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 692e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *nrs = NULL, *dnr, *or, *rt, *rtn, *rtl, *lrt = NULL; 693e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct interface *ifp; 694f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6950d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (avoid_routes) return; 6960d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync 697e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) { 698e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->state->new == NULL) 699e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 700e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = get_routes(ifp); 701e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = massage_host_routes(dnr, ifp); 702e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = add_subnet_route(dnr, ifp); 703e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = add_router_host_route(dnr, ifp); 704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = add_destination_route(dnr, ifp); 705e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = dnr; rt && (rtn = rt->next, 1); lrt = rt, rt = rtn) { 706e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->iface = ifp; 707a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->metric = ifp->metric; 708e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Is this route already in our table? */ 709e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((find_route(nrs, rt, NULL, NULL)) != NULL) 710e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 711a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->src.s_addr = ifp->addr.s_addr; 712e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Do we already manage it? */ 713e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((or = find_route(routes, rt, &rtl, NULL))) { 714e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (or->iface != ifp || 715a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt or->src.s_addr != ifp->addr.s_addr || 716a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->gate.s_addr != or->gate.s_addr || 717a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->metric != or->metric) 718e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 719a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (c_route(or, rt) != 0) 720e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 721e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 722e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (rtl != NULL) 723e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rtl->next = or->next; 724e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 725e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt routes = or->next; 726e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(or); 727f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 728a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (n_route(rt) != 0) 729e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 730f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 731e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dnr == rt) 732e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dnr = rtn; 733e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (lrt) 734e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lrt->next = rtn; 735e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->next = nrs; 736e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nrs = rt; 737a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt = lrt; /* When we loop this makes lrt correct */ 738f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 739e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_routes(dnr); 740f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 741e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Remove old routes we used to manage */ 743e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (rt = routes; rt; rt = rt->next) { 744e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (find_route(nrs, rt, NULL, NULL) == NULL) 745a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt d_route(rt); 746e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 747e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 748e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_routes(routes); 749e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt routes = nrs; 750f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 751f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 752f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 753f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdelete_address(struct interface *iface) 754f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 755f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int retval; 756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = iface->state->options; 759e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_INFORM || 760e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0)) 761e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 762e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: deleting IP address %s/%d", 763e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, 764e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntoa(iface->addr), 765e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntocidr(iface->net)); 766e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt retval = del_address(iface, &iface->addr, &iface->net); 767f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (retval == -1 && errno != EADDRNOTAVAIL) 768e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "del_address: %m"); 769f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->addr.s_addr = 0; 770f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->net.s_addr = 0; 771f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return retval; 772f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 773f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 774f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 775e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconfigure(struct interface *iface) 776f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 777e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp = iface->state->new; 778e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_lease *lease = &iface->state->lease; 779e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = iface->state->options; 780e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct rt *rt; 781f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 782e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* As we are now adjusting an interface, we need to ensure 783e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we have them in the right order for routing and configuration. */ 784e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sort_interfaces(); 785f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 786e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp == NULL) { 787e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & DHCPCD_PERSISTENT)) { 788e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt build_routes(); 789e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->addr.s_addr != 0) 790e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_address(iface); 791e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 792f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 793f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 794f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 795f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 796f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* This also changes netmask */ 797e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & DHCPCD_INFORM) || 798e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !has_address(iface->name, &lease->addr, &lease->net)) 799e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 800e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: adding IP address %s/%d", 801e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(lease->addr), 802e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntocidr(lease->net)); 803e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (add_address(iface, 804e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt &lease->addr, &lease->net, &lease->brd) == -1 && 805f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno != EEXIST) 806f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 807e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "add_address: %m"); 808f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 809f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 810f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 811f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 812f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Now delete the old address if different */ 813e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->addr.s_addr != lease->addr.s_addr && 814f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project iface->addr.s_addr != 0) 815f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project delete_address(iface); 816f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 817e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr = lease->addr.s_addr; 818e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr = lease->net.s_addr; 819e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 8200d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (!avoid_routes) { 8210d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync /* We need to delete the subnet route to have our metric or 8220d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync * prefer the interface. */ 8230d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync rt = get_subnet_route(dhcp); 8240d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (rt != NULL) { 8250d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync rt->iface = iface; 826a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt rt->metric = 0; 8270d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync if (!find_route(routes, rt, NULL, NULL)) 828a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt del_route(rt); 8290d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync free(rt); 8300d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync } 8310d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync 8320d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync build_routes(); 833f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 834f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 835e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!iface->state->lease.frominfo && 836e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) 837f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (write_lease(iface, dhcp) == -1) 838e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "write_lease: %m"); 839e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 840f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 841f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 842