1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/*
2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon
3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * Copyright (c) 2006-2011 Roy Marples <roy@marples.name>
4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * All rights reserved
5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Redistribution and use in source and binary forms, with or without
7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * modification, are permitted provided that the following conditions
8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * are met:
9f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
10f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
11f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
12f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *    documentation and/or other materials provided with the distribution.
14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *
15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * SUCH DAMAGE.
26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */
27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/types.h>
29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/ioctl.h>
30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/param.h>
31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/socket.h>
32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/time.h>
33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <arpa/inet.h>
35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <net/if.h>
36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <net/if_arp.h>
37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK
38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  include <net/if_dl.h>
39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  include <net/if_types.h>
40f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <netinet/in_systm.h>
42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/in.h>
43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/ip.h>
44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <netinet/udp.h>
46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#undef __FAVOR_BSD
47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_PACKET
48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  include <netpacket/packet.h>
49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA
51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  include <net/if_media.h>
52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <ctype.h>
55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h>
56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <ifaddrs.h>
57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <fnmatch.h>
58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stddef.h>
59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h>
60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h>
61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h>
62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h>
63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h>
64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
65f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h"
66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h"
67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h"
68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h"
69a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#include "ipv6rs.h"
70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h"
71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "signals.h"
72f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char hwaddr_buffer[(HWADDR_LEN * 3) + 1];
74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint socket_afnet = -1;
76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
77a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#if defined(__FreeBSD__) && defined(DEBUG_MEMORY)
78a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt/* FreeBSD does not zero the struct, causing valgrind errors */
79a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtunsigned int
80a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtif_nametoindex(const char *ifname)
81a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{
82a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	struct ifreq ifr;
83a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
84a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	memset(&ifr, 0, sizeof(ifr));
85a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
86a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (ioctl(socket_afnet, SIOCGIFINDEX, &ifr) != -1)
87a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		return ifr.ifr_index;
88a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	return 0;
89a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt}
90a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif
91a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectinet_ntocidr(struct in_addr address)
94f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
95f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int cidr = 0;
96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint32_t mask = htonl(address.s_addr);
97f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
98f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	while (mask) {
99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		cidr++;
100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		mask <<= 1;
101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return cidr;
103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectinet_cidrtoaddr(int cidr, struct in_addr *addr)
107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int ocets;
109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (cidr < 1 || cidr > 32) {
111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		errno = EINVAL;
112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ocets = (cidr + 7) / 8;
115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	addr->s_addr = 0;
117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (ocets > 0) {
118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		memset(&addr->s_addr, 255, (size_t)ocets - 1);
119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		memset((unsigned char *)&addr->s_addr + (ocets - 1),
120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    (256 - (1 << (32 - cidr) % 8)), 1);
121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
126f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectuint32_t
127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_netmask(uint32_t addr)
128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
129f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint32_t dst;
130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
131f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (addr == 0)
132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return 0;
133f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
134f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	dst = htonl(addr);
135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (IN_CLASSA(dst))
136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return ntohl(IN_CLASSA_NET);
137938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (IN_CLASSB(dst))
138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return ntohl(IN_CLASSB_NET);
139938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (IN_CLASSC(dst))
140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return ntohl(IN_CLASSC_NET);
141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectchar *
146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecthwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *p = hwaddr_buffer;
149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	size_t i;
150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	for (i = 0; i < hwlen && i < HWADDR_LEN; i++) {
152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (i > 0)
153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			*p ++= ':';
154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		p += snprintf(p, 3, "%.2x", hwaddr[i]);
155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	*p ++= '\0';
158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return hwaddr_buffer;
160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectsize_t
163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecthwaddr_aton(unsigned char *buffer, const char *addr)
164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	char c[3];
166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const char *p = addr;
167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	unsigned char *bp = buffer;
168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	size_t len = 0;
169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	c[2] = '\0';
171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	while (*p) {
172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		c[0] = *p++;
173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		c[1] = *p++;
174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		/* Ensure that digits are hex */
175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (isxdigit((unsigned char)c[0]) == 0 ||
176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		    isxdigit((unsigned char)c[1]) == 0)
177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		{
178f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			errno = EINVAL;
179f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			return 0;
180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		/* We should have at least two entries 00:01 */
182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (len == 0 && *p == '\0') {
183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			errno = EINVAL;
184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			return 0;
185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		/* Ensure that next data is EOL or a seperator with data */
187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) {
188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			errno = EINVAL;
189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			return 0;
190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (*p)
192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			p++;
193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (bp)
194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			*bp++ = (unsigned char)strtol(c, NULL, 16);
195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		len++;
196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return len;
198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct interface *
201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtinit_interface(const char *ifname)
202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct ifreq ifr;
204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = NULL;
205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memset(&ifr, 0, sizeof(ifr));
207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1)
209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		goto eexit;
210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface = xzalloc(sizeof(*iface));
212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	strlcpy(iface->name, ifname, sizeof(iface->name));
213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->flags = ifr.ifr_flags;
214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We reserve the 100 range for virtual interfaces, if and when
215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * we can work them out. */
216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->metric = 200 + if_nametoindex(iface->name);
217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (getifssid(ifname, iface->ssid) != -1) {
218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->wireless = 1;
219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->metric += 100;
220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ioctl(socket_afnet, SIOCGIFMTU, &ifr) == -1)
223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		goto eexit;
224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Ensure that the MTU is big enough for DHCP */
225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ifr.ifr_mtu < MTU_MIN) {
226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifr.ifr_mtu = MTU_MIN;
227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ioctl(socket_afnet, SIOCSIFMTU, &ifr) == -1)
229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			goto eexit;
230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
231f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	snprintf(iface->leasefile, sizeof(iface->leasefile),
233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    LEASEFILE, ifname);
234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* 0 is a valid fd, so init to -1 */
235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->raw_fd = -1;
236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->udp_fd = -1;
237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->arp_fd = -1;
238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	goto exit;
239f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidteexit:
241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface);
242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface = NULL;
243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtexit:
244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return iface;
245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfree_interface(struct interface *iface)
249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!iface)
251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
252a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	ipv6rs_free(iface);
253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state) {
254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free_options(iface->state->options);
255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(iface->state->old);
256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(iface->state->new);
257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(iface->state->offer);
258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(iface->state);
259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
260a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	free(iface->buffer);
261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface->clientid);
262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface);
263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtcarrier_status(struct interface *iface)
267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int ret;
269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct ifreq ifr;
270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA
271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct ifmediareq ifmr;
272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__
274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	char *p;
275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__
280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We can only test the real interface up */
281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if ((p = strchr(ifr.ifr_name, ':')))
282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		*p = '\0';
283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1)
286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->flags = ifr.ifr_flags;
288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ret = -1;
290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA
291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memset(&ifmr, 0, sizeof(ifmr));
292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name));
293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ioctl(socket_afnet, SIOCGIFMEDIA, &ifmr) != -1 &&
294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    ifmr.ifm_status & IFM_AVALID)
295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ret = (ifmr.ifm_status & IFM_ACTIVE) ? 1 : 0;
296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ret == -1)
298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ret = (ifr.ifr_flags & IFF_RUNNING) ? 1 : 0;
299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return ret;
300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtup_interface(struct interface *iface)
304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct ifreq ifr;
306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int retval = -1;
307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__
308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	char *p;
309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef __linux__
314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We can only bring the real interface up */
315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if ((p = strchr(ifr.ifr_name, ':')))
316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		*p = '\0';
317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == 0) {
319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if ((ifr.ifr_flags & IFF_UP))
320f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			retval = 0;
321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else {
322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifr.ifr_flags |= IFF_UP;
323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ioctl(socket_afnet, SIOCSIFFLAGS, &ifr) == 0)
324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				retval = 0;
325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->flags = ifr.ifr_flags;
327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return retval;
329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct interface *
332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdiscover_interfaces(int argc, char * const *argv)
333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct ifaddrs *ifaddrs, *ifa;
335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *p;
336a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	int i, sdl_type;
337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *ifp, *ifs, *ifl;
338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __linux__
339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char ifn[IF_NAMESIZE];
340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK
342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const struct sockaddr_dl *sdl;
343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef IFLR_ACTIVE
344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct if_laddrreq iflr;
345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int socket_aflink;
346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	socket_aflink = socket(AF_LINK, SOCK_DGRAM, 0);
348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (socket_aflink == -1)
349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return NULL;
350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memset(&iflr, 0, sizeof(iflr));
351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif AF_PACKET
353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const struct sockaddr_ll *sll;
354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (getifaddrs(&ifaddrs) == -1)
357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return NULL;
358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ifs = ifl = NULL;
360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifa->ifa_addr != NULL) {
362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK
363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifa->ifa_addr->sa_family != AF_LINK)
364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif AF_PACKET
366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifa->ifa_addr->sa_family != AF_PACKET)
367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* It's possible for an interface to have >1 AF_LINK.
372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * For our purposes, we use the first one. */
373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (ifp = ifs; ifp; ifp = ifp->next)
374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (strcmp(ifp->name, ifa->ifa_name) == 0)
375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifp)
377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (argc > 0) {
379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			for (i = 0; i < argc; i++) {
380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __linux__
381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				/* Check the real interface name */
382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				strlcpy(ifn, argv[i], sizeof(ifn));
383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				p = strchr(ifn, ':');
384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (p)
385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					*p = '\0';
386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (strcmp(ifn, ifa->ifa_name) == 0)
387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#else
389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (strcmp(argv[i], ifa->ifa_name) == 0)
390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (i == argc)
394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			p = argv[i];
396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else {
397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* -1 means we're discovering against a specific
398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * interface, but we still need the below rules
399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			 * to apply. */
400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0)
401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			for (i = 0; i < ifdc; i++)
403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (!fnmatch(ifdv[i], ifa->ifa_name, 0))
404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (i < ifdc)
406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			for (i = 0; i < ifac; i++)
408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (!fnmatch(ifav[i], ifa->ifa_name, 0))
409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifac && i == ifac)
411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			p = ifa->ifa_name;
413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if ((ifp = init_interface(p)) == NULL)
415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Bring the interface up if not already */
418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!(ifp->flags & IFF_UP)
419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef SIOCGIFMEDIA
420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    && carrier_status(ifp) != -1
421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		   )
423e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (up_interface(ifp) == 0)
425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				options |= DHCPCD_WAITUP;
426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_ERR, "%s: up_interface: %m", ifp->name);
428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
430a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		sdl_type = 0;
431e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Don't allow loopback unless explicit */
432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifp->flags & IFF_LOOPBACK) {
433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (argc == 0 && ifac == 0) {
434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free_interface(ifp);
435e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else if (ifa->ifa_addr != NULL) {
438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef AF_LINK
439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr;
440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef IFLR_ACTIVE
442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* We need to check for active address */
443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			strlcpy(iflr.iflr_name, ifp->name,
444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    sizeof(iflr.iflr_name));
445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			memcpy(&iflr.addr, ifa->ifa_addr,
446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iflr.flags = IFLR_PREFIX;
448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iflr.prefixlen = sdl->sdl_alen * NBBY;
449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ioctl(socket_aflink, SIOCGLIFADDR, &iflr) == -1 ||
450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    !(iflr.flags & IFLR_ACTIVE))
451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			{
452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free_interface(ifp);
453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
457a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			sdl_type = sdl->sdl_type;
458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			switch(sdl->sdl_type) {
459a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			case IFT_BRIDGE: /* FALLTHROUGH */
460a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			case IFT_L2VLAN: /* FALLTHOUGH */
461a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			case IFT_L3IPVLAN: /* FALLTHROUGH */
462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			case IFT_ETHER:
463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifp->family = ARPHRD_ETHER;
464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			case IFT_IEEE1394:
466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				ifp->family = ARPHRD_IEEE1394;
467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
468a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#ifdef IFT_INFINIBAND
469a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			case IFT_INFINIBAND:
470a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				ifp->family = ARPHRD_INFINIBAND;
471a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				break;
472a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif
473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifp->hwlen = sdl->sdl_alen;
475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef CLLADDR
476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#elif AF_PACKET
480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr;
481a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			ifp->family = sdl_type = sll->sll_hatype;
482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifp->hwlen = sll->sll_halen;
483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (ifp->hwlen != 0)
484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
487f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* We only work on ethernet by default */
489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (!(ifp->flags & IFF_POINTOPOINT) &&
490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    ifp->family != ARPHRD_ETHER)
491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (argc == 0 && ifac == 0) {
493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free_interface(ifp);
494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			switch (ifp->family) {
497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			case ARPHRD_IEEE1394: /* FALLTHROUGH */
498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			case ARPHRD_INFINIBAND:
499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				/* We don't warn for supported families */
500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				break;
501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			default:
502e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				syslog(LOG_WARNING,
503a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				    "%s: unsupported interface type %.2x"
504a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				    ", falling back to ethernet",
505a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				    ifp->name, sdl_type);
506a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				ifp->family = ARPHRD_ETHER;
507a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt				break;
508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
510e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Handle any platform init for the interface */
512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (if_init(ifp) == -1) {
513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "%s: if_init: %m", p);
514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free_interface(ifp);
515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifl)
519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifl->next = ifp;
520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			ifs = ifp;
522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ifl = ifp;
523f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	freeifaddrs(ifaddrs);
525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
526e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef IFLR_ACTIVE
527e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	close(socket_aflink);
528e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
529f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
530e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return ifs;
531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
532f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdo_address(const char *ifname,
535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act)
536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct ifaddrs *ifaddrs, *ifa;
538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	const struct sockaddr_in *a, *n, *d;
539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int retval;
540f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (getifaddrs(&ifaddrs) == -1)
542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
543f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	retval = 0;
545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifa->ifa_addr == NULL ||
547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    ifa->ifa_addr->sa_family != AF_INET ||
548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    strcmp(ifa->ifa_name, ifname) != 0)
549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		a = (const struct sockaddr_in *)(void *)ifa->ifa_addr;
551e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask;
552e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (ifa->ifa_flags & IFF_POINTOPOINT)
553e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			d = (const struct sockaddr_in *)(void *)
554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    ifa->ifa_dstaddr;
555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		else
556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			d = NULL;
557e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (act == 1) {
558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			addr->s_addr = a->sin_addr.s_addr;
559e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			net->s_addr = n->sin_addr.s_addr;
560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (dst) {
56149b71a9ee5f83c49125fd6aff49701524be7a618Dmitry Shmidt				/* TODO: Fix getifaddrs() */
56249b71a9ee5f83c49125fd6aff49701524be7a618Dmitry Shmidt				if ((ifa->ifa_flags & IFF_POINTOPOINT) && d)
563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					dst->s_addr = d->sin_addr.s_addr;
564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				else
565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					dst->s_addr = INADDR_ANY;
566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			retval = 1;
568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (addr->s_addr == a->sin_addr.s_addr &&
571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    (net == NULL || net->s_addr == n->sin_addr.s_addr))
572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			retval = 1;
574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
576e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
577e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	freeifaddrs(ifaddrs);
578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return retval;
579f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
580f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
581f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
582f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdo_mtu(const char *ifname, short int mtu)
583f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
584f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct ifreq ifr;
585f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int r;
586f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
587f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
588f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
589f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ifr.ifr_mtu = mtu;
590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	r = ioctl(socket_afnet, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
591f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (r == -1)
592f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return ifr.ifr_mtu;
594f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
596f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid
597f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectfree_routes(struct rt *routes)
598f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
599f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct rt *r;
600f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
601f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	while (routes) {
602f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		r = routes->next;
603f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		free(routes);
604f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		routes = r;
605f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
606f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
607f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
608f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
609f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectopen_udp_socket(struct interface *iface)
610f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
611f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int s;
612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct sockaddr_in sin;
613f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int n;
614f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef SO_BINDTODEVICE
615f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct ifreq ifr;
616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *p;
617f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
618f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
619f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
620f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
621f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
622f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	n = 1;
623f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
624f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		goto eexit;
625f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef SO_BINDTODEVICE
626f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
627f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We can only bind to the real device */
629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	p = strchr(ifr.ifr_name, ':');
630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (p)
631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*p = '\0';
632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr,
633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		sizeof(ifr)) == -1)
634f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		goto eexit;
635f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
636f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	/* As we don't use this socket for receiving, set the
637f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * receive buffer to 1 */
638f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	n = 1;
639f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
640f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		goto eexit;
641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memset(&sin, 0, sizeof(sin));
642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sin.sin_family = AF_INET;
643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sin.sin_port = htons(DHCP_CLIENT_PORT);
644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sin.sin_addr.s_addr = iface->addr.s_addr;
645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
646f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		goto eexit;
647f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
648f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	iface->udp_fd = s;
649f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	set_cloexec(s);
650f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
651f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
652f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projecteexit:
653f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	close(s);
654f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return -1;
655f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
656f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
657f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t
658f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectsend_packet(const struct interface *iface, struct in_addr to,
659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    const uint8_t *data, ssize_t len)
660f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct sockaddr_in sin;
662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memset(&sin, 0, sizeof(sin));
664e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sin.sin_family = AF_INET;
665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sin.sin_addr.s_addr = to.s_addr;
666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sin.sin_port = htons(DHCP_SERVER_PORT);
667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return sendto(iface->udp_fd, data, len, 0,
668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    (struct sockaddr *)&sin, sizeof(sin));
669f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
670f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
671f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct udp_dhcp_packet
672f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
673f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct ip ip;
674f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct udphdr udp;
675f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct dhcp_message dhcp;
676f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project};
677f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectconst size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet);
678f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
679f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic uint16_t
680f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectchecksum(const void *data, uint16_t len)
681f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
682f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const uint8_t *addr = data;
683f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint32_t sum = 0;
684f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
685f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	while (len > 1) {
686f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		sum += addr[0] * 256 + addr[1];
687f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		addr += 2;
688f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		len -= 2;
689f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
690f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
691f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (len == 1)
692f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		sum += *addr * 256;
693f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
694f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	sum = (sum >> 16) + (sum & 0xffff);
695f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	sum += (sum >> 16);
696f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
697f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	sum = htons(sum);
698f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
699f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return ~sum;
700f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
701f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
702f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t
703f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectmake_udp_packet(uint8_t **packet, const uint8_t *data, size_t length,
704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    struct in_addr source, struct in_addr dest)
705f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
706f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct udp_dhcp_packet *udpp;
707f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct ip *ip;
708f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct udphdr *udp;
709f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
710f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	udpp = xzalloc(sizeof(*udpp));
711f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip = &udpp->ip;
712f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	udp = &udpp->udp;
713f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
714f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	/* OK, this is important :)
715f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * We copy the data to our packet and then create a small part of the
716f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * ip structure and an invalid ip_len (basically udp length).
717f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * We then fill the udp structure and put the checksum
718f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * of the whole packet into the udp checksum.
719f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * Finally we complete the ip structure and ip checksum.
720f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * If we don't do the ordering like so then the udp checksum will be
721f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	 * broken, so find another way of doing it! */
722f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
723f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memcpy(&udpp->dhcp, data, length);
724f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
725f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip->ip_p = IPPROTO_UDP;
726f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip->ip_src.s_addr = source.s_addr;
727f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (dest.s_addr == 0)
728f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		ip->ip_dst.s_addr = INADDR_BROADCAST;
729f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	else
730f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		ip->ip_dst.s_addr = dest.s_addr;
731f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
732f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	udp->uh_sport = htons(DHCP_CLIENT_PORT);
733f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	udp->uh_dport = htons(DHCP_SERVER_PORT);
734f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	udp->uh_ulen = htons(sizeof(*udp) + length);
735f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip->ip_len = udp->uh_ulen;
736f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	udp->uh_sum = checksum(udpp, sizeof(*udpp));
737f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
738f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip->ip_v = IPVERSION;
739e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ip->ip_hl = sizeof(*ip) >> 2;
740e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ip->ip_id = arc4random() & UINT16_MAX;
741f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip->ip_ttl = IPDEFTTL;
742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length);
743f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ip->ip_sum = checksum(ip, sizeof(*ip));
744f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
745f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	*packet = (uint8_t *)udpp;
746f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return sizeof(*ip) + sizeof(*udp) + length;
747f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
748f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
749f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t
750f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_udp_data(const uint8_t **data, const uint8_t *udp)
751f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
752f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct udp_dhcp_packet packet;
753f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
754f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memcpy(&packet, udp, sizeof(packet));
755f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	*data = udp + offsetof(struct udp_dhcp_packet, dhcp);
756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return ntohs(packet.ip.ip_len) -
757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    sizeof(packet.ip) -
758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    sizeof(packet.udp);
759f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
760f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
761f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
762a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtvalid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from,
763a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    int noudpcsum)
764f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
765f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct udp_dhcp_packet packet;
766938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	uint16_t bytes, udpsum;
767f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
768e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (data_len < sizeof(packet.ip)) {
769e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (from)
770e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			from->s_addr = INADDR_ANY;
771e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		errno = EINVAL;
772e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
773e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
774e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memcpy(&packet, data, MIN(data_len, sizeof(packet)));
775e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (from)
776e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		from->s_addr = packet.ip.ip_src.s_addr;
777938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (data_len > sizeof(packet)) {
778938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt		errno = EINVAL;
779938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt		return -1;
780938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	}
781938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (checksum(&packet.ip, sizeof(packet.ip)) != 0) {
782f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		errno = EINVAL;
783f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
784f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
785f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
786938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	bytes = ntohs(packet.ip.ip_len);
787938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (data_len < bytes) {
788938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt		errno = EINVAL;
789938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt		return -1;
790938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	}
791a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
792a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt	if (noudpcsum == 0) {
793a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		udpsum = packet.udp.uh_sum;
794a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.udp.uh_sum = 0;
795a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_hl = 0;
796a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_v = 0;
797a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_tos = 0;
798a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_len = packet.udp.uh_ulen;
799a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_id = 0;
800a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_off = 0;
801a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_ttl = 0;
802a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		packet.ip.ip_sum = 0;
803a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		if (udpsum && checksum(&packet, bytes) != udpsum) {
804a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			errno = EINVAL;
805a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt			return -1;
806a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt		}
807f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
808f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
809938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	return 0;
810f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
811