1 /* dnsmasq is Copyright (c) 2000-2014 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
, char *err
, 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
;
97 unsigned char *class = NULL
;
100 subnet_addr
.s_addr
= override
.s_addr
= 0;
102 /* set tag with name == interface */
103 iface_id
.net
= iface_name
;
104 iface_id
.next
= NULL
;
107 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
110 if (mess
->htype
== 0 && mess
->hlen
!= 0)
113 /* check for DHCP rather than BOOTP */
114 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
116 u32 cookie
= htonl(DHCP_COOKIE
);
118 /* only insist on a cookie for DHCP. */
119 if (memcmp(mess
->options
, &cookie
, sizeof(u32
)) != 0)
122 mess_type
= option_uint(opt
, 0, 1);
124 /* two things to note here: expand_buf may move the packet,
125 so reassign mess from daemon->packet. Also, the size
126 sent includes the IP and UDP headers, hence the magic "-28" */
127 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
129 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
131 if (size
> DHCP_PACKET_MAX
)
132 size
= DHCP_PACKET_MAX
;
133 else if (size
< sizeof(struct dhcp_packet
))
134 size
= sizeof(struct dhcp_packet
);
136 if (expand_buf(&daemon
->dhcp_packet
, size
))
138 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
139 real_end
= end
= ((unsigned char *)mess
) + size
;
143 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
144 it can affect the context-determination code. */
145 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
146 mess
->ciaddr
.s_addr
= 0;
148 /* search for device identity from CPEWAN devices, we pass this through to the script */
149 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT_OPT
, 5)))
151 unsigned int elen
, offset
, len
= option_len(opt
);
153 for (offset
= 0; offset
< (len
- 5); offset
+= elen
+ 5)
155 elen
= option_uint(opt
, offset
+ 4 , 1);
156 if (option_uint(opt
, offset
, 4) == BRDBAND_FORUM_IANA
)
158 unsigned char *x
= option_ptr(opt
, offset
+ 5);
159 unsigned char *y
= option_ptr(opt
, offset
+ elen
+ 5);
160 oui
= option_find1(x
, y
, 1, 1);
161 serial
= option_find1(x
, y
, 2, 1);
163 class = option_find1(x
, y
, 3, 1);
165 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
166 the gateway id back. Note that the device class is optional */
169 cpewan_id
.net
= "cpewan-id";
170 cpewan_id
.next
= netid
;
178 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
180 /* Any agent-id needs to be copied back out, verbatim, as the last option
181 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
182 get overwritten, then it will be shuffled back at the end of processing.
183 Note that the incoming options must not be overwritten here, so there has to
184 be enough free space at the end of the packet to copy the option. */
186 unsigned int total
= option_len(opt
) + 2;
187 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
188 if (last_opt
&& last_opt
< end
- total
)
192 memcpy(agent_id
, opt
, total
);
195 /* look for RFC3527 Link selection sub-option */
196 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
197 subnet_addr
= option_addr(sopt
);
199 /* look for RFC5107 server-identifier-override */
200 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
201 override
= option_addr(sopt
);
203 /* if a circuit-id or remote-is option is provided, exact-match to options. */
204 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
208 if (vendor
->match_type
== MATCH_CIRCUIT
)
209 search
= SUBOPT_CIRCUIT_ID
;
210 else if (vendor
->match_type
== MATCH_REMOTE
)
211 search
= SUBOPT_REMOTE_ID
;
212 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
213 search
= SUBOPT_SUBSCR_ID
;
217 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
218 vendor
->len
== option_len(sopt
) &&
219 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
221 vendor
->netid
.next
= netid
;
222 netid
= &vendor
->netid
;
227 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
228 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
229 subnet_addr
= option_addr(opt
);
231 /* If there is no client identifier option, use the hardware address */
232 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
234 clid_len
= option_len(opt
);
235 clid
= option_ptr(opt
, 0);
238 /* do we have a lease in store? */
239 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
241 /* If this request is missing a clid, but we've seen one before,
242 use it again for option matching etc. */
243 if (lease
&& !clid
&& lease
->clid
)
245 clid_len
= lease
->clid_len
;
249 /* find mac to use for logging and hashing */
250 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
253 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
254 if (mac
->hwaddr_len
== mess
->hlen
&&
255 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
256 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
258 mac
->netid
.next
= netid
;
262 /* Determine network for this packet. Our caller will have already linked all the
263 contexts which match the addresses of the receiving interface but if the
264 machine has an address already, or came via a relay, or we have a subnet selector,
265 we search again. If we don't have have a giaddr or explicit subnet selector,
266 use the ciaddr. This is necessary because a machine which got a lease via a
267 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
268 from the physical network, continue using that to allow correct DHCPNAK generation later. */
269 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
271 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
275 if (subnet_addr
.s_addr
)
280 else if (mess
->giaddr
.s_addr
)
287 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
289 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
290 if (context_tmp
->netmask
.s_addr
&&
291 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
292 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
294 context_new
= context
;
300 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
302 struct in_addr netmask
= context_tmp
->netmask
;
304 /* guess the netmask for relayed networks */
305 if (!(context_tmp
->flags
& CONTEXT_NETMASK
) && context_tmp
->netmask
.s_addr
== 0)
307 if (IN_CLASSA(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSA(ntohl(context_tmp
->end
.s_addr
)))
308 netmask
.s_addr
= htonl(0xff000000);
309 else if (IN_CLASSB(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSB(ntohl(context_tmp
->end
.s_addr
)))
310 netmask
.s_addr
= htonl(0xffff0000);
311 else if (IN_CLASSC(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSC(ntohl(context_tmp
->end
.s_addr
)))
312 netmask
.s_addr
= htonl(0xffffff00);
315 /* This section fills in context mainly when a client which is on a remote (relayed)
316 network renews a lease without using the relay, after dnsmasq has restarted. */
317 if (netmask
.s_addr
!= 0 &&
318 is_same_net(addr
, context_tmp
->start
, netmask
) &&
319 is_same_net(addr
, context_tmp
->end
, netmask
))
321 context_tmp
->netmask
= netmask
;
322 if (context_tmp
->local
.s_addr
== 0)
323 context_tmp
->local
= fallback
;
324 if (context_tmp
->router
.s_addr
== 0)
325 context_tmp
->router
= mess
->giaddr
;
327 /* fill in missing broadcast addresses for relayed ranges */
328 if (!(context_tmp
->flags
& CONTEXT_BRDCAST
) && context_tmp
->broadcast
.s_addr
== 0 )
329 context_tmp
->broadcast
.s_addr
= context_tmp
->start
.s_addr
| ~context_tmp
->netmask
.s_addr
;
331 context_tmp
->current
= context_new
;
332 context_new
= context_tmp
;
336 if (context_new
|| force
)
337 context
= context_new
;
342 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
343 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
344 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
348 if (option_bool(OPT_LOG_OPTS
))
350 struct dhcp_context
*context_tmp
;
351 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
353 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
354 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
355 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP subnet: %s/%s"),
356 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
358 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
359 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
363 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
364 Otherwise assume the option is an array, and look for a matching element.
365 If no data given, existance of the option is enough. This code handles
366 rfc3925 V-I classes too. */
367 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
369 unsigned int len
, elen
, match
= 0;
372 if (o
->flags
& DHOPT_RFC3925
)
374 if (!(opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT
, 5)))
377 for (offset
= 0; offset
< (option_len(opt
) - 5u); offset
+= len
+ 5)
379 len
= option_uint(opt
, offset
+ 4 , 1);
380 /* Need to take care that bad data can't run us off the end of the packet */
381 if ((offset
+ len
+ 5 <= (option_len(opt
))) &&
382 (option_uint(opt
, offset
, 4) == (unsigned int)o
->u
.encap
))
383 for (o2
= offset
+ 5; o2
< offset
+ len
+ 5; o2
+= elen
+ 1)
385 elen
= option_uint(opt
, o2
, 1);
386 if ((o2
+ elen
+ 1 <= option_len(opt
)) &&
387 (match
= match_bytes(o
, option_ptr(opt
, o2
+ 1), elen
)))
396 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)))
399 match
= match_bytes(o
, option_ptr(opt
, 0), option_len(opt
));
404 o
->netid
->next
= netid
;
409 /* user-class options are, according to RFC3004, supposed to contain
410 a set of counted strings. Here we check that this is so (by seeing
411 if the counts are consistent with the overall option length) and if
412 so zero the counts so that we don't get spurious matches between
413 the vendor string and the counts. If the lengths don't add up, we
414 assume that the option is a single string and non RFC3004 compliant
415 and just do the substring match. dhclient provides these broken options.
416 The code, later, which sends user-class data to the lease-change script
417 relies on the transformation done here.
420 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
422 unsigned char *ucp
= option_ptr(opt
, 0);
424 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
425 if (j
== option_len(opt
))
426 for (j
= 0; j
< option_len(opt
); j
= tmp
)
428 tmp
= j
+ ucp
[j
] + 1;
433 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
437 if (vendor
->match_type
== MATCH_VENDOR
)
438 mopt
= OPTION_VENDOR_ID
;
439 else if (vendor
->match_type
== MATCH_USER
)
440 mopt
= OPTION_USER_CLASS
;
444 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
447 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
448 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
450 vendor
->netid
.next
= netid
;
451 netid
= &vendor
->netid
;
457 /* mark vendor-encapsulated options which match the client-supplied vendor class,
458 save client-supplied vendor class */
459 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
461 memcpy(daemon
->dhcp_buff3
, option_ptr(opt
, 0), option_len(opt
));
462 vendor_class_len
= option_len(opt
);
464 match_vendor_opts(opt
, daemon
->dhcp_opts
);
466 if (option_bool(OPT_LOG_OPTS
))
468 if (sanitise(opt
, daemon
->namebuff
))
469 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
470 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
471 my_syslog(MS_DHCP
| LOG_INFO
, _("%u user class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
474 mess
->op
= BOOTREPLY
;
476 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
477 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
479 /* set "known" tag for known hosts */
482 known_id
.net
= "known";
483 known_id
.next
= netid
;
487 if (mess_type
== 0 && !pxe
)
490 struct dhcp_netid id
, bootp_id
;
491 struct in_addr
*logaddr
= NULL
;
493 /* must have a MAC addr for bootp */
494 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
497 if (have_config(config
, CONFIG_DISABLE
))
498 message
= _("disabled");
500 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
502 if (have_config(config
, CONFIG_NAME
))
504 hostname
= config
->hostname
;
505 domain
= config
->domain
;
510 struct dhcp_netid_list
*list
;
512 for (list
= config
->netid
; list
; list
= list
->next
)
514 list
->list
->next
= netid
;
519 /* Match incoming filename field as a netid. */
522 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
523 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
524 id
.net
= (char *)daemon
->dhcp_buff2
;
529 /* Add "bootp" as a tag to allow different options, address ranges etc
531 bootp_id
.net
= "bootp";
532 bootp_id
.next
= netid
;
535 tagif_netid
= run_tag_if(netid
);
537 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
538 if (match_netid(id_list
->list
, tagif_netid
, 0))
539 message
= _("ignored");
545 if (have_config(config
, CONFIG_ADDR
))
548 logaddr
= &config
->addr
;
549 mess
->yiaddr
= config
->addr
;
550 if ((lease
= lease_find_by_addr(config
->addr
)) &&
551 (lease
->hwaddr_len
!= mess
->hlen
||
552 lease
->hwaddr_type
!= mess
->htype
||
553 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
554 message
= _("address in use");
558 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
559 !address_available(context
, lease
->addr
, tagif_netid
))
563 /* lease exists, wrong network. */
564 lease_prune(lease
, now
);
567 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, tagif_netid
, now
))
568 message
= _("no address available");
571 mess
->yiaddr
= lease
->addr
;
574 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
575 message
= _("wrong network");
576 else if (context
->netid
.net
)
578 context
->netid
.next
= netid
;
579 tagif_netid
= run_tag_if(&context
->netid
);
582 log_tags(tagif_netid
, ntohl(mess
->xid
));
584 if (!message
&& !nailed
)
586 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
587 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
590 message
= _("no address configured");
595 (!(lease
= lease4_allocate(mess
->yiaddr
))))
596 message
= _("no leases left");
600 logaddr
= &mess
->yiaddr
;
602 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0, now
, 1);
604 lease_set_hostname(lease
, hostname
, 1, get_domain(lease
->addr
), domain
);
605 /* infinite lease unless nailed in dhcp-host line. */
606 lease_set_expires(lease
,
607 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
609 lease_set_interface(lease
, int_index
, now
);
611 clear_packet(mess
, end
);
612 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
613 netid
, subnet_addr
, 0, 0, -1, NULL
, vendor_class_len
, now
);
617 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, NULL
, message
, mess
->xid
);
619 return message
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
622 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 3)))
624 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
625 int len
= option_len(opt
);
626 char *pq
= daemon
->dhcp_buff
;
627 unsigned char *pp
, *op
= option_ptr(opt
, 0);
634 /* NB, the following always sets at least one bit */
635 if (option_bool(OPT_FQDN_UPDATE
))
637 if (fqdn_flags
& 0x01)
639 fqdn_flags
|= 0x02; /* set O */
640 fqdn_flags
&= ~0x01; /* clear S */
642 fqdn_flags
|= 0x08; /* set N */
646 if (!(fqdn_flags
& 0x01))
647 fqdn_flags
|= 0x03; /* set S and O */
648 fqdn_flags
&= ~0x08; /* clear N */
651 if (fqdn_flags
& 0x04)
652 while (*op
!= 0 && ((op
+ (*op
)) - pp
) < len
)
654 memcpy(pq
, op
+1, *op
);
662 if (len
> 0 && op
[len
-1] == 0)
667 if (pq
!= daemon
->dhcp_buff
)
672 if (legal_hostname(daemon
->dhcp_buff
))
673 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
675 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
677 int len
= option_len(opt
);
678 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
679 /* Microsoft clients are broken, and need zero-terminated strings
680 in options. We detect this state here, and do the same in
681 any options we send */
682 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
685 daemon
->dhcp_buff
[len
] = 0;
686 if (legal_hostname(daemon
->dhcp_buff
))
687 client_hostname
= daemon
->dhcp_buff
;
690 if (client_hostname
&& option_bool(OPT_LOG_OPTS
))
691 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
693 if (have_config(config
, CONFIG_NAME
))
695 hostname
= config
->hostname
;
696 domain
= config
->domain
;
698 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
699 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
700 offer_hostname
= hostname
;
702 else if (client_hostname
)
704 domain
= strip_hostname(client_hostname
);
706 if (strlen(client_hostname
) != 0)
708 hostname
= client_hostname
;
711 /* Search again now we have a hostname.
712 Only accept configs without CLID and HWADDR here, (they won't match)
713 to avoid impersonation by name. */
714 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
715 mess
->chaddr
, mess
->hlen
,
716 mess
->htype
, hostname
);
717 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
720 /* set "known" tag for known hosts */
721 known_id
.net
= "known";
722 known_id
.next
= netid
;
731 struct dhcp_netid_list
*list
;
733 for (list
= config
->netid
; list
; list
= list
->next
)
735 list
->list
->next
= netid
;
740 tagif_netid
= run_tag_if(netid
);
742 /* if all the netids in the ignore list are present, ignore this client */
743 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
744 if (match_netid(id_list
->list
, tagif_netid
, 0))
747 /* If configured, we can override the server-id to be the address of the relay,
748 so that all traffic goes via the relay and can pick up agent-id info. This can be
749 configured for all relays, or by address. */
750 if (daemon
->override
&& mess
->giaddr
.s_addr
!= 0 && override
.s_addr
== 0)
752 if (!daemon
->override_relays
)
753 override
= mess
->giaddr
;
757 for (l
= daemon
->override_relays
; l
; l
= l
->next
)
758 if (l
->addr
.s_addr
== mess
->giaddr
.s_addr
)
761 override
= mess
->giaddr
;
765 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
766 if (have_config(config
, CONFIG_NOCLID
))
769 /* Check if client is PXE client. */
770 if (daemon
->enable_pxe
&&
771 (opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
772 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
774 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
776 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
780 /* Check if this is really a PXE bootserver request, and handle specially if so. */
781 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
782 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
783 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
785 struct pxe_service
*service
;
786 int type
= option_uint(opt
, 0, 2);
787 int layer
= option_uint(opt
, 2, 2);
788 unsigned char save71
[4];
789 struct dhcp_opt opt71
;
796 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
800 memcpy(save71
, option_ptr(opt
, 0), 4);
802 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
803 if (service
->type
== type
)
806 if (!service
|| !service
->basename
)
809 clear_packet(mess
, end
);
811 mess
->yiaddr
= mess
->ciaddr
;
812 mess
->ciaddr
.s_addr
= 0;
814 mess
->siaddr
= a_record_from_hosts(service
->sname
, now
);
815 else if (service
->server
.s_addr
!= 0)
816 mess
->siaddr
= service
->server
;
818 mess
->siaddr
= context
->local
;
820 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
821 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
822 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
823 pxe_misc(mess
, end
, uuid
);
825 prune_vendor_opts(tagif_netid
);
827 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
829 opt71
.flags
= DHOPT_VENDOR_MATCH
;
831 opt71
.next
= daemon
->dhcp_opts
;
832 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
834 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, NULL
, mess
->xid
);
835 log_tags(tagif_netid
, ntohl(mess
->xid
));
836 return dhcp_packet_size(mess
, agent_id
, real_end
);
839 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
841 pxearch
= option_uint(opt
, 0, 2);
843 /* proxy DHCP here. */
844 if ((mess_type
== DHCPDISCOVER
|| (pxe
&& mess_type
== DHCPREQUEST
)))
846 struct dhcp_context
*tmp
;
848 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
849 if ((tmp
->flags
& CONTEXT_PROXY
) &&
850 match_netid(tmp
->filter
, tagif_netid
, 1))
855 struct dhcp_boot
*boot
;
859 tmp
->netid
.next
= netid
;
860 tagif_netid
= run_tag_if(&tmp
->netid
);
863 boot
= find_boot(tagif_netid
);
865 mess
->yiaddr
.s_addr
= 0;
866 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
868 mess
->ciaddr
.s_addr
= 0;
869 mess
->flags
|= htons(0x8000); /* broadcast */
872 clear_packet(mess
, end
);
874 /* Provide the bootfile here, for gPXE, and in case we have no menu items
875 and set discovery_control = 8 */
878 if (boot
->next_server
.s_addr
)
879 mess
->siaddr
= boot
->next_server
;
880 else if (boot
->tftp_sname
)
881 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
884 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
887 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
888 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
889 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
890 pxe_misc(mess
, end
, uuid
);
891 prune_vendor_opts(tagif_netid
);
892 do_encap_opts(pxe_opts(pxearch
, tagif_netid
, context
->local
, now
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
894 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, ignore
? "proxy-ignored" : "proxy", NULL
, mess
->xid
);
895 log_tags(tagif_netid
, ntohl(mess
->xid
));
896 return ignore
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
902 /* if we're just a proxy server, go no further */
903 if ((context
->flags
& CONTEXT_PROXY
) || pxe
)
906 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
908 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
909 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
910 req_options
[option_len(opt
)] = OPTION_END
;
916 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
917 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
920 /* sanitise any message. Paranoid? Moi? */
921 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
923 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
926 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, NULL
, daemon
->dhcp_buff
, mess
->xid
);
928 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
929 lease_prune(lease
, now
);
931 if (have_config(config
, CONFIG_ADDR
) &&
932 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
934 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
935 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
936 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
937 config
->flags
|= CONFIG_DECLINED
;
938 config
->decline_time
= now
;
941 /* make sure this host gets a different address next time. */
942 for (; context
; context
= context
->current
)
943 context
->addr_epoch
++;
948 if (!(context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
)) ||
949 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
950 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
953 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
954 lease_prune(lease
, now
);
956 message
= _("unknown lease");
958 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, NULL
, message
, mess
->xid
);
963 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
965 if (option_bool(OPT_QUIET_DHCP
))
967 message
= _("ignored");
972 struct in_addr addr
, conf
;
974 addr
.s_addr
= conf
.s_addr
= 0;
976 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
977 addr
= option_addr(opt
);
979 if (have_config(config
, CONFIG_ADDR
))
981 char *addrs
= inet_ntoa(config
->addr
);
983 if ((ltmp
= lease_find_by_addr(config
->addr
)) &&
985 !config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
988 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
989 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
990 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
991 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
995 struct dhcp_context
*tmp
;
996 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
997 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1000 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
1001 else if (have_config(config
, CONFIG_DECLINED
) &&
1002 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
1003 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
1005 conf
= config
->addr
;
1010 mess
->yiaddr
= conf
;
1012 address_available(context
, lease
->addr
, tagif_netid
) &&
1013 !config_find_by_address(daemon
->dhcp_conf
, lease
->addr
))
1014 mess
->yiaddr
= lease
->addr
;
1015 else if (opt
&& address_available(context
, addr
, tagif_netid
) && !lease_find_by_addr(addr
) &&
1016 !config_find_by_address(daemon
->dhcp_conf
, addr
))
1017 mess
->yiaddr
= addr
;
1018 else if (emac_len
== 0)
1019 message
= _("no unique-id");
1020 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, tagif_netid
, now
))
1021 message
= _("no address available");
1024 log_packet("DHCPDISCOVER", opt
? option_ptr(opt
, 0) : NULL
, emac
, emac_len
, iface_name
, NULL
, message
, mess
->xid
);
1026 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1029 if (context
->netid
.net
)
1031 context
->netid
.next
= netid
;
1032 tagif_netid
= run_tag_if(&context
->netid
);
1035 log_tags(tagif_netid
, ntohl(mess
->xid
));
1037 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, NULL
, mess
->xid
);
1039 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1040 clear_packet(mess
, end
);
1041 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
1042 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1043 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1044 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1045 if (time
!= 0xffffffff)
1047 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
1048 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
1050 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
1051 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1053 return dhcp_packet_size(mess
, agent_id
, real_end
);
1056 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1058 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
1060 /* SELECTING or INIT_REBOOT */
1061 mess
->yiaddr
= option_addr(opt
);
1063 /* send vendor and user class info for new or recreated lease */
1066 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
1071 if (override
.s_addr
!= 0)
1073 if (option_addr(opt
).s_addr
!= override
.s_addr
)
1078 for (; context
; context
= context
->current
)
1079 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
1084 /* Handle very strange configs where clients have more than one route to the server.
1085 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1086 Have to set override to make sure we echo back the correct server-id */
1089 enumerate_interfaces(0);
1091 for (intr
= daemon
->interfaces
; intr
; intr
= intr
->next
)
1092 if (intr
->addr
.sa
.sa_family
== AF_INET
&&
1093 intr
->addr
.in
.sin_addr
.s_addr
== option_addr(opt
).s_addr
&&
1098 override
= intr
->addr
.in
.sin_addr
;
1101 /* In auth mode, a REQUEST sent to the wrong server
1102 should be faulted, so that the client establishes
1103 communication with us, otherwise, silently ignore. */
1104 if (!option_bool(OPT_AUTHORITATIVE
))
1106 message
= _("wrong server-ID");
1111 /* If a lease exists for this host and another address, squash it. */
1112 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1114 lease_prune(lease
, now
);
1121 if (!lease
&& !option_bool(OPT_AUTHORITATIVE
))
1124 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1125 message
= _("wrong address");
1130 /* RENEWING or REBINDING */
1131 /* Check existing lease for this address.
1132 We allow it to be missing if dhcp-authoritative mode
1133 as long as we can allocate the lease now - checked below.
1134 This makes for a smooth recovery from a lost lease DB */
1135 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1136 (!lease
&& !option_bool(OPT_AUTHORITATIVE
)))
1138 /* A client rebinding will broadcast the request, so we may see it even
1139 if the lease is held by another server. Just ignore it in that case.
1140 If the request is unicast to us, then somethings wrong, NAK */
1143 message
= _("lease not found");
1144 /* ensure we broadcast NAK */
1148 /* desynchronise renewals */
1150 mess
->yiaddr
= mess
->ciaddr
;
1153 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, NULL
, mess
->xid
);
1157 struct dhcp_config
*addr_config
;
1158 struct dhcp_context
*tmp
= NULL
;
1160 if (have_config(config
, CONFIG_ADDR
))
1161 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1162 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1165 if (!(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1167 /* If a machine moves networks whilst it has a lease, we catch that here. */
1168 message
= _("wrong network");
1169 /* ensure we broadcast NAK */
1173 /* Check for renewal of a lease which is outside the allowed range. */
1174 else if (!address_available(context
, mess
->yiaddr
, tagif_netid
) &&
1175 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1176 message
= _("address not available");
1178 /* Check if a new static address has been configured. Be very sure that
1179 when the client does DISCOVER, it will get the static address, otherwise
1180 an endless protocol loop will ensue. */
1181 else if (!tmp
&& !selecting
&&
1182 have_config(config
, CONFIG_ADDR
) &&
1183 (!have_config(config
, CONFIG_DECLINED
) ||
1184 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1185 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1186 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1187 message
= _("static lease available");
1189 /* Check to see if the address is reserved as a static address for another host */
1190 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1191 message
= _("address reserved");
1193 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1195 /* If a host is configured with more than one MAC address, it's OK to 'nix
1196 a lease from one of it's MACs to give the address to another. */
1197 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1199 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1200 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1201 inet_ntoa(ltmp
->addr
));
1205 message
= _("address in use");
1211 message
= _("no unique-id");
1215 if ((lease
= lease4_allocate(mess
->yiaddr
)))
1218 message
= _("no leases left");
1225 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, message
, mess
->xid
);
1227 mess
->yiaddr
.s_addr
= 0;
1228 clear_packet(mess
, end
);
1229 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1230 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1231 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1232 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1233 a distant subnet which unicast a REQ to us won't work. */
1234 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1235 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1237 mess
->flags
|= htons(0x8000); /* broadcast */
1238 mess
->ciaddr
.s_addr
= 0;
1243 if (context
->netid
.net
)
1245 context
->netid
.next
= netid
;
1246 tagif_netid
= run_tag_if( &context
->netid
);
1249 log_tags(tagif_netid
, ntohl(mess
->xid
));
1253 /* pick up INIT-REBOOT events. */
1254 lease
->flags
|= LEASE_CHANGED
;
1257 if (daemon
->lease_change_command
)
1259 struct dhcp_netid
*n
;
1261 if (mess
->giaddr
.s_addr
)
1262 lease
->giaddr
= mess
->giaddr
;
1264 free(lease
->extradata
);
1265 lease
->extradata
= NULL
;
1266 lease
->extradata_size
= lease
->extradata_len
= 0;
1268 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_VENDOR_ID
, 1));
1269 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_HOSTNAME
, 1));
1270 add_extradata_opt(lease
, oui
);
1271 add_extradata_opt(lease
, serial
);
1272 add_extradata_opt(lease
, class);
1274 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
1276 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_CIRCUIT_ID
, 1));
1277 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBSCR_ID
, 1));
1278 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_REMOTE_ID
, 1));
1282 add_extradata_opt(lease
, NULL
);
1283 add_extradata_opt(lease
, NULL
);
1284 add_extradata_opt(lease
, NULL
);
1287 /* space-concat tag set */
1289 add_extradata_opt(lease
, NULL
);
1291 for (n
= tagif_netid
; n
; n
= n
->next
)
1293 struct dhcp_netid
*n1
;
1295 for (n1
= n
->next
; n1
; n1
= n1
->next
)
1296 if (strcmp(n
->net
, n1
->net
) == 0)
1299 lease_add_extradata(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
1302 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1304 int len
= option_len(opt
);
1305 unsigned char *ucp
= option_ptr(opt
, 0);
1306 /* If the user-class option started as counted strings, the first byte will be zero. */
1307 if (len
!= 0 && ucp
[0] == 0)
1309 lease_add_extradata(lease
, ucp
, len
, 0);
1315 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1317 domain
= get_domain(mess
->yiaddr
);
1318 hostname
= client_hostname
;
1322 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1323 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
, now
, do_classes
);
1325 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1328 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1329 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1335 /* Last ditch, if configured, generate hostname from mac address */
1336 if (!hostname
&& emac_len
!= 0)
1338 for (id_list
= daemon
->dhcp_gen_names
; id_list
; id_list
= id_list
->next
)
1339 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1345 hostname
= daemon
->dhcp_buff
;
1346 /* buffer is 256 bytes, 3 bytes per octet */
1347 for (i
= 0; (i
< emac_len
) && (i
< 80); i
++)
1348 hostname
+= sprintf(hostname
, "%.2x%s", emac
[i
], (i
== emac_len
- 1) ? "" : "-");
1349 hostname
= daemon
->dhcp_buff
;
1354 lease_set_hostname(lease
, hostname
, hostname_auth
, get_domain(lease
->addr
), domain
);
1356 lease_set_expires(lease
, time
, now
);
1357 lease_set_interface(lease
, int_index
, now
);
1359 if (override
.s_addr
!= 0)
1360 lease
->override
= override
;
1362 override
= lease
->override
;
1364 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, NULL
, mess
->xid
);
1366 clear_packet(mess
, end
);
1367 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1368 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1369 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1370 if (time
!= 0xffffffff)
1372 while (fuzz
> (time
/16))
1374 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
1375 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
1377 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1378 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1381 return dhcp_packet_size(mess
, agent_id
, real_end
);
1384 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1385 message
= _("ignored");
1387 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, NULL
, mess
->xid
);
1389 if (message
|| mess
->ciaddr
.s_addr
== 0)
1392 /* For DHCPINFORM only, cope without a valid context */
1393 context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
);
1395 /* Find a least based on IP address if we didn't
1396 get one from MAC address/client-d */
1398 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1400 hostname
= lease
->hostname
;
1403 hostname
= host_from_dns(mess
->ciaddr
);
1405 if (context
&& context
->netid
.net
)
1407 context
->netid
.next
= netid
;
1408 tagif_netid
= run_tag_if(&context
->netid
);
1411 log_tags(tagif_netid
, ntohl(mess
->xid
));
1413 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, NULL
, mess
->xid
);
1417 lease_set_interface(lease
, int_index
, now
);
1418 if (override
.s_addr
!= 0)
1419 lease
->override
= override
;
1421 override
= lease
->override
;
1424 clear_packet(mess
, end
);
1425 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1426 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1428 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1429 we supply a utility which makes DHCPINFORM requests to get this information.
1430 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1431 which won't be true for ordinary clients, but will be true for the
1432 dhcp_lease_time utility. */
1433 if (lease
&& in_list(req_options
, OPTION_LEASE_TIME
))
1435 if (lease
->expires
== 0)
1438 time
= (unsigned int)difftime(lease
->expires
, now
);
1439 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1442 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1443 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1445 *is_inform
= 1; /* handle reply differently */
1446 return dhcp_packet_size(mess
, agent_id
, real_end
);
1452 /* find a good value to use as MAC address for logging and address-allocation hashing.
1453 This is normally just the chaddr field from the DHCP packet,
1454 but eg Firewire will have hlen == 0 and use the client-id instead.
1455 This could be anything, but will normally be EUI64 for Firewire.
1456 We assume that if the first byte of the client-id equals the htype byte
1457 then the client-id is using the usual encoding and use the rest of the
1458 client-id: if not we can use the whole client-id. This should give
1459 sane MAC address logs. */
1460 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1461 int clid_len
, unsigned char *clid
, int *len_out
)
1463 if (hwlen
== 0 && clid
&& clid_len
> 3)
1465 if (clid
[0] == hwtype
)
1467 *len_out
= clid_len
- 1 ;
1471 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1472 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1474 *len_out
= clid_len
- 1 ;
1479 *len_out
= clid_len
;
1487 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1489 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1493 unsigned int req_time
= option_uint(opt
, 0, 4);
1494 if (req_time
< 120 )
1495 req_time
= 120; /* sanity */
1496 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1503 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1505 if (override
.s_addr
!= 0)
1507 else if (context
&& context
->local
.s_addr
!= 0)
1508 return context
->local
;
1513 static int sanitise(unsigned char *opt
, char *buf
)
1523 p
= option_ptr(opt
, 0);
1525 for (i
= option_len(opt
); i
> 0; i
--)
1528 if (isprint((int)c
))
1531 *buf
= 0; /* add terminator */
1537 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
)
1540 lease_add_extradata(lease
, NULL
, 0, 0);
1542 lease_add_extradata(lease
, option_ptr(opt
, 0), option_len(opt
), 0);
1546 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1547 int mac_len
, char *interface
, char *string
, char *err
, u32 xid
)
1551 if (!err
&& !option_bool(OPT_LOG_OPTS
) && option_bool(OPT_QUIET_DHCP
))
1554 /* addr may be misaligned */
1556 memcpy(&a
, addr
, sizeof(a
));
1558 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1560 if(option_bool(OPT_LOG_OPTS
))
1561 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s%s",
1565 addr
? inet_ntoa(a
) : "",
1568 string
? string
: "",
1571 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s%s",
1574 addr
? inet_ntoa(a
) : "",
1577 string
? string
: "",
1581 static void log_options(unsigned char *start
, u32 xid
)
1583 while (*start
!= OPTION_END
)
1585 char *optname
= option_string(AF_INET
, start
[0], option_ptr(start
, 0), option_len(start
), daemon
->namebuff
, MAXDNAME
);
1587 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d %s %s",
1588 ntohl(xid
), option_len(start
), start
[0], optname
, daemon
->namebuff
);
1589 start
+= start
[1] + 2;
1593 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1599 else if (*p
== OPTION_END
)
1600 return opt
== OPTION_END
? p
: NULL
;
1601 else if (*p
== OPTION_PAD
)
1607 return NULL
; /* malformed packet */
1608 opt_len
= option_len(p
);
1609 if (p
> end
- (2 + opt_len
))
1610 return NULL
; /* malformed packet */
1611 if (*p
== opt
&& opt_len
>= minsize
)
1618 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1620 unsigned char *ret
, *overload
;
1622 /* skip over DHCP cookie; */
1623 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1626 /* look for overload option. */
1627 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1630 /* Can we look in filename area ? */
1631 if ((overload
[2] & 1) &&
1632 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1635 /* finally try sname area */
1636 if ((overload
[2] & 2) &&
1637 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1643 static struct in_addr
option_addr(unsigned char *opt
)
1645 /* this worries about unaligned data in the option. */
1646 /* struct in_addr is network byte order */
1649 memcpy(&ret
, option_ptr(opt
, 0), INADDRSZ
);
1654 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1656 /* this worries about unaligned data and byte order */
1657 unsigned int ret
= 0;
1659 unsigned char *p
= option_ptr(opt
, offset
);
1661 for (i
= 0; i
< size
; i
++)
1662 ret
= (ret
<< 8) | *p
++;
1667 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1670 start
+= start
[1] + 2;
1674 /* only for use when building packet: doesn't check for bad data. */
1675 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1677 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1681 if (*p
== OPTION_OVERLOAD
)
1688 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
)
1690 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1691 unsigned char *overload
;
1694 /* move agent_id back down to the end of the packet */
1697 memmove(p
, agent_id
, real_end
- agent_id
);
1698 p
+= real_end
- agent_id
;
1699 memset(p
, 0, real_end
- p
); /* in case of overlap */
1702 /* add END options to the regions. */
1703 overload
= find_overload(mess
);
1705 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1707 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1708 if (option_bool(OPT_LOG_OPTS
))
1709 log_options(mess
->file
, mess
->xid
);
1711 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1712 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1714 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1716 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1717 if (option_bool(OPT_LOG_OPTS
))
1718 log_options(mess
->sname
, mess
->xid
);
1720 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1721 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1726 if (option_bool(OPT_LOG_OPTS
))
1728 if (mess
->siaddr
.s_addr
!= 0)
1729 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1731 if ((mess
->flags
& htons(0x8000)) && mess
->ciaddr
.s_addr
== 0)
1732 my_syslog(MS_DHCP
| LOG_INFO
, _("%u broadcast response"), ntohl(mess
->xid
));
1734 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1737 ret
= (size_t)(p
- (unsigned char *)mess
);
1739 if (ret
< MIN_PACKETSZ
)
1745 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1747 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1749 if (p
+ len
+ 3 >= end
)
1750 /* not enough space in options area, try and use overload, if poss */
1752 unsigned char *overload
;
1754 if (!(overload
= find_overload(mess
)) &&
1755 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1757 /* attempt to overload fname and sname areas, we've reserved space for the
1758 overflow option previuously. */
1760 *(p
++) = OPTION_OVERLOAD
;
1766 /* using filename field ? */
1769 if (mess
->file
[0] == 0)
1772 if (overload
[2] & 1)
1774 p
= dhcp_skip_opts(mess
->file
);
1775 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1781 /* try to bring sname into play (it may be already) */
1782 if (mess
->sname
[0] == 0)
1785 if (overload
[2] & 2)
1787 p
= dhcp_skip_opts(mess
->sname
);
1788 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->sname
))
1795 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1807 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1810 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1813 for (i
= 0; i
< len
; i
++)
1814 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1817 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1818 char *string
, int null_term
)
1821 size_t len
= strlen(string
);
1823 if (null_term
&& len
!= 255)
1826 if ((p
= free_space(mess
, end
, opt
, len
)))
1827 memcpy(p
, string
, len
);
1830 /* return length, note this only does the data part */
1831 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1835 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1840 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1843 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1844 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1846 /* zero means "self" (but not in vendorclass options.) */
1848 memcpy(p
, &context
->local
, INADDRSZ
);
1850 memcpy(p
, a
, INADDRSZ
);
1855 /* empty string may be extended to "\0" by null_term */
1856 memcpy(p
, opt
->val
? opt
->val
: (unsigned char *)"", len
);
1861 static int in_list(unsigned char *list
, int opt
)
1865 /* If no requested options, send everything, not nothing. */
1869 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1876 static struct dhcp_opt
*option_find2(int opt
)
1878 struct dhcp_opt
*opts
;
1880 for (opts
= daemon
->dhcp_opts
; opts
; opts
= opts
->next
)
1881 if (opts
->opt
== opt
&& (opts
->flags
& DHOPT_TAGOK
))
1887 /* mark vendor-encapsulated options which match the client-supplied or
1888 config-supplied vendor class */
1889 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1891 for (; dopt
; dopt
= dopt
->next
)
1893 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1894 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1897 if (dopt
->u
.vendor_class
)
1898 len
= strlen((char *)dopt
->u
.vendor_class
);
1899 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1900 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1902 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1909 static int do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1910 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1912 int len
, enc_len
, ret
= 0;
1913 struct dhcp_opt
*start
;
1916 /* find size in advance */
1917 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1918 if (opt
->flags
& flag
)
1920 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1922 if (enc_len
+ new <= 255)
1926 p
= free_space(mess
, end
, encap
, enc_len
);
1927 for (; start
&& start
!= opt
; start
= start
->next
)
1928 if (p
&& (start
->flags
& flag
))
1930 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1931 *(p
++) = start
->opt
;
1941 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
1943 for (; start
; start
= start
->next
)
1944 if (start
->flags
& flag
)
1946 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1947 *(p
++) = start
->opt
;
1957 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
1961 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
1962 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
1963 memcpy(p
, uuid
, 17);
1966 static int prune_vendor_opts(struct dhcp_netid
*netid
)
1969 struct dhcp_opt
*opt
;
1971 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1972 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
1973 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1975 if (!match_netid(opt
->netid
, netid
, 1))
1976 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1977 else if (opt
->flags
& DHOPT_FORCE
)
1983 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
)
1987 unsigned char *p
, *q
;
1988 struct pxe_service
*service
;
1989 static struct dhcp_opt
*o
, *ret
;
1990 int i
, j
= NUM_OPTS
- 1;
1991 struct in_addr boot_server
;
1993 /* We pass back references to these, hence they are declared static */
1994 static unsigned char discovery_control
;
1995 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
1996 static struct dhcp_opt
*fake_opts
= NULL
;
1998 /* Disable multicast, since we don't support it, and broadcast
1999 unless we need it */
2000 discovery_control
= 3;
2002 ret
= daemon
->dhcp_opts
;
2004 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
2007 for (i
= 0; i
< NUM_OPTS
; i
++)
2009 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
2010 fake_opts
[i
].netid
= NULL
;
2011 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
2014 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2015 p
= (unsigned char *)daemon
->dhcp_buff
;
2016 q
= (unsigned char *)daemon
->dhcp_buff3
;
2018 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
2019 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
2021 size_t len
= strlen(service
->menu
);
2022 /* opt 43 max size is 255. encapsulated option has type and length
2023 bytes, so its max size is 253. */
2024 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
2026 *(p
++) = service
->type
>> 8;
2027 *(p
++) = service
->type
;
2029 memcpy(p
, service
->menu
, len
);
2036 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
2037 return daemon
->dhcp_opts
;
2040 boot_server
= service
->basename
? local
:
2041 (service
->sname
? a_record_from_hosts(service
->sname
, now
) : service
->server
);
2043 if (boot_server
.s_addr
!= 0)
2045 if (q
- (unsigned char *)daemon
->dhcp_buff3
+ 3 + INADDRSZ
>= 253)
2048 /* Boot service with known address - give it */
2049 *(q
++) = service
->type
>> 8;
2050 *(q
++) = service
->type
;
2052 /* dest misaligned */
2053 memcpy(q
, &boot_server
.s_addr
, INADDRSZ
);
2056 else if (service
->type
!= 0)
2057 /* We don't know the server for a service type, so we'll
2058 allow the client to broadcast for it */
2059 discovery_control
= 2;
2062 /* if no prompt, wait forever if there's a choice */
2063 fake_prompt
[0] = (i
> 1) ? 255 : 0;
2066 discovery_control
= 8; /* no menu - just use use mess->filename */
2069 ret
= &fake_opts
[j
--];
2070 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
2071 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
2072 ret
->opt
= SUBOPT_PXE_MENU
;
2074 if (q
- (unsigned char *)daemon
->dhcp_buff3
!= 0)
2076 ret
= &fake_opts
[j
--];
2077 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff3
;
2078 ret
->val
= (unsigned char *)daemon
->dhcp_buff3
;
2079 ret
->opt
= SUBOPT_PXE_SERVERS
;
2083 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
2084 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
2089 ret
= &fake_opts
[j
--];
2090 ret
->len
= sizeof(fake_prompt
);
2091 ret
->val
= fake_prompt
;
2092 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
2095 ret
= &fake_opts
[j
--];
2097 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
2098 ret
->val
= &discovery_control
;
2103 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
2105 memset(mess
->sname
, 0, sizeof(mess
->sname
));
2106 memset(mess
->file
, 0, sizeof(mess
->file
));
2107 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
2108 mess
->siaddr
.s_addr
= 0;
2111 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
2113 struct dhcp_boot
*boot
;
2115 /* decide which dhcp-boot option we're using */
2116 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2117 if (match_netid(boot
->netid
, netid
, 0))
2120 /* No match, look for one without a netid */
2121 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2122 if (match_netid(boot
->netid
, netid
, 1))
2128 static void do_options(struct dhcp_context
*context
,
2129 struct dhcp_packet
*mess
,
2131 unsigned char *req_options
,
2134 struct dhcp_netid
*netid
,
2135 struct in_addr subnet_addr
,
2136 unsigned char fqdn_flags
,
2137 int null_term
, int pxe_arch
,
2138 unsigned char *uuid
,
2139 int vendor_class_len
,
2142 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2143 struct dhcp_boot
*boot
;
2145 int i
, len
, force_encap
= 0;
2146 unsigned char f0
= 0, s0
= 0;
2147 int done_file
= 0, done_server
= 0;
2148 int done_vendor_class
= 0;
2149 struct dhcp_netid
*tagif
;
2150 struct dhcp_netid_list
*id_list
;
2152 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2154 context
->netid
.next
= NULL
;
2155 tagif
= option_filter(netid
, context
&& context
->netid
.net
? &context
->netid
: NULL
, config_opts
);
2158 if (option_bool(OPT_LOG_OPTS
) && req_options
)
2160 char *q
= daemon
->namebuff
;
2161 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2163 char *s
= option_string(AF_INET
, req_options
[i
], NULL
, 0, NULL
, 0);
2164 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2167 strlen(s
) != 0 ? ":" : "",
2169 req_options
[i
+1] == OPTION_END
? "" : ", ");
2170 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2172 q
= daemon
->namebuff
;
2173 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2178 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
2179 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
2182 mess
->flags
|= htons(0x8000); /* force broadcast */
2185 mess
->siaddr
= context
->local
;
2187 /* See if we can send the boot stuff as options.
2188 To do this we need a requested option list, BOOTP
2189 and very old DHCP clients won't have this, we also
2190 provide an manual option to disable it.
2191 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2192 names, so we always send those. */
2193 if ((boot
= find_boot(tagif
)))
2197 if (!option_bool(OPT_NO_OVERRIDE
) &&
2199 in_list(req_options
, OPTION_SNAME
))
2200 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2202 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2207 if (!option_bool(OPT_NO_OVERRIDE
) &&
2209 in_list(req_options
, OPTION_FILENAME
))
2210 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2212 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2215 if (boot
->next_server
.s_addr
)
2216 mess
->siaddr
= boot
->next_server
;
2217 else if (boot
->tftp_sname
)
2218 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
2221 /* Use the values of the relevant options if no dhcp-boot given and
2222 they're not explicitly asked for as options. OPTION_END is used
2223 as an internal way to specify siaddr without using dhcp-boot, for use in
2226 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
2227 (opt
= option_find2(OPTION_FILENAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2229 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2233 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2234 (opt
= option_find2(OPTION_SNAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2236 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2240 if ((opt
= option_find2(OPTION_END
)))
2241 mess
->siaddr
.s_addr
= ((struct in_addr
*)opt
->val
)->s_addr
;
2244 /* We don't want to do option-overload for BOOTP, so make the file and sname
2245 fields look like they are in use, even when they aren't. This gets restored
2246 at the end of this function. */
2248 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2252 s0
= mess
->sname
[0];
2256 /* At this point, if mess->sname or mess->file are zeroed, they are available
2257 for option overload, reserve space for the overload option. */
2258 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2261 /* rfc3011 says this doesn't need to be in the requested options list. */
2262 if (subnet_addr
.s_addr
)
2263 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2265 /* replies to DHCPINFORM may not have a valid context */
2268 if (!option_find2(OPTION_NETMASK
))
2269 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2271 /* May not have a "guessed" broadcast address if we got no packets via a relay
2272 from this net yet (ie just unicast renewals after a restart */
2273 if (context
->broadcast
.s_addr
&&
2274 !option_find2(OPTION_BROADCAST
))
2275 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2277 /* Same comments as broadcast apply, and also may not be able to get a sensible
2278 default when using subnet select. User must configure by steam in that case. */
2279 if (context
->router
.s_addr
&&
2280 in_list(req_options
, OPTION_ROUTER
) &&
2281 !option_find2(OPTION_ROUTER
))
2282 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2284 if (daemon
->port
== NAMESERVER_PORT
&&
2285 in_list(req_options
, OPTION_DNSSERVER
) &&
2286 !option_find2(OPTION_DNSSERVER
))
2287 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2290 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2291 !option_find2(OPTION_DOMAINNAME
))
2292 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2294 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2297 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2298 !option_find2(OPTION_HOSTNAME
))
2299 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2301 if (fqdn_flags
!= 0)
2303 len
= strlen(hostname
) + 3;
2305 if (fqdn_flags
& 0x04)
2311 len
+= strlen(domain
) + 1;
2312 else if (fqdn_flags
& 0x04)
2315 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2317 *(p
++) = fqdn_flags
& 0x0f; /* MBZ bits to zero */
2321 if (fqdn_flags
& 0x04)
2323 p
= do_rfc1035_name(p
, hostname
);
2326 p
= do_rfc1035_name(p
, domain
);
2332 memcpy(p
, hostname
, strlen(hostname
));
2333 p
+= strlen(hostname
);
2337 memcpy(p
, domain
, strlen(domain
));
2338 p
+= strlen(domain
);
2347 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2349 int optno
= opt
->opt
;
2351 /* netids match and not encapsulated? */
2352 if (!(opt
->flags
& DHOPT_TAGOK
))
2355 /* was it asked for, or are we sending it anyway? */
2356 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2359 /* prohibit some used-internally options */
2360 if (optno
== OPTION_CLIENT_FQDN
||
2361 optno
== OPTION_MAXMESSAGE
||
2362 optno
== OPTION_OVERLOAD
||
2363 optno
== OPTION_PAD
||
2364 optno
== OPTION_END
)
2367 if (optno
== OPTION_SNAME
&& done_server
)
2370 if (optno
== OPTION_FILENAME
&& done_file
)
2373 /* For the options we have default values on
2374 dhc-option=<optionno> means "don't include this option"
2375 not "include a zero-length option" */
2376 if (opt
->len
== 0 &&
2377 (optno
== OPTION_NETMASK
||
2378 optno
== OPTION_BROADCAST
||
2379 optno
== OPTION_ROUTER
||
2380 optno
== OPTION_DNSSERVER
||
2381 optno
== OPTION_DOMAINNAME
||
2382 optno
== OPTION_HOSTNAME
))
2385 /* vendor-class comes from elsewhere for PXE */
2386 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2389 /* always force null-term for filename and servername - buggy PXE again. */
2390 len
= do_opt(opt
, NULL
, context
,
2391 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2393 if ((p
= free_space(mess
, end
, optno
, len
)))
2395 do_opt(opt
, p
, context
,
2396 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2398 /* If we send a vendor-id, revisit which vendor-ops we consider
2399 it appropriate to send. */
2400 if (optno
== OPTION_VENDOR_ID
)
2402 match_vendor_opts(p
- 2, config_opts
);
2403 done_vendor_class
= 1;
2408 /* Now send options to be encapsulated in arbitrary options,
2409 eg dhcp-option=encap:172,17,.......
2410 Also handle vendor-identifying vendor-encapsulated options,
2411 dhcp-option = vi-encap:13,17,.......
2412 The may be more that one "outer" to do, so group
2413 all the options which match each outer in turn. */
2414 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2415 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2417 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2421 if ((flags
= (opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_RFC3925
))))
2426 if (opt
->flags
& DHOPT_ENCAP_DONE
)
2429 for (len
= 0, o
= config_opts
; o
; o
= o
->next
)
2431 int outer
= flags
& DHOPT_ENCAPSULATE
? o
->u
.encap
: OPTION_VENDOR_IDENT_OPT
;
2433 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2435 if (!(o
->flags
& flags
) || opt
->u
.encap
!= o
->u
.encap
)
2438 o
->flags
|= DHOPT_ENCAP_DONE
;
2439 if (match_netid(o
->netid
, tagif
, 1) &&
2440 ((o
->flags
& DHOPT_FORCE
) || in_list(req_options
, outer
)))
2442 o
->flags
|= DHOPT_ENCAP_MATCH
;
2444 len
+= do_opt(o
, NULL
, NULL
, 0) + 2;
2450 if (flags
& DHOPT_ENCAPSULATE
)
2451 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2453 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt
->u
.encap
);
2454 else if ((p
= free_space(mess
, end
, OPTION_VENDOR_IDENT_OPT
, len
+ 5)))
2456 int swap_ent
= htonl(opt
->u
.encap
);
2457 memcpy(p
, &swap_ent
, 4);
2460 for (o
= config_opts
; o
; o
= o
->next
)
2461 if (o
->flags
& DHOPT_ENCAP_MATCH
)
2463 len
= do_opt(o
, p
+ 2, NULL
, 0);
2473 force_encap
= prune_vendor_opts(tagif
);
2475 if (context
&& pxe_arch
!= -1)
2477 pxe_misc(mess
, end
, uuid
);
2478 config_opts
= pxe_opts(pxe_arch
, tagif
, context
->local
, now
);
2481 if ((force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
)) &&
2482 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
) &&
2483 pxe_arch
== -1 && !done_vendor_class
&& vendor_class_len
!= 0 &&
2484 (p
= free_space(mess
, end
, OPTION_VENDOR_ID
, vendor_class_len
)))
2485 /* If we send vendor encapsulated options, and haven't already sent option 60,
2486 echo back the value we got from the client. */
2487 memcpy(p
, daemon
->dhcp_buff3
, vendor_class_len
);
2489 /* restore BOOTP anti-overload hack */
2490 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2493 mess
->sname
[0] = s0
;