1 /* $NetBSD: dhc6.c,v 1.6 2014/07/12 12:09:37 spz Exp $ */
2 /* dhc6.c - DHCPv6 client routines. */
3
4 /*
5 * Copyright (c) 2012-2013 by Internet Systems Consortium, Inc. ("ISC")
6 * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 * Internet Systems Consortium, Inc.
21 * 950 Charter Street
22 * Redwood City, CA 94063
23 * <info@isc.org>
24 * https://www.isc.org/
25 */
26
27 #include <sys/cdefs.h>
28 __RCSID("$NetBSD: dhc6.c,v 1.6 2014/07/12 12:09:37 spz Exp $");
29
30 #include "dhcpd.h"
31
32 #ifdef DHCPv6
33
34 struct sockaddr_in6 DHCPv6DestAddr;
35
36 /*
37 * Option definition structures that are used by the software - declared
38 * here once and assigned at startup to save lookups.
39 */
40 struct option *clientid_option = NULL;
41 struct option *elapsed_option = NULL;
42 struct option *ia_na_option = NULL;
43 struct option *ia_ta_option = NULL;
44 struct option *ia_pd_option = NULL;
45 struct option *iaaddr_option = NULL;
46 struct option *iaprefix_option = NULL;
47 struct option *oro_option = NULL;
48 struct option *irt_option = NULL;
49
50 static struct dhc6_lease *dhc6_dup_lease(struct dhc6_lease *lease,
51 const char *file, int line);
52 static struct dhc6_ia *dhc6_dup_ia(struct dhc6_ia *ia,
53 const char *file, int line);
54 static struct dhc6_addr *dhc6_dup_addr(struct dhc6_addr *addr,
55 const char *file, int line);
56 static void dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line);
57 static isc_result_t dhc6_parse_ia_na(struct dhc6_ia **pia,
58 struct packet *packet,
59 struct option_state *options);
60 static isc_result_t dhc6_parse_ia_ta(struct dhc6_ia **pia,
61 struct packet *packet,
62 struct option_state *options);
63 static isc_result_t dhc6_parse_ia_pd(struct dhc6_ia **pia,
64 struct packet *packet,
65 struct option_state *options);
66 static isc_result_t dhc6_parse_addrs(struct dhc6_addr **paddr,
67 struct packet *packet,
68 struct option_state *options);
69 static isc_result_t dhc6_parse_prefixes(struct dhc6_addr **ppref,
70 struct packet *packet,
71 struct option_state *options);
72 static struct dhc6_ia *find_ia(struct dhc6_ia *head,
73 u_int16_t type, const char *id);
74 static struct dhc6_addr *find_addr(struct dhc6_addr *head,
75 struct iaddr *address);
76 static struct dhc6_addr *find_pref(struct dhc6_addr *head,
77 struct iaddr *prefix, u_int8_t plen);
78 void init_handler(struct packet *packet, struct client_state *client);
79 void info_request_handler(struct packet *packet, struct client_state *client);
80 void rapid_commit_handler(struct packet *packet, struct client_state *client);
81 void do_init6(void *input);
82 void do_info_request6(void *input);
83 void do_confirm6(void *input);
84 void reply_handler(struct packet *packet, struct client_state *client);
85 static isc_result_t dhc6_add_ia_na(struct client_state *client,
86 struct data_string *packet,
87 struct dhc6_lease *lease,
88 u_int8_t message);
89 static isc_result_t dhc6_add_ia_ta(struct client_state *client,
90 struct data_string *packet,
91 struct dhc6_lease *lease,
92 u_int8_t message);
93 static isc_result_t dhc6_add_ia_pd(struct client_state *client,
94 struct data_string *packet,
95 struct dhc6_lease *lease,
96 u_int8_t message);
97 static isc_boolean_t stopping_finished(void);
98 static void dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst);
99 void do_select6(void *input);
100 void do_refresh6(void *input);
101 static void do_release6(void *input);
102 static void start_bound(struct client_state *client);
103 static void start_informed(struct client_state *client);
104 void informed_handler(struct packet *packet, struct client_state *client);
105 void bound_handler(struct packet *packet, struct client_state *client);
106 void start_renew6(void *input);
107 void start_rebind6(void *input);
108 void do_depref(void *input);
109 void do_expire(void *input);
110 static void make_client6_options(struct client_state *client,
111 struct option_state **op,
112 struct dhc6_lease *lease, u_int8_t message);
113 static void script_write_params6(struct client_state *client,
114 const char *prefix,
115 struct option_state *options);
116 static void script_write_requested6(struct client_state *client);
117 static isc_boolean_t active_prefix(struct client_state *client);
118
119 static int check_timing6(struct client_state *client, u_int8_t msg_type,
120 char *msg_str, struct dhc6_lease *lease,
121 struct data_string *ds);
122
123 extern int onetry;
124 extern int stateless;
125
126 /*
127 * Assign DHCPv6 port numbers as a client.
128 */
129 void
dhcpv6_client_assignments(void)130 dhcpv6_client_assignments(void)
131 {
132 struct servent *ent;
133 unsigned code;
134
135 if (path_dhclient_pid == NULL)
136 path_dhclient_pid = _PATH_DHCLIENT6_PID;
137 if (path_dhclient_db == NULL)
138 path_dhclient_db = _PATH_DHCLIENT6_DB;
139
140 if (local_port == 0) {
141 ent = getservbyname("dhcpv6-client", "udp");
142 if (ent == NULL)
143 local_port = htons(546);
144 else
145 local_port = ent->s_port;
146 }
147
148 if (remote_port == 0) {
149 ent = getservbyname("dhcpv6-server", "udp");
150 if (ent == NULL)
151 remote_port = htons(547);
152 else
153 remote_port = ent->s_port;
154 }
155
156 memset(&DHCPv6DestAddr, 0, sizeof(DHCPv6DestAddr));
157 DHCPv6DestAddr.sin6_family = AF_INET6;
158 DHCPv6DestAddr.sin6_port = remote_port;
159 if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
160 &DHCPv6DestAddr.sin6_addr) <= 0) {
161 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers);
162 }
163
164 code = D6O_CLIENTID;
165 if (!option_code_hash_lookup(&clientid_option,
166 dhcpv6_universe.code_hash, &code, 0, MDL))
167 log_fatal("Unable to find the CLIENTID option definition.");
168
169 code = D6O_ELAPSED_TIME;
170 if (!option_code_hash_lookup(&elapsed_option,
171 dhcpv6_universe.code_hash, &code, 0, MDL))
172 log_fatal("Unable to find the ELAPSED_TIME option definition.");
173
174 code = D6O_IA_NA;
175 if (!option_code_hash_lookup(&ia_na_option, dhcpv6_universe.code_hash,
176 &code, 0, MDL))
177 log_fatal("Unable to find the IA_NA option definition.");
178
179 code = D6O_IA_TA;
180 if (!option_code_hash_lookup(&ia_ta_option, dhcpv6_universe.code_hash,
181 &code, 0, MDL))
182 log_fatal("Unable to find the IA_TA option definition.");
183
184 code = D6O_IA_PD;
185 if (!option_code_hash_lookup(&ia_pd_option, dhcpv6_universe.code_hash,
186 &code, 0, MDL))
187 log_fatal("Unable to find the IA_PD option definition.");
188
189 code = D6O_IAADDR;
190 if (!option_code_hash_lookup(&iaaddr_option, dhcpv6_universe.code_hash,
191 &code, 0, MDL))
192 log_fatal("Unable to find the IAADDR option definition.");
193
194 code = D6O_IAPREFIX;
195 if (!option_code_hash_lookup(&iaprefix_option,
196 dhcpv6_universe.code_hash,
197 &code, 0, MDL))
198 log_fatal("Unable to find the IAPREFIX option definition.");
199
200 code = D6O_ORO;
201 if (!option_code_hash_lookup(&oro_option, dhcpv6_universe.code_hash,
202 &code, 0, MDL))
203 log_fatal("Unable to find the ORO option definition.");
204
205 code = D6O_INFORMATION_REFRESH_TIME;
206 if (!option_code_hash_lookup(&irt_option, dhcpv6_universe.code_hash,
207 &code, 0, MDL))
208 log_fatal("Unable to find the IRT option definition.");
209
210 #ifndef __CYGWIN32__ /* XXX */
211 endservent();
212 #endif
213 }
214
215 /*
216 * Instead of implementing RFC3315 RAND (section 14) as a float "between"
217 * -0.1 and 0.1 non-inclusive, we implement it as an integer.
218 *
219 * The result is expected to follow this table:
220 *
221 * split range answer
222 * - ERROR - base <= 0
223 * 0 1 0..0 1 <= base <= 10
224 * 1 3 -1..1 11 <= base <= 20
225 * 2 5 -2..2 21 <= base <= 30
226 * 3 7 -3..3 31 <= base <= 40
227 * ...
228 *
229 * XXX: For this to make sense, we really need to do timing on a
230 * XXX: usec scale...we currently can assume zero for any value less than
231 * XXX: 11, which are very common in early stages of transmission for most
232 * XXX: messages.
233 */
234 static TIME
dhc6_rand(TIME base)235 dhc6_rand(TIME base)
236 {
237 TIME rval;
238 TIME range;
239 TIME split;
240
241 /*
242 * A zero or less timeout is a bad thing...we don't want to
243 * DHCP-flood anyone.
244 */
245 if (base <= 0)
246 log_fatal("Impossible condition at %s:%d.", MDL);
247
248 /*
249 * The first thing we do is count how many random integers we want
250 * in either direction (best thought of as the maximum negative
251 * integer, as we will subtract this potentially from a random 0).
252 */
253 split = (base - 1) / 10;
254
255 /* Don't bother with the rest of the math if we know we'll get 0. */
256 if (split == 0)
257 return 0;
258
259 /*
260 * Then we count the total number of integers in this set. This
261 * is twice the number of integers in positive and negative
262 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
263 */
264 range = (split * 2) + 1;
265
266 /* Take a random number from [0..(range-1)]. */
267 rval = random();
268 rval %= range;
269
270 /* Offset it to uncover potential negative values. */
271 rval -= split;
272
273 return rval;
274 }
275
276 /* Initialize message exchange timers (set RT from Initial-RT). */
277 static void
dhc6_retrans_init(struct client_state * client)278 dhc6_retrans_init(struct client_state *client)
279 {
280 int xid;
281
282 /* Initialize timers. */
283 client->txcount = 0;
284 client->RT = client->IRT + dhc6_rand(client->IRT);
285
286 /* Generate a new random 24-bit transaction ID for this exchange. */
287
288 #if (RAND_MAX >= 0x00ffffff)
289 xid = random();
290 #elif (RAND_MAX >= 0x0000ffff)
291 xid = (random() << 16) ^ random();
292 #elif (RAND_MAX >= 0x000000ff)
293 xid = (random() << 16) ^ (random() << 8) ^ random();
294 #else
295 # error "Random number generator of less than 8 bits not supported."
296 #endif
297
298 client->dhcpv6_transaction_id[0] = (xid >> 16) & 0xff;
299 client->dhcpv6_transaction_id[1] = (xid >> 8) & 0xff;
300 client->dhcpv6_transaction_id[2] = xid & 0xff;
301 }
302
303 /* Advance the DHCPv6 retransmission state once. */
304 static void
dhc6_retrans_advance(struct client_state * client)305 dhc6_retrans_advance(struct client_state *client)
306 {
307 struct timeval elapsed;
308
309 /* elapsed = cur - start */
310 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
311 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
312 if (elapsed.tv_usec < 0) {
313 elapsed.tv_sec -= 1;
314 elapsed.tv_usec += 1000000;
315 }
316 /* retrans_advance is called after consuming client->RT. */
317 /* elapsed += RT */
318 elapsed.tv_sec += client->RT / 100;
319 elapsed.tv_usec += (client->RT % 100) * 10000;
320 if (elapsed.tv_usec >= 1000000) {
321 elapsed.tv_sec += 1;
322 elapsed.tv_usec -= 1000000;
323 }
324
325 /*
326 * RT for each subsequent message transmission is based on the previous
327 * value of RT:
328 *
329 * RT = 2*RTprev + RAND*RTprev
330 */
331 client->RT += client->RT + dhc6_rand(client->RT);
332
333 /*
334 * MRT specifies an upper bound on the value of RT (disregarding the
335 * randomization added by the use of RAND). If MRT has a value of 0,
336 * there is no upper limit on the value of RT. Otherwise:
337 *
338 * if (RT > MRT)
339 * RT = MRT + RAND*MRT
340 */
341 if ((client->MRT != 0) && (client->RT > client->MRT))
342 client->RT = client->MRT + dhc6_rand(client->MRT);
343
344 /*
345 * Further, if there's an MRD, we should wake up upon reaching
346 * the MRD rather than at some point after it.
347 */
348 if (client->MRD == 0) {
349 /* Done. */
350 client->txcount++;
351 return;
352 }
353 /* elapsed += client->RT */
354 elapsed.tv_sec += client->RT / 100;
355 elapsed.tv_usec += (client->RT % 100) * 10000;
356 if (elapsed.tv_usec >= 1000000) {
357 elapsed.tv_sec += 1;
358 elapsed.tv_usec -= 1000000;
359 }
360 if (elapsed.tv_sec >= client->MRD) {
361 /*
362 * wake at RT + cur = start + MRD
363 */
364 client->RT = client->MRD +
365 (client->start_time.tv_sec - cur_tv.tv_sec);
366 client->RT = client->RT * 100 +
367 (client->start_time.tv_usec - cur_tv.tv_usec) / 10000;
368 }
369 client->txcount++;
370 }
371
372 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
373 static int
valid_reply(struct packet * packet,struct client_state * client)374 valid_reply(struct packet *packet, struct client_state *client)
375 {
376 struct data_string sid, cid;
377 struct option_cache *oc;
378 int rval = ISC_TRUE;
379
380 memset(&sid, 0, sizeof(sid));
381 memset(&cid, 0, sizeof(cid));
382
383 if (!lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID)) {
384 log_error("Response without a server identifier received.");
385 rval = ISC_FALSE;
386 }
387
388 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
389 if (!oc ||
390 !evaluate_option_cache(&sid, packet, NULL, client, packet->options,
391 client->sent_options, &global_scope, oc,
392 MDL)) {
393 log_error("Response without a client identifier.");
394 rval = ISC_FALSE;
395 }
396
397 oc = lookup_option(&dhcpv6_universe, client->sent_options,
398 D6O_CLIENTID);
399 if (!oc ||
400 !evaluate_option_cache(&cid, packet, NULL, client,
401 client->sent_options, NULL, &global_scope,
402 oc, MDL)) {
403 log_error("Local client identifier is missing!");
404 rval = ISC_FALSE;
405 }
406
407 if (sid.len == 0 ||
408 sid.len != cid.len ||
409 memcmp(sid.data, cid.data, sid.len)) {
410 log_error("Advertise with matching transaction ID, but "
411 "mismatching client id.");
412 rval = ISC_FALSE;
413 }
414
415 return rval;
416 }
417
418 /*
419 * Create a complete copy of a DHCPv6 lease structure.
420 */
421 static struct dhc6_lease *
dhc6_dup_lease(struct dhc6_lease * lease,const char * file,int line)422 dhc6_dup_lease(struct dhc6_lease *lease, const char *file, int line)
423 {
424 struct dhc6_lease *copy;
425 struct dhc6_ia **insert_ia, *ia;
426
427 copy = dmalloc(sizeof(*copy), file, line);
428 if (copy == NULL) {
429 log_error("Out of memory for v6 lease structure.");
430 return NULL;
431 }
432
433 data_string_copy(©->server_id, &lease->server_id, file, line);
434 copy->pref = lease->pref;
435
436 memcpy(copy->dhcpv6_transaction_id, lease->dhcpv6_transaction_id,
437 sizeof(copy->dhcpv6_transaction_id));
438
439 option_state_reference(©->options, lease->options, file, line);
440
441 insert_ia = ©->bindings;
442 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
443 *insert_ia = dhc6_dup_ia(ia, file, line);
444
445 if (*insert_ia == NULL) {
446 dhc6_lease_destroy(©, file, line);
447 return NULL;
448 }
449
450 insert_ia = &(*insert_ia)->next;
451 }
452
453 return copy;
454 }
455
456 /*
457 * Duplicate an IA structure.
458 */
459 static struct dhc6_ia *
dhc6_dup_ia(struct dhc6_ia * ia,const char * file,int line)460 dhc6_dup_ia(struct dhc6_ia *ia, const char *file, int line)
461 {
462 struct dhc6_ia *copy;
463 struct dhc6_addr **insert_addr, *addr;
464
465 copy = dmalloc(sizeof(*ia), file, line);
466
467 memcpy(copy->iaid, ia->iaid, sizeof(copy->iaid));
468
469 copy->ia_type = ia->ia_type;
470 copy->starts = ia->starts;
471 copy->renew = ia->renew;
472 copy->rebind = ia->rebind;
473
474 insert_addr = ©->addrs;
475 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
476 *insert_addr = dhc6_dup_addr(addr, file, line);
477
478 if (*insert_addr == NULL) {
479 dhc6_ia_destroy(©, file, line);
480 return NULL;
481 }
482
483 insert_addr = &(*insert_addr)->next;
484 }
485
486 if (ia->options != NULL)
487 option_state_reference(©->options, ia->options,
488 file, line);
489
490 return copy;
491 }
492
493 /*
494 * Duplicate an IAADDR or IAPREFIX structure.
495 */
496 static struct dhc6_addr *
dhc6_dup_addr(struct dhc6_addr * addr,const char * file,int line)497 dhc6_dup_addr(struct dhc6_addr *addr, const char *file, int line)
498 {
499 struct dhc6_addr *copy;
500
501 copy = dmalloc(sizeof(*addr), file, line);
502
503 if (copy == NULL)
504 return NULL;
505
506 memcpy(©->address, &addr->address, sizeof(copy->address));
507
508 copy->plen = addr->plen;
509 copy->flags = addr->flags;
510 copy->starts = addr->starts;
511 copy->preferred_life = addr->preferred_life;
512 copy->max_life = addr->max_life;
513
514 if (addr->options != NULL)
515 option_state_reference(©->options, addr->options,
516 file, line);
517
518 return copy;
519 }
520
521 /*
522 * Form a DHCPv6 lease structure based upon packet contents. Creates and
523 * populates IA's and any IAADDR/IAPREFIX's they contain.
524 * Parsed options are deleted in order to not save them in the lease file.
525 */
526 static struct dhc6_lease *
dhc6_leaseify(struct packet * packet)527 dhc6_leaseify(struct packet *packet)
528 {
529 struct data_string ds;
530 struct dhc6_lease *lease;
531 struct option_cache *oc;
532
533 lease = dmalloc(sizeof(*lease), MDL);
534 if (lease == NULL) {
535 log_error("Out of memory for v6 lease structure.");
536 return NULL;
537 }
538
539 memcpy(lease->dhcpv6_transaction_id, packet->dhcpv6_transaction_id, 3);
540 option_state_reference(&lease->options, packet->options, MDL);
541
542 memset(&ds, 0, sizeof(ds));
543
544 /* Determine preference (default zero). */
545 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
546 if (oc &&
547 evaluate_option_cache(&ds, packet, NULL, NULL, lease->options,
548 NULL, &global_scope, oc, MDL)) {
549 if (ds.len != 1) {
550 log_error("Invalid length of DHCPv6 Preference option "
551 "(%d != 1)", ds.len);
552 data_string_forget(&ds, MDL);
553 dhc6_lease_destroy(&lease, MDL);
554 return NULL;
555 } else {
556 lease->pref = ds.data[0];
557 log_debug("RCV: X-- Preference %u.",
558 (unsigned)lease->pref);
559 }
560
561 data_string_forget(&ds, MDL);
562 }
563 delete_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
564
565 /*
566 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
567 * options.
568 */
569 if (dhc6_parse_ia_na(&lease->bindings, packet,
570 lease->options) != ISC_R_SUCCESS) {
571 /* Error conditions are logged by the caller. */
572 dhc6_lease_destroy(&lease, MDL);
573 return NULL;
574 }
575 /*
576 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
577 * options.
578 */
579 if (dhc6_parse_ia_ta(&lease->bindings, packet,
580 lease->options) != ISC_R_SUCCESS) {
581 /* Error conditions are logged by the caller. */
582 dhc6_lease_destroy(&lease, MDL);
583 return NULL;
584 }
585 /*
586 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
587 * options.
588 */
589 if (dhc6_parse_ia_pd(&lease->bindings, packet,
590 lease->options) != ISC_R_SUCCESS) {
591 /* Error conditions are logged by the caller. */
592 dhc6_lease_destroy(&lease, MDL);
593 return NULL;
594 }
595
596 /*
597 * This is last because in the future we may want to make a different
598 * key based upon additional information from the packet (we may need
599 * to allow multiple leases in one client state per server, but we're
600 * not sure based on what additional keys now).
601 */
602 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
603 if ((oc == NULL) ||
604 !evaluate_option_cache(&lease->server_id, packet, NULL, NULL,
605 lease->options, NULL, &global_scope,
606 oc, MDL) ||
607 lease->server_id.len == 0) {
608 /* This should be impossible due to validation checks earlier.
609 */
610 log_error("Invalid SERVERID option cache.");
611 dhc6_lease_destroy(&lease, MDL);
612 return NULL;
613 } else {
614 log_debug("RCV: X-- Server ID: %s",
615 print_hex_1(lease->server_id.len,
616 lease->server_id.data, 52));
617 }
618
619 return lease;
620 }
621
622 static isc_result_t
dhc6_parse_ia_na(struct dhc6_ia ** pia,struct packet * packet,struct option_state * options)623 dhc6_parse_ia_na(struct dhc6_ia **pia, struct packet *packet,
624 struct option_state *options)
625 {
626 struct data_string ds;
627 struct dhc6_ia *ia;
628 struct option_cache *oc;
629 isc_result_t result;
630
631 memset(&ds, 0, sizeof(ds));
632
633 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_NA);
634 for ( ; oc != NULL ; oc = oc->next) {
635 ia = dmalloc(sizeof(*ia), MDL);
636 if (ia == NULL) {
637 log_error("Out of memory allocating IA_NA structure.");
638 return ISC_R_NOMEMORY;
639 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
640 options, NULL,
641 &global_scope, oc, MDL) &&
642 ds.len >= 12) {
643 memcpy(ia->iaid, ds.data, 4);
644 ia->ia_type = D6O_IA_NA;
645 ia->starts = cur_time;
646 ia->renew = getULong(ds.data + 4);
647 ia->rebind = getULong(ds.data + 8);
648
649 log_debug("RCV: X-- IA_NA %s",
650 print_hex_1(4, ia->iaid, 59));
651 /* XXX: This should be the printed time I think. */
652 log_debug("RCV: | X-- starts %u",
653 (unsigned)ia->starts);
654 log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
655 log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
656
657 /*
658 * RFC3315 section 22.4, discard IA_NA's that
659 * have t1 greater than t2, and both not zero.
660 * Since RFC3315 defines this behaviour, it is not
661 * an error - just normal operation.
662 *
663 * Note that RFC3315 says we MUST honor these values
664 * if they are not zero. So insane values are
665 * totally OK.
666 */
667 if ((ia->renew > 0) && (ia->rebind > 0) &&
668 (ia->renew > ia->rebind)) {
669 log_debug("RCV: | !-- INVALID renew/rebind "
670 "times, IA_NA discarded.");
671 dfree(ia, MDL);
672 data_string_forget(&ds, MDL);
673 continue;
674 }
675
676 if (ds.len > 12) {
677 log_debug("RCV: | X-- [Options]");
678
679 if (!option_state_allocate(&ia->options,
680 MDL)) {
681 log_error("Out of memory allocating "
682 "IA_NA option state.");
683 dfree(ia, MDL);
684 data_string_forget(&ds, MDL);
685 return ISC_R_NOMEMORY;
686 }
687
688 if (!parse_option_buffer(ia->options,
689 ds.data + 12,
690 ds.len - 12,
691 &dhcpv6_universe)) {
692 log_error("Corrupt IA_NA options.");
693 option_state_dereference(&ia->options,
694 MDL);
695 dfree(ia, MDL);
696 data_string_forget(&ds, MDL);
697 return DHCP_R_BADPARSE;
698 }
699 }
700 data_string_forget(&ds, MDL);
701
702 if (ia->options != NULL) {
703 result = dhc6_parse_addrs(&ia->addrs, packet,
704 ia->options);
705 if (result != ISC_R_SUCCESS) {
706 option_state_dereference(&ia->options,
707 MDL);
708 dfree(ia, MDL);
709 return result;
710 }
711 }
712
713 while (*pia != NULL)
714 pia = &(*pia)->next;
715 *pia = ia;
716 pia = &ia->next;
717 } else {
718 log_error("Invalid IA_NA option cache.");
719 dfree(ia, MDL);
720 if (ds.len != 0)
721 data_string_forget(&ds, MDL);
722 return ISC_R_UNEXPECTED;
723 }
724 }
725 delete_option(&dhcpv6_universe, options, D6O_IA_NA);
726
727 return ISC_R_SUCCESS;
728 }
729
730 static isc_result_t
dhc6_parse_ia_ta(struct dhc6_ia ** pia,struct packet * packet,struct option_state * options)731 dhc6_parse_ia_ta(struct dhc6_ia **pia, struct packet *packet,
732 struct option_state *options)
733 {
734 struct data_string ds;
735 struct dhc6_ia *ia;
736 struct option_cache *oc;
737 isc_result_t result;
738
739 memset(&ds, 0, sizeof(ds));
740
741 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_TA);
742 for ( ; oc != NULL ; oc = oc->next) {
743 ia = dmalloc(sizeof(*ia), MDL);
744 if (ia == NULL) {
745 log_error("Out of memory allocating IA_TA structure.");
746 return ISC_R_NOMEMORY;
747 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
748 options, NULL,
749 &global_scope, oc, MDL) &&
750 ds.len >= 4) {
751 memcpy(ia->iaid, ds.data, 4);
752 ia->ia_type = D6O_IA_TA;
753 ia->starts = cur_time;
754
755 log_debug("RCV: X-- IA_TA %s",
756 print_hex_1(4, ia->iaid, 59));
757 /* XXX: This should be the printed time I think. */
758 log_debug("RCV: | X-- starts %u",
759 (unsigned)ia->starts);
760
761 if (ds.len > 4) {
762 log_debug("RCV: | X-- [Options]");
763
764 if (!option_state_allocate(&ia->options,
765 MDL)) {
766 log_error("Out of memory allocating "
767 "IA_TA option state.");
768 dfree(ia, MDL);
769 data_string_forget(&ds, MDL);
770 return ISC_R_NOMEMORY;
771 }
772
773 if (!parse_option_buffer(ia->options,
774 ds.data + 4,
775 ds.len - 4,
776 &dhcpv6_universe)) {
777 log_error("Corrupt IA_TA options.");
778 option_state_dereference(&ia->options,
779 MDL);
780 dfree(ia, MDL);
781 data_string_forget(&ds, MDL);
782 return DHCP_R_BADPARSE;
783 }
784 }
785 data_string_forget(&ds, MDL);
786
787 if (ia->options != NULL) {
788 result = dhc6_parse_addrs(&ia->addrs, packet,
789 ia->options);
790 if (result != ISC_R_SUCCESS) {
791 option_state_dereference(&ia->options,
792 MDL);
793 dfree(ia, MDL);
794 return result;
795 }
796 }
797
798 while (*pia != NULL)
799 pia = &(*pia)->next;
800 *pia = ia;
801 pia = &ia->next;
802 } else {
803 log_error("Invalid IA_TA option cache.");
804 dfree(ia, MDL);
805 if (ds.len != 0)
806 data_string_forget(&ds, MDL);
807 return ISC_R_UNEXPECTED;
808 }
809 }
810 delete_option(&dhcpv6_universe, options, D6O_IA_TA);
811
812 return ISC_R_SUCCESS;
813 }
814
815 static isc_result_t
dhc6_parse_ia_pd(struct dhc6_ia ** pia,struct packet * packet,struct option_state * options)816 dhc6_parse_ia_pd(struct dhc6_ia **pia, struct packet *packet,
817 struct option_state *options)
818 {
819 struct data_string ds;
820 struct dhc6_ia *ia;
821 struct option_cache *oc;
822 isc_result_t result;
823
824 memset(&ds, 0, sizeof(ds));
825
826 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_PD);
827 for ( ; oc != NULL ; oc = oc->next) {
828 ia = dmalloc(sizeof(*ia), MDL);
829 if (ia == NULL) {
830 log_error("Out of memory allocating IA_PD structure.");
831 return ISC_R_NOMEMORY;
832 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
833 options, NULL,
834 &global_scope, oc, MDL) &&
835 ds.len >= 12) {
836 memcpy(ia->iaid, ds.data, 4);
837 ia->ia_type = D6O_IA_PD;
838 ia->starts = cur_time;
839 ia->renew = getULong(ds.data + 4);
840 ia->rebind = getULong(ds.data + 8);
841
842 log_debug("RCV: X-- IA_PD %s",
843 print_hex_1(4, ia->iaid, 59));
844 /* XXX: This should be the printed time I think. */
845 log_debug("RCV: | X-- starts %u",
846 (unsigned)ia->starts);
847 log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
848 log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
849
850 /*
851 * RFC3633 section 9, discard IA_PD's that
852 * have t1 greater than t2, and both not zero.
853 * Since RFC3633 defines this behaviour, it is not
854 * an error - just normal operation.
855 */
856 if ((ia->renew > 0) && (ia->rebind > 0) &&
857 (ia->renew > ia->rebind)) {
858 log_debug("RCV: | !-- INVALID renew/rebind "
859 "times, IA_PD discarded.");
860 dfree(ia, MDL);
861 data_string_forget(&ds, MDL);
862 continue;
863 }
864
865 if (ds.len > 12) {
866 log_debug("RCV: | X-- [Options]");
867
868 if (!option_state_allocate(&ia->options,
869 MDL)) {
870 log_error("Out of memory allocating "
871 "IA_PD option state.");
872 dfree(ia, MDL);
873 data_string_forget(&ds, MDL);
874 return ISC_R_NOMEMORY;
875 }
876
877 if (!parse_option_buffer(ia->options,
878 ds.data + 12,
879 ds.len - 12,
880 &dhcpv6_universe)) {
881 log_error("Corrupt IA_PD options.");
882 option_state_dereference(&ia->options,
883 MDL);
884 dfree(ia, MDL);
885 data_string_forget(&ds, MDL);
886 return DHCP_R_BADPARSE;
887 }
888 }
889 data_string_forget(&ds, MDL);
890
891 if (ia->options != NULL) {
892 result = dhc6_parse_prefixes(&ia->addrs,
893 packet,
894 ia->options);
895 if (result != ISC_R_SUCCESS) {
896 option_state_dereference(&ia->options,
897 MDL);
898 dfree(ia, MDL);
899 return result;
900 }
901 }
902
903 while (*pia != NULL)
904 pia = &(*pia)->next;
905 *pia = ia;
906 pia = &ia->next;
907 } else {
908 log_error("Invalid IA_PD option cache.");
909 dfree(ia, MDL);
910 if (ds.len != 0)
911 data_string_forget(&ds, MDL);
912 return ISC_R_UNEXPECTED;
913 }
914 }
915 delete_option(&dhcpv6_universe, options, D6O_IA_PD);
916
917 return ISC_R_SUCCESS;
918 }
919
920
921 static isc_result_t
dhc6_parse_addrs(struct dhc6_addr ** paddr,struct packet * packet,struct option_state * options)922 dhc6_parse_addrs(struct dhc6_addr **paddr, struct packet *packet,
923 struct option_state *options)
924 {
925 struct data_string ds;
926 struct option_cache *oc;
927 struct dhc6_addr *addr;
928
929 memset(&ds, 0, sizeof(ds));
930
931 oc = lookup_option(&dhcpv6_universe, options, D6O_IAADDR);
932 for ( ; oc != NULL ; oc = oc->next) {
933 addr = dmalloc(sizeof(*addr), MDL);
934 if (addr == NULL) {
935 log_error("Out of memory allocating "
936 "address structure.");
937 return ISC_R_NOMEMORY;
938 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
939 options, NULL, &global_scope,
940 oc, MDL) &&
941 (ds.len >= 24)) {
942
943 addr->address.len = 16;
944 memcpy(addr->address.iabuf, ds.data, 16);
945 addr->starts = cur_time;
946 addr->preferred_life = getULong(ds.data + 16);
947 addr->max_life = getULong(ds.data + 20);
948
949 log_debug("RCV: | | X-- IAADDR %s",
950 piaddr(addr->address));
951 log_debug("RCV: | | | X-- Preferred lifetime %u.",
952 addr->preferred_life);
953 log_debug("RCV: | | | X-- Max lifetime %u.",
954 addr->max_life);
955
956 /*
957 * RFC 3315 section 22.6 says we must discard
958 * addresses whose pref is later than valid.
959 */
960 if ((addr->preferred_life > addr->max_life)) {
961 log_debug("RCV: | | | !-- INVALID lifetimes, "
962 "IAADDR discarded. Check your "
963 "server configuration.");
964 dfree(addr, MDL);
965 data_string_forget(&ds, MDL);
966 continue;
967 }
968
969 /*
970 * Fortunately this is the last recursion in the
971 * protocol.
972 */
973 if (ds.len > 24) {
974 if (!option_state_allocate(&addr->options,
975 MDL)) {
976 log_error("Out of memory allocating "
977 "IAADDR option state.");
978 dfree(addr, MDL);
979 data_string_forget(&ds, MDL);
980 return ISC_R_NOMEMORY;
981 }
982
983 if (!parse_option_buffer(addr->options,
984 ds.data + 24,
985 ds.len - 24,
986 &dhcpv6_universe)) {
987 log_error("Corrupt IAADDR options.");
988 option_state_dereference(&addr->options,
989 MDL);
990 dfree(addr, MDL);
991 data_string_forget(&ds, MDL);
992 return DHCP_R_BADPARSE;
993 }
994 }
995
996 if (addr->options != NULL)
997 log_debug("RCV: | | | X-- "
998 "[Options]");
999
1000 data_string_forget(&ds, MDL);
1001
1002 *paddr = addr;
1003 paddr = &addr->next;
1004 } else {
1005 log_error("Invalid IAADDR option cache.");
1006 dfree(addr, MDL);
1007 if (ds.len != 0)
1008 data_string_forget(&ds, MDL);
1009 return ISC_R_UNEXPECTED;
1010 }
1011 }
1012 delete_option(&dhcpv6_universe, options, D6O_IAADDR);
1013
1014 return ISC_R_SUCCESS;
1015 }
1016
1017 static isc_result_t
dhc6_parse_prefixes(struct dhc6_addr ** ppfx,struct packet * packet,struct option_state * options)1018 dhc6_parse_prefixes(struct dhc6_addr **ppfx, struct packet *packet,
1019 struct option_state *options)
1020 {
1021 struct data_string ds;
1022 struct option_cache *oc;
1023 struct dhc6_addr *pfx;
1024
1025 memset(&ds, 0, sizeof(ds));
1026
1027 oc = lookup_option(&dhcpv6_universe, options, D6O_IAPREFIX);
1028 for ( ; oc != NULL ; oc = oc->next) {
1029 pfx = dmalloc(sizeof(*pfx), MDL);
1030 if (pfx == NULL) {
1031 log_error("Out of memory allocating "
1032 "prefix structure.");
1033 return ISC_R_NOMEMORY;
1034 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
1035 options, NULL, &global_scope,
1036 oc, MDL) &&
1037 (ds.len >= 25)) {
1038
1039 pfx->preferred_life = getULong(ds.data);
1040 pfx->max_life = getULong(ds.data + 4);
1041 pfx->plen = getUChar(ds.data + 8);
1042 pfx->address.len = 16;
1043 memcpy(pfx->address.iabuf, ds.data + 9, 16);
1044 pfx->starts = cur_time;
1045
1046 log_debug("RCV: | | X-- IAPREFIX %s/%d",
1047 piaddr(pfx->address), (int)pfx->plen);
1048 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1049 pfx->preferred_life);
1050 log_debug("RCV: | | | X-- Max lifetime %u.",
1051 pfx->max_life);
1052
1053 /* Sanity check over the prefix length */
1054 if ((pfx->plen < 4) || (pfx->plen > 128)) {
1055 log_debug("RCV: | | | !-- INVALID prefix "
1056 "length, IAPREFIX discarded. "
1057 "Check your server configuration.");
1058 dfree(pfx, MDL);
1059 data_string_forget(&ds, MDL);
1060 continue;
1061 }
1062 /*
1063 * RFC 3633 section 10 says we must discard
1064 * prefixes whose pref is later than valid.
1065 */
1066 if ((pfx->preferred_life > pfx->max_life)) {
1067 log_debug("RCV: | | | !-- INVALID lifetimes, "
1068 "IAPREFIX discarded. Check your "
1069 "server configuration.");
1070 dfree(pfx, MDL);
1071 data_string_forget(&ds, MDL);
1072 continue;
1073 }
1074
1075 /*
1076 * Fortunately this is the last recursion in the
1077 * protocol.
1078 */
1079 if (ds.len > 25) {
1080 if (!option_state_allocate(&pfx->options,
1081 MDL)) {
1082 log_error("Out of memory allocating "
1083 "IAPREFIX option state.");
1084 dfree(pfx, MDL);
1085 data_string_forget(&ds, MDL);
1086 return ISC_R_NOMEMORY;
1087 }
1088
1089 if (!parse_option_buffer(pfx->options,
1090 ds.data + 25,
1091 ds.len - 25,
1092 &dhcpv6_universe)) {
1093 log_error("Corrupt IAPREFIX options.");
1094 option_state_dereference(&pfx->options,
1095 MDL);
1096 dfree(pfx, MDL);
1097 data_string_forget(&ds, MDL);
1098 return DHCP_R_BADPARSE;
1099 }
1100 }
1101
1102 if (pfx->options != NULL)
1103 log_debug("RCV: | | | X-- "
1104 "[Options]");
1105
1106 data_string_forget(&ds, MDL);
1107
1108 *ppfx = pfx;
1109 ppfx = &pfx->next;
1110 } else {
1111 log_error("Invalid IAPREFIX option cache.");
1112 dfree(pfx, MDL);
1113 if (ds.len != 0)
1114 data_string_forget(&ds, MDL);
1115 return ISC_R_UNEXPECTED;
1116 }
1117 }
1118 delete_option(&dhcpv6_universe, options, D6O_IAPREFIX);
1119
1120 return ISC_R_SUCCESS;
1121 }
1122
1123 /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
1124 void
dhc6_lease_destroy(struct dhc6_lease ** src,const char * file,int line)1125 dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
1126 {
1127 struct dhc6_ia *ia, *nia;
1128 struct dhc6_lease *lease;
1129
1130 if (src == NULL || *src == NULL) {
1131 log_error("Attempt to destroy null lease.");
1132 return;
1133 }
1134 lease = *src;
1135
1136 if (lease->server_id.len != 0)
1137 data_string_forget(&lease->server_id, file, line);
1138
1139 for (ia = lease->bindings ; ia != NULL ; ia = nia) {
1140 nia = ia->next;
1141
1142 dhc6_ia_destroy(&ia, file, line);
1143 }
1144
1145 if (lease->options != NULL)
1146 option_state_dereference(&lease->options, file, line);
1147
1148 dfree(lease, file, line);
1149 *src = NULL;
1150 }
1151
1152 /*
1153 * Traverse the addresses list, and destroy their contents, and NULL the
1154 * list pointer.
1155 */
1156 static void
dhc6_ia_destroy(struct dhc6_ia ** src,const char * file,int line)1157 dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line)
1158 {
1159 struct dhc6_addr *addr, *naddr;
1160 struct dhc6_ia *ia;
1161
1162 if (src == NULL || *src == NULL) {
1163 log_error("Attempt to destroy null IA.");
1164 return;
1165 }
1166 ia = *src;
1167
1168 for (addr = ia->addrs ; addr != NULL ; addr = naddr) {
1169 naddr = addr->next;
1170
1171 if (addr->options != NULL)
1172 option_state_dereference(&addr->options, file, line);
1173
1174 dfree(addr, file, line);
1175 }
1176
1177 if (ia->options != NULL)
1178 option_state_dereference(&ia->options, file, line);
1179
1180 dfree(ia, file, line);
1181 *src = NULL;
1182 }
1183
1184 /*
1185 * For a given lease, insert it into the tail of the lease list. Upon
1186 * finding a duplicate by server id, remove it and take over its position.
1187 */
1188 static void
insert_lease(struct dhc6_lease ** head,struct dhc6_lease * new)1189 insert_lease(struct dhc6_lease **head, struct dhc6_lease *new)
1190 {
1191 while (*head != NULL) {
1192 if ((*head)->server_id.len == new->server_id.len &&
1193 memcmp((*head)->server_id.data, new->server_id.data,
1194 new->server_id.len) == 0) {
1195 new->next = (*head)->next;
1196 dhc6_lease_destroy(head, MDL);
1197 break;
1198 }
1199
1200 head= &(*head)->next;
1201 }
1202
1203 *head = new;
1204 return;
1205 }
1206
1207 /*
1208 * Not really clear what to do here yet.
1209 */
1210 static int
dhc6_score_lease(struct client_state * client,struct dhc6_lease * lease)1211 dhc6_score_lease(struct client_state *client, struct dhc6_lease *lease)
1212 {
1213 struct dhc6_ia *ia;
1214 struct dhc6_addr *addr;
1215 struct option **req;
1216 int i;
1217
1218 if (lease->score)
1219 return lease->score;
1220
1221 lease->score = 1;
1222
1223 /* If this lease lacks a required option, dump it. */
1224 /* XXX: we should be able to cache the failure... */
1225 req = client->config->required_options;
1226 if (req != NULL) {
1227 for (i = 0 ; req[i] != NULL ; i++) {
1228 if (lookup_option(&dhcpv6_universe, lease->options,
1229 req[i]->code) == NULL) {
1230 lease->score = 0;
1231 return lease->score;
1232 }
1233 }
1234 }
1235
1236 /* If this lease contains a requested option, improve its score. */
1237 req = client->config->requested_options;
1238 if (req != NULL) {
1239 for (i = 0 ; req[i] != NULL ; i++) {
1240 if (lookup_option(&dhcpv6_universe, lease->options,
1241 req[i]->code) != NULL)
1242 lease->score++;
1243 }
1244 }
1245
1246 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
1247 lease->score += 50;
1248
1249 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
1250 lease->score += 100;
1251 }
1252 }
1253
1254 return lease->score;
1255 }
1256
1257 /*
1258 * start_init6() kicks off the process, transmitting a packet and
1259 * scheduling a retransmission event.
1260 */
1261 void
start_init6(struct client_state * client)1262 start_init6(struct client_state *client)
1263 {
1264 struct timeval tv;
1265
1266 log_debug("PRC: Soliciting for leases (INIT).");
1267 client->state = S_INIT;
1268
1269 /* Initialize timers, RFC3315 section 17.1.2. */
1270 client->IRT = SOL_TIMEOUT * 100;
1271 client->MRT = SOL_MAX_RT * 100;
1272 client->MRC = 0;
1273 /* Default is 0 (no max) but -1 changes this. */
1274 if (!onetry)
1275 client->MRD = 0;
1276 else
1277 client->MRD = client->config->timeout;
1278
1279 dhc6_retrans_init(client);
1280
1281 /*
1282 * RFC3315 section 17.1.2 goes out of its way:
1283 * Also, the first RT MUST be selected to be strictly greater than IRT
1284 * by choosing RAND to be strictly greater than 0.
1285 */
1286 /* if RAND < 0 then RAND = -RAND */
1287 if (client->RT <= client->IRT)
1288 client->RT = client->IRT + (client->IRT - client->RT);
1289 /* if RAND == 0 then RAND = 1 */
1290 if (client->RT <= client->IRT)
1291 client->RT = client->IRT + 1;
1292
1293 client->v6_handler = init_handler;
1294
1295 /*
1296 * RFC3315 section 17.1.2 says we MUST start the first packet
1297 * between 0 and SOL_MAX_DELAY seconds. The good news is
1298 * SOL_MAX_DELAY is 1.
1299 */
1300 tv.tv_sec = cur_tv.tv_sec;
1301 tv.tv_usec = cur_tv.tv_usec;
1302 tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
1303 if (tv.tv_usec >= 1000000) {
1304 tv.tv_sec += 1;
1305 tv.tv_usec -= 1000000;
1306 }
1307 add_timeout(&tv, do_init6, client, NULL, NULL);
1308
1309 if (nowait)
1310 finish_daemon();
1311 }
1312
1313 /*
1314 * start_info_request6() kicks off the process, transmitting an info
1315 * request packet and scheduling a retransmission event.
1316 */
1317 void
start_info_request6(struct client_state * client)1318 start_info_request6(struct client_state *client)
1319 {
1320 struct timeval tv;
1321
1322 log_debug("PRC: Requesting information (INIT).");
1323 client->state = S_INIT;
1324
1325 /* Initialize timers, RFC3315 section 18.1.5. */
1326 client->IRT = INF_TIMEOUT * 100;
1327 client->MRT = INF_MAX_RT * 100;
1328 client->MRC = 0;
1329 /* Default is 0 (no max) but -1 changes this. */
1330 if (!onetry)
1331 client->MRD = 0;
1332 else
1333 client->MRD = client->config->timeout;
1334
1335 dhc6_retrans_init(client);
1336
1337 client->v6_handler = info_request_handler;
1338
1339 /*
1340 * RFC3315 section 18.1.5 says we MUST start the first packet
1341 * between 0 and INF_MAX_DELAY seconds. The good news is
1342 * INF_MAX_DELAY is 1.
1343 */
1344 tv.tv_sec = cur_tv.tv_sec;
1345 tv.tv_usec = cur_tv.tv_usec;
1346 tv.tv_usec += (random() % (INF_MAX_DELAY * 100)) * 10000;
1347 if (tv.tv_usec >= 1000000) {
1348 tv.tv_sec += 1;
1349 tv.tv_usec -= 1000000;
1350 }
1351 add_timeout(&tv, do_info_request6, client, NULL, NULL);
1352
1353 if (nowait)
1354 go_daemon();
1355 }
1356
1357 /*
1358 * start_confirm6() kicks off an "init-reboot" version of the process, at
1359 * startup to find out if old bindings are 'fair' and at runtime whenever
1360 * a link cycles state we'll eventually want to do this.
1361 */
1362 void
start_confirm6(struct client_state * client)1363 start_confirm6(struct client_state *client)
1364 {
1365 struct timeval tv;
1366
1367 /* If there is no active lease, there is nothing to check. */
1368 if ((client->active_lease == NULL) ||
1369 !active_prefix(client) ||
1370 client->active_lease->released) {
1371 start_init6(client);
1372 return;
1373 }
1374
1375 log_debug("PRC: Confirming active lease (INIT-REBOOT).");
1376 client->state = S_REBOOTING;
1377
1378 /* Initialize timers, RFC3315 section 17.1.3. */
1379 client->IRT = CNF_TIMEOUT * 100;
1380 client->MRT = CNF_MAX_RT * 100;
1381 client->MRC = 0;
1382 client->MRD = CNF_MAX_RD;
1383
1384 dhc6_retrans_init(client);
1385
1386 client->v6_handler = reply_handler;
1387
1388 /*
1389 * RFC3315 section 18.1.2 says we MUST start the first packet
1390 * between 0 and CNF_MAX_DELAY seconds. The good news is
1391 * CNF_MAX_DELAY is 1.
1392 */
1393 tv.tv_sec = cur_tv.tv_sec;
1394 tv.tv_usec = cur_tv.tv_usec;
1395 tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
1396 if (tv.tv_usec >= 1000000) {
1397 tv.tv_sec += 1;
1398 tv.tv_usec -= 1000000;
1399 }
1400 if (wanted_ia_pd != 0) {
1401 client->state = S_REBINDING;
1402 client->refresh_type = DHCPV6_REBIND;
1403 add_timeout(&tv, do_refresh6, client, NULL, NULL);
1404 } else
1405 add_timeout(&tv, do_confirm6, client, NULL, NULL);
1406 }
1407
1408 /*
1409 * check_timing6() check on the timing for sending a v6 message
1410 * and then do the basic initialization for a v6 message.
1411 */
1412 #define CHK_TIM_SUCCESS 0
1413 #define CHK_TIM_MRC_EXCEEDED 1
1414 #define CHK_TIM_MRD_EXCEEDED 2
1415 #define CHK_TIM_ALLOC_FAILURE 3
1416
1417 int
check_timing6(struct client_state * client,u_int8_t msg_type,char * msg_str,struct dhc6_lease * lease,struct data_string * ds)1418 check_timing6 (struct client_state *client, u_int8_t msg_type,
1419 char *msg_str, struct dhc6_lease *lease,
1420 struct data_string *ds)
1421 {
1422 struct timeval elapsed;
1423
1424 /*
1425 * Start_time starts at the first transmission.
1426 */
1427 if (client->txcount == 0) {
1428 client->start_time.tv_sec = cur_tv.tv_sec;
1429 client->start_time.tv_usec = cur_tv.tv_usec;
1430 } else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
1431 log_info("Max retransmission count exceeded.");
1432 return(CHK_TIM_MRC_EXCEEDED);
1433 }
1434
1435 /* elapsed = cur - start */
1436 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
1437 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
1438 if (elapsed.tv_usec < 0) {
1439 elapsed.tv_sec -= 1;
1440 elapsed.tv_usec += 1000000;
1441 }
1442
1443 /* Check if finished (-1 argument). */
1444 if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
1445 log_info("Max retransmission duration exceeded.");
1446 return(CHK_TIM_MRD_EXCEEDED);
1447 }
1448
1449 memset(ds, 0, sizeof(*ds));
1450 if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
1451 log_error("Unable to allocate memory for %s.", msg_str);
1452 return(CHK_TIM_ALLOC_FAILURE);
1453 }
1454 ds->data = ds->buffer->data;
1455 ds->len = 4;
1456
1457 ds->buffer->data[0] = msg_type;
1458 memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
1459
1460 /* Form an elapsed option. */
1461 /* Maximum value is 65535 1/100s coded as 0xffff. */
1462 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
1463 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
1464 client->elapsed = 0xffff;
1465 } else {
1466 client->elapsed = elapsed.tv_sec * 100;
1467 client->elapsed += elapsed.tv_usec / 10000;
1468 }
1469
1470 if (client->elapsed == 0)
1471 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
1472 else
1473 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
1474 (unsigned)client->elapsed);
1475
1476 client->elapsed = htons(client->elapsed);
1477
1478 make_client6_options(client, &client->sent_options, lease, msg_type);
1479
1480 return(CHK_TIM_SUCCESS);
1481 }
1482
1483 /*
1484 * do_init6() marshals and transmits a solicit.
1485 */
1486 void
do_init6(void * input)1487 do_init6(void *input)
1488 {
1489 struct client_state *client;
1490 struct dhc6_ia *old_ia;
1491 struct dhc6_addr *old_addr;
1492 struct data_string ds;
1493 struct data_string ia;
1494 struct data_string addr;
1495 struct timeval tv;
1496 u_int32_t t1, t2;
1497 int i, idx, len, send_ret;
1498
1499 client = input;
1500
1501 /*
1502 * In RFC3315 section 17.1.2, the retransmission timer is
1503 * used as the selecting timer.
1504 */
1505 if (client->advertised_leases != NULL) {
1506 start_selecting6(client);
1507 return;
1508 }
1509
1510 switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
1511 case CHK_TIM_MRC_EXCEEDED:
1512 case CHK_TIM_ALLOC_FAILURE:
1513 return;
1514 case CHK_TIM_MRD_EXCEEDED:
1515 client->state = S_STOPPED;
1516 if (client->active_lease != NULL) {
1517 dhc6_lease_destroy(&client->active_lease, MDL);
1518 client->active_lease = NULL;
1519 }
1520 /* Stop if and only if this is the last client. */
1521 if (stopping_finished())
1522 exit(2);
1523 return;
1524 }
1525
1526 /*
1527 * Fetch any configured 'sent' options (includes DUID) in wire format.
1528 */
1529 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
1530 NULL, client->sent_options, &global_scope,
1531 &dhcpv6_universe);
1532
1533 /* Use a specific handler with rapid-commit. */
1534 if (lookup_option(&dhcpv6_universe, client->sent_options,
1535 D6O_RAPID_COMMIT) != NULL) {
1536 client->v6_handler = rapid_commit_handler;
1537 }
1538
1539 /* Append IA_NA. */
1540 for (i = 0; i < wanted_ia_na; i++) {
1541 /*
1542 * XXX: maybe the IA_NA('s) should be put into the sent_options
1543 * cache. They'd have to be pulled down as they also contain
1544 * different option caches in the same universe...
1545 */
1546 memset(&ia, 0, sizeof(ia));
1547 if (!buffer_allocate(&ia.buffer, 12, MDL)) {
1548 log_error("Unable to allocate memory for IA_NA.");
1549 data_string_forget(&ds, MDL);
1550 return;
1551 }
1552 ia.data = ia.buffer->data;
1553 ia.len = 12;
1554
1555 /*
1556 * A simple IAID is the last 4 bytes
1557 * of the hardware address.
1558 */
1559 if (client->interface->hw_address.hlen > 4) {
1560 idx = client->interface->hw_address.hlen - 4;
1561 len = 4;
1562 } else {
1563 idx = 0;
1564 len = client->interface->hw_address.hlen;
1565 }
1566 memcpy(ia.buffer->data,
1567 client->interface->hw_address.hbuf + idx,
1568 len);
1569 if (i)
1570 ia.buffer->data[3] += i;
1571
1572 t1 = client->config->requested_lease / 2;
1573 t2 = t1 + (t1 / 2);
1574 putULong(ia.buffer->data + 4, t1);
1575 putULong(ia.buffer->data + 8, t2);
1576
1577 log_debug("XMT: X-- IA_NA %s",
1578 print_hex_1(4, ia.buffer->data, 55));
1579 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
1580 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
1581
1582 if ((client->active_lease != NULL) &&
1583 ((old_ia = find_ia(client->active_lease->bindings,
1584 D6O_IA_NA,
1585 (char *)ia.buffer->data)) != NULL)) {
1586 /*
1587 * For each address in the old IA_NA,
1588 * request a binding.
1589 */
1590 memset(&addr, 0, sizeof(addr));
1591 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1592 old_addr = old_addr->next) {
1593 if (old_addr->address.len != 16) {
1594 log_error("Invalid IPv6 address "
1595 "length %d. "
1596 "Ignoring. (%s:%d)",
1597 old_addr->address.len,
1598 MDL);
1599 continue;
1600 }
1601
1602 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
1603 log_error("Unable to allocate memory "
1604 "for IAADDR.");
1605 data_string_forget(&ia, MDL);
1606 data_string_forget(&ds, MDL);
1607 return;
1608 }
1609 addr.data = addr.buffer->data;
1610 addr.len = 24;
1611
1612 memcpy(addr.buffer->data,
1613 old_addr->address.iabuf,
1614 16);
1615
1616 t1 = client->config->requested_lease;
1617 t2 = t1 + (t1 / 2);
1618 putULong(addr.buffer->data + 16, t1);
1619 putULong(addr.buffer->data + 20, t2);
1620
1621 log_debug("XMT: | X-- Request address %s.",
1622 piaddr(old_addr->address));
1623 log_debug("XMT: | | X-- Request "
1624 "preferred in +%u",
1625 (unsigned)t1);
1626 log_debug("XMT: | | X-- Request valid "
1627 "in +%u",
1628 (unsigned)t2);
1629
1630 append_option(&ia, &dhcpv6_universe,
1631 iaaddr_option,
1632 &addr);
1633
1634 data_string_forget(&addr, MDL);
1635 }
1636 }
1637
1638 append_option(&ds, &dhcpv6_universe, ia_na_option, &ia);
1639 data_string_forget(&ia, MDL);
1640 }
1641
1642 /* Append IA_TA. */
1643 for (i = 0; i < wanted_ia_ta; i++) {
1644 /*
1645 * XXX: maybe the IA_TA('s) should be put into the sent_options
1646 * cache. They'd have to be pulled down as they also contain
1647 * different option caches in the same universe...
1648 */
1649 memset(&ia, 0, sizeof(ia));
1650 if (!buffer_allocate(&ia.buffer, 4, MDL)) {
1651 log_error("Unable to allocate memory for IA_TA.");
1652 data_string_forget(&ds, MDL);
1653 return;
1654 }
1655 ia.data = ia.buffer->data;
1656 ia.len = 4;
1657
1658 /*
1659 * A simple IAID is the last 4 bytes
1660 * of the hardware address.
1661 */
1662 if (client->interface->hw_address.hlen > 4) {
1663 idx = client->interface->hw_address.hlen - 4;
1664 len = 4;
1665 } else {
1666 idx = 0;
1667 len = client->interface->hw_address.hlen;
1668 }
1669 memcpy(ia.buffer->data,
1670 client->interface->hw_address.hbuf + idx,
1671 len);
1672 if (i)
1673 ia.buffer->data[3] += i;
1674
1675 log_debug("XMT: X-- IA_TA %s",
1676 print_hex_1(4, ia.buffer->data, 55));
1677
1678 if ((client->active_lease != NULL) &&
1679 ((old_ia = find_ia(client->active_lease->bindings,
1680 D6O_IA_TA,
1681 (char *)ia.buffer->data)) != NULL)) {
1682 /*
1683 * For each address in the old IA_TA,
1684 * request a binding.
1685 */
1686 memset(&addr, 0, sizeof(addr));
1687 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1688 old_addr = old_addr->next) {
1689 if (old_addr->address.len != 16) {
1690 log_error("Invalid IPv6 address "
1691 "length %d. "
1692 "Ignoring. (%s:%d)",
1693 old_addr->address.len,
1694 MDL);
1695 continue;
1696 }
1697
1698 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
1699 log_error("Unable to allocate memory "
1700 "for IAADDR.");
1701 data_string_forget(&ia, MDL);
1702 data_string_forget(&ds, MDL);
1703 return;
1704 }
1705 addr.data = addr.buffer->data;
1706 addr.len = 24;
1707
1708 memcpy(addr.buffer->data,
1709 old_addr->address.iabuf,
1710 16);
1711
1712 t1 = client->config->requested_lease;
1713 t2 = t1 + (t1 / 2);
1714 putULong(addr.buffer->data + 16, t1);
1715 putULong(addr.buffer->data + 20, t2);
1716
1717 log_debug("XMT: | X-- Request address %s.",
1718 piaddr(old_addr->address));
1719 log_debug("XMT: | | X-- Request "
1720 "preferred in +%u",
1721 (unsigned)t1);
1722 log_debug("XMT: | | X-- Request valid "
1723 "in +%u",
1724 (unsigned)t2);
1725
1726 append_option(&ia, &dhcpv6_universe,
1727 iaaddr_option,
1728 &addr);
1729
1730 data_string_forget(&addr, MDL);
1731 }
1732 }
1733
1734 append_option(&ds, &dhcpv6_universe, ia_ta_option, &ia);
1735 data_string_forget(&ia, MDL);
1736 }
1737
1738 /* Append IA_PD. */
1739 for (i = 0; i < wanted_ia_pd; i++) {
1740 /*
1741 * XXX: maybe the IA_PD('s) should be put into the sent_options
1742 * cache. They'd have to be pulled down as they also contain
1743 * different option caches in the same universe...
1744 */
1745 memset(&ia, 0, sizeof(ia));
1746 if (!buffer_allocate(&ia.buffer, 12, MDL)) {
1747 log_error("Unable to allocate memory for IA_PD.");
1748 data_string_forget(&ds, MDL);
1749 return;
1750 }
1751 ia.data = ia.buffer->data;
1752 ia.len = 12;
1753
1754 /*
1755 * A simple IAID is the last 4 bytes
1756 * of the hardware address.
1757 */
1758 if (client->interface->hw_address.hlen > 4) {
1759 idx = client->interface->hw_address.hlen - 4;
1760 len = 4;
1761 } else {
1762 idx = 0;
1763 len = client->interface->hw_address.hlen;
1764 }
1765 memcpy(ia.buffer->data,
1766 client->interface->hw_address.hbuf + idx,
1767 len);
1768 if (i)
1769 ia.buffer->data[3] += i;
1770
1771 t1 = client->config->requested_lease / 2;
1772 t2 = t1 + (t1 / 2);
1773 putULong(ia.buffer->data + 4, t1);
1774 putULong(ia.buffer->data + 8, t2);
1775
1776 log_debug("XMT: X-- IA_PD %s",
1777 print_hex_1(4, ia.buffer->data, 55));
1778 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
1779 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
1780
1781 if ((client->active_lease != NULL) &&
1782 ((old_ia = find_ia(client->active_lease->bindings,
1783 D6O_IA_PD,
1784 (char *)ia.buffer->data)) != NULL)) {
1785 /*
1786 * For each prefix in the old IA_PD,
1787 * request a binding.
1788 */
1789 memset(&addr, 0, sizeof(addr));
1790 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1791 old_addr = old_addr->next) {
1792 if (old_addr->address.len != 16) {
1793 log_error("Invalid IPv6 prefix, "
1794 "Ignoring. (%s:%d)",
1795 MDL);
1796 continue;
1797 }
1798
1799 if (!buffer_allocate(&addr.buffer, 25, MDL)) {
1800 log_error("Unable to allocate memory "
1801 "for IAPREFIX.");
1802 data_string_forget(&ia, MDL);
1803 data_string_forget(&ds, MDL);
1804 return;
1805 }
1806 addr.data = addr.buffer->data;
1807 addr.len = 25;
1808
1809 t1 = client->config->requested_lease;
1810 t2 = t1 + (t1 / 2);
1811 putULong(addr.buffer->data, t1);
1812 putULong(addr.buffer->data + 4, t2);
1813
1814 putUChar(addr.buffer->data + 8,
1815 old_addr->plen);
1816 memcpy(addr.buffer->data + 9,
1817 old_addr->address.iabuf,
1818 16);
1819
1820 log_debug("XMT: | X-- Request prefix %s/%u.",
1821 piaddr(old_addr->address),
1822 (unsigned) old_addr->plen);
1823 log_debug("XMT: | | X-- Request "
1824 "preferred in +%u",
1825 (unsigned)t1);
1826 log_debug("XMT: | | X-- Request valid "
1827 "in +%u",
1828 (unsigned)t2);
1829
1830 append_option(&ia, &dhcpv6_universe,
1831 iaprefix_option,
1832 &addr);
1833
1834 data_string_forget(&addr, MDL);
1835 }
1836 }
1837
1838 append_option(&ds, &dhcpv6_universe, ia_pd_option, &ia);
1839 data_string_forget(&ia, MDL);
1840 }
1841
1842 /* Transmit and wait. */
1843
1844 log_info("XMT: Solicit on %s, interval %ld0ms.",
1845 client->name ? client->name : client->interface->name,
1846 (long int)client->RT);
1847
1848 send_ret = send_packet6(client->interface,
1849 ds.data, ds.len, &DHCPv6DestAddr);
1850 if (send_ret != ds.len) {
1851 log_error("dhc6: send_packet6() sent %d of %d bytes",
1852 send_ret, ds.len);
1853 }
1854
1855 data_string_forget(&ds, MDL);
1856
1857 /* Wait RT */
1858 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
1859 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
1860 if (tv.tv_usec >= 1000000) {
1861 tv.tv_sec += 1;
1862 tv.tv_usec -= 1000000;
1863 }
1864 add_timeout(&tv, do_init6, client, NULL, NULL);
1865
1866 dhc6_retrans_advance(client);
1867 }
1868
1869 /* do_info_request6() marshals and transmits an information-request. */
1870 void
do_info_request6(void * input)1871 do_info_request6(void *input)
1872 {
1873 struct client_state *client;
1874 struct data_string ds;
1875 struct timeval tv;
1876 int send_ret;
1877
1878 client = input;
1879
1880 switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
1881 "Info-Request", NULL, &ds)) {
1882 case CHK_TIM_MRC_EXCEEDED:
1883 case CHK_TIM_ALLOC_FAILURE:
1884 return;
1885 case CHK_TIM_MRD_EXCEEDED:
1886 exit(2);
1887 case CHK_TIM_SUCCESS:
1888 break;
1889 }
1890
1891 /* Fetch any configured 'sent' options (includes DUID) in wire format.
1892 */
1893 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
1894 NULL, client->sent_options, &global_scope,
1895 &dhcpv6_universe);
1896
1897 /* Transmit and wait. */
1898
1899 log_info("XMT: Info-Request on %s, interval %ld0ms.",
1900 client->name ? client->name : client->interface->name,
1901 (long int)client->RT);
1902
1903 send_ret = send_packet6(client->interface,
1904 ds.data, ds.len, &DHCPv6DestAddr);
1905 if (send_ret != ds.len) {
1906 log_error("dhc6: send_packet6() sent %d of %d bytes",
1907 send_ret, ds.len);
1908 }
1909
1910 data_string_forget(&ds, MDL);
1911
1912 /* Wait RT */
1913 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
1914 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
1915 if (tv.tv_usec >= 1000000) {
1916 tv.tv_sec += 1;
1917 tv.tv_usec -= 1000000;
1918 }
1919 add_timeout(&tv, do_info_request6, client, NULL, NULL);
1920
1921 dhc6_retrans_advance(client);
1922 }
1923
1924 /* do_confirm6() creates a Confirm packet and transmits it. This function
1925 * is called on every timeout to (re)transmit.
1926 */
1927 void
do_confirm6(void * input)1928 do_confirm6(void *input)
1929 {
1930 struct client_state *client;
1931 struct data_string ds;
1932 int send_ret;
1933 struct timeval tv;
1934
1935 client = input;
1936
1937 if (client->active_lease == NULL)
1938 log_fatal("Impossible condition at %s:%d.", MDL);
1939
1940 /* In section 17.1.3, it is said:
1941 *
1942 * If the client receives no responses before the message
1943 * transmission process terminates, as described in section 14,
1944 * the client SHOULD continue to use any IP addresses, using the
1945 * last known lifetimes for those addresses, and SHOULD continue
1946 * to use any other previously obtained configuration parameters.
1947 *
1948 * So if confirm times out, we go active.
1949 *
1950 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
1951 * stick there until we get a reply?
1952 */
1953
1954 switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
1955 client->active_lease, &ds)) {
1956 case CHK_TIM_MRC_EXCEEDED:
1957 case CHK_TIM_MRD_EXCEEDED:
1958 start_bound(client);
1959 return;
1960 case CHK_TIM_ALLOC_FAILURE:
1961 return;
1962 case CHK_TIM_SUCCESS:
1963 break;
1964 }
1965
1966 /* Fetch any configured 'sent' options (includes DUID') in wire format.
1967 */
1968 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
1969 client->sent_options, &global_scope,
1970 &dhcpv6_universe);
1971
1972 /* Append IA's. */
1973 if (wanted_ia_na &&
1974 dhc6_add_ia_na(client, &ds, client->active_lease,
1975 DHCPV6_CONFIRM) != ISC_R_SUCCESS) {
1976 data_string_forget(&ds, MDL);
1977 return;
1978 }
1979 if (wanted_ia_ta &&
1980 dhc6_add_ia_ta(client, &ds, client->active_lease,
1981 DHCPV6_CONFIRM) != ISC_R_SUCCESS) {
1982 data_string_forget(&ds, MDL);
1983 return;
1984 }
1985
1986 /* Transmit and wait. */
1987
1988 log_info("XMT: Confirm on %s, interval %ld0ms.",
1989 client->name ? client->name : client->interface->name,
1990 (long int)client->RT);
1991
1992 send_ret = send_packet6(client->interface, ds.data, ds.len,
1993 &DHCPv6DestAddr);
1994 if (send_ret != ds.len) {
1995 log_error("dhc6: sendpacket6() sent %d of %d bytes",
1996 send_ret, ds.len);
1997 }
1998
1999 data_string_forget(&ds, MDL);
2000
2001 /* Wait RT */
2002 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2003 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2004 if (tv.tv_usec >= 1000000) {
2005 tv.tv_sec += 1;
2006 tv.tv_usec -= 1000000;
2007 }
2008 add_timeout(&tv, do_confirm6, client, NULL, NULL);
2009
2010 dhc6_retrans_advance(client);
2011 }
2012
2013 /*
2014 * Release addresses.
2015 */
2016 void
start_release6(struct client_state * client)2017 start_release6(struct client_state *client)
2018 {
2019 /* Cancel any pending transmissions */
2020 cancel_timeout(do_confirm6, client);
2021 cancel_timeout(do_select6, client);
2022 cancel_timeout(do_refresh6, client);
2023 cancel_timeout(do_release6, client);
2024 client->state = S_STOPPED;
2025
2026 /*
2027 * It is written: "The client MUST NOT use any of the addresses it
2028 * is releasing as the source address in the Release message or in
2029 * any subsequently transmitted message." So unconfigure now.
2030 */
2031 unconfigure6(client, "RELEASE6");
2032
2033 /* Note this in the lease file. */
2034 if (client->active_lease == NULL)
2035 return;
2036 client->active_lease->released = ISC_TRUE;
2037 write_client6_lease(client, client->active_lease, 0, 1);
2038
2039 /* Set timers per RFC3315 section 18.1.6. */
2040 client->IRT = REL_TIMEOUT * 100;
2041 client->MRT = 0;
2042 client->MRC = REL_MAX_RC;
2043 client->MRD = 0;
2044
2045 dhc6_retrans_init(client);
2046 client->v6_handler = reply_handler;
2047
2048 do_release6(client);
2049 }
2050 /*
2051 * do_release6() creates a Release packet and transmits it.
2052 */
2053 static void
do_release6(void * input)2054 do_release6(void *input)
2055 {
2056 struct client_state *client;
2057 struct data_string ds;
2058 int send_ret;
2059 struct timeval tv;
2060
2061 client = input;
2062
2063 if ((client->active_lease == NULL) || !active_prefix(client))
2064 return;
2065
2066 switch(check_timing6(client, DHCPV6_RELEASE, "Release",
2067 client->active_lease, &ds)) {
2068 case CHK_TIM_MRC_EXCEEDED:
2069 case CHK_TIM_ALLOC_FAILURE:
2070 case CHK_TIM_MRD_EXCEEDED:
2071 goto release_done;
2072 case CHK_TIM_SUCCESS:
2073 break;
2074 }
2075
2076 /*
2077 * Don't use unicast as we don't know if we still have an
2078 * available address with enough scope.
2079 */
2080
2081 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
2082 client->sent_options, &global_scope,
2083 &dhcpv6_universe);
2084
2085 /* Append IA's (but don't release temporary addresses). */
2086 if (wanted_ia_na &&
2087 dhc6_add_ia_na(client, &ds, client->active_lease,
2088 DHCPV6_RELEASE) != ISC_R_SUCCESS) {
2089 data_string_forget(&ds, MDL);
2090 goto release_done;
2091 }
2092 if (wanted_ia_pd &&
2093 dhc6_add_ia_pd(client, &ds, client->active_lease,
2094 DHCPV6_RELEASE) != ISC_R_SUCCESS) {
2095 data_string_forget(&ds, MDL);
2096 goto release_done;
2097 }
2098
2099 /* Transmit and wait. */
2100 log_info("XMT: Release on %s, interval %ld0ms.",
2101 client->name ? client->name : client->interface->name,
2102 (long int)client->RT);
2103
2104 send_ret = send_packet6(client->interface, ds.data, ds.len,
2105 &DHCPv6DestAddr);
2106 if (send_ret != ds.len) {
2107 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2108 send_ret, ds.len);
2109 }
2110
2111 data_string_forget(&ds, MDL);
2112
2113 /* Wait RT */
2114 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2115 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2116 if (tv.tv_usec >= 1000000) {
2117 tv.tv_sec += 1;
2118 tv.tv_usec -= 1000000;
2119 }
2120 add_timeout(&tv, do_release6, client, NULL, NULL);
2121 dhc6_retrans_advance(client);
2122 return;
2123
2124 release_done:
2125 dhc6_lease_destroy(&client->active_lease, MDL);
2126 client->active_lease = NULL;
2127 if (stopping_finished())
2128 exit(0);
2129 }
2130
2131 /* status_log() just puts a status code into displayable form and logs it
2132 * to info level.
2133 */
2134 static void
status_log(int code,const char * scope,const char * additional,int len)2135 status_log(int code, const char *scope, const char *additional, int len)
2136 {
2137 const char *msg = NULL;
2138
2139 switch(code) {
2140 case STATUS_Success:
2141 msg = "Success";
2142 break;
2143
2144 case STATUS_UnspecFail:
2145 msg = "UnspecFail";
2146 break;
2147
2148 case STATUS_NoAddrsAvail:
2149 msg = "NoAddrsAvail";
2150 break;
2151
2152 case STATUS_NoBinding:
2153 msg = "NoBinding";
2154 break;
2155
2156 case STATUS_NotOnLink:
2157 msg = "NotOnLink";
2158 break;
2159
2160 case STATUS_UseMulticast:
2161 msg = "UseMulticast";
2162 break;
2163
2164 case STATUS_NoPrefixAvail:
2165 msg = "NoPrefixAvail";
2166 break;
2167
2168 default:
2169 msg = "UNKNOWN";
2170 break;
2171 }
2172
2173 if (len > 0)
2174 log_info("%s status code %s: %s", scope, msg,
2175 print_hex_1(len,
2176 (const unsigned char *)additional, 50));
2177 else
2178 log_info("%s status code %s.", scope, msg);
2179 }
2180
2181 /* Acquire a status code.
2182 */
2183 static isc_result_t
dhc6_get_status_code(struct option_state * options,unsigned * code,struct data_string * msg)2184 dhc6_get_status_code(struct option_state *options, unsigned *code,
2185 struct data_string *msg)
2186 {
2187 struct option_cache *oc;
2188 struct data_string ds;
2189 isc_result_t rval = ISC_R_SUCCESS;
2190
2191 if ((options == NULL) || (code == NULL))
2192 return DHCP_R_INVALIDARG;
2193
2194 if ((msg != NULL) && (msg->len != 0))
2195 return DHCP_R_INVALIDARG;
2196
2197 memset(&ds, 0, sizeof(ds));
2198
2199 /* Assume success if there is no option. */
2200 *code = STATUS_Success;
2201
2202 oc = lookup_option(&dhcpv6_universe, options, D6O_STATUS_CODE);
2203 if ((oc != NULL) &&
2204 evaluate_option_cache(&ds, NULL, NULL, NULL, options,
2205 NULL, &global_scope, oc, MDL)) {
2206 if (ds.len < 2) {
2207 log_error("Invalid status code length %d.", ds.len);
2208 rval = DHCP_R_FORMERR;
2209 } else
2210 *code = getUShort(ds.data);
2211
2212 if ((msg != NULL) && (ds.len > 2)) {
2213 data_string_copy(msg, &ds, MDL);
2214 msg->data += 2;
2215 msg->len -= 2;
2216 }
2217
2218 data_string_forget(&ds, MDL);
2219 return rval;
2220 }
2221
2222 return ISC_R_NOTFOUND;
2223 }
2224
2225 /* Look at status codes in an advertise, and reform the return value.
2226 */
2227 static isc_result_t
dhc6_check_status(isc_result_t rval,struct option_state * options,const char * scope,unsigned * code)2228 dhc6_check_status(isc_result_t rval, struct option_state *options,
2229 const char *scope, unsigned *code)
2230 {
2231 struct data_string msg;
2232 isc_result_t status;
2233
2234 if ((scope == NULL) || (code == NULL))
2235 return DHCP_R_INVALIDARG;
2236
2237 /* If we don't find a code, we assume success. */
2238 *code = STATUS_Success;
2239
2240 /* If there is no options cache, then there is no code. */
2241 if (options != NULL) {
2242 memset(&msg, 0, sizeof(msg));
2243 status = dhc6_get_status_code(options, code, &msg);
2244
2245 if (status == ISC_R_SUCCESS) {
2246 status_log(*code, scope, (char *)msg.data, msg.len);
2247 data_string_forget(&msg, MDL);
2248
2249 if (*code != STATUS_Success)
2250 rval = ISC_R_FAILURE;
2251
2252 } else if (status != ISC_R_NOTFOUND)
2253 rval = status;
2254 }
2255
2256 return rval;
2257 }
2258
2259 /* Look in the packet, any IA's, and any IAADDR's within those IA's to find
2260 * status code options that are not SUCCESS.
2261 */
2262 static isc_result_t
dhc6_check_advertise(struct dhc6_lease * lease)2263 dhc6_check_advertise(struct dhc6_lease *lease)
2264 {
2265 struct dhc6_ia *ia;
2266 struct dhc6_addr *addr;
2267 isc_result_t rval = ISC_R_SUCCESS;
2268 int have_addrs = ISC_FALSE;
2269 unsigned code;
2270 const char *scope;
2271
2272 rval = dhc6_check_status(rval, lease->options, "message", &code);
2273
2274 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
2275 switch (ia->ia_type) {
2276 case D6O_IA_NA:
2277 scope = "IA_NA";
2278 break;
2279 case D6O_IA_TA:
2280 scope = "IA_TA";
2281 break;
2282 case D6O_IA_PD:
2283 scope = "IA_PD";
2284 break;
2285 default:
2286 log_error("dhc6_check_advertise: no type.");
2287 return ISC_R_FAILURE;
2288 }
2289 rval = dhc6_check_status(rval, ia->options, scope, &code);
2290
2291 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
2292 if (ia->ia_type != D6O_IA_PD)
2293 scope = "IAADDR";
2294 else
2295 scope = "IAPREFIX";
2296 rval = dhc6_check_status(rval, addr->options,
2297 scope, &code);
2298 have_addrs = ISC_TRUE;
2299 }
2300 }
2301
2302 if (have_addrs != ISC_TRUE)
2303 rval = ISC_R_ADDRNOTAVAIL;
2304
2305 return rval;
2306 }
2307
2308 /* status code <-> action matrix for the client in INIT state
2309 * (rapid/commit). Returns always false as no action is defined.
2310 */
2311 static isc_boolean_t
dhc6_init_action(struct client_state * client,isc_result_t * rvalp,unsigned code)2312 dhc6_init_action(struct client_state *client, isc_result_t *rvalp,
2313 unsigned code)
2314 {
2315 if (rvalp == NULL)
2316 log_fatal("Impossible condition at %s:%d.", MDL);
2317
2318 if (client == NULL) {
2319 *rvalp = DHCP_R_INVALIDARG;
2320 return ISC_FALSE;
2321 }
2322
2323 if (*rvalp == ISC_R_SUCCESS)
2324 return ISC_FALSE;
2325
2326 /* No possible action in any case... */
2327 return ISC_FALSE;
2328 }
2329
2330 /* status code <-> action matrix for the client in SELECT state
2331 * (request/reply). Returns true if action was taken (and the
2332 * packet should be ignored), or false if no action was taken.
2333 */
2334 static isc_boolean_t
dhc6_select_action(struct client_state * client,isc_result_t * rvalp,unsigned code)2335 dhc6_select_action(struct client_state *client, isc_result_t *rvalp,
2336 unsigned code)
2337 {
2338 struct dhc6_lease *lease;
2339 isc_result_t rval;
2340
2341 if (rvalp == NULL)
2342 log_fatal("Impossible condition at %s:%d.", MDL);
2343
2344 if (client == NULL) {
2345 *rvalp = DHCP_R_INVALIDARG;
2346 return ISC_FALSE;
2347 }
2348 rval = *rvalp;
2349
2350 if (rval == ISC_R_SUCCESS)
2351 return ISC_FALSE;
2352
2353 switch (code) {
2354 /* We may have an earlier failure status code (so no
2355 * success rval), and a success code now. This
2356 * doesn't upgrade the rval to success, but it does
2357 * mean we take no action here.
2358 */
2359 case STATUS_Success:
2360 /* Gimpy server, or possibly an attacker. */
2361 case STATUS_NoBinding:
2362 case STATUS_UseMulticast:
2363 /* Take no action. */
2364 return ISC_FALSE;
2365
2366 /* If the server can't deal with us, either try the
2367 * next advertised server, or continue retrying if there
2368 * weren't any.
2369 */
2370 default:
2371 case STATUS_UnspecFail:
2372 if (client->advertised_leases != NULL) {
2373 dhc6_lease_destroy(&client->selected_lease, MDL);
2374 client->selected_lease = NULL;
2375
2376 start_selecting6(client);
2377
2378 break;
2379 } else /* Take no action - continue to retry. */
2380 return ISC_FALSE;
2381
2382 /* If the server has no addresses, try other servers if
2383 * we got some, otherwise go to INIT to hope for more
2384 * servers.
2385 */
2386 case STATUS_NoAddrsAvail:
2387 case STATUS_NoPrefixAvail:
2388 if (client->state == S_REBOOTING)
2389 return ISC_FALSE;
2390
2391 if (client->selected_lease == NULL)
2392 log_fatal("Impossible case at %s:%d.", MDL);
2393
2394 dhc6_lease_destroy(&client->selected_lease, MDL);
2395 client->selected_lease = NULL;
2396
2397 if (client->advertised_leases != NULL)
2398 start_selecting6(client);
2399 else
2400 start_init6(client);
2401
2402 break;
2403
2404 /* If we got a NotOnLink from a Confirm, then we're not
2405 * on link. Kill the old-active binding and start over.
2406 *
2407 * If we got a NotOnLink from our Request, something weird
2408 * happened. Start over from scratch anyway.
2409 */
2410 case STATUS_NotOnLink:
2411 if (client->state == S_REBOOTING) {
2412 if (client->active_lease == NULL)
2413 log_fatal("Impossible case at %s:%d.", MDL);
2414
2415 dhc6_lease_destroy(&client->active_lease, MDL);
2416 } else {
2417 if (client->selected_lease == NULL)
2418 log_fatal("Impossible case at %s:%d.", MDL);
2419
2420 dhc6_lease_destroy(&client->selected_lease, MDL);
2421 client->selected_lease = NULL;
2422
2423 while (client->advertised_leases != NULL) {
2424 lease = client->advertised_leases;
2425 client->advertised_leases = lease->next;
2426
2427 dhc6_lease_destroy(&lease, MDL);
2428 }
2429 }
2430
2431 start_init6(client);
2432 break;
2433 }
2434
2435 return ISC_TRUE;
2436 }
2437
2438 static void
dhc6_withdraw_lease(struct client_state * client)2439 dhc6_withdraw_lease(struct client_state *client)
2440 {
2441 struct dhc6_ia *ia;
2442 struct dhc6_addr *addr;
2443
2444 if ((client == NULL) || (client->active_lease == NULL))
2445 return;
2446
2447 for (ia = client->active_lease->bindings ; ia != NULL ;
2448 ia = ia->next) {
2449 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
2450 addr->max_life = addr->preferred_life = 0;
2451 }
2452 }
2453
2454 /* Perform expiry. */
2455 do_expire(client);
2456 }
2457
2458 /* status code <-> action matrix for the client in BOUND state
2459 * (request/reply). Returns true if action was taken (and the
2460 * packet should be ignored), or false if no action was taken.
2461 */
2462 static isc_boolean_t
dhc6_reply_action(struct client_state * client,isc_result_t * rvalp,unsigned code)2463 dhc6_reply_action(struct client_state *client, isc_result_t *rvalp,
2464 unsigned code)
2465 {
2466 isc_result_t rval;
2467
2468 if (rvalp == NULL)
2469 log_fatal("Impossible condition at %s:%d.", MDL);
2470
2471 if (client == NULL) {
2472 *rvalp = DHCP_R_INVALIDARG;
2473 return ISC_FALSE;
2474 }
2475 rval = *rvalp;
2476
2477 if (rval == ISC_R_SUCCESS)
2478 return ISC_FALSE;
2479
2480 switch (code) {
2481 /* It's possible an earlier status code set rval to a failure
2482 * code, and we've encountered a later success.
2483 */
2484 case STATUS_Success:
2485 /* In "refreshes" (where we get replies), we probably
2486 * still have a valid lease. So "take no action" and
2487 * the upper levels will keep retrying until the lease
2488 * expires (or we rebind).
2489 */
2490 case STATUS_UnspecFail:
2491 /* For unknown codes...it's a soft (retryable) error. */
2492 default:
2493 return ISC_FALSE;
2494
2495 /* The server is telling us to use a multicast address, so
2496 * we have to delete the unicast option from the active
2497 * lease, then allow retransmission to occur normally.
2498 * (XXX: It might be preferable in this case to retransmit
2499 * sooner than the current interval, but for now we don't.)
2500 */
2501 case STATUS_UseMulticast:
2502 if (client->active_lease != NULL)
2503 delete_option(&dhcp_universe,
2504 client->active_lease->options,
2505 D6O_UNICAST);
2506 return ISC_FALSE;
2507
2508 /* "When the client receives a NotOnLink status from the
2509 * server in response to a Request, the client can either
2510 * re-issue the Request without specifying any addresses
2511 * or restart the DHCP server discovery process."
2512 *
2513 * This is strange. If competing server evaluation is
2514 * useful (and therefore in the protocol), then why would
2515 * a client's first reaction be to request from the same
2516 * server on a different link? Surely you'd want to
2517 * re-evaluate your server selection.
2518 *
2519 * Well, I guess that's the answer.
2520 */
2521 case STATUS_NotOnLink:
2522 /* In this case, we need to rescind all current active
2523 * bindings (just 'expire' them all normally, if early).
2524 * They're no use to us on the wrong link. Then head back
2525 * to init, redo server selection and get new addresses.
2526 */
2527 dhc6_withdraw_lease(client);
2528 break;
2529
2530 /* "If the status code is NoAddrsAvail, the client has
2531 * received no usable addresses in the IA and may choose
2532 * to try obtaining addresses for the IA from another
2533 * server."
2534 */
2535 case STATUS_NoAddrsAvail:
2536 case STATUS_NoPrefixAvail:
2537 /* Head back to init, keeping any active bindings (!). */
2538 start_init6(client);
2539 break;
2540
2541 /* - sends a Request message if the IA contained a Status
2542 * Code option with the NoBinding status (and does not
2543 * send any additional Renew/Rebind messages)
2544 */
2545 case STATUS_NoBinding:
2546 if (client->advertised_leases != NULL)
2547 log_fatal("Impossible condition at %s:%d.", MDL);
2548
2549 client->advertised_leases =
2550 dhc6_dup_lease(client->active_lease, MDL);
2551 start_selecting6(client);
2552 break;
2553 }
2554
2555 return ISC_TRUE;
2556 }
2557
2558 /* status code <-> action matrix for the client in STOPPED state
2559 * (release/decline). Returns true if action was taken (and the
2560 * packet should be ignored), or false if no action was taken.
2561 * NoBinding is translated into Success.
2562 */
2563 static isc_boolean_t
dhc6_stop_action(struct client_state * client,isc_result_t * rvalp,unsigned code)2564 dhc6_stop_action(struct client_state *client, isc_result_t *rvalp,
2565 unsigned code)
2566 {
2567 isc_result_t rval;
2568
2569 if (rvalp == NULL)
2570 log_fatal("Impossible condition at %s:%d.", MDL);
2571
2572 if (client == NULL) {
2573 *rvalp = DHCP_R_INVALIDARG;
2574 return ISC_FALSE;
2575 }
2576 rval = *rvalp;
2577
2578 if (rval == ISC_R_SUCCESS)
2579 return ISC_FALSE;
2580
2581 switch (code) {
2582 /* It's possible an earlier status code set rval to a failure
2583 * code, and we've encountered a later success.
2584 */
2585 case STATUS_Success:
2586 /* For unknown codes...it's a soft (retryable) error. */
2587 case STATUS_UnspecFail:
2588 default:
2589 return ISC_FALSE;
2590
2591 /* NoBinding is not an error */
2592 case STATUS_NoBinding:
2593 if (rval == ISC_R_FAILURE)
2594 *rvalp = ISC_R_SUCCESS;
2595 return ISC_FALSE;
2596
2597 /* Should not happen */
2598 case STATUS_NoAddrsAvail:
2599 case STATUS_NoPrefixAvail:
2600 break;
2601
2602 /* Give up on it */
2603 case STATUS_NotOnLink:
2604 break;
2605
2606 /* The server is telling us to use a multicast address, so
2607 * we have to delete the unicast option from the active
2608 * lease, then allow retransmission to occur normally.
2609 * (XXX: It might be preferable in this case to retransmit
2610 * sooner than the current interval, but for now we don't.)
2611 */
2612 case STATUS_UseMulticast:
2613 if (client->active_lease != NULL)
2614 delete_option(&dhcp_universe,
2615 client->active_lease->options,
2616 D6O_UNICAST);
2617 return ISC_FALSE;
2618 }
2619
2620 return ISC_TRUE;
2621 }
2622
2623 /* Look at a new and old lease, and make sure the new information is not
2624 * losing us any state.
2625 */
2626 static isc_result_t
dhc6_check_reply(struct client_state * client,struct dhc6_lease * new)2627 dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
2628 {
2629 isc_boolean_t (*action)(struct client_state *,
2630 isc_result_t *, unsigned);
2631 struct dhc6_ia *ia;
2632 struct dhc6_addr *addr;
2633 isc_result_t rval = ISC_R_SUCCESS;
2634 unsigned code;
2635 const char *scope;
2636 int nscore, sscore;
2637
2638 if ((client == NULL) || (new == NULL))
2639 return DHCP_R_INVALIDARG;
2640
2641 switch (client->state) {
2642 case S_INIT:
2643 action = dhc6_init_action;
2644 break;
2645
2646 case S_SELECTING:
2647 case S_REBOOTING:
2648 action = dhc6_select_action;
2649 break;
2650
2651 case S_RENEWING:
2652 case S_REBINDING:
2653 action = dhc6_reply_action;
2654 break;
2655
2656 case S_STOPPED:
2657 action = dhc6_stop_action;
2658 break;
2659
2660 default:
2661 log_fatal("Impossible condition at %s:%d.", MDL);
2662 return ISC_R_CANCELED;
2663 }
2664
2665 /* If there is a code to extract, and if there is some
2666 * action to take based on that code, then take the action
2667 * and do not continue.
2668 */
2669 rval = dhc6_check_status(rval, new->options, "message", &code);
2670 if (action(client, &rval, code))
2671 return ISC_R_CANCELED;
2672
2673 for (ia = new->bindings ; ia != NULL ; ia = ia->next) {
2674 switch (ia->ia_type) {
2675 case D6O_IA_NA:
2676 scope = "IA_NA";
2677 break;
2678 case D6O_IA_TA:
2679 scope = "IA_TA";
2680 break;
2681 case D6O_IA_PD:
2682 scope = "IA_PD";
2683 break;
2684 default:
2685 log_error("dhc6_check_reply: no type.");
2686 return DHCP_R_INVALIDARG;
2687 }
2688 rval = dhc6_check_status(rval, ia->options,
2689 scope, &code);
2690 if (action(client, &rval, code))
2691 return ISC_R_CANCELED;
2692
2693 for (addr = ia->addrs ; addr != NULL ;
2694 addr = addr->next) {
2695 if (ia->ia_type != D6O_IA_PD)
2696 scope = "IAADDR";
2697 else
2698 scope = "IAPREFIX";
2699 rval = dhc6_check_status(rval, addr->options,
2700 scope, &code);
2701 if (action(client, &rval, code))
2702 return ISC_R_CANCELED;
2703 }
2704 }
2705
2706 /* A Confirm->Reply is unsuitable for comparison to the old lease. */
2707 if (client->state == S_REBOOTING)
2708 return rval;
2709
2710 /* No old lease in rapid-commit. */
2711 if (client->state == S_INIT)
2712 return rval;
2713
2714 switch (client->state) {
2715 case S_SELECTING:
2716 /* Compare the new lease with the selected lease to make
2717 * sure there is no risky business.
2718 */
2719 nscore = dhc6_score_lease(client, new);
2720 sscore = dhc6_score_lease(client, client->selected_lease);
2721 if ((client->advertised_leases != NULL) &&
2722 (nscore < (sscore / 2))) {
2723 /* XXX: An attacker might reply this way to make
2724 * XXX: sure we latch onto their configuration.
2725 * XXX: We might want to ignore the packet and
2726 * XXX: schedule re-selection at the next timeout?
2727 */
2728 log_error("PRC: BAIT AND SWITCH detected. Score of "
2729 "supplied lease (%d) is substantially "
2730 "smaller than the advertised score (%d). "
2731 "Trying other servers.",
2732 nscore, sscore);
2733
2734 dhc6_lease_destroy(&client->selected_lease, MDL);
2735 client->selected_lease = NULL;
2736
2737 start_selecting6(client);
2738
2739 return ISC_R_CANCELED;
2740 }
2741 break;
2742
2743 case S_RENEWING:
2744 case S_REBINDING:
2745 /* This leaves one RFC3315 status check unimplemented:
2746 *
2747 * - sends a Renew/Rebind if the IA is not in the Reply
2748 * message
2749 *
2750 * We rely on the scheduling system to note that the IA has
2751 * not left Renewal/Rebinding/whatever since it still carries
2752 * old times from the last successful binding. So this is
2753 * implemented actually, just not explicitly.
2754 */
2755 break;
2756
2757 case S_STOPPED:
2758 /* Nothing critical to do at this stage. */
2759 break;
2760
2761 default:
2762 log_fatal("REALLY impossible condition at %s:%d.", MDL);
2763 return ISC_R_CANCELED;
2764 }
2765
2766 return rval;
2767 }
2768
2769 /* While in init state, we only collect advertisements. If there happens
2770 * to be an advertisement with a preference option of 255, that's an
2771 * automatic exit. Otherwise, we collect advertisements until our timeout
2772 * expires (client->RT).
2773 */
2774 void
init_handler(struct packet * packet,struct client_state * client)2775 init_handler(struct packet *packet, struct client_state *client)
2776 {
2777 struct dhc6_lease *lease;
2778
2779 /* In INIT state, we send solicits, we only expect to get
2780 * advertises (rapid commit has its own handler).
2781 */
2782 if (packet->dhcpv6_msg_type != DHCPV6_ADVERTISE)
2783 return;
2784
2785 /* RFC3315 section 15.3 validation (same as 15.10 since we
2786 * always include a client id).
2787 */
2788 if (!valid_reply(packet, client)) {
2789 log_error("Invalid Advertise - rejecting.");
2790 return;
2791 }
2792
2793 lease = dhc6_leaseify(packet);
2794
2795 if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) {
2796 log_debug("PRC: Lease failed to satisfy.");
2797 dhc6_lease_destroy(&lease, MDL);
2798 return;
2799 }
2800
2801 insert_lease(&client->advertised_leases, lease);
2802
2803 /* According to RFC3315 section 17.1.2, the client MUST wait for
2804 * the first RT before selecting a lease. But on the 400th RT,
2805 * we dont' want to wait the full timeout if we finally get an
2806 * advertise. We could probably wait a second, but ohwell,
2807 * RFC3315 doesn't say so.
2808 *
2809 * If the lease is highest possible preference, 255, RFC3315 claims
2810 * we should continue immediately even on the first RT. We probably
2811 * should not if the advertise contains less than one IA and address.
2812 */
2813 if ((client->txcount > 1) ||
2814 ((lease->pref == 255) &&
2815 (dhc6_score_lease(client, lease) > 150))) {
2816 log_debug("RCV: Advertisement immediately selected.");
2817 cancel_timeout(do_init6, client);
2818 start_selecting6(client);
2819 } else
2820 log_debug("RCV: Advertisement recorded.");
2821 }
2822
2823 /* info_request_handler() accepts a Reply to an Info-request.
2824 */
2825 void
info_request_handler(struct packet * packet,struct client_state * client)2826 info_request_handler(struct packet *packet, struct client_state *client)
2827 {
2828 isc_result_t check_status;
2829 unsigned code;
2830
2831 if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
2832 return;
2833
2834 /* RFC3315 section 15.10 validation (same as 15.3 since we
2835 * always include a client id).
2836 */
2837 if (!valid_reply(packet, client)) {
2838 log_error("Invalid Reply - rejecting.");
2839 return;
2840 }
2841
2842 check_status = dhc6_check_status(ISC_R_SUCCESS, packet->options,
2843 "message", &code);
2844 if (check_status != ISC_R_SUCCESS) {
2845 /* If no action was taken, but there is an error, then
2846 * we wait for a retransmission.
2847 */
2848 if (check_status != ISC_R_CANCELED)
2849 return;
2850 }
2851
2852 /* We're done retransmitting at this point. */
2853 cancel_timeout(do_info_request6, client);
2854
2855 /* Action was taken, so now that we've torn down our scheduled
2856 * retransmissions, return.
2857 */
2858 if (check_status == ISC_R_CANCELED)
2859 return;
2860
2861 /* Cleanup if a previous attempt to go bound failed. */
2862 if (client->old_lease != NULL) {
2863 dhc6_lease_destroy(&client->old_lease, MDL);
2864 client->old_lease = NULL;
2865 }
2866
2867 /* Cache options in the active_lease. */
2868 if (client->active_lease != NULL)
2869 client->old_lease = client->active_lease;
2870 client->active_lease = dmalloc(sizeof(struct dhc6_lease), MDL);
2871 if (client->active_lease == NULL)
2872 log_fatal("Out of memory for v6 lease structure.");
2873 option_state_reference(&client->active_lease->options,
2874 packet->options, MDL);
2875
2876 start_informed(client);
2877 }
2878
2879 /* Specific version of init_handler() for rapid-commit.
2880 */
2881 void
rapid_commit_handler(struct packet * packet,struct client_state * client)2882 rapid_commit_handler(struct packet *packet, struct client_state *client)
2883 {
2884 struct dhc6_lease *lease;
2885 isc_result_t check_status;
2886
2887 /* On ADVERTISE just fall back to the init_handler().
2888 */
2889 if (packet->dhcpv6_msg_type == DHCPV6_ADVERTISE) {
2890 init_handler(packet, client);
2891 return;
2892 } else if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
2893 return;
2894
2895 /* RFC3315 section 15.10 validation (same as 15.3 since we
2896 * always include a client id).
2897 */
2898 if (!valid_reply(packet, client)) {
2899 log_error("Invalid Reply - rejecting.");
2900 return;
2901 }
2902
2903 /* A rapid-commit option MUST be here. */
2904 if (lookup_option(&dhcpv6_universe, packet->options,
2905 D6O_RAPID_COMMIT) == 0) {
2906 log_error("Reply without Rapid-Commit - rejecting.");
2907 return;
2908 }
2909
2910 lease = dhc6_leaseify(packet);
2911
2912 /* This is an out of memory condition...hopefully a temporary
2913 * problem. Returning now makes us try to retransmit later.
2914 */
2915 if (lease == NULL)
2916 return;
2917
2918 check_status = dhc6_check_reply(client, lease);
2919 if (check_status != ISC_R_SUCCESS) {
2920 dhc6_lease_destroy(&lease, MDL);
2921 return;
2922 }
2923
2924 /* Jump to the selecting state. */
2925 cancel_timeout(do_init6, client);
2926 client->state = S_SELECTING;
2927
2928 /* Merge any bindings in the active lease (if there is one) into
2929 * the new active lease.
2930 */
2931 dhc6_merge_lease(client->active_lease, lease);
2932
2933 /* Cleanup if a previous attempt to go bound failed. */
2934 if (client->old_lease != NULL) {
2935 dhc6_lease_destroy(&client->old_lease, MDL);
2936 client->old_lease = NULL;
2937 }
2938
2939 /* Make this lease active and BIND to it. */
2940 if (client->active_lease != NULL)
2941 client->old_lease = client->active_lease;
2942 client->active_lease = lease;
2943
2944 /* We're done with the ADVERTISEd leases, if any. */
2945 while(client->advertised_leases != NULL) {
2946 lease = client->advertised_leases;
2947 client->advertised_leases = lease->next;
2948
2949 dhc6_lease_destroy(&lease, MDL);
2950 }
2951
2952 start_bound(client);
2953 }
2954
2955 /* Find the 'best' lease in the cache of advertised leases (usually). From
2956 * RFC3315 Section 17.1.3:
2957 *
2958 * Upon receipt of one or more valid Advertise messages, the client
2959 * selects one or more Advertise messages based upon the following
2960 * criteria.
2961 *
2962 * - Those Advertise messages with the highest server preference value
2963 * are preferred over all other Advertise messages.
2964 *
2965 * - Within a group of Advertise messages with the same server
2966 * preference value, a client MAY select those servers whose
2967 * Advertise messages advertise information of interest to the
2968 * client. For example, the client may choose a server that returned
2969 * an advertisement with configuration options of interest to the
2970 * client.
2971 *
2972 * - The client MAY choose a less-preferred server if that server has a
2973 * better set of advertised parameters, such as the available
2974 * addresses advertised in IAs.
2975 *
2976 * Note that the first and third contradict each other. The third should
2977 * probably be taken to mean that the client should prefer answers that
2978 * offer bindings, even if that violates the preference rule.
2979 *
2980 * The above also isn't deterministic where there are ties. So the final
2981 * tiebreaker we add, if all other values are equal, is to compare the
2982 * server identifiers and to select the numerically lower one.
2983 */
2984 static struct dhc6_lease *
dhc6_best_lease(struct client_state * client,struct dhc6_lease ** head)2985 dhc6_best_lease(struct client_state *client, struct dhc6_lease **head)
2986 {
2987 struct dhc6_lease **rpos, *rval, **candp, *cand;
2988 int cscore, rscore;
2989
2990 if (head == NULL || *head == NULL)
2991 return NULL;
2992
2993 rpos = head;
2994 rval = *rpos;
2995 rscore = dhc6_score_lease(client, rval);
2996 candp = &rval->next;
2997 cand = *candp;
2998
2999 log_debug("PRC: Considering best lease.");
3000 log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
3001 print_hex_1(rval->server_id.len,
3002 rval->server_id.data, 48),
3003 rscore, (unsigned)rval->pref);
3004
3005 for (; cand != NULL ; candp = &cand->next, cand = *candp) {
3006 cscore = dhc6_score_lease(client, cand);
3007
3008 log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
3009 print_hex_1(cand->server_id.len,
3010 cand->server_id.data, 48),
3011 cscore, (unsigned)cand->pref);
3012
3013 /* Above you'll find quoted RFC3315 Section 17.1.3.
3014 *
3015 * The third clause tells us to give up on leases that
3016 * have no bindings even if their preference is better.
3017 * So where our 'selected' lease's score is less than 150
3018 * (1 ia + 1 addr), choose any candidate >= 150.
3019 *
3020 * The first clause tells us to make preference the primary
3021 * deciding factor. So if it's lower, reject, if it's
3022 * higher, select.
3023 *
3024 * The second clause tells us where the preference is
3025 * equal, we should use 'our judgement' of what we like
3026 * to see in an advertisement primarily.
3027 *
3028 * But there can still be a tie. To make this deterministic,
3029 * we compare the server identifiers and select the binary
3030 * lowest.
3031 *
3032 * Since server id's are unique in this list, there is
3033 * no further tie to break.
3034 */
3035 if ((rscore < 150) && (cscore >= 150)) {
3036 log_debug("PRC: | X-- Selected, has bindings.");
3037 } else if (cand->pref < rval->pref) {
3038 log_debug("PRC: | X-- Rejected, lower preference.");
3039 continue;
3040 } else if (cand->pref > rval->pref) {
3041 log_debug("PRC: | X-- Selected, higher preference.");
3042 } else if (cscore > rscore) {
3043 log_debug("PRC: | X-- Selected, equal preference, "
3044 "higher score.");
3045 } else if (cscore < rscore) {
3046 log_debug("PRC: | X-- Rejected, equal preference, "
3047 "lower score.");
3048 continue;
3049 } else if ((cand->server_id.len < rval->server_id.len) ||
3050 ((cand->server_id.len == rval->server_id.len) &&
3051 (memcmp(cand->server_id.data,
3052 rval->server_id.data,
3053 cand->server_id.len) < 0))) {
3054 log_debug("PRC: | X-- Selected, equal preference, "
3055 "equal score, binary lesser server ID.");
3056 } else {
3057 log_debug("PRC: | X-- Rejected, equal preference, "
3058 "equal score, binary greater server ID.");
3059 continue;
3060 }
3061
3062 rpos = candp;
3063 rval = cand;
3064 rscore = cscore;
3065 }
3066
3067 /* Remove the selected lease from the chain. */
3068 *rpos = rval->next;
3069
3070 return rval;
3071 }
3072
3073 /* Select a lease out of the advertised leases and setup state to try and
3074 * acquire that lease.
3075 */
3076 void
start_selecting6(struct client_state * client)3077 start_selecting6(struct client_state *client)
3078 {
3079 struct dhc6_lease *lease;
3080
3081 if (client->advertised_leases == NULL) {
3082 log_error("Can not enter DHCPv6 SELECTING state with no "
3083 "leases to select from!");
3084 return;
3085 }
3086
3087 log_debug("PRC: Selecting best advertised lease.");
3088 client->state = S_SELECTING;
3089
3090 lease = dhc6_best_lease(client, &client->advertised_leases);
3091
3092 if (lease == NULL)
3093 log_fatal("Impossible error at %s:%d.", MDL);
3094
3095 client->selected_lease = lease;
3096
3097 /* Set timers per RFC3315 section 18.1.1. */
3098 client->IRT = REQ_TIMEOUT * 100;
3099 client->MRT = REQ_MAX_RT * 100;
3100 client->MRC = REQ_MAX_RC;
3101 client->MRD = 0;
3102
3103 dhc6_retrans_init(client);
3104
3105 client->v6_handler = reply_handler;
3106
3107 /* ("re")transmit the first packet. */
3108 do_select6(client);
3109 }
3110
3111 /* Transmit a Request to select a lease offered in Advertisements. In
3112 * the event of failure, either move on to the next-best advertised lease,
3113 * or head back to INIT state if there are none.
3114 */
3115 void
do_select6(void * input)3116 do_select6(void *input)
3117 {
3118 struct client_state *client;
3119 struct dhc6_lease *lease;
3120 struct data_string ds;
3121 struct timeval tv;
3122 int send_ret;
3123
3124 client = input;
3125
3126 /* 'lease' is fewer characters to type. */
3127 lease = client->selected_lease;
3128 if (lease == NULL || lease->bindings == NULL) {
3129 log_error("Illegal to attempt selection without selecting "
3130 "a lease.");
3131 return;
3132 }
3133
3134 switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
3135 case CHK_TIM_MRC_EXCEEDED:
3136 case CHK_TIM_MRD_EXCEEDED:
3137 log_debug("PRC: Lease %s failed.",
3138 print_hex_1(lease->server_id.len,
3139 lease->server_id.data, 56));
3140
3141 /* Get rid of the lease that timed/counted out. */
3142 dhc6_lease_destroy(&lease, MDL);
3143 client->selected_lease = NULL;
3144
3145 /* If there are more leases great. If not, get more. */
3146 if (client->advertised_leases != NULL)
3147 start_selecting6(client);
3148 else
3149 start_init6(client);
3150 return;
3151 case CHK_TIM_ALLOC_FAILURE:
3152 return;
3153 case CHK_TIM_SUCCESS:
3154 break;
3155 }
3156
3157 /* Now make a packet that looks suspiciously like the one we
3158 * got from the server. But different.
3159 *
3160 * XXX: I guess IAID is supposed to be something the client
3161 * indicates and uses as a key to its internal state. It is
3162 * kind of odd to ask the server for IA's whose IAID the client
3163 * did not manufacture. We first need a formal dhclient.conf
3164 * construct for the iaid, then we can delve into this matter
3165 * more properly. In the time being, this will work.
3166 */
3167
3168 /* Fetch any configured 'sent' options (includes DUID) in wire format.
3169 */
3170 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
3171 NULL, client->sent_options, &global_scope,
3172 &dhcpv6_universe);
3173
3174 /* Now append any IA's, and within them any IAADDR/IAPREFIXs. */
3175 if (wanted_ia_na &&
3176 dhc6_add_ia_na(client, &ds, lease,
3177 DHCPV6_REQUEST) != ISC_R_SUCCESS) {
3178 data_string_forget(&ds, MDL);
3179 return;
3180 }
3181 if (wanted_ia_ta &&
3182 dhc6_add_ia_ta(client, &ds, lease,
3183 DHCPV6_REQUEST) != ISC_R_SUCCESS) {
3184 data_string_forget(&ds, MDL);
3185 return;
3186 }
3187 if (wanted_ia_pd &&
3188 dhc6_add_ia_pd(client, &ds, lease,
3189 DHCPV6_REQUEST) != ISC_R_SUCCESS) {
3190 data_string_forget(&ds, MDL);
3191 return;
3192 }
3193
3194 log_info("XMT: Request on %s, interval %ld0ms.",
3195 client->name ? client->name : client->interface->name,
3196 (long int)client->RT);
3197
3198 send_ret = send_packet6(client->interface,
3199 ds.data, ds.len, &DHCPv6DestAddr);
3200 if (send_ret != ds.len) {
3201 log_error("dhc6: send_packet6() sent %d of %d bytes",
3202 send_ret, ds.len);
3203 }
3204
3205 data_string_forget(&ds, MDL);
3206
3207 /* Wait RT */
3208 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
3209 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
3210 if (tv.tv_usec >= 1000000) {
3211 tv.tv_sec += 1;
3212 tv.tv_usec -= 1000000;
3213 }
3214 add_timeout(&tv, do_select6, client, NULL, NULL);
3215
3216 dhc6_retrans_advance(client);
3217 }
3218
3219 /* For each IA_NA in the lease, for each address in the IA_NA,
3220 * append that information onto the packet-so-far.
3221 */
3222 static isc_result_t
dhc6_add_ia_na(struct client_state * client,struct data_string * packet,struct dhc6_lease * lease,u_int8_t message)3223 dhc6_add_ia_na(struct client_state *client, struct data_string *packet,
3224 struct dhc6_lease *lease, u_int8_t message)
3225 {
3226 struct data_string iads;
3227 struct data_string addrds;
3228 struct dhc6_addr *addr;
3229 struct dhc6_ia *ia;
3230 isc_result_t rval = ISC_R_SUCCESS;
3231 TIME t1, t2;
3232
3233 memset(&iads, 0, sizeof(iads));
3234 memset(&addrds, 0, sizeof(addrds));
3235 for (ia = lease->bindings;
3236 ia != NULL && rval == ISC_R_SUCCESS;
3237 ia = ia->next) {
3238 if (ia->ia_type != D6O_IA_NA)
3239 continue;
3240
3241 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
3242 log_error("Unable to allocate memory for IA_NA.");
3243 rval = ISC_R_NOMEMORY;
3244 break;
3245 }
3246
3247 /* Copy the IAID into the packet buffer. */
3248 memcpy(iads.buffer->data, ia->iaid, 4);
3249 iads.data = iads.buffer->data;
3250 iads.len = 12;
3251
3252 switch (message) {
3253 case DHCPV6_REQUEST:
3254 case DHCPV6_RENEW:
3255 case DHCPV6_REBIND:
3256
3257 t1 = client->config->requested_lease / 2;
3258 t2 = t1 + (t1 / 2);
3259 #if MAX_TIME > 0xffffffff
3260 if (t1 > 0xffffffff)
3261 t1 = 0xffffffff;
3262 if (t2 > 0xffffffff)
3263 t2 = 0xffffffff;
3264 #endif
3265 putULong(iads.buffer->data + 4, t1);
3266 putULong(iads.buffer->data + 8, t2);
3267
3268 log_debug("XMT: X-- IA_NA %s",
3269 print_hex_1(4, iads.data, 59));
3270 log_debug("XMT: | X-- Requested renew +%u",
3271 (unsigned) t1);
3272 log_debug("XMT: | X-- Requested rebind +%u",
3273 (unsigned) t2);
3274 break;
3275
3276 case DHCPV6_CONFIRM:
3277 case DHCPV6_RELEASE:
3278 case DHCPV6_DECLINE:
3279 /* Set t1 and t2 to zero; server will ignore them */
3280 memset(iads.buffer->data + 4, 0, 8);
3281 log_debug("XMT: X-- IA_NA %s",
3282 print_hex_1(4, iads.buffer->data, 55));
3283
3284 break;
3285
3286 default:
3287 log_fatal("Impossible condition at %s:%d.", MDL);
3288 }
3289
3290 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3291 /*
3292 * Do not confirm expired addresses, do not request
3293 * expired addresses (but we keep them around for
3294 * solicit).
3295 */
3296 if (addr->flags & DHC6_ADDR_EXPIRED)
3297 continue;
3298
3299 if (addr->address.len != 16) {
3300 log_error("Illegal IPv6 address length (%d), "
3301 "ignoring. (%s:%d)",
3302 addr->address.len, MDL);
3303 continue;
3304 }
3305
3306 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
3307 log_error("Unable to allocate memory for "
3308 "IAADDR.");
3309 rval = ISC_R_NOMEMORY;
3310 break;
3311 }
3312
3313 addrds.data = addrds.buffer->data;
3314 addrds.len = 24;
3315
3316 /* Copy the address into the packet buffer. */
3317 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
3318
3319 /* Copy in additional information as appropriate */
3320 switch (message) {
3321 case DHCPV6_REQUEST:
3322 case DHCPV6_RENEW:
3323 case DHCPV6_REBIND:
3324 t1 = client->config->requested_lease;
3325 t2 = t1 + 300;
3326 putULong(addrds.buffer->data + 16, t1);
3327 putULong(addrds.buffer->data + 20, t2);
3328
3329 log_debug("XMT: | | X-- IAADDR %s",
3330 piaddr(addr->address));
3331 log_debug("XMT: | | | X-- Preferred "
3332 "lifetime +%u", (unsigned)t1);
3333 log_debug("XMT: | | | X-- Max lifetime +%u",
3334 (unsigned)t2);
3335
3336 break;
3337
3338 case DHCPV6_CONFIRM:
3339 /*
3340 * Set preferred and max life to zero,
3341 * per 17.1.3.
3342 */
3343 memset(addrds.buffer->data + 16, 0, 8);
3344 log_debug("XMT: | X-- Confirm Address %s",
3345 piaddr(addr->address));
3346 break;
3347
3348 case DHCPV6_RELEASE:
3349 /* Preferred and max life are irrelevant */
3350 memset(addrds.buffer->data + 16, 0, 8);
3351 log_debug("XMT: | X-- Release Address %s",
3352 piaddr(addr->address));
3353 break;
3354
3355 case DHCPV6_DECLINE:
3356 /* Preferred and max life are irrelevant */
3357 memset(addrds.buffer->data + 16, 0, 8);
3358 log_debug("XMT: | X-- Decline Address %s",
3359 piaddr(addr->address));
3360 break;
3361
3362 default:
3363 log_fatal("Impossible condition at %s:%d.",
3364 MDL);
3365 }
3366
3367 append_option(&iads, &dhcpv6_universe, iaaddr_option,
3368 &addrds);
3369 data_string_forget(&addrds, MDL);
3370 }
3371
3372 /*
3373 * It doesn't make sense to make a request without an
3374 * address.
3375 */
3376 if (ia->addrs == NULL) {
3377 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
3378 rval = ISC_R_FAILURE;
3379 } else if (rval == ISC_R_SUCCESS) {
3380 log_debug("XMT: V IA_NA appended.");
3381 append_option(packet, &dhcpv6_universe, ia_na_option,
3382 &iads);
3383 }
3384
3385 data_string_forget(&iads, MDL);
3386 }
3387
3388 return rval;
3389 }
3390
3391 /* For each IA_TA in the lease, for each address in the IA_TA,
3392 * append that information onto the packet-so-far.
3393 */
3394 static isc_result_t
dhc6_add_ia_ta(struct client_state * client,struct data_string * packet,struct dhc6_lease * lease,u_int8_t message)3395 dhc6_add_ia_ta(struct client_state *client, struct data_string *packet,
3396 struct dhc6_lease *lease, u_int8_t message)
3397 {
3398 struct data_string iads;
3399 struct data_string addrds;
3400 struct dhc6_addr *addr;
3401 struct dhc6_ia *ia;
3402 isc_result_t rval = ISC_R_SUCCESS;
3403 TIME t1, t2;
3404
3405 memset(&iads, 0, sizeof(iads));
3406 memset(&addrds, 0, sizeof(addrds));
3407 for (ia = lease->bindings;
3408 ia != NULL && rval == ISC_R_SUCCESS;
3409 ia = ia->next) {
3410 if (ia->ia_type != D6O_IA_TA)
3411 continue;
3412
3413 if (!buffer_allocate(&iads.buffer, 4, MDL)) {
3414 log_error("Unable to allocate memory for IA_TA.");
3415 rval = ISC_R_NOMEMORY;
3416 break;
3417 }
3418
3419 /* Copy the IAID into the packet buffer. */
3420 memcpy(iads.buffer->data, ia->iaid, 4);
3421 iads.data = iads.buffer->data;
3422 iads.len = 4;
3423
3424 log_debug("XMT: X-- IA_TA %s",
3425 print_hex_1(4, iads.buffer->data, 55));
3426
3427 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3428 /*
3429 * Do not confirm expired addresses, do not request
3430 * expired addresses (but we keep them around for
3431 * solicit).
3432 */
3433 if (addr->flags & DHC6_ADDR_EXPIRED)
3434 continue;
3435
3436 if (addr->address.len != 16) {
3437 log_error("Illegal IPv6 address length (%d), "
3438 "ignoring. (%s:%d)",
3439 addr->address.len, MDL);
3440 continue;
3441 }
3442
3443 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
3444 log_error("Unable to allocate memory for "
3445 "IAADDR.");
3446 rval = ISC_R_NOMEMORY;
3447 break;
3448 }
3449
3450 addrds.data = addrds.buffer->data;
3451 addrds.len = 24;
3452
3453 /* Copy the address into the packet buffer. */
3454 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
3455
3456 /* Copy in additional information as appropriate */
3457 switch (message) {
3458 case DHCPV6_REQUEST:
3459 case DHCPV6_RENEW:
3460 case DHCPV6_REBIND:
3461 t1 = client->config->requested_lease;
3462 t2 = t1 + 300;
3463 putULong(addrds.buffer->data + 16, t1);
3464 putULong(addrds.buffer->data + 20, t2);
3465
3466 log_debug("XMT: | | X-- IAADDR %s",
3467 piaddr(addr->address));
3468 log_debug("XMT: | | | X-- Preferred "
3469 "lifetime +%u", (unsigned)t1);
3470 log_debug("XMT: | | | X-- Max lifetime +%u",
3471 (unsigned)t2);
3472
3473 break;
3474
3475 case DHCPV6_CONFIRM:
3476 /*
3477 * Set preferred and max life to zero,
3478 * per 17.1.3.
3479 */
3480 memset(addrds.buffer->data + 16, 0, 8);
3481 log_debug("XMT: | X-- Confirm Address %s",
3482 piaddr(addr->address));
3483 break;
3484
3485 case DHCPV6_RELEASE:
3486 /* Preferred and max life are irrelevant */
3487 memset(addrds.buffer->data + 16, 0, 8);
3488 log_debug("XMT: | X-- Release Address %s",
3489 piaddr(addr->address));
3490 break;
3491
3492 default:
3493 log_fatal("Impossible condition at %s:%d.",
3494 MDL);
3495 }
3496
3497 append_option(&iads, &dhcpv6_universe, iaaddr_option,
3498 &addrds);
3499 data_string_forget(&addrds, MDL);
3500 }
3501
3502 /*
3503 * It doesn't make sense to make a request without an
3504 * address.
3505 */
3506 if (ia->addrs == NULL) {
3507 log_debug("!!!: V IA_TA has no IAADDRs - removed.");
3508 rval = ISC_R_FAILURE;
3509 } else if (rval == ISC_R_SUCCESS) {
3510 log_debug("XMT: V IA_TA appended.");
3511 append_option(packet, &dhcpv6_universe, ia_ta_option,
3512 &iads);
3513 }
3514
3515 data_string_forget(&iads, MDL);
3516 }
3517
3518 return rval;
3519 }
3520
3521 /* For each IA_PD in the lease, for each prefix in the IA_PD,
3522 * append that information onto the packet-so-far.
3523 */
3524 static isc_result_t
dhc6_add_ia_pd(struct client_state * client,struct data_string * packet,struct dhc6_lease * lease,u_int8_t message)3525 dhc6_add_ia_pd(struct client_state *client, struct data_string *packet,
3526 struct dhc6_lease *lease, u_int8_t message)
3527 {
3528 struct data_string iads;
3529 struct data_string prefds;
3530 struct dhc6_addr *pref;
3531 struct dhc6_ia *ia;
3532 isc_result_t rval = ISC_R_SUCCESS;
3533 TIME t1, t2;
3534
3535 memset(&iads, 0, sizeof(iads));
3536 memset(&prefds, 0, sizeof(prefds));
3537 for (ia = lease->bindings;
3538 ia != NULL && rval == ISC_R_SUCCESS;
3539 ia = ia->next) {
3540 if (ia->ia_type != D6O_IA_PD)
3541 continue;
3542
3543 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
3544 log_error("Unable to allocate memory for IA_PD.");
3545 rval = ISC_R_NOMEMORY;
3546 break;
3547 }
3548
3549 /* Copy the IAID into the packet buffer. */
3550 memcpy(iads.buffer->data, ia->iaid, 4);
3551 iads.data = iads.buffer->data;
3552 iads.len = 12;
3553
3554 switch (message) {
3555 case DHCPV6_REQUEST:
3556 case DHCPV6_RENEW:
3557 case DHCPV6_REBIND:
3558
3559 t1 = client->config->requested_lease / 2;
3560 t2 = t1 + (t1 / 2);
3561 #if MAX_TIME > 0xffffffff
3562 if (t1 > 0xffffffff)
3563 t1 = 0xffffffff;
3564 if (t2 > 0xffffffff)
3565 t2 = 0xffffffff;
3566 #endif
3567 putULong(iads.buffer->data + 4, t1);
3568 putULong(iads.buffer->data + 8, t2);
3569
3570 log_debug("XMT: X-- IA_PD %s",
3571 print_hex_1(4, iads.data, 59));
3572 log_debug("XMT: | X-- Requested renew +%u",
3573 (unsigned) t1);
3574 log_debug("XMT: | X-- Requested rebind +%u",
3575 (unsigned) t2);
3576 break;
3577
3578 case DHCPV6_RELEASE:
3579 /* Set t1 and t2 to zero; server will ignore them */
3580 memset(iads.buffer->data + 4, 0, 8);
3581 log_debug("XMT: X-- IA_PD %s",
3582 print_hex_1(4, iads.buffer->data, 55));
3583
3584 break;
3585
3586 default:
3587 log_fatal("Impossible condition at %s:%d.", MDL);
3588 }
3589
3590 for (pref = ia->addrs ; pref != NULL ; pref = pref->next) {
3591 /*
3592 * Do not confirm expired prefixes, do not request
3593 * expired prefixes (but we keep them around for
3594 * solicit).
3595 */
3596 if (pref->flags & DHC6_ADDR_EXPIRED)
3597 continue;
3598
3599 if (pref->address.len != 16) {
3600 log_error("Illegal IPv6 prefix "
3601 "ignoring. (%s:%d)",
3602 MDL);
3603 continue;
3604 }
3605
3606 if (pref->plen == 0) {
3607 log_info("Null IPv6 prefix, "
3608 "ignoring. (%s:%d)",
3609 MDL);
3610 }
3611
3612 if (!buffer_allocate(&prefds.buffer, 25, MDL)) {
3613 log_error("Unable to allocate memory for "
3614 "IAPREFIX.");
3615 rval = ISC_R_NOMEMORY;
3616 break;
3617 }
3618
3619 prefds.data = prefds.buffer->data;
3620 prefds.len = 25;
3621
3622 /* Copy the prefix into the packet buffer. */
3623 putUChar(prefds.buffer->data + 8, pref->plen);
3624 memcpy(prefds.buffer->data + 9,
3625 pref->address.iabuf,
3626 16);
3627
3628 /* Copy in additional information as appropriate */
3629 switch (message) {
3630 case DHCPV6_REQUEST:
3631 case DHCPV6_RENEW:
3632 case DHCPV6_REBIND:
3633 t1 = client->config->requested_lease;
3634 t2 = t1 + 300;
3635 putULong(prefds.buffer->data, t1);
3636 putULong(prefds.buffer->data + 4, t2);
3637
3638 log_debug("XMT: | | X-- IAPREFIX %s/%u",
3639 piaddr(pref->address),
3640 (unsigned) pref->plen);
3641 log_debug("XMT: | | | X-- Preferred "
3642 "lifetime +%u", (unsigned)t1);
3643 log_debug("XMT: | | | X-- Max lifetime +%u",
3644 (unsigned)t2);
3645
3646 break;
3647
3648 case DHCPV6_RELEASE:
3649 /* Preferred and max life are irrelevant */
3650 memset(prefds.buffer->data, 0, 8);
3651 log_debug("XMT: | X-- Release Prefix %s/%u",
3652 piaddr(pref->address),
3653 (unsigned) pref->plen);
3654 break;
3655
3656 default:
3657 log_fatal("Impossible condition at %s:%d.",
3658 MDL);
3659 }
3660
3661 append_option(&iads, &dhcpv6_universe,
3662 iaprefix_option, &prefds);
3663 data_string_forget(&prefds, MDL);
3664 }
3665
3666 /*
3667 * It doesn't make sense to make a request without an
3668 * address.
3669 */
3670 if (ia->addrs == NULL) {
3671 log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
3672 rval = ISC_R_FAILURE;
3673 } else if (rval == ISC_R_SUCCESS) {
3674 log_debug("XMT: V IA_PD appended.");
3675 append_option(packet, &dhcpv6_universe,
3676 ia_pd_option, &iads);
3677 }
3678
3679 data_string_forget(&iads, MDL);
3680 }
3681
3682 return rval;
3683 }
3684
3685 /* stopping_finished() checks if there is a remaining work to do.
3686 */
3687 static isc_boolean_t
stopping_finished(void)3688 stopping_finished(void)
3689 {
3690 struct interface_info *ip;
3691 struct client_state *client;
3692
3693 for (ip = interfaces; ip; ip = ip -> next) {
3694 for (client = ip -> client; client; client = client -> next) {
3695 if (client->state != S_STOPPED)
3696 return ISC_FALSE;
3697 if (client->active_lease != NULL)
3698 return ISC_FALSE;
3699 }
3700 }
3701 return ISC_TRUE;
3702 }
3703
3704 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
3705 * Rebind. Basically any Reply packet.
3706 */
3707 void
reply_handler(struct packet * packet,struct client_state * client)3708 reply_handler(struct packet *packet, struct client_state *client)
3709 {
3710 struct dhc6_lease *lease;
3711 isc_result_t check_status;
3712
3713 if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
3714 return;
3715
3716 /* RFC3315 section 15.10 validation (same as 15.3 since we
3717 * always include a client id).
3718 */
3719 if (!valid_reply(packet, client)) {
3720 log_error("Invalid Reply - rejecting.");
3721 return;
3722 }
3723
3724 lease = dhc6_leaseify(packet);
3725
3726 /* This is an out of memory condition...hopefully a temporary
3727 * problem. Returning now makes us try to retransmit later.
3728 */
3729 if (lease == NULL)
3730 return;
3731
3732 check_status = dhc6_check_reply(client, lease);
3733 if (check_status != ISC_R_SUCCESS) {
3734 dhc6_lease_destroy(&lease, MDL);
3735
3736 /* If no action was taken, but there is an error, then
3737 * we wait for a retransmission.
3738 */
3739 if (check_status != ISC_R_CANCELED)
3740 return;
3741 }
3742
3743 /* We're done retransmitting at this point. */
3744 cancel_timeout(do_confirm6, client);
3745 cancel_timeout(do_select6, client);
3746 cancel_timeout(do_refresh6, client);
3747 cancel_timeout(do_release6, client);
3748
3749 /* If this is in response to a Release/Decline, clean up and return. */
3750 if (client->state == S_STOPPED) {
3751 if (client->active_lease == NULL)
3752 return;
3753
3754 dhc6_lease_destroy(&client->active_lease, MDL);
3755 client->active_lease = NULL;
3756 /* We should never wait for nothing!? */
3757 if (stopping_finished())
3758 exit(0);
3759 return;
3760 }
3761
3762 /* Action was taken, so now that we've torn down our scheduled
3763 * retransmissions, return.
3764 */
3765 if (check_status == ISC_R_CANCELED)
3766 return;
3767
3768 if (client->selected_lease != NULL) {
3769 dhc6_lease_destroy(&client->selected_lease, MDL);
3770 client->selected_lease = NULL;
3771 }
3772
3773 /* If this is in response to a confirm, we use the lease we've
3774 * already got, not the reply we were sent.
3775 */
3776 if (client->state == S_REBOOTING) {
3777 if (client->active_lease == NULL)
3778 log_fatal("Impossible condition at %s:%d.", MDL);
3779
3780 dhc6_lease_destroy(&lease, MDL);
3781 start_bound(client);
3782 return;
3783 }
3784
3785 /* Merge any bindings in the active lease (if there is one) into
3786 * the new active lease.
3787 */
3788 dhc6_merge_lease(client->active_lease, lease);
3789
3790 /* Cleanup if a previous attempt to go bound failed. */
3791 if (client->old_lease != NULL) {
3792 dhc6_lease_destroy(&client->old_lease, MDL);
3793 client->old_lease = NULL;
3794 }
3795
3796 /* Make this lease active and BIND to it. */
3797 if (client->active_lease != NULL)
3798 client->old_lease = client->active_lease;
3799 client->active_lease = lease;
3800
3801 /* We're done with the ADVERTISEd leases, if any. */
3802 while(client->advertised_leases != NULL) {
3803 lease = client->advertised_leases;
3804 client->advertised_leases = lease->next;
3805
3806 dhc6_lease_destroy(&lease, MDL);
3807 }
3808
3809 start_bound(client);
3810 }
3811
3812 /* DHCPv6 packets are a little sillier than they needed to be - the root
3813 * packet contains options, then IA's which contain options, then within
3814 * that IAADDR's which contain options.
3815 *
3816 * To sort this out at dhclient-script time (which fetches config parameters
3817 * in environment variables), start_bound() iterates over each IAADDR, and
3818 * calls this function to marshall an environment variable set that includes
3819 * the most-specific option values related to that IAADDR in particular.
3820 *
3821 * To achieve this, we load environment variables for the root options space,
3822 * then the IA, then the IAADDR. Any duplicate option names will be
3823 * over-written by the later versions.
3824 */
3825 static void
dhc6_marshall_values(const char * prefix,struct client_state * client,struct dhc6_lease * lease,struct dhc6_ia * ia,struct dhc6_addr * addr)3826 dhc6_marshall_values(const char *prefix, struct client_state *client,
3827 struct dhc6_lease *lease, struct dhc6_ia *ia,
3828 struct dhc6_addr *addr)
3829 {
3830 /* Option cache contents, in descending order of
3831 * scope.
3832 */
3833 if ((lease != NULL) && (lease->options != NULL))
3834 script_write_params6(client, prefix, lease->options);
3835 if ((ia != NULL) && (ia->options != NULL))
3836 script_write_params6(client, prefix, ia->options);
3837 if ((addr != NULL) && (addr->options != NULL))
3838 script_write_params6(client, prefix, addr->options);
3839
3840 /* addr fields. */
3841 if (addr != NULL) {
3842 if ((ia != NULL) && (ia->ia_type == D6O_IA_PD)) {
3843 client_envadd(client, prefix,
3844 "ip6_prefix", "%s/%u",
3845 piaddr(addr->address),
3846 (unsigned) addr->plen);
3847 } else {
3848 /* Current practice is that all subnets are /64's, but
3849 * some suspect this may not be permanent.
3850 */
3851 client_envadd(client, prefix, "ip6_prefixlen",
3852 "%d", 64);
3853 client_envadd(client, prefix, "ip6_address",
3854 "%s", piaddr(addr->address));
3855 }
3856 if ((ia != NULL) && (ia->ia_type == D6O_IA_TA)) {
3857 client_envadd(client, prefix,
3858 "ip6_type", "temporary");
3859 }
3860 client_envadd(client, prefix, "life_starts", "%d",
3861 (int)(addr->starts));
3862 client_envadd(client, prefix, "preferred_life", "%d",
3863 (int)(addr->preferred_life));
3864 client_envadd(client, prefix, "max_life", "%d",
3865 (int)(addr->max_life));
3866 }
3867
3868 /* ia fields. */
3869 if (ia != NULL) {
3870 client_envadd(client, prefix, "iaid", "%s",
3871 print_hex_1(4, ia->iaid, 12));
3872 client_envadd(client, prefix, "starts", "%d",
3873 (int)(ia->starts));
3874 client_envadd(client, prefix, "renew", "%u", ia->renew);
3875 client_envadd(client, prefix, "rebind", "%u", ia->rebind);
3876 }
3877 }
3878
3879 /* Look at where the client's active lease is sitting. If it's looking to
3880 * time out on renew, rebind, depref, or expiration, do those things.
3881 */
3882 static void
dhc6_check_times(struct client_state * client)3883 dhc6_check_times(struct client_state *client)
3884 {
3885 struct dhc6_lease *lease;
3886 struct dhc6_ia *ia;
3887 struct dhc6_addr *addr;
3888 TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
3889 lo_expire=MAX_TIME, hi_expire=0, tmp;
3890 int has_addrs = ISC_FALSE;
3891 struct timeval tv;
3892
3893 lease = client->active_lease;
3894
3895 /* Bit spammy. We should probably keep record of scheduled
3896 * events instead.
3897 */
3898 cancel_timeout(start_renew6, client);
3899 cancel_timeout(start_rebind6, client);
3900 cancel_timeout(do_depref, client);
3901 cancel_timeout(do_expire, client);
3902
3903 for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
3904 TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
3905
3906 this_ia_lo_expire = MAX_TIME;
3907 this_ia_hi_expire = 0;
3908
3909 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3910 if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
3911 if (addr->preferred_life == 0xffffffff)
3912 tmp = MAX_TIME;
3913 else
3914 tmp = addr->starts +
3915 addr->preferred_life;
3916
3917 if (tmp < depref)
3918 depref = tmp;
3919 }
3920
3921 if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
3922 /* Find EPOCH-relative expiration. */
3923 if (addr->max_life == 0xffffffff)
3924 tmp = MAX_TIME;
3925 else
3926 tmp = addr->starts + addr->max_life;
3927
3928 /* Make the times ia->starts relative. */
3929 tmp -= ia->starts;
3930
3931 if (tmp > this_ia_hi_expire)
3932 this_ia_hi_expire = tmp;
3933 if (tmp < this_ia_lo_expire)
3934 this_ia_lo_expire = tmp;
3935
3936 has_addrs = ISC_TRUE;
3937 }
3938 }
3939
3940 /* These times are ia->starts relative. */
3941 if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
3942 use_expire = this_ia_hi_expire;
3943 else
3944 use_expire = this_ia_lo_expire;
3945
3946 /*
3947 * If the auto-selected expiration time is "infinite", or
3948 * zero, assert a reasonable default.
3949 */
3950 if ((use_expire == MAX_TIME) || (use_expire <= 1))
3951 use_expire = client->config->requested_lease / 2;
3952 else
3953 use_expire /= 2;
3954
3955 /* Don't renew/rebind temporary addresses. */
3956 if (ia->ia_type != D6O_IA_TA) {
3957
3958 if (ia->renew == 0) {
3959 tmp = ia->starts + use_expire;
3960 } else if (ia->renew == 0xffffffff)
3961 tmp = MAX_TIME;
3962 else
3963 tmp = ia->starts + ia->renew;
3964
3965 if (tmp < renew)
3966 renew = tmp;
3967
3968 if (ia->rebind == 0) {
3969 /* Set rebind to 3/4 expiration interval. */
3970 tmp = ia->starts;
3971 tmp += use_expire + (use_expire / 2);
3972 } else if (ia->rebind == 0xffffffff)
3973 tmp = MAX_TIME;
3974 else
3975 tmp = ia->starts + ia->rebind;
3976
3977 if (tmp < rebind)
3978 rebind = tmp;
3979 }
3980
3981 /*
3982 * Return expiration ranges to EPOCH relative for event
3983 * scheduling (add_timeout()).
3984 */
3985 this_ia_hi_expire += ia->starts;
3986 this_ia_lo_expire += ia->starts;
3987
3988 if (this_ia_hi_expire > hi_expire)
3989 hi_expire = this_ia_hi_expire;
3990 if (this_ia_lo_expire < lo_expire)
3991 lo_expire = this_ia_lo_expire;
3992 }
3993
3994 /* If there are no addresses, give up, go to INIT.
3995 * Note that if an address is unexpired with a date in the past,
3996 * we're scheduling an expiration event to ocurr in the past. We
3997 * could probably optimize this to expire now (but then there's
3998 * recursion).
3999 *
4000 * In the future, we may decide that we're done here, or to
4001 * schedule a future request (using 4-pkt info-request model).
4002 */
4003 if (has_addrs == ISC_FALSE) {
4004 dhc6_lease_destroy(&client->active_lease, MDL);
4005 client->active_lease = NULL;
4006
4007 /* Go back to the beginning. */
4008 start_init6(client);
4009 return;
4010 }
4011
4012 switch(client->state) {
4013 case S_BOUND:
4014 /* We'd like to hit renewing, but if rebinding has already
4015 * passed (time warp), head straight there.
4016 */
4017 if ((rebind > cur_time) && (renew < rebind)) {
4018 log_debug("PRC: Renewal event scheduled in %d seconds, "
4019 "to run for %u seconds.",
4020 (int)(renew - cur_time),
4021 (unsigned)(rebind - renew));
4022 client->next_MRD = rebind;
4023 tv.tv_sec = renew;
4024 tv.tv_usec = 0;
4025 add_timeout(&tv, start_renew6, client, NULL, NULL);
4026
4027 break;
4028 }
4029 /* FALL THROUGH */
4030 case S_RENEWING:
4031 /* While actively renewing, MRD is bounded by the time
4032 * we stop renewing and start rebinding. This helps us
4033 * process the state change on time.
4034 */
4035 client->MRD = rebind - cur_time;
4036 if (rebind != MAX_TIME) {
4037 log_debug("PRC: Rebind event scheduled in %d seconds, "
4038 "to run for %d seconds.",
4039 (int)(rebind - cur_time),
4040 (int)(hi_expire - rebind));
4041 client->next_MRD = hi_expire;
4042 tv.tv_sec = rebind;
4043 tv.tv_usec = 0;
4044 add_timeout(&tv, start_rebind6, client, NULL, NULL);
4045 }
4046 break;
4047
4048 case S_REBINDING:
4049 /* For now, we rebind up until the last lease expires. In
4050 * the future, we might want to start SOLICITing when we've
4051 * depreffed an address.
4052 */
4053 client->MRD = hi_expire - cur_time;
4054 break;
4055
4056 default:
4057 log_fatal("Impossible condition at %s:%d.", MDL);
4058 }
4059
4060 /* Separately, set a time at which we will depref and expire
4061 * leases. This might happen with multiple addresses while we
4062 * keep trying to refresh.
4063 */
4064 if (depref != MAX_TIME) {
4065 log_debug("PRC: Depreference scheduled in %d seconds.",
4066 (int)(depref - cur_time));
4067 tv.tv_sec = depref;
4068 tv.tv_usec = 0;
4069 add_timeout(&tv, do_depref, client, NULL, NULL);
4070 }
4071 if (lo_expire != MAX_TIME) {
4072 log_debug("PRC: Expiration scheduled in %d seconds.",
4073 (int)(lo_expire - cur_time));
4074 tv.tv_sec = lo_expire;
4075 tv.tv_usec = 0;
4076 add_timeout(&tv, do_expire, client, NULL, NULL);
4077 }
4078 }
4079
4080 /* In a given IA chain, find the IA with the same type and 'iaid'. */
4081 static struct dhc6_ia *
find_ia(struct dhc6_ia * head,u_int16_t type,const char * id)4082 find_ia(struct dhc6_ia *head, u_int16_t type, const char *id)
4083 {
4084 struct dhc6_ia *ia;
4085
4086 for (ia = head ; ia != NULL ; ia = ia->next) {
4087 if (ia->ia_type != type)
4088 continue;
4089 if (memcmp(ia->iaid, id, 4) == 0)
4090 return ia;
4091 }
4092
4093 return NULL;
4094 }
4095
4096 /* In a given address chain, find a matching address. */
4097 static struct dhc6_addr *
find_addr(struct dhc6_addr * head,struct iaddr * address)4098 find_addr(struct dhc6_addr *head, struct iaddr *address)
4099 {
4100 struct dhc6_addr *addr;
4101
4102 for (addr = head ; addr != NULL ; addr = addr->next) {
4103 if ((addr->address.len == address->len) &&
4104 (memcmp(addr->address.iabuf, address->iabuf,
4105 address->len) == 0))
4106 return addr;
4107 }
4108
4109 return NULL;
4110 }
4111
4112 /* In a given prefix chain, find a matching prefix. */
4113 static struct dhc6_addr *
find_pref(struct dhc6_addr * head,struct iaddr * prefix,u_int8_t plen)4114 find_pref(struct dhc6_addr *head, struct iaddr *prefix, u_int8_t plen)
4115 {
4116 struct dhc6_addr *pref;
4117
4118 for (pref = head ; pref != NULL ; pref = pref->next) {
4119 if ((pref->address.len == prefix->len) &&
4120 (pref->plen == plen) &&
4121 (memcmp(pref->address.iabuf, prefix->iabuf,
4122 prefix->len) == 0))
4123 return pref;
4124 }
4125
4126 return NULL;
4127 }
4128
4129 /* Merge the bindings from the source lease into the destination lease
4130 * structure, where they are missing. We have to copy the stateful
4131 * objects rather than move them over, because later code needs to be
4132 * able to compare new versus old if they contain any bindings.
4133 */
4134 static void
dhc6_merge_lease(struct dhc6_lease * src,struct dhc6_lease * dst)4135 dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst)
4136 {
4137 struct dhc6_ia *sia, *dia, *tia;
4138 struct dhc6_addr *saddr, *daddr, *taddr;
4139 int changes = 0;
4140
4141 if ((dst == NULL) || (src == NULL))
4142 return;
4143
4144 for (sia = src->bindings ; sia != NULL ; sia = sia->next) {
4145 dia = find_ia(dst->bindings, sia->ia_type, (char *)sia->iaid);
4146
4147 if (dia == NULL) {
4148 tia = dhc6_dup_ia(sia, MDL);
4149
4150 if (tia == NULL)
4151 log_fatal("Out of memory merging lease - "
4152 "Unable to continue without losing "
4153 "state! (%s:%d)", MDL);
4154
4155 /* XXX: consider sorting? */
4156 tia->next = dst->bindings;
4157 dst->bindings = tia;
4158 changes = 1;
4159 } else {
4160 for (saddr = sia->addrs ; saddr != NULL ;
4161 saddr = saddr->next) {
4162 if (sia->ia_type != D6O_IA_PD)
4163 daddr = find_addr(dia->addrs,
4164 &saddr->address);
4165 else
4166 daddr = find_pref(dia->addrs,
4167 &saddr->address,
4168 saddr->plen);
4169
4170 if (daddr == NULL) {
4171 taddr = dhc6_dup_addr(saddr, MDL);
4172
4173 if (taddr == NULL)
4174 log_fatal("Out of memory "
4175 "merging lease - "
4176 "Unable to continue "
4177 "without losing "
4178 "state! (%s:%d)",
4179 MDL);
4180
4181 /* XXX: consider sorting? */
4182 taddr->next = dia->addrs;
4183 dia->addrs = taddr;
4184 changes = 1;
4185 }
4186 }
4187 }
4188 }
4189
4190 /* If we made changes, reset the score to 0 so it is recalculated. */
4191 if (changes)
4192 dst->score = 0;
4193 }
4194
4195 /* We've either finished selecting or succeeded in Renew or Rebinding our
4196 * lease. In all cases we got a Reply. Give dhclient-script a tickle
4197 * to inform it about the new values, and then lay in wait for the next
4198 * event.
4199 */
4200 static void
start_bound(struct client_state * client)4201 start_bound(struct client_state *client)
4202 {
4203 struct dhc6_ia *ia, *oldia;
4204 struct dhc6_addr *addr, *oldaddr;
4205 struct dhc6_lease *lease, *old;
4206 const char *reason;
4207 #if defined (NSUPDATE)
4208 TIME dns_update_offset = 1;
4209 #endif
4210
4211 lease = client->active_lease;
4212 if (lease == NULL) {
4213 log_error("Cannot enter bound state unless an active lease "
4214 "is selected.");
4215 return;
4216 }
4217 lease->released = ISC_FALSE;
4218 old = client->old_lease;
4219
4220 client->v6_handler = bound_handler;
4221
4222 switch (client->state) {
4223 case S_SELECTING:
4224 case S_REBOOTING: /* Pretend we got bound. */
4225 reason = "BOUND6";
4226 break;
4227
4228 case S_RENEWING:
4229 reason = "RENEW6";
4230 break;
4231
4232 case S_REBINDING:
4233 reason = "REBIND6";
4234 break;
4235
4236 default:
4237 log_fatal("Impossible condition at %s:%d.", MDL);
4238 /* Silence compiler warnings. */
4239 return;
4240 }
4241
4242 log_debug("PRC: Bound to lease %s.",
4243 print_hex_1(client->active_lease->server_id.len,
4244 client->active_lease->server_id.data, 55));
4245 client->state = S_BOUND;
4246
4247 write_client6_lease(client, lease, 0, 1);
4248
4249 oldia = NULL;
4250 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4251 if (old != NULL)
4252 oldia = find_ia(old->bindings,
4253 ia->ia_type,
4254 (char *)ia->iaid);
4255 else
4256 oldia = NULL;
4257
4258 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4259 if (oldia != NULL) {
4260 if (ia->ia_type != D6O_IA_PD)
4261 oldaddr = find_addr(oldia->addrs,
4262 &addr->address);
4263 else
4264 oldaddr = find_pref(oldia->addrs,
4265 &addr->address,
4266 addr->plen);
4267 } else
4268 oldaddr = NULL;
4269
4270 #if defined (NSUPDATE)
4271 if ((oldaddr == NULL) && (ia->ia_type == D6O_IA_NA))
4272 dhclient_schedule_updates(client,
4273 &addr->address,
4274 dns_update_offset++);
4275 #endif
4276
4277 /* Shell out to setup the new binding. */
4278 script_init(client, reason, NULL);
4279
4280 if (old != NULL)
4281 dhc6_marshall_values("old_", client, old,
4282 oldia, oldaddr);
4283 dhc6_marshall_values("new_", client, lease, ia, addr);
4284 script_write_requested6(client);
4285
4286 script_go(client);
4287 }
4288
4289 /* XXX: maybe we should loop on the old values instead? */
4290 if (ia->addrs == NULL) {
4291 script_init(client, reason, NULL);
4292
4293 if (old != NULL)
4294 dhc6_marshall_values("old_", client, old,
4295 oldia,
4296 oldia != NULL ?
4297 oldia->addrs : NULL);
4298
4299 dhc6_marshall_values("new_", client, lease, ia,
4300 NULL);
4301 script_write_requested6(client);
4302
4303 script_go(client);
4304 }
4305 }
4306
4307 /* XXX: maybe we should loop on the old values instead? */
4308 if (lease->bindings == NULL) {
4309 script_init(client, reason, NULL);
4310
4311 if (old != NULL)
4312 dhc6_marshall_values("old_", client, old,
4313 old->bindings,
4314 (old->bindings != NULL) ?
4315 old->bindings->addrs : NULL);
4316
4317 dhc6_marshall_values("new_", client, lease, NULL, NULL);
4318 script_write_requested6(client);
4319
4320 script_go(client);
4321 }
4322
4323 go_daemon();
4324
4325 if (client->old_lease != NULL) {
4326 dhc6_lease_destroy(&client->old_lease, MDL);
4327 client->old_lease = NULL;
4328 }
4329
4330 /* Schedule events. */
4331 dhc6_check_times(client);
4332 }
4333
4334 /* While bound, ignore packets. In the future we'll want to answer
4335 * Reconfigure-Request messages and the like.
4336 */
4337 void
bound_handler(struct packet * packet,struct client_state * client)4338 bound_handler(struct packet *packet, struct client_state *client)
4339 {
4340 log_debug("RCV: Input packets are ignored once bound.");
4341 }
4342
4343 /* start_renew6() gets us all ready to go to start transmitting Renew packets.
4344 * Note that client->next_MRD must be set before entering this function -
4345 * it must be set to the time at which the client should start Rebinding.
4346 */
4347 void
start_renew6(void * input)4348 start_renew6(void *input)
4349 {
4350 struct client_state *client;
4351
4352 client = (struct client_state *)input;
4353
4354 log_info("PRC: Renewing lease on %s.",
4355 client->name ? client->name : client->interface->name);
4356 client->state = S_RENEWING;
4357
4358 client->v6_handler = reply_handler;
4359
4360 /* Times per RFC3315 section 18.1.3. */
4361 client->IRT = REN_TIMEOUT * 100;
4362 client->MRT = REN_MAX_RT * 100;
4363 client->MRC = 0;
4364 /* MRD is special in renew - we need to set it by checking timer
4365 * state.
4366 */
4367 client->MRD = client->next_MRD - cur_time;
4368
4369 dhc6_retrans_init(client);
4370
4371 client->refresh_type = DHCPV6_RENEW;
4372 do_refresh6(client);
4373 }
4374
4375 /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
4376 * gives the retransmission state a bump for the next time. Note that
4377 * client->refresh_type must be set before entering this function.
4378 */
4379 void
do_refresh6(void * input)4380 do_refresh6(void *input)
4381 {
4382 struct option_cache *oc;
4383 struct sockaddr_in6 unicast, *dest_addr = &DHCPv6DestAddr;
4384 struct data_string ds;
4385 struct client_state *client;
4386 struct dhc6_lease *lease;
4387 struct timeval elapsed, tv;
4388 int send_ret;
4389
4390 client = (struct client_state *)input;
4391 memset(&ds, 0, sizeof(ds));
4392
4393 lease = client->active_lease;
4394 if (lease == NULL) {
4395 log_error("Cannot renew without an active binding.");
4396 return;
4397 }
4398
4399 /* Ensure we're emitting a valid message type. */
4400 switch (client->refresh_type) {
4401 case DHCPV6_RENEW:
4402 case DHCPV6_REBIND:
4403 break;
4404
4405 default:
4406 log_fatal("Internal inconsistency (%d) at %s:%d.",
4407 client->refresh_type, MDL);
4408 }
4409
4410 /*
4411 * Start_time starts at the first transmission.
4412 */
4413 if (client->txcount == 0) {
4414 client->start_time.tv_sec = cur_tv.tv_sec;
4415 client->start_time.tv_usec = cur_tv.tv_usec;
4416 }
4417
4418 /* elapsed = cur - start */
4419 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
4420 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
4421 if (elapsed.tv_usec < 0) {
4422 elapsed.tv_sec -= 1;
4423 elapsed.tv_usec += 1000000;
4424 }
4425 if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
4426 ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
4427 /* We're done. Move on to the next phase, if any. */
4428 dhc6_check_times(client);
4429 return;
4430 }
4431
4432 /*
4433 * Check whether the server has sent a unicast option; if so, we can
4434 * use the address it specified for RENEWs.
4435 */
4436 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_UNICAST);
4437 if (oc && evaluate_option_cache(&ds, NULL, NULL, NULL,
4438 lease->options, NULL, &global_scope,
4439 oc, MDL)) {
4440 if (ds.len < 16) {
4441 log_error("Invalid unicast option length %d.", ds.len);
4442 } else {
4443 memset(&unicast, 0, sizeof(DHCPv6DestAddr));
4444 unicast.sin6_family = AF_INET6;
4445 unicast.sin6_port = remote_port;
4446 memcpy(&unicast.sin6_addr, ds.data, 16);
4447 if (client->refresh_type == DHCPV6_RENEW) {
4448 dest_addr = &unicast;
4449 }
4450 }
4451
4452 data_string_forget(&ds, MDL);
4453 }
4454
4455 /* Commence forming a renew packet. */
4456 memset(&ds, 0, sizeof(ds));
4457 if (!buffer_allocate(&ds.buffer, 4, MDL)) {
4458 log_error("Unable to allocate memory for packet.");
4459 return;
4460 }
4461 ds.data = ds.buffer->data;
4462 ds.len = 4;
4463
4464 ds.buffer->data[0] = client->refresh_type;
4465 memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
4466
4467 /* Form an elapsed option. */
4468 /* Maximum value is 65535 1/100s coded as 0xffff. */
4469 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
4470 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
4471 client->elapsed = 0xffff;
4472 } else {
4473 client->elapsed = elapsed.tv_sec * 100;
4474 client->elapsed += elapsed.tv_usec / 10000;
4475 }
4476
4477 if (client->elapsed == 0)
4478 log_debug("XMT: Forming %s, 0 ms elapsed.",
4479 dhcpv6_type_names[client->refresh_type]);
4480 else
4481 log_debug("XMT: Forming %s, %u0 ms elapsed.",
4482 dhcpv6_type_names[client->refresh_type],
4483 (unsigned)client->elapsed);
4484
4485 client->elapsed = htons(client->elapsed);
4486
4487 make_client6_options(client, &client->sent_options, lease,
4488 client->refresh_type);
4489
4490 /* Put in any options from the sent cache. */
4491 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
4492 client->sent_options, &global_scope,
4493 &dhcpv6_universe);
4494
4495 /* Append IA's */
4496 if (wanted_ia_na &&
4497 dhc6_add_ia_na(client, &ds, lease,
4498 client->refresh_type) != ISC_R_SUCCESS) {
4499 data_string_forget(&ds, MDL);
4500 return;
4501 }
4502 if (wanted_ia_pd &&
4503 dhc6_add_ia_pd(client, &ds, lease,
4504 client->refresh_type) != ISC_R_SUCCESS) {
4505 data_string_forget(&ds, MDL);
4506 return;
4507 }
4508
4509 log_info("XMT: %s on %s, interval %ld0ms.",
4510 dhcpv6_type_names[client->refresh_type],
4511 client->name ? client->name : client->interface->name,
4512 (long int)client->RT);
4513
4514 send_ret = send_packet6(client->interface, ds.data, ds.len, dest_addr);
4515
4516 if (send_ret != ds.len) {
4517 log_error("dhc6: send_packet6() sent %d of %d bytes",
4518 send_ret, ds.len);
4519 }
4520
4521 data_string_forget(&ds, MDL);
4522
4523 /* Wait RT */
4524 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
4525 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
4526 if (tv.tv_usec >= 1000000) {
4527 tv.tv_sec += 1;
4528 tv.tv_usec -= 1000000;
4529 }
4530 add_timeout(&tv, do_refresh6, client, NULL, NULL);
4531
4532 dhc6_retrans_advance(client);
4533 }
4534
4535 /* start_rebind6() gets us all set up to go and rebind a lease. Note that
4536 * client->next_MRD must be set before entering this function. In this case,
4537 * MRD must be set to the maximum time any address in the packet will
4538 * expire.
4539 */
4540 void
start_rebind6(void * input)4541 start_rebind6(void *input)
4542 {
4543 struct client_state *client;
4544
4545 client = (struct client_state *)input;
4546
4547 log_info("PRC: Rebinding lease on %s.",
4548 client->name ? client->name : client->interface->name);
4549 client->state = S_REBINDING;
4550
4551 client->v6_handler = reply_handler;
4552
4553 /* Times per RFC3315 section 18.1.4. */
4554 client->IRT = REB_TIMEOUT * 100;
4555 client->MRT = REB_MAX_RT * 100;
4556 client->MRC = 0;
4557 /* MRD is special in rebind - it's determined by the timer
4558 * state.
4559 */
4560 client->MRD = client->next_MRD - cur_time;
4561
4562 dhc6_retrans_init(client);
4563
4564 client->refresh_type = DHCPV6_REBIND;
4565 do_refresh6(client);
4566 }
4567
4568 /* do_depref() runs through a given lease's addresses, for each that has
4569 * not yet been depreffed, shells out to the dhclient-script to inform it
4570 * of the status change. The dhclient-script should then do...something...
4571 * to encourage applications to move off the address and onto one of the
4572 * remaining 'preferred' addresses.
4573 */
4574 void
do_depref(void * input)4575 do_depref(void *input)
4576 {
4577 struct client_state *client;
4578 struct dhc6_lease *lease;
4579 struct dhc6_ia *ia;
4580 struct dhc6_addr *addr;
4581
4582 client = (struct client_state *)input;
4583
4584 lease = client->active_lease;
4585 if (lease == NULL)
4586 return;
4587
4588 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4589 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4590 if (addr->flags & DHC6_ADDR_DEPREFFED)
4591 continue;
4592
4593 if (addr->starts + addr->preferred_life <= cur_time) {
4594 script_init(client, "DEPREF6", NULL);
4595 dhc6_marshall_values("cur_", client, lease,
4596 ia, addr);
4597 script_write_requested6(client);
4598 script_go(client);
4599
4600 addr->flags |= DHC6_ADDR_DEPREFFED;
4601
4602 if (ia->ia_type != D6O_IA_PD)
4603 log_info("PRC: Address %s depreferred.",
4604 piaddr(addr->address));
4605 else
4606 log_info("PRC: Prefix %s/%u depreferred.",
4607 piaddr(addr->address),
4608 (unsigned) addr->plen);
4609
4610 #if defined (NSUPDATE)
4611 /* Remove DDNS bindings at depref time. */
4612 if ((ia->ia_type == D6O_IA_NA) &&
4613 client->config->do_forward_update)
4614 client_dns_remove(client,
4615 &addr->address);
4616 #endif
4617 }
4618 }
4619 }
4620
4621 dhc6_check_times(client);
4622 }
4623
4624 /* do_expire() searches through all the addresses on a given lease, and
4625 * expires/removes any addresses that are no longer valid.
4626 */
4627 void
do_expire(void * input)4628 do_expire(void *input)
4629 {
4630 struct client_state *client;
4631 struct dhc6_lease *lease;
4632 struct dhc6_ia *ia;
4633 struct dhc6_addr *addr;
4634 int has_addrs = ISC_FALSE;
4635
4636 client = (struct client_state *)input;
4637
4638 lease = client->active_lease;
4639 if (lease == NULL)
4640 return;
4641
4642 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4643 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4644 if (addr->flags & DHC6_ADDR_EXPIRED)
4645 continue;
4646
4647 if (addr->starts + addr->max_life <= cur_time) {
4648 script_init(client, "EXPIRE6", NULL);
4649 dhc6_marshall_values("old_", client, lease,
4650 ia, addr);
4651 script_write_requested6(client);
4652 script_go(client);
4653
4654 addr->flags |= DHC6_ADDR_EXPIRED;
4655
4656 if (ia->ia_type != D6O_IA_PD)
4657 log_info("PRC: Address %s expired.",
4658 piaddr(addr->address));
4659 else
4660 log_info("PRC: Prefix %s/%u expired.",
4661 piaddr(addr->address),
4662 (unsigned) addr->plen);
4663
4664 #if defined (NSUPDATE)
4665 /* We remove DNS records at depref time, but
4666 * it is possible that we might get here
4667 * without depreffing.
4668 */
4669 if ((ia->ia_type == D6O_IA_NA) &&
4670 client->config->do_forward_update &&
4671 !(addr->flags & DHC6_ADDR_DEPREFFED))
4672 client_dns_remove(client,
4673 &addr->address);
4674 #endif
4675
4676 continue;
4677 }
4678
4679 has_addrs = ISC_TRUE;
4680 }
4681 }
4682
4683 /* Clean up empty leases. */
4684 if (has_addrs == ISC_FALSE) {
4685 log_info("PRC: Bound lease is devoid of active addresses."
4686 " Re-initializing.");
4687
4688 dhc6_lease_destroy(&lease, MDL);
4689 client->active_lease = NULL;
4690
4691 start_init6(client);
4692 return;
4693 }
4694
4695 /* Schedule the next run through. */
4696 dhc6_check_times(client);
4697 }
4698
4699 /*
4700 * Run client script to unconfigure interface.
4701 * Called with reason STOP6 when dhclient -x is run, or with reason
4702 * RELEASE6 when server has replied to a Release message.
4703 * Stateless is a special case.
4704 */
4705 void
unconfigure6(struct client_state * client,const char * reason)4706 unconfigure6(struct client_state *client, const char *reason)
4707 {
4708 struct dhc6_ia *ia;
4709 struct dhc6_addr *addr;
4710
4711 if (stateless) {
4712 script_init(client, reason, NULL);
4713 if (client->active_lease != NULL)
4714 script_write_params6(client, "old_",
4715 client->active_lease->options);
4716 script_write_requested6(client);
4717 script_go(client);
4718 return;
4719 }
4720
4721 if (client->active_lease == NULL)
4722 return;
4723
4724 for (ia = client->active_lease->bindings ; ia != NULL ; ia = ia->next) {
4725 if (ia->ia_type == D6O_IA_TA)
4726 continue;
4727
4728 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4729 script_init(client, reason, NULL);
4730 dhc6_marshall_values("old_", client,
4731 client->active_lease, ia, addr);
4732 script_write_requested6(client);
4733 script_go(client);
4734
4735 #if defined (NSUPDATE)
4736 if ((ia->ia_type == D6O_IA_NA) &&
4737 client->config->do_forward_update)
4738 client_dns_remove(client, &addr->address);
4739 #endif
4740 }
4741 }
4742 }
4743
4744 static void
refresh_info_request6(void * input)4745 refresh_info_request6(void *input)
4746 {
4747 struct client_state *client;
4748
4749 client = (struct client_state *)input;
4750 start_info_request6(client);
4751 }
4752
4753 /* Timeout for Information-Request (using the IRT option).
4754 */
4755 static void
dhc6_check_irt(struct client_state * client)4756 dhc6_check_irt(struct client_state *client)
4757 {
4758 struct option **req;
4759 struct option_cache *oc;
4760 TIME expire = MAX_TIME;
4761 struct timeval tv;
4762 int i;
4763 isc_boolean_t found = ISC_FALSE;
4764
4765 cancel_timeout(refresh_info_request6, client);
4766
4767 req = client->config->requested_options;
4768 for (i = 0; req[i] != NULL; i++) {
4769 if (req[i] == irt_option) {
4770 found = ISC_TRUE;
4771 break;
4772 }
4773 }
4774 /* Simply return gives a endless loop waiting for nothing. */
4775 if (!found)
4776 exit(0);
4777
4778 oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
4779 D6O_INFORMATION_REFRESH_TIME);
4780 if (oc != NULL) {
4781 struct data_string irt;
4782
4783 memset(&irt, 0, sizeof(irt));
4784 if (!evaluate_option_cache(&irt, NULL, NULL, client,
4785 client->active_lease->options,
4786 NULL, &global_scope, oc, MDL) ||
4787 (irt.len < 4)) {
4788 log_error("Can't evaluate IRT.");
4789 } else {
4790 expire = getULong(irt.data);
4791 if (expire < IRT_MINIMUM)
4792 expire = IRT_MINIMUM;
4793 if (expire == 0xffffffff)
4794 expire = MAX_TIME;
4795 }
4796 data_string_forget(&irt, MDL);
4797 } else
4798 expire = IRT_DEFAULT;
4799
4800 if (expire != MAX_TIME) {
4801 log_debug("PRC: Refresh event scheduled in %u seconds.",
4802 (unsigned) expire);
4803 tv.tv_sec = cur_time + expire;
4804 tv.tv_usec = 0;
4805 add_timeout(&tv, refresh_info_request6, client, NULL, NULL);
4806 }
4807 }
4808
4809 /* We got a Reply. Give dhclient-script a tickle to inform it about
4810 * the new values, and then lay in wait for the next event.
4811 */
4812 static void
start_informed(struct client_state * client)4813 start_informed(struct client_state *client)
4814 {
4815 client->v6_handler = informed_handler;
4816
4817 log_debug("PRC: Done.");
4818
4819 client->state = S_BOUND;
4820
4821 script_init(client, "RENEW6", NULL);
4822 if (client->old_lease != NULL)
4823 script_write_params6(client, "old_",
4824 client->old_lease->options);
4825 script_write_params6(client, "new_", client->active_lease->options);
4826 script_write_requested6(client);
4827 script_go(client);
4828
4829 go_daemon();
4830
4831 if (client->old_lease != NULL) {
4832 dhc6_lease_destroy(&client->old_lease, MDL);
4833 client->old_lease = NULL;
4834 }
4835
4836 /* Schedule events. */
4837 dhc6_check_irt(client);
4838 }
4839
4840 /* While informed, ignore packets.
4841 */
4842 void
informed_handler(struct packet * packet,struct client_state * client)4843 informed_handler(struct packet *packet, struct client_state *client)
4844 {
4845 log_debug("RCV: Input packets are ignored once bound.");
4846 }
4847
4848 /* make_client6_options() fetches option caches relevant to the client's
4849 * scope and places them into the sent_options cache. This cache is later
4850 * used to populate DHCPv6 output packets with options.
4851 */
4852 static void
make_client6_options(struct client_state * client,struct option_state ** op,struct dhc6_lease * lease,u_int8_t message)4853 make_client6_options(struct client_state *client, struct option_state **op,
4854 struct dhc6_lease *lease, u_int8_t message)
4855 {
4856 struct option_cache *oc;
4857 struct option **req;
4858 struct buffer *buffer;
4859 int buflen, i, oro_len;
4860
4861 if ((op == NULL) || (client == NULL))
4862 return;
4863
4864 if (*op)
4865 option_state_dereference(op, MDL);
4866
4867 /* Create a cache to carry options to transmission. */
4868 option_state_allocate(op, MDL);
4869
4870 /* Create and store an 'elapsed time' option in the cache. */
4871 oc = NULL;
4872 if (option_cache_allocate(&oc, MDL)) {
4873 const unsigned char *cdata;
4874
4875 cdata = (unsigned char *)&client->elapsed;
4876
4877 if (make_const_data(&oc->expression, cdata, 2, 0, 0, MDL)) {
4878 option_reference(&oc->option, elapsed_option, MDL);
4879 save_option(&dhcpv6_universe, *op, oc);
4880 }
4881
4882 option_cache_dereference(&oc, MDL);
4883 }
4884
4885 /* Bring in any configured options to send. */
4886 if (client->config->on_transmission)
4887 execute_statements_in_scope(NULL, NULL, NULL, client,
4888 lease ? lease->options : NULL,
4889 *op, &global_scope,
4890 client->config->on_transmission,
4891 NULL, NULL);
4892
4893 /* Rapid-commit is only for SOLICITs. */
4894 if (message != DHCPV6_SOLICIT)
4895 delete_option(&dhcpv6_universe, *op, D6O_RAPID_COMMIT);
4896
4897 /* See if the user configured a DUID in a relevant scope. If not,
4898 * introduce our default manufactured id.
4899 */
4900 if ((oc = lookup_option(&dhcpv6_universe, *op,
4901 D6O_CLIENTID)) == NULL) {
4902 if (!option_cache(&oc, &default_duid, NULL, clientid_option,
4903 MDL))
4904 log_fatal("Failure assembling a DUID.");
4905
4906 save_option(&dhcpv6_universe, *op, oc);
4907 option_cache_dereference(&oc, MDL);
4908 }
4909
4910 /* In cases where we're responding to a single server, put the
4911 * server's id in the response.
4912 *
4913 * Note that lease is NULL for SOLICIT or INFO request messages,
4914 * and otherwise MUST be present.
4915 */
4916 if (lease == NULL) {
4917 if ((message != DHCPV6_SOLICIT) &&
4918 (message != DHCPV6_INFORMATION_REQUEST))
4919 log_fatal("Impossible condition at %s:%d.", MDL);
4920 } else if ((message != DHCPV6_REBIND) &&
4921 (message != DHCPV6_CONFIRM)) {
4922 oc = lookup_option(&dhcpv6_universe, lease->options,
4923 D6O_SERVERID);
4924 if (oc != NULL)
4925 save_option(&dhcpv6_universe, *op, oc);
4926 }
4927
4928 /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
4929 * deprecated by adjustments to the 'request' syntax also used for
4930 * DHCPv4.
4931 */
4932 if (lookup_option(&dhcpv6_universe, *op, D6O_ORO) != NULL)
4933 log_error("'send dhcp6.oro' syntax is deprecated, please "
4934 "use the 'request' syntax (\"man dhclient.conf\").");
4935
4936 /* Construct and store an ORO (Option Request Option). It is a
4937 * fatal error to fail to send an ORO (of at least zero length).
4938 *
4939 * Discussion: RFC3315 appears to be inconsistent in its statements
4940 * of whether or not the ORO is mandatory. In section 18.1.1
4941 * ("Creation and Transmission of Request Messages"):
4942 *
4943 * The client MUST include an Option Request option (see section
4944 * 22.7) to indicate the options the client is interested in
4945 * receiving. The client MAY include options with data values as
4946 * hints to the server about parameter values the client would like
4947 * to have returned.
4948 *
4949 * This MUST is missing from the creation/transmission of other
4950 * messages (such as Renew and Rebind), and the section 22.7 ("Option
4951 * Request Option" format and definition):
4952 *
4953 * A client MAY include an Option Request option in a Solicit,
4954 * Request, Renew, Rebind, Confirm or Information-request message to
4955 * inform the server about options the client wants the server to
4956 * send to the client. A server MAY include an Option Request
4957 * option in a Reconfigure option to indicate which options the
4958 * client should request from the server.
4959 *
4960 * seems to relax the requirement from MUST to MAY (and still other
4961 * language in RFC3315 supports this).
4962 *
4963 * In lieu of a clarification of RFC3315, we will conform with the
4964 * MUST. Instead of an absent ORO, we will if there are no options
4965 * to request supply an empty ORO. Theoretically, an absent ORO is
4966 * difficult to interpret (does the client want all options or no
4967 * options?). A zero-length ORO is intuitively clear: requesting
4968 * nothing.
4969 */
4970 buffer = NULL;
4971 oro_len = 0;
4972 buflen = 32;
4973 if (!buffer_allocate(&buffer, buflen, MDL))
4974 log_fatal("Out of memory constructing DHCPv6 ORO.");
4975 req = client->config->requested_options;
4976 if (req != NULL) {
4977 for (i = 0 ; req[i] != NULL ; i++) {
4978 if (buflen == oro_len) {
4979 struct buffer *tmpbuf = NULL;
4980
4981 buflen += 32;
4982
4983 /* Shell game. */
4984 buffer_reference(&tmpbuf, buffer, MDL);
4985 buffer_dereference(&buffer, MDL);
4986
4987 if (!buffer_allocate(&buffer, buflen, MDL))
4988 log_fatal("Out of memory resizing "
4989 "DHCPv6 ORO buffer.");
4990
4991 memcpy(buffer->data, tmpbuf->data, oro_len);
4992
4993 buffer_dereference(&tmpbuf, MDL);
4994 }
4995
4996 if (req[i]->universe == &dhcpv6_universe) {
4997 /* Append the code to the ORO. */
4998 putUShort(buffer->data + oro_len,
4999 req[i]->code);
5000 oro_len += 2;
5001 }
5002 }
5003 }
5004
5005 oc = NULL;
5006 if (make_const_option_cache(&oc, &buffer, NULL, oro_len,
5007 oro_option, MDL)) {
5008 save_option(&dhcpv6_universe, *op, oc);
5009 } else {
5010 log_fatal("Unable to create ORO option cache.");
5011 }
5012
5013 /*
5014 * Note: make_const_option_cache() consumes the buffer, we do not
5015 * need to dereference it (XXX).
5016 */
5017 option_cache_dereference(&oc, MDL);
5018 }
5019
5020 /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
5021 * filename, server-name, etc specifics.
5022 *
5023 * Simply, store all values present in all universes of the option state
5024 * (probably derived from a DHCPv6 packet) into environment variables
5025 * named after the option names (and universe names) but with the 'prefix'
5026 * prepended.
5027 *
5028 * Later, dhclient-script may compare for example "new_time_servers" and
5029 * "old_time_servers" for differences, and only upon detecting a change
5030 * bother to rewrite ntp.conf and restart it. Or something along those
5031 * generic lines.
5032 */
5033 static void
script_write_params6(struct client_state * client,const char * prefix,struct option_state * options)5034 script_write_params6(struct client_state *client, const char *prefix,
5035 struct option_state *options)
5036 {
5037 struct envadd_state es;
5038 int i;
5039
5040 if (options == NULL)
5041 return;
5042
5043 es.client = client;
5044 es.prefix = prefix;
5045
5046 for (i = 0 ; i < options->universe_count ; i++) {
5047 option_space_foreach(NULL, NULL, client, NULL, options,
5048 &global_scope, universes[i], &es,
5049 client_option_envadd);
5050 }
5051 }
5052
5053 /*
5054 * A clone of the DHCPv4 routine.
5055 * Write out the environment variables for the objects that the
5056 * client requested. If the object was requested the variable will be:
5057 * requested_<option_name>=1
5058 * If it wasn't requested there won't be a variable.
5059 */
script_write_requested6(client)5060 static void script_write_requested6(client)
5061 struct client_state *client;
5062 {
5063 int i;
5064 struct option **req;
5065 char name[256];
5066 req = client->config->requested_options;
5067
5068 if (req == NULL)
5069 return;
5070
5071 for (i = 0 ; req[i] != NULL ; i++) {
5072 if ((req[i]->universe == &dhcpv6_universe) &&
5073 dhcp_option_ev_name (name, sizeof(name), req[i])) {
5074 client_envadd(client, "requested_", name, "%d", 1);
5075 }
5076 }
5077 }
5078
5079 /*
5080 * Check if there is something not fully defined in the active lease.
5081 */
5082 static isc_boolean_t
active_prefix(struct client_state * client)5083 active_prefix(struct client_state *client)
5084 {
5085 struct dhc6_lease *lease;
5086 struct dhc6_ia *ia;
5087 struct dhc6_addr *pref;
5088 char zeros[16];
5089
5090 lease = client->active_lease;
5091 if (lease == NULL)
5092 return ISC_FALSE;
5093 memset(zeros, 0, 16);
5094 for (ia = lease->bindings; ia != NULL; ia = ia->next) {
5095 if (ia->ia_type != D6O_IA_PD)
5096 continue;
5097 for (pref = ia->addrs; pref != NULL; pref = pref->next) {
5098 if (pref->plen == 0)
5099 return ISC_FALSE;
5100 if (pref->address.len != 16)
5101 return ISC_FALSE;
5102 if (memcmp(pref->address.iabuf, zeros, 16) == 0)
5103 return ISC_FALSE;
5104 }
5105 }
5106 return ISC_TRUE;
5107 }
5108 #endif /* DHCPv6 */
5109