]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc3315.c
1 /* dnsmasq is Copyright (c) 2000-2012 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 for (c
= daemon
->dhcp6
; c
; c
= c
->next
)
87 if (!IN6_IS_ADDR_LOOPBACK(link_address
) &&
88 !IN6_IS_ADDR_LINKLOCAL(link_address
) &&
89 !IN6_IS_ADDR_MULTICAST(link_address
) &&
90 is_same_net6(link_address
, &c
->start6
, c
->prefix
) &&
91 is_same_net6(link_address
, &c
->end6
, c
->prefix
))
99 inet_ntop(AF_INET6
, link_address
, daemon
->addrbuff
, ADDRSTRLEN
);
100 my_syslog(MS_DHCP
| LOG_WARNING
,
101 _("no address range available for DHCPv6 request from relay at %s"),
109 my_syslog(MS_DHCP
| LOG_WARNING
,
110 _("no address range available for DHCPv6 request via %s"), iface_name
);
114 return dhcp6_no_relay(msg_type
, link_address
, *relay_tagsp
, context
, interface
, iface_name
, fallback
, inbuff
, sz
, is_unicast
, now
);
117 /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
118 which is 1 + 1 + 16 + 16 + 2 + 2 = 38 */
122 /* copy header stuff into reply message and set type to reply */
123 outmsgtypep
= put_opt6(inbuff
, 34);
124 *outmsgtypep
= DHCP6RELAYREPL
;
126 /* look for relay options and set tags if found. */
127 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
131 if (vendor
->match_type
== MATCH_SUBSCRIBER
)
132 mopt
= OPTION6_SUBSCRIBER_ID
;
133 else if (vendor
->match_type
== MATCH_REMOTE
)
134 mopt
= OPTION6_REMOTE_ID
;
138 if ((opt
= opt6_find(opts
, end
, mopt
, 1)) &&
139 vendor
->len
== opt6_len(opt
) &&
140 memcmp(vendor
->data
, opt6_ptr(opt
, 0), vendor
->len
) == 0 &&
141 vendor
->netid
.next
!= &vendor
->netid
)
143 vendor
->netid
.next
= *relay_tagsp
;
144 *relay_tagsp
= &vendor
->netid
;
149 for (opt
= opts
; opt
; opt
= opt6_next(opt
, end
))
151 int o
= new_opt6(opt6_type(opt
));
152 if (opt6_type(opt
) == OPTION6_RELAY_MSG
)
154 struct in6_addr link_address
;
155 /* the packet data is unaligned, copy to aligned storage */
156 memcpy(&link_address
, inbuff
+ 2, IN6ADDRSZ
);
157 /* Not, zero is_unicast since that is now known to refer to the
158 relayed packet, not the original sent by the client */
159 if (!dhcp6_maybe_relay(&link_address
, relay_tagsp
, context
, interface
, iface_name
, fallback
, opt6_ptr(opt
, 0), opt6_len(opt
), 0, now
))
163 put_opt6(opt6_ptr(opt
, 0), opt6_len(opt
));
170 static int dhcp6_no_relay(int msg_type
, struct in6_addr
*link_address
, struct dhcp_netid
*tags
, struct dhcp_context
*context
,
171 int interface
, char *iface_name
, struct in6_addr
*fallback
, void *inbuff
, size_t sz
, int is_unicast
, time_t now
)
173 void *packet_options
= inbuff
+ 4;
174 void *end
= inbuff
+ sz
;
177 unsigned char *clid
= NULL
;
178 int clid_len
= 0, start_opts
;
179 struct dhcp_netid
*tagif
, *context_tags
= NULL
;
180 char *client_hostname
= NULL
, *hostname
= NULL
;
181 char *domain
= NULL
, *send_domain
= NULL
;
182 struct dhcp_config
*config
= NULL
;
183 struct dhcp_netid known_id
, iface_id
;
184 int done_dns
= 0, hostname_auth
= 0, do_encap
= 0;
185 unsigned char *outmsgtypep
;
186 struct dhcp_opt
*opt_cfg
;
187 struct dhcp_vendor
*vendor
;
188 struct dhcp_context
*context_tmp
;
189 unsigned int xid
, ignore
= 0;
190 unsigned int fqdn_flags
= 0x01; /* default to send if we recieve no FQDN option */
192 /* set tag with name == interface */
193 iface_id
.net
= iface_name
;
194 iface_id
.next
= tags
;
197 /* copy over transaction-id, and save pointer to message type */
198 outmsgtypep
= put_opt6(inbuff
, 4);
199 start_opts
= save_counter(-1);
200 xid
= outmsgtypep
[3] | outmsgtypep
[2] << 8 | outmsgtypep
[1] << 16;
202 /* We're going to be linking tags from all context we use.
203 mark them as unused so we don't link one twice and break the list */
204 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
206 context
->netid
.next
= &context
->netid
;
208 if (option_bool(OPT_LOG_OPTS
))
210 inet_ntop(AF_INET6
, &context_tmp
->start6
, daemon
->dhcp_buff
, ADDRSTRLEN
);
211 inet_ntop(AF_INET6
, &context_tmp
->end6
, daemon
->dhcp_buff2
, ADDRSTRLEN
);
212 if (context_tmp
->flags
& (CONTEXT_STATIC
))
213 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCPv6 subnet: %s/%d"),
214 xid
, daemon
->dhcp_buff
, context_tmp
->prefix
);
216 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
217 xid
, daemon
->dhcp_buff
, daemon
->dhcp_buff2
);
221 if ((opt
= opt6_find(packet_options
, end
, OPTION6_CLIENT_ID
, 1)))
223 clid
= opt6_ptr(opt
, 0);
224 clid_len
= opt6_len(opt
);
225 o
= new_opt6(OPTION6_CLIENT_ID
);
226 put_opt6(clid
, clid_len
);
229 else if (msg_type
!= DHCP6IREQ
)
232 /* server-id must match except for SOLICIT and CONFIRM messages */
233 if (msg_type
!= DHCP6SOLICIT
&& msg_type
!= DHCP6CONFIRM
&& msg_type
!= DHCP6IREQ
&&
234 (!(opt
= opt6_find(packet_options
, end
, OPTION6_SERVER_ID
, 1)) ||
235 opt6_len(opt
) != daemon
->duid_len
||
236 memcmp(opt6_ptr(opt
, 0), daemon
->duid
, daemon
->duid_len
) != 0))
239 o
= new_opt6(OPTION6_SERVER_ID
);
240 put_opt6(daemon
->duid
, daemon
->duid_len
);
244 (msg_type
== DHCP6REQUEST
|| msg_type
== DHCP6RENEW
|| msg_type
== DHCP6RELEASE
|| msg_type
== DHCP6DECLINE
))
247 o1
= new_opt6(OPTION6_STATUS_CODE
);
248 put_opt6_short(DHCP6USEMULTI
);
249 put_opt6_string("Use multicast");
254 /* match vendor and user class options */
255 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
259 if (vendor
->match_type
== MATCH_VENDOR
)
260 mopt
= OPTION6_VENDOR_CLASS
;
261 else if (vendor
->match_type
== MATCH_USER
)
262 mopt
= OPTION6_USER_CLASS
;
266 if ((opt
= opt6_find(packet_options
, end
, mopt
, 2)))
268 void *enc_opt
, *enc_end
= opt6_ptr(opt
, opt6_len(opt
));
271 if (mopt
== OPTION6_VENDOR_CLASS
)
273 if (opt6_len(opt
) < 4)
276 if (vendor
->enterprise
!= opt6_uint(opt
, 0, 4))
282 for (enc_opt
= opt6_ptr(opt
, offset
); enc_opt
; enc_opt
= opt6_next(enc_opt
, enc_end
))
283 for (i
= 0; i
<= (opt6_len(enc_opt
) - vendor
->len
); i
++)
284 if (memcmp(vendor
->data
, opt6_ptr(enc_opt
, i
), vendor
->len
) == 0)
286 vendor
->netid
.next
= tags
;
287 tags
= &vendor
->netid
;
293 if (option_bool(OPT_LOG_OPTS
) && (opt
= opt6_find(packet_options
, end
, OPTION6_VENDOR_CLASS
, 4)))
294 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %u"), xid
, opt6_uint(opt
, 0, 4));
296 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
297 Otherwise assume the option is an array, and look for a matching element.
298 If no data given, existance of the option is enough. This code handles
300 for (opt_cfg
= daemon
->dhcp_match6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
304 if (opt_cfg
->flags
& DHOPT_RFC3925
)
306 for (opt
= opt6_find(packet_options
, end
, OPTION6_VENDOR_OPTS
, 4);
308 opt
= opt6_find(opt6_next(opt
, end
), end
, OPTION6_VENDOR_OPTS
, 4))
311 void *vend
= opt6_ptr(opt
, opt6_len(opt
));
313 for (vopt
= opt6_find(opt6_ptr(opt
, 4), vend
, opt_cfg
->opt
, 0);
315 vopt
= opt6_find(opt6_next(vopt
, vend
), vend
, opt_cfg
->opt
, 0))
316 if ((match
= match_bytes(opt_cfg
, opt6_ptr(vopt
, 0), opt6_len(vopt
))))
324 if (!(opt
= opt6_find(packet_options
, end
, opt_cfg
->opt
, 1)))
327 match
= match_bytes(opt_cfg
, opt6_ptr(opt
, 0), opt6_len(opt
));
332 opt_cfg
->netid
->next
= tags
;
333 tags
= opt_cfg
->netid
;
337 if ((opt
= opt6_find(packet_options
, end
, OPTION6_FQDN
, 1)))
340 int len
= opt6_len(opt
) - 1;
342 fqdn_flags
= opt6_uint(opt
, 0, 1);
344 /* Always force update, since the client has no way to do it itself. */
345 if (!option_bool(OPT_FQDN_UPDATE
) && !(fqdn_flags
& 0x01))
350 if (len
!= 0 && len
< 255)
352 unsigned char *pp
, *op
= opt6_ptr(opt
, 1);
353 char *pq
= daemon
->dhcp_buff
;
356 while (*op
!= 0 && ((op
+ (*op
)) - pp
) < len
)
358 memcpy(pq
, op
+1, *op
);
364 if (pq
!= daemon
->dhcp_buff
)
368 if (legal_hostname(daemon
->dhcp_buff
))
370 client_hostname
= daemon
->dhcp_buff
;
371 if (option_bool(OPT_LOG_OPTS
))
372 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), xid
, client_hostname
);
379 config
= find_config6(daemon
->dhcp_conf
, context
, clid
, clid_len
, NULL
);
381 if (have_config(config
, CONFIG_NAME
))
383 hostname
= config
->hostname
;
384 domain
= config
->domain
;
387 else if (client_hostname
)
389 domain
= strip_hostname(client_hostname
);
391 if (strlen(client_hostname
) != 0)
393 hostname
= client_hostname
;
396 /* Search again now we have a hostname.
397 Only accept configs without CLID here, (it won't match)
398 to avoid impersonation by name. */
399 struct dhcp_config
*new = find_config6(daemon
->dhcp_conf
, context
, NULL
, 0, hostname
);
400 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
409 struct dhcp_netid_list
*list
;
411 for (list
= config
->netid
; list
; list
= list
->next
)
413 list
->list
->next
= tags
;
417 /* set "known" tag for known hosts */
418 known_id
.net
= "known";
419 known_id
.next
= tags
;
422 if (have_config(config
, CONFIG_DISABLE
))
426 tagif
= run_tag_if(tags
);
428 /* if all the netids in the ignore list are present, ignore this client */
429 if (daemon
->dhcp_ignore
)
431 struct dhcp_netid_list
*id_list
;
433 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
434 if (match_netid(id_list
->list
, tagif
, 0))
438 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
441 struct dhcp_netid_list
*id_list
;
443 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
444 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif
, 0))
459 void *rapid_commit
= opt6_find(packet_options
, end
, OPTION6_RAPID_COMMIT
, 0);
460 int make_lease
= (msg_type
== DHCP6REQUEST
|| rapid_commit
);
461 int serial
= 0, used_config
= 0;
465 o
= new_opt6(OPTION6_RAPID_COMMIT
);
469 /* set reply message type */
470 *outmsgtypep
= make_lease
? DHCP6REPLY
: DHCP6ADVERTISE
;
472 log6_packet(msg_type
== DHCP6SOLICIT
? "DHCPSOLICIT" : "DHCPREQUEST",
473 clid
, clid_len
, NULL
, xid
, iface_name
, ignore
? "ignored" : NULL
);
478 for (opt
= packet_options
; opt
; opt
= opt6_next(opt
, end
))
480 int iaid
, ia_type
= opt6_type(opt
);
481 void *ia_option
, *ia_end
;
482 unsigned int min_time
= 0xffffffff;
484 int address_assigned
= 0;
486 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
489 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
492 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
495 iaid
= opt6_uint(opt
, 0, 4);
496 ia_end
= opt6_ptr(opt
, opt6_len(opt
));
497 ia_option
= opt6_find(opt6_ptr(opt
, ia_type
== OPTION6_IA_NA
? 12 : 4), ia_end
, OPTION6_IAADDR
, 24);
499 /* reset "USED" flags on leases */
500 lease6_find(NULL
, 0, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
, iaid
, NULL
);
502 o
= new_opt6(ia_type
);
504 if (ia_type
== OPTION6_IA_NA
)
507 t1cntr
= save_counter(-1);
508 /* so we can fill these in later */
515 struct in6_addr alloced_addr
, *addrp
= NULL
;
516 u32 requested_time
= 0;
517 struct dhcp_lease
*lease
= NULL
;
521 struct in6_addr
*req_addr
= opt6_ptr(ia_option
, 0);
522 requested_time
= opt6_uint(ia_option
, 16, 4);
524 if (!address6_available(context
, req_addr
, tags
) &&
525 (!have_config(config
, CONFIG_ADDR6
) || memcmp(&config
->addr6
, req_addr
, IN6ADDRSZ
) != 0))
527 if (msg_type
== DHCP6REQUEST
)
529 /* host has a lease, but it's not on the correct link */
530 o1
= new_opt6(OPTION6_STATUS_CODE
);
531 put_opt6_short(DHCP6NOTONLINK
);
532 put_opt6_string("Not on link");
536 else if ((lease
= lease6_find(NULL
, 0, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
,
538 (clid_len
!= lease
->clid_len
||
539 memcmp(clid
, lease
->clid
, clid_len
) != 0))
541 /* Address leased to another DUID */
542 o1
= new_opt6(OPTION6_STATUS_CODE
);
543 put_opt6_short(DHCP6UNSPEC
);
544 put_opt6_string("Address in use");
552 /* must have an address to CONFIRM */
553 if (msg_type
== DHCP6REQUEST
&& ia_type
== OPTION6_IA_NA
)
556 /* Don't used configured addresses for temporary leases. */
557 if (have_config(config
, CONFIG_ADDR6
) && !used_config
&& ia_type
== OPTION6_IA_NA
)
559 struct dhcp_lease
*ltmp
= lease6_find_by_addr(&config
->addr6
, 128, 0);
562 inet_ntop(AF_INET6
, &config
->addr6
, daemon
->addrbuff
, ADDRSTRLEN
);
564 if (ltmp
&& ltmp
->clid
&&
565 (ltmp
->clid_len
!= clid_len
|| memcmp(ltmp
->clid
, clid
, clid_len
) != 0))
566 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
567 daemon
->addrbuff
, print_mac(daemon
->namebuff
, ltmp
->clid
, ltmp
->clid_len
));
568 else if (have_config(config
, CONFIG_DECLINED
) &&
569 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
570 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"),
573 addrp
= &config
->addr6
;
578 (lease
= lease6_find(clid
, clid_len
,
579 ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
, iaid
, NULL
)) &&
580 address6_available(context
, (struct in6_addr
*)&lease
->hwaddr
, tags
) &&
581 !config_find_by_address6(daemon
->dhcp_conf
, (struct in6_addr
*)&lease
->hwaddr
, 128, 0))
582 addrp
= (struct in6_addr
*)&lease
->hwaddr
;
584 if (!addrp
&& address6_allocate(context
, clid
, clid_len
, serial
++, tags
, &alloced_addr
))
585 addrp
= &alloced_addr
;
590 unsigned int lease_time
;
591 struct dhcp_context
*this_context
;
592 struct dhcp_config
*valid_config
= config
;
594 /* don't use a config to set lease time if it specifies an address which isn't this. */
595 if (have_config(config
, CONFIG_ADDR6
) && memcmp(&config
->addr6
, addrp
, IN6ADDRSZ
) != 0)
598 address_assigned
= 1;
600 /* shouldn't ever fail */
601 if ((this_context
= narrow_context6(context
, addrp
, tagif
)))
603 /* get tags from context if we've not used it before */
604 if (this_context
->netid
.next
== &this_context
->netid
&& this_context
->netid
.net
)
606 this_context
->netid
.next
= context_tags
;
607 context_tags
= &this_context
->netid
;
610 struct dhcp_netid_list
*id_list
;
612 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
613 if ((!id_list
->list
) || match_netid(id_list
->list
, &this_context
->netid
, 0))
620 lease_time
= have_config(valid_config
, CONFIG_TIME
) ? valid_config
->lease_time
: this_context
->lease_time
;
624 if (requested_time
< 120u )
625 requested_time
= 120u; /* sanity */
626 if (lease_time
== 0xffffffff || (requested_time
!= 0xffffffff && requested_time
< lease_time
))
627 lease_time
= requested_time
;
630 if (lease_time
< min_time
)
631 min_time
= lease_time
;
633 /* May fail to create lease */
634 if (!lease
&& make_lease
)
635 lease
= lease6_allocate(addrp
, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
);
639 lease_set_expires(lease
, lease_time
, now
);
640 lease_set_hwaddr(lease
, NULL
, clid
, 0, iaid
, clid_len
, now
, 0);
641 lease_set_interface(lease
, interface
, now
);
642 if (hostname
&& ia_type
== OPTION6_IA_NA
)
644 char *addr_domain
= get_domain6(addrp
);
646 send_domain
= addr_domain
;
647 lease_set_hostname(lease
, hostname
, hostname_auth
, addr_domain
, domain
);
651 if (daemon
->lease_change_command
)
654 lease
->flags
|= LEASE_CHANGED
;
655 free(lease
->extradata
);
656 lease
->extradata
= NULL
;
657 lease
->extradata_size
= lease
->extradata_len
= 0;
658 lease
->hwaddr_len
= 0; /* surrogate for no of vendor classes */
660 if ((class_opt
= opt6_find(packet_options
, end
, OPTION6_VENDOR_CLASS
, 4)))
662 void *enc_opt
, *enc_end
= opt6_ptr(class_opt
, opt6_len(class_opt
));
664 /* send enterprise number first */
665 sprintf(daemon
->dhcp_buff2
, "%u", opt6_uint(class_opt
, 0, 4));
666 lease_add_extradata(lease
, (unsigned char *)daemon
->dhcp_buff2
, strlen(daemon
->dhcp_buff2
), 0);
668 if (opt6_len(class_opt
) >= 6)
669 for (enc_opt
= opt6_ptr(class_opt
, 4); enc_opt
; enc_opt
= opt6_next(enc_opt
, enc_end
))
672 lease_add_extradata(lease
, opt6_ptr(enc_opt
, 0), opt6_len(enc_opt
), 0);
676 lease_add_extradata(lease
, (unsigned char *)client_hostname
,
677 client_hostname
? strlen(client_hostname
) : 0, 0);
679 /* space-concat tag set */
680 if (!tagif
&& !context_tags
)
681 lease_add_extradata(lease
, NULL
, 0, 0);
684 struct dhcp_netid
*n
, *l
, *tmp
= tags
;
686 /* link temporarily */
687 for (n
= context_tags
; n
&& n
->next
; n
= n
->next
);
694 for (n
= run_tag_if(tmp
); n
; n
= n
->next
)
696 struct dhcp_netid
*n1
;
698 for (n1
= n
->next
; n1
; n1
= n1
->next
)
699 if (strcmp(n
->net
, n1
->net
) == 0)
702 lease_add_extradata(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
711 inet_ntop(AF_INET6
, link_address
, daemon
->addrbuff
, ADDRSTRLEN
);
713 lease_add_extradata(lease
, (unsigned char *)daemon
->addrbuff
, link_address
? strlen(daemon
->addrbuff
) : 0, 0);
715 if ((class_opt
= opt6_find(packet_options
, end
, OPTION6_USER_CLASS
, 2)))
717 void *enc_opt
, *enc_end
= opt6_ptr(class_opt
, opt6_len(class_opt
));
718 for (enc_opt
= opt6_ptr(class_opt
, 0); enc_opt
; enc_opt
= opt6_next(enc_opt
, enc_end
))
719 lease_add_extradata(lease
, opt6_ptr(enc_opt
, 0), opt6_len(enc_opt
), 0);
725 else if (!send_domain
)
726 send_domain
= get_domain6(addrp
);
729 if (lease
|| !make_lease
)
731 o1
= new_opt6(OPTION6_IAADDR
);
732 put_opt6(addrp
, sizeof(*addrp
));
733 /* preferred lifetime */
734 put_opt6_long(this_context
&& (this_context
->flags
& CONTEXT_DEPRECATE
) ? 0 : lease_time
);
735 put_opt6_long(lease_time
); /* valid lifetime */
738 log6_packet( make_lease
? "DHCPREPLY" : "DHCPADVERTISE",
739 clid
, clid_len
, addrp
, xid
, iface_name
, hostname
);
747 !(ia_option
= opt6_find(opt6_next(ia_option
, ia_end
), ia_end
, OPTION6_IAADDR
, 24)))
749 if (address_assigned
)
751 o1
= new_opt6(OPTION6_STATUS_CODE
);
752 put_opt6_short(DHCP6SUCCESS
);
753 put_opt6_string("Oh hai from dnsmasq");
756 if (ia_type
== OPTION6_IA_NA
)
758 /* go back an fill in fields in IA_NA option */
759 unsigned int t1
= min_time
== 0xffffffff ? 0xffffffff : min_time
/2;
760 unsigned int t2
= min_time
== 0xffffffff ? 0xffffffff : (min_time
/8) * 7;
761 int sav
= save_counter(t1cntr
);
769 /* no address, return error */
770 o1
= new_opt6(OPTION6_STATUS_CODE
);
771 put_opt6_short(DHCP6NOADDRS
);
772 put_opt6_string("No addresses available");
778 if (address_assigned
)
780 /* If --dhcp-authoritative is set, we can tell client not to wait for
781 other possible servers */
782 o
= new_opt6(OPTION6_PREFERENCE
);
783 put_opt6_char(option_bool(OPT_AUTHORITATIVE
) ? 255 : 0);
797 /* set reply message type */
798 *outmsgtypep
= DHCP6REPLY
;
800 log6_packet("DHCPRENEW", clid
, clid_len
, NULL
, xid
, iface_name
, NULL
);
802 for (opt
= packet_options
; opt
; opt
= opt6_next(opt
, end
))
804 int ia_type
= opt6_type(opt
);
805 void *ia_option
, *ia_end
;
806 unsigned int min_time
= 0xffffffff;
807 int t1cntr
= 0, iacntr
;
810 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
813 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
816 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
819 iaid
= opt6_uint(opt
, 0, 4);
821 o
= new_opt6(ia_type
);
823 if (ia_type
== OPTION6_IA_NA
)
826 t1cntr
= save_counter(-1);
827 /* so we can fill these in later */
832 iacntr
= save_counter(-1);
834 /* reset "USED" flags on leases */
835 lease6_find(NULL
, 0, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
, iaid
, NULL
);
837 ia_option
= opt6_ptr(opt
, ia_type
== OPTION6_IA_NA
? 12 : 4);
838 ia_end
= opt6_ptr(opt
, opt6_len(opt
));
840 for (ia_option
= opt6_find(ia_option
, ia_end
, OPTION6_IAADDR
, 24);
842 ia_option
= opt6_find(opt6_next(ia_option
, ia_end
), ia_end
, OPTION6_IAADDR
, 24))
844 struct dhcp_lease
*lease
= NULL
;
845 struct in6_addr
*req_addr
= opt6_ptr(ia_option
, 0);
846 u32 requested_time
= opt6_uint(ia_option
, 16, 4);
847 unsigned int lease_time
;
848 struct dhcp_context
*this_context
;
849 struct dhcp_config
*valid_config
= config
;
851 /* don't use a config to set lease time if it specifies an address which isn't this. */
852 if (have_config(config
, CONFIG_ADDR6
) && memcmp(&config
->addr6
, req_addr
, IN6ADDRSZ
) != 0)
855 if (!(lease
= lease6_find(clid
, clid_len
,
856 ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
,
859 /* If the server cannot find a client entry for the IA the server
860 returns the IA containing no addresses with a Status Code option set
861 to NoBinding in the Reply message. */
862 save_counter(iacntr
);
865 log6_packet("DHCPREPLY", clid
, clid_len
, req_addr
, xid
, iface_name
, "lease not found");
867 o1
= new_opt6(OPTION6_STATUS_CODE
);
868 put_opt6_short(DHCP6NOBINDING
);
869 put_opt6_string("No binding found");
875 if (!address6_available(context
, req_addr
, tagif
) ||
876 !(this_context
= narrow_context6(context
, req_addr
, tagif
)))
883 /* get tags from context if we've not used it before */
884 if (this_context
->netid
.next
== &this_context
->netid
&& this_context
->netid
.net
)
886 this_context
->netid
.next
= context_tags
;
887 context_tags
= &this_context
->netid
;
890 struct dhcp_netid_list
*id_list
;
892 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
893 if ((!id_list
->list
) || match_netid(id_list
->list
, &this_context
->netid
, 0))
900 lease_time
= have_config(valid_config
, CONFIG_TIME
) ? valid_config
->lease_time
: this_context
->lease_time
;
902 if (requested_time
< 120u )
903 requested_time
= 120u; /* sanity */
904 if (lease_time
== 0xffffffff || (requested_time
!= 0xffffffff && requested_time
< lease_time
))
905 lease_time
= requested_time
;
907 lease_set_expires(lease
, lease_time
, now
);
908 if (ia_type
== OPTION6_IA_NA
&& hostname
)
910 char *addr_domain
= get_domain6(req_addr
);
912 send_domain
= addr_domain
;
913 lease_set_hostname(lease
, hostname
, hostname_auth
, addr_domain
, domain
);
916 if (lease_time
< min_time
)
917 min_time
= lease_time
;
920 log6_packet("DHCPREPLY", clid
, clid_len
, req_addr
, xid
, iface_name
, hostname
);
922 o1
= new_opt6(OPTION6_IAADDR
);
923 put_opt6(req_addr
, sizeof(*req_addr
));
924 /* preferred lifetime */
925 put_opt6_long(this_context
&& (this_context
->flags
& CONTEXT_DEPRECATE
) ? 0 : lease_time
);
926 put_opt6_long(lease_time
); /* valid lifetime */
932 /* go back an fill in fields in IA_NA option */
933 int sav
= save_counter(t1cntr
);
934 unsigned int t1
, t2
, fuzz
= rand16();
936 while (fuzz
> (min_time
/16))
938 t1
= min_time
== 0xffffffff ? 0xffffffff : min_time
/2 - fuzz
;
939 t2
= min_time
== 0xffffffff ? 0xffffffff : ((min_time
/8)*7) - fuzz
;
954 /* set reply message type */
955 *outmsgtypep
= DHCP6REPLY
;
957 log6_packet("DHCPCONFIRM", clid
, clid_len
, NULL
, xid
, iface_name
, NULL
);
959 for (opt
= packet_options
; opt
; opt
= opt6_next(opt
, end
))
961 int ia_type
= opt6_type(opt
);
962 void *ia_option
, *ia_end
;
964 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
967 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
970 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
973 ia_option
= opt6_ptr(opt
, ia_type
== OPTION6_IA_NA
? 12 : 4);
974 ia_end
= opt6_ptr(opt
, opt6_len(opt
));
976 for (ia_option
= opt6_find(ia_option
, ia_end
, OPTION6_IAADDR
, 24);
978 ia_option
= opt6_find(opt6_next(ia_option
, ia_end
), ia_end
, OPTION6_IAADDR
, 24))
980 struct in6_addr
*req_addr
= opt6_ptr(ia_option
, 0);
982 if (!address6_available(context
, req_addr
, run_tag_if(tags
)))
984 o1
= new_opt6(OPTION6_STATUS_CODE
);
985 put_opt6_short(DHCP6NOTONLINK
);
986 put_opt6_string("Confirm failed");
991 log6_packet("DHCPREPLY", clid
, clid_len
, req_addr
, xid
, iface_name
, hostname
);
995 o1
= new_opt6(OPTION6_STATUS_CODE
);
996 put_opt6_short(DHCP6SUCCESS
);
997 put_opt6_string("All addresses still on link");
1006 *outmsgtypep
= DHCP6REPLY
;
1007 log6_packet("DHCPINFORMATION-REQUEST", clid
, clid_len
, NULL
, xid
, iface_name
, hostname
);
1014 /* set reply message type */
1015 *outmsgtypep
= DHCP6REPLY
;
1017 log6_packet("DHCPRELEASE", clid
, clid_len
, NULL
, xid
, iface_name
, NULL
);
1019 for (opt
= packet_options
; opt
; opt
= opt6_next(opt
, end
))
1021 int iaid
, ia_type
= opt6_type(opt
);
1022 void *ia_option
, *ia_end
;
1025 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
1028 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
1031 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
1034 iaid
= opt6_uint(opt
, 0, 4);
1035 ia_end
= opt6_ptr(opt
, opt6_len(opt
));
1036 ia_option
= opt6_ptr(opt
, ia_type
== OPTION6_IA_NA
? 12 : 4);
1038 /* reset "USED" flags on leases */
1039 lease6_find(NULL
, 0, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
, iaid
, NULL
);
1041 for (ia_option
= opt6_find(ia_option
, ia_end
, OPTION6_IAADDR
, 24);
1043 ia_option
= opt6_find(opt6_next(ia_option
, ia_end
), ia_end
, OPTION6_IAADDR
, 24))
1045 struct dhcp_lease
*lease
;
1047 if ((lease
= lease6_find(clid
, clid_len
, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
,
1048 iaid
, opt6_ptr(ia_option
, 0))))
1049 lease_prune(lease
, now
);
1054 o
= new_opt6(ia_type
);
1055 put_opt6_long(iaid
);
1056 if (ia_type
== OPTION6_IA_NA
)
1064 o1
= new_opt6(OPTION6_IAADDR
);
1065 put_opt6(opt6_ptr(ia_option
, 0), IN6ADDRSZ
);
1074 o1
= new_opt6(OPTION6_STATUS_CODE
);
1075 put_opt6_short(DHCP6NOBINDING
);
1076 put_opt6_string("No binding found");
1083 o1
= new_opt6(OPTION6_STATUS_CODE
);
1084 put_opt6_short(DHCP6SUCCESS
);
1085 put_opt6_string("Release received");
1093 /* set reply message type */
1094 *outmsgtypep
= DHCP6REPLY
;
1096 log6_packet("DHCPDECLINE", clid
, clid_len
, NULL
, xid
, iface_name
, NULL
);
1098 for (opt
= packet_options
; opt
; opt
= opt6_next(opt
, end
))
1100 int iaid
, ia_type
= opt6_type(opt
);
1101 void *ia_option
, *ia_end
;
1104 if (ia_type
!= OPTION6_IA_NA
&& ia_type
!= OPTION6_IA_TA
)
1107 if (ia_type
== OPTION6_IA_NA
&& opt6_len(opt
) < 12)
1110 if (ia_type
== OPTION6_IA_TA
&& opt6_len(opt
) < 4)
1113 iaid
= opt6_uint(opt
, 0, 4);
1114 ia_end
= opt6_ptr(opt
, opt6_len(opt
));
1115 ia_option
= opt6_ptr(opt
, ia_type
== OPTION6_IA_NA
? 12 : 4);
1117 /* reset "USED" flags on leases */
1118 lease6_find(NULL
, 0, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
, iaid
, NULL
);
1120 for (ia_option
= opt6_find(ia_option
, ia_end
, OPTION6_IAADDR
, 24);
1122 ia_option
= opt6_find(opt6_next(ia_option
, ia_end
), ia_end
, OPTION6_IAADDR
, 24))
1124 struct dhcp_lease
*lease
;
1125 struct in6_addr
*addrp
= opt6_ptr(ia_option
, 0);
1127 if (have_config(config
, CONFIG_ADDR6
) &&
1128 memcmp(&config
->addr6
, addrp
, IN6ADDRSZ
) == 0)
1130 prettyprint_time(daemon
->dhcp_buff3
, DECLINE_BACKOFF
);
1131 inet_ntop(AF_INET6
, addrp
, daemon
->addrbuff
, ADDRSTRLEN
);
1132 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
1133 daemon
->addrbuff
, daemon
->dhcp_buff3
);
1134 config
->flags
|= CONFIG_DECLINED
;
1135 config
->decline_time
= now
;
1138 /* make sure this host gets a different address next time. */
1139 for (; context
; context
= context
->current
)
1140 context
->addr_epoch
++;
1142 if ((lease
= lease6_find(clid
, clid_len
, ia_type
== OPTION6_IA_NA
? LEASE_NA
: LEASE_TA
,
1143 iaid
, opt6_ptr(ia_option
, 0))))
1144 lease_prune(lease
, now
);
1149 o
= new_opt6(ia_type
);
1150 put_opt6_long(iaid
);
1151 if (ia_type
== OPTION6_IA_NA
)
1159 o1
= new_opt6(OPTION6_IAADDR
);
1160 put_opt6(opt6_ptr(ia_option
, 0), IN6ADDRSZ
);
1169 o1
= new_opt6(OPTION6_STATUS_CODE
);
1170 put_opt6_short(DHCP6NOBINDING
);
1171 put_opt6_string("No binding found");
1184 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
1185 tagif
= option_filter(tags
, context_tags
, daemon
->dhcp_opts6
);
1187 oro
= opt6_find(packet_options
, end
, OPTION6_ORO
, 0);
1189 for (opt_cfg
= daemon
->dhcp_opts6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
1191 /* netids match and not encapsulated? */
1192 if (!(opt_cfg
->flags
& DHOPT_TAGOK
))
1195 if (!(opt_cfg
->flags
& DHOPT_FORCE
) && oro
)
1197 for (i
= 0; i
< opt6_len(oro
) - 1; i
+= 2)
1198 if (opt6_uint(oro
, i
, 2) == (unsigned)opt_cfg
->opt
)
1201 /* option not requested */
1202 if (i
>= opt6_len(oro
) - 1)
1206 if (opt_cfg
->opt
== OPTION6_DNS_SERVER
)
1209 if (opt_cfg
->len
== 0)
1213 o
= new_opt6(opt_cfg
->opt
);
1214 if (opt_cfg
->flags
& DHOPT_ADDR6
)
1217 struct in6_addr
*a
= (struct in6_addr
*)opt_cfg
->val
;
1218 for (j
= 0; j
< opt_cfg
->len
; j
+=IN6ADDRSZ
, a
++)
1220 /* zero means "self" (but not in vendorclass options.) */
1221 if (IN6_IS_ADDR_UNSPECIFIED(a
))
1223 if (IN6_IS_ADDR_UNSPECIFIED(&context
->local6
))
1224 put_opt6(fallback
, IN6ADDRSZ
);
1226 put_opt6(&context
->local6
, IN6ADDRSZ
);
1229 put_opt6(a
, IN6ADDRSZ
);
1232 else if (opt_cfg
->val
)
1233 put_opt6(opt_cfg
->val
, opt_cfg
->len
);
1238 (!IN6_IS_ADDR_UNSPECIFIED(&context
->local6
) ||
1239 !IN6_IS_ADDR_UNSPECIFIED(fallback
)))
1241 o
= new_opt6(OPTION6_DNS_SERVER
);
1242 if (IN6_IS_ADDR_UNSPECIFIED(&context
->local6
))
1243 put_opt6(fallback
, IN6ADDRSZ
);
1245 put_opt6(&context
->local6
, IN6ADDRSZ
);
1249 /* handle vendor-identifying vendor-encapsulated options,
1250 dhcp-option = vi-encap:13,17,....... */
1251 for (opt_cfg
= daemon
->dhcp_opts6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
1252 opt_cfg
->flags
&= ~DHOPT_ENCAP_DONE
;
1255 for (i
= 0; i
< opt6_len(oro
) - 1; i
+= 2)
1256 if (opt6_uint(oro
, i
, 2) == OPTION6_VENDOR_OPTS
)
1259 for (opt_cfg
= daemon
->dhcp_opts6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
1261 if (opt_cfg
->flags
& DHOPT_RFC3925
)
1264 struct dhcp_opt
*oc
;
1266 if (opt_cfg
->flags
& DHOPT_ENCAP_DONE
)
1269 for (oc
= daemon
->dhcp_opts6
; oc
; oc
= oc
->next
)
1271 oc
->flags
&= ~DHOPT_ENCAP_MATCH
;
1273 if (!(oc
->flags
& DHOPT_RFC3925
) || opt_cfg
->u
.encap
!= oc
->u
.encap
)
1276 oc
->flags
|= DHOPT_ENCAP_DONE
;
1277 if (match_netid(oc
->netid
, tagif
, 1))
1279 /* option requested/forced? */
1280 if (!oro
|| do_encap
|| (oc
->flags
& DHOPT_FORCE
))
1282 oc
->flags
|= DHOPT_ENCAP_MATCH
;
1290 o
= new_opt6(OPTION6_VENDOR_OPTS
);
1291 put_opt6_long(opt_cfg
->u
.encap
);
1293 for (oc
= daemon
->dhcp_opts6
; oc
; oc
= oc
->next
)
1294 if (oc
->flags
& DHOPT_ENCAP_MATCH
)
1296 o1
= new_opt6(oc
->opt
);
1297 put_opt6(oc
->val
, oc
->len
);
1309 size_t len
= strlen(hostname
);
1312 len
+= strlen(send_domain
) + 1;
1314 o
= new_opt6(OPTION6_FQDN
);
1315 if ((p
= expand(len
+ 3)))
1317 *(p
++) = fqdn_flags
;
1318 p
= do_rfc1035_name(p
, hostname
);
1320 p
= do_rfc1035_name(p
, send_domain
);
1328 if (option_bool(OPT_LOG_OPTS
) && oro
)
1330 char *q
= daemon
->namebuff
;
1331 for (i
= 0; i
< opt6_len(oro
) - 1; i
+= 2)
1333 char *s
= option_string(AF_INET6
, opt6_uint(oro
, i
, 2), NULL
, 0, NULL
, 0);
1334 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
1336 opt6_uint(oro
, i
, 2),
1337 strlen(s
) != 0 ? ":" : "",
1339 (i
> opt6_len(oro
) - 3) ? "" : ", ");
1340 if ( i
> opt6_len(oro
) - 3 || (q
- daemon
->namebuff
) > 40)
1342 q
= daemon
->namebuff
;
1343 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), xid
, daemon
->namebuff
);
1348 log_tags(tagif
, xid
);
1350 if (option_bool(OPT_LOG_OPTS
))
1351 log6_opts(0, xid
, daemon
->outpacket
.iov_base
+ start_opts
, daemon
->outpacket
.iov_base
+ save_counter(-1));
1356 static void log6_opts(int nest
, unsigned int xid
, void *start_opts
, void *end_opts
)
1359 char *desc
= nest
? "nest" : "sent";
1361 if (start_opts
== end_opts
)
1364 for (opt
= start_opts
; opt
; opt
= opt6_next(opt
, end_opts
))
1366 int type
= opt6_type(opt
);
1367 void *ia_options
= NULL
;
1370 if (type
== OPTION6_IA_NA
)
1372 sprintf(daemon
->namebuff
, "IAID=%u T1=%u T2=%u",
1373 opt6_uint(opt
, 0, 4), opt6_uint(opt
, 4, 4), opt6_uint(opt
, 8, 4));
1375 ia_options
= opt6_ptr(opt
, 12);
1377 else if (type
== OPTION6_IA_TA
)
1379 sprintf(daemon
->namebuff
, "IAID=%u", opt6_uint(opt
, 0, 4));
1381 ia_options
= opt6_ptr(opt
, 4);
1383 else if (type
== OPTION6_IAADDR
)
1385 inet_ntop(AF_INET6
, opt6_ptr(opt
, 0), daemon
->addrbuff
, ADDRSTRLEN
);
1386 sprintf(daemon
->namebuff
, "%s PL=%u VL=%u",
1387 daemon
->addrbuff
, opt6_uint(opt
, 16, 4), opt6_uint(opt
, 20, 4));
1389 ia_options
= opt6_ptr(opt
, 24);
1391 else if (type
== OPTION6_STATUS_CODE
)
1393 int len
= sprintf(daemon
->namebuff
, "%u ", opt6_uint(opt
, 0, 2));
1394 memcpy(daemon
->namebuff
+ len
, opt6_ptr(opt
, 2), opt6_len(opt
)-2);
1395 daemon
->namebuff
[len
+ opt6_len(opt
) - 2] = 0;
1400 /* account for flag byte on FQDN */
1401 int offset
= type
== OPTION6_FQDN
? 1 : 0;
1402 optname
= option_string(AF_INET6
, type
, opt6_ptr(opt
, offset
), opt6_len(opt
) - offset
, daemon
->namebuff
, MAXDNAME
);
1405 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s size:%3d option:%3d %s %s",
1406 xid
, desc
, opt6_len(opt
), type
, optname
, daemon
->namebuff
);
1409 log6_opts(1, xid
, ia_options
, opt6_ptr(opt
, opt6_len(opt
)));
1413 static void log6_packet(char *type
, unsigned char *clid
, int clid_len
, struct in6_addr
*addr
, int xid
, char *iface
, char *string
)
1415 /* avoid buffer overflow */
1419 print_mac(daemon
->namebuff
, clid
, clid_len
);
1423 inet_ntop(AF_INET6
, addr
, daemon
->dhcp_buff2
, 255);
1424 strcat(daemon
->dhcp_buff2
, " ");
1427 daemon
->dhcp_buff2
[0] = 0;
1429 if(option_bool(OPT_LOG_OPTS
))
1430 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s %s",
1436 string
? string
: "");
1438 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s %s",
1443 string
? string
: "");
1446 static void *opt6_find (void *opts
, void *end
, unsigned int search
, unsigned int minsize
)
1460 GETSHORT(opt
, opts
);
1461 GETSHORT(opt_len
, opts
);
1463 if (opt_len
> (end
- opts
))
1466 if (opt
== search
&& (opt_len
>= minsize
))
1473 static void *opt6_next(void *opts
, void *end
)
1481 GETSHORT(opt_len
, opts
);
1483 if (opt_len
>= (end
- opts
))
1486 return opts
+ opt_len
;
1489 static unsigned int opt6_uint(unsigned char *opt
, int offset
, int size
)
1491 /* this worries about unaligned data and byte order */
1492 unsigned int ret
= 0;
1494 unsigned char *p
= opt6_ptr(opt
, offset
);
1496 for (i
= 0; i
< size
; i
++)
1497 ret
= (ret
<< 8) | *p
++;