]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc2131.c
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/>.
21 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
22 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
25 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
);
28 static int sanitise(unsigned char *opt
, char *buf
);
29 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
);
30 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
);
31 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
32 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
33 int opt
, char *string
, int null_term
);
34 static struct in_addr
option_addr(unsigned char *opt
);
35 static unsigned int option_uint(unsigned char *opt
, int i
, int size
);
36 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
37 int mac_len
, char *interface
, char *string
, u32 xid
);
38 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
39 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
40 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
);
41 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
42 static int in_list(unsigned char *list
, int opt
);
43 static void do_options(struct dhcp_context
*context
,
44 struct dhcp_packet
*mess
,
45 unsigned char *real_end
,
46 unsigned char *req_options
,
49 struct dhcp_netid
*netid
,
50 struct in_addr subnet_addr
,
51 unsigned char fqdn_flags
,
52 int null_term
, int pxearch
,
58 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
59 static int do_encap_opts(struct dhcp_opt
*opts
, int encap
, int flag
, struct dhcp_packet
*mess
, unsigned char *end
, int null_term
);
60 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
);
61 static int prune_vendor_opts(struct dhcp_netid
*netid
);
62 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
);
63 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
);
66 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
67 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
, int pxe
, struct in_addr fallback
)
69 unsigned char *opt
, *clid
= NULL
;
70 struct dhcp_lease
*ltmp
, *lease
= NULL
;
71 struct dhcp_vendor
*vendor
;
73 struct dhcp_netid_list
*id_list
;
74 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0, pxearch
= -1;
75 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
76 unsigned char *end
= (unsigned char *)(mess
+ 1);
77 unsigned char *real_end
= (unsigned char *)(mess
+ 1);
78 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
, *domain
= NULL
;
79 int hostname_auth
= 0, borken_opt
= 0;
80 unsigned char *req_options
= NULL
;
83 struct dhcp_config
*config
;
84 struct dhcp_netid
*netid
, *tagif_netid
;
85 struct in_addr subnet_addr
, override
;
86 unsigned short fuzz
= 0;
87 unsigned int mess_type
= 0;
88 unsigned char fqdn_flags
= 0;
89 unsigned char *agent_id
= NULL
, *uuid
= NULL
;
90 unsigned char *emac
= NULL
;
91 int vendor_class_len
= 0, emac_len
= 0;
92 struct dhcp_netid known_id
, iface_id
, cpewan_id
;
94 unsigned char pxe_uuid
[17];
95 unsigned char *oui
= NULL
, *serial
= NULL
, *class = NULL
;
97 subnet_addr
.s_addr
= override
.s_addr
= 0;
99 /* set tag with name == interface */
100 iface_id
.net
= iface_name
;
101 iface_id
.next
= NULL
;
104 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
107 if (mess
->htype
== 0 && mess
->hlen
!= 0)
110 /* check for DHCP rather than BOOTP */
111 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
113 u32 cookie
= htonl(DHCP_COOKIE
);
115 /* only insist on a cookie for DHCP. */
116 if (memcmp(mess
->options
, &cookie
, sizeof(u32
)) != 0)
119 mess_type
= option_uint(opt
, 0, 1);
121 /* two things to note here: expand_buf may move the packet,
122 so reassign mess from daemon->packet. Also, the size
123 sent includes the IP and UDP headers, hence the magic "-28" */
124 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
126 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
128 if (size
> DHCP_PACKET_MAX
)
129 size
= DHCP_PACKET_MAX
;
130 else if (size
< sizeof(struct dhcp_packet
))
131 size
= sizeof(struct dhcp_packet
);
133 if (expand_buf(&daemon
->dhcp_packet
, size
))
135 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
136 real_end
= end
= ((unsigned char *)mess
) + size
;
140 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
141 it can affect the context-determination code. */
142 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
143 mess
->ciaddr
.s_addr
= 0;
145 /* search for device identity from CPEWAN devices, we pass this through to the script */
146 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT_OPT
, 5)))
148 unsigned int elen
, offset
, len
= option_len(opt
);
150 for (offset
= 0; offset
< (len
- 5); offset
+= elen
+ 5)
152 elen
= option_uint(opt
, offset
+ 4 , 1);
153 if (option_uint(opt
, offset
, 4) == BRDBAND_FORUM_IANA
)
155 unsigned char *x
= option_ptr(opt
, offset
+ 5);
156 unsigned char *y
= option_ptr(opt
, offset
+ elen
+ 5);
157 oui
= option_find1(x
, y
, 1, 1);
158 serial
= option_find1(x
, y
, 2, 1);
159 class = option_find1(x
, y
, 3, 1);
161 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
162 the gateway id back. Note that the device class is optional */
165 cpewan_id
.net
= "cpewan-id";
166 cpewan_id
.next
= netid
;
174 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
176 /* Any agent-id needs to be copied back out, verbatim, as the last option
177 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
178 get overwritten, then it will be shuffled back at the end of processing.
179 Note that the incoming options must not be overwritten here, so there has to
180 be enough free space at the end of the packet to copy the option. */
182 unsigned int total
= option_len(opt
) + 2;
183 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
184 if (last_opt
&& last_opt
< end
- total
)
188 memcpy(agent_id
, opt
, total
);
191 /* look for RFC3527 Link selection sub-option */
192 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
193 subnet_addr
= option_addr(sopt
);
195 /* look for RFC5107 server-identifier-override */
196 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
197 override
= option_addr(sopt
);
199 /* if a circuit-id or remote-is option is provided, exact-match to options. */
200 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
204 if (vendor
->match_type
== MATCH_CIRCUIT
)
205 search
= SUBOPT_CIRCUIT_ID
;
206 else if (vendor
->match_type
== MATCH_REMOTE
)
207 search
= SUBOPT_REMOTE_ID
;
208 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
209 search
= SUBOPT_SUBSCR_ID
;
213 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
214 vendor
->len
== option_len(sopt
) &&
215 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
217 vendor
->netid
.next
= netid
;
218 netid
= &vendor
->netid
;
223 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
224 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
225 subnet_addr
= option_addr(opt
);
227 /* If there is no client identifier option, use the hardware address */
228 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
230 clid_len
= option_len(opt
);
231 clid
= option_ptr(opt
, 0);
234 /* do we have a lease in store? */
235 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
237 /* If this request is missing a clid, but we've seen one before,
238 use it again for option matching etc. */
239 if (lease
&& !clid
&& lease
->clid
)
241 clid_len
= lease
->clid_len
;
245 /* find mac to use for logging and hashing */
246 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
249 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
250 if (mac
->hwaddr_len
== mess
->hlen
&&
251 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
252 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
254 mac
->netid
.next
= netid
;
258 /* Determine network for this packet. Our caller will have already linked all the
259 contexts which match the addresses of the receiving interface but if the
260 machine has an address already, or came via a relay, or we have a subnet selector,
261 we search again. If we don't have have a giaddr or explicit subnet selector,
262 use the ciaddr. This is necessary because a machine which got a lease via a
263 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
264 from the physical network, continue using that to allow correct DHCPNAK generation later. */
265 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
267 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
271 if (subnet_addr
.s_addr
)
276 else if (mess
->giaddr
.s_addr
)
283 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
285 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
286 if (context_tmp
->netmask
.s_addr
&&
287 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
288 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
290 context_new
= context
;
296 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
298 struct in_addr netmask
= context_tmp
->netmask
;
300 /* guess the netmask for relayed networks */
301 if (!(context_tmp
->flags
& CONTEXT_NETMASK
) && context_tmp
->netmask
.s_addr
== 0)
303 if (IN_CLASSA(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSA(ntohl(context_tmp
->end
.s_addr
)))
304 netmask
.s_addr
= htonl(0xff000000);
305 else if (IN_CLASSB(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSB(ntohl(context_tmp
->end
.s_addr
)))
306 netmask
.s_addr
= htonl(0xffff0000);
307 else if (IN_CLASSC(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSC(ntohl(context_tmp
->end
.s_addr
)))
308 netmask
.s_addr
= htonl(0xffffff00);
311 /* This section fills in context mainly when a client which is on a remote (relayed)
312 network renews a lease without using the relay, after dnsmasq has restarted. */
313 if (netmask
.s_addr
!= 0 &&
314 is_same_net(addr
, context_tmp
->start
, netmask
) &&
315 is_same_net(addr
, context_tmp
->end
, netmask
))
317 context_tmp
->netmask
= netmask
;
318 if (context_tmp
->local
.s_addr
== 0)
319 context_tmp
->local
= fallback
;
320 if (context_tmp
->router
.s_addr
== 0)
321 context_tmp
->router
= mess
->giaddr
;
323 /* fill in missing broadcast addresses for relayed ranges */
324 if (!(context_tmp
->flags
& CONTEXT_BRDCAST
) && context_tmp
->broadcast
.s_addr
== 0 )
325 context_tmp
->broadcast
.s_addr
= context_tmp
->start
.s_addr
| ~context_tmp
->netmask
.s_addr
;
327 context_tmp
->current
= context_new
;
328 context_new
= context_tmp
;
332 if (context_new
|| force
)
333 context
= context_new
;
338 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
339 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
340 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
344 if (option_bool(OPT_LOG_OPTS
))
346 struct dhcp_context
*context_tmp
;
347 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
349 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
350 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
351 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP subnet: %s/%s"),
352 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
354 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
355 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
359 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
360 Otherwise assume the option is an array, and look for a matching element.
361 If no data given, existance of the option is enough. This code handles
362 rfc3925 V-I classes too. */
363 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
365 unsigned int len
, elen
, match
= 0;
368 if (o
->flags
& DHOPT_RFC3925
)
370 if (!(opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT
, 5)))
373 for (offset
= 0; offset
< (option_len(opt
) - 5u); offset
+= len
+ 5)
375 len
= option_uint(opt
, offset
+ 4 , 1);
376 /* Need to take care that bad data can't run us off the end of the packet */
377 if ((offset
+ len
+ 5 <= (option_len(opt
))) &&
378 (option_uint(opt
, offset
, 4) == (unsigned int)o
->u
.encap
))
379 for (o2
= offset
+ 5; o2
< offset
+ len
+ 5; o2
+= elen
+ 1)
381 elen
= option_uint(opt
, o2
, 1);
382 if ((o2
+ elen
+ 1 <= option_len(opt
)) &&
383 (match
= match_bytes(o
, option_ptr(opt
, o2
+ 1), elen
)))
392 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)))
395 match
= match_bytes(o
, option_ptr(opt
, 0), option_len(opt
));
400 o
->netid
->next
= netid
;
405 /* user-class options are, according to RFC3004, supposed to contain
406 a set of counted strings. Here we check that this is so (by seeing
407 if the counts are consistent with the overall option length) and if
408 so zero the counts so that we don't get spurious matches between
409 the vendor string and the counts. If the lengths don't add up, we
410 assume that the option is a single string and non RFC3004 compliant
411 and just do the substring match. dhclient provides these broken options.
412 The code, later, which sends user-class data to the lease-change script
413 relies on the transformation done here.
416 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
418 unsigned char *ucp
= option_ptr(opt
, 0);
420 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
421 if (j
== option_len(opt
))
422 for (j
= 0; j
< option_len(opt
); j
= tmp
)
424 tmp
= j
+ ucp
[j
] + 1;
429 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
433 if (vendor
->match_type
== MATCH_VENDOR
)
434 mopt
= OPTION_VENDOR_ID
;
435 else if (vendor
->match_type
== MATCH_USER
)
436 mopt
= OPTION_USER_CLASS
;
440 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
443 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
444 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
446 vendor
->netid
.next
= netid
;
447 netid
= &vendor
->netid
;
453 /* mark vendor-encapsulated options which match the client-supplied vendor class,
454 save client-supplied vendor class */
455 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
457 memcpy(daemon
->dhcp_buff3
, option_ptr(opt
, 0), option_len(opt
));
458 vendor_class_len
= option_len(opt
);
460 match_vendor_opts(opt
, daemon
->dhcp_opts
);
462 if (option_bool(OPT_LOG_OPTS
))
464 if (sanitise(opt
, daemon
->namebuff
))
465 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
466 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
467 my_syslog(MS_DHCP
| LOG_INFO
, _("%u user class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
470 mess
->op
= BOOTREPLY
;
472 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
473 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
475 /* set "known" tag for known hosts */
478 known_id
.net
= "known";
479 known_id
.next
= netid
;
483 if (mess_type
== 0 && !pxe
)
486 struct dhcp_netid id
, bootp_id
;
487 struct in_addr
*logaddr
= NULL
;
489 /* must have a MAC addr for bootp */
490 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
493 if (have_config(config
, CONFIG_DISABLE
))
494 message
= _("disabled");
496 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
498 if (have_config(config
, CONFIG_NAME
))
500 hostname
= config
->hostname
;
501 domain
= config
->domain
;
506 struct dhcp_netid_list
*list
;
508 for (list
= config
->netid
; list
; list
= list
->next
)
510 list
->list
->next
= netid
;
515 /* Match incoming filename field as a netid. */
518 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
519 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
520 id
.net
= (char *)daemon
->dhcp_buff2
;
525 /* Add "bootp" as a tag to allow different options, address ranges etc
527 bootp_id
.net
= "bootp";
528 bootp_id
.next
= netid
;
531 tagif_netid
= run_tag_if(netid
);
533 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
534 if (match_netid(id_list
->list
, tagif_netid
, 0))
535 message
= _("ignored");
541 if (have_config(config
, CONFIG_ADDR
))
544 logaddr
= &config
->addr
;
545 mess
->yiaddr
= config
->addr
;
546 if ((lease
= lease_find_by_addr(config
->addr
)) &&
547 (lease
->hwaddr_len
!= mess
->hlen
||
548 lease
->hwaddr_type
!= mess
->htype
||
549 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
550 message
= _("address in use");
554 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
555 !address_available(context
, lease
->addr
, tagif_netid
))
559 /* lease exists, wrong network. */
560 lease_prune(lease
, now
);
563 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, tagif_netid
, now
))
564 message
= _("no address available");
567 mess
->yiaddr
= lease
->addr
;
570 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
571 message
= _("wrong network");
572 else if (context
->netid
.net
)
574 context
->netid
.next
= netid
;
575 tagif_netid
= run_tag_if(&context
->netid
);
578 log_tags(tagif_netid
, ntohl(mess
->xid
));
580 if (!message
&& !nailed
)
582 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
583 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
586 message
= _("no address configured");
591 (!(lease
= lease4_allocate(mess
->yiaddr
))))
592 message
= _("no leases left");
596 logaddr
= &mess
->yiaddr
;
598 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0, now
, 1);
600 lease_set_hostname(lease
, hostname
, 1, get_domain(lease
->addr
), domain
);
601 /* infinite lease unless nailed in dhcp-host line. */
602 lease_set_expires(lease
,
603 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
605 lease_set_interface(lease
, int_index
, now
);
607 clear_packet(mess
, end
);
608 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
609 netid
, subnet_addr
, 0, 0, -1, NULL
, vendor_class_len
, now
);
613 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
, mess
->xid
);
615 return message
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
618 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 3)))
620 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
621 int len
= option_len(opt
);
622 char *pq
= daemon
->dhcp_buff
;
623 unsigned char *pp
, *op
= option_ptr(opt
, 0);
630 /* NB, the following always sets at least one bit */
631 if (option_bool(OPT_FQDN_UPDATE
))
633 if (fqdn_flags
& 0x01)
635 fqdn_flags
|= 0x02; /* set O */
636 fqdn_flags
&= ~0x01; /* clear S */
638 fqdn_flags
|= 0x08; /* set N */
642 if (!(fqdn_flags
& 0x01))
643 fqdn_flags
|= 0x03; /* set S and O */
644 fqdn_flags
&= ~0x08; /* clear N */
647 if (fqdn_flags
& 0x04)
648 while (*op
!= 0 && ((op
+ (*op
)) - pp
) < len
)
650 memcpy(pq
, op
+1, *op
);
658 if (len
> 0 && op
[len
-1] == 0)
663 if (pq
!= daemon
->dhcp_buff
)
668 if (legal_hostname(daemon
->dhcp_buff
))
669 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
671 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
673 int len
= option_len(opt
);
674 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
675 /* Microsoft clients are broken, and need zero-terminated strings
676 in options. We detect this state here, and do the same in
677 any options we send */
678 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
681 daemon
->dhcp_buff
[len
] = 0;
682 if (legal_hostname(daemon
->dhcp_buff
))
683 client_hostname
= daemon
->dhcp_buff
;
686 if (client_hostname
&& option_bool(OPT_LOG_OPTS
))
687 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
689 if (have_config(config
, CONFIG_NAME
))
691 hostname
= config
->hostname
;
692 domain
= config
->domain
;
694 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
695 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
696 offer_hostname
= hostname
;
698 else if (client_hostname
)
700 domain
= strip_hostname(client_hostname
);
702 if (strlen(client_hostname
) != 0)
704 hostname
= client_hostname
;
707 /* Search again now we have a hostname.
708 Only accept configs without CLID and HWADDR here, (they won't match)
709 to avoid impersonation by name. */
710 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
711 mess
->chaddr
, mess
->hlen
,
712 mess
->htype
, hostname
);
713 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
716 /* set "known" tag for known hosts */
717 known_id
.net
= "known";
718 known_id
.next
= netid
;
727 struct dhcp_netid_list
*list
;
729 for (list
= config
->netid
; list
; list
= list
->next
)
731 list
->list
->next
= netid
;
736 tagif_netid
= run_tag_if(netid
);
738 /* if all the netids in the ignore list are present, ignore this client */
739 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
740 if (match_netid(id_list
->list
, tagif_netid
, 0))
743 /* If configured, we can override the server-id to be the address of the relay,
744 so that all traffic goes via the relay and can pick up agent-id info. This can be
745 configured for all relays, or by address. */
746 if (daemon
->override
&& mess
->giaddr
.s_addr
!= 0 && override
.s_addr
== 0)
748 if (!daemon
->override_relays
)
749 override
= mess
->giaddr
;
753 for (l
= daemon
->override_relays
; l
; l
= l
->next
)
754 if (l
->addr
.s_addr
== mess
->giaddr
.s_addr
)
757 override
= mess
->giaddr
;
761 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
762 if (have_config(config
, CONFIG_NOCLID
))
765 /* Check if client is PXE client. */
766 if (daemon
->enable_pxe
&&
767 (opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
768 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
770 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
772 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
776 /* Check if this is really a PXE bootserver request, and handle specially if so. */
777 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
778 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
779 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
781 struct pxe_service
*service
;
782 int type
= option_uint(opt
, 0, 2);
783 int layer
= option_uint(opt
, 2, 2);
784 unsigned char save71
[4];
785 struct dhcp_opt opt71
;
792 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
796 memcpy(save71
, option_ptr(opt
, 0), 4);
798 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
799 if (service
->type
== type
)
802 if (!service
|| !service
->basename
)
805 clear_packet(mess
, end
);
807 mess
->yiaddr
= mess
->ciaddr
;
808 mess
->ciaddr
.s_addr
= 0;
810 mess
->siaddr
= a_record_from_hosts(service
->sname
, now
);
811 else if (service
->server
.s_addr
!= 0)
812 mess
->siaddr
= service
->server
;
814 mess
->siaddr
= context
->local
;
816 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
817 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
818 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
819 pxe_misc(mess
, end
, uuid
);
821 prune_vendor_opts(tagif_netid
);
823 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
825 opt71
.flags
= DHOPT_VENDOR_MATCH
;
827 opt71
.next
= daemon
->dhcp_opts
;
828 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
830 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, mess
->xid
);
831 log_tags(tagif_netid
, ntohl(mess
->xid
));
832 return dhcp_packet_size(mess
, agent_id
, real_end
);
835 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
837 pxearch
= option_uint(opt
, 0, 2);
839 /* proxy DHCP here. */
840 if ((mess_type
== DHCPDISCOVER
|| (pxe
&& mess_type
== DHCPREQUEST
)))
842 struct dhcp_context
*tmp
;
844 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
845 if ((tmp
->flags
& CONTEXT_PROXY
) &&
846 match_netid(tmp
->filter
, tagif_netid
, 1))
851 struct dhcp_boot
*boot
= find_boot(tagif_netid
);
853 mess
->yiaddr
.s_addr
= 0;
854 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
856 mess
->ciaddr
.s_addr
= 0;
857 mess
->flags
|= htons(0x8000); /* broadcast */
860 clear_packet(mess
, end
);
862 /* Provide the bootfile here, for gPXE, and in case we have no menu items
863 and set discovery_control = 8 */
866 if (boot
->next_server
.s_addr
)
867 mess
->siaddr
= boot
->next_server
;
868 else if (boot
->tftp_sname
)
869 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
872 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
875 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
876 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
877 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
878 pxe_misc(mess
, end
, uuid
);
879 prune_vendor_opts(tagif_netid
);
880 do_encap_opts(pxe_opts(pxearch
, tagif_netid
, context
->local
, now
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
882 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, ignore
? "proxy-ignored" : "proxy", mess
->xid
);
883 log_tags(tagif_netid
, ntohl(mess
->xid
));
884 return ignore
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
890 /* if we're just a proxy server, go no further */
891 if ((context
->flags
& CONTEXT_PROXY
) || pxe
)
894 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
896 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
897 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
898 req_options
[option_len(opt
)] = OPTION_END
;
904 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
905 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
908 /* sanitise any message. Paranoid? Moi? */
909 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
911 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
914 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
, mess
->xid
);
916 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
917 lease_prune(lease
, now
);
919 if (have_config(config
, CONFIG_ADDR
) &&
920 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
922 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
923 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
924 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
925 config
->flags
|= CONFIG_DECLINED
;
926 config
->decline_time
= now
;
929 /* make sure this host gets a different address next time. */
930 for (; context
; context
= context
->current
)
931 context
->addr_epoch
++;
936 if (!(context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
)) ||
937 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
938 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
941 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
942 lease_prune(lease
, now
);
944 message
= _("unknown lease");
946 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
951 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
953 message
= _("ignored");
958 struct in_addr addr
, conf
;
960 addr
.s_addr
= conf
.s_addr
= 0;
962 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
963 addr
= option_addr(opt
);
965 if (have_config(config
, CONFIG_ADDR
))
967 char *addrs
= inet_ntoa(config
->addr
);
969 if ((ltmp
= lease_find_by_addr(config
->addr
)) &&
971 !config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
974 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
975 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
976 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
977 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
981 struct dhcp_context
*tmp
;
982 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
983 if (context
->router
.s_addr
== config
->addr
.s_addr
)
986 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
987 else if (have_config(config
, CONFIG_DECLINED
) &&
988 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
989 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
998 address_available(context
, lease
->addr
, tagif_netid
) &&
999 !config_find_by_address(daemon
->dhcp_conf
, lease
->addr
))
1000 mess
->yiaddr
= lease
->addr
;
1001 else if (opt
&& address_available(context
, addr
, tagif_netid
) && !lease_find_by_addr(addr
) &&
1002 !config_find_by_address(daemon
->dhcp_conf
, addr
))
1003 mess
->yiaddr
= addr
;
1004 else if (emac_len
== 0)
1005 message
= _("no unique-id");
1006 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, tagif_netid
, now
))
1007 message
= _("no address available");
1010 log_packet("DHCPDISCOVER", opt
? option_ptr(opt
, 0) : NULL
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1012 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1015 if (context
->netid
.net
)
1017 context
->netid
.next
= netid
;
1018 tagif_netid
= run_tag_if(&context
->netid
);
1021 log_tags(tagif_netid
, ntohl(mess
->xid
));
1023 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1025 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1026 clear_packet(mess
, end
);
1027 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
1028 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1029 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1030 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1031 if (time
!= 0xffffffff)
1033 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
1034 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
1036 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
1037 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1039 return dhcp_packet_size(mess
, agent_id
, real_end
);
1042 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1044 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
1046 /* SELECTING or INIT_REBOOT */
1047 mess
->yiaddr
= option_addr(opt
);
1049 /* send vendor and user class info for new or recreated lease */
1052 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
1057 if (override
.s_addr
!= 0)
1059 if (option_addr(opt
).s_addr
!= override
.s_addr
)
1064 for (; context
; context
= context
->current
)
1065 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
1070 /* Handle very strange configs where clients have more than one route to the server.
1071 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1072 Have to set override to make sure we echo back the correct server-id */
1075 enumerate_interfaces(0);
1077 for (intr
= daemon
->interfaces
; intr
; intr
= intr
->next
)
1078 if (intr
->addr
.sa
.sa_family
== AF_INET
&&
1079 intr
->addr
.in
.sin_addr
.s_addr
== option_addr(opt
).s_addr
&&
1084 override
= intr
->addr
.in
.sin_addr
;
1087 /* In auth mode, a REQUEST sent to the wrong server
1088 should be faulted, so that the client establishes
1089 communication with us, otherwise, silently ignore. */
1090 if (!option_bool(OPT_AUTHORITATIVE
))
1092 message
= _("wrong server-ID");
1097 /* If a lease exists for this host and another address, squash it. */
1098 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1100 lease_prune(lease
, now
);
1107 if (!lease
&& !option_bool(OPT_AUTHORITATIVE
))
1110 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1111 message
= _("wrong address");
1116 /* RENEWING or REBINDING */
1117 /* Check existing lease for this address.
1118 We allow it to be missing if dhcp-authoritative mode
1119 as long as we can allocate the lease now - checked below.
1120 This makes for a smooth recovery from a lost lease DB */
1121 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1122 (!lease
&& !option_bool(OPT_AUTHORITATIVE
)))
1124 /* A client rebinding will broadcast the request, so we may see it even
1125 if the lease is held by another server. Just ignore it in that case.
1126 If the request is unicast to us, then somethings wrong, NAK */
1129 message
= _("lease not found");
1130 /* ensure we broadcast NAK */
1134 /* desynchronise renewals */
1136 mess
->yiaddr
= mess
->ciaddr
;
1139 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1143 struct dhcp_config
*addr_config
;
1144 struct dhcp_context
*tmp
= NULL
;
1146 if (have_config(config
, CONFIG_ADDR
))
1147 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1148 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1151 if (!(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1153 /* If a machine moves networks whilst it has a lease, we catch that here. */
1154 message
= _("wrong network");
1155 /* ensure we broadcast NAK */
1159 /* Check for renewal of a lease which is outside the allowed range. */
1160 else if (!address_available(context
, mess
->yiaddr
, tagif_netid
) &&
1161 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1162 message
= _("address not available");
1164 /* Check if a new static address has been configured. Be very sure that
1165 when the client does DISCOVER, it will get the static address, otherwise
1166 an endless protocol loop will ensue. */
1167 else if (!tmp
&& !selecting
&&
1168 have_config(config
, CONFIG_ADDR
) &&
1169 (!have_config(config
, CONFIG_DECLINED
) ||
1170 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1171 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1172 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1173 message
= _("static lease available");
1175 /* Check to see if the address is reserved as a static address for another host */
1176 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1177 message
= _("address reserved");
1179 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1181 /* If a host is configured with more than one MAC address, it's OK to 'nix
1182 a lease from one of it's MACs to give the address to another. */
1183 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1185 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1186 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1187 inet_ntoa(ltmp
->addr
));
1191 message
= _("address in use");
1197 message
= _("no unique-id");
1201 if ((lease
= lease4_allocate(mess
->yiaddr
)))
1204 message
= _("no leases left");
1211 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1213 mess
->yiaddr
.s_addr
= 0;
1214 clear_packet(mess
, end
);
1215 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1216 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1217 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1218 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1219 a distant subnet which unicast a REQ to us won't work. */
1220 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1221 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1223 mess
->flags
|= htons(0x8000); /* broadcast */
1224 mess
->ciaddr
.s_addr
= 0;
1229 if (context
->netid
.net
)
1231 context
->netid
.next
= netid
;
1232 tagif_netid
= run_tag_if( &context
->netid
);
1235 log_tags(tagif_netid
, ntohl(mess
->xid
));
1239 /* pick up INIT-REBOOT events. */
1240 lease
->flags
|= LEASE_CHANGED
;
1243 if (daemon
->lease_change_command
)
1245 struct dhcp_netid
*n
;
1247 if (mess
->giaddr
.s_addr
)
1248 lease
->giaddr
= mess
->giaddr
;
1250 free(lease
->extradata
);
1251 lease
->extradata
= NULL
;
1252 lease
->extradata_size
= lease
->extradata_len
= 0;
1254 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_VENDOR_ID
, 1));
1255 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_HOSTNAME
, 1));
1256 add_extradata_opt(lease
, oui
);
1257 add_extradata_opt(lease
, serial
);
1258 add_extradata_opt(lease
, class);
1260 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
1262 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_CIRCUIT_ID
, 1));
1263 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBSCR_ID
, 1));
1264 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_REMOTE_ID
, 1));
1268 add_extradata_opt(lease
, NULL
);
1269 add_extradata_opt(lease
, NULL
);
1270 add_extradata_opt(lease
, NULL
);
1273 /* space-concat tag set */
1275 add_extradata_opt(lease
, NULL
);
1277 for (n
= tagif_netid
; n
; n
= n
->next
)
1279 struct dhcp_netid
*n1
;
1281 for (n1
= n
->next
; n1
; n1
= n1
->next
)
1282 if (strcmp(n
->net
, n1
->net
) == 0)
1285 lease_add_extradata(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
1288 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1290 int len
= option_len(opt
);
1291 unsigned char *ucp
= option_ptr(opt
, 0);
1292 /* If the user-class option started as counted strings, the first byte will be zero. */
1293 if (len
!= 0 && ucp
[0] == 0)
1295 lease_add_extradata(lease
, ucp
, len
, 0);
1301 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1303 domain
= get_domain(mess
->yiaddr
);
1304 hostname
= client_hostname
;
1308 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1309 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
, now
, do_classes
);
1311 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1314 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1315 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1321 /* Last ditch, if configured, generate hostname from mac address */
1322 if (!hostname
&& emac_len
!= 0)
1324 for (id_list
= daemon
->dhcp_gen_names
; id_list
; id_list
= id_list
->next
)
1325 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1331 hostname
= daemon
->dhcp_buff
;
1332 /* buffer is 256 bytes, 3 bytes per octet */
1333 for (i
= 0; (i
< emac_len
) && (i
< 80); i
++)
1334 hostname
+= sprintf(hostname
, "%.2x%s", emac
[i
], (i
== emac_len
- 1) ? "" : "-");
1335 hostname
= daemon
->dhcp_buff
;
1340 lease_set_hostname(lease
, hostname
, hostname_auth
, get_domain(lease
->addr
), domain
);
1342 lease_set_expires(lease
, time
, now
);
1343 lease_set_interface(lease
, int_index
, now
);
1345 if (override
.s_addr
!= 0)
1346 lease
->override
= override
;
1348 override
= lease
->override
;
1350 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1352 clear_packet(mess
, end
);
1353 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1354 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1355 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1356 if (time
!= 0xffffffff)
1358 while (fuzz
> (time
/16))
1360 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
1361 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
1363 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1364 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1367 return dhcp_packet_size(mess
, agent_id
, real_end
);
1370 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1371 message
= _("ignored");
1373 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1375 if (message
|| mess
->ciaddr
.s_addr
== 0)
1378 /* For DHCPINFORM only, cope without a valid context */
1379 context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
);
1381 /* Find a least based on IP address if we didn't
1382 get one from MAC address/client-d */
1384 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1386 hostname
= lease
->hostname
;
1388 if (!hostname
&& (hostname
= host_from_dns(mess
->ciaddr
)))
1389 domain
= get_domain(mess
->ciaddr
);
1391 if (context
&& context
->netid
.net
)
1393 context
->netid
.next
= netid
;
1394 tagif_netid
= run_tag_if(&context
->netid
);
1397 log_tags(tagif_netid
, ntohl(mess
->xid
));
1399 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1403 lease_set_interface(lease
, int_index
, now
);
1404 if (override
.s_addr
!= 0)
1405 lease
->override
= override
;
1407 override
= lease
->override
;
1410 clear_packet(mess
, end
);
1411 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1412 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1414 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1415 we supply a utility which makes DHCPINFORM requests to get this information.
1416 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1417 which won't be true for ordinary clients, but will be true for the
1418 dhcp_lease_time utility. */
1419 if (lease
&& in_list(req_options
, OPTION_LEASE_TIME
))
1421 if (lease
->expires
== 0)
1424 time
= (unsigned int)difftime(lease
->expires
, now
);
1425 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1428 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1429 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1431 *is_inform
= 1; /* handle reply differently */
1432 return dhcp_packet_size(mess
, agent_id
, real_end
);
1438 /* find a good value to use as MAC address for logging and address-allocation hashing.
1439 This is normally just the chaddr field from the DHCP packet,
1440 but eg Firewire will have hlen == 0 and use the client-id instead.
1441 This could be anything, but will normally be EUI64 for Firewire.
1442 We assume that if the first byte of the client-id equals the htype byte
1443 then the client-id is using the usual encoding and use the rest of the
1444 client-id: if not we can use the whole client-id. This should give
1445 sane MAC address logs. */
1446 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1447 int clid_len
, unsigned char *clid
, int *len_out
)
1449 if (hwlen
== 0 && clid
&& clid_len
> 3)
1451 if (clid
[0] == hwtype
)
1453 *len_out
= clid_len
- 1 ;
1457 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1458 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1460 *len_out
= clid_len
- 1 ;
1465 *len_out
= clid_len
;
1473 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1475 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1479 unsigned int req_time
= option_uint(opt
, 0, 4);
1480 if (req_time
< 120 )
1481 req_time
= 120; /* sanity */
1482 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1489 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1491 if (override
.s_addr
!= 0)
1493 else if (context
&& context
->local
.s_addr
!= 0)
1494 return context
->local
;
1499 static int sanitise(unsigned char *opt
, char *buf
)
1509 p
= option_ptr(opt
, 0);
1511 for (i
= option_len(opt
); i
> 0; i
--)
1514 if (isprint((int)c
))
1517 *buf
= 0; /* add terminator */
1523 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
)
1526 lease_add_extradata(lease
, NULL
, 0, 0);
1528 lease_add_extradata(lease
, option_ptr(opt
, 0), option_len(opt
), 0);
1532 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1533 int mac_len
, char *interface
, char *string
, u32 xid
)
1537 /* addr may be misaligned */
1539 memcpy(&a
, addr
, sizeof(a
));
1541 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1543 if(option_bool(OPT_LOG_OPTS
))
1544 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s",
1548 addr
? inet_ntoa(a
) : "",
1551 string
? string
: "");
1553 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s",
1556 addr
? inet_ntoa(a
) : "",
1559 string
? string
: "");
1562 static void log_options(unsigned char *start
, u32 xid
)
1564 while (*start
!= OPTION_END
)
1566 char *optname
= option_string(AF_INET
, start
[0], option_ptr(start
, 0), option_len(start
), daemon
->namebuff
, MAXDNAME
);
1568 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d %s %s",
1569 ntohl(xid
), option_len(start
), start
[0], optname
, daemon
->namebuff
);
1570 start
+= start
[1] + 2;
1574 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1580 else if (*p
== OPTION_END
)
1581 return opt
== OPTION_END
? p
: NULL
;
1582 else if (*p
== OPTION_PAD
)
1588 return NULL
; /* malformed packet */
1589 opt_len
= option_len(p
);
1590 if (p
> end
- (2 + opt_len
))
1591 return NULL
; /* malformed packet */
1592 if (*p
== opt
&& opt_len
>= minsize
)
1599 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1601 unsigned char *ret
, *overload
;
1603 /* skip over DHCP cookie; */
1604 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1607 /* look for overload option. */
1608 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1611 /* Can we look in filename area ? */
1612 if ((overload
[2] & 1) &&
1613 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1616 /* finally try sname area */
1617 if ((overload
[2] & 2) &&
1618 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1624 static struct in_addr
option_addr(unsigned char *opt
)
1626 /* this worries about unaligned data in the option. */
1627 /* struct in_addr is network byte order */
1630 memcpy(&ret
, option_ptr(opt
, 0), INADDRSZ
);
1635 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1637 /* this worries about unaligned data and byte order */
1638 unsigned int ret
= 0;
1640 unsigned char *p
= option_ptr(opt
, offset
);
1642 for (i
= 0; i
< size
; i
++)
1643 ret
= (ret
<< 8) | *p
++;
1648 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1651 start
+= start
[1] + 2;
1655 /* only for use when building packet: doesn't check for bad data. */
1656 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1658 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1662 if (*p
== OPTION_OVERLOAD
)
1669 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
)
1671 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1672 unsigned char *overload
;
1675 /* move agent_id back down to the end of the packet */
1678 memmove(p
, agent_id
, real_end
- agent_id
);
1679 p
+= real_end
- agent_id
;
1680 memset(p
, 0, real_end
- p
); /* in case of overlap */
1683 /* add END options to the regions. */
1684 overload
= find_overload(mess
);
1686 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1688 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1689 if (option_bool(OPT_LOG_OPTS
))
1690 log_options(mess
->file
, mess
->xid
);
1692 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1693 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1695 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1697 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1698 if (option_bool(OPT_LOG_OPTS
))
1699 log_options(mess
->sname
, mess
->xid
);
1701 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1702 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1707 if (option_bool(OPT_LOG_OPTS
))
1709 if (mess
->siaddr
.s_addr
!= 0)
1710 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1712 if ((mess
->flags
& htons(0x8000)) && mess
->ciaddr
.s_addr
== 0)
1713 my_syslog(MS_DHCP
| LOG_INFO
, _("%u broadcast response"), ntohl(mess
->xid
));
1715 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1718 ret
= (size_t)(p
- (unsigned char *)mess
);
1720 if (ret
< MIN_PACKETSZ
)
1726 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1728 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1730 if (p
+ len
+ 3 >= end
)
1731 /* not enough space in options area, try and use overload, if poss */
1733 unsigned char *overload
;
1735 if (!(overload
= find_overload(mess
)) &&
1736 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1738 /* attempt to overload fname and sname areas, we've reserved space for the
1739 overflow option previuously. */
1741 *(p
++) = OPTION_OVERLOAD
;
1747 /* using filename field ? */
1750 if (mess
->file
[0] == 0)
1753 if (overload
[2] & 1)
1755 p
= dhcp_skip_opts(mess
->file
);
1756 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1762 /* try to bring sname into play (it may be already) */
1763 if (mess
->sname
[0] == 0)
1766 if (overload
[2] & 2)
1768 p
= dhcp_skip_opts(mess
->sname
);
1769 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->sname
))
1776 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1788 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1791 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1794 for (i
= 0; i
< len
; i
++)
1795 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1798 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1799 char *string
, int null_term
)
1802 size_t len
= strlen(string
);
1804 if (null_term
&& len
!= 255)
1807 if ((p
= free_space(mess
, end
, opt
, len
)))
1808 memcpy(p
, string
, len
);
1811 /* return length, note this only does the data part */
1812 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1816 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1821 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1824 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1825 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1827 /* zero means "self" (but not in vendorclass options.) */
1829 memcpy(p
, &context
->local
, INADDRSZ
);
1831 memcpy(p
, a
, INADDRSZ
);
1836 /* empty string may be extended to "\0" by null_term */
1837 memcpy(p
, opt
->val
? opt
->val
: (unsigned char *)"", len
);
1842 static int in_list(unsigned char *list
, int opt
)
1846 /* If no requested options, send everything, not nothing. */
1850 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1857 static struct dhcp_opt
*option_find2(int opt
)
1859 struct dhcp_opt
*opts
;
1861 for (opts
= daemon
->dhcp_opts
; opts
; opts
= opts
->next
)
1862 if (opts
->opt
== opt
&& (opts
->flags
& DHOPT_TAGOK
))
1868 /* mark vendor-encapsulated options which match the client-supplied or
1869 config-supplied vendor class */
1870 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1872 for (; dopt
; dopt
= dopt
->next
)
1874 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1875 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1878 if (dopt
->u
.vendor_class
)
1879 len
= strlen((char *)dopt
->u
.vendor_class
);
1880 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1881 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1883 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1890 static int do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1891 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1893 int len
, enc_len
, ret
= 0;
1894 struct dhcp_opt
*start
;
1897 /* find size in advance */
1898 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1899 if (opt
->flags
& flag
)
1901 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1903 if (enc_len
+ new <= 255)
1907 p
= free_space(mess
, end
, encap
, enc_len
);
1908 for (; start
&& start
!= opt
; start
= start
->next
)
1909 if (p
&& (start
->flags
& flag
))
1911 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1912 *(p
++) = start
->opt
;
1922 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
1924 for (; start
; start
= start
->next
)
1925 if (start
->flags
& flag
)
1927 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1928 *(p
++) = start
->opt
;
1938 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
1942 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
1943 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
1944 memcpy(p
, uuid
, 17);
1947 static int prune_vendor_opts(struct dhcp_netid
*netid
)
1950 struct dhcp_opt
*opt
;
1952 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1953 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
1954 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1956 if (!match_netid(opt
->netid
, netid
, 1))
1957 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1958 else if (opt
->flags
& DHOPT_FORCE
)
1964 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
)
1968 unsigned char *p
, *q
;
1969 struct pxe_service
*service
;
1970 static struct dhcp_opt
*o
, *ret
;
1971 int i
, j
= NUM_OPTS
- 1;
1972 struct in_addr boot_server
;
1974 /* We pass back references to these, hence they are declared static */
1975 static unsigned char discovery_control
;
1976 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
1977 static struct dhcp_opt
*fake_opts
= NULL
;
1979 /* Disable multicast, since we don't support it, and broadcast
1980 unless we need it */
1981 discovery_control
= 3;
1983 ret
= daemon
->dhcp_opts
;
1985 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
1988 for (i
= 0; i
< NUM_OPTS
; i
++)
1990 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
1991 fake_opts
[i
].netid
= NULL
;
1992 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
1995 /* create the data for the PXE_MENU and PXE_SERVERS options. */
1996 p
= (unsigned char *)daemon
->dhcp_buff
;
1997 q
= (unsigned char *)daemon
->dhcp_buff3
;
1999 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
2000 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
2002 size_t len
= strlen(service
->menu
);
2003 /* opt 43 max size is 255. encapsulated option has type and length
2004 bytes, so its max size is 253. */
2005 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
2007 *(p
++) = service
->type
>> 8;
2008 *(p
++) = service
->type
;
2010 memcpy(p
, service
->menu
, len
);
2017 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
2018 return daemon
->dhcp_opts
;
2021 boot_server
= service
->basename
? local
:
2022 (service
->sname
? a_record_from_hosts(service
->sname
, now
) : service
->server
);
2024 if (boot_server
.s_addr
!= 0)
2026 if (q
- (unsigned char *)daemon
->dhcp_buff3
+ 3 + INADDRSZ
>= 253)
2029 /* Boot service with known address - give it */
2030 *(q
++) = service
->type
>> 8;
2031 *(q
++) = service
->type
;
2033 /* dest misaligned */
2034 memcpy(q
, &boot_server
.s_addr
, INADDRSZ
);
2037 else if (service
->type
!= 0)
2038 /* We don't know the server for a service type, so we'll
2039 allow the client to broadcast for it */
2040 discovery_control
= 2;
2043 /* if no prompt, wait forever if there's a choice */
2044 fake_prompt
[0] = (i
> 1) ? 255 : 0;
2047 discovery_control
= 8; /* no menu - just use use mess->filename */
2050 ret
= &fake_opts
[j
--];
2051 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
2052 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
2053 ret
->opt
= SUBOPT_PXE_MENU
;
2055 if (q
- (unsigned char *)daemon
->dhcp_buff3
!= 0)
2057 ret
= &fake_opts
[j
--];
2058 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff3
;
2059 ret
->val
= (unsigned char *)daemon
->dhcp_buff3
;
2060 ret
->opt
= SUBOPT_PXE_SERVERS
;
2064 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
2065 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
2070 ret
= &fake_opts
[j
--];
2071 ret
->len
= sizeof(fake_prompt
);
2072 ret
->val
= fake_prompt
;
2073 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
2076 ret
= &fake_opts
[j
--];
2078 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
2079 ret
->val
= &discovery_control
;
2084 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
2086 memset(mess
->sname
, 0, sizeof(mess
->sname
));
2087 memset(mess
->file
, 0, sizeof(mess
->file
));
2088 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
2089 mess
->siaddr
.s_addr
= 0;
2092 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
2094 struct dhcp_boot
*boot
;
2096 /* decide which dhcp-boot option we're using */
2097 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2098 if (match_netid(boot
->netid
, netid
, 0))
2101 /* No match, look for one without a netid */
2102 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2103 if (match_netid(boot
->netid
, netid
, 1))
2109 static void do_options(struct dhcp_context
*context
,
2110 struct dhcp_packet
*mess
,
2112 unsigned char *req_options
,
2115 struct dhcp_netid
*netid
,
2116 struct in_addr subnet_addr
,
2117 unsigned char fqdn_flags
,
2118 int null_term
, int pxe_arch
,
2119 unsigned char *uuid
,
2120 int vendor_class_len
,
2123 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2124 struct dhcp_boot
*boot
;
2126 int i
, len
, force_encap
= 0;
2127 unsigned char f0
= 0, s0
= 0;
2128 int done_file
= 0, done_server
= 0;
2129 int done_vendor_class
= 0;
2130 struct dhcp_netid
*tagif
;
2131 struct dhcp_netid_list
*id_list
;
2133 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2135 context
->netid
.next
= NULL
;
2136 tagif
= option_filter(netid
, context
&& context
->netid
.net
? &context
->netid
: NULL
, config_opts
);
2139 if (option_bool(OPT_LOG_OPTS
) && req_options
)
2141 char *q
= daemon
->namebuff
;
2142 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2144 char *s
= option_string(AF_INET
, req_options
[i
], NULL
, 0, NULL
, 0);
2145 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2148 strlen(s
) != 0 ? ":" : "",
2150 req_options
[i
+1] == OPTION_END
? "" : ", ");
2151 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2153 q
= daemon
->namebuff
;
2154 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2159 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
2160 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
2163 mess
->flags
|= htons(0x8000); /* force broadcast */
2166 mess
->siaddr
= context
->local
;
2168 /* See if we can send the boot stuff as options.
2169 To do this we need a requested option list, BOOTP
2170 and very old DHCP clients won't have this, we also
2171 provide an manual option to disable it.
2172 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2173 names, so we always send those. */
2174 if ((boot
= find_boot(tagif
)))
2178 if (!option_bool(OPT_NO_OVERRIDE
) &&
2180 in_list(req_options
, OPTION_SNAME
))
2181 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2183 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2188 if (!option_bool(OPT_NO_OVERRIDE
) &&
2190 in_list(req_options
, OPTION_FILENAME
))
2191 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2193 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2196 if (boot
->next_server
.s_addr
)
2197 mess
->siaddr
= boot
->next_server
;
2198 else if (boot
->tftp_sname
)
2199 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
2202 /* Use the values of the relevant options if no dhcp-boot given and
2203 they're not explicitly asked for as options. OPTION_END is used
2204 as an internal way to specify siaddr without using dhcp-boot, for use in
2207 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
2208 (opt
= option_find2(OPTION_FILENAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2210 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2214 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2215 (opt
= option_find2(OPTION_SNAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2217 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2221 if ((opt
= option_find2(OPTION_END
)))
2222 mess
->siaddr
.s_addr
= ((struct in_addr
*)opt
->val
)->s_addr
;
2225 /* We don't want to do option-overload for BOOTP, so make the file and sname
2226 fields look like they are in use, even when they aren't. This gets restored
2227 at the end of this function. */
2229 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2233 s0
= mess
->sname
[0];
2237 /* At this point, if mess->sname or mess->file are zeroed, they are available
2238 for option overload, reserve space for the overload option. */
2239 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2242 /* rfc3011 says this doesn't need to be in the requested options list. */
2243 if (subnet_addr
.s_addr
)
2244 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2246 /* replies to DHCPINFORM may not have a valid context */
2249 if (!option_find2(OPTION_NETMASK
))
2250 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2252 /* May not have a "guessed" broadcast address if we got no packets via a relay
2253 from this net yet (ie just unicast renewals after a restart */
2254 if (context
->broadcast
.s_addr
&&
2255 !option_find2(OPTION_BROADCAST
))
2256 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2258 /* Same comments as broadcast apply, and also may not be able to get a sensible
2259 default when using subnet select. User must configure by steam in that case. */
2260 if (context
->router
.s_addr
&&
2261 in_list(req_options
, OPTION_ROUTER
) &&
2262 !option_find2(OPTION_ROUTER
))
2263 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2265 if (daemon
->port
== NAMESERVER_PORT
&&
2266 in_list(req_options
, OPTION_DNSSERVER
) &&
2267 !option_find2(OPTION_DNSSERVER
))
2268 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2271 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2272 !option_find2(OPTION_DOMAINNAME
))
2273 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2275 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2278 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2279 !option_find2(OPTION_HOSTNAME
))
2280 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2282 if (fqdn_flags
!= 0)
2284 len
= strlen(hostname
) + 3;
2286 if (fqdn_flags
& 0x04)
2292 len
+= strlen(domain
) + 1;
2293 else if (fqdn_flags
& 0x04)
2296 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2298 *(p
++) = fqdn_flags
& 0x0f; /* MBZ bits to zero */
2302 if (fqdn_flags
& 0x04)
2304 p
= do_rfc1035_name(p
, hostname
);
2307 p
= do_rfc1035_name(p
, domain
);
2313 memcpy(p
, hostname
, strlen(hostname
));
2314 p
+= strlen(hostname
);
2318 memcpy(p
, domain
, strlen(domain
));
2319 p
+= strlen(domain
);
2328 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2330 int optno
= opt
->opt
;
2332 /* netids match and not encapsulated? */
2333 if (!(opt
->flags
& DHOPT_TAGOK
))
2336 /* was it asked for, or are we sending it anyway? */
2337 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2340 /* prohibit some used-internally options */
2341 if (optno
== OPTION_CLIENT_FQDN
||
2342 optno
== OPTION_MAXMESSAGE
||
2343 optno
== OPTION_OVERLOAD
||
2344 optno
== OPTION_PAD
||
2345 optno
== OPTION_END
)
2348 if (optno
== OPTION_SNAME
&& done_server
)
2351 if (optno
== OPTION_FILENAME
&& done_file
)
2354 /* For the options we have default values on
2355 dhc-option=<optionno> means "don't include this option"
2356 not "include a zero-length option" */
2357 if (opt
->len
== 0 &&
2358 (optno
== OPTION_NETMASK
||
2359 optno
== OPTION_BROADCAST
||
2360 optno
== OPTION_ROUTER
||
2361 optno
== OPTION_DNSSERVER
||
2362 optno
== OPTION_DOMAINNAME
||
2363 optno
== OPTION_HOSTNAME
))
2366 /* vendor-class comes from elsewhere for PXE */
2367 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2370 /* always force null-term for filename and servername - buggy PXE again. */
2371 len
= do_opt(opt
, NULL
, context
,
2372 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2374 if ((p
= free_space(mess
, end
, optno
, len
)))
2376 do_opt(opt
, p
, context
,
2377 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2379 /* If we send a vendor-id, revisit which vendor-ops we consider
2380 it appropriate to send. */
2381 if (optno
== OPTION_VENDOR_ID
)
2383 match_vendor_opts(p
- 2, config_opts
);
2384 done_vendor_class
= 1;
2389 /* Now send options to be encapsulated in arbitrary options,
2390 eg dhcp-option=encap:172,17,.......
2391 Also handle vendor-identifying vendor-encapsulated options,
2392 dhcp-option = vi-encap:13,17,.......
2393 The may be more that one "outer" to do, so group
2394 all the options which match each outer in turn. */
2395 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2396 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2398 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2402 if ((flags
= (opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_RFC3925
))))
2407 if (opt
->flags
& DHOPT_ENCAP_DONE
)
2410 for (len
= 0, o
= config_opts
; o
; o
= o
->next
)
2412 int outer
= flags
& DHOPT_ENCAPSULATE
? o
->u
.encap
: OPTION_VENDOR_IDENT_OPT
;
2414 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2416 if (!(o
->flags
& flags
) || opt
->u
.encap
!= o
->u
.encap
)
2419 o
->flags
|= DHOPT_ENCAP_DONE
;
2420 if (match_netid(o
->netid
, tagif
, 1) &&
2421 ((o
->flags
& DHOPT_FORCE
) || in_list(req_options
, outer
)))
2423 o
->flags
|= DHOPT_ENCAP_MATCH
;
2425 len
+= do_opt(o
, NULL
, NULL
, 0) + 2;
2431 if (flags
& DHOPT_ENCAPSULATE
)
2432 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2434 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt
->u
.encap
);
2435 else if ((p
= free_space(mess
, end
, OPTION_VENDOR_IDENT_OPT
, len
+ 5)))
2437 int swap_ent
= htonl(opt
->u
.encap
);
2438 memcpy(p
, &swap_ent
, 4);
2441 for (o
= config_opts
; o
; o
= o
->next
)
2442 if (o
->flags
& DHOPT_ENCAP_MATCH
)
2444 len
= do_opt(o
, p
+ 2, NULL
, 0);
2454 force_encap
= prune_vendor_opts(tagif
);
2456 if (context
&& pxe_arch
!= -1)
2458 pxe_misc(mess
, end
, uuid
);
2459 config_opts
= pxe_opts(pxe_arch
, tagif
, context
->local
, now
);
2462 if ((force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
)) &&
2463 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
) &&
2464 pxe_arch
== -1 && !done_vendor_class
&& vendor_class_len
!= 0 &&
2465 (p
= free_space(mess
, end
, OPTION_VENDOR_ID
, vendor_class_len
)))
2466 /* If we send vendor encapsulated options, and haven't already sent option 60,
2467 echo back the value we got from the client. */
2468 memcpy(p
, daemon
->dhcp_buff3
, vendor_class_len
);
2470 /* restore BOOTP anti-overload hack */
2471 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2474 mess
->sname
[0] = s0
;