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/>.
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
;
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
;
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
;
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
;
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. */
83 struct dhcp_context
*c
;
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
))
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"),
111 my_syslog(MS_DHCP
| LOG_WARNING
,
112 _("no address range available for DHCPv6 request via %s"), iface_name
);
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 */
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
)
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
;
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
;
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
))
165 put_opt6(opt6_ptr(opt
, 0), opt6_len(opt
));
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
;
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
;
199 /* set tag "dhcpv6" */
200 v6_id
.net
= "dhcpv6";
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
);
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
);
236 else if (msg_type
!= DHCP6IREQ
)
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))
246 o
= new_opt6(OPTION6_SERVER_ID
);
247 put_opt6(daemon
->duid
, daemon
->duid_len
);
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");
261 /* match vendor and user class options */
262 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
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
;
273 if ((opt
= opt6_find(packet_options
, end
, mopt
, 2)))
275 void *enc_opt
, *enc_end
= opt6_ptr(opt
, opt6_len(opt
));
278 if (mopt
== OPTION6_VENDOR_CLASS
)
280 if (opt6_len(opt
) < 4)
283 if (vendor
->enterprise
!= opt6_uint(opt
, 0, 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
;
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
307 for (opt_cfg
= daemon
->dhcp_match6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
311 if (opt_cfg
->flags
& DHOPT_RFC3925
)
313 for (opt
= opt6_find(packet_options
, end
, OPTION6_VENDOR_OPTS
, 4);
315 opt
= opt6_find(opt6_next(opt
, end
), end
, OPTION6_VENDOR_OPTS
, 4))
318 void *vend
= opt6_ptr(opt
, opt6_len(opt
));
320 for (vopt
= opt6_find(opt6_ptr(opt
, 4), vend
, opt_cfg
->opt
, 0);
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
))))
331 if (!(opt
= opt6_find(packet_options
, end
, opt_cfg
->opt
, 1)))
334 match
= match_bytes(opt_cfg
, opt6_ptr(opt
, 0), opt6_len(opt
));
339 opt_cfg
->netid
->next
= tags
;
340 tags
= opt_cfg
->netid
;
344 if ((opt
= opt6_find(packet_options
, end
, OPTION6_FQDN
, 1)))
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))
357 if (len
!= 0 && len
< 255)
359 unsigned char *pp
, *op
= opt6_ptr(opt
, 1);
360 char *pq
= daemon
->dhcp_buff
;
363 while (*op
!= 0 && ((op
+ (*op
)) - pp
) < len
)
365 memcpy(pq
, op
+1, *op
);
371 if (pq
!= daemon
->dhcp_buff
)
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
);
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
;
394 else if (client_hostname
)
396 domain
= strip_hostname(client_hostname
);
398 if (strlen(client_hostname
) != 0)
400 hostname
= client_hostname
;
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
)
416 struct dhcp_netid_list
*list
;
418 for (list
= config
->netid
; list
; list
= list
->next
)
420 list
->list
->next
= tags
;
424 /* set "known" tag for known hosts */
425 known_id
.net
= "known";
426 known_id
.next
= tags
;
429 if (have_config(config
, CONFIG_DISABLE
))
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))
445 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
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))
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;
472 o
= new_opt6(OPTION6_RAPID_COMMIT
);
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
);
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;
491 int address_assigned
= 0;
493 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
496 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
499 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
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
);
511 if (ia_type
== OPTION6_IA_NA
)
514 t1cntr
= save_counter(-1);
515 /* so we can fill these in later */
522 struct in6_addr alloced_addr
, *addrp
= NULL
;
523 u32 requested_time
= 0;
524 struct dhcp_lease
*lease
= NULL
;
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");
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");
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");
565 /* must have an address to CONFIRM */
566 if (msg_type
== DHCP6REQUEST
&& ia_type
== OPTION6_IA_NA
)
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);
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"),
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
);
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
;
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)
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
;
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))
637 if (have_config(valid_config
, CONFIG_TIME
))
638 lease_time
= valid_config
->lease_time
;
640 lease_time
= this_context
->lease_time
;
642 if (this_context
->valid
< lease_time
)
643 lease_time
= this_context
->valid
;
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
);
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
);
669 send_domain
= addr_domain
;
670 lease_set_hostname(lease
, hostname
, hostname_auth
, addr_domain
, domain
);
674 if (daemon
->lease_change_command
)
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
));
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
))
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);
707 struct dhcp_netid
*n
, *l
, *tmp
= tags
;
709 /* link temporarily */
710 for (n
= context_tags
; n
&& n
->next
; n
= n
->next
);
717 for (n
= run_tag_if(tmp
); n
; n
= n
->next
)
719 struct dhcp_netid
*n1
;
721 for (n1
= n
->next
; n1
; n1
= n1
->next
)
722 if (strcmp(n
->net
, n1
->net
) == 0)
725 lease_add_extradata(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
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);
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 */
762 log6_packet( make_lease
? "DHCPREPLY" : "DHCPADVERTISE",
763 clid
, clid_len
, addrp
, xid
, iface_name
, hostname
);
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");
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
);
793 /* no address, return error */
794 o1
= new_opt6(OPTION6_STATUS_CODE
);
795 put_opt6_short(DHCP6NOADDRS
);
796 put_opt6_string("No addresses available");
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);
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
;
834 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
837 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
840 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
843 iaid
= opt6_uint(opt
, 0, 4);
845 o
= new_opt6(ia_type
);
847 if (ia_type
== OPTION6_IA_NA
)
850 t1cntr
= save_counter(-1);
851 /* so we can fill these in later */
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);
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)
879 if (!(lease
= lease6_find(clid
, clid_len
,
880 ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
,
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
);
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");
899 if (!address6_available(context
, req_addr
, tagif
) ||
900 !(this_context
= narrow_context6(context
, req_addr
, tagif
)))
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
;
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))
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
);
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 */
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))
962 t1
= min_time
== 0xffffffff ? 0xffffffff : min_time
/2 - fuzz
;
963 t2
= min_time
== 0xffffffff ? 0xffffffff : ((min_time
/8)*7) - fuzz
;
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
)
991 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
994 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
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);
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");
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");
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
);
1038 *outmsgtypep
= DHCP6REPLY
;
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
;
1056 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
1059 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
1062 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
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);
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
);
1085 o
= new_opt6(ia_type
);
1086 put_opt6_long(iaid
);
1087 if (ia_type
== OPTION6_IA_NA
)
1095 o1
= new_opt6(OPTION6_IAADDR
);
1096 put_opt6(opt6_ptr(ia_option
, 0), IN6ADDRSZ
);
1105 o1
= new_opt6(OPTION6_STATUS_CODE
);
1106 put_opt6_short(DHCP6NOBINDING
);
1107 put_opt6_string("No binding found");
1114 o1
= new_opt6(OPTION6_STATUS_CODE
);
1115 put_opt6_short(DHCP6SUCCESS
);
1116 put_opt6_string("Release received");
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
;
1135 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
1138 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
1141 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
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);
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
;
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
);
1180 o
= new_opt6(ia_type
);
1181 put_opt6_long(iaid
);
1182 if (ia_type
== OPTION6_IA_NA
)
1190 o1
= new_opt6(OPTION6_IAADDR
);
1191 put_opt6(opt6_ptr(ia_option
, 0), IN6ADDRSZ
);
1200 o1
= new_opt6(OPTION6_STATUS_CODE
);
1201 put_opt6_short(DHCP6NOBINDING
);
1202 put_opt6_string("No binding found");
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
))
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
)
1232 /* option not requested */
1233 if (i
>= opt6_len(oro
) - 1)
1237 if (opt_cfg
->opt
== OPTION6_DNS_SERVER
)
1240 if (opt_cfg
->len
== 0)
1244 o
= new_opt6(opt_cfg
->opt
);
1245 if (opt_cfg
->flags
& DHOPT_ADDR6
)
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
);
1257 put_opt6(&context
->local6
, IN6ADDRSZ
);
1260 put_opt6(a
, IN6ADDRSZ
);
1263 else if (opt_cfg
->val
)
1264 put_opt6(opt_cfg
->val
, opt_cfg
->len
);
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
);
1276 put_opt6(&context
->local6
, IN6ADDRSZ
);
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
;
1286 for (i
= 0; i
< opt6_len(oro
) - 1; i
+= 2)
1287 if (opt6_uint(oro
, i
, 2) == OPTION6_VENDOR_OPTS
)
1290 for (opt_cfg
= daemon
->dhcp_opts6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
1292 if (opt_cfg
->flags
& DHOPT_RFC3925
)
1295 struct dhcp_opt
*oc
;
1297 if (opt_cfg
->flags
& DHOPT_ENCAP_DONE
)
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
)
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
;
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
);
1340 size_t len
= strlen(hostname
);
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
);
1351 p
= do_rfc1035_name(p
, send_domain
);
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
),
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));
1387 static void log6_opts(int nest
, unsigned int xid
, void *start_opts
, void *end_opts
)
1390 char *desc
= nest
? "nest" : "sent";
1392 if (start_opts
== end_opts
)
1395 for (opt
= start_opts
; opt
; opt
= opt6_next(opt
, end_opts
))
1397 int type
= opt6_type(opt
);
1398 void *ia_options
= NULL
;
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));
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));
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));
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;
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
);
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 */
1450 print_mac(daemon
->namebuff
, clid
, clid_len
);
1454 inet_ntop(AF_INET6
, addr
, daemon
->dhcp_buff2
, 255);
1455 strcat(daemon
->dhcp_buff2
, " ");
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",
1467 string
? string
: "");
1469 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s %s",
1474 string
? string
: "");
1477 static void *opt6_find (void *opts
, void *end
, unsigned int search
, unsigned int minsize
)
1491 GETSHORT(opt
, opts
);
1492 GETSHORT(opt_len
, opts
);
1494 if (opt_len
> (end
- opts
))
1497 if (opt
== search
&& (opt_len
>= minsize
))
1504 static void *opt6_next(void *opts
, void *end
)
1512 GETSHORT(opt_len
, opts
);
1514 if (opt_len
>= (end
- opts
))
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;
1525 unsigned char *p
= opt6_ptr(opt
, offset
);
1527 for (i
= 0; i
< size
; i
++)
1528 ret
= (ret
<< 8) | *p
++;