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