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