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
28a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtconst char copyright[] = "Copyright (c) 2006-2012 Roy Marples";
29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/file.h>
31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/socket.h>
32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/stat.h>
33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/time.h>
34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/types.h>
35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/uio.h>
36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <arpa/inet.h>
38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <net/route.h>
39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __linux__
41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  include <asm/types.h> /* for systems with broken headers */
42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  include <linux/rtnetlink.h>
43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <ctype.h>
46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h>
47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <getopt.h>
48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <limits.h>
49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <paths.h>
50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <signal.h>
51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h>
52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h>
53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h>
54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h>
55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h>
56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <time.h>
57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "arp.h"
59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "bind.h"
60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h"
61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h"
62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "configure.h"
63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "control.h"
64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcpcd.h"
65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "duid.h"
66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h"
67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h"
68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-pref.h"
69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "ipv4ll.h"
70a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#include "ipv6rs.h"
71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h"
72a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#include "platform.h"
73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "signals.h"
74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
750545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID
760545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <linux/capability.h>
770545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <linux/prctl.h>
780545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <cutils/properties.h>
790545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <private/android_filesystem_config.h>
800545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
810545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt
82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* We should define a maximum for the NAK exponential backoff */
83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define NAKOFF_MAX              60
84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Wait N nanoseconds between sending a RELEASE and dropping the address.
86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This gives the kernel enough time to actually send it. */
87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define RELEASE_DELAY_S		0
88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define RELEASE_DELAY_NS	10000000
89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
90a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtunsigned long long options = 0;
91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint pidfd = -1;
92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct interface *ifaces = NULL;
93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint ifac = 0;
94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtchar **ifav = NULL;
95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint ifdc = 0;
96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtchar **ifdv = NULL;
970d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync/* If set, avoid routes after a DHCP success */
980d3a47d979ac35a49b2a2da9e80e16bd37aab877repo syncint avoid_routes = 0;
99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char **margv;
101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int margc;
102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct if_options *if_options;
103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char **ifv;
104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int ifc;
105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char *cffile;
106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char *pidfile;
107a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic int linkfd = -1, ipv6rsfd = -1;
108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct dhcp_op {
110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t value;
111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const char *name;
112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project};
113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const struct dhcp_op dhcp_ops[] = {
115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_DISCOVER, "DISCOVER" },
116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_OFFER,    "OFFER" },
117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_REQUEST,  "REQUEST" },
118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_DECLINE,  "DECLINE" },
119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_ACK,      "ACK" },
120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_NAK,      "NAK" },
121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_RELEASE,  "RELEASE" },
122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ DHCP_INFORM,   "INFORM" },
123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{ 0, NULL }
124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt};
125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void send_release(struct interface *);
127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const char *
129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_dhcp_op(uint8_t type)
130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const struct dhcp_op *d;
132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (d = dhcp_ops; d->name; d++)
134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (d->value == type)
135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return d->name;
136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return NULL;
137f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
139f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic pid_t
140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtread_pid(void)
141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	FILE *fp;
143938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	pid_t pid;
144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if ((fp = fopen(pidfile, "r")) == NULL) {
146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		errno = ENOENT;
147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return 0;
148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
149938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (fscanf(fp, "%d", &pid) != 1)
150938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt		pid = 0;
151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	fclose(fp);
152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return pid;
153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic void
156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectusage(void)
157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
158a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
159a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtprintf("usage: "PACKAGE"\t[-aABbDdEGgHJKkLnpqTVw]\n"
160a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-C, --nohook hook] [-c, --script script]\n"
161a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-e, --env value] [-F, --fqdn FQDN] [-f, --config file]\n"
162a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-h, --hostname hostname] [-I, --clientid clientid]\n"
163a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-i, --vendorclassid vendorclassid] [-l, --leasetime seconds]\n"
164a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-m, --metric metric] [-O, --nooption option]\n"
165a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-o, --option option] [-Q, --require option]\n"
166a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-r, --request address] [-S, --static value]\n"
167a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-s, --inform address[/cidr]] [-t, --timeout seconds]\n"
168a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-u, --userclass class] [-v, --vendor code, value]\n"
169a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-W, --whitelist address[/cidr]] [-y, --reboot seconds]\n"
170a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-X, --blacklist address[/cidr]] [-Z, --denyinterfaces pattern]\n"
171a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"\t\t[-z, --allowinterfaces pattern] [interface] [...]\n"
172a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"       "PACKAGE"\t-k, --release [interface]\n"
173a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"       "PACKAGE"\t-U, --dumplease interface\n"
174a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"       "PACKAGE"\t-v, --version\n"
175a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	"       "PACKAGE"\t-x, --exit [interface]\n");
176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtcleanup(void)
180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY
182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface;
183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int i;
184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free_options(if_options);
186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (ifaces) {
188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface = ifaces;
189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifaces = iface->next;
190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free_interface(iface);
191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 0; i < ifac; i++)
194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(ifav[i]);
195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(ifav);
196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 0; i < ifdc; i++)
197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(ifdv[i]);
198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(ifdv);
199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (linkfd != -1)
202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(linkfd);
203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (pidfd > -1) {
204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (options & DHCPCD_MASTER) {
205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (stop_control() == -1)
206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "stop_control: %m");
207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(pidfd);
209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		unlink(pidfile);
210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY
212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(pidfile);
213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */
217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_exit_timeout(_unused void *arg)
219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int timeout;
221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_ERR, "timed out");
223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & DHCPCD_TIMEOUT_IPV4LL)) {
224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (options & DHCPCD_MASTER) {
225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			daemonise();
226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else
228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	options &= ~DHCPCD_TIMEOUT_IPV4LL;
231a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2);
232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout);
233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	add_timeout_sec(timeout, handle_exit_timeout, NULL);
234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
237a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtdrop_dhcp(struct interface *iface, const char *reason)
238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface->state->old);
240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->old = iface->state->new;
241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->new = NULL;
242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->reason = reason;
243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	configure(iface);
244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface->state->old);
245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->old = NULL;
246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->lease.addr.s_addr = 0;
247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct interface *
250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfind_interface(const char *ifname)
251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp;
253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifp = ifaces; ifp; ifp = ifp->next)
255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(ifp->name, ifname) == 0)
256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return ifp;
257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return NULL;
258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstop_interface(struct interface *iface)
262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp, *ifl = NULL;
264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_INFO, "%s: removing interface", iface->name);
266a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (iface->ras) {
267a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ipv6rs_free(iface);
268a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		iface->ras = NULL;
269a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		run_script_reason(iface, "ROUTERADVERT");
270a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (strcmp(iface->state->reason, "RELEASE") != 0)
272a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		drop_dhcp(iface, "STOP");
273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	close_sockets(iface);
274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifp = ifaces; ifp; ifp = ifp->next) {
276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifp == iface)
277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifl = ifp;
279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifl)
281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifl->next = ifp->next;
282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifaces = ifp->next;
284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free_interface(ifp);
285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & (DHCPCD_MASTER | DHCPCD_TEST)))
286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_FAILURE);
287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic uint32_t
290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdhcp_xid(struct interface *iface)
291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint32_t xid;
293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->options->options & DHCPCD_XID_HWADDR &&
295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->hwlen >= sizeof(xid))
296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* The lower bits are probably more unique on the network */
297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		memcpy(&xid, (iface->hwaddr + iface->hwlen) - sizeof(xid),
298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    sizeof(xid));
299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		xid = arc4random();
301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return xid;
303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_message(struct interface *iface, int type,
307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    void (*callback)(void *))
308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_state *state = iface->state;
310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo = state->options;
311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct dhcp_message *dhcp;
312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t *udp;
313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ssize_t len, r;
314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct in_addr from, to;
315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	in_addr_t a = 0;
316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeval tv;
317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!callback)
319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_DEBUG, "%s: sending %s with xid 0x%x",
320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name, get_dhcp_op(type), state->xid);
321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else {
322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (state->interval == 0)
323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->interval = 4;
324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else {
325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->interval *= 2;
326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (state->interval > 64)
327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				state->interval = 64;
328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		tv.tv_sec = state->interval + DHCP_RAND_MIN;
330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		tv.tv_usec = arc4random() % (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U);
331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_DEBUG,
332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    "%s: sending %s (xid 0x%x), next in %0.2f seconds",
333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name, get_dhcp_op(type), state->xid,
334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    timeval_to_double(&tv));
335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Ensure sockets are open. */
338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	open_sockets(iface);
339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* If we couldn't open a UDP port for our IP address
341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * then we cannot renew.
342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * This could happen if our IP was pulled out from underneath us.
343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * Also, we should not unicast from a BOOTP lease. */
344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->udp_fd == -1 ||
345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    (!(ifo->options & DHCPCD_INFORM) && is_bootp(iface->state->new)))
346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		a = iface->addr.s_addr;
348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->addr.s_addr = 0;
349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	len = make_message(&dhcp, iface, type);
351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (a)
352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->addr.s_addr = a;
353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	from.s_addr = dhcp->ciaddr;
354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (from.s_addr)
355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		to.s_addr = state->lease.server.s_addr;
356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		to.s_addr = 0;
358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (to.s_addr && to.s_addr != INADDR_BROADCAST) {
359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		r = send_packet(iface, to, (uint8_t *)dhcp, len);
360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (r == -1) {
361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: send_packet: %m", iface->name);
362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			close_sockets(iface);
363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else {
365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		len = make_udp_packet(&udp, (uint8_t *)dhcp, len, from, to);
366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		r = send_raw_packet(iface, ETHERTYPE_IP, udp, len);
367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(udp);
368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* If we failed to send a raw packet this normally means
369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * we don't have the ability to work beneath the IP layer
370e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * for this interface.
371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * As such we remove it from consideration without actually
372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * stopping the interface. */
373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (r == -1) {
374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: send_raw_packet: %m", iface->name);
375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (!(options & DHCPCD_TEST))
376a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				drop_dhcp(iface, "FAIL");
377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			close_sockets(iface);
378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			delete_timeout(NULL, iface);
379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			callback = NULL;
380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(dhcp);
383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Even if we fail to send a packet we should continue as we are
385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * as our failure timeouts will change out codepath when needed. */
386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (callback)
387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_tv(&tv, callback, iface);
388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_inform(void *arg)
392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_message((struct interface *)arg, DHCP_INFORM, send_inform);
394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_discover(void *arg)
398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_message((struct interface *)arg, DHCP_DISCOVER, send_discover);
400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_request(void *arg)
404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_message((struct interface *)arg, DHCP_REQUEST, send_request);
406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_renew(void *arg)
410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_message((struct interface *)arg, DHCP_REQUEST, send_renew);
412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_rebind(void *arg)
416e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_message((struct interface *)arg, DHCP_REQUEST, send_rebind);
418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_expire(void *arg)
422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
423e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->interval = 0;
426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->addr.s_addr == 0) {
427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* We failed to reboot, so enter discovery. */
428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->lease.addr.s_addr = 0;
429e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_discover(iface);
430e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
431e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_ERR, "%s: lease expired", iface->name);
434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
435a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	drop_dhcp(iface, "EXPIRE");
436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	unlink(iface->leasefile);
437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->carrier != LINK_DOWN)
438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_interface(iface);
439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtlog_dhcp(int lvl, const char *msg,
443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    const struct interface *iface, const struct dhcp_message *dhcp,
444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    const struct in_addr *from)
445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const char *tfrom;
447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *a;
448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct in_addr addr;
449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int r;
450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (strcmp(msg, "NAK:") == 0)
452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		a = get_option_string(dhcp, DHO_MESSAGE);
453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else if (dhcp->yiaddr != 0) {
454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		addr.s_addr = dhcp->yiaddr;
455e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		a = xstrdup(inet_ntoa(addr));
456e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else
457e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		a = NULL;
458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
459e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	tfrom = "from";
460e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	r = get_option_addr(&addr, dhcp, DHO_SERVERID);
461e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (dhcp->servername[0] && r == 0)
462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(lvl, "%s: %s %s %s %s `%s'", iface->name, msg, a,
463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    tfrom, inet_ntoa(addr), dhcp->servername);
464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else {
465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (r != 0) {
466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			tfrom = "via";
467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			addr = *from;
468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
469e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (a == NULL)
470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(lvl, "%s: %s %s %s",
471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, msg, tfrom, inet_ntoa(addr));
472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(lvl, "%s: %s %s %s %s",
474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, msg, a, tfrom, inet_ntoa(addr));
475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(a);
477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int
480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtblacklisted_ip(const struct if_options *ifo, in_addr_t addr)
481e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t i;
483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 0; i < ifo->blacklist_len; i += 2)
485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifo->blacklist[i] == (addr & ifo->blacklist[i + 1]))
486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return 1;
487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return 0;
488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int
491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtwhitelisted_ip(const struct if_options *ifo, in_addr_t addr)
492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t i;
494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->whitelist_len == 0)
496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 0; i < ifo->whitelist_len; i += 2)
498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifo->whitelist[i] == (addr & ifo->whitelist[i + 1]))
499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return 1;
500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return 0;
501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
502e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
503e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
504e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_dhcp(struct interface *iface, struct dhcp_message **dhcpp, const struct in_addr *from)
505e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
506e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_state *state = iface->state;
507e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo = state->options;
508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct dhcp_message *dhcp = *dhcpp;
509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct dhcp_lease *lease = &state->lease;
510e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t type, tmp;
511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct in_addr addr;
512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t i;
513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* reset the message counter */
515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	state->interval = 0;
516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We may have found a BOOTP server */
518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (get_option_uint8(&type, dhcp, DHO_MESSAGETYPE) == -1)
519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		type = 0;
520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (type == DHCP_NAK) {
522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* For NAK, only check if we require the ServerID */
523e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (has_option_mask(ifo->requiremask, DHO_SERVERID) &&
524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    get_option_addr(&addr, dhcp, DHO_SERVERID) == -1)
525e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
526e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			log_dhcp(LOG_WARNING, "reject NAK", iface, dhcp, from);
527e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
528e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
529e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* We should restart on a NAK */
530e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		log_dhcp(LOG_WARNING, "NAK:", iface, dhcp, from);
531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!(options & DHCPCD_TEST)) {
532a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			drop_dhcp(iface, "NAK");
533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			unlink(iface->leasefile);
534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close_sockets(iface);
536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* If we constantly get NAKS then we should slowly back off */
537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_sec(state->nakoff, start_interface, iface);
538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		state->nakoff *= 2;
539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (state->nakoff > NAKOFF_MAX)
540e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->nakoff = NAKOFF_MAX;
541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
543e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Ensure that all required options are present */
545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 1; i < 255; i++) {
546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (has_option_mask(ifo->requiremask, i) &&
547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    get_option_uint8(&tmp, dhcp, i) != 0)
548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* If we are bootp, then ignore the need for serverid.
550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * To ignore bootp, require dhcp_message_type instead. */
551e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (type == 0 && i == DHO_SERVERID)
552e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
553e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
556a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
557a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
558a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	/* Ensure that the address offered is valid */
559a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if ((type == 0 || type == DHCP_OFFER || type == DHCP_ACK) &&
560a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	    (dhcp->ciaddr == INADDR_ANY || dhcp->ciaddr == INADDR_BROADCAST) &&
561a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	    (dhcp->yiaddr == INADDR_ANY || dhcp->yiaddr == INADDR_BROADCAST))
562a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	{
563a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		log_dhcp(LOG_WARNING, "reject invalid address",
564a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		    iface, dhcp, from);
565a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		return;
566a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* No NAK, so reset the backoff */
569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	state->nakoff = 1;
570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((type == 0 || type == DHCP_OFFER) &&
572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    state->state == DHS_DISCOVER)
573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		lease->frominfo = 0;
575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		lease->addr.s_addr = dhcp->yiaddr;
576e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		lease->cookie = dhcp->cookie;
577e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (type == 0 ||
578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0)
579e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			lease->server.s_addr = INADDR_ANY;
580e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		log_dhcp(LOG_INFO, "offered", iface, dhcp, from);
581e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(state->offer);
582e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		state->offer = dhcp;
583e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*dhcpp = NULL;
584e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (options & DHCPCD_TEST) {
585e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free(state->old);
586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->old = state->new;
587e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->new = state->offer;
588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->offer = NULL;
589e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->reason = "TEST";
590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			run_script(iface);
591e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_SUCCESS);
592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
593e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		delete_timeout(send_discover, iface);
594e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* We don't request BOOTP addresses */
595e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (type) {
596e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* We used to ARP check here, but that seems to be in
597e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * violation of RFC2131 where it only describes
598e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * DECLINE after REQUEST.
599e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * It also seems that some MS DHCP servers actually
600e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * ignore DECLINE if no REQUEST, ie we decline a
601e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * DISCOVER. */
602e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			start_request(iface);
603e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
604e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
605e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
606e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
607e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (type) {
608e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (type == DHCP_OFFER) {
609e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			log_dhcp(LOG_INFO, "ignoring offer of",
610e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface, dhcp, from);
611e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
613e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
614e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* We should only be dealing with acks */
615e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (type != DHCP_ACK) {
616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			log_dhcp(LOG_ERR, "not ACK or OFFER",
617e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface, dhcp, from);
618e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
619e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
620e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
621e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!(ifo->options & DHCPCD_INFORM))
622e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			log_dhcp(LOG_INFO, "acknowledged", iface, dhcp, from);
623e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
624e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
625e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* BOOTP could have already assigned this above, so check we still
626e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * have a pointer. */
627e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (*dhcpp) {
628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(state->offer);
629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		state->offer = dhcp;
630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*dhcpp = NULL;
631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	lease->frominfo = 0;
634e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
635e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
636e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We now have an offer, so close the DHCP sockets.
637e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * This allows us to safely ARP when broken DHCP servers send an ACK
638e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * follows by an invalid NAK. */
639e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	close_sockets(iface);
640e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_ARP &&
642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->addr.s_addr != state->offer->yiaddr)
643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* If the interface already has the address configured
645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * then we can't ARP for duplicate detection. */
646e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		addr.s_addr = state->offer->yiaddr;
647e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (has_address(iface->name, &addr, NULL) != 1) {
648e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->claims = 0;
649e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->probes = 0;
650e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->conflicts = 0;
651e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			state->state = DHS_PROBE;
652e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			send_arp_probe(iface);
653e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
654e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
655e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
656e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
657e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	bind_interface(iface);
658e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
660e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_dhcp_packet(void *arg)
662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
664e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t *packet;
665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct dhcp_message *dhcp = NULL;
666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const uint8_t *pp;
667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ssize_t bytes;
668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct in_addr from;
669a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	int i, partialcsum = 0;
670e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
671e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We loop through until our buffer is empty.
672e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * The benefit is that if we get >1 DHCP packet in our buffer and
673e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * the first one fails for any reason, we can use the next. */
674e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	packet = xmalloc(udp_dhcp_len);
675e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for(;;) {
676e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		bytes = get_raw_packet(iface, ETHERTYPE_IP,
677a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		    packet, udp_dhcp_len, &partialcsum);
678e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (bytes == 0 || bytes == -1)
679e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
680a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (valid_udp_packet(packet, bytes, &from, partialcsum) == -1) {
681e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: invalid UDP packet from %s",
682e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, inet_ntoa(from));
683e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
684e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
685e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		i = whitelisted_ip(iface->state->options, from.s_addr);
686e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (i == 0) {
687e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_WARNING,
688e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "%s: non whitelisted DHCP packet from %s",
689e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, inet_ntoa(from));
690e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
691e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (i != 1 &&
692e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    blacklisted_ip(iface->state->options, from.s_addr) == 1)
693e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
694e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_WARNING,
695e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "%s: blacklisted DHCP packet from %s",
696e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, inet_ntoa(from));
697e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
698e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
699e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->flags & IFF_POINTOPOINT &&
700e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->dst.s_addr != from.s_addr)
701e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
702e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_WARNING,
703e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "%s: server %s is not destination",
704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, inet_ntoa(from));
705e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
706e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		bytes = get_udp_data(&pp, packet);
707e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if ((size_t)bytes > sizeof(*dhcp)) {
708e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR,
709e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "%s: packet greater than DHCP size from %s",
710e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, inet_ntoa(from));
711e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
712e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
713e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!dhcp)
714e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			dhcp = xzalloc(sizeof(*dhcp));
715e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		memcpy(dhcp, pp, bytes);
716e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (dhcp->cookie != htonl(MAGIC_COOKIE)) {
717e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_DEBUG, "%s: bogus cookie from %s",
718e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, inet_ntoa(from));
719e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
720e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
721e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Ensure it's the right transaction */
722e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->state->xid != dhcp->xid) {
723e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_DEBUG,
724e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "%s: wrong xid 0x%x (expecting 0x%x) from %s",
725e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, dhcp->xid, iface->state->xid,
726e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    inet_ntoa(from));
727e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
728e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
729e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Ensure packet is for us */
730e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->hwlen <= sizeof(dhcp->chaddr) &&
731e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    memcmp(dhcp->chaddr, iface->hwaddr, iface->hwlen))
732e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
733e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_DEBUG, "%s: xid 0x%x is not for hwaddr %s",
734e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, dhcp->xid,
735e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    hwaddr_ntoa(dhcp->chaddr, sizeof(dhcp->chaddr)));
736e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
737e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
738e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		handle_dhcp(iface, &dhcp, &from);
739e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->raw_fd == -1)
740e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
741e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(packet);
743e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(dhcp);
744e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
745e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
746e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
747e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_release(struct interface *iface)
748e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
749e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timespec ts;
750e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
751e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->new != NULL &&
752e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->state->new->cookie == htonl(MAGIC_COOKIE))
753e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
754e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: releasing lease of %s",
755e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name, inet_ntoa(iface->state->lease.addr));
756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->xid = dhcp_xid(iface);
757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		send_message(iface, DHCP_RELEASE, NULL);
758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Give the packet a chance to go before dropping the ip */
759e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ts.tv_sec = RELEASE_DELAY_S;
760e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ts.tv_nsec = RELEASE_DELAY_NS;
761e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		nanosleep(&ts, NULL);
762a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		drop_dhcp(iface, "RELEASE");
763e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
764e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	unlink(iface->leasefile);
765f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
766f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
767e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
768e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_decline(struct interface *iface)
769f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
770e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_message(iface, DHCP_DECLINE, NULL);
771e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
772e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
773e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
774e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconfigure_interface1(struct interface *iface)
775e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
776e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_state *ifs = iface->state;
777e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo = ifs->options;
778e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t *duid;
779e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t len = 0, ifl;
780e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
781e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Do any platform specific configuration */
782e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if_conf(iface);
783e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
784e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->flags & IFF_POINTOPOINT && !(ifo->options & DHCPCD_INFORM))
785e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifo->options |= DHCPCD_STATIC;
786e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->flags & IFF_NOARP ||
787e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
788e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
789a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (!(iface->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST)))
790a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ifo->options &= ~DHCPCD_IPV6RS;
791e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_LINK && carrier_status(iface) == -1)
792e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifo->options &= ~DHCPCD_LINK;
793e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
794e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->metric != -1)
795e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->metric = ifo->metric;
796e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
797e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* If we haven't specified a ClientID and our hardware address
798e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * length is greater than DHCP_CHADDR_LEN then we enforce a ClientID
799e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * of the hardware address family and the hardware address. */
800e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->hwlen > DHCP_CHADDR_LEN)
801e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifo->options |= DHCPCD_CLIENTID;
802e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
803e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Firewire and InfiniBand interfaces require ClientID and
804e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * the broadcast option being set. */
805e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	switch (iface->family) {
806e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case ARPHRD_IEEE1394:	/* FALLTHROUGH */
807e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case ARPHRD_INFINIBAND:
808e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifo->options |= DHCPCD_CLIENTID | DHCPCD_BROADCAST;
809e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		break;
810e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
811e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
812e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface->clientid);
813e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->clientid = NULL;
814e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (*ifo->clientid) {
815e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->clientid = xmalloc(ifo->clientid[0] + 1);
816e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		memcpy(iface->clientid, ifo->clientid, ifo->clientid[0] + 1);
817e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else if (ifo->options & DHCPCD_CLIENTID) {
818e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifo->options & DHCPCD_DUID) {
819e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			duid = xmalloc(DUID_LEN);
820e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if ((len = get_duid(duid, iface)) == 0)
821e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "get_duid: %m");
822e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
823e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (len > 0) {
824e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->clientid = xmalloc(len + 6);
825e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->clientid[0] = len + 5;
826e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->clientid[1] = 255; /* RFC 4361 */
827e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifl = strlen(iface->name);
828e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifl < 5) {
829e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				memcpy(iface->clientid + 2, iface->name, ifl);
830e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (ifl < 4)
831e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					memset(iface->clientid + 2 + ifl,
832e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					    0, 4 - ifl);
833f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			} else {
834e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifl = htonl(if_nametoindex(iface->name));
835e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				memcpy(iface->clientid + 2, &ifl, 4);
836f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			}
837e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (len == 0) {
838e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			len = iface->hwlen + 1;
839e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->clientid = xmalloc(len + 1);
840e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->clientid[0] = len;
841e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->clientid[1] = iface->family;
842e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			memcpy(iface->clientid + 2, iface->hwaddr,
843e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->hwlen);
844e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
845e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
846e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_CLIENTID)
847e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_DEBUG, "%s: using ClientID %s", iface->name,
848e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    hwaddr_ntoa(iface->clientid + 1, *iface->clientid));
849a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	else if (iface->hwlen)
850e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_DEBUG, "%s: using hwaddr %s", iface->name,
851e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    hwaddr_ntoa(iface->hwaddr, iface->hwlen));
852e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
853e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
854e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
855e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtselect_profile(struct interface *iface, const char *profile)
856e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
857e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo;
858e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int ret;
859e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
860e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ret = 0;
861e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifo = read_config(cffile, iface->name, iface->ssid, profile);
862e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo == NULL) {
863e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_DEBUG, "%s: no profile %s", iface->name, profile);
864e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ret = -1;
865e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		goto exit;
866e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
867e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (profile != NULL) {
868e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		strlcpy(iface->state->profile, profile,
869e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    sizeof(iface->state->profile));
870e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: selected profile %s",
871e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name, profile);
872e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else
873e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*iface->state->profile = '\0';
874e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free_options(iface->state->options);
875e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->options = ifo;
876e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
877e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtexit:
878e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (profile)
879e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		configure_interface1(iface);
880e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return ret;
881e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
882e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
883e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
884e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_fallback(void *arg)
885e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
886e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface;
887e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
888e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface = (struct interface *)arg;
889e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	select_profile(iface, iface->state->options->fallback);
890e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	start_interface(iface);
891e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
892e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
893e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
894e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconfigure_interface(struct interface *iface, int argc, char **argv)
895e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
896e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	select_profile(iface, NULL);
897e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	add_options(iface->state->options, argc, argv);
898e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	configure_interface1(iface);
899e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
900e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
901a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtvoid
902a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidthandle_carrier(int action, int flags, const char *ifname)
903e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
904e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface;
905e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int carrier;
906e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
907e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & DHCPCD_LINK))
908e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
909e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (iface = ifaces; iface; iface = iface->next)
910e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(iface->name, ifname) == 0)
911e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
912a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (!iface) {
913a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (options & DHCPCD_LINK)
914a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			handle_interface(1, ifname);
915a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		return;
916a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
917a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (!(iface->state->options->options & DHCPCD_LINK))
918e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
919a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
920a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (action) {
921a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		carrier = action == 1 ? 1 : 0;
922a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		iface->flags = flags;
923a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	} else
924a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		carrier = carrier_status(iface);
925a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
926e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (carrier == -1)
927e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR, "%s: carrier_status: %m", ifname);
928a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	else if (carrier == 0 || ~iface->flags & IFF_UP) {
929e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->carrier != LINK_DOWN) {
930e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->carrier = LINK_DOWN;
931e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_INFO, "%s: carrier lost", iface->name);
932e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			close_sockets(iface);
933e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			delete_timeouts(iface, start_expire, NULL);
934a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (iface->ras) {
935a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				ipv6rs_free(iface);
936a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				iface->ras = NULL;
937a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				run_script_reason(iface, "ROUTERADVERT");
938a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			}
939a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			drop_dhcp(iface, "NOCARRIER");
940e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
941a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	} else if (carrier == 1 && !(~iface->flags & IFF_UP)) {
942e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->carrier != LINK_UP) {
943e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->carrier = LINK_UP;
944e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_INFO, "%s: carrier acquired", iface->name);
945e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (iface->wireless)
946e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				getifssid(iface->name, iface->ssid);
947e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			configure_interface(iface, margc, margv);
948e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->state->interval = 0;
949e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->state->reason = "CARRIER";
950e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			run_script(iface);
951e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			start_interface(iface);
952f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
953f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
954e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
955e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
956e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
957e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_discover(void *arg)
958e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
959e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
960e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo = iface->state->options;
961a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	int timeout = ifo->timeout;
962a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
963a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	/* If we're rebooting and we're not daemonised then we need
964a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	 * to shorten the normal timeout to ensure we try correctly
965a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	 * for a fallback or IPv4LL address. */
966a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (iface->state->state == DHS_REBOOT &&
967a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	    !(options & DHCPCD_DAEMONISED))
968a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	{
969a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		timeout -= ifo->reboot;
970a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (timeout <= 0)
971a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			timeout = 2;
972a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
973e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
974e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->state = DHS_DISCOVER;
975e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->xid = dhcp_xid(iface);
976e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
977e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->fallback)
978a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		add_timeout_sec(timeout, start_fallback, iface);
979e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else if (ifo->options & DHCPCD_IPV4LL &&
980e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    !IN_LINKLOCAL(htonl(iface->addr.s_addr)))
981e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
982e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (IN_LINKLOCAL(htonl(iface->state->fail.s_addr)))
983e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			add_timeout_sec(RATE_LIMIT_INTERVAL, start_ipv4ll, iface);
984e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
985a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			add_timeout_sec(timeout, start_ipv4ll, iface);
986e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
987a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (ifo->options & DHCPCD_REQUEST)
988a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		syslog(LOG_INFO, "%s: broadcasting for a lease (requesting %s)",
989a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		    iface->name, inet_ntoa(ifo->req_addr));
990a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	else
991a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		syslog(LOG_INFO, "%s: broadcasting for a lease", iface->name);
992e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_discover(iface);
993e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
994f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
995e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
996e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_request(void *arg)
997e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
998e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
999e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1000e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->state = DHS_REQUEST;
1001e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_request(iface);
1002f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
1003f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1004e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1005e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_renew(void *arg)
1006f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
1007e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
1008e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1009e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_INFO, "%s: renewing lease of %s",
1010e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->name, inet_ntoa(iface->state->lease.addr));
1011e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->state = DHS_RENEW;
1012e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->xid = dhcp_xid(iface);
1013e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_renew(iface);
1014e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1015e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1016e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1017e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_rebind(void *arg)
1018e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1019e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
1020e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1021e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_ERR, "%s: failed to renew, attempting to rebind",
1022e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->name);
1023e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->state = DHS_REBIND;
1024e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(send_renew, iface);
1025e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->lease.server.s_addr = 0;
1026e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_rebind(iface);
1027e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1028e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1029e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1030e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_timeout(void *arg)
1031e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1032e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
1033e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1034e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	bind_interface(iface);
1035e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->interval = 0;
1036e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	start_discover(iface);
1037e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1038e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1039e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct dhcp_message *
1040e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdhcp_message_new(struct in_addr *addr, struct in_addr *mask)
1041e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1042e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct dhcp_message *dhcp;
1043e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t *p;
1044e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1045e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	dhcp = xzalloc(sizeof(*dhcp));
1046e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	dhcp->yiaddr = addr->s_addr;
1047e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	p = dhcp->options;
1048e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (mask && mask->s_addr != INADDR_ANY) {
1049e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*p++ = DHO_SUBNETMASK;
1050e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*p++ = sizeof(mask->s_addr);
1051e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		memcpy(p, &mask->s_addr, sizeof(mask->s_addr));
1052e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		p+= sizeof(mask->s_addr);
1053e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1054e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*p++ = DHO_END;
1055e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return dhcp;
1056e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1057e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1058e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int
1059e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_3rdparty(struct interface *iface)
1060e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1061e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo;
1062e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct in_addr addr, net, dst;
1063e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1064e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifo = iface->state->options;
1065e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->req_addr.s_addr != INADDR_ANY)
1066e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return 0;
1067e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1068e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (get_address(iface->name, &addr, &net, &dst) == 1)
1069e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		handle_ifa(RTM_NEWADDR, iface->name, &addr, &net, &dst);
1070e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else {
1071e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO,
1072e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    "%s: waiting for 3rd party to configure IP address",
1073e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name);
1074e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->reason = "3RDPARTY";
1075e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		run_script(iface);
1076e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1077e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return 1;
1078e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1079e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1080e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1081e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_static(struct interface *iface)
1082e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1083e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo;
1084e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1085e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (handle_3rdparty(iface))
1086e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1087e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifo = iface->state->options;
1088e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->offer =
1089e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
1090e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
1091e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	bind_interface(iface);
1092e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1093e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1094e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1095e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_inform(struct interface *iface)
1096e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1097e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (handle_3rdparty(iface))
1098e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1099e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_TEST) {
1101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->addr.s_addr = iface->state->options->req_addr.s_addr;
1102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->net.s_addr = iface->state->options->req_mask.s_addr;
1103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	} else {
1104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->options->options |= DHCPCD_STATIC;
1105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_static(iface);
1106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->state = DHS_INFORM;
1109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->xid = dhcp_xid(iface);
1110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_inform(iface);
1111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_reboot(struct interface *iface)
1115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo = iface->state->options;
1117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_LINK && iface->carrier == LINK_DOWN) {
1119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: waiting for carrier", iface->name);
1120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_STATIC) {
1123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_static(iface);
1124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->reboot == 0 || iface->state->offer == NULL) {
1127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_discover(iface);
1128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_INFORM) {
1131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: informing address of %s",
1132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name, inet_ntoa(iface->state->lease.addr));
1133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else if (iface->state->offer->cookie == 0) {
1134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifo->options & DHCPCD_IPV4LL) {
1135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->state->claims = 0;
1136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			send_arp_announce(iface);
1137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else
1138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			start_discover(iface);
1139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else {
1141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: rebinding lease of %s",
1142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name, inet_ntoa(iface->state->lease.addr));
1143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->state = DHS_REBOOT;
1145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->xid = dhcp_xid(iface);
1146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->lease.server.s_addr = 0;
1147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
1148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->fallback)
1149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_sec(ifo->reboot, start_fallback, iface);
1150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else if (ifo->options & DHCPCD_LASTLEASE &&
1151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->state->lease.frominfo)
1152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_sec(ifo->reboot, start_timeout, iface);
1153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else if (!(ifo->options & DHCPCD_INFORM &&
1154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		options & (DHCPCD_MASTER | DHCPCD_DAEMONISED)))
1155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_sec(ifo->reboot, start_expire, iface);
1156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Don't bother ARP checking as the server could NAK us first. */
1157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_INFORM)
1158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		send_inform(iface);
1159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
1160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		send_request(iface);
1161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_interface(void *arg)
1165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
1167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo = iface->state->options;
1168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct stat st;
1169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeval now;
1170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint32_t l;
1171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int nolease;
1172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1173a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	handle_carrier(0, 0, iface->name);
1174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->carrier == LINK_DOWN) {
1175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: waiting for carrier", iface->name);
1176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->start_uptime = uptime();
1180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface->state->offer);
1181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->offer = NULL;
1182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1183a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (options & DHCPCD_IPV6RS && ifo->options & DHCPCD_IPV6RS) {
1184a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (check_ipv6(iface->name) == 1)
1185a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			ipv6rs_start(iface);
1186a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		else
1187a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			ifo->options &= ~DHCPCD_IPV6RS;
1188a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
1189a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
1190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->arping_index < ifo->arping_len) {
1191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_arping(iface);
1192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_STATIC) {
1195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_static(iface);
1196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifo->options & DHCPCD_INFORM) {
1199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_inform(iface);
1200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->hwlen == 0 && ifo->clientid[0] == '\0') {
1203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_WARNING, "%s: needs a clientid to configure",
1204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name);
1205a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		drop_dhcp(iface, "FAIL");
1206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close_sockets(iface);
1207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		delete_timeout(NULL, iface);
1208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We don't want to read the old lease if we NAK an old test */
1211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	nolease = iface->state->offer && options & DHCPCD_TEST;
1212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!nolease)
1213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->offer = read_lease(iface);
1214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->offer) {
1215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		get_lease(&iface->state->lease, iface->state->offer);
1216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->lease.frominfo = 1;
1217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->state->offer->cookie == 0) {
1218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (iface->state->offer->yiaddr ==
1219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->addr.s_addr)
1220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			{
1221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free(iface->state->offer);
1222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				iface->state->offer = NULL;
1223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (iface->state->lease.leasetime != ~0U &&
1225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    stat(iface->leasefile, &st) == 0)
1226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
1227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* Offset lease times and check expiry */
1228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			gettimeofday(&now, NULL);
1229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if ((time_t)iface->state->lease.leasetime <
12300545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt			    (time_t)(now.tv_sec - st.st_mtime))
1231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			{
1232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_DEBUG,
1233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    "%s: discarding expired lease",
1234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    iface->name);
1235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free(iface->state->offer);
1236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				iface->state->offer = NULL;
1237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				iface->state->lease.addr.s_addr = 0;
1238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			} else {
1239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				l = now.tv_sec - st.st_mtime;
1240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				iface->state->lease.leasetime -= l;
1241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				iface->state->lease.renewaltime -= l;
1242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				iface->state->lease.rebindtime -= l;
1243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			}
1244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1245f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->offer == NULL)
1247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_discover(iface);
1248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else if (iface->state->offer->cookie == 0 &&
1249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->state->options->options & DHCPCD_IPV4LL)
1250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_ipv4ll(iface);
1251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
1252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_reboot(iface);
1253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtinit_state(struct interface *iface, int argc, char **argv)
1257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_state *ifs;
1259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state)
1261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifs = iface->state;
1262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
1263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifs = iface->state = xzalloc(sizeof(*ifs));
1264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifs->state = DHS_INIT;
1266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifs->reason = "PREINIT";
1267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifs->nakoff = 1;
1268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	configure_interface(iface, argc, argv);
1269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & DHCPCD_TEST))
1270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		run_script(iface);
1271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We need to drop the leasefile so that start_interface
1272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * doesn't load it. */
1273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifs->options->options & DHCPCD_REQUEST)
1274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		unlink(iface->leasefile);
1275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifs->options->options & DHCPCD_LINK) {
1277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		switch (carrier_status(iface)) {
1278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 0:
1279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->carrier = LINK_DOWN;
1280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifs->reason = "NOCARRIER";
1281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 1:
1283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->carrier = LINK_UP;
1284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifs->reason = "CARRIER";
1285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		default:
1287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->carrier = LINK_UNKNOWN;
1288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
1289f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!(options & DHCPCD_TEST))
1291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			run_script(iface);
1292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else
1293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->carrier = LINK_UNKNOWN;
1294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_interface(int action, const char *ifname)
1298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifs, *ifp, *ifn, *ifl = NULL;
1300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const char * const argv[] = { ifname };
1301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int i;
1302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (action == -1) {
1304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifp = find_interface(ifname);
1305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifp != NULL)
1306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			stop_interface(ifp);
1307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* If running off an interface list, check it's in it. */
1311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifc) {
1312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (i = 0; i < ifc; i++)
1313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (strcmp(ifv[i], ifname) == 0)
1314f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				break;
1315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (i >= ifc)
1316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
1317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifs = discover_interfaces(-1, UNCONST(argv));
1320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifp = ifs; ifp; ifp = ifp->next) {
1321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(ifp->name, ifname) != 0)
1322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
1323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Check if we already have the interface */
1324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (ifn = ifaces; ifn; ifn = ifn->next) {
1325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (strcmp(ifn->name, ifp->name) == 0)
1326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				break;
1327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifl = ifn;
1328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
1329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifn) {
1330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* The flags and hwaddr could have changed */
1331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifn->flags = ifp->flags;
1332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifn->hwlen = ifp->hwlen;
1333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifp->hwlen != 0)
1334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				memcpy(ifn->hwaddr, ifp->hwaddr, ifn->hwlen);
1335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else {
1336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifl)
1337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifl->next = ifp;
1338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
1339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifaces = ifp;
1340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
1341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		init_state(ifp, 0, NULL);
1342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_interface(ifp);
1343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
1345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef RTM_CHGADDR
1347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_hwaddr(const char *ifname, unsigned char *hwaddr, size_t hwlen)
1349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp;
1351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo;
1352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifp = ifaces; ifp; ifp = ifp->next)
1354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(ifp->name, ifname) == 0 && ifp->hwlen <= hwlen) {
1355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifo = ifp->state->options;
1356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (!(ifo->options &
1357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    (DHCPCD_INFORM | DHCPCD_STATIC | DHCPCD_CLIENTID))
1358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    		    && ifp->state->new != NULL &&
1359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    ifp->state->new->cookie == htonl(MAGIC_COOKIE))
1360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			{
1361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_INFO,
1362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    "%s: expiring for new hardware address",
1363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    ifp->name);
1364a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				drop_dhcp(ifp, "EXPIRE");
1365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			memcpy(ifp->hwaddr, hwaddr, hwlen);
1367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifp->hwlen = hwlen;
1368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (!(ifo->options &
1369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    (DHCPCD_INFORM | DHCPCD_STATIC | DHCPCD_CLIENTID)))
1370e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			{
1371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_DEBUG, "%s: using hwaddr %s",
1372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    ifp->name,
1373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    		    hwaddr_ntoa(ifp->hwaddr, ifp->hwlen));
1374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifp->state->interval = 0;
1375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifp->state->nakoff = 1;
1376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				start_interface(ifp);
1377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
1379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(hwaddr);
1380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
1382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_ifa(int type, const char *ifname,
1385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    struct in_addr *addr, struct in_addr *net, struct in_addr *dst)
1386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
1387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp;
1388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo;
1389f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int i;
1390f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (addr->s_addr == INADDR_ANY)
1392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifp = ifaces; ifp; ifp = ifp->next)
1394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(ifp->name, ifname) == 0)
1395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifp == NULL)
1397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1398a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
1399a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (type == RTM_DELADDR) {
1400a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (ifp->state->new &&
1401a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		    ifp->state->new->yiaddr == addr->s_addr)
1402a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			syslog(LOG_INFO, "%s: removing IP address %s/%d",
1403a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			    ifp->name, inet_ntoa(ifp->state->lease.addr),
1404a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			    inet_ntocidr(ifp->state->lease.net));
1405a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		return;
1406a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
1407a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
1408a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (type != RTM_NEWADDR)
1409a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		return;
1410a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
1411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifo = ifp->state->options;
1412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)) == 0 ||
1413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    ifo->req_addr.s_addr != INADDR_ANY)
1414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1415a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
1416a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	free(ifp->state->old);
1417a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	ifp->state->old = ifp->state->new;
1418a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	ifp->state->new = dhcp_message_new(addr, net);
1419a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	ifp->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
1420a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (dst) {
1421a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		for (i = 1; i < 255; i++)
1422a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
1423a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				dhcp_message_add_addr(ifp->state->new, i, *dst);
1424a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
1425a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	ifp->state->reason = "STATIC";
1426a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	build_routes();
1427a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	run_script(ifp);
1428a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (ifo->options & DHCPCD_INFORM) {
1429a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ifp->state->state = DHS_INFORM;
1430a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ifp->state->xid = dhcp_xid(ifp);
1431a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ifp->state->lease.server.s_addr =
1432a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		    dst ? dst->s_addr : INADDR_ANY;
1433a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ifp->addr = *addr;
1434a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ifp->net = *net;
1435a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		send_inform(ifp);
1436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */
1440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_link(_unused void *arg)
1442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (manage_link(linkfd) == -1)
1444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR, "manage_link: %m");
1445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_reboot(struct interface *iface, int argc, char **argv)
1449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const struct if_options *ifo;
1451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int opt;
1452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifo = iface->state->options;
1454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	opt = ifo->options;
1455e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	configure_interface(iface, argc, argv);
1456e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifo = iface->state->options;
1457e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->interval = 0;
1458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
1459e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->addr.s_addr != ifo->req_addr.s_addr) ||
1460e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    (opt & (DHCPCD_INFORM | DHCPCD_STATIC) &&
1461e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
1462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
1463a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		drop_dhcp(iface, "EXPIRE");
1464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else {
1465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(iface->state->offer);
1466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->offer = NULL;
1467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	start_interface(iface);
1469e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtreconf_reboot(int action, int argc, char **argv, int oi)
1473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifl, *ifn, *ifp, *ifs, *ift;
1475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifs = discover_interfaces(argc - oi, argv + oi);
1477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifs == NULL)
1478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifp = ifs; ifp && (ift = ifp->next, 1); ifp = ift) {
1481e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifl = NULL;
1482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (ifn = ifaces; ifn; ifn = ifn->next) {
1483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (strcmp(ifn->name, ifp->name) == 0)
1484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
1485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifl = ifn;
1486f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifn) {
1488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (action)
1489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if_reboot(ifn, argc, argv);
1490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else if (ifn->state->new)
1491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				configure(ifn);
1492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free_interface(ifp);
1493f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		} else {
1494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifp->next = NULL;
1495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			init_state(ifp, argc, argv);
1496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			start_interface(ifp);
1497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifl)
1498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifl->next = ifp;
1499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
1500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifaces = ifp;
1501f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1502f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1503f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1504e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sort_interfaces();
1505f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
1506f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1507e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */
1508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
1509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_signal(_unused void *arg)
1510f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
1511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp, *ifl;
1512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_options *ifo;
1513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int sig = signal_read();
1514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int do_release, do_rebind, i;
1515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	do_rebind = do_release = 0;
1517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	switch (sig) {
1518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case SIGINT:
1519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "received SIGINT, stopping");
1520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		break;
1521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case SIGTERM:
1522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "received SIGTERM, stopping");
1523e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		break;
1524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case SIGALRM:
15250c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff#ifdef ANDROID
15260c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff		syslog(LOG_INFO, "received SIGALRM, renewing");
15270c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff		for (ifp = ifaces; ifp; ifp = ifp->next) {
15280c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff			start_renew(ifp);
15290c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff		}
15300c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff#else
1531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "received SIGALRM, rebinding");
1532e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (i = 0; i < ifac; i++)
1533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free(ifav[i]);
1534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(ifav);
1535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifav = NULL;
1536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifac = 0;
1537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (i = 0; i < ifdc; i++)
1538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free(ifdv[i]);
1539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(ifdv);
1540e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifdc = 0;
1541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifdv = NULL;
1542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifo = read_config(cffile, NULL, NULL, NULL);
1543e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_options(ifo, margc, margv);
1544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* We need to preserve these two options. */
1545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (options & DHCPCD_MASTER)
1546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifo->options |= DHCPCD_MASTER;
1547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (options & DHCPCD_DAEMONISED)
1548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifo->options |= DHCPCD_DAEMONISED;
1549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		options = ifo->options;
1550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free_options(ifo);
1551a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		reconf_reboot(1, ifc, ifv, 0);
15520c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff#endif
1553e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case SIGHUP:
1555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "received SIGHUP, releasing");
1556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		do_release = 1;
1557e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		break;
1558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case SIGUSR1:
1559e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "received SIGUSR, reconfiguring");
1560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (ifp = ifaces; ifp; ifp = ifp->next)
1561e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifp->state->new)
1562e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				configure(ifp);
1563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	case SIGPIPE:
1565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_WARNING, "received SIGPIPE");
1566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	default:
1568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR,
1569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    "received signal %d, but don't know what to do with it",
1570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    sig);
1571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
1572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1573f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_TEST)
1575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_FAILURE);
1576f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1577a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	/* As drop_dhcp could re-arrange the order, we do it like this. */
1578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (;;) {
1579e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Be sane and drop the last config first */
1580e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifl = NULL;
1581e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (ifp = ifaces; ifp; ifp = ifp->next) {
1582e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifp->next == NULL)
1583e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
1584e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifl = ifp;
1585f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifp == NULL)
1587e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifp->carrier != LINK_DOWN &&
1589e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    (do_release ||
1590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifp->state->options->options & DHCPCD_RELEASE))
1591e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			send_release(ifp);
1592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		stop_interface(ifp);
1593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1594e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	exit(EXIT_FAILURE);
1595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
1596f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1597f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
1598e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_args(struct fd_list *fd, int argc, char **argv)
1599f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
1600e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp;
1601e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int do_exit = 0, do_release = 0, do_reboot = 0, do_reconf = 0;
1602e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int opt, oi = 0;
1603e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ssize_t len;
1604e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t l;
1605e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct iovec iov[2];
1606e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *tmp, *p;
1607e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1608e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (fd != NULL) {
1609e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Special commands for our control socket */
1610e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(*argv, "--version") == 0) {
1611e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			len = strlen(VERSION) + 1;
1612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[0].iov_base = &len;
1613e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[0].iov_len = sizeof(ssize_t);
1614e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[1].iov_base = UNCONST(VERSION);
1615e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[1].iov_len = len;
1616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (writev(fd->fd, iov, 2) == -1) {
1617e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "writev: %m");
1618e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				return -1;
1619e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1620e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return 0;
1621e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (strcmp(*argv, "--getconfigfile") == 0) {
1622e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			len = strlen(cffile ? cffile : CONFIG) + 1;
1623e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[0].iov_base = &len;
1624e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[0].iov_len = sizeof(ssize_t);
1625e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[1].iov_base = cffile ? cffile : UNCONST(CONFIG);
1626e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iov[1].iov_len = len;
1627e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (writev(fd->fd, iov, 2) == -1) {
1628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "writev: %m");
1629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				return -1;
1630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return 0;
1632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (strcmp(*argv, "--getinterfaces") == 0) {
1633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			len = 0;
1634e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (argc == 1) {
1635a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				for (ifp = ifaces; ifp; ifp = ifp->next) {
1636e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					len++;
1637a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt					if (ifp->ras)
1638a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt						len++;
1639a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				}
1640e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				len = write(fd->fd, &len, sizeof(len));
1641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (len != sizeof(len))
1642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					return -1;
1643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				for (ifp = ifaces; ifp; ifp = ifp->next)
1644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					send_interface(fd->fd, ifp);
1645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				return 0;
1646e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1647e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			opt = 0;
1648e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			while (argv[++opt] != NULL) {
1649e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				for (ifp = ifaces; ifp; ifp = ifp->next)
1650a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt					if (strcmp(argv[opt], ifp->name) == 0) {
1651e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt						len++;
1652a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt						if (ifp->ras)
1653a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt							len++;
1654a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt					}
1655e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1656e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			len = write(fd->fd, &len, sizeof(len));
1657e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (len != sizeof(len))
1658e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				return -1;
1659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			opt = 0;
1660e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			while (argv[++opt] != NULL) {
1661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				for (ifp = ifaces; ifp; ifp = ifp->next)
1662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					if (strcmp(argv[opt], ifp->name) == 0)
1663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt						send_interface(fd->fd, ifp);
1664e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return 0;
1666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (strcmp(*argv, "--listen") == 0) {
1667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			fd->listener = 1;
1668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return 0;
1669e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
1670f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1671f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1672e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Log the command */
1673e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	len = 0;
1674e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (opt = 0; opt < argc; opt++)
1675e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		len += strlen(argv[opt]) + 1;
1676e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	tmp = p = xmalloc(len + 1);
1677e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (opt = 0; opt < argc; opt++) {
1678e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		l = strlen(argv[opt]);
1679e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		strlcpy(p, argv[opt], l + 1);
1680e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		p += l;
1681e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*p++ = ' ';
1682e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1683e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*--p = '\0';
1684e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_INFO, "control command: %s", tmp);
1685e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(tmp);
1686f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1687e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	optind = 0;
1688e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
1689f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{
1690f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		switch (opt) {
1691e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'g':
1692e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			do_reconf = 1;
1693e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1694e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'k':
1695e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			do_release = 1;
1696e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1697e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'n':
1698e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			do_reboot = 1;
1699e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1700e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'x':
1701e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			do_exit = 1;
1702f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
1703f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1704f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1705f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1706e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We need at least one interface */
1707e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (optind == argc) {
1708e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR, "handle_args: no interface");
1709e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
1710f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1711f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1712e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (do_release || do_exit) {
1713e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (oi = optind; oi < argc; oi++) {
1714e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			for (ifp = ifaces; ifp; ifp = ifp->next)
1715e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (strcmp(ifp->name, argv[oi]) == 0)
1716f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project					break;
1717e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (!ifp)
1718f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				continue;
1719e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (do_release)
1720e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifp->state->options->options |= DHCPCD_RELEASE;
1721e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifp->state->options->options & DHCPCD_RELEASE &&
1722e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    ifp->carrier != LINK_DOWN)
1723e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				send_release(ifp);
1724e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			stop_interface(ifp);
1725f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1726e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return 0;
1727e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1728e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1729e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	reconf_reboot(do_reboot, argc, argv, optind);
1730e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return 0;
1731e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1732e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1733e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1734e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtopen_sockets(struct interface *iface)
1735e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1736e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->raw_fd == -1) {
1737e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (open_socket(iface, ETHERTYPE_IP) == -1)
1738e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: open_socket: %m", iface->name);
1739e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
1740e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			add_event(iface->raw_fd, handle_dhcp_packet, iface);
1741e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->udp_fd == -1 &&
1743e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->addr.s_addr != 0 &&
1744e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->state->new != NULL &&
1745e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    (iface->state->new->cookie == htonl(MAGIC_COOKIE) ||
1746e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    iface->state->options->options & DHCPCD_INFORM))
1747e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
1748e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (open_udp_socket(iface) == -1 && errno != EADDRINUSE)
1749e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: open_udp_socket: %m", iface->name);
1750e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1751e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1752e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1753e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
1754e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtclose_sockets(struct interface *iface)
1755e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->arp_fd != -1) {
1757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		delete_event(iface->arp_fd);
1758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(iface->arp_fd);
1759e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->arp_fd = -1;
1760e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1761e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->raw_fd != -1) {
1762e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		delete_event(iface->raw_fd);
1763e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(iface->raw_fd);
1764e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->raw_fd = -1;
1765e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1766e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->udp_fd != -1) {
1767e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* we don't listen to events on the udp */
1768e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(iface->udp_fd);
1769e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->udp_fd = -1;
1770e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1771e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
1772e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
17730545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID
17740545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidtvoid switchUser(void)
17750545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt{
17760545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	gid_t groups[] = { AID_INET, AID_SHELL };
17770545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	struct __user_cap_header_struct header;
17780545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	struct __user_cap_data_struct cap;
17790545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt
17800545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	setgroups(sizeof(groups)/sizeof(groups[0]), groups);
17810545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt
17820545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
17830545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt
17840545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	setgid(AID_DHCP);
17850545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	setuid(AID_DHCP);
17860545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	header.version = _LINUX_CAPABILITY_VERSION;
17870545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	header.pid = 0;
17880545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	cap.effective = cap.permitted =
17890545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
17900545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		(1 << CAP_NET_BROADCAST) | (1 << CAP_NET_BIND_SERVICE);
17910545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	cap.inheritable = 0;
17920545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	capset(&header, &cap);
17930545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt}
17940545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif /* ANDROID */
17950545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt
1796e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
1797e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmain(int argc, char **argv)
1798e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
1799e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface;
1800e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int opt, oi = 0, signal_fd, sig = 0, i, control_fd;
1801e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t len;
1802e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	pid_t pid;
1803e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timespec ts;
1804e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
18050545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID
180648d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff	/* Reuse system properties for a p2p interface */
180748d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff	char p2p_interface[PROPERTY_KEY_MAX];
18080545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	switchUser();
18090545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
1810e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	closefrom(3);
1811e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	openlog(PACKAGE, LOG_PERROR | LOG_PID, LOG_DAEMON);
1812e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	setlogmask(LOG_UPTO(LOG_INFO));
1813e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1814e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Test for --help and --version */
1815e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (argc > 1) {
1816e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (strcmp(argv[1], "--help") == 0) {
1817f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			usage();
1818e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_SUCCESS);
1819e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (strcmp(argv[1], "--version") == 0) {
1820e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			printf(""PACKAGE" "VERSION"\n%s\n", copyright);
1821e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_SUCCESS);
1822f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1823f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1824f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1825e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	i = 0;
1826e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
1827f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{
1828f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		switch (opt) {
1829f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case 'f':
1830e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			cffile = optarg;
1831e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
1832e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'g':
1833e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			sig = SIGUSR1;
1834f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
1835f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case 'k':
1836f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			sig = SIGHUP;
1837f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
1838f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case 'n':
1839f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			sig = SIGALRM;
1840f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
1841f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case 'x':
1842f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			sig = SIGTERM;
1843f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
1844f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case 'T':
1845e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			i = 1;
1846f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
1847e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'U':
1848e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			i = 2;
1849f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
18500d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync		case 'a':
18510d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync			avoid_routes = 1;
18520d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync			break;
1853e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case 'V':
1854e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			print_options();
1855e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_SUCCESS);
1856e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		case '?':
1857e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			usage();
1858e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
1859f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1860f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1861f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1862e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	margv = argv;
1863e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	margc = argc;
1864e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if_options = read_config(cffile, NULL, NULL, NULL);
1865e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	opt = add_options(if_options, argc, argv);
1866e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (opt != 1) {
1867e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (opt == 0)
1868e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			usage();
1869e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_FAILURE);
1870e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1871e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	options = if_options->options;
1872e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (i != 0) {
1873e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (i == 1)
1874e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			options |= DHCPCD_TEST;
1875e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
1876e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			options |= DHCPCD_DUMPLEASE;
1877e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		options |= DHCPCD_PERSISTENT;
1878e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		options &= ~DHCPCD_DAEMONISE;
1879e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1880e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1881f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef THERE_IS_NO_FORK
1882e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	options &= ~DHCPCD_DAEMONISE;
1883f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
1884f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1885e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_DEBUG)
1886e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		setlogmask(LOG_UPTO(LOG_DEBUG));
1887e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_QUIET)
1888e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(STDERR_FILENO);
1889e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
1890e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & (DHCPCD_TEST | DHCPCD_DUMPLEASE))) {
1891e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* If we have any other args, we should run as a single dhcpcd
1892e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 *  instance for that interface. */
1893e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		len = strlen(PIDFILE) + IF_NAMESIZE + 2;
1894e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		pidfile = xmalloc(len);
1895e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (optind == argc - 1)
1896e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			snprintf(pidfile, len, PIDFILE, "-", argv[optind]);
1897e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else {
1898e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			snprintf(pidfile, len, PIDFILE, "", "");
1899e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			options |= DHCPCD_MASTER;
1900f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1901e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
1902f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1903e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (chdir("/") == -1)
1904e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR, "chdir `/': %m");
1905e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	atexit(cleanup);
1906f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1907e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_DUMPLEASE) {
1908e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (optind != argc - 1) {
1909e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "dumplease requires an interface");
1910e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
1911f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1912e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifaces = iface = xzalloc(sizeof(*iface));
1913e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		strlcpy(iface->name, argv[optind], sizeof(iface->name));
1914e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		snprintf(iface->leasefile, sizeof(iface->leasefile),
1915e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    LEASEFILE, iface->name);
1916e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state = xzalloc(sizeof(*iface->state));
1917e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->options = xzalloc(sizeof(*iface->state->options));
1918e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		strlcpy(iface->state->options->script, if_options->script,
1919e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    sizeof(iface->state->options->script));
1920e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->new = read_lease(iface);
1921e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->state->new == NULL && errno == ENOENT) {
1922e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			strlcpy(iface->leasefile, argv[optind],
1923e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    sizeof(iface->leasefile));
1924e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->state->new = read_lease(iface);
1925e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
1926e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->state->new == NULL) {
1927e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (errno == ENOENT)
1928e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "%s: no lease to dump",
1929e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    iface->name);
1930e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
1931e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
1932e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->reason = "DUMP";
1933e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		run_script(iface);
1934e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_SUCCESS);
1935f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1936f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
1937e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) {
1938e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		control_fd = open_control();
1939e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (control_fd != -1) {
1940e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_INFO,
1941e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "sending commands to master dhcpcd process");
1942e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			i = send_control(argc, argv);
1943e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (i > 0) {
1944e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_DEBUG, "send OK");
1945e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				exit(EXIT_SUCCESS);
1946e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			} else {
1947e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "failed to send commands");
1948e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				exit(EXIT_FAILURE);
1949e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
1950e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else {
1951e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (errno != ENOENT)
1952e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "open_control: %m");
1953f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
1954f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
1955f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
19560545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifndef ANDROID
19570545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt	/* android runs us as user "dhcp" */
1958e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (geteuid())
1959e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_WARNING,
1960e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    PACKAGE " will not work correctly unless run as root");
19610545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
1962e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (sig != 0) {
19630545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID
19640545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		char pidpropname[PROPERTY_KEY_MAX];
19650545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		char pidpropval[PROPERTY_VALUE_MAX];
19660545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt
196798564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt		if (optind != argc - 1) {
196898564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt			syslog(LOG_ERR, "Android requires an interface");
196998564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt			exit(EXIT_FAILURE);
197098564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt		}
197198564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt
197248d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff		if (strncmp(argv[optind], "p2p", 3) == 0) {
197348d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff			strncpy(p2p_interface, "p2p", sizeof(p2p_interface));
197448d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff		} else {
197548d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff			strncpy(p2p_interface, argv[optind], sizeof(p2p_interface));
197648d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff		}
197748d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff
19780545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		if (snprintf(pidpropname,
19790545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt			     sizeof(pidpropname),
198048d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff			     "dhcp.%s.pid", p2p_interface) >= PROPERTY_KEY_MAX)
19810545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt			exit(EXIT_FAILURE);
19820545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		property_get(pidpropname, pidpropval, NULL);
19830545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		if (strlen(pidpropval) == 0)
19840545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt			exit(EXIT_FAILURE);
19850545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		pid = atoi(pidpropval);
19860545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#else
1987e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		pid = read_pid();
19880545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
1989e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (pid != 0)
1990e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_INFO, "sending signal %d to pid %d",
1991e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    sig, pid);
1992e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (pid == 0 || kill(pid, sig) != 0) {
1993f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			if (sig != SIGALRM)
1994e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, ""PACKAGE" not running");
1995e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (pid != 0 && errno != ESRCH) {
1996e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "kill: %m");
1997e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				exit(EXIT_FAILURE);
1998f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			}
1999e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			unlink(pidfile);
2000e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (sig != SIGALRM)
2001e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				exit(EXIT_FAILURE);
2002e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else {
2003a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (sig == SIGALRM || sig == SIGUSR1)
2004e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				exit(EXIT_SUCCESS);
2005f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			/* Spin until it exits */
2006e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_INFO, "waiting for pid %d to exit", pid);
2007f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			ts.tv_sec = 0;
2008f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			ts.tv_nsec = 100000000; /* 10th of a second */
2009f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			for(i = 0; i < 100; i++) {
2010f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				nanosleep(&ts, NULL);
2011e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (read_pid() == 0)
2012e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					exit(EXIT_SUCCESS);
2013f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			}
2014e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "pid %d failed to exit", pid);
2015e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
2016f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
2017f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
2018f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
2019e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & DHCPCD_TEST)) {
20200545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID
20210545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		char pidpropname[PROPERTY_KEY_MAX];
20220545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt		char pidpropval[PROPERTY_VALUE_MAX];
20230545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
20240545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifndef ANDROID
2025e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if ((pid = read_pid()) > 0 &&
2026f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		    kill(pid, 0) == 0)
2027f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		{
2028e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, ""PACKAGE
2029e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    " already running on pid %d (%s)",
2030e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    pid, pidfile);
2031e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
2032f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
2033e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2034e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Ensure we have the needed directories */
2035a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST)
2036e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "mkdir `%s': %m", RUNDIR);
2037a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (mkdir(DBDIR, 0755) == -1 && errno != EEXIST)
2038e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "mkdir `%s': %m", DBDIR);
20390545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
2040a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
2041e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		pidfd = open(pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0664);
2042a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (pidfd == -1)
2043e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "open `%s': %m", pidfile);
2044a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		else {
2045a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			/* Lock the file so that only one instance of dhcpcd
2046a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			 * runs on an interface */
2047a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (flock(pidfd, LOCK_EX | LOCK_NB) == -1) {
2048a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				syslog(LOG_ERR, "flock `%s': %m", pidfile);
2049a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				exit(EXIT_FAILURE);
2050a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			}
2051a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (set_cloexec(pidfd) == -1)
2052a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				exit(EXIT_FAILURE);
20530545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID
2054a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (optind != argc - 1) {
2055a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				syslog(LOG_ERR, "Android requires an interface");
2056a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				exit(EXIT_FAILURE);
2057a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			}
205898564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt
2059a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (strncmp(argv[optind], "p2p", 3) == 0) {
2060a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				strncpy(p2p_interface, "p2p", sizeof(p2p_interface));
2061a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			} else {
2062a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				strncpy(p2p_interface, argv[optind], sizeof(p2p_interface));
2063a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			}
206448d5a1d50750ffa5d14b64841fc7e81dadafd1a4Irfan Sheriff
2065a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (snprintf(pidpropname,
2066a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				     sizeof(pidpropname),
2067a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				     "dhcp.%s.pid", p2p_interface) >= PROPERTY_KEY_MAX)
2068a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				exit(EXIT_FAILURE);
2069a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			if (snprintf(pidpropval, sizeof(pidpropval), "%d", getpid()) >= PROPERTY_VALUE_MAX)
2070a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				exit(EXIT_FAILURE);
2071a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			property_set(pidpropname, pidpropval);
20720545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#else
2073a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			writepid(pidfd, getpid());
20740545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif
2075a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		}
2076e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
2077e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2078e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	syslog(LOG_INFO, "version " VERSION " starting");
2079e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2080e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((signal_fd = signal_init()) == -1)
2081e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_FAILURE);
2082e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (signal_setup() == -1)
2083e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_FAILURE);
2084e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	add_event(signal_fd, handle_signal, NULL);
2085e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2086e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_MASTER) {
2087a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (start_control() == -1)
2088e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "start_control: %m");
2089e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
2090f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
2091e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (init_sockets() == -1) {
2092e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR, "init_socket: %m");
2093e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		exit(EXIT_FAILURE);
2094e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
2095e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (if_options->options & DHCPCD_LINK) {
2096e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		linkfd = open_link_socket();
2097e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (linkfd == -1)
2098e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "open_link_socket: %m");
2099e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
2100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			add_event(linkfd, handle_link, NULL);
2101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
2102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
2103a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#if 0
2104a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) {
2105a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		syslog(LOG_ERR, "ipv6rs: %m");
2106a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		options &= ~DHCPCD_IPV6RS;
2107a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
2108a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif
2109a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
2110a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (options & DHCPCD_IPV6RS && !check_ipv6(NULL))
2111a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		options &= ~DHCPCD_IPV6RS;
2112a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (options & DHCPCD_IPV6RS) {
2113a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		ipv6rsfd = ipv6rs_open();
2114a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (ipv6rsfd == -1) {
2115a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			syslog(LOG_ERR, "ipv6rs: %m");
2116a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			options &= ~DHCPCD_IPV6RS;
2117a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		} else {
2118a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			add_event(ipv6rsfd, ipv6rs_handledata, NULL);
2119a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt//			atexit(restore_rtadv);
2120a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		}
2121a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	}
2122a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
2123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifc = argc - optind;
2124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifv = argv + optind;
2125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* When running dhcpcd against a single interface, we need to retain
2127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * the old behaviour of waiting for an IP address */
2128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifc == 1)
2129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		options |= DHCPCD_WAITIP;
2130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifaces = discover_interfaces(ifc, ifv);
2132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 0; i < ifc; i++) {
2133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (iface = ifaces; iface; iface = iface->next)
2134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (strcmp(iface->name, ifv[i]) == 0)
2135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
2136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!iface)
2137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: interface not found or invalid",
2138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    ifv[i]);
2139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
2140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!ifaces) {
2141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifc == 0)
2142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "no valid interfaces found");
2143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
2144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
2145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!(options & DHCPCD_LINK)) {
2146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR,
2147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "aborting as link detection is disabled");
2148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
2149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
2150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
2151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
2152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (options & DHCPCD_BACKGROUND)
2153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		daemonise();
2154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
2155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	opt = 0;
2156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (iface = ifaces; iface; iface = iface->next) {
2157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		init_state(iface, argc, argv);
2158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->carrier != LINK_DOWN)
2159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			opt = 1;
2160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
2161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!(options & DHCPCD_BACKGROUND)) {
2163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* If we don't have a carrier, we may have to wait for a second
2164a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		 * before one becomes available if we brought an interface up */
2165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (opt == 0 &&
2166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    options & DHCPCD_LINK &&
2167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    options & DHCPCD_WAITUP &&
2168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    !(options & DHCPCD_WAITIP))
2169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
2170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ts.tv_sec = 1;
2171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ts.tv_nsec = 0;
2172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			nanosleep(&ts, NULL);
2173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			for (iface = ifaces; iface; iface = iface->next) {
2174a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				handle_carrier(0, 0, iface->name);
2175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (iface->carrier != LINK_DOWN) {
2176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					opt = 1;
2177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
2178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				}
2179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
2180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
2181a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (options & DHCPCD_MASTER)
2182a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			i = if_options->timeout;
2183a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		else
2184a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			i = ifaces->state->options->timeout;
2185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (opt == 0 &&
2186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    options & DHCPCD_LINK &&
2187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    !(options & DHCPCD_WAITIP))
2188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
2189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_WARNING, "no interfaces have a carrier");
2190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			daemonise();
2191a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		} else if (i > 0) {
2192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (options & DHCPCD_IPV4LL)
2193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				options |= DHCPCD_TIMEOUT_IPV4LL;
2194a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			add_timeout_sec(i, handle_exit_timeout, NULL);
2195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
2196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
2197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free_options(if_options);
2198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if_options = NULL;
2199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sort_interfaces();
2201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (iface = ifaces; iface; iface = iface->next)
2202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_sec(0, start_interface, iface);
2203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
2204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	start_eloop();
2205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	exit(EXIT_SUCCESS);
2206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
2207