dhcp.c revision 1.3 1 1.1 pooka /*
2 1.1 pooka * dhcpcd - DHCP client daemon
3 1.1 pooka * Copyright (c) 2006-2010 Roy Marples <roy (at) marples.name>
4 1.1 pooka * All rights reserved
5 1.1 pooka
6 1.1 pooka * Redistribution and use in source and binary forms, with or without
7 1.1 pooka * modification, are permitted provided that the following conditions
8 1.1 pooka * are met:
9 1.1 pooka * 1. Redistributions of source code must retain the above copyright
10 1.1 pooka * notice, this list of conditions and the following disclaimer.
11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 pooka * notice, this list of conditions and the following disclaimer in the
13 1.1 pooka * documentation and/or other materials provided with the distribution.
14 1.1 pooka *
15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 1.1 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 1.1 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 1.1 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 1.1 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 pooka * SUCH DAMAGE.
26 1.1 pooka */
27 1.1 pooka
28 1.1 pooka #include <ctype.h>
29 1.1 pooka #include <errno.h>
30 1.1 pooka #include <fcntl.h>
31 1.1 pooka #include <stdlib.h>
32 1.1 pooka #include <string.h>
33 1.1 pooka #include <unistd.h>
34 1.1 pooka
35 1.1 pooka #include "common.h"
36 1.1 pooka #include "dhcp.h"
37 1.1 pooka
38 1.1 pooka #define REQUEST (1 << 0)
39 1.1 pooka #define UINT8 (1 << 1)
40 1.1 pooka #define UINT16 (1 << 2)
41 1.1 pooka #define SINT16 (1 << 3)
42 1.1 pooka #define UINT32 (1 << 4)
43 1.1 pooka #define SINT32 (1 << 5)
44 1.1 pooka #define IPV4 (1 << 6)
45 1.1 pooka #define STRING (1 << 7)
46 1.1 pooka #define PAIR (1 << 8)
47 1.1 pooka #define ARRAY (1 << 9)
48 1.1 pooka #define RFC3361 (1 << 10)
49 1.1 pooka #define RFC3397 (1 << 11)
50 1.1 pooka #define RFC3442 (1 << 12)
51 1.1 pooka
52 1.1 pooka #define IPV4R IPV4 | REQUEST
53 1.1 pooka
54 1.1 pooka #define DAD "Duplicate address detected"
55 1.1 pooka
56 1.1 pooka /* Our aggregate option buffer.
57 1.1 pooka * We ONLY use this when options are split, which for most purposes is
58 1.1 pooka * practically never. See RFC3396 for details. */
59 1.1 pooka static uint8_t *opt_buffer;
60 1.1 pooka
61 1.1 pooka struct dhcp_opt {
62 1.1 pooka uint8_t option;
63 1.1 pooka int type;
64 1.1 pooka const char *var;
65 1.1 pooka };
66 1.1 pooka
67 1.2 joerg static const struct dhcp_opt dhcp_opts[] = {
68 1.1 pooka { 1, IPV4 | REQUEST, "subnet_mask" },
69 1.1 pooka /* RFC 3442 states that the CSR has to come before all other
70 1.1 pooka * routes. For completeness, we also specify static routes,
71 1.1 pooka * then routers. */
72 1.1 pooka { 121, RFC3442, "classless_static_routes" },
73 1.1 pooka { 249, RFC3442, "ms_classless_static_routes" },
74 1.1 pooka { 33, IPV4 | ARRAY | REQUEST, "static_routes" },
75 1.1 pooka { 3, IPV4 | ARRAY | REQUEST, "routers" },
76 1.1 pooka { 2, UINT32, "time_offset" },
77 1.1 pooka { 4, IPV4 | ARRAY, "time_servers" },
78 1.1 pooka { 5, IPV4 | ARRAY, "ien116_name_servers" },
79 1.1 pooka { 6, IPV4 | ARRAY, "domain_name_servers" },
80 1.1 pooka { 7, IPV4 | ARRAY, "log_servers" },
81 1.1 pooka { 8, IPV4 | ARRAY, "cookie_servers" },
82 1.1 pooka { 9, IPV4 | ARRAY, "lpr_servers" },
83 1.1 pooka { 10, IPV4 | ARRAY, "impress_servers" },
84 1.1 pooka { 11, IPV4 | ARRAY, "resource_location_servers" },
85 1.1 pooka { 12, STRING, "host_name" },
86 1.1 pooka { 13, UINT16, "boot_size" },
87 1.1 pooka { 14, STRING, "merit_dump" },
88 1.1 pooka { 15, STRING, "domain_name" },
89 1.1 pooka { 16, IPV4, "swap_server" },
90 1.1 pooka { 17, STRING, "root_path" },
91 1.1 pooka { 18, STRING, "extensions_path" },
92 1.1 pooka { 19, UINT8, "ip_forwarding" },
93 1.1 pooka { 20, UINT8, "non_local_source_routing" },
94 1.1 pooka { 21, IPV4 | ARRAY, "policy_filter" },
95 1.1 pooka { 22, SINT16, "max_dgram_reassembly" },
96 1.1 pooka { 23, UINT16, "default_ip_ttl" },
97 1.1 pooka { 24, UINT32, "path_mtu_aging_timeout" },
98 1.1 pooka { 25, UINT16 | ARRAY, "path_mtu_plateau_table" },
99 1.1 pooka { 26, UINT16, "interface_mtu" },
100 1.1 pooka { 27, UINT8, "all_subnets_local" },
101 1.1 pooka { 28, IPV4 | REQUEST, "broadcast_address" },
102 1.1 pooka { 29, UINT8, "perform_mask_discovery" },
103 1.1 pooka { 30, UINT8, "mask_supplier" },
104 1.1 pooka { 31, UINT8, "router_discovery" },
105 1.1 pooka { 32, IPV4, "router_solicitation_address" },
106 1.1 pooka { 34, UINT8, "trailer_encapsulation" },
107 1.1 pooka { 35, UINT32, "arp_cache_timeout" },
108 1.1 pooka { 36, UINT16, "ieee802_3_encapsulation" },
109 1.1 pooka { 37, UINT8, "default_tcp_ttl" },
110 1.1 pooka { 38, UINT32, "tcp_keepalive_interval" },
111 1.1 pooka { 39, UINT8, "tcp_keepalive_garbage" },
112 1.1 pooka { 40, STRING, "nis_domain" },
113 1.1 pooka { 41, IPV4 | ARRAY, "nis_servers" },
114 1.1 pooka { 42, IPV4 | ARRAY, "ntp_servers" },
115 1.1 pooka { 43, STRING, "vendor_encapsulated_options" },
116 1.1 pooka { 44, IPV4 | ARRAY, "netbios_name_servers" },
117 1.1 pooka { 45, IPV4, "netbios_dd_server" },
118 1.1 pooka { 46, UINT8, "netbios_node_type" },
119 1.1 pooka { 47, STRING, "netbios_scope" },
120 1.1 pooka { 48, IPV4 | ARRAY, "font_servers" },
121 1.1 pooka { 49, IPV4 | ARRAY, "x_display_manager" },
122 1.1 pooka { 50, IPV4, "dhcp_requested_address" },
123 1.1 pooka { 51, UINT32 | REQUEST, "dhcp_lease_time" },
124 1.1 pooka { 52, UINT8, "dhcp_option_overload" },
125 1.1 pooka { 53, UINT8, "dhcp_message_type" },
126 1.1 pooka { 54, IPV4, "dhcp_server_identifier" },
127 1.1 pooka { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" },
128 1.1 pooka { 56, STRING, "dhcp_message" },
129 1.1 pooka { 57, UINT16, "dhcp_max_message_size" },
130 1.1 pooka { 58, UINT32 | REQUEST, "dhcp_renewal_time" },
131 1.1 pooka { 59, UINT32 | REQUEST, "dhcp_rebinding_time" },
132 1.1 pooka { 64, STRING, "nisplus_domain" },
133 1.1 pooka { 65, IPV4 | ARRAY, "nisplus_servers" },
134 1.1 pooka { 66, STRING, "tftp_server_name" },
135 1.1 pooka { 67, STRING, "bootfile_name" },
136 1.1 pooka { 68, IPV4 | ARRAY, "mobile_ip_home_agent" },
137 1.1 pooka { 69, IPV4 | ARRAY, "smtp_server" },
138 1.1 pooka { 70, IPV4 | ARRAY, "pop_server" },
139 1.1 pooka { 71, IPV4 | ARRAY, "nntp_server" },
140 1.1 pooka { 72, IPV4 | ARRAY, "www_server" },
141 1.1 pooka { 73, IPV4 | ARRAY, "finger_server" },
142 1.1 pooka { 74, IPV4 | ARRAY, "irc_server" },
143 1.1 pooka { 75, IPV4 | ARRAY, "streettalk_server" },
144 1.1 pooka { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" },
145 1.1 pooka { 77, STRING, "user_class" },
146 1.1 pooka { 81, STRING | RFC3397, "fqdn_name" },
147 1.1 pooka { 85, IPV4 | ARRAY, "nds_servers" },
148 1.1 pooka { 86, STRING, "nds_tree_name" },
149 1.1 pooka { 87, STRING, "nds_context" },
150 1.1 pooka { 88, STRING | RFC3397, "bcms_controller_names" },
151 1.1 pooka { 89, IPV4 | ARRAY, "bcms_controller_address" },
152 1.1 pooka { 91, UINT32, "client_last_transaction_time" },
153 1.1 pooka { 92, IPV4 | ARRAY, "associated_ip" },
154 1.1 pooka { 98, STRING, "uap_servers" },
155 1.1 pooka { 112, IPV4 | ARRAY, "netinfo_server_address" },
156 1.1 pooka { 113, STRING, "netinfo_server_tag" },
157 1.1 pooka { 114, STRING, "default_url" },
158 1.1 pooka { 118, IPV4, "subnet_selection" },
159 1.1 pooka { 119, STRING | RFC3397, "domain_search" },
160 1.1 pooka { 0, 0, NULL }
161 1.1 pooka };
162 1.1 pooka
163 1.1 pooka static int
164 1.1 pooka valid_length(uint8_t option, int dl, int *type)
165 1.1 pooka {
166 1.1 pooka const struct dhcp_opt *opt;
167 1.1 pooka ssize_t sz;
168 1.1 pooka
169 1.1 pooka if (dl == 0)
170 1.1 pooka return -1;
171 1.1 pooka
172 1.1 pooka for (opt = dhcp_opts; opt->option; opt++) {
173 1.1 pooka if (opt->option != option)
174 1.1 pooka continue;
175 1.1 pooka
176 1.1 pooka if (type)
177 1.1 pooka *type = opt->type;
178 1.1 pooka
179 1.1 pooka if (opt->type == 0 ||
180 1.1 pooka opt->type & STRING ||
181 1.1 pooka opt->type & RFC3442)
182 1.1 pooka return 0;
183 1.1 pooka
184 1.1 pooka sz = 0;
185 1.1 pooka if (opt->type & UINT32 || opt->type & IPV4)
186 1.1 pooka sz = sizeof(uint32_t);
187 1.1 pooka if (opt->type & UINT16)
188 1.1 pooka sz = sizeof(uint16_t);
189 1.1 pooka if (opt->type & UINT8)
190 1.1 pooka sz = sizeof(uint8_t);
191 1.1 pooka if (opt->type & IPV4 || opt->type & ARRAY)
192 1.1 pooka return dl % sz;
193 1.1 pooka return (dl == sz ? 0 : -1);
194 1.1 pooka }
195 1.1 pooka
196 1.1 pooka /* unknown option, so let it pass */
197 1.1 pooka return 0;
198 1.1 pooka }
199 1.1 pooka
200 1.1 pooka #ifdef DEBUG_MEMORY
201 1.1 pooka static void
202 1.1 pooka free_option_buffer(void)
203 1.1 pooka {
204 1.1 pooka free(opt_buffer);
205 1.1 pooka }
206 1.1 pooka #endif
207 1.1 pooka
208 1.1 pooka #define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL)
209 1.1 pooka static const uint8_t *
210 1.1 pooka get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
211 1.1 pooka {
212 1.1 pooka const uint8_t *p = dhcp->options;
213 1.1 pooka const uint8_t *e = p + sizeof(dhcp->options);
214 1.1 pooka uint8_t l, ol = 0;
215 1.1 pooka uint8_t o = 0;
216 1.1 pooka uint8_t overl = 0;
217 1.1 pooka uint8_t *bp = NULL;
218 1.1 pooka const uint8_t *op = NULL;
219 1.1 pooka int bl = 0;
220 1.1 pooka
221 1.1 pooka while (p < e) {
222 1.1 pooka o = *p++;
223 1.1 pooka if (o == opt) {
224 1.1 pooka if (op) {
225 1.1 pooka if (!opt_buffer) {
226 1.1 pooka opt_buffer = xmalloc(sizeof(*dhcp));
227 1.1 pooka #ifdef DEBUG_MEMORY
228 1.1 pooka atexit(free_option_buffer);
229 1.1 pooka #endif
230 1.1 pooka }
231 1.1 pooka if (!bp)
232 1.1 pooka bp = opt_buffer;
233 1.1 pooka memcpy(bp, op, ol);
234 1.1 pooka bp += ol;
235 1.1 pooka }
236 1.1 pooka ol = *p;
237 1.1 pooka op = p + 1;
238 1.1 pooka bl += ol;
239 1.1 pooka }
240 1.1 pooka switch (o) {
241 1.1 pooka case DHO_PAD:
242 1.1 pooka continue;
243 1.1 pooka case DHO_END:
244 1.1 pooka if (overl & 1) {
245 1.1 pooka /* bit 1 set means parse boot file */
246 1.1 pooka overl &= ~1;
247 1.1 pooka p = dhcp->bootfile;
248 1.1 pooka e = p + sizeof(dhcp->bootfile);
249 1.1 pooka } else if (overl & 2) {
250 1.1 pooka /* bit 2 set means parse server name */
251 1.1 pooka overl &= ~2;
252 1.1 pooka p = dhcp->servername;
253 1.1 pooka e = p + sizeof(dhcp->servername);
254 1.1 pooka } else
255 1.1 pooka goto exit;
256 1.1 pooka break;
257 1.1 pooka case DHO_OPTIONSOVERLOADED:
258 1.1 pooka /* Ensure we only get this option once */
259 1.1 pooka if (!overl)
260 1.1 pooka overl = p[1];
261 1.1 pooka break;
262 1.1 pooka }
263 1.1 pooka l = *p++;
264 1.1 pooka p += l;
265 1.1 pooka }
266 1.1 pooka
267 1.1 pooka exit:
268 1.1 pooka if (valid_length(opt, bl, type) == -1) {
269 1.1 pooka errno = EINVAL;
270 1.1 pooka return NULL;
271 1.1 pooka }
272 1.1 pooka if (len)
273 1.1 pooka *len = bl;
274 1.1 pooka if (bp) {
275 1.1 pooka memcpy(bp, op, ol);
276 1.1 pooka return (const uint8_t *)opt_buffer;
277 1.1 pooka }
278 1.1 pooka if (op)
279 1.1 pooka return op;
280 1.1 pooka errno = ENOENT;
281 1.1 pooka return NULL;
282 1.1 pooka }
283 1.1 pooka
284 1.1 pooka int
285 1.1 pooka get_option_addr(struct in_addr *a, const struct dhcp_message *dhcp,
286 1.1 pooka uint8_t option)
287 1.1 pooka {
288 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option);
289 1.1 pooka
290 1.1 pooka if (!p)
291 1.1 pooka return -1;
292 1.1 pooka memcpy(&a->s_addr, p, sizeof(a->s_addr));
293 1.1 pooka return 0;
294 1.1 pooka }
295 1.1 pooka
296 1.1 pooka int
297 1.1 pooka get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option)
298 1.1 pooka {
299 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option);
300 1.1 pooka uint32_t d;
301 1.1 pooka
302 1.1 pooka if (!p)
303 1.1 pooka return -1;
304 1.1 pooka memcpy(&d, p, sizeof(d));
305 1.1 pooka *i = ntohl(d);
306 1.1 pooka return 0;
307 1.1 pooka }
308 1.1 pooka
309 1.1 pooka int
310 1.1 pooka get_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option)
311 1.1 pooka {
312 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option);
313 1.1 pooka uint16_t d;
314 1.1 pooka
315 1.1 pooka if (!p)
316 1.1 pooka return -1;
317 1.1 pooka memcpy(&d, p, sizeof(d));
318 1.1 pooka *i = ntohs(d);
319 1.1 pooka return 0;
320 1.1 pooka }
321 1.1 pooka
322 1.1 pooka int
323 1.1 pooka get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
324 1.1 pooka {
325 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option);
326 1.1 pooka
327 1.1 pooka if (!p)
328 1.1 pooka return -1;
329 1.1 pooka if (i)
330 1.1 pooka *i = *(p);
331 1.1 pooka return 0;
332 1.1 pooka }
333 1.1 pooka
334 1.1 pooka static struct rt *
335 1.1 pooka decode_rfc3442_rt(int dl, const uint8_t *data)
336 1.1 pooka {
337 1.1 pooka const uint8_t *p = data;
338 1.1 pooka const uint8_t *e;
339 1.1 pooka uint8_t cidr;
340 1.1 pooka size_t ocets;
341 1.1 pooka struct rt *routes = NULL;
342 1.1 pooka struct rt *rt = NULL;
343 1.1 pooka
344 1.1 pooka /* Minimum is 5 -first is CIDR and a router length of 4 */
345 1.1 pooka if (dl < 5)
346 1.1 pooka return NULL;
347 1.1 pooka
348 1.1 pooka e = p + dl;
349 1.1 pooka while (p < e) {
350 1.1 pooka cidr = *p++;
351 1.1 pooka if (cidr > 32) {
352 1.1 pooka free_routes(routes);
353 1.1 pooka errno = EINVAL;
354 1.1 pooka return NULL;
355 1.1 pooka }
356 1.1 pooka
357 1.1 pooka if (rt) {
358 1.1 pooka rt->next = xzalloc(sizeof(*rt));
359 1.1 pooka rt = rt->next;
360 1.1 pooka } else {
361 1.1 pooka routes = rt = xzalloc(sizeof(*routes));
362 1.1 pooka }
363 1.1 pooka rt->next = NULL;
364 1.1 pooka
365 1.1 pooka ocets = (cidr + 7) / 8;
366 1.1 pooka /* If we have ocets then we have a destination and netmask */
367 1.1 pooka if (ocets > 0) {
368 1.1 pooka memcpy(&rt->dest.s_addr, p, ocets);
369 1.1 pooka p += ocets;
370 1.1 pooka rt->net.s_addr = htonl(~0U << (32 - cidr));
371 1.1 pooka }
372 1.1 pooka
373 1.1 pooka /* Finally, snag the router */
374 1.1 pooka memcpy(&rt->gate.s_addr, p, 4);
375 1.1 pooka p += 4;
376 1.1 pooka }
377 1.1 pooka return routes;
378 1.1 pooka }
379 1.1 pooka
380 1.1 pooka
381 1.1 pooka /* This calculates the netmask that we should use for static routes.
382 1.1 pooka * This IS different from the calculation used to calculate the netmask
383 1.1 pooka * for an interface address. */
384 1.1 pooka static uint32_t
385 1.1 pooka route_netmask(uint32_t ip_in)
386 1.1 pooka {
387 1.1 pooka /* used to be unsigned long - check if error */
388 1.1 pooka uint32_t p = ntohl(ip_in);
389 1.1 pooka uint32_t t;
390 1.1 pooka
391 1.1 pooka if (IN_CLASSA(p))
392 1.1 pooka t = ~IN_CLASSA_NET;
393 1.1 pooka else {
394 1.1 pooka if (IN_CLASSB(p))
395 1.1 pooka t = ~IN_CLASSB_NET;
396 1.1 pooka else {
397 1.1 pooka if (IN_CLASSC(p))
398 1.1 pooka t = ~IN_CLASSC_NET;
399 1.1 pooka else
400 1.1 pooka t = 0;
401 1.1 pooka }
402 1.1 pooka }
403 1.1 pooka
404 1.1 pooka while (t & p)
405 1.1 pooka t >>= 1;
406 1.1 pooka
407 1.1 pooka return (htonl(~t));
408 1.1 pooka }
409 1.1 pooka
410 1.1 pooka /* We need to obey routing options.
411 1.1 pooka * If we have a CSR then we only use that.
412 1.1 pooka * Otherwise we add static routes and then routers. */
413 1.1 pooka struct rt *
414 1.1 pooka get_option_routes(const struct dhcp_message *dhcp,
415 1.1 pooka const char *ifname, int *opts)
416 1.1 pooka {
417 1.1 pooka const uint8_t *p;
418 1.1 pooka const uint8_t *e;
419 1.1 pooka struct rt *routes = NULL;
420 1.1 pooka struct rt *route = NULL;
421 1.1 pooka int len;
422 1.1 pooka
423 1.1 pooka /* If we have CSR's then we MUST use these only */
424 1.1 pooka p = get_option(dhcp, DHO_CSR, &len, NULL);
425 1.1 pooka /* Check for crappy MS option */
426 1.1 pooka if (!p)
427 1.1 pooka p = get_option(dhcp, DHO_MSCSR, &len, NULL);
428 1.1 pooka if (p) {
429 1.1 pooka routes = decode_rfc3442_rt(len, p);
430 1.1 pooka if (routes && !(*opts & DHCPCD_CSR_WARNED)) {
431 1.1 pooka *opts |= DHCPCD_CSR_WARNED;
432 1.1 pooka return routes;
433 1.1 pooka }
434 1.1 pooka }
435 1.1 pooka
436 1.1 pooka /* OK, get our static routes first. */
437 1.1 pooka p = get_option(dhcp, DHO_STATICROUTE, &len, NULL);
438 1.1 pooka if (p) {
439 1.1 pooka e = p + len;
440 1.1 pooka while (p < e) {
441 1.1 pooka if (route) {
442 1.1 pooka route->next = xmalloc(sizeof(*route));
443 1.1 pooka route = route->next;
444 1.1 pooka } else
445 1.1 pooka routes = route = xmalloc(sizeof(*routes));
446 1.1 pooka route->next = NULL;
447 1.1 pooka memcpy(&route->dest.s_addr, p, 4);
448 1.1 pooka p += 4;
449 1.1 pooka memcpy(&route->gate.s_addr, p, 4);
450 1.1 pooka p += 4;
451 1.1 pooka route->net.s_addr = route_netmask(route->dest.s_addr);
452 1.1 pooka }
453 1.1 pooka }
454 1.1 pooka
455 1.1 pooka /* Now grab our routers */
456 1.1 pooka p = get_option(dhcp, DHO_ROUTER, &len, NULL);
457 1.1 pooka if (p) {
458 1.1 pooka e = p + len;
459 1.1 pooka while (p < e) {
460 1.1 pooka if (route) {
461 1.1 pooka route->next = xzalloc(sizeof(*route));
462 1.1 pooka route = route->next;
463 1.1 pooka } else
464 1.1 pooka routes = route = xzalloc(sizeof(*route));
465 1.1 pooka memcpy(&route->gate.s_addr, p, 4);
466 1.1 pooka p += 4;
467 1.1 pooka }
468 1.1 pooka }
469 1.1 pooka
470 1.1 pooka return routes;
471 1.1 pooka }
472 1.1 pooka
473 1.1 pooka static size_t
474 1.1 pooka encode_rfc1035(const char *src, uint8_t *dst)
475 1.1 pooka {
476 1.1 pooka uint8_t *p = dst;
477 1.1 pooka uint8_t *lp = p++;
478 1.1 pooka
479 1.1 pooka if (*src == '\0')
480 1.1 pooka return 0;
481 1.1 pooka for (; *src; src++) {
482 1.1 pooka if (*src == '\0')
483 1.1 pooka break;
484 1.1 pooka if (*src == '.') {
485 1.1 pooka /* Skip the trailing . */
486 1.1 pooka if (src[1] == '\0')
487 1.1 pooka break;
488 1.1 pooka *lp = p - lp - 1;
489 1.1 pooka if (*lp == '\0')
490 1.1 pooka return p - dst;
491 1.1 pooka lp = p++;
492 1.1 pooka } else
493 1.1 pooka *p++ = (uint8_t)*src;
494 1.1 pooka }
495 1.1 pooka *lp = p - lp - 1;
496 1.1 pooka *p++ = '\0';
497 1.1 pooka return p - dst;
498 1.1 pooka }
499 1.1 pooka
500 1.1 pooka #define PUTADDR(_type, _val) \
501 1.1 pooka { \
502 1.1 pooka *p++ = _type; \
503 1.1 pooka *p++ = 4; \
504 1.1 pooka memcpy(p, &_val.s_addr, 4); \
505 1.1 pooka p += 4; \
506 1.1 pooka }
507 1.1 pooka
508 1.1 pooka int
509 1.1 pooka dhcp_message_add_addr(struct dhcp_message *dhcp,
510 1.1 pooka uint8_t type, struct in_addr addr)
511 1.1 pooka {
512 1.1 pooka uint8_t *p;
513 1.1 pooka size_t len;
514 1.1 pooka
515 1.1 pooka p = dhcp->options;
516 1.1 pooka while (*p != DHO_END) {
517 1.1 pooka p++;
518 1.1 pooka p += *p + 1;
519 1.1 pooka }
520 1.1 pooka
521 1.1 pooka len = p - (uint8_t *)dhcp;
522 1.1 pooka if (len + 6 > sizeof(*dhcp)) {
523 1.1 pooka errno = ENOMEM;
524 1.1 pooka return -1;
525 1.1 pooka }
526 1.1 pooka
527 1.1 pooka PUTADDR(type, addr);
528 1.1 pooka *p = DHO_END;
529 1.1 pooka return 0;
530 1.1 pooka }
531 1.1 pooka
532 1.1 pooka ssize_t
533 1.1 pooka make_message(struct dhcp_message **message,
534 1.1 pooka const struct interface *iface,
535 1.1 pooka uint8_t type)
536 1.1 pooka {
537 1.1 pooka struct dhcp_message *dhcp;
538 1.1 pooka uint8_t *m, *lp, *p;
539 1.1 pooka uint8_t *n_params = NULL;
540 1.1 pooka time_t up = uptime() - iface->start_uptime;
541 1.1 pooka uint32_t ul;
542 1.1 pooka uint16_t sz;
543 1.1 pooka size_t len;
544 1.1 pooka const char *hp;
545 1.1 pooka const struct dhcp_opt *opt;
546 1.1 pooka const struct if_options *ifo = iface->state->options;
547 1.1 pooka const struct dhcp_lease *lease = &iface->state->lease;
548 1.1 pooka
549 1.1 pooka dhcp = xzalloc(sizeof (*dhcp));
550 1.1 pooka m = (uint8_t *)dhcp;
551 1.1 pooka p = dhcp->options;
552 1.1 pooka
553 1.1 pooka if ((type == DHCP_INFORM || type == DHCP_RELEASE ||
554 1.1 pooka (type == DHCP_REQUEST &&
555 1.1 pooka iface->net.s_addr == lease->net.s_addr &&
556 1.1 pooka (iface->state->new == NULL ||
557 1.1 pooka iface->state->new->cookie == htonl(MAGIC_COOKIE)))))
558 1.1 pooka {
559 1.1 pooka dhcp->ciaddr = iface->addr.s_addr;
560 1.1 pooka /* In-case we haven't actually configured the address yet */
561 1.1 pooka if (type == DHCP_INFORM && iface->addr.s_addr == 0)
562 1.1 pooka dhcp->ciaddr = lease->addr.s_addr;
563 1.1 pooka }
564 1.1 pooka
565 1.1 pooka dhcp->op = DHCP_BOOTREQUEST;
566 1.1 pooka dhcp->hwtype = iface->family;
567 1.1 pooka switch (iface->family) {
568 1.1 pooka case ARPHRD_ETHER:
569 1.1 pooka case ARPHRD_IEEE802:
570 1.1 pooka dhcp->hwlen = iface->hwlen;
571 1.1 pooka memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen);
572 1.1 pooka break;
573 1.1 pooka }
574 1.1 pooka
575 1.1 pooka if (ifo->options & DHCPCD_BROADCAST &&
576 1.1 pooka dhcp->ciaddr == 0 &&
577 1.1 pooka type != DHCP_DECLINE &&
578 1.1 pooka type != DHCP_RELEASE)
579 1.1 pooka dhcp->flags = htons(BROADCAST_FLAG);
580 1.1 pooka
581 1.1 pooka if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
582 1.1 pooka if (up < 0 || up > (time_t)UINT16_MAX)
583 1.1 pooka dhcp->secs = htons((uint16_t)UINT16_MAX);
584 1.1 pooka else
585 1.1 pooka dhcp->secs = htons(up);
586 1.1 pooka }
587 1.1 pooka dhcp->xid = iface->state->xid;
588 1.1 pooka dhcp->cookie = htonl(MAGIC_COOKIE);
589 1.1 pooka
590 1.1 pooka *p++ = DHO_MESSAGETYPE;
591 1.1 pooka *p++ = 1;
592 1.1 pooka *p++ = type;
593 1.1 pooka
594 1.1 pooka if (iface->clientid) {
595 1.1 pooka *p++ = DHO_CLIENTID;
596 1.1 pooka memcpy(p, iface->clientid, iface->clientid[0] + 1);
597 1.1 pooka p += iface->clientid[0] + 1;
598 1.1 pooka }
599 1.1 pooka
600 1.1 pooka if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) {
601 1.1 pooka if (type == DHCP_DECLINE ||
602 1.1 pooka (type == DHCP_REQUEST &&
603 1.1 pooka lease->addr.s_addr != iface->addr.s_addr))
604 1.1 pooka {
605 1.1 pooka PUTADDR(DHO_IPADDRESS, lease->addr);
606 1.1 pooka if (lease->server.s_addr)
607 1.1 pooka PUTADDR(DHO_SERVERID, lease->server);
608 1.1 pooka }
609 1.1 pooka
610 1.1 pooka if (type == DHCP_RELEASE) {
611 1.1 pooka if (lease->server.s_addr)
612 1.1 pooka PUTADDR(DHO_SERVERID, lease->server);
613 1.1 pooka }
614 1.1 pooka }
615 1.1 pooka
616 1.1 pooka if (type == DHCP_DECLINE) {
617 1.1 pooka *p++ = DHO_MESSAGE;
618 1.1 pooka len = strlen(DAD);
619 1.1 pooka *p++ = len;
620 1.1 pooka memcpy(p, DAD, len);
621 1.1 pooka p += len;
622 1.1 pooka }
623 1.1 pooka
624 1.1 pooka if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST)
625 1.1 pooka PUTADDR(DHO_IPADDRESS, ifo->req_addr);
626 1.1 pooka
627 1.1 pooka if (type == DHCP_DISCOVER ||
628 1.1 pooka type == DHCP_INFORM ||
629 1.1 pooka type == DHCP_REQUEST)
630 1.1 pooka {
631 1.1 pooka *p++ = DHO_MAXMESSAGESIZE;
632 1.1 pooka *p++ = 2;
633 1.1 pooka sz = get_mtu(iface->name);
634 1.1 pooka if (sz < MTU_MIN) {
635 1.1 pooka if (set_mtu(iface->name, MTU_MIN) == 0)
636 1.1 pooka sz = MTU_MIN;
637 1.1 pooka } else if (sz > MTU_MAX) {
638 1.1 pooka /* Even though our MTU could be greater than
639 1.1 pooka * MTU_MAX (1500) dhcpcd does not presently
640 1.1 pooka * handle DHCP packets any bigger. */
641 1.1 pooka sz = MTU_MAX;
642 1.1 pooka }
643 1.1 pooka sz = htons(sz);
644 1.1 pooka memcpy(p, &sz, 2);
645 1.1 pooka p += 2;
646 1.1 pooka
647 1.1 pooka if (ifo->userclass[0]) {
648 1.1 pooka *p++ = DHO_USERCLASS;
649 1.1 pooka memcpy(p, ifo->userclass, ifo->userclass[0] + 1);
650 1.1 pooka p += ifo->userclass[0] + 1;
651 1.1 pooka }
652 1.1 pooka
653 1.1 pooka if (ifo->vendorclassid[0]) {
654 1.1 pooka *p++ = DHO_VENDORCLASSID;
655 1.1 pooka memcpy(p, ifo->vendorclassid,
656 1.1 pooka ifo->vendorclassid[0] + 1);
657 1.1 pooka p += ifo->vendorclassid[0] + 1;
658 1.1 pooka }
659 1.1 pooka
660 1.1 pooka
661 1.1 pooka if (type != DHCP_INFORM) {
662 1.1 pooka if (ifo->leasetime != 0) {
663 1.1 pooka *p++ = DHO_LEASETIME;
664 1.1 pooka *p++ = 4;
665 1.1 pooka ul = htonl(ifo->leasetime);
666 1.1 pooka memcpy(p, &ul, 4);
667 1.1 pooka p += 4;
668 1.1 pooka }
669 1.1 pooka }
670 1.1 pooka
671 1.1 pooka /* Regardless of RFC2132, we should always send a hostname
672 1.1 pooka * upto the first dot (the short hostname) as otherwise
673 1.1 pooka * confuses some DHCP servers when updating DNS.
674 1.1 pooka * The FQDN option should be used if a FQDN is required. */
675 1.1 pooka if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) {
676 1.1 pooka *p++ = DHO_HOSTNAME;
677 1.1 pooka hp = strchr(ifo->hostname, '.');
678 1.1 pooka if (hp)
679 1.1 pooka len = hp - ifo->hostname;
680 1.1 pooka else
681 1.1 pooka len = strlen(ifo->hostname);
682 1.1 pooka *p++ = len;
683 1.1 pooka memcpy(p, ifo->hostname, len);
684 1.1 pooka p += len;
685 1.1 pooka }
686 1.1 pooka if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) {
687 1.1 pooka /* IETF DHC-FQDN option (81), RFC4702 */
688 1.1 pooka *p++ = DHO_FQDN;
689 1.1 pooka lp = p;
690 1.1 pooka *p++ = 3;
691 1.1 pooka /*
692 1.1 pooka * Flags: 0000NEOS
693 1.1 pooka * S: 1 => Client requests Server to update
694 1.1 pooka * a RR in DNS as well as PTR
695 1.1 pooka * O: 1 => Server indicates to client that
696 1.1 pooka * DNS has been updated
697 1.1 pooka * E: 1 => Name data is DNS format
698 1.1 pooka * N: 1 => Client requests Server to not
699 1.1 pooka * update DNS
700 1.1 pooka */
701 1.1 pooka *p++ = (ifo->fqdn & 0x09) | 0x04;
702 1.1 pooka *p++ = 0; /* from server for PTR RR */
703 1.1 pooka *p++ = 0; /* from server for A RR if S=1 */
704 1.1 pooka ul = encode_rfc1035(ifo->hostname, p);
705 1.1 pooka *lp += ul;
706 1.1 pooka p += ul;
707 1.1 pooka }
708 1.1 pooka
709 1.1 pooka /* vendor is already encoded correctly, so just add it */
710 1.1 pooka if (ifo->vendor[0]) {
711 1.1 pooka *p++ = DHO_VENDOR;
712 1.1 pooka memcpy(p, ifo->vendor, ifo->vendor[0] + 1);
713 1.1 pooka p += ifo->vendor[0] + 1;
714 1.1 pooka }
715 1.1 pooka
716 1.1 pooka *p++ = DHO_PARAMETERREQUESTLIST;
717 1.1 pooka n_params = p;
718 1.1 pooka *p++ = 0;
719 1.1 pooka for (opt = dhcp_opts; opt->option; opt++) {
720 1.1 pooka if (!(opt->type & REQUEST ||
721 1.1 pooka has_option_mask(ifo->requestmask, opt->option)))
722 1.1 pooka continue;
723 1.1 pooka if (type == DHCP_INFORM &&
724 1.1 pooka (opt->option == DHO_RENEWALTIME ||
725 1.1 pooka opt->option == DHO_REBINDTIME))
726 1.1 pooka continue;
727 1.1 pooka *p++ = opt->option;
728 1.1 pooka }
729 1.1 pooka *n_params = p - n_params - 1;
730 1.1 pooka }
731 1.1 pooka *p++ = DHO_END;
732 1.1 pooka
733 1.3 andvar #ifdef BOOTP_MESSAGE_LENGTH_MIN
734 1.1 pooka /* Some crappy DHCP servers think they have to obey the BOOTP minimum
735 1.1 pooka * message length.
736 1.1 pooka * They are wrong, but we should still cater for them. */
737 1.3 andvar while (p - m < BOOTP_MESSAGE_LENGTH_MIN)
738 1.1 pooka *p++ = DHO_PAD;
739 1.1 pooka #endif
740 1.1 pooka
741 1.1 pooka *message = dhcp;
742 1.1 pooka return p - m;
743 1.1 pooka }
744 1.1 pooka
745 1.1 pooka void
746 1.1 pooka get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp)
747 1.1 pooka {
748 1.1 pooka struct timeval now;
749 1.1 pooka
750 1.1 pooka lease->cookie = dhcp->cookie;
751 1.1 pooka /* BOOTP does not set yiaddr for replies when ciaddr is set. */
752 1.1 pooka if (dhcp->yiaddr)
753 1.1 pooka lease->addr.s_addr = dhcp->yiaddr;
754 1.1 pooka else
755 1.1 pooka lease->addr.s_addr = dhcp->ciaddr;
756 1.1 pooka if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1)
757 1.1 pooka lease->net.s_addr = get_netmask(lease->addr.s_addr);
758 1.1 pooka if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1)
759 1.1 pooka lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr;
760 1.1 pooka if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) {
761 1.1 pooka /* Ensure that we can use the lease */
762 1.1 pooka get_monotonic(&now);
763 1.1 pooka if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec)
764 1.1 pooka lease->leasetime = ~0U; /* Infinite lease */
765 1.1 pooka } else
766 1.1 pooka lease->leasetime = ~0U; /* Default to infinite lease */
767 1.1 pooka if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0)
768 1.1 pooka lease->renewaltime = 0;
769 1.1 pooka if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0)
770 1.1 pooka lease->rebindtime = 0;
771 1.1 pooka if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0)
772 1.1 pooka lease->server.s_addr = INADDR_ANY;
773 1.1 pooka }
774