]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc3315.c
reconfirm SLAAC addresses when DHCPv4 leases go though INIT_REBOOT state.
[people/ms/dnsmasq.git] / src / rfc3315.c
1 /* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
18 #include "dnsmasq.h"
19
20 #ifdef HAVE_DHCP6
21
22 static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **relay_tagsp, struct dhcp_context *context,
23 int interface, char *iface_name, struct in6_addr *fallback, void *inbuff, size_t sz, int is_unicast, time_t now);
24 static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dhcp_netid *tags, struct dhcp_context *context,
25 int interface, char *iface_name, struct in6_addr *fallback, void *inbuff, size_t sz, int is_unicast, time_t now);
26 static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
27 static void log6_packet(char *type, unsigned char *clid, int clid_len, struct in6_addr *addr, int xid, char *iface, char *string);
28
29 static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize);
30 static void *opt6_next(void *opts, void *end);
31 static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
32
33 #define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
34 #define opt6_type(opt) (opt6_uint(opt, -4, 2))
35 #define opt6_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[4+(i)]))
36
37
38 unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
39 struct in6_addr *fallback, size_t sz, int is_unicast, time_t now)
40 {
41 struct dhcp_netid *relay_tags = NULL;
42 struct dhcp_vendor *vendor;
43 int msg_type;
44
45 if (sz <= 4)
46 return 0;
47
48 msg_type = *((unsigned char *)daemon->dhcp_packet.iov_base);
49
50 /* Mark these so we only match each at most once, to avoid tangled linked lists */
51 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
52 vendor->netid.next = &vendor->netid;
53
54 save_counter(0);
55
56 if (dhcp6_maybe_relay(NULL, &relay_tags, context, interface, iface_name, fallback, daemon->dhcp_packet.iov_base, sz, is_unicast, now))
57 return msg_type == DHCP6RELAYFORW ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
58
59 return 0;
60 }
61
62 /* This cost me blood to write, it will probably cost you blood to understand - srk. */
63 static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **relay_tagsp, struct dhcp_context *context,
64 int interface, char *iface_name, struct in6_addr *fallback, void *inbuff, size_t sz, int is_unicast, time_t now)
65 {
66 void *end = inbuff + sz;
67 void *opts = inbuff + 34;
68 int msg_type = *((unsigned char *)inbuff);
69 unsigned char *outmsgtypep;
70 void *opt;
71 struct dhcp_vendor *vendor;
72
73 /* if not an encaplsulated relayed message, just do the stuff */
74 if (msg_type != DHCP6RELAYFORW)
75 {
76 /* if link_address != NULL if points to the link address field of the
77 innermost nested RELAYFORW message, which is where we find the
78 address of the network on which we can allocate an address.
79 Recalculate the available contexts using that information. */
80
81 if (link_address)
82 {
83 struct dhcp_context *c;
84 context = NULL;
85
86 for (c = daemon->dhcp6; c; c = c->next)
87 if (!IN6_IS_ADDR_LOOPBACK(link_address) &&
88 !IN6_IS_ADDR_LINKLOCAL(link_address) &&
89 !IN6_IS_ADDR_MULTICAST(link_address) &&
90 is_same_net6(link_address, &c->start6, c->prefix) &&
91 is_same_net6(link_address, &c->end6, c->prefix))
92 {
93 c->current = context;
94 context = c;
95 }
96
97 if (!context)
98 {
99 inet_ntop(AF_INET6, link_address, daemon->addrbuff, ADDRSTRLEN);
100 my_syslog(MS_DHCP | LOG_WARNING,
101 _("no address range available for DHCPv6 request from relay at %s"),
102 daemon->addrbuff);
103 return 0;
104 }
105 }
106
107 if (!context)
108 {
109 my_syslog(MS_DHCP | LOG_WARNING,
110 _("no address range available for DHCPv6 request via %s"), iface_name);
111 return 0;
112 }
113
114 return dhcp6_no_relay(msg_type, link_address, *relay_tagsp, context, interface, iface_name, fallback, inbuff, sz, is_unicast, now);
115 }
116
117 /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
118 which is 1 + 1 + 16 + 16 + 2 + 2 = 38 */
119 if (sz < 38)
120 return 0;
121
122 /* copy header stuff into reply message and set type to reply */
123 outmsgtypep = put_opt6(inbuff, 34);
124 *outmsgtypep = DHCP6RELAYREPL;
125
126 /* look for relay options and set tags if found. */
127 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
128 {
129 int mopt;
130
131 if (vendor->match_type == MATCH_SUBSCRIBER)
132 mopt = OPTION6_SUBSCRIBER_ID;
133 else if (vendor->match_type == MATCH_REMOTE)
134 mopt = OPTION6_REMOTE_ID;
135 else
136 continue;
137
138 if ((opt = opt6_find(opts, end, mopt, 1)) &&
139 vendor->len == opt6_len(opt) &&
140 memcmp(vendor->data, opt6_ptr(opt, 0), vendor->len) == 0 &&
141 vendor->netid.next != &vendor->netid)
142 {
143 vendor->netid.next = *relay_tagsp;
144 *relay_tagsp = &vendor->netid;
145 break;
146 }
147 }
148
149 for (opt = opts; opt; opt = opt6_next(opt, end))
150 {
151 int o = new_opt6(opt6_type(opt));
152 if (opt6_type(opt) == OPTION6_RELAY_MSG)
153 {
154 struct in6_addr link_address;
155 /* the packet data is unaligned, copy to aligned storage */
156 memcpy(&link_address, inbuff + 2, IN6ADDRSZ);
157 /* Not, zero is_unicast since that is now known to refer to the
158 relayed packet, not the original sent by the client */
159 if (!dhcp6_maybe_relay(&link_address, relay_tagsp, context, interface, iface_name, fallback, opt6_ptr(opt, 0), opt6_len(opt), 0, now))
160 return 0;
161 }
162 else
163 put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
164 end_opt6(o);
165 }
166
167 return 1;
168 }
169
170 static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dhcp_netid *tags, struct dhcp_context *context,
171 int interface, char *iface_name, struct in6_addr *fallback, void *inbuff, size_t sz, int is_unicast, time_t now)
172 {
173 void *packet_options = inbuff + 4;
174 void *end = inbuff + sz;
175 void *opt, *oro;
176 int i, o, o1;
177 unsigned char *clid = NULL;
178 int clid_len = 0, start_opts;
179 struct dhcp_netid *tagif, *context_tags = NULL;
180 char *client_hostname= NULL, *hostname = NULL;
181 char *domain = NULL, *send_domain = NULL;
182 struct dhcp_config *config = NULL;
183 struct dhcp_netid known_id, iface_id;
184 int done_dns = 0, hostname_auth = 0, do_encap = 0;
185 unsigned char *outmsgtypep;
186 struct dhcp_opt *opt_cfg;
187 struct dhcp_vendor *vendor;
188 struct dhcp_context *context_tmp;
189 unsigned int xid, ignore = 0;
190 unsigned int fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
191
192 /* set tag with name == interface */
193 iface_id.net = iface_name;
194 iface_id.next = tags;
195 tags = &iface_id;
196
197 /* copy over transaction-id, and save pointer to message type */
198 outmsgtypep = put_opt6(inbuff, 4);
199 start_opts = save_counter(-1);
200 xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
201
202 /* We're going to be linking tags from all context we use.
203 mark them as unused so we don't link one twice and break the list */
204 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
205 {
206 context->netid.next = &context->netid;
207
208 if (option_bool(OPT_LOG_OPTS))
209 {
210 inet_ntop(AF_INET6, &context_tmp->start6, daemon->dhcp_buff, ADDRSTRLEN);
211 inet_ntop(AF_INET6, &context_tmp->end6, daemon->dhcp_buff2, ADDRSTRLEN);
212 if (context_tmp->flags & (CONTEXT_STATIC))
213 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCPv6 subnet: %s/%d"),
214 xid, daemon->dhcp_buff, context_tmp->prefix);
215 else
216 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
217 xid, daemon->dhcp_buff, daemon->dhcp_buff2);
218 }
219 }
220
221 if ((opt = opt6_find(packet_options, end, OPTION6_CLIENT_ID, 1)))
222 {
223 clid = opt6_ptr(opt, 0);
224 clid_len = opt6_len(opt);
225 o = new_opt6(OPTION6_CLIENT_ID);
226 put_opt6(clid, clid_len);
227 end_opt6(o);
228 }
229 else if (msg_type != DHCP6IREQ)
230 return 0;
231
232 /* server-id must match except for SOLICIT and CONFIRM messages */
233 if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ &&
234 (!(opt = opt6_find(packet_options, end, OPTION6_SERVER_ID, 1)) ||
235 opt6_len(opt) != daemon->duid_len ||
236 memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
237 return 0;
238
239 o = new_opt6(OPTION6_SERVER_ID);
240 put_opt6(daemon->duid, daemon->duid_len);
241 end_opt6(o);
242
243 if (is_unicast &&
244 (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
245
246 {
247 o1 = new_opt6(OPTION6_STATUS_CODE);
248 put_opt6_short(DHCP6USEMULTI);
249 put_opt6_string("Use multicast");
250 end_opt6(o1);
251 return 1;
252 }
253
254 /* match vendor and user class options */
255 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
256 {
257 int mopt;
258
259 if (vendor->match_type == MATCH_VENDOR)
260 mopt = OPTION6_VENDOR_CLASS;
261 else if (vendor->match_type == MATCH_USER)
262 mopt = OPTION6_USER_CLASS;
263 else
264 continue;
265
266 if ((opt = opt6_find(packet_options, end, mopt, 2)))
267 {
268 void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
269 int offset = 0;
270
271 if (mopt == OPTION6_VENDOR_CLASS)
272 {
273 if (opt6_len(opt) < 4)
274 continue;
275
276 if (vendor->enterprise != opt6_uint(opt, 0, 4))
277 continue;
278
279 offset = 4;
280 }
281
282 for (enc_opt = opt6_ptr(opt, offset); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
283 for (i = 0; i <= (opt6_len(enc_opt) - vendor->len); i++)
284 if (memcmp(vendor->data, opt6_ptr(enc_opt, i), vendor->len) == 0)
285 {
286 vendor->netid.next = tags;
287 tags = &vendor->netid;
288 break;
289 }
290 }
291 }
292
293 if (option_bool(OPT_LOG_OPTS) && (opt = opt6_find(packet_options, end, OPTION6_VENDOR_CLASS, 4)))
294 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %u"), xid, opt6_uint(opt, 0, 4));
295
296 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
297 Otherwise assume the option is an array, and look for a matching element.
298 If no data given, existance of the option is enough. This code handles
299 V-I opts too. */
300 for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
301 {
302 int match = 0;
303
304 if (opt_cfg->flags & DHOPT_RFC3925)
305 {
306 for (opt = opt6_find(packet_options, end, OPTION6_VENDOR_OPTS, 4);
307 opt;
308 opt = opt6_find(opt6_next(opt, end), end, OPTION6_VENDOR_OPTS, 4))
309 {
310 void *vopt;
311 void *vend = opt6_ptr(opt, opt6_len(opt));
312
313 for (vopt = opt6_find(opt6_ptr(opt, 4), vend, opt_cfg->opt, 0);
314 vopt;
315 vopt = opt6_find(opt6_next(vopt, vend), vend, opt_cfg->opt, 0))
316 if ((match = match_bytes(opt_cfg, opt6_ptr(vopt, 0), opt6_len(vopt))))
317 break;
318 }
319 if (match)
320 break;
321 }
322 else
323 {
324 if (!(opt = opt6_find(packet_options, end, opt_cfg->opt, 1)))
325 continue;
326
327 match = match_bytes(opt_cfg, opt6_ptr(opt, 0), opt6_len(opt));
328 }
329
330 if (match)
331 {
332 opt_cfg->netid->next = tags;
333 tags = opt_cfg->netid;
334 }
335 }
336
337 if ((opt = opt6_find(packet_options, end, OPTION6_FQDN, 1)))
338 {
339 /* RFC4704 refers */
340 int len = opt6_len(opt) - 1;
341
342 fqdn_flags = opt6_uint(opt, 0, 1);
343
344 /* Always force update, since the client has no way to do it itself. */
345 if (!option_bool(OPT_FQDN_UPDATE) && !(fqdn_flags & 0x01))
346 fqdn_flags |= 0x03;
347
348 fqdn_flags &= ~0x04;
349
350 if (len != 0 && len < 255)
351 {
352 unsigned char *pp, *op = opt6_ptr(opt, 1);
353 char *pq = daemon->dhcp_buff;
354
355 pp = op;
356 while (*op != 0 && ((op + (*op)) - pp) < len)
357 {
358 memcpy(pq, op+1, *op);
359 pq += *op;
360 op += (*op)+1;
361 *(pq++) = '.';
362 }
363
364 if (pq != daemon->dhcp_buff)
365 pq--;
366 *pq = 0;
367
368 if (legal_hostname(daemon->dhcp_buff))
369 {
370 client_hostname = daemon->dhcp_buff;
371 if (option_bool(OPT_LOG_OPTS))
372 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), xid, client_hostname);
373 }
374 }
375 }
376
377 if (clid)
378 {
379 config = find_config6(daemon->dhcp_conf, context, clid, clid_len, NULL);
380
381 if (have_config(config, CONFIG_NAME))
382 {
383 hostname = config->hostname;
384 domain = config->domain;
385 hostname_auth = 1;
386 }
387 else if (client_hostname)
388 {
389 domain = strip_hostname(client_hostname);
390
391 if (strlen(client_hostname) != 0)
392 {
393 hostname = client_hostname;
394 if (!config)
395 {
396 /* Search again now we have a hostname.
397 Only accept configs without CLID here, (it won't match)
398 to avoid impersonation by name. */
399 struct dhcp_config *new = find_config6(daemon->dhcp_conf, context, NULL, 0, hostname);
400 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
401 config = new;
402 }
403 }
404 }
405 }
406
407 if (config)
408 {
409 struct dhcp_netid_list *list;
410
411 for (list = config->netid; list; list = list->next)
412 {
413 list->list->next = tags;
414 tags = list->list;
415 }
416
417 /* set "known" tag for known hosts */
418 known_id.net = "known";
419 known_id.next = tags;
420 tags = &known_id;
421
422 if (have_config(config, CONFIG_DISABLE))
423 ignore = 1;
424 }
425
426 tagif = run_tag_if(tags);
427
428 /* if all the netids in the ignore list are present, ignore this client */
429 if (daemon->dhcp_ignore)
430 {
431 struct dhcp_netid_list *id_list;
432
433 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
434 if (match_netid(id_list->list, tagif, 0))
435 ignore = 1;
436 }
437
438 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
439 if (!hostname_auth)
440 {
441 struct dhcp_netid_list *id_list;
442
443 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
444 if ((!id_list->list) || match_netid(id_list->list, tagif, 0))
445 break;
446 if (id_list)
447 hostname = NULL;
448 }
449
450
451 switch (msg_type)
452 {
453 default:
454 return 0;
455
456 case DHCP6SOLICIT:
457 case DHCP6REQUEST:
458 {
459 void *rapid_commit = opt6_find(packet_options, end, OPTION6_RAPID_COMMIT, 0);
460 int make_lease = (msg_type == DHCP6REQUEST || rapid_commit);
461 int serial = 0, used_config = 0;
462
463 if (rapid_commit)
464 {
465 o = new_opt6(OPTION6_RAPID_COMMIT);
466 end_opt6(o);
467 }
468
469 /* set reply message type */
470 *outmsgtypep = make_lease ? DHCP6REPLY : DHCP6ADVERTISE;
471
472 log6_packet(msg_type == DHCP6SOLICIT ? "DHCPSOLICIT" : "DHCPREQUEST",
473 clid, clid_len, NULL, xid, iface_name, ignore ? "ignored" : NULL);
474
475 if (ignore)
476 return 0;
477
478 for (opt = packet_options; opt; opt = opt6_next(opt, end))
479 {
480 int iaid, ia_type = opt6_type(opt);
481 void *ia_option, *ia_end;
482 unsigned int min_time = 0xffffffff;
483 int t1cntr = 0;
484 int address_assigned = 0;
485
486 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
487 continue;
488
489 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
490 continue;
491
492 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
493 continue;
494
495 iaid = opt6_uint(opt, 0, 4);
496 ia_end = opt6_ptr(opt, opt6_len(opt));
497 ia_option = opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
498
499 /* reset "USED" flags on leases */
500 lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
501
502 o = new_opt6(ia_type);
503 put_opt6_long(iaid);
504 if (ia_type == OPTION6_IA_NA)
505 {
506 /* save pointer */
507 t1cntr = save_counter(-1);
508 /* so we can fill these in later */
509 put_opt6_long(0);
510 put_opt6_long(0);
511 }
512
513 while (1)
514 {
515 struct in6_addr alloced_addr, *addrp = NULL;
516 u32 requested_time = 0;
517 struct dhcp_lease *lease = NULL;
518
519 if (ia_option)
520 {
521 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
522 requested_time = opt6_uint(ia_option, 16, 4);
523
524 if (!address6_available(context, req_addr, tags) &&
525 (!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0))
526 {
527 if (msg_type == DHCP6REQUEST)
528 {
529 /* host has a lease, but it's not on the correct link */
530 o1 = new_opt6(OPTION6_STATUS_CODE);
531 put_opt6_short(DHCP6NOTONLINK);
532 put_opt6_string("Not on link");
533 end_opt6(o1);
534 }
535 }
536 else if ((lease = lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
537 iaid, req_addr)) &&
538 (clid_len != lease->clid_len ||
539 memcmp(clid, lease->clid, clid_len) != 0))
540 {
541 /* Address leased to another DUID */
542 o1 = new_opt6(OPTION6_STATUS_CODE);
543 put_opt6_short(DHCP6UNSPEC);
544 put_opt6_string("Address in use");
545 end_opt6(o1);
546 }
547 else
548 addrp = req_addr;
549 }
550 else
551 {
552 /* must have an address to CONFIRM */
553 if (msg_type == DHCP6REQUEST && ia_type == OPTION6_IA_NA)
554 return 0;
555
556 /* Don't used configured addresses for temporary leases. */
557 if (have_config(config, CONFIG_ADDR6) && !used_config && ia_type == OPTION6_IA_NA)
558 {
559 struct dhcp_lease *ltmp = lease6_find_by_addr(&config->addr6, 128, 0);
560
561 used_config = 1;
562 inet_ntop(AF_INET6, &config->addr6, daemon->addrbuff, ADDRSTRLEN);
563
564 if (ltmp && ltmp->clid &&
565 (ltmp->clid_len != clid_len || memcmp(ltmp->clid, clid, clid_len) != 0))
566 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
567 daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len));
568 else if (have_config(config, CONFIG_DECLINED) &&
569 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
570 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
571 daemon->addrbuff);
572 else
573 addrp = &config->addr6;
574 }
575
576 /* existing lease */
577 if (!addrp &&
578 (lease = lease6_find(clid, clid_len,
579 ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL)) &&
580 address6_available(context, (struct in6_addr *)&lease->hwaddr, tags) &&
581 !config_find_by_address6(daemon->dhcp_conf, (struct in6_addr *)&lease->hwaddr, 128, 0))
582 addrp = (struct in6_addr *)&lease->hwaddr;
583
584 if (!addrp && address6_allocate(context, clid, clid_len, serial++, tags, &alloced_addr))
585 addrp = &alloced_addr;
586 }
587
588 if (addrp)
589 {
590 unsigned int lease_time;
591 struct dhcp_context *this_context;
592 struct dhcp_config *valid_config = config;
593
594 /* don't use a config to set lease time if it specifies an address which isn't this. */
595 if (have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, addrp, IN6ADDRSZ) != 0)
596 valid_config = NULL;
597
598 address_assigned = 1;
599
600 /* shouldn't ever fail */
601 if ((this_context = narrow_context6(context, addrp, tagif)))
602 {
603 /* get tags from context if we've not used it before */
604 if (this_context->netid.next == &this_context->netid && this_context->netid.net)
605 {
606 this_context->netid.next = context_tags;
607 context_tags = &this_context->netid;
608 if (!hostname_auth)
609 {
610 struct dhcp_netid_list *id_list;
611
612 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
613 if ((!id_list->list) || match_netid(id_list->list, &this_context->netid, 0))
614 break;
615 if (id_list)
616 hostname = NULL;
617 }
618 }
619
620 lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
621
622 if (ia_option)
623 {
624 if (requested_time < 120u )
625 requested_time = 120u; /* sanity */
626 if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
627 lease_time = requested_time;
628 }
629
630 if (lease_time < min_time)
631 min_time = lease_time;
632
633 /* May fail to create lease */
634 if (!lease && make_lease)
635 lease = lease6_allocate(addrp, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
636
637 if (lease)
638 {
639 lease_set_expires(lease, lease_time, now);
640 lease_set_hwaddr(lease, NULL, clid, 0, iaid, clid_len, now, 0);
641 lease_set_interface(lease, interface, now);
642 if (hostname && ia_type == OPTION6_IA_NA)
643 {
644 char *addr_domain = get_domain6(addrp);
645 if (!send_domain)
646 send_domain = addr_domain;
647 lease_set_hostname(lease, hostname, hostname_auth, addr_domain, domain);
648 }
649
650 #ifdef HAVE_SCRIPT
651 if (daemon->lease_change_command)
652 {
653 void *class_opt;
654 lease->flags |= LEASE_CHANGED;
655 free(lease->extradata);
656 lease->extradata = NULL;
657 lease->extradata_size = lease->extradata_len = 0;
658 lease->hwaddr_len = 0; /* surrogate for no of vendor classes */
659
660 if ((class_opt = opt6_find(packet_options, end, OPTION6_VENDOR_CLASS, 4)))
661 {
662 void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
663 lease->hwaddr_len++;
664 /* send enterprise number first */
665 sprintf(daemon->dhcp_buff2, "%u", opt6_uint(class_opt, 0, 4));
666 lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
667
668 if (opt6_len(class_opt) >= 6)
669 for (enc_opt = opt6_ptr(class_opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
670 {
671 lease->hwaddr_len++;
672 lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
673 }
674 }
675
676 lease_add_extradata(lease, (unsigned char *)client_hostname,
677 client_hostname ? strlen(client_hostname) : 0, 0);
678
679 /* space-concat tag set */
680 if (!tagif && !context_tags)
681 lease_add_extradata(lease, NULL, 0, 0);
682 else
683 {
684 struct dhcp_netid *n, *l, *tmp = tags;
685
686 /* link temporarily */
687 for (n = context_tags; n && n->next; n = n->next);
688 if ((l = n))
689 {
690 l->next = tags;
691 tmp = context_tags;
692 }
693
694 for (n = run_tag_if(tmp); n; n = n->next)
695 {
696 struct dhcp_netid *n1;
697 /* kill dupes */
698 for (n1 = n->next; n1; n1 = n1->next)
699 if (strcmp(n->net, n1->net) == 0)
700 break;
701 if (!n1)
702 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
703 }
704
705 /* unlink again */
706 if (l)
707 l->next = NULL;
708 }
709
710 if (link_address)
711 inet_ntop(AF_INET6, link_address, daemon->addrbuff, ADDRSTRLEN);
712
713 lease_add_extradata(lease, (unsigned char *)daemon->addrbuff, link_address ? strlen(daemon->addrbuff) : 0, 0);
714
715 if ((class_opt = opt6_find(packet_options, end, OPTION6_USER_CLASS, 2)))
716 {
717 void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
718 for (enc_opt = opt6_ptr(class_opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
719 lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
720 }
721 }
722 #endif
723
724 }
725 else if (!send_domain)
726 send_domain = get_domain6(addrp);
727
728
729 if (lease || !make_lease)
730 {
731 o1 = new_opt6(OPTION6_IAADDR);
732 put_opt6(addrp, sizeof(*addrp));
733 /* preferred lifetime */
734 put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
735 put_opt6_long(lease_time); /* valid lifetime */
736 end_opt6(o1);
737
738 log6_packet( make_lease ? "DHCPREPLY" : "DHCPADVERTISE",
739 clid, clid_len, addrp, xid, iface_name, hostname);
740 }
741
742 }
743 }
744
745
746 if (!ia_option ||
747 !(ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)))
748 {
749 if (address_assigned)
750 {
751 o1 = new_opt6(OPTION6_STATUS_CODE);
752 put_opt6_short(DHCP6SUCCESS);
753 put_opt6_string("Oh hai from dnsmasq");
754 end_opt6(o1);
755
756 if (ia_type == OPTION6_IA_NA)
757 {
758 /* go back an fill in fields in IA_NA option */
759 unsigned int t1 = min_time == 0xffffffff ? 0xffffffff : min_time/2;
760 unsigned int t2 = min_time == 0xffffffff ? 0xffffffff : (min_time/8) * 7;
761 int sav = save_counter(t1cntr);
762 put_opt6_long(t1);
763 put_opt6_long(t2);
764 save_counter(sav);
765 }
766 }
767 else
768 {
769 /* no address, return error */
770 o1 = new_opt6(OPTION6_STATUS_CODE);
771 put_opt6_short(DHCP6NOADDRS);
772 put_opt6_string("No addresses available");
773 end_opt6(o1);
774 }
775
776 end_opt6(o);
777
778 if (address_assigned)
779 {
780 /* If --dhcp-authoritative is set, we can tell client not to wait for
781 other possible servers */
782 o = new_opt6(OPTION6_PREFERENCE);
783 put_opt6_char(option_bool(OPT_AUTHORITATIVE) ? 255 : 0);
784 end_opt6(o);
785 }
786
787 break;
788 }
789 }
790 }
791
792 break;
793 }
794
795 case DHCP6RENEW:
796 {
797 /* set reply message type */
798 *outmsgtypep = DHCP6REPLY;
799
800 log6_packet("DHCPRENEW", clid, clid_len, NULL, xid, iface_name, NULL);
801
802 for (opt = packet_options; opt; opt = opt6_next(opt, end))
803 {
804 int ia_type = opt6_type(opt);
805 void *ia_option, *ia_end;
806 unsigned int min_time = 0xffffffff;
807 int t1cntr = 0, iacntr;
808 unsigned int iaid;
809
810 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
811 continue;
812
813 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
814 continue;
815
816 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
817 continue;
818
819 iaid = opt6_uint(opt, 0, 4);
820
821 o = new_opt6(ia_type);
822 put_opt6_long(iaid);
823 if (ia_type == OPTION6_IA_NA)
824 {
825 /* save pointer */
826 t1cntr = save_counter(-1);
827 /* so we can fill these in later */
828 put_opt6_long(0);
829 put_opt6_long(0);
830 }
831
832 iacntr = save_counter(-1);
833
834 /* reset "USED" flags on leases */
835 lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
836
837 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
838 ia_end = opt6_ptr(opt, opt6_len(opt));
839
840 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
841 ia_option;
842 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
843 {
844 struct dhcp_lease *lease = NULL;
845 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
846 u32 requested_time = opt6_uint(ia_option, 16, 4);
847 unsigned int lease_time;
848 struct dhcp_context *this_context;
849 struct dhcp_config *valid_config = config;
850
851 /* don't use a config to set lease time if it specifies an address which isn't this. */
852 if (have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0)
853 valid_config = NULL;
854
855 if (!(lease = lease6_find(clid, clid_len,
856 ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
857 iaid, req_addr)))
858 {
859 /* If the server cannot find a client entry for the IA the server
860 returns the IA containing no addresses with a Status Code option set
861 to NoBinding in the Reply message. */
862 save_counter(iacntr);
863 t1cntr = 0;
864
865 log6_packet("DHCPREPLY", clid, clid_len, req_addr, xid, iface_name, "lease not found");
866
867 o1 = new_opt6(OPTION6_STATUS_CODE);
868 put_opt6_short(DHCP6NOBINDING);
869 put_opt6_string("No binding found");
870 end_opt6(o1);
871 break;
872 }
873
874
875 if (!address6_available(context, req_addr, tagif) ||
876 !(this_context = narrow_context6(context, req_addr, tagif)))
877 {
878 lease_time = 0;
879 this_context = NULL;
880 }
881 else
882 {
883 /* get tags from context if we've not used it before */
884 if (this_context->netid.next == &this_context->netid && this_context->netid.net)
885 {
886 this_context->netid.next = context_tags;
887 context_tags = &this_context->netid;
888 if (!hostname_auth)
889 {
890 struct dhcp_netid_list *id_list;
891
892 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
893 if ((!id_list->list) || match_netid(id_list->list, &this_context->netid, 0))
894 break;
895 if (id_list)
896 hostname = NULL;
897 }
898 }
899
900 lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
901
902 if (requested_time < 120u )
903 requested_time = 120u; /* sanity */
904 if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
905 lease_time = requested_time;
906
907 lease_set_expires(lease, lease_time, now);
908 if (ia_type == OPTION6_IA_NA && hostname)
909 {
910 char *addr_domain = get_domain6(req_addr);
911 if (!send_domain)
912 send_domain = addr_domain;
913 lease_set_hostname(lease, hostname, hostname_auth, addr_domain, domain);
914 }
915
916 if (lease_time < min_time)
917 min_time = lease_time;
918 }
919
920 log6_packet("DHCPREPLY", clid, clid_len, req_addr, xid, iface_name, hostname);
921
922 o1 = new_opt6(OPTION6_IAADDR);
923 put_opt6(req_addr, sizeof(*req_addr));
924 /* preferred lifetime */
925 put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
926 put_opt6_long(lease_time); /* valid lifetime */
927 end_opt6(o1);
928 }
929
930 if (t1cntr != 0)
931 {
932 /* go back an fill in fields in IA_NA option */
933 int sav = save_counter(t1cntr);
934 unsigned int t1, t2, fuzz = rand16();
935
936 while (fuzz > (min_time/16))
937 fuzz = fuzz/2;
938 t1 = min_time == 0xffffffff ? 0xffffffff : min_time/2 - fuzz;
939 t2 = min_time == 0xffffffff ? 0xffffffff : ((min_time/8)*7) - fuzz;
940
941 put_opt6_long(t1);
942 put_opt6_long(t2);
943 save_counter(sav);
944 }
945
946 end_opt6(o);
947 }
948 break;
949
950 }
951
952 case DHCP6CONFIRM:
953 {
954 /* set reply message type */
955 *outmsgtypep = DHCP6REPLY;
956
957 log6_packet("DHCPCONFIRM", clid, clid_len, NULL, xid, iface_name, NULL);
958
959 for (opt = packet_options; opt; opt = opt6_next(opt, end))
960 {
961 int ia_type = opt6_type(opt);
962 void *ia_option, *ia_end;
963
964 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
965 continue;
966
967 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
968 continue;
969
970 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
971 continue;
972
973 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
974 ia_end = opt6_ptr(opt, opt6_len(opt));
975
976 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
977 ia_option;
978 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
979 {
980 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
981
982 if (!address6_available(context, req_addr, run_tag_if(tags)))
983 {
984 o1 = new_opt6(OPTION6_STATUS_CODE);
985 put_opt6_short(DHCP6NOTONLINK);
986 put_opt6_string("Confirm failed");
987 end_opt6(o1);
988 return 1;
989 }
990
991 log6_packet("DHCPREPLY", clid, clid_len, req_addr, xid, iface_name, hostname);
992 }
993 }
994
995 o1 = new_opt6(OPTION6_STATUS_CODE);
996 put_opt6_short(DHCP6SUCCESS );
997 put_opt6_string("All addresses still on link");
998 end_opt6(o1);
999 return 1;
1000 }
1001
1002 case DHCP6IREQ:
1003 {
1004 if (ignore)
1005 return 0;
1006 *outmsgtypep = DHCP6REPLY;
1007 log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, hostname);
1008 break;
1009 }
1010
1011
1012 case DHCP6RELEASE:
1013 {
1014 /* set reply message type */
1015 *outmsgtypep = DHCP6REPLY;
1016
1017 log6_packet("DHCPRELEASE", clid, clid_len, NULL, xid, iface_name, NULL);
1018
1019 for (opt = packet_options; opt; opt = opt6_next(opt, end))
1020 {
1021 int iaid, ia_type = opt6_type(opt);
1022 void *ia_option, *ia_end;
1023 int made_ia = 0;
1024
1025 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
1026 continue;
1027
1028 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
1029 continue;
1030
1031 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
1032 continue;
1033
1034 iaid = opt6_uint(opt, 0, 4);
1035 ia_end = opt6_ptr(opt, opt6_len(opt));
1036 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
1037
1038 /* reset "USED" flags on leases */
1039 lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
1040
1041 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
1042 ia_option;
1043 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1044 {
1045 struct dhcp_lease *lease;
1046
1047 if ((lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1048 iaid, opt6_ptr(ia_option, 0))))
1049 lease_prune(lease, now);
1050 else
1051 {
1052 if (!made_ia)
1053 {
1054 o = new_opt6(ia_type);
1055 put_opt6_long(iaid);
1056 if (ia_type == OPTION6_IA_NA)
1057 {
1058 put_opt6_long(0);
1059 put_opt6_long(0);
1060 }
1061 made_ia = 1;
1062 }
1063
1064 o1 = new_opt6(OPTION6_IAADDR);
1065 put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
1066 put_opt6_long(0);
1067 put_opt6_long(0);
1068 end_opt6(o1);
1069 }
1070 }
1071
1072 if (made_ia)
1073 {
1074 o1 = new_opt6(OPTION6_STATUS_CODE);
1075 put_opt6_short(DHCP6NOBINDING);
1076 put_opt6_string("No binding found");
1077 end_opt6(o1);
1078
1079 end_opt6(o);
1080 }
1081 }
1082
1083 o1 = new_opt6(OPTION6_STATUS_CODE);
1084 put_opt6_short(DHCP6SUCCESS);
1085 put_opt6_string("Release received");
1086 end_opt6(o1);
1087
1088 return 1;
1089 }
1090
1091 case DHCP6DECLINE:
1092 {
1093 /* set reply message type */
1094 *outmsgtypep = DHCP6REPLY;
1095
1096 log6_packet("DHCPDECLINE", clid, clid_len, NULL, xid, iface_name, NULL);
1097
1098 for (opt = packet_options; opt; opt = opt6_next(opt, end))
1099 {
1100 int iaid, ia_type = opt6_type(opt);
1101 void *ia_option, *ia_end;
1102 int made_ia = 0;
1103
1104 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
1105 continue;
1106
1107 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
1108 continue;
1109
1110 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
1111 continue;
1112
1113 iaid = opt6_uint(opt, 0, 4);
1114 ia_end = opt6_ptr(opt, opt6_len(opt));
1115 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
1116
1117 /* reset "USED" flags on leases */
1118 lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
1119
1120 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
1121 ia_option;
1122 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1123 {
1124 struct dhcp_lease *lease;
1125 struct in6_addr *addrp = opt6_ptr(ia_option, 0);
1126
1127 if (have_config(config, CONFIG_ADDR6) &&
1128 memcmp(&config->addr6, addrp, IN6ADDRSZ) == 0)
1129 {
1130 prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
1131 inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
1132 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
1133 daemon->addrbuff, daemon->dhcp_buff3);
1134 config->flags |= CONFIG_DECLINED;
1135 config->decline_time = now;
1136 }
1137 else
1138 /* make sure this host gets a different address next time. */
1139 for (; context; context = context->current)
1140 context->addr_epoch++;
1141
1142 if ((lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1143 iaid, opt6_ptr(ia_option, 0))))
1144 lease_prune(lease, now);
1145 else
1146 {
1147 if (!made_ia)
1148 {
1149 o = new_opt6(ia_type);
1150 put_opt6_long(iaid);
1151 if (ia_type == OPTION6_IA_NA)
1152 {
1153 put_opt6_long(0);
1154 put_opt6_long(0);
1155 }
1156 made_ia = 1;
1157 }
1158
1159 o1 = new_opt6(OPTION6_IAADDR);
1160 put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
1161 put_opt6_long(0);
1162 put_opt6_long(0);
1163 end_opt6(o1);
1164 }
1165 }
1166
1167 if (made_ia)
1168 {
1169 o1 = new_opt6(OPTION6_STATUS_CODE);
1170 put_opt6_short(DHCP6NOBINDING);
1171 put_opt6_string("No binding found");
1172 end_opt6(o1);
1173
1174 end_opt6(o);
1175 }
1176
1177 }
1178 return 1;
1179 }
1180
1181 }
1182
1183
1184 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
1185 tagif = option_filter(tags, context_tags, daemon->dhcp_opts6);
1186
1187 oro = opt6_find(packet_options, end, OPTION6_ORO, 0);
1188
1189 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1190 {
1191 /* netids match and not encapsulated? */
1192 if (!(opt_cfg->flags & DHOPT_TAGOK))
1193 continue;
1194
1195 if (!(opt_cfg->flags & DHOPT_FORCE) && oro)
1196 {
1197 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1198 if (opt6_uint(oro, i, 2) == (unsigned)opt_cfg->opt)
1199 break;
1200
1201 /* option not requested */
1202 if (i >= opt6_len(oro) - 1)
1203 continue;
1204 }
1205
1206 if (opt_cfg->opt == OPTION6_DNS_SERVER)
1207 {
1208 done_dns = 1;
1209 if (opt_cfg->len == 0)
1210 continue;
1211 }
1212
1213 o = new_opt6(opt_cfg->opt);
1214 if (opt_cfg->flags & DHOPT_ADDR6)
1215 {
1216 int j;
1217 struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
1218 for (j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
1219 {
1220 /* zero means "self" (but not in vendorclass options.) */
1221 if (IN6_IS_ADDR_UNSPECIFIED(a))
1222 {
1223 if (IN6_IS_ADDR_UNSPECIFIED(&context->local6))
1224 put_opt6(fallback, IN6ADDRSZ);
1225 else
1226 put_opt6(&context->local6, IN6ADDRSZ);
1227 }
1228 else
1229 put_opt6(a, IN6ADDRSZ);
1230 }
1231 }
1232 else if (opt_cfg->val)
1233 put_opt6(opt_cfg->val, opt_cfg->len);
1234 end_opt6(o);
1235 }
1236
1237 if (!done_dns &&
1238 (!IN6_IS_ADDR_UNSPECIFIED(&context->local6) ||
1239 !IN6_IS_ADDR_UNSPECIFIED(fallback)))
1240 {
1241 o = new_opt6(OPTION6_DNS_SERVER);
1242 if (IN6_IS_ADDR_UNSPECIFIED(&context->local6))
1243 put_opt6(fallback, IN6ADDRSZ);
1244 else
1245 put_opt6(&context->local6, IN6ADDRSZ);
1246 end_opt6(o);
1247 }
1248
1249 /* handle vendor-identifying vendor-encapsulated options,
1250 dhcp-option = vi-encap:13,17,....... */
1251 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1252 opt_cfg->flags &= ~DHOPT_ENCAP_DONE;
1253
1254 if (oro)
1255 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1256 if (opt6_uint(oro, i, 2) == OPTION6_VENDOR_OPTS)
1257 do_encap = 1;
1258
1259 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1260 {
1261 if (opt_cfg->flags & DHOPT_RFC3925)
1262 {
1263 int found = 0;
1264 struct dhcp_opt *oc;
1265
1266 if (opt_cfg->flags & DHOPT_ENCAP_DONE)
1267 continue;
1268
1269 for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1270 {
1271 oc->flags &= ~DHOPT_ENCAP_MATCH;
1272
1273 if (!(oc->flags & DHOPT_RFC3925) || opt_cfg->u.encap != oc->u.encap)
1274 continue;
1275
1276 oc->flags |= DHOPT_ENCAP_DONE;
1277 if (match_netid(oc->netid, tagif, 1))
1278 {
1279 /* option requested/forced? */
1280 if (!oro || do_encap || (oc->flags & DHOPT_FORCE))
1281 {
1282 oc->flags |= DHOPT_ENCAP_MATCH;
1283 found = 1;
1284 }
1285 }
1286 }
1287
1288 if (found)
1289 {
1290 o = new_opt6(OPTION6_VENDOR_OPTS);
1291 put_opt6_long(opt_cfg->u.encap);
1292
1293 for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1294 if (oc->flags & DHOPT_ENCAP_MATCH)
1295 {
1296 o1 = new_opt6(oc->opt);
1297 put_opt6(oc->val, oc->len);
1298 end_opt6(o1);
1299 }
1300 end_opt6(o);
1301 }
1302 }
1303 }
1304
1305
1306 if (hostname)
1307 {
1308 unsigned char *p;
1309 size_t len = strlen(hostname);
1310
1311 if (send_domain)
1312 len += strlen(send_domain) + 1;
1313
1314 o = new_opt6(OPTION6_FQDN);
1315 if ((p = expand(len + 3)))
1316 {
1317 *(p++) = fqdn_flags;
1318 p = do_rfc1035_name(p, hostname);
1319 if (send_domain)
1320 p = do_rfc1035_name(p, send_domain);
1321 *p = 0;
1322 }
1323 end_opt6(o);
1324 }
1325
1326
1327 /* logging */
1328 if (option_bool(OPT_LOG_OPTS) && oro)
1329 {
1330 char *q = daemon->namebuff;
1331 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1332 {
1333 char *s = option_string(AF_INET6, opt6_uint(oro, i, 2), NULL, 0, NULL, 0);
1334 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
1335 "%d%s%s%s",
1336 opt6_uint(oro, i, 2),
1337 strlen(s) != 0 ? ":" : "",
1338 s,
1339 (i > opt6_len(oro) - 3) ? "" : ", ");
1340 if ( i > opt6_len(oro) - 3 || (q - daemon->namebuff) > 40)
1341 {
1342 q = daemon->namebuff;
1343 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), xid, daemon->namebuff);
1344 }
1345 }
1346 }
1347
1348 log_tags(tagif, xid);
1349
1350 if (option_bool(OPT_LOG_OPTS))
1351 log6_opts(0, xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));
1352
1353 return 1;
1354 }
1355
1356 static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts)
1357 {
1358 void *opt;
1359 char *desc = nest ? "nest" : "sent";
1360
1361 if (start_opts == end_opts)
1362 return;
1363
1364 for (opt = start_opts; opt; opt = opt6_next(opt, end_opts))
1365 {
1366 int type = opt6_type(opt);
1367 void *ia_options = NULL;
1368 char *optname;
1369
1370 if (type == OPTION6_IA_NA)
1371 {
1372 sprintf(daemon->namebuff, "IAID=%u T1=%u T2=%u",
1373 opt6_uint(opt, 0, 4), opt6_uint(opt, 4, 4), opt6_uint(opt, 8, 4));
1374 optname = "ia-na";
1375 ia_options = opt6_ptr(opt, 12);
1376 }
1377 else if (type == OPTION6_IA_TA)
1378 {
1379 sprintf(daemon->namebuff, "IAID=%u", opt6_uint(opt, 0, 4));
1380 optname = "ia-ta";
1381 ia_options = opt6_ptr(opt, 4);
1382 }
1383 else if (type == OPTION6_IAADDR)
1384 {
1385 inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
1386 sprintf(daemon->namebuff, "%s PL=%u VL=%u",
1387 daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
1388 optname = "iaaddr";
1389 ia_options = opt6_ptr(opt, 24);
1390 }
1391 else if (type == OPTION6_STATUS_CODE)
1392 {
1393 int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
1394 memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
1395 daemon->namebuff[len + opt6_len(opt) - 2] = 0;
1396 optname = "status";
1397 }
1398 else
1399 {
1400 /* account for flag byte on FQDN */
1401 int offset = type == OPTION6_FQDN ? 1 : 0;
1402 optname = option_string(AF_INET6, type, opt6_ptr(opt, offset), opt6_len(opt) - offset, daemon->namebuff, MAXDNAME);
1403 }
1404
1405 my_syslog(MS_DHCP | LOG_INFO, "%u %s size:%3d option:%3d %s %s",
1406 xid, desc, opt6_len(opt), type, optname, daemon->namebuff);
1407
1408 if (ia_options)
1409 log6_opts(1, xid, ia_options, opt6_ptr(opt, opt6_len(opt)));
1410 }
1411 }
1412
1413 static void log6_packet(char *type, unsigned char *clid, int clid_len, struct in6_addr *addr, int xid, char *iface, char *string)
1414 {
1415 /* avoid buffer overflow */
1416 if (clid_len > 100)
1417 clid_len = 100;
1418
1419 print_mac(daemon->namebuff, clid, clid_len);
1420
1421 if (addr)
1422 {
1423 inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
1424 strcat(daemon->dhcp_buff2, " ");
1425 }
1426 else
1427 daemon->dhcp_buff2[0] = 0;
1428
1429 if(option_bool(OPT_LOG_OPTS))
1430 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s %s",
1431 xid,
1432 type,
1433 iface,
1434 daemon->dhcp_buff2,
1435 daemon->namebuff,
1436 string ? string : "");
1437 else
1438 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s %s",
1439 type,
1440 iface,
1441 daemon->dhcp_buff2,
1442 daemon->namebuff,
1443 string ? string : "");
1444 }
1445
1446 static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize)
1447 {
1448 u16 opt, opt_len;
1449 void *start;
1450
1451 if (!opts)
1452 return NULL;
1453
1454 while (1)
1455 {
1456 if (end - opts < 4)
1457 return NULL;
1458
1459 start = opts;
1460 GETSHORT(opt, opts);
1461 GETSHORT(opt_len, opts);
1462
1463 if (opt_len > (end - opts))
1464 return NULL;
1465
1466 if (opt == search && (opt_len >= minsize))
1467 return start;
1468
1469 opts += opt_len;
1470 }
1471 }
1472
1473 static void *opt6_next(void *opts, void *end)
1474 {
1475 u16 opt_len;
1476
1477 if (end - opts < 4)
1478 return NULL;
1479
1480 opts += 2;
1481 GETSHORT(opt_len, opts);
1482
1483 if (opt_len >= (end - opts))
1484 return NULL;
1485
1486 return opts + opt_len;
1487 }
1488
1489 static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
1490 {
1491 /* this worries about unaligned data and byte order */
1492 unsigned int ret = 0;
1493 int i;
1494 unsigned char *p = opt6_ptr(opt, offset);
1495
1496 for (i = 0; i < size; i++)
1497 ret = (ret << 8) | *p++;
1498
1499 return ret;
1500 }
1501
1502 #endif