Dnsmasq: update to 2.66TEST16
[tomato.git] / release / src / router / dnsmasq / src / rfc3315.c
blob785a426e247fb82317c691331c5b64ae0fd3be13
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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.
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.
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/>.
18 #include "dnsmasq.h"
20 #ifdef HAVE_DHCP6
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);
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);
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)]))
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)
41 struct dhcp_netid *relay_tags = NULL;
42 struct dhcp_vendor *vendor;
43 int msg_type;
45 if (sz <= 4)
46 return 0;
48 msg_type = *((unsigned char *)daemon->dhcp_packet.iov_base);
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;
54 save_counter(0);
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;
59 return 0;
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)
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;
73 /* if not an encaplsulated relayed message, just do the stuff */
74 if (msg_type != DHCP6RELAYFORW)
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. */
81 if (link_address)
83 struct dhcp_context *c;
84 context = NULL;
86 if (!IN6_IS_ADDR_LOOPBACK(link_address) &&
87 !IN6_IS_ADDR_LINKLOCAL(link_address) &&
88 !IN6_IS_ADDR_MULTICAST(link_address))
89 for (c = daemon->dhcp6; c; c = c->next)
90 if ((c->flags & CONTEXT_DHCP) &&
91 !(c->flags & CONTEXT_TEMPLATE) &&
92 is_same_net6(link_address, &c->start6, c->prefix) &&
93 is_same_net6(link_address, &c->end6, c->prefix))
95 c->current = context;
96 context = c;
99 if (!context)
101 inet_ntop(AF_INET6, link_address, daemon->addrbuff, ADDRSTRLEN);
102 my_syslog(MS_DHCP | LOG_WARNING,
103 _("no address range available for DHCPv6 request from relay at %s"),
104 daemon->addrbuff);
105 return 0;
109 if (!context)
111 my_syslog(MS_DHCP | LOG_WARNING,
112 _("no address range available for DHCPv6 request via %s"), iface_name);
113 return 0;
116 return dhcp6_no_relay(msg_type, link_address, *relay_tagsp, context, interface, iface_name, fallback, inbuff, sz, is_unicast, now);
119 /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
120 which is 1 + 1 + 16 + 16 + 2 + 2 = 38 */
121 if (sz < 38)
122 return 0;
124 /* copy header stuff into reply message and set type to reply */
125 outmsgtypep = put_opt6(inbuff, 34);
126 *outmsgtypep = DHCP6RELAYREPL;
128 /* look for relay options and set tags if found. */
129 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
131 int mopt;
133 if (vendor->match_type == MATCH_SUBSCRIBER)
134 mopt = OPTION6_SUBSCRIBER_ID;
135 else if (vendor->match_type == MATCH_REMOTE)
136 mopt = OPTION6_REMOTE_ID;
137 else
138 continue;
140 if ((opt = opt6_find(opts, end, mopt, 1)) &&
141 vendor->len == opt6_len(opt) &&
142 memcmp(vendor->data, opt6_ptr(opt, 0), vendor->len) == 0 &&
143 vendor->netid.next != &vendor->netid)
145 vendor->netid.next = *relay_tagsp;
146 *relay_tagsp = &vendor->netid;
147 break;
151 for (opt = opts; opt; opt = opt6_next(opt, end))
153 int o = new_opt6(opt6_type(opt));
154 if (opt6_type(opt) == OPTION6_RELAY_MSG)
156 struct in6_addr link_address;
157 /* the packet data is unaligned, copy to aligned storage */
158 memcpy(&link_address, inbuff + 2, IN6ADDRSZ);
159 /* Not, zero is_unicast since that is now known to refer to the
160 relayed packet, not the original sent by the client */
161 if (!dhcp6_maybe_relay(&link_address, relay_tagsp, context, interface, iface_name, fallback, opt6_ptr(opt, 0), opt6_len(opt), 0, now))
162 return 0;
164 else
165 put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
166 end_opt6(o);
169 return 1;
172 static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dhcp_netid *tags, struct dhcp_context *context,
173 int interface, char *iface_name, struct in6_addr *fallback, void *inbuff, size_t sz, int is_unicast, time_t now)
175 void *packet_options = inbuff + 4;
176 void *end = inbuff + sz;
177 void *opt, *oro;
178 int i, o, o1;
179 unsigned char *clid = NULL;
180 int clid_len = 0, start_opts;
181 struct dhcp_netid *tagif, *context_tags = NULL;
182 char *client_hostname= NULL, *hostname = NULL;
183 char *domain = NULL, *send_domain = NULL;
184 struct dhcp_config *config = NULL;
185 struct dhcp_netid known_id, iface_id, v6_id;
186 int done_dns = 0, hostname_auth = 0, do_encap = 0;
187 unsigned char *outmsgtypep;
188 struct dhcp_opt *opt_cfg;
189 struct dhcp_vendor *vendor;
190 struct dhcp_context *context_tmp;
191 unsigned int xid, ignore = 0;
192 unsigned int fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
194 /* set tag with name == interface */
195 iface_id.net = iface_name;
196 iface_id.next = tags;
197 tags = &iface_id;
199 /* set tag "dhcpv6" */
200 v6_id.net = "dhcpv6";
201 v6_id.next = tags;
202 tags = &v6_id;
204 /* copy over transaction-id, and save pointer to message type */
205 outmsgtypep = put_opt6(inbuff, 4);
206 start_opts = save_counter(-1);
207 xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
209 /* We're going to be linking tags from all context we use.
210 mark them as unused so we don't link one twice and break the list */
211 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
213 context->netid.next = &context->netid;
215 if (option_bool(OPT_LOG_OPTS))
217 inet_ntop(AF_INET6, &context_tmp->start6, daemon->dhcp_buff, ADDRSTRLEN);
218 inet_ntop(AF_INET6, &context_tmp->end6, daemon->dhcp_buff2, ADDRSTRLEN);
219 if (context_tmp->flags & (CONTEXT_STATIC))
220 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCPv6 subnet: %s/%d"),
221 xid, daemon->dhcp_buff, context_tmp->prefix);
222 else
223 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
224 xid, daemon->dhcp_buff, daemon->dhcp_buff2);
228 if ((opt = opt6_find(packet_options, end, OPTION6_CLIENT_ID, 1)))
230 clid = opt6_ptr(opt, 0);
231 clid_len = opt6_len(opt);
232 o = new_opt6(OPTION6_CLIENT_ID);
233 put_opt6(clid, clid_len);
234 end_opt6(o);
236 else if (msg_type != DHCP6IREQ)
237 return 0;
239 /* server-id must match except for SOLICIT and CONFIRM messages */
240 if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ &&
241 (!(opt = opt6_find(packet_options, end, OPTION6_SERVER_ID, 1)) ||
242 opt6_len(opt) != daemon->duid_len ||
243 memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
244 return 0;
246 o = new_opt6(OPTION6_SERVER_ID);
247 put_opt6(daemon->duid, daemon->duid_len);
248 end_opt6(o);
250 if (is_unicast &&
251 (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
254 o1 = new_opt6(OPTION6_STATUS_CODE);
255 put_opt6_short(DHCP6USEMULTI);
256 put_opt6_string("Use multicast");
257 end_opt6(o1);
258 return 1;
261 /* match vendor and user class options */
262 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
264 int mopt;
266 if (vendor->match_type == MATCH_VENDOR)
267 mopt = OPTION6_VENDOR_CLASS;
268 else if (vendor->match_type == MATCH_USER)
269 mopt = OPTION6_USER_CLASS;
270 else
271 continue;
273 if ((opt = opt6_find(packet_options, end, mopt, 2)))
275 void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
276 int offset = 0;
278 if (mopt == OPTION6_VENDOR_CLASS)
280 if (opt6_len(opt) < 4)
281 continue;
283 if (vendor->enterprise != opt6_uint(opt, 0, 4))
284 continue;
286 offset = 4;
289 for (enc_opt = opt6_ptr(opt, offset); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
290 for (i = 0; i <= (opt6_len(enc_opt) - vendor->len); i++)
291 if (memcmp(vendor->data, opt6_ptr(enc_opt, i), vendor->len) == 0)
293 vendor->netid.next = tags;
294 tags = &vendor->netid;
295 break;
300 if (option_bool(OPT_LOG_OPTS) && (opt = opt6_find(packet_options, end, OPTION6_VENDOR_CLASS, 4)))
301 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %u"), xid, opt6_uint(opt, 0, 4));
303 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
304 Otherwise assume the option is an array, and look for a matching element.
305 If no data given, existance of the option is enough. This code handles
306 V-I opts too. */
307 for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
309 int match = 0;
311 if (opt_cfg->flags & DHOPT_RFC3925)
313 for (opt = opt6_find(packet_options, end, OPTION6_VENDOR_OPTS, 4);
314 opt;
315 opt = opt6_find(opt6_next(opt, end), end, OPTION6_VENDOR_OPTS, 4))
317 void *vopt;
318 void *vend = opt6_ptr(opt, opt6_len(opt));
320 for (vopt = opt6_find(opt6_ptr(opt, 4), vend, opt_cfg->opt, 0);
321 vopt;
322 vopt = opt6_find(opt6_next(vopt, vend), vend, opt_cfg->opt, 0))
323 if ((match = match_bytes(opt_cfg, opt6_ptr(vopt, 0), opt6_len(vopt))))
324 break;
326 if (match)
327 break;
329 else
331 if (!(opt = opt6_find(packet_options, end, opt_cfg->opt, 1)))
332 continue;
334 match = match_bytes(opt_cfg, opt6_ptr(opt, 0), opt6_len(opt));
337 if (match)
339 opt_cfg->netid->next = tags;
340 tags = opt_cfg->netid;
344 if ((opt = opt6_find(packet_options, end, OPTION6_FQDN, 1)))
346 /* RFC4704 refers */
347 int len = opt6_len(opt) - 1;
349 fqdn_flags = opt6_uint(opt, 0, 1);
351 /* Always force update, since the client has no way to do it itself. */
352 if (!option_bool(OPT_FQDN_UPDATE) && !(fqdn_flags & 0x01))
353 fqdn_flags |= 0x03;
355 fqdn_flags &= ~0x04;
357 if (len != 0 && len < 255)
359 unsigned char *pp, *op = opt6_ptr(opt, 1);
360 char *pq = daemon->dhcp_buff;
362 pp = op;
363 while (*op != 0 && ((op + (*op)) - pp) < len)
365 memcpy(pq, op+1, *op);
366 pq += *op;
367 op += (*op)+1;
368 *(pq++) = '.';
371 if (pq != daemon->dhcp_buff)
372 pq--;
373 *pq = 0;
375 if (legal_hostname(daemon->dhcp_buff))
377 client_hostname = daemon->dhcp_buff;
378 if (option_bool(OPT_LOG_OPTS))
379 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), xid, client_hostname);
384 if (clid)
386 config = find_config6(daemon->dhcp_conf, context, clid, clid_len, NULL);
388 if (have_config(config, CONFIG_NAME))
390 hostname = config->hostname;
391 domain = config->domain;
392 hostname_auth = 1;
394 else if (client_hostname)
396 domain = strip_hostname(client_hostname);
398 if (strlen(client_hostname) != 0)
400 hostname = client_hostname;
401 if (!config)
403 /* Search again now we have a hostname.
404 Only accept configs without CLID here, (it won't match)
405 to avoid impersonation by name. */
406 struct dhcp_config *new = find_config6(daemon->dhcp_conf, context, NULL, 0, hostname);
407 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
408 config = new;
414 if (config)
416 struct dhcp_netid_list *list;
418 for (list = config->netid; list; list = list->next)
420 list->list->next = tags;
421 tags = list->list;
424 /* set "known" tag for known hosts */
425 known_id.net = "known";
426 known_id.next = tags;
427 tags = &known_id;
429 if (have_config(config, CONFIG_DISABLE))
430 ignore = 1;
433 tagif = run_tag_if(tags);
435 /* if all the netids in the ignore list are present, ignore this client */
436 if (daemon->dhcp_ignore)
438 struct dhcp_netid_list *id_list;
440 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
441 if (match_netid(id_list->list, tagif, 0))
442 ignore = 1;
445 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
446 if (!hostname_auth)
448 struct dhcp_netid_list *id_list;
450 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
451 if ((!id_list->list) || match_netid(id_list->list, tagif, 0))
452 break;
453 if (id_list)
454 hostname = NULL;
458 switch (msg_type)
460 default:
461 return 0;
463 case DHCP6SOLICIT:
464 case DHCP6REQUEST:
466 void *rapid_commit = opt6_find(packet_options, end, OPTION6_RAPID_COMMIT, 0);
467 int make_lease = (msg_type == DHCP6REQUEST || rapid_commit);
468 int serial = 0, used_config = 0;
470 if (rapid_commit)
472 o = new_opt6(OPTION6_RAPID_COMMIT);
473 end_opt6(o);
476 /* set reply message type */
477 *outmsgtypep = make_lease ? DHCP6REPLY : DHCP6ADVERTISE;
479 log6_packet(msg_type == DHCP6SOLICIT ? "DHCPSOLICIT" : "DHCPREQUEST",
480 clid, clid_len, NULL, xid, iface_name, ignore ? "ignored" : NULL);
482 if (ignore)
483 return 0;
485 for (opt = packet_options; opt; opt = opt6_next(opt, end))
487 int iaid, ia_type = opt6_type(opt);
488 void *ia_option, *ia_end;
489 unsigned int min_time = 0xffffffff;
490 int t1cntr = 0;
491 int address_assigned = 0;
493 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
494 continue;
496 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
497 continue;
499 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
500 continue;
502 iaid = opt6_uint(opt, 0, 4);
503 ia_end = opt6_ptr(opt, opt6_len(opt));
504 ia_option = opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
506 /* reset "USED" flags on leases */
507 lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
509 o = new_opt6(ia_type);
510 put_opt6_long(iaid);
511 if (ia_type == OPTION6_IA_NA)
513 /* save pointer */
514 t1cntr = save_counter(-1);
515 /* so we can fill these in later */
516 put_opt6_long(0);
517 put_opt6_long(0);
520 while (1)
522 struct in6_addr alloced_addr, *addrp = NULL;
523 u32 requested_time = 0;
524 struct dhcp_lease *lease = NULL;
526 if (ia_option)
528 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
529 requested_time = opt6_uint(ia_option, 16, 4);
530 struct dhcp_context *dynamic;
532 if ((dynamic = address6_available(context, req_addr, tags)) || address6_valid(context, req_addr, tags))
534 if (!dynamic && !(have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, req_addr, IN6ADDRSZ) == 0))
536 /* Static range, not configured. */
537 o1 = new_opt6(OPTION6_STATUS_CODE);
538 put_opt6_short(DHCP6UNSPEC);
539 put_opt6_string("Address unavailable");
540 end_opt6(o1);
542 else if (lease6_find_by_addr(req_addr, 128, 0) &&
543 !(lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, req_addr)))
545 /* Address leased to another DUID/IAID */
546 o1 = new_opt6(OPTION6_STATUS_CODE);
547 put_opt6_short(DHCP6UNSPEC);
548 put_opt6_string("Address in use");
549 end_opt6(o1);
551 else
552 addrp = req_addr;
554 else if (msg_type == DHCP6REQUEST)
556 /* requested address not on the correct link */
557 o1 = new_opt6(OPTION6_STATUS_CODE);
558 put_opt6_short(DHCP6NOTONLINK);
559 put_opt6_string("Not on link");
560 end_opt6(o1);
563 else
565 /* must have an address to CONFIRM */
566 if (msg_type == DHCP6REQUEST && ia_type == OPTION6_IA_NA)
567 return 0;
569 /* Don't used configured addresses for temporary leases. */
570 if (have_config(config, CONFIG_ADDR6) && !used_config && ia_type == OPTION6_IA_NA)
572 struct dhcp_lease *ltmp = lease6_find_by_addr(&config->addr6, 128, 0);
574 used_config = 1;
575 inet_ntop(AF_INET6, &config->addr6, daemon->addrbuff, ADDRSTRLEN);
577 if (ltmp && ltmp->clid &&
578 (ltmp->clid_len != clid_len || memcmp(ltmp->clid, clid, clid_len) != 0 || ltmp->hwaddr_type != iaid))
579 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s#%d"),
580 daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len), ltmp->hwaddr_type);
581 else if (have_config(config, CONFIG_DECLINED) &&
582 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
583 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
584 daemon->addrbuff);
585 else
587 addrp = &config->addr6;
588 /* may have existing lease for this address */
589 lease = lease6_find(clid, clid_len,
590 ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, addrp);
594 /* existing lease */
595 if (!addrp &&
596 (lease = lease6_find(clid, clid_len,
597 ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL)) &&
598 !config_find_by_address6(daemon->dhcp_conf, (struct in6_addr *)&lease->hwaddr, 128, 0))
599 addrp = (struct in6_addr *)&lease->hwaddr;
601 if (!addrp && address6_allocate(context, clid, clid_len, serial++, tags, &alloced_addr))
602 addrp = &alloced_addr;
605 if (addrp)
607 unsigned int lease_time;
608 struct dhcp_context *this_context;
609 struct dhcp_config *valid_config = config;
611 /* don't use a config to set lease time if it specifies an address which isn't this. */
612 if (have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, addrp, IN6ADDRSZ) != 0)
613 valid_config = NULL;
615 address_assigned = 1;
617 /* shouldn't ever fail */
618 if ((this_context = narrow_context6(context, addrp, tagif)))
620 /* get tags from context if we've not used it before */
621 if (this_context->netid.next == &this_context->netid && this_context->netid.net)
623 this_context->netid.next = context_tags;
624 context_tags = &this_context->netid;
625 if (!hostname_auth)
627 struct dhcp_netid_list *id_list;
629 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
630 if ((!id_list->list) || match_netid(id_list->list, &this_context->netid, 0))
631 break;
632 if (id_list)
633 hostname = NULL;
637 if (have_config(valid_config, CONFIG_TIME))
638 lease_time = valid_config->lease_time;
639 else
640 lease_time = this_context->lease_time;
642 if (this_context->valid < lease_time)
643 lease_time = this_context->valid;
645 if (ia_option)
647 if (requested_time < 120u )
648 requested_time = 120u; /* sanity */
649 if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
650 lease_time = requested_time;
653 if (lease_time < min_time)
654 min_time = lease_time;
656 /* May fail to create lease */
657 if (!lease && make_lease)
658 lease = lease6_allocate(addrp, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
660 if (lease)
662 lease_set_expires(lease, lease_time, now);
663 lease_set_hwaddr(lease, NULL, clid, 0, iaid, clid_len, now, 0);
664 lease_set_interface(lease, interface, now);
665 if (hostname && ia_type == OPTION6_IA_NA)
667 char *addr_domain = get_domain6(addrp);
668 if (!send_domain)
669 send_domain = addr_domain;
670 lease_set_hostname(lease, hostname, hostname_auth, addr_domain, domain);
673 #ifdef HAVE_SCRIPT
674 if (daemon->lease_change_command)
676 void *class_opt;
677 lease->flags |= LEASE_CHANGED;
678 free(lease->extradata);
679 lease->extradata = NULL;
680 lease->extradata_size = lease->extradata_len = 0;
681 lease->hwaddr_len = 0; /* surrogate for no of vendor classes */
683 if ((class_opt = opt6_find(packet_options, end, OPTION6_VENDOR_CLASS, 4)))
685 void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
686 lease->hwaddr_len++;
687 /* send enterprise number first */
688 sprintf(daemon->dhcp_buff2, "%u", opt6_uint(class_opt, 0, 4));
689 lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
691 if (opt6_len(class_opt) >= 6)
692 for (enc_opt = opt6_ptr(class_opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
694 lease->hwaddr_len++;
695 lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
699 lease_add_extradata(lease, (unsigned char *)client_hostname,
700 client_hostname ? strlen(client_hostname) : 0, 0);
702 /* space-concat tag set */
703 if (!tagif && !context_tags)
704 lease_add_extradata(lease, NULL, 0, 0);
705 else
707 struct dhcp_netid *n, *l, *tmp = tags;
709 /* link temporarily */
710 for (n = context_tags; n && n->next; n = n->next);
711 if ((l = n))
713 l->next = tags;
714 tmp = context_tags;
717 for (n = run_tag_if(tmp); n; n = n->next)
719 struct dhcp_netid *n1;
720 /* kill dupes */
721 for (n1 = n->next; n1; n1 = n1->next)
722 if (strcmp(n->net, n1->net) == 0)
723 break;
724 if (!n1)
725 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
728 /* unlink again */
729 if (l)
730 l->next = NULL;
733 if (link_address)
734 inet_ntop(AF_INET6, link_address, daemon->addrbuff, ADDRSTRLEN);
736 lease_add_extradata(lease, (unsigned char *)daemon->addrbuff, link_address ? strlen(daemon->addrbuff) : 0, 0);
738 if ((class_opt = opt6_find(packet_options, end, OPTION6_USER_CLASS, 2)))
740 void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
741 for (enc_opt = opt6_ptr(class_opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
742 lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
745 #endif
748 else if (!send_domain)
749 send_domain = get_domain6(addrp);
752 if (lease || !make_lease)
754 o1 = new_opt6(OPTION6_IAADDR);
755 put_opt6(addrp, sizeof(*addrp));
756 /* preferred lifetime */
757 put_opt6_long(this_context && (this_context->preferred < lease_time) ?
758 this_context->preferred : lease_time);
759 put_opt6_long(lease_time); /* valid lifetime */
760 end_opt6(o1);
762 log6_packet( make_lease ? "DHCPREPLY" : "DHCPADVERTISE",
763 clid, clid_len, addrp, xid, iface_name, hostname);
770 if (!ia_option ||
771 !(ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)))
773 if (address_assigned)
775 o1 = new_opt6(OPTION6_STATUS_CODE);
776 put_opt6_short(DHCP6SUCCESS);
777 put_opt6_string("Oh hai from dnsmasq");
778 end_opt6(o1);
780 if (ia_type == OPTION6_IA_NA)
782 /* go back an fill in fields in IA_NA option */
783 unsigned int t1 = min_time == 0xffffffff ? 0xffffffff : min_time/2;
784 unsigned int t2 = min_time == 0xffffffff ? 0xffffffff : (min_time/8) * 7;
785 int sav = save_counter(t1cntr);
786 put_opt6_long(t1);
787 put_opt6_long(t2);
788 save_counter(sav);
791 else
793 /* no address, return error */
794 o1 = new_opt6(OPTION6_STATUS_CODE);
795 put_opt6_short(DHCP6NOADDRS);
796 put_opt6_string("No addresses available");
797 end_opt6(o1);
800 end_opt6(o);
802 if (address_assigned)
804 /* If --dhcp-authoritative is set, we can tell client not to wait for
805 other possible servers */
806 o = new_opt6(OPTION6_PREFERENCE);
807 put_opt6_char(option_bool(OPT_AUTHORITATIVE) ? 255 : 0);
808 end_opt6(o);
811 break;
816 break;
819 case DHCP6RENEW:
821 /* set reply message type */
822 *outmsgtypep = DHCP6REPLY;
824 log6_packet("DHCPRENEW", clid, clid_len, NULL, xid, iface_name, NULL);
826 for (opt = packet_options; opt; opt = opt6_next(opt, end))
828 int ia_type = opt6_type(opt);
829 void *ia_option, *ia_end;
830 unsigned int min_time = 0xffffffff;
831 int t1cntr = 0, iacntr;
832 unsigned int iaid;
834 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
835 continue;
837 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
838 continue;
840 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
841 continue;
843 iaid = opt6_uint(opt, 0, 4);
845 o = new_opt6(ia_type);
846 put_opt6_long(iaid);
847 if (ia_type == OPTION6_IA_NA)
849 /* save pointer */
850 t1cntr = save_counter(-1);
851 /* so we can fill these in later */
852 put_opt6_long(0);
853 put_opt6_long(0);
856 iacntr = save_counter(-1);
858 /* reset "USED" flags on leases */
859 lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
861 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
862 ia_end = opt6_ptr(opt, opt6_len(opt));
864 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
865 ia_option;
866 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
868 struct dhcp_lease *lease = NULL;
869 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
870 u32 requested_time = opt6_uint(ia_option, 16, 4);
871 unsigned int lease_time;
872 struct dhcp_context *this_context;
873 struct dhcp_config *valid_config = config;
875 /* don't use a config to set lease time if it specifies an address which isn't this. */
876 if (have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0)
877 valid_config = NULL;
879 if (!(lease = lease6_find(clid, clid_len,
880 ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
881 iaid, req_addr)))
883 /* If the server cannot find a client entry for the IA the server
884 returns the IA containing no addresses with a Status Code option set
885 to NoBinding in the Reply message. */
886 save_counter(iacntr);
887 t1cntr = 0;
889 log6_packet("DHCPREPLY", clid, clid_len, req_addr, xid, iface_name, "lease not found");
891 o1 = new_opt6(OPTION6_STATUS_CODE);
892 put_opt6_short(DHCP6NOBINDING);
893 put_opt6_string("No binding found");
894 end_opt6(o1);
895 break;
899 if (!address6_available(context, req_addr, tagif) ||
900 !(this_context = narrow_context6(context, req_addr, tagif)))
902 lease_time = 0;
903 this_context = NULL;
905 else
907 /* get tags from context if we've not used it before */
908 if (this_context->netid.next == &this_context->netid && this_context->netid.net)
910 this_context->netid.next = context_tags;
911 context_tags = &this_context->netid;
912 if (!hostname_auth)
914 struct dhcp_netid_list *id_list;
916 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
917 if ((!id_list->list) || match_netid(id_list->list, &this_context->netid, 0))
918 break;
919 if (id_list)
920 hostname = NULL;
924 lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
926 if (requested_time < 120u )
927 requested_time = 120u; /* sanity */
928 if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
929 lease_time = requested_time;
931 lease_set_expires(lease, lease_time, now);
932 if (ia_type == OPTION6_IA_NA && hostname)
934 char *addr_domain = get_domain6(req_addr);
935 if (!send_domain)
936 send_domain = addr_domain;
937 lease_set_hostname(lease, hostname, hostname_auth, addr_domain, domain);
940 if (lease_time < min_time)
941 min_time = lease_time;
944 log6_packet("DHCPREPLY", clid, clid_len, req_addr, xid, iface_name, hostname);
946 o1 = new_opt6(OPTION6_IAADDR);
947 put_opt6(req_addr, sizeof(*req_addr));
948 /* preferred lifetime */
949 put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
950 put_opt6_long(lease_time); /* valid lifetime */
951 end_opt6(o1);
954 if (t1cntr != 0)
956 /* go back an fill in fields in IA_NA option */
957 int sav = save_counter(t1cntr);
958 unsigned int t1, t2, fuzz = rand16();
960 while (fuzz > (min_time/16))
961 fuzz = fuzz/2;
962 t1 = min_time == 0xffffffff ? 0xffffffff : min_time/2 - fuzz;
963 t2 = min_time == 0xffffffff ? 0xffffffff : ((min_time/8)*7) - fuzz;
965 put_opt6_long(t1);
966 put_opt6_long(t2);
967 save_counter(sav);
970 end_opt6(o);
972 break;
976 case DHCP6CONFIRM:
978 /* set reply message type */
979 *outmsgtypep = DHCP6REPLY;
981 log6_packet("DHCPCONFIRM", clid, clid_len, NULL, xid, iface_name, NULL);
983 for (opt = packet_options; opt; opt = opt6_next(opt, end))
985 int ia_type = opt6_type(opt);
986 void *ia_option, *ia_end;
988 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
989 continue;
991 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
992 continue;
994 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
995 continue;
997 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
998 ia_end = opt6_ptr(opt, opt6_len(opt));
1000 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
1001 ia_option;
1002 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1004 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
1006 if (!address6_available(context, req_addr, run_tag_if(tags)))
1008 o1 = new_opt6(OPTION6_STATUS_CODE);
1009 put_opt6_short(DHCP6NOTONLINK);
1010 put_opt6_string("Confirm failed");
1011 end_opt6(o1);
1012 return 1;
1015 log6_packet("DHCPREPLY", clid, clid_len, req_addr, xid, iface_name, hostname);
1019 o1 = new_opt6(OPTION6_STATUS_CODE);
1020 put_opt6_short(DHCP6SUCCESS );
1021 put_opt6_string("All addresses still on link");
1022 end_opt6(o1);
1023 return 1;
1026 case DHCP6IREQ:
1028 /* We can't discriminate contexts based on address, as we don't know it.
1029 If there is only one possible context, we can use its tags */
1030 if (context && context->netid.net && !context->current)
1032 context->netid.next = NULL;
1033 context_tags = &context->netid;
1035 log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, ignore ? "ignored" : hostname);
1036 if (ignore)
1037 return 0;
1038 *outmsgtypep = DHCP6REPLY;
1039 break;
1043 case DHCP6RELEASE:
1045 /* set reply message type */
1046 *outmsgtypep = DHCP6REPLY;
1048 log6_packet("DHCPRELEASE", clid, clid_len, NULL, xid, iface_name, NULL);
1050 for (opt = packet_options; opt; opt = opt6_next(opt, end))
1052 int iaid, ia_type = opt6_type(opt);
1053 void *ia_option, *ia_end;
1054 int made_ia = 0;
1056 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
1057 continue;
1059 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
1060 continue;
1062 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
1063 continue;
1065 iaid = opt6_uint(opt, 0, 4);
1066 ia_end = opt6_ptr(opt, opt6_len(opt));
1067 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
1069 /* reset "USED" flags on leases */
1070 lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
1072 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
1073 ia_option;
1074 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1076 struct dhcp_lease *lease;
1078 if ((lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1079 iaid, opt6_ptr(ia_option, 0))))
1080 lease_prune(lease, now);
1081 else
1083 if (!made_ia)
1085 o = new_opt6(ia_type);
1086 put_opt6_long(iaid);
1087 if (ia_type == OPTION6_IA_NA)
1089 put_opt6_long(0);
1090 put_opt6_long(0);
1092 made_ia = 1;
1095 o1 = new_opt6(OPTION6_IAADDR);
1096 put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
1097 put_opt6_long(0);
1098 put_opt6_long(0);
1099 end_opt6(o1);
1103 if (made_ia)
1105 o1 = new_opt6(OPTION6_STATUS_CODE);
1106 put_opt6_short(DHCP6NOBINDING);
1107 put_opt6_string("No binding found");
1108 end_opt6(o1);
1110 end_opt6(o);
1114 o1 = new_opt6(OPTION6_STATUS_CODE);
1115 put_opt6_short(DHCP6SUCCESS);
1116 put_opt6_string("Release received");
1117 end_opt6(o1);
1119 return 1;
1122 case DHCP6DECLINE:
1124 /* set reply message type */
1125 *outmsgtypep = DHCP6REPLY;
1127 log6_packet("DHCPDECLINE", clid, clid_len, NULL, xid, iface_name, NULL);
1129 for (opt = packet_options; opt; opt = opt6_next(opt, end))
1131 int iaid, ia_type = opt6_type(opt);
1132 void *ia_option, *ia_end;
1133 int made_ia = 0;
1135 if (ia_type != OPTION6_IA_NA && ia_type != OPTION6_IA_TA)
1136 continue;
1138 if (ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
1139 continue;
1141 if (ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
1142 continue;
1144 iaid = opt6_uint(opt, 0, 4);
1145 ia_end = opt6_ptr(opt, opt6_len(opt));
1146 ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
1148 /* reset "USED" flags on leases */
1149 lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
1151 for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
1152 ia_option;
1153 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1155 struct dhcp_lease *lease;
1156 struct in6_addr *addrp = opt6_ptr(ia_option, 0);
1158 if (have_config(config, CONFIG_ADDR6) &&
1159 memcmp(&config->addr6, addrp, IN6ADDRSZ) == 0)
1161 prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
1162 inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
1163 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
1164 daemon->addrbuff, daemon->dhcp_buff3);
1165 config->flags |= CONFIG_DECLINED;
1166 config->decline_time = now;
1168 else
1169 /* make sure this host gets a different address next time. */
1170 for (; context; context = context->current)
1171 context->addr_epoch++;
1173 if ((lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1174 iaid, opt6_ptr(ia_option, 0))))
1175 lease_prune(lease, now);
1176 else
1178 if (!made_ia)
1180 o = new_opt6(ia_type);
1181 put_opt6_long(iaid);
1182 if (ia_type == OPTION6_IA_NA)
1184 put_opt6_long(0);
1185 put_opt6_long(0);
1187 made_ia = 1;
1190 o1 = new_opt6(OPTION6_IAADDR);
1191 put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
1192 put_opt6_long(0);
1193 put_opt6_long(0);
1194 end_opt6(o1);
1198 if (made_ia)
1200 o1 = new_opt6(OPTION6_STATUS_CODE);
1201 put_opt6_short(DHCP6NOBINDING);
1202 put_opt6_string("No binding found");
1203 end_opt6(o1);
1205 end_opt6(o);
1209 return 1;
1215 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
1216 tagif = option_filter(tags, context_tags, daemon->dhcp_opts6);
1218 oro = opt6_find(packet_options, end, OPTION6_ORO, 0);
1220 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1222 /* netids match and not encapsulated? */
1223 if (!(opt_cfg->flags & DHOPT_TAGOK))
1224 continue;
1226 if (!(opt_cfg->flags & DHOPT_FORCE) && oro)
1228 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1229 if (opt6_uint(oro, i, 2) == (unsigned)opt_cfg->opt)
1230 break;
1232 /* option not requested */
1233 if (i >= opt6_len(oro) - 1)
1234 continue;
1237 if (opt_cfg->opt == OPTION6_DNS_SERVER)
1239 done_dns = 1;
1240 if (opt_cfg->len == 0)
1241 continue;
1244 o = new_opt6(opt_cfg->opt);
1245 if (opt_cfg->flags & DHOPT_ADDR6)
1247 int j;
1248 struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
1249 for (j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
1251 /* zero means "self" (but not in vendorclass options.) */
1252 if (IN6_IS_ADDR_UNSPECIFIED(a))
1254 if (IN6_IS_ADDR_UNSPECIFIED(&context->local6))
1255 put_opt6(fallback, IN6ADDRSZ);
1256 else
1257 put_opt6(&context->local6, IN6ADDRSZ);
1259 else
1260 put_opt6(a, IN6ADDRSZ);
1263 else if (opt_cfg->val)
1264 put_opt6(opt_cfg->val, opt_cfg->len);
1265 end_opt6(o);
1268 if (daemon->port == NAMESERVER_PORT && !done_dns &&
1269 (!IN6_IS_ADDR_UNSPECIFIED(&context->local6) ||
1270 !IN6_IS_ADDR_UNSPECIFIED(fallback)))
1272 o = new_opt6(OPTION6_DNS_SERVER);
1273 if (IN6_IS_ADDR_UNSPECIFIED(&context->local6))
1274 put_opt6(fallback, IN6ADDRSZ);
1275 else
1276 put_opt6(&context->local6, IN6ADDRSZ);
1277 end_opt6(o);
1280 /* handle vendor-identifying vendor-encapsulated options,
1281 dhcp-option = vi-encap:13,17,....... */
1282 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1283 opt_cfg->flags &= ~DHOPT_ENCAP_DONE;
1285 if (oro)
1286 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1287 if (opt6_uint(oro, i, 2) == OPTION6_VENDOR_OPTS)
1288 do_encap = 1;
1290 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1292 if (opt_cfg->flags & DHOPT_RFC3925)
1294 int found = 0;
1295 struct dhcp_opt *oc;
1297 if (opt_cfg->flags & DHOPT_ENCAP_DONE)
1298 continue;
1300 for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1302 oc->flags &= ~DHOPT_ENCAP_MATCH;
1304 if (!(oc->flags & DHOPT_RFC3925) || opt_cfg->u.encap != oc->u.encap)
1305 continue;
1307 oc->flags |= DHOPT_ENCAP_DONE;
1308 if (match_netid(oc->netid, tagif, 1))
1310 /* option requested/forced? */
1311 if (!oro || do_encap || (oc->flags & DHOPT_FORCE))
1313 oc->flags |= DHOPT_ENCAP_MATCH;
1314 found = 1;
1319 if (found)
1321 o = new_opt6(OPTION6_VENDOR_OPTS);
1322 put_opt6_long(opt_cfg->u.encap);
1324 for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1325 if (oc->flags & DHOPT_ENCAP_MATCH)
1327 o1 = new_opt6(oc->opt);
1328 put_opt6(oc->val, oc->len);
1329 end_opt6(o1);
1331 end_opt6(o);
1337 if (hostname)
1339 unsigned char *p;
1340 size_t len = strlen(hostname);
1342 if (send_domain)
1343 len += strlen(send_domain) + 1;
1345 o = new_opt6(OPTION6_FQDN);
1346 if ((p = expand(len + 3)))
1348 *(p++) = fqdn_flags;
1349 p = do_rfc1035_name(p, hostname);
1350 if (send_domain)
1351 p = do_rfc1035_name(p, send_domain);
1352 *p = 0;
1354 end_opt6(o);
1358 /* logging */
1359 if (option_bool(OPT_LOG_OPTS) && oro)
1361 char *q = daemon->namebuff;
1362 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1364 char *s = option_string(AF_INET6, opt6_uint(oro, i, 2), NULL, 0, NULL, 0);
1365 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
1366 "%d%s%s%s",
1367 opt6_uint(oro, i, 2),
1368 strlen(s) != 0 ? ":" : "",
1370 (i > opt6_len(oro) - 3) ? "" : ", ");
1371 if ( i > opt6_len(oro) - 3 || (q - daemon->namebuff) > 40)
1373 q = daemon->namebuff;
1374 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), xid, daemon->namebuff);
1379 log_tags(tagif, xid);
1381 if (option_bool(OPT_LOG_OPTS))
1382 log6_opts(0, xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));
1384 return 1;
1387 static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts)
1389 void *opt;
1390 char *desc = nest ? "nest" : "sent";
1392 if (start_opts == end_opts)
1393 return;
1395 for (opt = start_opts; opt; opt = opt6_next(opt, end_opts))
1397 int type = opt6_type(opt);
1398 void *ia_options = NULL;
1399 char *optname;
1401 if (type == OPTION6_IA_NA)
1403 sprintf(daemon->namebuff, "IAID=%u T1=%u T2=%u",
1404 opt6_uint(opt, 0, 4), opt6_uint(opt, 4, 4), opt6_uint(opt, 8, 4));
1405 optname = "ia-na";
1406 ia_options = opt6_ptr(opt, 12);
1408 else if (type == OPTION6_IA_TA)
1410 sprintf(daemon->namebuff, "IAID=%u", opt6_uint(opt, 0, 4));
1411 optname = "ia-ta";
1412 ia_options = opt6_ptr(opt, 4);
1414 else if (type == OPTION6_IAADDR)
1416 inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
1417 sprintf(daemon->namebuff, "%s PL=%u VL=%u",
1418 daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
1419 optname = "iaaddr";
1420 ia_options = opt6_ptr(opt, 24);
1422 else if (type == OPTION6_STATUS_CODE)
1424 int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
1425 memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
1426 daemon->namebuff[len + opt6_len(opt) - 2] = 0;
1427 optname = "status";
1429 else
1431 /* account for flag byte on FQDN */
1432 int offset = type == OPTION6_FQDN ? 1 : 0;
1433 optname = option_string(AF_INET6, type, opt6_ptr(opt, offset), opt6_len(opt) - offset, daemon->namebuff, MAXDNAME);
1436 my_syslog(MS_DHCP | LOG_INFO, "%u %s size:%3d option:%3d %s %s",
1437 xid, desc, opt6_len(opt), type, optname, daemon->namebuff);
1439 if (ia_options)
1440 log6_opts(1, xid, ia_options, opt6_ptr(opt, opt6_len(opt)));
1444 static void log6_packet(char *type, unsigned char *clid, int clid_len, struct in6_addr *addr, int xid, char *iface, char *string)
1446 /* avoid buffer overflow */
1447 if (clid_len > 100)
1448 clid_len = 100;
1450 print_mac(daemon->namebuff, clid, clid_len);
1452 if (addr)
1454 inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
1455 strcat(daemon->dhcp_buff2, " ");
1457 else
1458 daemon->dhcp_buff2[0] = 0;
1460 if(option_bool(OPT_LOG_OPTS))
1461 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s %s",
1462 xid,
1463 type,
1464 iface,
1465 daemon->dhcp_buff2,
1466 daemon->namebuff,
1467 string ? string : "");
1468 else
1469 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s %s",
1470 type,
1471 iface,
1472 daemon->dhcp_buff2,
1473 daemon->namebuff,
1474 string ? string : "");
1477 static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize)
1479 u16 opt, opt_len;
1480 void *start;
1482 if (!opts)
1483 return NULL;
1485 while (1)
1487 if (end - opts < 4)
1488 return NULL;
1490 start = opts;
1491 GETSHORT(opt, opts);
1492 GETSHORT(opt_len, opts);
1494 if (opt_len > (end - opts))
1495 return NULL;
1497 if (opt == search && (opt_len >= minsize))
1498 return start;
1500 opts += opt_len;
1504 static void *opt6_next(void *opts, void *end)
1506 u16 opt_len;
1508 if (end - opts < 4)
1509 return NULL;
1511 opts += 2;
1512 GETSHORT(opt_len, opts);
1514 if (opt_len >= (end - opts))
1515 return NULL;
1517 return opts + opt_len;
1520 static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
1522 /* this worries about unaligned data and byte order */
1523 unsigned int ret = 0;
1524 int i;
1525 unsigned char *p = opt6_ptr(opt, offset);
1527 for (i = 0; i < size; i++)
1528 ret = (ret << 8) | *p++;
1530 return ret;
1533 #endif