1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h>
2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h>
3f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h>
4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <fcntl.h>
5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h"
7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h"
8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef DEFAULT_LEASETIME
10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define DEFAULT_LEASETIME	3600	/* 1 hour */
11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define REQUEST	(1 << 0)
14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT8	(1 << 1)
15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT16	(1 << 2)
16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define SINT16	(1 << 3)
17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT32	(1 << 4)
18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define SINT32	(1 << 5)
19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define IPV4	(1 << 6)
20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define STRING	(1 << 7)
21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define PAIR	(1 << 8)
22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define ARRAY	(1 << 9)
23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3361	(1 << 10)
24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3397	(1 << 11)
25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3442 (1 << 12)
26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_opt {
28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint8_t option;
29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int type;
30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const char *var;
31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project};
32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const struct dhcp_opt const dhcp_opts[] = {
34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 1,	IPV4 | REQUEST,	"subnet_mask" },
35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 2,	UINT32,		"time_offset" },
36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 3,	IPV4 | ARRAY | REQUEST,	"routers" },
37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 4,	IPV4 | ARRAY,	"time_servers" },
38f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 5,	IPV4 | ARRAY,	"ien116_name_servers" },
39f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 6,	IPV4 | ARRAY,	"domain_name_servers" },
40f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 7,	IPV4 | ARRAY,	"log_servers" },
41f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 8,	IPV4 | ARRAY,	"cookie_servers" },
42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 9, 	IPV4 | ARRAY,	"lpr_servers" },
43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 10,	IPV4 | ARRAY,	"impress_servers" },
44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 11,	IPV4 | ARRAY,	"resource_location_servers" },
45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 12,	STRING,		"host_name" },
46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 13,	UINT16,		"boot_size" },
47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 14,	STRING,		"merit_dump" },
48f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 15,	STRING,		"domain_name" },
49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 16,	IPV4,		"swap_server" },
50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 17,	STRING,		"root_path" },
51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 18,	STRING,		"extensions_path" },
52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 19,	UINT8,		"ip_forwarding" },
53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 20,	UINT8,		"non_local_source_routing" },
54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 21,	IPV4 | ARRAY,	"policy_filter" },
55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 22,	SINT16,		"max_dgram_reassembly" },
56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 23,	UINT16,		"default_ip_ttl" },
57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 24,	UINT32,		"path_mtu_aging_timeout" },
58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 25,	UINT16 | ARRAY,	"path_mtu_plateau_table" },
59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 26,	UINT16,		"interface_mtu" },
60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 27,	UINT8,		"all_subnets_local" },
61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 28,	IPV4 | REQUEST,	"broadcast_address" },
62f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 29,	UINT8,		"perform_mask_discovery" },
63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 30,	UINT8,		"mask_supplier" },
64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 31,	UINT8,		"router_discovery" },
65f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 32,	IPV4,		"router_solicitation_address" },
66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 33,	IPV4 | ARRAY | REQUEST,	"static_routes" },
67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 34,	UINT8,		"trailer_encapsulation" },
68f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 35, 	UINT32,		"arp_cache_timeout" },
69f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 36,	UINT16,		"ieee802_3_encapsulation" },
70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 37,	UINT8,		"default_tcp_ttl" },
71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 38,	UINT32,		"tcp_keepalive_interval" },
72f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 39,	UINT8,		"tcp_keepalive_garbage" },
73f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 40,	STRING,		"nis_domain" },
74f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 41,	IPV4 | ARRAY,	"nis_servers" },
75f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 42,	IPV4 | ARRAY,	"ntp_servers" },
76f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 43,	STRING,		"vendor_encapsulated_options" },
77f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 44,	IPV4 | ARRAY,	"netbios_name_servers" },
78f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 45,	IPV4,		"netbios_dd_server" },
79f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 46,	UINT8,		"netbios_node_type" },
80f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 47,	STRING,		"netbios_scope" },
81f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 48,	IPV4 | ARRAY,	"font_servers" },
82f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 49,	IPV4 | ARRAY,	"x_display_manager" },
83f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 50, 	IPV4,		"dhcp_requested_address" },
84f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 51,	UINT32 | REQUEST,	"dhcp_lease_time" },
85f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 52,	UINT8,		"dhcp_option_overload" },
86f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 53,	UINT8,		"dhcp_message_type" },
87f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 54,	IPV4,		"dhcp_server_identifier" },
88f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 55,	UINT8 | ARRAY,	"dhcp_parameter_request_list" },
89f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 56,	STRING,		"dhcp_message" },
90f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 57,	UINT16,		"dhcp_max_message_size" },
91f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 58,	UINT32 | REQUEST,	"dhcp_renewal_time" },
92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 59,	UINT32 | REQUEST,	"dhcp_rebinding_time" },
93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 64,	STRING,		"nisplus_domain" },
94f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 65,	IPV4 | ARRAY,	"nisplus_servers" },
95f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 66,	STRING,		"tftp_server_name" },
96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 67,	STRING,		"bootfile_name" },
97f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 68,	IPV4 | ARRAY,	"mobile_ip_home_agent" },
98f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 69,	IPV4 | ARRAY,	"smtp_server" },
99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 70,	IPV4 | ARRAY,	"pop_server" },
100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 71,	IPV4 | ARRAY,	"nntp_server" },
101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 72,	IPV4 | ARRAY,	"www_server" },
102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 73,	IPV4 | ARRAY,	"finger_server" },
103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 74,	IPV4 | ARRAY,	"irc_server" },
104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 75,	IPV4 | ARRAY,	"streettalk_server" },
105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 76,	IPV4 | ARRAY,	"streettalk_directory_assistance_server" },
106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 77,	STRING,		"user_class" },
107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 85,	IPV4 | ARRAY,	"nds_servers" },
108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 86,	STRING,		"nds_tree_name" },
109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 87,	STRING,		"nds_context" },
110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 88,	STRING | RFC3397,	"bcms_controller_names" },
111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 89,	IPV4 | ARRAY,	"bcms_controller_address" },
112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 91,	UINT32,		"client_last_transaction_time" },
113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 92,	IPV4 | ARRAY,	"associated_ip" },
114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 98,	STRING,		"uap_servers" },
115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 112,	IPV4 | ARRAY,	"netinfo_server_address" },
116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 113,	STRING,		"netinfo_server_tag" },
117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 114,	STRING,		"default_url" },
118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 118,	IPV4,		"subnet_selection" },
119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 119,	STRING | RFC3397,	"domain_search" },
120f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 121,  RFC3442 | REQUEST,	"classless_static_routes" },
121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 249,  RFC3442,	"ms-classless_static_routes" },
122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	{ 0, 0, NULL }
123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project};
124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_message *
126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_lease_from_file(const char *leasefile)
127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int fd;
129f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	struct dhcp_message *dhcp;
130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ssize_t bytes;
131f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	fd = open(leasefile, O_RDONLY);
133f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (fd == -1)
134f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return NULL;
135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	dhcp = malloc(sizeof(*dhcp));
136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memset(dhcp, 0, sizeof(*dhcp));
137f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	bytes = read(fd, dhcp, sizeof(*dhcp));
138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	close(fd);
139f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (bytes < 0) {
140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		free(dhcp);
141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		dhcp = NULL;
142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return dhcp;
144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic uint8_t *dhcp_opt_buffer = NULL;
147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int
149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvalid_length(uint8_t option, int dl, int *type)
150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const struct dhcp_opt *opt;
152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	ssize_t sz;
153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (dl == 0)
155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	for (opt = dhcp_opts; opt->option; opt++) {
158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (opt->option != option)
159f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			continue;
160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (type)
162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			*type = opt->type;
163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (opt->type == 0 || opt->type & STRING || opt->type & RFC3442)
165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			return 0;
166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		sz = 0;
168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (opt->type & UINT32 || opt->type & IPV4)
169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			sz = sizeof(uint32_t);
170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (opt->type & UINT16)
171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			sz = sizeof(uint16_t);
172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (opt->type & UINT8)
173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			sz = sizeof(uint8_t);
174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (opt->type & IPV4 || opt->type & ARRAY)
175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			return dl % sz;
176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return (dl == sz ? 0 : -1);
177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
178f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
179f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	/* unknown option, so let it pass */
180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic void
184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectfree_option_buffer(void)
185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	free(dhcp_opt_buffer);
187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL)
191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const uint8_t *
192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const uint8_t *p = dhcp->options;
195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const uint8_t *e = p + sizeof(dhcp->options);
196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint8_t l, ol = 0;
197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint8_t o = 0;
198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint8_t overl = 0;
199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint8_t *bp = NULL;
200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const uint8_t *op = NULL;
201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	int bl = 0;
202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	while (p < e) {
204f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		o = *p++;
205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		if (o == opt) {
206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			if (op) {
207f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				if (!dhcp_opt_buffer) {
208f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project					dhcp_opt_buffer = malloc(sizeof(struct dhcp_message));
209f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project					atexit(free_option_buffer);
210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				}
211f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				if (!bp)
212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project					bp = dhcp_opt_buffer;
213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				memcpy(bp, op, ol);
214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				bp += ol;
215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			}
216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			ol = *p;
217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			op = p + 1;
218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			bl += ol;
219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		switch (o) {
221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case DHO_PAD:
222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			continue;
223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case DHO_END:
224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			if (overl & 1) {
225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				/* bit 1 set means parse boot file */
226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				overl &= ~1;
227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				p = dhcp->bootfile;
228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				e = p + sizeof(dhcp->bootfile);
229f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			} else if (overl & 2) {
230f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				/* bit 2 set means parse server name */
231f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				overl &= ~2;
232f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				p = dhcp->servername;
233f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				e = p + sizeof(dhcp->servername);
234f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			} else
235f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				goto exit;
236f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
237f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		case DHO_OPTIONSOVERLOADED:
238f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			/* Ensure we only get this option once */
239f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			if (!overl)
240f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project				overl = p[1];
241f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project			break;
242f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		}
243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		l = *p++;
244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		p += l;
245f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
247f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectexit:
248f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (valid_length(o, bl, type) == -1) {
249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		errno = EINVAL;
250f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return NULL;
251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
252f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (len)
253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		*len = bl;
254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (bp) {
255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		memcpy(bp, op, ol);
256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return (const uint8_t *)&dhcp_opt_buffer;
257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	}
258f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (op)
259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return op;
260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	errno = ENOENT;
261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return NULL;
262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
265938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtget_option_addr32(uint32_t *a, const struct dhcp_message *dhcp, uint8_t option)
266f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	const uint8_t *p = get_option_raw(dhcp, option);
268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (!p)
270f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	memcpy(a, p, sizeof(*a));
272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option)
277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint32_t a;
279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
280938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt	if (get_option_addr32(&a, dhcp, option) == -1)
281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return -1;
282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	*i = ntohl(a);
284f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
285f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
286f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
287f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectuint32_t
288f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_netmask(uint32_t addr)
289f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
290f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	uint32_t dst;
291f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
292f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (addr == 0)
293f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return 0;
294f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
295f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	dst = htonl(addr);
296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (IN_CLASSA(dst))
297f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return ntohl(IN_CLASSA_NET);
298f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (IN_CLASSB (dst))
299f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return ntohl(IN_CLASSB_NET);
300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	if (IN_CLASSC (dst))
301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project		return ntohl(IN_CLASSC_NET);
302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
303f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project	return 0;
304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid showlease(struct dhcp_lease *lease)
307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    printf("addr:      %s\n", inet_ntoa(lease->addr));
309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    printf("net:       %s\n", inet_ntoa(lease->net));
310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    printf("leasetime: %d\n", lease->leasetime);
311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    printf("renew:     %d\n", lease->renewaltime);
312f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    printf("rebind:    %d\n", lease->rebindtime);
313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    printf("server:    %s\n", inet_ntoa(lease->server));
314f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define MAX_LEASETIME 2147460
316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint
318f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectmain(int argc, char *argv[])
319f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
320f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    struct dhcp_message *dhcp;
321f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    struct dhcp_lease *lease;
322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    char leasefile[PATH_MAX];
323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (argc < 2) {
325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        fprintf(stderr, "Usage: %s <interface>\n", argv[0]);
326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        exit(1);
327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    snprintf(leasefile, PATH_MAX, LEASEFILE, argv[1]);
329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if ((dhcp = get_lease_from_file(leasefile)) == NULL) {
330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        fprintf(stderr, "Couldn't read lease file: %s\n", strerror(errno));
331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        exit(1);
332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    lease = malloc(sizeof(*lease));
334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    lease->frominfo = 0;
335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    lease->addr.s_addr = dhcp->yiaddr;
336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
337938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    if (get_option_addr32(&lease->net.s_addr, dhcp, DHO_SUBNETMASK) == -1)
338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        lease->net.s_addr = get_netmask(dhcp->yiaddr);
339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) != 0)
340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        lease->leasetime = DEFAULT_LEASETIME;
341938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    get_option_addr32(&lease->server.s_addr, dhcp, DHO_SERVERID);
342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    /* Dm: limit lease time value to avoid negative numbers when
343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project       converting to milliseconds */
344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if ((lease->leasetime != ~0U) && (lease->leasetime > MAX_LEASETIME))
345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        lease->leasetime = MAX_LEASETIME;
346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0)
347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        lease->renewaltime = 0;
348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0)
349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        lease->rebindtime = 0;
350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    showlease(lease);
351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    free(lease);
352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return 0;
353f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
354