dnsmasq: v2.67test16 patch Sept.25th/2013.
[tomato.git] / release / src / router / dnsmasq / src / rfc3315.c
blob12d6aca4b32992fd2f4aad308c549164584c5cb4
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 struct state {
23 unsigned char *clid;
24 int clid_len, iaid, ia_type, interface, hostname_auth, lease_allocate;
25 char *client_hostname, *hostname, *domain, *send_domain;
26 struct dhcp_context *context;
27 struct in6_addr *link_address, *fallback;
28 unsigned int xid, fqdn_flags;
29 char *iface_name;
30 void *packet_options, *end;
31 struct dhcp_netid *tags, *context_tags;
32 unsigned char mac[DHCP_CHADDR_MAX];
33 unsigned int mac_len, mac_type;
34 #ifdef OPTION6_PREFIX_CLASS
35 struct prefix_class *send_prefix_class;
36 #endif
39 static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
40 struct in6_addr *client_addr, int is_unicast, time_t now);
41 static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now);
42 static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
43 static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
44 static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize);
45 static void *opt6_next(void *opts, void *end);
46 static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
47 static void get_context_tag(struct state *state, struct dhcp_context *context);
48 static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
49 static int build_ia(struct state *state, int *t1cntr);
50 static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
51 #ifdef OPTION6_PREFIX_CLASS
52 static struct prefix_class *prefix_class_from_context(struct dhcp_context *context);
53 #endif
54 static void mark_context_used(struct state *state, struct in6_addr *addr);
55 static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
56 static int check_address(struct state *state, struct in6_addr *addr);
57 static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
58 unsigned int *min_time, struct in6_addr *addr, time_t now);
59 static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
60 static int add_local_addrs(struct dhcp_context *context);
61 static struct dhcp_netid *add_options(struct state *state, int do_refresh);
62 static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
63 unsigned int *preferred_timep, unsigned int lease_time);
65 #define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
66 #define opt6_type(opt) (opt6_uint(opt, -4, 2))
67 #define opt6_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[4+(i)]))
70 unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
71 struct in6_addr *fallback, size_t sz, struct in6_addr *client_addr, time_t now)
73 struct dhcp_vendor *vendor;
74 int msg_type;
75 struct state state;
77 if (sz <= 4)
78 return 0;
80 msg_type = *((unsigned char *)daemon->dhcp_packet.iov_base);
82 /* Mark these so we only match each at most once, to avoid tangled linked lists */
83 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
84 vendor->netid.next = &vendor->netid;
86 save_counter(0);
87 state.context = context;
88 state.interface = interface;
89 state.iface_name = iface_name;
90 state.fallback = fallback;
91 state.mac_len = 0;
92 state.tags = NULL;
93 state.link_address = NULL;
95 if (dhcp6_maybe_relay(&state, daemon->dhcp_packet.iov_base, sz, client_addr,
96 IN6_IS_ADDR_MULTICAST(client_addr), now))
97 return msg_type == DHCP6RELAYFORW ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
99 return 0;
102 /* This cost me blood to write, it will probably cost you blood to understand - srk. */
103 static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
104 struct in6_addr *client_addr, int is_unicast, time_t now)
106 void *end = inbuff + sz;
107 void *opts = inbuff + 34;
108 int msg_type = *((unsigned char *)inbuff);
109 unsigned char *outmsgtypep;
110 void *opt;
111 struct dhcp_vendor *vendor;
113 /* if not an encaplsulated relayed message, just do the stuff */
114 if (msg_type != DHCP6RELAYFORW)
116 /* if link_address != NULL if points to the link address field of the
117 innermost nested RELAYFORW message, which is where we find the
118 address of the network on which we can allocate an address.
119 Recalculate the available contexts using that information.
121 link_address == NULL means there's no relay in use, so we try and find the client's
122 MAC address from the local ND cache. */
124 if (!state->link_address)
125 get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type);
126 else
128 struct dhcp_context *c;
129 state->context = NULL;
131 if (!IN6_IS_ADDR_LOOPBACK(state->link_address) &&
132 !IN6_IS_ADDR_LINKLOCAL(state->link_address) &&
133 !IN6_IS_ADDR_MULTICAST(state->link_address))
134 for (c = daemon->dhcp6; c; c = c->next)
135 if ((c->flags & CONTEXT_DHCP) &&
136 !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
137 is_same_net6(state->link_address, &c->start6, c->prefix) &&
138 is_same_net6(state->link_address, &c->end6, c->prefix))
140 c->preferred = c->valid = 0xffffffff;
141 c->current = state->context;
142 state->context = c;
145 if (!state->context)
147 inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN);
148 my_syslog(MS_DHCP | LOG_WARNING,
149 _("no address range available for DHCPv6 request from relay at %s"),
150 daemon->addrbuff);
151 return 0;
155 if (!state->context)
157 my_syslog(MS_DHCP | LOG_WARNING,
158 _("no address range available for DHCPv6 request via %s"), state->iface_name);
159 return 0;
162 return dhcp6_no_relay(state, msg_type, inbuff, sz, is_unicast, now);
165 /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
166 which is 1 + 1 + 16 + 16 + 2 + 2 = 38 */
167 if (sz < 38)
168 return 0;
170 /* copy header stuff into reply message and set type to reply */
171 if (!(outmsgtypep = put_opt6(inbuff, 34)))
172 return 0;
173 *outmsgtypep = DHCP6RELAYREPL;
175 /* look for relay options and set tags if found. */
176 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
178 int mopt;
180 if (vendor->match_type == MATCH_SUBSCRIBER)
181 mopt = OPTION6_SUBSCRIBER_ID;
182 else if (vendor->match_type == MATCH_REMOTE)
183 mopt = OPTION6_REMOTE_ID;
184 else
185 continue;
187 if ((opt = opt6_find(opts, end, mopt, 1)) &&
188 vendor->len == opt6_len(opt) &&
189 memcmp(vendor->data, opt6_ptr(opt, 0), vendor->len) == 0 &&
190 vendor->netid.next != &vendor->netid)
192 vendor->netid.next = state->tags;
193 state->tags = &vendor->netid;
194 break;
198 /* RFC-6939 */
199 if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
201 state->mac_type = opt6_uint(opt, 0, 2);
202 state->mac_len = opt6_len(opt) - 2;
203 memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
206 for (opt = opts; opt; opt = opt6_next(opt, end))
208 int o = new_opt6(opt6_type(opt));
209 if (opt6_type(opt) == OPTION6_RELAY_MSG)
211 struct in6_addr align;
212 /* the packet data is unaligned, copy to aligned storage */
213 memcpy(&align, inbuff + 2, IN6ADDRSZ);
214 state->link_address = &align;
215 /* zero is_unicast since that is now known to refer to the
216 relayed packet, not the original sent by the client */
217 if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
218 return 0;
220 else if (opt6_type(opt) != OPTION6_CLIENT_MAC)
221 put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
222 end_opt6(o);
225 return 1;
228 static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now)
230 void *opt;
231 int i, o, o1, start_opts;
232 struct dhcp_opt *opt_cfg;
233 struct dhcp_netid *tagif;
234 struct dhcp_config *config = NULL;
235 struct dhcp_netid known_id, iface_id, v6_id;
236 unsigned char *outmsgtypep;
237 struct dhcp_vendor *vendor;
238 struct dhcp_context *context_tmp;
239 struct dhcp_mac *mac_opt;
240 unsigned int ignore = 0;
241 #ifdef OPTION6_PREFIX_CLASS
242 struct prefix_class *p;
243 int dump_all_prefix_classes = 0;
244 #endif
246 state->packet_options = inbuff + 4;
247 state->end = inbuff + sz;
248 state->clid = NULL;
249 state->clid_len = 0;
250 state->lease_allocate = 0;
251 state->context_tags = NULL;
252 state->domain = NULL;
253 state->send_domain = NULL;
254 state->hostname_auth = 0;
255 state->hostname = NULL;
256 state->client_hostname = NULL;
257 state->fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
258 #ifdef OPTION6_PREFIX_CLASS
259 state->send_prefix_class = NULL;
260 #endif
262 /* set tag with name == interface */
263 iface_id.net = state->iface_name;
264 iface_id.next = state->tags;
265 state->tags = &iface_id;
267 /* set tag "dhcpv6" */
268 v6_id.net = "dhcpv6";
269 v6_id.next = state->tags;
270 state->tags = &v6_id;
272 /* copy over transaction-id, and save pointer to message type */
273 if (!(outmsgtypep = put_opt6(inbuff, 4)))
274 return 0;
275 start_opts = save_counter(-1);
276 state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
278 /* We're going to be linking tags from all context we use.
279 mark them as unused so we don't link one twice and break the list */
280 for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
282 context_tmp->netid.next = &context_tmp->netid;
284 if (option_bool(OPT_LOG_OPTS))
286 inet_ntop(AF_INET6, &context_tmp->start6, daemon->dhcp_buff, ADDRSTRLEN);
287 inet_ntop(AF_INET6, &context_tmp->end6, daemon->dhcp_buff2, ADDRSTRLEN);
288 if (context_tmp->flags & (CONTEXT_STATIC))
289 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCPv6 subnet: %s/%d"),
290 state->xid, daemon->dhcp_buff, context_tmp->prefix);
291 else
292 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
293 state->xid, daemon->dhcp_buff, daemon->dhcp_buff2);
297 if ((opt = opt6_find(state->packet_options, state->end, OPTION6_CLIENT_ID, 1)))
299 state->clid = opt6_ptr(opt, 0);
300 state->clid_len = opt6_len(opt);
301 o = new_opt6(OPTION6_CLIENT_ID);
302 put_opt6(state->clid, state->clid_len);
303 end_opt6(o);
305 else if (msg_type != DHCP6IREQ)
306 return 0;
308 /* server-id must match except for SOLICIT and CONFIRM messages */
309 if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ &&
310 (!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
311 opt6_len(opt) != daemon->duid_len ||
312 memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
313 return 0;
315 o = new_opt6(OPTION6_SERVER_ID);
316 put_opt6(daemon->duid, daemon->duid_len);
317 end_opt6(o);
319 if (is_unicast &&
320 (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
323 o1 = new_opt6(OPTION6_STATUS_CODE);
324 put_opt6_short(DHCP6USEMULTI);
325 put_opt6_string("Use multicast");
326 end_opt6(o1);
327 return 1;
330 /* match vendor and user class options */
331 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
333 int mopt;
335 if (vendor->match_type == MATCH_VENDOR)
336 mopt = OPTION6_VENDOR_CLASS;
337 else if (vendor->match_type == MATCH_USER)
338 mopt = OPTION6_USER_CLASS;
339 else
340 continue;
342 if ((opt = opt6_find(state->packet_options, state->end, mopt, 2)))
344 void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
345 int offset = 0;
347 if (mopt == OPTION6_VENDOR_CLASS)
349 if (opt6_len(opt) < 4)
350 continue;
352 if (vendor->enterprise != opt6_uint(opt, 0, 4))
353 continue;
355 offset = 4;
358 for (enc_opt = opt6_ptr(opt, offset); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
359 for (i = 0; i <= (opt6_len(enc_opt) - vendor->len); i++)
360 if (memcmp(vendor->data, opt6_ptr(enc_opt, i), vendor->len) == 0)
362 vendor->netid.next = state->tags;
363 state->tags = &vendor->netid;
364 break;
369 if (option_bool(OPT_LOG_OPTS) && (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
370 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %u"), state->xid, opt6_uint(opt, 0, 4));
372 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
373 Otherwise assume the option is an array, and look for a matching element.
374 If no data given, existance of the option is enough. This code handles
375 V-I opts too. */
376 for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
378 int match = 0;
380 if (opt_cfg->flags & DHOPT_RFC3925)
382 for (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_OPTS, 4);
383 opt;
384 opt = opt6_find(opt6_next(opt, state->end), state->end, OPTION6_VENDOR_OPTS, 4))
386 void *vopt;
387 void *vend = opt6_ptr(opt, opt6_len(opt));
389 for (vopt = opt6_find(opt6_ptr(opt, 4), vend, opt_cfg->opt, 0);
390 vopt;
391 vopt = opt6_find(opt6_next(vopt, vend), vend, opt_cfg->opt, 0))
392 if ((match = match_bytes(opt_cfg, opt6_ptr(vopt, 0), opt6_len(vopt))))
393 break;
395 if (match)
396 break;
398 else
400 if (!(opt = opt6_find(state->packet_options, state->end, opt_cfg->opt, 1)))
401 continue;
403 match = match_bytes(opt_cfg, opt6_ptr(opt, 0), opt6_len(opt));
406 if (match)
408 opt_cfg->netid->next = state->tags;
409 state->tags = opt_cfg->netid;
413 if (state->mac_len != 0)
415 if (option_bool(OPT_LOG_OPTS))
417 print_mac(daemon->dhcp_buff, state->mac, state->mac_len);
418 my_syslog(MS_DHCP | LOG_INFO, _("%u client MAC address: %s"), state->xid, daemon->dhcp_buff);
421 for (mac_opt = daemon->dhcp_macs; mac_opt; mac_opt = mac_opt->next)
422 if ((unsigned)mac_opt->hwaddr_len == state->mac_len &&
423 ((unsigned)mac_opt->hwaddr_type == state->mac_type || mac_opt->hwaddr_type == 0) &&
424 memcmp_masked(mac_opt->hwaddr, state->mac, state->mac_len, mac_opt->mask))
426 mac_opt->netid.next = state->tags;
427 state->tags = &mac_opt->netid;
431 if ((opt = opt6_find(state->packet_options, state->end, OPTION6_FQDN, 1)))
433 /* RFC4704 refers */
434 int len = opt6_len(opt) - 1;
436 state->fqdn_flags = opt6_uint(opt, 0, 1);
438 /* Always force update, since the client has no way to do it itself. */
439 if (!option_bool(OPT_FQDN_UPDATE) && !(state->fqdn_flags & 0x01))
440 state->fqdn_flags |= 0x03;
442 state->fqdn_flags &= ~0x04;
444 if (len != 0 && len < 255)
446 unsigned char *pp, *op = opt6_ptr(opt, 1);
447 char *pq = daemon->dhcp_buff;
449 pp = op;
450 while (*op != 0 && ((op + (*op)) - pp) < len)
452 memcpy(pq, op+1, *op);
453 pq += *op;
454 op += (*op)+1;
455 *(pq++) = '.';
458 if (pq != daemon->dhcp_buff)
459 pq--;
460 *pq = 0;
462 if (legal_hostname(daemon->dhcp_buff))
464 state->client_hostname = daemon->dhcp_buff;
465 if (option_bool(OPT_LOG_OPTS))
466 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), state->xid, state->client_hostname);
471 if (state->clid)
473 config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL);
475 if (have_config(config, CONFIG_NAME))
477 state->hostname = config->hostname;
478 state->domain = config->domain;
479 state->hostname_auth = 1;
481 else if (state->client_hostname)
483 state->domain = strip_hostname(state->client_hostname);
485 if (strlen(state->client_hostname) != 0)
487 state->hostname = state->client_hostname;
488 if (!config)
490 /* Search again now we have a hostname.
491 Only accept configs without CLID here, (it won't match)
492 to avoid impersonation by name. */
493 struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname);
494 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
495 config = new;
501 if (config)
503 struct dhcp_netid_list *list;
505 for (list = config->netid; list; list = list->next)
507 list->list->next = state->tags;
508 state->tags = list->list;
511 /* set "known" tag for known hosts */
512 known_id.net = "known";
513 known_id.next = state->tags;
514 state->tags = &known_id;
516 if (have_config(config, CONFIG_DISABLE))
517 ignore = 1;
520 #ifdef OPTION6_PREFIX_CLASS
521 /* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
522 if (daemon->prefix_classes && (msg_type == DHCP6SOLICIT || msg_type == DHCP6REQUEST))
524 void *oro;
526 if ((oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0)))
527 for (i = 0; i < opt6_len(oro) - 1; i += 2)
528 if (opt6_uint(oro, i, 2) == OPTION6_PREFIX_CLASS)
530 dump_all_prefix_classes = 1;
531 break;
534 if (msg_type != DHCP6SOLICIT || dump_all_prefix_classes)
535 /* Add the tags associated with prefix classes so we can use the DHCP ranges.
536 Not done for SOLICIT as we add them one-at-time. */
537 for (p = daemon->prefix_classes; p ; p = p->next)
539 p->tag.next = state->tags;
540 state->tags = &p->tag;
543 #endif
545 tagif = run_tag_if(state->tags);
547 /* if all the netids in the ignore list are present, ignore this client */
548 if (daemon->dhcp_ignore)
550 struct dhcp_netid_list *id_list;
552 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
553 if (match_netid(id_list->list, tagif, 0))
554 ignore = 1;
557 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
558 if (!state->hostname_auth)
560 struct dhcp_netid_list *id_list;
562 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
563 if ((!id_list->list) || match_netid(id_list->list, tagif, 0))
564 break;
565 if (id_list)
566 state->hostname = NULL;
570 switch (msg_type)
572 default:
573 return 0;
576 case DHCP6SOLICIT:
578 int address_assigned = 0;
579 /* tags without all prefix-class tags */
580 struct dhcp_netid *solicit_tags;
581 struct dhcp_context *c;
583 *outmsgtypep = DHCP6ADVERTISE;
585 if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
587 *outmsgtypep = DHCP6REPLY;
588 state->lease_allocate = 1;
589 o = new_opt6(OPTION6_RAPID_COMMIT);
590 end_opt6(o);
593 log6_packet(state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
595 request_no_address:
596 solicit_tags = tagif;
597 #ifdef HAVE_QUIET_DHCP
598 if (!option_bool(OPT_QUIET_DHCP6))
599 #endif
600 if (ignore)
601 return 0;
603 /* reset USED bits in leases */
604 lease6_reset();
606 /* Can use configured address max once per prefix */
607 for (c = state->context; c; c = c->current)
608 c->flags &= ~CONTEXT_CONF_USED;
610 for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
612 void *ia_option, *ia_end;
613 unsigned int min_time = 0xffffffff;
614 int t1cntr;
615 int ia_counter;
616 /* set unless we're sending a particular prefix-class, when we
617 want only dhcp-ranges with the correct tags set and not those without any tags. */
618 int plain_range = 1;
619 u32 lease_time;
620 struct dhcp_lease *ltmp;
621 struct in6_addr *req_addr;
622 struct in6_addr addr;
624 if (!check_ia(state, opt, &ia_end, &ia_option))
625 continue;
627 /* reset USED bits in contexts - one address per prefix per IAID */
628 for (c = state->context; c; c = c->current)
629 c->flags &= ~CONTEXT_USED;
631 #ifdef OPTION6_PREFIX_CLASS
632 if (daemon->prefix_classes && state->ia_type == OPTION6_IA_NA)
634 void *prefix_opt;
635 int prefix_class;
637 if (dump_all_prefix_classes)
638 /* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
639 plain_range = 0;
640 else
642 if ((prefix_opt = opt6_find(opt6_ptr(opt, 12), ia_end, OPTION6_PREFIX_CLASS, 2)))
645 prefix_class = opt6_uint(prefix_opt, 0, 2);
647 for (p = daemon->prefix_classes; p ; p = p->next)
648 if (p->class == prefix_class)
649 break;
651 if (!p)
652 my_syslog(MS_DHCP | LOG_WARNING, _("unknown prefix-class %d"), prefix_class);
653 else
655 /* add tag to list, and exclude undecorated dhcp-ranges */
656 p->tag.next = state->tags;
657 solicit_tags = run_tag_if(&p->tag);
658 plain_range = 0;
659 state->send_prefix_class = p;
662 else
664 /* client didn't ask for a prefix class, lets see if we can find one. */
665 for (p = daemon->prefix_classes; p ; p = p->next)
667 p->tag.next = NULL;
668 if (match_netid(&p->tag, solicit_tags, 1))
669 break;
672 if (p)
674 plain_range = 0;
675 state->send_prefix_class = p;
679 if (p && option_bool(OPT_LOG_OPTS))
680 my_syslog(MS_DHCP | LOG_INFO, "%u prefix class %d tag:%s", state->xid, p->class, p->tag.net);
683 #endif
685 o = build_ia(state, &t1cntr);
687 for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
689 req_addr = opt6_ptr(ia_option, 0);
691 if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
693 lease_time = c->lease_time;
694 /* If the client asks for an address on the same network as a configured address,
695 offer the configured address instead, to make moving to newly-configured
696 addresses automatic. */
697 if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
699 req_addr = &addr;
700 mark_config_used(c, &addr);
701 if (have_config(config, CONFIG_TIME))
702 lease_time = config->lease_time;
704 else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
705 continue; /* not an address we're allowed */
706 else if (!check_address(state, req_addr))
707 continue; /* address leased elsewhere */
709 /* add address to output packet */
710 #ifdef OPTION6_PREFIX_CLASS
711 if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
712 state->send_prefix_class = prefix_class_from_context(c);
713 #endif
714 add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
715 mark_context_used(state, req_addr);
716 get_context_tag(state, c);
717 address_assigned = 1;
721 /* Suggest configured address(es) */
722 for (c = state->context; c; c = c->current)
723 if (!(c->flags & CONTEXT_CONF_USED) &&
724 match_netid(c->filter, solicit_tags, plain_range) &&
725 config_valid(config, c, &addr) &&
726 check_address(state, &addr))
728 mark_config_used(state->context, &addr);
729 if (have_config(config, CONFIG_TIME))
730 lease_time = config->lease_time;
731 else
732 lease_time = c->lease_time;
733 /* add address to output packet */
734 #ifdef OPTION6_PREFIX_CLASS
735 if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
736 state->send_prefix_class = prefix_class_from_context(c);
737 #endif
738 add_address(state, c, lease_time, NULL, &min_time, &addr, now);
739 mark_context_used(state, &addr);
740 get_context_tag(state, c);
741 address_assigned = 1;
744 /* return addresses for existing leases */
745 ltmp = NULL;
746 while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
748 req_addr = &ltmp->addr6;
749 if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
751 #ifdef OPTION6_PREFIX_CLASS
752 if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
753 state->send_prefix_class = prefix_class_from_context(c);
754 #endif
755 add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
756 mark_context_used(state, req_addr);
757 get_context_tag(state, c);
758 address_assigned = 1;
762 /* Return addresses for all valid contexts which don't yet have one */
763 while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
765 #ifdef OPTION6_PREFIX_CLASS
766 if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
767 state->send_prefix_class = prefix_class_from_context(c);
768 #endif
769 add_address(state, c, c->lease_time, NULL, &min_time, &addr, now);
770 mark_context_used(state, &addr);
771 get_context_tag(state, c);
772 address_assigned = 1;
775 end_ia(t1cntr, min_time, 0);
776 end_opt6(o);
779 if (address_assigned)
781 o1 = new_opt6(OPTION6_STATUS_CODE);
782 put_opt6_short(DHCP6SUCCESS);
783 put_opt6_string(_("success"));
784 end_opt6(o1);
786 /* If --dhcp-authoritative is set, we can tell client not to wait for
787 other possible servers */
788 o = new_opt6(OPTION6_PREFERENCE);
789 put_opt6_char(option_bool(OPT_AUTHORITATIVE) ? 255 : 0);
790 end_opt6(o);
791 tagif = add_options(state, 0);
793 else
795 /* no address, return error */
796 o1 = new_opt6(OPTION6_STATUS_CODE);
797 put_opt6_short(DHCP6NOADDRS);
798 put_opt6_string(_("no addresses available"));
799 end_opt6(o1);
800 #ifdef HAVE_QUIET_DHCP
801 if (!option_bool(OPT_QUIET_DHCP6))
802 #endif
803 log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available"));
806 break;
809 case DHCP6REQUEST:
811 int address_assigned = 0;
812 int start = save_counter(-1);
814 /* set reply message type */
815 *outmsgtypep = DHCP6REPLY;
816 state->lease_allocate = 1;
818 #ifdef HAVE_QUIET_DHCP
819 if (!option_bool(OPT_QUIET_DHCP6))
820 #endif
821 log6_packet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
823 if (ignore)
824 return 0;
826 for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
828 void *ia_option, *ia_end;
829 unsigned int min_time = 0xffffffff;
830 int t1cntr;
832 if (!check_ia(state, opt, &ia_end, &ia_option))
833 continue;
835 if (!ia_option)
837 /* If we get a request with a IA_*A without addresses, treat it exactly like
838 a SOLICT with rapid commit set. */
839 save_counter(start);
840 goto request_no_address;
843 o = build_ia(state, &t1cntr);
845 for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
847 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
848 struct dhcp_context *dynamic, *c;
849 unsigned int lease_time;
850 struct in6_addr addr;
851 int config_ok = 0;
853 if ((c = address6_valid(state->context, req_addr, tagif, 1)))
854 config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
856 if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
858 if (!dynamic && !config_ok)
860 /* Static range, not configured. */
861 o1 = new_opt6(OPTION6_STATUS_CODE);
862 put_opt6_short(DHCP6UNSPEC);
863 put_opt6_string(_("address unavailable"));
864 end_opt6(o1);
866 else if (!check_address(state, req_addr))
868 /* Address leased to another DUID/IAID */
869 o1 = new_opt6(OPTION6_STATUS_CODE);
870 put_opt6_short(DHCP6UNSPEC);
871 put_opt6_string(_("address in use"));
872 end_opt6(o1);
874 else
876 if (!dynamic)
877 dynamic = c;
879 lease_time = dynamic->lease_time;
881 if (config_ok && have_config(config, CONFIG_TIME))
882 lease_time = config->lease_time;
884 #ifdef OPTION6_PREFIX_CLASS
885 if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
886 state->send_prefix_class = prefix_class_from_context(c);
887 #endif
888 add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
889 get_context_tag(state, dynamic);
890 address_assigned = 1;
893 else
895 /* requested address not on the correct link */
896 o1 = new_opt6(OPTION6_STATUS_CODE);
897 put_opt6_short(DHCP6NOTONLINK);
898 put_opt6_string(_("not on link"));
899 end_opt6(o1);
903 end_ia(t1cntr, min_time, 0);
904 end_opt6(o);
907 if (address_assigned)
909 o1 = new_opt6(OPTION6_STATUS_CODE);
910 put_opt6_short(DHCP6SUCCESS);
911 put_opt6_string(_("success"));
912 end_opt6(o1);
914 else
916 /* no address, return error */
917 o1 = new_opt6(OPTION6_STATUS_CODE);
918 put_opt6_short(DHCP6NOADDRS);
919 put_opt6_string(_("no addresses available"));
920 end_opt6(o1);
921 #ifdef HAVE_QUIET_DHCP
922 if (!option_bool(OPT_QUIET_DHCP6))
923 #endif
924 log6_packet(state, "DHCPREPLY", NULL, _("no addresses available"));
927 tagif = add_options(state, 0);
928 break;
932 case DHCP6RENEW:
934 /* set reply message type */
935 *outmsgtypep = DHCP6REPLY;
937 #ifdef HAVE_QUIET_DHCP
938 if (!option_bool(OPT_QUIET_DHCP6))
939 #endif
940 log6_packet(state, "DHCPRENEW", NULL, NULL);
942 for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
944 void *ia_option, *ia_end;
945 unsigned int min_time = 0xffffffff;
946 int t1cntr, iacntr;
948 if (!check_ia(state, opt, &ia_end, &ia_option))
949 continue;
951 o = build_ia(state, &t1cntr);
952 iacntr = save_counter(-1);
954 for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
956 struct dhcp_lease *lease = NULL;
957 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
958 unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
959 unsigned int valid_time = opt6_uint(ia_option, 20, 4);
960 char *message = NULL;
961 struct dhcp_context *this_context;
963 if (!(lease = lease6_find(state->clid, state->clid_len,
964 state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
965 state->iaid, req_addr)))
967 /* If the server cannot find a client entry for the IA the server
968 returns the IA containing no addresses with a Status Code option set
969 to NoBinding in the Reply message. */
970 save_counter(iacntr);
971 t1cntr = 0;
973 #ifdef HAVE_QUIET_DHCP
974 if (!option_bool(OPT_QUIET_DHCP6))
975 #endif
976 log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
978 o1 = new_opt6(OPTION6_STATUS_CODE);
979 put_opt6_short(DHCP6NOBINDING);
980 put_opt6_string(_("no binding found"));
981 end_opt6(o1);
983 preferred_time = valid_time = 0;
984 break;
988 if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
989 (this_context = address6_valid(state->context, req_addr, tagif, 1)))
991 struct in6_addr addr;
992 unsigned int lease_time;
994 get_context_tag(state, this_context);
996 if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
997 lease_time = config->lease_time;
998 else
999 lease_time = this_context->lease_time;
1001 calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time);
1003 lease_set_expires(lease, valid_time, now);
1004 /* Update MAC record in case it's new information. */
1005 if (state->mac_len != 0)
1006 lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
1007 if (state->ia_type == OPTION6_IA_NA && state->hostname)
1009 char *addr_domain = get_domain6(req_addr);
1010 if (!state->send_domain)
1011 state->send_domain = addr_domain;
1012 lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
1013 message = state->hostname;
1017 if (preferred_time == 0)
1018 message = _("deprecated");
1020 else
1022 preferred_time = valid_time = 0;
1023 message = _("address invalid");
1026 #ifdef HAVE_QUIET_DHCP
1027 if (!option_bool(OPT_QUIET_DHCP6))
1028 #endif
1029 log6_packet(state, "DHCPREPLY", req_addr, message);
1031 o1 = new_opt6(OPTION6_IAADDR);
1032 put_opt6(req_addr, sizeof(*req_addr));
1033 put_opt6_long(preferred_time);
1034 put_opt6_long(valid_time);
1035 end_opt6(o1);
1038 end_ia(t1cntr, min_time, 1);
1039 end_opt6(o);
1042 tagif = add_options(state, 0);
1043 break;
1047 case DHCP6CONFIRM:
1049 /* set reply message type */
1050 *outmsgtypep = DHCP6REPLY;
1052 #ifdef HAVE_QUIET_DHCP
1053 if (!option_bool(OPT_QUIET_DHCP6))
1054 #endif
1055 log6_packet(state, "DHCPCONFIRM", NULL, NULL);
1057 for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1059 void *ia_option, *ia_end;
1061 for (check_ia(state, opt, &ia_end, &ia_option);
1062 ia_option;
1063 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1065 struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
1067 if (!address6_available(state->context, req_addr, tagif, 1))
1069 o1 = new_opt6(OPTION6_STATUS_CODE);
1070 put_opt6_short(DHCP6NOTONLINK);
1071 put_opt6_string(_("confirm failed"));
1072 end_opt6(o1);
1073 return 1;
1076 #ifdef HAVE_QUIET_DHCP
1077 if (!option_bool(OPT_QUIET_DHCP6))
1078 #endif
1079 log6_packet(state, "DHCPREPLY", req_addr, state->hostname);
1083 o1 = new_opt6(OPTION6_STATUS_CODE);
1084 put_opt6_short(DHCP6SUCCESS );
1085 put_opt6_string(_("all addresses still on link"));
1086 end_opt6(o1);
1087 break;
1090 case DHCP6IREQ:
1092 /* We can't discriminate contexts based on address, as we don't know it.
1093 If there is only one possible context, we can use its tags */
1094 if (state->context && state->context->netid.net && !state->context->current)
1096 state->context->netid.next = NULL;
1097 state->context_tags = &state->context->netid;
1100 /* Similarly, we can't determine domain from address, but if the FQDN is
1101 given in --dhcp-host, we can use that, and failing that we can use the
1102 unqualified configured domain, if any. */
1103 if (state->hostname_auth)
1104 state->send_domain = state->domain;
1105 else
1106 state->send_domain = get_domain6(NULL);
1108 #ifdef HAVE_QUIET_DHCP
1109 if (!option_bool(OPT_QUIET_DHCP6))
1110 #endif
1111 log6_packet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
1112 if (ignore)
1113 return 0;
1114 *outmsgtypep = DHCP6REPLY;
1115 tagif = add_options(state, 1);
1116 break;
1120 case DHCP6RELEASE:
1122 /* set reply message type */
1123 *outmsgtypep = DHCP6REPLY;
1125 #ifdef HAVE_QUIET_DHCP
1126 if (!option_bool(OPT_QUIET_DHCP6))
1127 #endif
1128 log6_packet(state, "DHCPRELEASE", NULL, NULL);
1130 for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1132 void *ia_option, *ia_end;
1133 int made_ia = 0;
1135 for (check_ia(state, opt, &ia_end, &ia_option);
1136 ia_option;
1137 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1139 struct dhcp_lease *lease;
1141 if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1142 state->iaid, opt6_ptr(ia_option, 0))))
1143 lease_prune(lease, now);
1144 else
1146 if (!made_ia)
1148 o = new_opt6(state->ia_type);
1149 put_opt6_long(state->iaid);
1150 if (state->ia_type == OPTION6_IA_NA)
1152 put_opt6_long(0);
1153 put_opt6_long(0);
1155 made_ia = 1;
1158 o1 = new_opt6(OPTION6_IAADDR);
1159 put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
1160 put_opt6_long(0);
1161 put_opt6_long(0);
1162 end_opt6(o1);
1166 if (made_ia)
1168 o1 = new_opt6(OPTION6_STATUS_CODE);
1169 put_opt6_short(DHCP6NOBINDING);
1170 put_opt6_string(_("no binding found"));
1171 end_opt6(o1);
1173 end_opt6(o);
1177 o1 = new_opt6(OPTION6_STATUS_CODE);
1178 put_opt6_short(DHCP6SUCCESS);
1179 put_opt6_string(_("release received"));
1180 end_opt6(o1);
1182 break;
1185 case DHCP6DECLINE:
1187 /* set reply message type */
1188 *outmsgtypep = DHCP6REPLY;
1190 #ifdef HAVE_QUIET_DHCP
1191 if (!option_bool(OPT_QUIET_DHCP6))
1192 #endif
1193 log6_packet(state, "DHCPDECLINE", NULL, NULL);
1195 for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1197 void *ia_option, *ia_end;
1198 int made_ia = 0;
1200 for (check_ia(state, opt, &ia_end, &ia_option);
1201 ia_option;
1202 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1204 struct dhcp_lease *lease;
1205 struct in6_addr *addrp = opt6_ptr(ia_option, 0);
1207 if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
1209 prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
1210 inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
1211 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
1212 daemon->addrbuff, daemon->dhcp_buff3);
1213 config->flags |= CONFIG_DECLINED;
1214 config->decline_time = now;
1216 else
1217 /* make sure this host gets a different address next time. */
1218 for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
1219 context_tmp->addr_epoch++;
1221 if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1222 state->iaid, opt6_ptr(ia_option, 0))))
1223 lease_prune(lease, now);
1224 else
1226 if (!made_ia)
1228 o = new_opt6(state->ia_type);
1229 put_opt6_long(state->iaid);
1230 if (state->ia_type == OPTION6_IA_NA)
1232 put_opt6_long(0);
1233 put_opt6_long(0);
1235 made_ia = 1;
1238 o1 = new_opt6(OPTION6_IAADDR);
1239 put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
1240 put_opt6_long(0);
1241 put_opt6_long(0);
1242 end_opt6(o1);
1246 if (made_ia)
1248 o1 = new_opt6(OPTION6_STATUS_CODE);
1249 put_opt6_short(DHCP6NOBINDING);
1250 put_opt6_string(_("no binding found"));
1251 end_opt6(o1);
1253 end_opt6(o);
1257 break;
1262 log_tags(tagif, state->xid);
1263 log6_opts(0, state->xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));
1265 return 1;
1269 static struct dhcp_netid *add_options(struct state *state, int do_refresh)
1271 void *oro;
1272 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
1273 struct dhcp_netid *tagif = option_filter(state->tags, state->context_tags, daemon->dhcp_opts6);
1274 struct dhcp_opt *opt_cfg;
1275 int done_dns = 0, done_refresh = !do_refresh, do_encap = 0;
1276 int i, o, o1;
1278 oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0);
1280 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1282 /* netids match and not encapsulated? */
1283 if (!(opt_cfg->flags & DHOPT_TAGOK))
1284 continue;
1286 if (!(opt_cfg->flags & DHOPT_FORCE) && oro)
1288 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1289 if (opt6_uint(oro, i, 2) == (unsigned)opt_cfg->opt)
1290 break;
1292 /* option not requested */
1293 if (i >= opt6_len(oro) - 1)
1294 continue;
1297 if (opt_cfg->opt == OPTION6_DNS_SERVER)
1299 done_dns = 1;
1300 if (opt_cfg->len == 0)
1301 continue;
1304 if (opt_cfg->opt == OPTION6_REFRESH_TIME)
1305 done_refresh = 1;
1307 o = new_opt6(opt_cfg->opt);
1308 if (opt_cfg->flags & DHOPT_ADDR6)
1310 int j;
1311 struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
1312 for (j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
1314 /* zero means "self" (but not in vendorclass options.) */
1315 if (IN6_IS_ADDR_UNSPECIFIED(a))
1317 if (!add_local_addrs(state->context))
1318 put_opt6(state->fallback, IN6ADDRSZ);
1320 else
1321 put_opt6(a, IN6ADDRSZ);
1324 else if (opt_cfg->val)
1325 put_opt6(opt_cfg->val, opt_cfg->len);
1326 end_opt6(o);
1329 if (daemon->port == NAMESERVER_PORT && !done_dns)
1331 o = new_opt6(OPTION6_DNS_SERVER);
1332 if (!add_local_addrs(state->context))
1333 put_opt6(state->fallback, IN6ADDRSZ);
1334 end_opt6(o);
1337 if (state->context && !done_refresh)
1339 struct dhcp_context *c;
1340 unsigned int lease_time = 0xffffffff;
1342 /* Find the smallest lease tie of all contexts,
1343 subjext to the RFC-4242 stipulation that this must not
1344 be less than 600. */
1345 for (c = state->context; c; c = c->next)
1346 if (c->lease_time < lease_time)
1348 if (c->lease_time < 600)
1349 lease_time = 600;
1350 else
1351 lease_time = c->lease_time;
1354 o = new_opt6(OPTION6_REFRESH_TIME);
1355 put_opt6_long(lease_time);
1356 end_opt6(o);
1359 /* handle vendor-identifying vendor-encapsulated options,
1360 dhcp-option = vi-encap:13,17,....... */
1361 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1362 opt_cfg->flags &= ~DHOPT_ENCAP_DONE;
1364 if (oro)
1365 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1366 if (opt6_uint(oro, i, 2) == OPTION6_VENDOR_OPTS)
1367 do_encap = 1;
1369 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1371 if (opt_cfg->flags & DHOPT_RFC3925)
1373 int found = 0;
1374 struct dhcp_opt *oc;
1376 if (opt_cfg->flags & DHOPT_ENCAP_DONE)
1377 continue;
1379 for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1381 oc->flags &= ~DHOPT_ENCAP_MATCH;
1383 if (!(oc->flags & DHOPT_RFC3925) || opt_cfg->u.encap != oc->u.encap)
1384 continue;
1386 oc->flags |= DHOPT_ENCAP_DONE;
1387 if (match_netid(oc->netid, tagif, 1))
1389 /* option requested/forced? */
1390 if (!oro || do_encap || (oc->flags & DHOPT_FORCE))
1392 oc->flags |= DHOPT_ENCAP_MATCH;
1393 found = 1;
1398 if (found)
1400 o = new_opt6(OPTION6_VENDOR_OPTS);
1401 put_opt6_long(opt_cfg->u.encap);
1403 for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1404 if (oc->flags & DHOPT_ENCAP_MATCH)
1406 o1 = new_opt6(oc->opt);
1407 put_opt6(oc->val, oc->len);
1408 end_opt6(o1);
1410 end_opt6(o);
1416 if (state->hostname)
1418 unsigned char *p;
1419 size_t len = strlen(state->hostname);
1421 if (state->send_domain)
1422 len += strlen(state->send_domain) + 2;
1424 o = new_opt6(OPTION6_FQDN);
1425 if ((p = expand(len + 2)))
1427 *(p++) = state->fqdn_flags;
1428 p = do_rfc1035_name(p, state->hostname);
1429 if (state->send_domain)
1431 p = do_rfc1035_name(p, state->send_domain);
1432 *p = 0;
1435 end_opt6(o);
1439 /* logging */
1440 if (option_bool(OPT_LOG_OPTS) && oro)
1442 char *q = daemon->namebuff;
1443 for (i = 0; i < opt6_len(oro) - 1; i += 2)
1445 char *s = option_string(AF_INET6, opt6_uint(oro, i, 2), NULL, 0, NULL, 0);
1446 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
1447 "%d%s%s%s",
1448 opt6_uint(oro, i, 2),
1449 strlen(s) != 0 ? ":" : "",
1451 (i > opt6_len(oro) - 3) ? "" : ", ");
1452 if ( i > opt6_len(oro) - 3 || (q - daemon->namebuff) > 40)
1454 q = daemon->namebuff;
1455 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), state->xid, daemon->namebuff);
1460 return tagif;
1463 static int add_local_addrs(struct dhcp_context *context)
1465 int done = 0;
1467 for (; context; context = context->current)
1468 if ((context->flags & CONTEXT_USED) && !IN6_IS_ADDR_UNSPECIFIED(&context->local6))
1470 /* squash duplicates */
1471 struct dhcp_context *c;
1472 for (c = context->current; c; c = c->current)
1473 if ((c->flags & CONTEXT_USED) &&
1474 IN6_ARE_ADDR_EQUAL(&context->local6, &c->local6))
1475 break;
1477 if (!c)
1479 done = 1;
1480 put_opt6(&context->local6, IN6ADDRSZ);
1484 return done;
1488 static void get_context_tag(struct state *state, struct dhcp_context *context)
1490 /* get tags from context if we've not used it before */
1491 if (context->netid.next == &context->netid && context->netid.net)
1493 context->netid.next = state->context_tags;
1494 state->context_tags = &context->netid;
1495 if (!state->hostname_auth)
1497 struct dhcp_netid_list *id_list;
1499 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1500 if ((!id_list->list) || match_netid(id_list->list, &context->netid, 0))
1501 break;
1502 if (id_list)
1503 state->hostname = NULL;
1508 #ifdef OPTION6_PREFIX_CLASS
1509 static struct prefix_class *prefix_class_from_context(struct dhcp_context *context)
1511 struct prefix_class *p;
1512 struct dhcp_netid *t;
1514 for (p = daemon->prefix_classes; p ; p = p->next)
1515 for (t = context->filter; t; t = t->next)
1516 if (strcmp(p->tag.net, t->net) == 0)
1517 return p;
1519 return NULL;
1521 #endif
1523 static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
1525 state->ia_type = opt6_type(opt);
1526 *ia_option = NULL;
1528 if (state->ia_type != OPTION6_IA_NA && state->ia_type != OPTION6_IA_TA)
1529 return 0;
1531 if (state->ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
1532 return 0;
1534 if (state->ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
1535 return 0;
1537 *endp = opt6_ptr(opt, opt6_len(opt));
1538 state->iaid = opt6_uint(opt, 0, 4);
1539 *ia_option = opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
1541 return 1;
1545 static int build_ia(struct state *state, int *t1cntr)
1547 int o = new_opt6(state->ia_type);
1549 put_opt6_long(state->iaid);
1550 *t1cntr = 0;
1552 if (state->ia_type == OPTION6_IA_NA)
1554 /* save pointer */
1555 *t1cntr = save_counter(-1);
1556 /* so we can fill these in later */
1557 put_opt6_long(0);
1558 put_opt6_long(0);
1561 return o;
1564 static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
1566 if (t1cntr != 0)
1568 /* go back an fill in fields in IA_NA option */
1569 int sav = save_counter(t1cntr);
1570 unsigned int t1, t2, fuzz = 0;
1572 if (do_fuzz)
1574 fuzz = rand16();
1576 while (fuzz > (min_time/16))
1577 fuzz = fuzz/2;
1580 t1 = (min_time == 0xffffffff) ? 0xffffffff : min_time/2 - fuzz;
1581 t2 = (min_time == 0xffffffff) ? 0xffffffff : ((min_time/8)*7) - fuzz;
1582 put_opt6_long(t1);
1583 put_opt6_long(t2);
1584 save_counter(sav);
1588 static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
1589 unsigned int *min_time, struct in6_addr *addr, time_t now)
1591 unsigned int valid_time = 0, preferred_time = 0;
1592 int o = new_opt6(OPTION6_IAADDR);
1593 struct dhcp_lease *lease;
1595 /* get client requested times */
1596 if (ia_option)
1598 preferred_time = opt6_uint(ia_option, 16, 4);
1599 valid_time = opt6_uint(ia_option, 20, 4);
1602 calculate_times(context, min_time, &valid_time, &preferred_time, lease_time);
1604 put_opt6(addr, sizeof(*addr));
1605 put_opt6_long(preferred_time);
1606 put_opt6_long(valid_time);
1608 #ifdef OPTION6_PREFIX_CLASS
1609 if (state->send_prefix_class)
1611 int o1 = new_opt6(OPTION6_PREFIX_CLASS);
1612 put_opt6_short(state->send_prefix_class->class);
1613 end_opt6(o1);
1615 #endif
1617 end_opt6(o);
1619 if (state->lease_allocate)
1620 update_leases(state, context, addr, valid_time, now);
1622 if ((lease = lease6_find_by_addr(addr, 128, 0)))
1623 lease->flags |= LEASE_USED;
1625 /* get tags from context if we've not used it before */
1626 if (context->netid.next == &context->netid && context->netid.net)
1628 context->netid.next = state->context_tags;
1629 state->context_tags = &context->netid;
1631 if (!state->hostname_auth)
1633 struct dhcp_netid_list *id_list;
1635 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1636 if ((!id_list->list) || match_netid(id_list->list, &context->netid, 0))
1637 break;
1638 if (id_list)
1639 state->hostname = NULL;
1643 #ifdef HAVE_QUIET_DHCP
1644 if (!option_bool(OPT_QUIET_DHCP6))
1645 #endif
1646 log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
1650 static void mark_context_used(struct state *state, struct in6_addr *addr)
1652 struct dhcp_context *context;
1654 /* Mark that we have an address for this prefix. */
1655 #ifdef OPTION6_PREFIX_CLASS
1656 for (context = state->context; context; context = context->current)
1657 if (is_same_net6(addr, &context->start6, context->prefix) &&
1658 (!state->send_prefix_class || state->send_prefix_class == prefix_class_from_context(context)))
1659 context->flags |= CONTEXT_USED;
1660 #else
1661 for (context = state->context; context; context = context->current)
1662 if (is_same_net6(addr, &context->start6, context->prefix))
1663 context->flags |= CONTEXT_USED;
1664 #endif
1667 static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
1669 for (; context; context = context->current)
1670 if (is_same_net6(addr, &context->start6, context->prefix))
1671 context->flags |= CONTEXT_CONF_USED;
1674 /* make sure address not leased to another CLID/IAID */
1675 static int check_address(struct state *state, struct in6_addr *addr)
1677 struct dhcp_lease *lease;
1679 if (!(lease = lease6_find_by_addr(addr, 128, 0)))
1680 return 1;
1682 if (lease->clid_len != state->clid_len ||
1683 memcmp(lease->clid, state->clid, state->clid_len) != 0 ||
1684 lease->iaid != state->iaid)
1685 return 0;
1687 return 1;
1691 /* Calculate valid and preferred times to send in leases/renewals.
1693 Inputs are:
1695 *valid_timep, *preferred_timep - requested times from IAADDR options.
1696 context->valid, context->preferred - times associated with subnet address on local interface.
1697 context->flags | CONTEXT_DEPRECATE - "deprecated" flag in dhcp-range.
1698 lease_time - configured time for context for individual client.
1699 *min_time - smallest valid time sent so far.
1701 Outputs are :
1703 *valid_timep, *preferred_timep - times to be send in IAADDR option.
1704 *min_time - smallest valid time sent so far, to calculate T1 and T2.
1707 static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
1708 unsigned int *preferred_timep, unsigned int lease_time)
1710 unsigned int req_preferred = *preferred_timep, req_valid = *valid_timep;
1711 unsigned int valid_time = lease_time, preferred_time = lease_time;
1713 /* RFC 3315: "A server ignores the lifetimes set
1714 by the client if the preferred lifetime is greater than the valid
1715 lifetime. */
1716 if (req_preferred <= req_valid)
1718 if (req_preferred != 0)
1720 /* 0 == "no preference from client" */
1721 if (req_preferred < 120u)
1722 req_preferred = 120u; /* sanity */
1724 if (req_preferred < preferred_time)
1725 preferred_time = req_preferred;
1728 if (req_valid != 0)
1729 /* 0 == "no preference from client" */
1731 if (req_valid < 120u)
1732 req_valid = 120u; /* sanity */
1734 if (req_valid < valid_time)
1735 valid_time = req_valid;
1739 /* deprecate (preferred == 0) which configured, or when local address
1740 is deprecated */
1741 if ((context->flags & CONTEXT_DEPRECATE) || context->preferred == 0)
1742 preferred_time = 0;
1744 if (preferred_time != 0 && preferred_time < *min_time)
1745 *min_time = preferred_time;
1747 if (valid_time != 0 && valid_time < *min_time)
1748 *min_time = valid_time;
1750 *valid_timep = valid_time;
1751 *preferred_timep = preferred_time;
1754 static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now)
1756 struct dhcp_lease *lease = lease6_find_by_addr(addr, 128, 0);
1757 #ifdef HAVE_SCRIPT
1758 struct dhcp_netid *tagif = run_tag_if(state->tags);
1759 #endif
1761 (void)context;
1763 if (!lease)
1764 lease = lease6_allocate(addr, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
1766 if (lease)
1768 lease_set_expires(lease, lease_time, now);
1769 lease_set_iaid(lease, state->iaid);
1770 lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
1771 lease_set_interface(lease, state->interface, now);
1772 if (state->hostname && state->ia_type == OPTION6_IA_NA)
1774 char *addr_domain = get_domain6(addr);
1775 if (!state->send_domain)
1776 state->send_domain = addr_domain;
1777 lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
1780 #ifdef HAVE_SCRIPT
1781 if (daemon->lease_change_command)
1783 void *class_opt;
1784 lease->flags |= LEASE_CHANGED;
1785 free(lease->extradata);
1786 lease->extradata = NULL;
1787 lease->extradata_size = lease->extradata_len = 0;
1788 lease->vendorclass_count = 0;
1790 if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
1792 void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
1793 lease->vendorclass_count++;
1794 /* send enterprise number first */
1795 sprintf(daemon->dhcp_buff2, "%u", opt6_uint(class_opt, 0, 4));
1796 lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
1798 if (opt6_len(class_opt) >= 6)
1799 for (enc_opt = opt6_ptr(class_opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
1801 lease->vendorclass_count++;
1802 lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
1806 lease_add_extradata(lease, (unsigned char *)state->client_hostname,
1807 state->client_hostname ? strlen(state->client_hostname) : 0, 0);
1809 /* space-concat tag set */
1810 if (!tagif && !context->netid.net)
1811 lease_add_extradata(lease, NULL, 0, 0);
1812 else
1814 if (context->netid.net)
1815 lease_add_extradata(lease, (unsigned char *)context->netid.net, strlen(context->netid.net), tagif ? ' ' : 0);
1817 if (tagif)
1819 struct dhcp_netid *n;
1820 for (n = tagif; n; n = n->next)
1822 struct dhcp_netid *n1;
1823 /* kill dupes */
1824 for (n1 = n->next; n1; n1 = n1->next)
1825 if (strcmp(n->net, n1->net) == 0)
1826 break;
1827 if (!n1)
1828 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
1833 if (state->link_address)
1834 inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN);
1836 lease_add_extradata(lease, (unsigned char *)daemon->addrbuff, state->link_address ? strlen(daemon->addrbuff) : 0, 0);
1838 if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
1840 void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
1841 for (enc_opt = opt6_ptr(class_opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
1842 lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
1845 #endif
1852 static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts)
1854 void *opt;
1855 char *desc = nest ? "nest" : "sent";
1857 if (!option_bool(OPT_LOG_OPTS) || start_opts == end_opts)
1858 return;
1860 for (opt = start_opts; opt; opt = opt6_next(opt, end_opts))
1862 int type = opt6_type(opt);
1863 void *ia_options = NULL;
1864 char *optname;
1866 if (type == OPTION6_IA_NA)
1868 sprintf(daemon->namebuff, "IAID=%u T1=%u T2=%u",
1869 opt6_uint(opt, 0, 4), opt6_uint(opt, 4, 4), opt6_uint(opt, 8, 4));
1870 optname = "ia-na";
1871 ia_options = opt6_ptr(opt, 12);
1873 else if (type == OPTION6_IA_TA)
1875 sprintf(daemon->namebuff, "IAID=%u", opt6_uint(opt, 0, 4));
1876 optname = "ia-ta";
1877 ia_options = opt6_ptr(opt, 4);
1879 else if (type == OPTION6_IAADDR)
1881 inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
1882 sprintf(daemon->namebuff, "%s PL=%u VL=%u",
1883 daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
1884 optname = "iaaddr";
1885 ia_options = opt6_ptr(opt, 24);
1887 #ifdef OPTION6_PREFIX_CLASS
1888 else if (type == OPTION6_PREFIX_CLASS)
1890 optname = "prefix-class";
1891 sprintf(daemon->namebuff, "class=%u", opt6_uint(opt, 0, 2));
1893 #endif
1894 else if (type == OPTION6_STATUS_CODE)
1896 int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
1897 memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
1898 daemon->namebuff[len + opt6_len(opt) - 2] = 0;
1899 optname = "status";
1901 else
1903 /* account for flag byte on FQDN */
1904 int offset = type == OPTION6_FQDN ? 1 : 0;
1905 optname = option_string(AF_INET6, type, opt6_ptr(opt, offset), opt6_len(opt) - offset, daemon->namebuff, MAXDNAME);
1908 my_syslog(MS_DHCP | LOG_INFO, "%u %s size:%3d option:%3d %s %s",
1909 xid, desc, opt6_len(opt), type, optname, daemon->namebuff);
1911 if (ia_options)
1912 log6_opts(1, xid, ia_options, opt6_ptr(opt, opt6_len(opt)));
1916 static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string)
1918 int clid_len = state->clid_len;
1920 /* avoid buffer overflow */
1921 if (clid_len > 100)
1922 clid_len = 100;
1924 print_mac(daemon->namebuff, state->clid, clid_len);
1926 if (addr)
1928 inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
1929 strcat(daemon->dhcp_buff2, " ");
1931 else
1932 daemon->dhcp_buff2[0] = 0;
1934 if(option_bool(OPT_LOG_OPTS))
1935 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s %s",
1936 state->xid,
1937 type,
1938 state->iface_name,
1939 daemon->dhcp_buff2,
1940 daemon->namebuff,
1941 string ? string : "");
1942 else
1943 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s %s",
1944 type,
1945 state->iface_name,
1946 daemon->dhcp_buff2,
1947 daemon->namebuff,
1948 string ? string : "");
1951 static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize)
1953 u16 opt, opt_len;
1954 void *start;
1956 if (!opts)
1957 return NULL;
1959 while (1)
1961 if (end - opts < 4)
1962 return NULL;
1964 start = opts;
1965 GETSHORT(opt, opts);
1966 GETSHORT(opt_len, opts);
1968 if (opt_len > (end - opts))
1969 return NULL;
1971 if (opt == search && (opt_len >= minsize))
1972 return start;
1974 opts += opt_len;
1978 static void *opt6_next(void *opts, void *end)
1980 u16 opt_len;
1982 if (end - opts < 4)
1983 return NULL;
1985 opts += 2;
1986 GETSHORT(opt_len, opts);
1988 if (opt_len >= (end - opts))
1989 return NULL;
1991 return opts + opt_len;
1994 static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
1996 /* this worries about unaligned data and byte order */
1997 unsigned int ret = 0;
1998 int i;
1999 unsigned char *p = opt6_ptr(opt, offset);
2001 for (i = 0; i < size; i++)
2002 ret = (ret << 8) | *p++;
2004 return ret;
2007 void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id)
2009 /* ->local is same value for all relays on ->current chain */
2011 struct all_addr from;
2012 unsigned char *header;
2013 unsigned char *inbuff = daemon->dhcp_packet.iov_base;
2014 int msg_type = *inbuff;
2015 int hopcount;
2016 struct in6_addr multicast;
2017 unsigned int maclen, mactype;
2018 unsigned char mac[DHCP_CHADDR_MAX];
2020 inet_pton(AF_INET6, ALL_SERVERS, &multicast);
2021 get_client_mac(peer_address, scope_id, mac, &maclen, &mactype);
2023 /* source address == relay address */
2024 from.addr.addr6 = relay->local.addr.addr6;
2026 /* Get hop count from nested relayed message */
2027 if (msg_type == DHCP6RELAYFORW)
2028 hopcount = *((unsigned char *)inbuff+1) + 1;
2029 else
2030 hopcount = 0;
2032 /* RFC 3315 HOP_COUNT_LIMIT */
2033 if (hopcount > 32)
2034 return;
2036 save_counter(0);
2038 if ((header = put_opt6(NULL, 34)))
2040 int o;
2042 header[0] = DHCP6RELAYFORW;
2043 header[1] = hopcount;
2044 memcpy(&header[2], &relay->local.addr.addr6, IN6ADDRSZ);
2045 memcpy(&header[18], peer_address, IN6ADDRSZ);
2047 /* RFC-6939 */
2048 if (maclen != 0)
2050 o = new_opt6(OPTION6_CLIENT_MAC);
2051 put_opt6_short(mactype);
2052 put_opt6(mac, maclen);
2053 end_opt6(o);
2056 o = new_opt6(OPTION6_RELAY_MSG);
2057 put_opt6(inbuff, sz);
2058 end_opt6(o);
2060 for (; relay; relay = relay->current)
2062 union mysockaddr to;
2064 to.sa.sa_family = AF_INET6;
2065 to.in6.sin6_addr = relay->server.addr.addr6;
2066 to.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
2067 to.in6.sin6_flowinfo = 0;
2068 to.in6.sin6_scope_id = 0;
2070 if (IN6_ARE_ADDR_EQUAL(&relay->server.addr.addr6, &multicast))
2072 int multicast_iface;
2073 if (!relay->interface || strchr(relay->interface, '*') ||
2074 (multicast_iface = if_nametoindex(relay->interface)) == 0 ||
2075 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1)
2076 my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast to DHCPv6 server without correct interface"));
2079 send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(0), &to, &from, 0);
2081 if (option_bool(OPT_LOG_OPTS))
2083 inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN);
2084 inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN);
2085 my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->namebuff);
2088 /* Save this for replies */
2089 relay->iface_index = scope_id;
2094 unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface)
2096 struct dhcp_relay *relay;
2097 struct in6_addr link;
2098 unsigned char *inbuff = daemon->dhcp_packet.iov_base;
2100 /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
2101 which is 1 + 1 + 16 + 16 + 2 + 2 = 38 */
2103 if (sz < 38 || *inbuff != DHCP6RELAYREPL)
2104 return 0;
2106 memcpy(&link, &inbuff[2], IN6ADDRSZ);
2108 for (relay = daemon->relay6; relay; relay = relay->next)
2109 if (IN6_ARE_ADDR_EQUAL(&link, &relay->local.addr.addr6) &&
2110 (!relay->interface || wildcard_match(relay->interface, arrival_interface)))
2111 break;
2113 save_counter(0);
2115 if (relay)
2117 void *opt, *opts = inbuff + 34;
2118 void *end = inbuff + sz;
2119 for (opt = opts; opt; opt = opt6_next(opt, end))
2120 if (opt6_type(opt) == OPTION6_RELAY_MSG && opt6_len(opt) > 0)
2122 int encap_type = *((unsigned char *)opt6_ptr(opt, 0));
2123 put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
2124 memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ);
2125 peer->sin6_scope_id = relay->iface_index;
2126 return encap_type == DHCP6RELAYREPL ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
2130 return 0;
2133 #endif