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