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