]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc2131.c
1 /* dnsmasq is Copyright (c) 2000-2015 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
,
56 unsigned int lease_time
,
60 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
61 static int do_encap_opts(struct dhcp_opt
*opts
, int encap
, int flag
, struct dhcp_packet
*mess
, unsigned char *end
, int null_term
);
62 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
);
63 static int prune_vendor_opts(struct dhcp_netid
*netid
);
64 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
);
65 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
);
68 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
69 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
, int pxe
, struct in_addr fallback
)
71 unsigned char *opt
, *clid
= NULL
;
72 struct dhcp_lease
*ltmp
, *lease
= NULL
;
73 struct dhcp_vendor
*vendor
;
75 struct dhcp_netid_list
*id_list
;
76 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0, pxearch
= -1;
77 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
78 unsigned char *end
= (unsigned char *)(mess
+ 1);
79 unsigned char *real_end
= (unsigned char *)(mess
+ 1);
80 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
, *domain
= NULL
;
81 int hostname_auth
= 0, borken_opt
= 0;
82 unsigned char *req_options
= NULL
;
85 struct dhcp_config
*config
;
86 struct dhcp_netid
*netid
, *tagif_netid
;
87 struct in_addr subnet_addr
, override
;
88 unsigned short fuzz
= 0;
89 unsigned int mess_type
= 0;
90 unsigned char fqdn_flags
= 0;
91 unsigned char *agent_id
= NULL
, *uuid
= NULL
;
92 unsigned char *emac
= NULL
;
93 int vendor_class_len
= 0, emac_len
= 0;
94 struct dhcp_netid known_id
, iface_id
, cpewan_id
;
96 unsigned char pxe_uuid
[17];
97 unsigned char *oui
= NULL
, *serial
= NULL
;
99 unsigned char *class = NULL
;
102 subnet_addr
.s_addr
= override
.s_addr
= 0;
104 /* set tag with name == interface */
105 iface_id
.net
= iface_name
;
106 iface_id
.next
= NULL
;
109 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
112 if (mess
->htype
== 0 && mess
->hlen
!= 0)
115 /* check for DHCP rather than BOOTP */
116 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
118 u32 cookie
= htonl(DHCP_COOKIE
);
120 /* only insist on a cookie for DHCP. */
121 if (memcmp(mess
->options
, &cookie
, sizeof(u32
)) != 0)
124 mess_type
= option_uint(opt
, 0, 1);
126 /* two things to note here: expand_buf may move the packet,
127 so reassign mess from daemon->packet. Also, the size
128 sent includes the IP and UDP headers, hence the magic "-28" */
129 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
131 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
133 if (size
> DHCP_PACKET_MAX
)
134 size
= DHCP_PACKET_MAX
;
135 else if (size
< sizeof(struct dhcp_packet
))
136 size
= sizeof(struct dhcp_packet
);
138 if (expand_buf(&daemon
->dhcp_packet
, size
))
140 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
141 real_end
= end
= ((unsigned char *)mess
) + size
;
145 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
146 it can affect the context-determination code. */
147 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
148 mess
->ciaddr
.s_addr
= 0;
150 /* search for device identity from CPEWAN devices, we pass this through to the script */
151 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT_OPT
, 5)))
153 unsigned int elen
, offset
, len
= option_len(opt
);
155 for (offset
= 0; offset
< (len
- 5); offset
+= elen
+ 5)
157 elen
= option_uint(opt
, offset
+ 4 , 1);
158 if (option_uint(opt
, offset
, 4) == BRDBAND_FORUM_IANA
)
160 unsigned char *x
= option_ptr(opt
, offset
+ 5);
161 unsigned char *y
= option_ptr(opt
, offset
+ elen
+ 5);
162 oui
= option_find1(x
, y
, 1, 1);
163 serial
= option_find1(x
, y
, 2, 1);
165 class = option_find1(x
, y
, 3, 1);
167 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
168 the gateway id back. Note that the device class is optional */
171 cpewan_id
.net
= "cpewan-id";
172 cpewan_id
.next
= netid
;
180 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
182 /* Any agent-id needs to be copied back out, verbatim, as the last option
183 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
184 get overwritten, then it will be shuffled back at the end of processing.
185 Note that the incoming options must not be overwritten here, so there has to
186 be enough free space at the end of the packet to copy the option. */
188 unsigned int total
= option_len(opt
) + 2;
189 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
190 if (last_opt
&& last_opt
< end
- total
)
194 memcpy(agent_id
, opt
, total
);
197 /* look for RFC3527 Link selection sub-option */
198 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
199 subnet_addr
= option_addr(sopt
);
201 /* look for RFC5107 server-identifier-override */
202 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
203 override
= option_addr(sopt
);
205 /* if a circuit-id or remote-is option is provided, exact-match to options. */
206 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
210 if (vendor
->match_type
== MATCH_CIRCUIT
)
211 search
= SUBOPT_CIRCUIT_ID
;
212 else if (vendor
->match_type
== MATCH_REMOTE
)
213 search
= SUBOPT_REMOTE_ID
;
214 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
215 search
= SUBOPT_SUBSCR_ID
;
219 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
220 vendor
->len
== option_len(sopt
) &&
221 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
223 vendor
->netid
.next
= netid
;
224 netid
= &vendor
->netid
;
229 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
230 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
231 subnet_addr
= option_addr(opt
);
233 /* If there is no client identifier option, use the hardware address */
234 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
236 clid_len
= option_len(opt
);
237 clid
= option_ptr(opt
, 0);
240 /* do we have a lease in store? */
241 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
243 /* If this request is missing a clid, but we've seen one before,
244 use it again for option matching etc. */
245 if (lease
&& !clid
&& lease
->clid
)
247 clid_len
= lease
->clid_len
;
251 /* find mac to use for logging and hashing */
252 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
255 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
256 if (mac
->hwaddr_len
== mess
->hlen
&&
257 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
258 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
260 mac
->netid
.next
= netid
;
264 /* Determine network for this packet. Our caller will have already linked all the
265 contexts which match the addresses of the receiving interface but if the
266 machine has an address already, or came via a relay, or we have a subnet selector,
267 we search again. If we don't have have a giaddr or explicit subnet selector,
268 use the ciaddr. This is necessary because a machine which got a lease via a
269 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
270 from the physical network, continue using that to allow correct DHCPNAK generation later. */
271 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
273 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
277 if (subnet_addr
.s_addr
)
282 else if (mess
->giaddr
.s_addr
)
289 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
291 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
292 if (context_tmp
->netmask
.s_addr
&&
293 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
294 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
296 context_new
= context
;
302 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
304 struct in_addr netmask
= context_tmp
->netmask
;
306 /* guess the netmask for relayed networks */
307 if (!(context_tmp
->flags
& CONTEXT_NETMASK
) && context_tmp
->netmask
.s_addr
== 0)
309 if (IN_CLASSA(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSA(ntohl(context_tmp
->end
.s_addr
)))
310 netmask
.s_addr
= htonl(0xff000000);
311 else if (IN_CLASSB(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSB(ntohl(context_tmp
->end
.s_addr
)))
312 netmask
.s_addr
= htonl(0xffff0000);
313 else if (IN_CLASSC(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSC(ntohl(context_tmp
->end
.s_addr
)))
314 netmask
.s_addr
= htonl(0xffffff00);
317 /* This section fills in context mainly when a client which is on a remote (relayed)
318 network renews a lease without using the relay, after dnsmasq has restarted. */
319 if (netmask
.s_addr
!= 0 &&
320 is_same_net(addr
, context_tmp
->start
, netmask
) &&
321 is_same_net(addr
, context_tmp
->end
, netmask
))
323 context_tmp
->netmask
= netmask
;
324 if (context_tmp
->local
.s_addr
== 0)
325 context_tmp
->local
= fallback
;
326 if (context_tmp
->router
.s_addr
== 0)
327 context_tmp
->router
= mess
->giaddr
;
329 /* fill in missing broadcast addresses for relayed ranges */
330 if (!(context_tmp
->flags
& CONTEXT_BRDCAST
) && context_tmp
->broadcast
.s_addr
== 0 )
331 context_tmp
->broadcast
.s_addr
= context_tmp
->start
.s_addr
| ~context_tmp
->netmask
.s_addr
;
333 context_tmp
->current
= context_new
;
334 context_new
= context_tmp
;
338 if (context_new
|| force
)
339 context
= context_new
;
344 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
345 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
346 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
350 if (option_bool(OPT_LOG_OPTS
))
352 struct dhcp_context
*context_tmp
;
353 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
355 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
356 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
357 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP subnet: %s/%s"),
358 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
360 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
361 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
365 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
366 Otherwise assume the option is an array, and look for a matching element.
367 If no data given, existance of the option is enough. This code handles
368 rfc3925 V-I classes too. */
369 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
371 unsigned int len
, elen
, match
= 0;
374 if (o
->flags
& DHOPT_RFC3925
)
376 if (!(opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT
, 5)))
379 for (offset
= 0; offset
< (option_len(opt
) - 5u); offset
+= len
+ 5)
381 len
= option_uint(opt
, offset
+ 4 , 1);
382 /* Need to take care that bad data can't run us off the end of the packet */
383 if ((offset
+ len
+ 5 <= (option_len(opt
))) &&
384 (option_uint(opt
, offset
, 4) == (unsigned int)o
->u
.encap
))
385 for (o2
= offset
+ 5; o2
< offset
+ len
+ 5; o2
+= elen
+ 1)
387 elen
= option_uint(opt
, o2
, 1);
388 if ((o2
+ elen
+ 1 <= option_len(opt
)) &&
389 (match
= match_bytes(o
, option_ptr(opt
, o2
+ 1), elen
)))
398 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)))
401 match
= match_bytes(o
, option_ptr(opt
, 0), option_len(opt
));
406 o
->netid
->next
= netid
;
411 /* user-class options are, according to RFC3004, supposed to contain
412 a set of counted strings. Here we check that this is so (by seeing
413 if the counts are consistent with the overall option length) and if
414 so zero the counts so that we don't get spurious matches between
415 the vendor string and the counts. If the lengths don't add up, we
416 assume that the option is a single string and non RFC3004 compliant
417 and just do the substring match. dhclient provides these broken options.
418 The code, later, which sends user-class data to the lease-change script
419 relies on the transformation done here.
422 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
424 unsigned char *ucp
= option_ptr(opt
, 0);
426 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
427 if (j
== option_len(opt
))
428 for (j
= 0; j
< option_len(opt
); j
= tmp
)
430 tmp
= j
+ ucp
[j
] + 1;
435 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
439 if (vendor
->match_type
== MATCH_VENDOR
)
440 mopt
= OPTION_VENDOR_ID
;
441 else if (vendor
->match_type
== MATCH_USER
)
442 mopt
= OPTION_USER_CLASS
;
446 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
449 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
450 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
452 vendor
->netid
.next
= netid
;
453 netid
= &vendor
->netid
;
459 /* mark vendor-encapsulated options which match the client-supplied vendor class,
460 save client-supplied vendor class */
461 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
463 memcpy(daemon
->dhcp_buff3
, option_ptr(opt
, 0), option_len(opt
));
464 vendor_class_len
= option_len(opt
);
466 match_vendor_opts(opt
, daemon
->dhcp_opts
);
468 if (option_bool(OPT_LOG_OPTS
))
470 if (sanitise(opt
, daemon
->namebuff
))
471 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
472 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
473 my_syslog(MS_DHCP
| LOG_INFO
, _("%u user class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
476 mess
->op
= BOOTREPLY
;
478 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
479 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
481 /* set "known" tag for known hosts */
484 known_id
.net
= "known";
485 known_id
.next
= netid
;
489 if (mess_type
== 0 && !pxe
)
492 struct dhcp_netid id
, bootp_id
;
493 struct in_addr
*logaddr
= NULL
;
495 /* must have a MAC addr for bootp */
496 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
499 if (have_config(config
, CONFIG_DISABLE
))
500 message
= _("disabled");
502 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
504 if (have_config(config
, CONFIG_NAME
))
506 hostname
= config
->hostname
;
507 domain
= config
->domain
;
512 struct dhcp_netid_list
*list
;
514 for (list
= config
->netid
; list
; list
= list
->next
)
516 list
->list
->next
= netid
;
521 /* Match incoming filename field as a netid. */
524 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
525 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
526 id
.net
= (char *)daemon
->dhcp_buff2
;
531 /* Add "bootp" as a tag to allow different options, address ranges etc
533 bootp_id
.net
= "bootp";
534 bootp_id
.next
= netid
;
537 tagif_netid
= run_tag_if(netid
);
539 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
540 if (match_netid(id_list
->list
, tagif_netid
, 0))
541 message
= _("ignored");
547 if (have_config(config
, CONFIG_ADDR
))
550 logaddr
= &config
->addr
;
551 mess
->yiaddr
= config
->addr
;
552 if ((lease
= lease_find_by_addr(config
->addr
)) &&
553 (lease
->hwaddr_len
!= mess
->hlen
||
554 lease
->hwaddr_type
!= mess
->htype
||
555 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
556 message
= _("address in use");
560 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
561 !address_available(context
, lease
->addr
, tagif_netid
))
565 /* lease exists, wrong network. */
566 lease_prune(lease
, now
);
569 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, tagif_netid
, now
))
570 message
= _("no address available");
573 mess
->yiaddr
= lease
->addr
;
576 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
577 message
= _("wrong network");
578 else if (context
->netid
.net
)
580 context
->netid
.next
= netid
;
581 tagif_netid
= run_tag_if(&context
->netid
);
584 log_tags(tagif_netid
, ntohl(mess
->xid
));
586 if (!message
&& !nailed
)
588 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
589 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
592 message
= _("no address configured");
597 (!(lease
= lease4_allocate(mess
->yiaddr
))))
598 message
= _("no leases left");
602 logaddr
= &mess
->yiaddr
;
604 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0, now
, 1);
606 lease_set_hostname(lease
, hostname
, 1, get_domain(lease
->addr
), domain
);
607 /* infinite lease unless nailed in dhcp-host line. */
608 lease_set_expires(lease
,
609 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
611 lease_set_interface(lease
, int_index
, now
);
613 clear_packet(mess
, end
);
614 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
615 netid
, subnet_addr
, 0, 0, -1, NULL
, vendor_class_len
, now
, 0xffffffff, 0);
619 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, NULL
, message
, mess
->xid
);
621 return message
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
624 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 3)))
626 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
627 int len
= option_len(opt
);
628 char *pq
= daemon
->dhcp_buff
;
629 unsigned char *pp
, *op
= option_ptr(opt
, 0);
636 /* NB, the following always sets at least one bit */
637 if (option_bool(OPT_FQDN_UPDATE
))
639 if (fqdn_flags
& 0x01)
641 fqdn_flags
|= 0x02; /* set O */
642 fqdn_flags
&= ~0x01; /* clear S */
644 fqdn_flags
|= 0x08; /* set N */
648 if (!(fqdn_flags
& 0x01))
649 fqdn_flags
|= 0x03; /* set S and O */
650 fqdn_flags
&= ~0x08; /* clear N */
653 if (fqdn_flags
& 0x04)
654 while (*op
!= 0 && ((op
+ (*op
)) - pp
) < len
)
656 memcpy(pq
, op
+1, *op
);
664 if (len
> 0 && op
[len
-1] == 0)
669 if (pq
!= daemon
->dhcp_buff
)
674 if (legal_hostname(daemon
->dhcp_buff
))
675 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
677 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
679 int len
= option_len(opt
);
680 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
681 /* Microsoft clients are broken, and need zero-terminated strings
682 in options. We detect this state here, and do the same in
683 any options we send */
684 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
687 daemon
->dhcp_buff
[len
] = 0;
688 if (legal_hostname(daemon
->dhcp_buff
))
689 client_hostname
= daemon
->dhcp_buff
;
692 if (client_hostname
&& option_bool(OPT_LOG_OPTS
))
693 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
695 if (have_config(config
, CONFIG_NAME
))
697 hostname
= config
->hostname
;
698 domain
= config
->domain
;
700 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
701 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
702 offer_hostname
= hostname
;
704 else if (client_hostname
)
706 domain
= strip_hostname(client_hostname
);
708 if (strlen(client_hostname
) != 0)
710 hostname
= client_hostname
;
713 /* Search again now we have a hostname.
714 Only accept configs without CLID and HWADDR here, (they won't match)
715 to avoid impersonation by name. */
716 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
717 mess
->chaddr
, mess
->hlen
,
718 mess
->htype
, hostname
);
719 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
722 /* set "known" tag for known hosts */
723 known_id
.net
= "known";
724 known_id
.next
= netid
;
733 struct dhcp_netid_list
*list
;
735 for (list
= config
->netid
; list
; list
= list
->next
)
737 list
->list
->next
= netid
;
742 tagif_netid
= run_tag_if(netid
);
744 /* if all the netids in the ignore list are present, ignore this client */
745 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
746 if (match_netid(id_list
->list
, tagif_netid
, 0))
749 /* If configured, we can override the server-id to be the address of the relay,
750 so that all traffic goes via the relay and can pick up agent-id info. This can be
751 configured for all relays, or by address. */
752 if (daemon
->override
&& mess
->giaddr
.s_addr
!= 0 && override
.s_addr
== 0)
754 if (!daemon
->override_relays
)
755 override
= mess
->giaddr
;
759 for (l
= daemon
->override_relays
; l
; l
= l
->next
)
760 if (l
->addr
.s_addr
== mess
->giaddr
.s_addr
)
763 override
= mess
->giaddr
;
767 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
768 if (have_config(config
, CONFIG_NOCLID
))
771 /* Check if client is PXE client. */
772 if (daemon
->enable_pxe
&&
773 (opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
774 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
776 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
778 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
782 /* Check if this is really a PXE bootserver request, and handle specially if so. */
783 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
784 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
785 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
787 struct pxe_service
*service
;
788 int type
= option_uint(opt
, 0, 2);
789 int layer
= option_uint(opt
, 2, 2);
790 unsigned char save71
[4];
791 struct dhcp_opt opt71
;
798 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
802 memcpy(save71
, option_ptr(opt
, 0), 4);
804 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
805 if (service
->type
== type
)
808 if (!service
|| !service
->basename
)
811 clear_packet(mess
, end
);
813 mess
->yiaddr
= mess
->ciaddr
;
814 mess
->ciaddr
.s_addr
= 0;
816 mess
->siaddr
= a_record_from_hosts(service
->sname
, now
);
817 else if (service
->server
.s_addr
!= 0)
818 mess
->siaddr
= service
->server
;
820 mess
->siaddr
= context
->local
;
822 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
823 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
824 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
825 pxe_misc(mess
, end
, uuid
);
827 prune_vendor_opts(tagif_netid
);
829 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
831 opt71
.flags
= DHOPT_VENDOR_MATCH
;
833 opt71
.next
= daemon
->dhcp_opts
;
834 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
836 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, NULL
, mess
->xid
);
837 log_tags(tagif_netid
, ntohl(mess
->xid
));
838 return dhcp_packet_size(mess
, agent_id
, real_end
);
841 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
843 pxearch
= option_uint(opt
, 0, 2);
845 /* proxy DHCP here. */
846 if ((mess_type
== DHCPDISCOVER
|| (pxe
&& mess_type
== DHCPREQUEST
)))
848 struct dhcp_context
*tmp
;
850 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
851 if ((tmp
->flags
& CONTEXT_PROXY
) &&
852 match_netid(tmp
->filter
, tagif_netid
, 1))
857 struct dhcp_boot
*boot
;
861 tmp
->netid
.next
= netid
;
862 tagif_netid
= run_tag_if(&tmp
->netid
);
865 boot
= find_boot(tagif_netid
);
867 mess
->yiaddr
.s_addr
= 0;
868 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
870 mess
->ciaddr
.s_addr
= 0;
871 mess
->flags
|= htons(0x8000); /* broadcast */
874 clear_packet(mess
, end
);
876 /* Provide the bootfile here, for gPXE, and in case we have no menu items
877 and set discovery_control = 8 */
880 if (boot
->next_server
.s_addr
)
881 mess
->siaddr
= boot
->next_server
;
882 else if (boot
->tftp_sname
)
883 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
886 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
889 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
890 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
891 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
892 pxe_misc(mess
, end
, uuid
);
893 prune_vendor_opts(tagif_netid
);
894 do_encap_opts(pxe_opts(pxearch
, tagif_netid
, context
->local
, now
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
896 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, ignore
? "proxy-ignored" : "proxy", NULL
, mess
->xid
);
897 log_tags(tagif_netid
, ntohl(mess
->xid
));
898 return ignore
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
904 /* if we're just a proxy server, go no further */
905 if ((context
->flags
& CONTEXT_PROXY
) || pxe
)
908 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
910 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
911 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
912 req_options
[option_len(opt
)] = OPTION_END
;
918 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
919 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
922 /* sanitise any message. Paranoid? Moi? */
923 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
925 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
928 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, NULL
, daemon
->dhcp_buff
, mess
->xid
);
930 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
931 lease_prune(lease
, now
);
933 if (have_config(config
, CONFIG_ADDR
) &&
934 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
936 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
937 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
938 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
939 config
->flags
|= CONFIG_DECLINED
;
940 config
->decline_time
= now
;
943 /* make sure this host gets a different address next time. */
944 for (; context
; context
= context
->current
)
945 context
->addr_epoch
++;
950 if (!(context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
)) ||
951 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
952 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
955 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
956 lease_prune(lease
, now
);
958 message
= _("unknown lease");
960 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, NULL
, message
, mess
->xid
);
965 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
967 if (option_bool(OPT_QUIET_DHCP
))
969 message
= _("ignored");
974 struct in_addr addr
, conf
;
976 addr
.s_addr
= conf
.s_addr
= 0;
978 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
979 addr
= option_addr(opt
);
981 if (have_config(config
, CONFIG_ADDR
))
983 char *addrs
= inet_ntoa(config
->addr
);
985 if ((ltmp
= lease_find_by_addr(config
->addr
)) &&
987 !config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
990 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
991 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
992 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
993 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
997 struct dhcp_context
*tmp
;
998 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
999 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1002 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
1003 else if (have_config(config
, CONFIG_DECLINED
) &&
1004 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
1005 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
1007 conf
= config
->addr
;
1012 mess
->yiaddr
= conf
;
1014 address_available(context
, lease
->addr
, tagif_netid
) &&
1015 !config_find_by_address(daemon
->dhcp_conf
, lease
->addr
))
1016 mess
->yiaddr
= lease
->addr
;
1017 else if (opt
&& address_available(context
, addr
, tagif_netid
) && !lease_find_by_addr(addr
) &&
1018 !config_find_by_address(daemon
->dhcp_conf
, addr
))
1019 mess
->yiaddr
= addr
;
1020 else if (emac_len
== 0)
1021 message
= _("no unique-id");
1022 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, tagif_netid
, now
))
1023 message
= _("no address available");
1026 log_packet("DHCPDISCOVER", opt
? option_ptr(opt
, 0) : NULL
, emac
, emac_len
, iface_name
, NULL
, message
, mess
->xid
);
1028 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1031 if (context
->netid
.net
)
1033 context
->netid
.next
= netid
;
1034 tagif_netid
= run_tag_if(&context
->netid
);
1037 log_tags(tagif_netid
, ntohl(mess
->xid
));
1039 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, NULL
, mess
->xid
);
1041 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1042 clear_packet(mess
, end
);
1043 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
1044 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1045 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1046 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1047 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
1048 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
, time
, fuzz
);
1050 return dhcp_packet_size(mess
, agent_id
, real_end
);
1053 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1055 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
1057 /* SELECTING or INIT_REBOOT */
1058 mess
->yiaddr
= option_addr(opt
);
1060 /* send vendor and user class info for new or recreated lease */
1063 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
1068 if (override
.s_addr
!= 0)
1070 if (option_addr(opt
).s_addr
!= override
.s_addr
)
1075 for (; context
; context
= context
->current
)
1076 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
1081 /* Handle very strange configs where clients have more than one route to the server.
1082 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1083 Have to set override to make sure we echo back the correct server-id */
1086 enumerate_interfaces(0);
1088 for (intr
= daemon
->interfaces
; intr
; intr
= intr
->next
)
1089 if (intr
->addr
.sa
.sa_family
== AF_INET
&&
1090 intr
->addr
.in
.sin_addr
.s_addr
== option_addr(opt
).s_addr
&&
1095 override
= intr
->addr
.in
.sin_addr
;
1098 /* In auth mode, a REQUEST sent to the wrong server
1099 should be faulted, so that the client establishes
1100 communication with us, otherwise, silently ignore. */
1101 if (!option_bool(OPT_AUTHORITATIVE
))
1103 message
= _("wrong server-ID");
1108 /* If a lease exists for this host and another address, squash it. */
1109 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1111 lease_prune(lease
, now
);
1118 if (!lease
&& !option_bool(OPT_AUTHORITATIVE
))
1121 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1122 message
= _("wrong address");
1127 /* RENEWING or REBINDING */
1128 /* Check existing lease for this address.
1129 We allow it to be missing if dhcp-authoritative mode
1130 as long as we can allocate the lease now - checked below.
1131 This makes for a smooth recovery from a lost lease DB */
1132 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1133 (!lease
&& !option_bool(OPT_AUTHORITATIVE
)))
1135 /* A client rebinding will broadcast the request, so we may see it even
1136 if the lease is held by another server. Just ignore it in that case.
1137 If the request is unicast to us, then somethings wrong, NAK */
1140 message
= _("lease not found");
1141 /* ensure we broadcast NAK */
1145 /* desynchronise renewals */
1147 mess
->yiaddr
= mess
->ciaddr
;
1150 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, NULL
, mess
->xid
);
1154 struct dhcp_config
*addr_config
;
1155 struct dhcp_context
*tmp
= NULL
;
1157 if (have_config(config
, CONFIG_ADDR
))
1158 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1159 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1162 if (!(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1164 /* If a machine moves networks whilst it has a lease, we catch that here. */
1165 message
= _("wrong network");
1166 /* ensure we broadcast NAK */
1170 /* Check for renewal of a lease which is outside the allowed range. */
1171 else if (!address_available(context
, mess
->yiaddr
, tagif_netid
) &&
1172 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1173 message
= _("address not available");
1175 /* Check if a new static address has been configured. Be very sure that
1176 when the client does DISCOVER, it will get the static address, otherwise
1177 an endless protocol loop will ensue. */
1178 else if (!tmp
&& !selecting
&&
1179 have_config(config
, CONFIG_ADDR
) &&
1180 (!have_config(config
, CONFIG_DECLINED
) ||
1181 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1182 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1183 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1184 message
= _("static lease available");
1186 /* Check to see if the address is reserved as a static address for another host */
1187 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1188 message
= _("address reserved");
1190 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1192 /* If a host is configured with more than one MAC address, it's OK to 'nix
1193 a lease from one of it's MACs to give the address to another. */
1194 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1196 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1197 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1198 inet_ntoa(ltmp
->addr
));
1202 message
= _("address in use");
1208 message
= _("no unique-id");
1212 if ((lease
= lease4_allocate(mess
->yiaddr
)))
1215 message
= _("no leases left");
1222 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, message
, mess
->xid
);
1224 mess
->yiaddr
.s_addr
= 0;
1225 clear_packet(mess
, end
);
1226 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1227 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1228 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1229 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1230 a distant subnet which unicast a REQ to us won't work. */
1231 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1232 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1234 mess
->flags
|= htons(0x8000); /* broadcast */
1235 mess
->ciaddr
.s_addr
= 0;
1240 if (context
->netid
.net
)
1242 context
->netid
.next
= netid
;
1243 tagif_netid
= run_tag_if( &context
->netid
);
1246 log_tags(tagif_netid
, ntohl(mess
->xid
));
1250 /* pick up INIT-REBOOT events. */
1251 lease
->flags
|= LEASE_CHANGED
;
1254 if (daemon
->lease_change_command
)
1256 struct dhcp_netid
*n
;
1258 if (mess
->giaddr
.s_addr
)
1259 lease
->giaddr
= mess
->giaddr
;
1261 free(lease
->extradata
);
1262 lease
->extradata
= NULL
;
1263 lease
->extradata_size
= lease
->extradata_len
= 0;
1265 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_VENDOR_ID
, 1));
1266 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_HOSTNAME
, 1));
1267 add_extradata_opt(lease
, oui
);
1268 add_extradata_opt(lease
, serial
);
1269 add_extradata_opt(lease
, class);
1271 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
1273 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_CIRCUIT_ID
, 1));
1274 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBSCR_ID
, 1));
1275 add_extradata_opt(lease
, option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_REMOTE_ID
, 1));
1279 add_extradata_opt(lease
, NULL
);
1280 add_extradata_opt(lease
, NULL
);
1281 add_extradata_opt(lease
, NULL
);
1284 /* space-concat tag set */
1286 add_extradata_opt(lease
, NULL
);
1288 for (n
= tagif_netid
; n
; n
= n
->next
)
1290 struct dhcp_netid
*n1
;
1292 for (n1
= n
->next
; n1
; n1
= n1
->next
)
1293 if (strcmp(n
->net
, n1
->net
) == 0)
1296 lease_add_extradata(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
1299 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1301 int len
= option_len(opt
);
1302 unsigned char *ucp
= option_ptr(opt
, 0);
1303 /* If the user-class option started as counted strings, the first byte will be zero. */
1304 if (len
!= 0 && ucp
[0] == 0)
1306 lease_add_extradata(lease
, ucp
, len
, 0);
1312 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1314 domain
= get_domain(mess
->yiaddr
);
1315 hostname
= client_hostname
;
1319 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1320 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
, now
, do_classes
);
1322 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1325 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1326 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1332 /* Last ditch, if configured, generate hostname from mac address */
1333 if (!hostname
&& emac_len
!= 0)
1335 for (id_list
= daemon
->dhcp_gen_names
; id_list
; id_list
= id_list
->next
)
1336 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1342 hostname
= daemon
->dhcp_buff
;
1343 /* buffer is 256 bytes, 3 bytes per octet */
1344 for (i
= 0; (i
< emac_len
) && (i
< 80); i
++)
1345 hostname
+= sprintf(hostname
, "%.2x%s", emac
[i
], (i
== emac_len
- 1) ? "" : "-");
1346 hostname
= daemon
->dhcp_buff
;
1351 lease_set_hostname(lease
, hostname
, hostname_auth
, get_domain(lease
->addr
), domain
);
1353 lease_set_expires(lease
, time
, now
);
1354 lease_set_interface(lease
, int_index
, now
);
1356 if (override
.s_addr
!= 0)
1357 lease
->override
= override
;
1359 override
= lease
->override
;
1361 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, NULL
, mess
->xid
);
1363 clear_packet(mess
, end
);
1364 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1365 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1366 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1367 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1368 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
, time
, fuzz
);
1371 return dhcp_packet_size(mess
, agent_id
, real_end
);
1374 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1375 message
= _("ignored");
1377 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, NULL
, mess
->xid
);
1379 if (message
|| mess
->ciaddr
.s_addr
== 0)
1382 /* For DHCPINFORM only, cope without a valid context */
1383 context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
);
1385 /* Find a least based on IP address if we didn't
1386 get one from MAC address/client-d */
1388 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1390 hostname
= lease
->hostname
;
1393 hostname
= host_from_dns(mess
->ciaddr
);
1395 if (context
&& context
->netid
.net
)
1397 context
->netid
.next
= netid
;
1398 tagif_netid
= run_tag_if(&context
->netid
);
1401 log_tags(tagif_netid
, ntohl(mess
->xid
));
1403 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, NULL
, mess
->xid
);
1407 lease_set_interface(lease
, int_index
, now
);
1408 if (override
.s_addr
!= 0)
1409 lease
->override
= override
;
1411 override
= lease
->override
;
1414 clear_packet(mess
, end
);
1415 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1416 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1418 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1419 we supply a utility which makes DHCPINFORM requests to get this information.
1420 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1421 which won't be true for ordinary clients, but will be true for the
1422 dhcp_lease_time utility. */
1423 if (lease
&& in_list(req_options
, OPTION_LEASE_TIME
))
1425 if (lease
->expires
== 0)
1428 time
= (unsigned int)difftime(lease
->expires
, now
);
1429 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1432 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1433 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
, 0xffffffff, 0);
1435 *is_inform
= 1; /* handle reply differently */
1436 return dhcp_packet_size(mess
, agent_id
, real_end
);
1442 /* find a good value to use as MAC address for logging and address-allocation hashing.
1443 This is normally just the chaddr field from the DHCP packet,
1444 but eg Firewire will have hlen == 0 and use the client-id instead.
1445 This could be anything, but will normally be EUI64 for Firewire.
1446 We assume that if the first byte of the client-id equals the htype byte
1447 then the client-id is using the usual encoding and use the rest of the
1448 client-id: if not we can use the whole client-id. This should give
1449 sane MAC address logs. */
1450 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1451 int clid_len
, unsigned char *clid
, int *len_out
)
1453 if (hwlen
== 0 && clid
&& clid_len
> 3)
1455 if (clid
[0] == hwtype
)
1457 *len_out
= clid_len
- 1 ;
1461 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1462 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1464 *len_out
= clid_len
- 1 ;
1469 *len_out
= clid_len
;
1477 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1479 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1483 unsigned int req_time
= option_uint(opt
, 0, 4);
1484 if (req_time
< 120 )
1485 req_time
= 120; /* sanity */
1486 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1493 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1495 if (override
.s_addr
!= 0)
1497 else if (context
&& context
->local
.s_addr
!= 0)
1498 return context
->local
;
1503 static int sanitise(unsigned char *opt
, char *buf
)
1513 p
= option_ptr(opt
, 0);
1515 for (i
= option_len(opt
); i
> 0; i
--)
1518 if (isprint((int)c
))
1521 *buf
= 0; /* add terminator */
1527 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
)
1530 lease_add_extradata(lease
, NULL
, 0, 0);
1532 lease_add_extradata(lease
, option_ptr(opt
, 0), option_len(opt
), 0);
1536 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1537 int mac_len
, char *interface
, char *string
, char *err
, u32 xid
)
1541 if (!err
&& !option_bool(OPT_LOG_OPTS
) && option_bool(OPT_QUIET_DHCP
))
1544 /* addr may be misaligned */
1546 memcpy(&a
, addr
, sizeof(a
));
1548 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1550 if(option_bool(OPT_LOG_OPTS
))
1551 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s%s",
1555 addr
? inet_ntoa(a
) : "",
1558 string
? string
: "",
1561 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s%s",
1564 addr
? inet_ntoa(a
) : "",
1567 string
? string
: "",
1571 static void log_options(unsigned char *start
, u32 xid
)
1573 while (*start
!= OPTION_END
)
1575 char *optname
= option_string(AF_INET
, start
[0], option_ptr(start
, 0), option_len(start
), daemon
->namebuff
, MAXDNAME
);
1577 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d %s %s",
1578 ntohl(xid
), option_len(start
), start
[0], optname
, daemon
->namebuff
);
1579 start
+= start
[1] + 2;
1583 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1589 else if (*p
== OPTION_END
)
1590 return opt
== OPTION_END
? p
: NULL
;
1591 else if (*p
== OPTION_PAD
)
1597 return NULL
; /* malformed packet */
1598 opt_len
= option_len(p
);
1599 if (p
> end
- (2 + opt_len
))
1600 return NULL
; /* malformed packet */
1601 if (*p
== opt
&& opt_len
>= minsize
)
1608 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1610 unsigned char *ret
, *overload
;
1612 /* skip over DHCP cookie; */
1613 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1616 /* look for overload option. */
1617 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1620 /* Can we look in filename area ? */
1621 if ((overload
[2] & 1) &&
1622 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1625 /* finally try sname area */
1626 if ((overload
[2] & 2) &&
1627 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1633 static struct in_addr
option_addr(unsigned char *opt
)
1635 /* this worries about unaligned data in the option. */
1636 /* struct in_addr is network byte order */
1639 memcpy(&ret
, option_ptr(opt
, 0), INADDRSZ
);
1644 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1646 /* this worries about unaligned data and byte order */
1647 unsigned int ret
= 0;
1649 unsigned char *p
= option_ptr(opt
, offset
);
1651 for (i
= 0; i
< size
; i
++)
1652 ret
= (ret
<< 8) | *p
++;
1657 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1660 start
+= start
[1] + 2;
1664 /* only for use when building packet: doesn't check for bad data. */
1665 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1667 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1671 if (*p
== OPTION_OVERLOAD
)
1678 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
)
1680 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1681 unsigned char *overload
;
1684 /* move agent_id back down to the end of the packet */
1687 memmove(p
, agent_id
, real_end
- agent_id
);
1688 p
+= real_end
- agent_id
;
1689 memset(p
, 0, real_end
- p
); /* in case of overlap */
1692 /* add END options to the regions. */
1693 overload
= find_overload(mess
);
1695 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1697 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1698 if (option_bool(OPT_LOG_OPTS
))
1699 log_options(mess
->file
, mess
->xid
);
1701 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1702 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1704 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1706 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1707 if (option_bool(OPT_LOG_OPTS
))
1708 log_options(mess
->sname
, mess
->xid
);
1710 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1711 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1716 if (option_bool(OPT_LOG_OPTS
))
1718 if (mess
->siaddr
.s_addr
!= 0)
1719 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1721 if ((mess
->flags
& htons(0x8000)) && mess
->ciaddr
.s_addr
== 0)
1722 my_syslog(MS_DHCP
| LOG_INFO
, _("%u broadcast response"), ntohl(mess
->xid
));
1724 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1727 ret
= (size_t)(p
- (unsigned char *)mess
);
1729 if (ret
< MIN_PACKETSZ
)
1735 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1737 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1739 if (p
+ len
+ 3 >= end
)
1740 /* not enough space in options area, try and use overload, if poss */
1742 unsigned char *overload
;
1744 if (!(overload
= find_overload(mess
)) &&
1745 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1747 /* attempt to overload fname and sname areas, we've reserved space for the
1748 overflow option previuously. */
1750 *(p
++) = OPTION_OVERLOAD
;
1756 /* using filename field ? */
1759 if (mess
->file
[0] == 0)
1762 if (overload
[2] & 1)
1764 p
= dhcp_skip_opts(mess
->file
);
1765 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1771 /* try to bring sname into play (it may be already) */
1772 if (mess
->sname
[0] == 0)
1775 if (overload
[2] & 2)
1777 p
= dhcp_skip_opts(mess
->sname
);
1778 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->sname
))
1785 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1797 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1800 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1803 for (i
= 0; i
< len
; i
++)
1804 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1807 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1808 char *string
, int null_term
)
1811 size_t len
= strlen(string
);
1813 if (null_term
&& len
!= 255)
1816 if ((p
= free_space(mess
, end
, opt
, len
)))
1817 memcpy(p
, string
, len
);
1820 /* return length, note this only does the data part */
1821 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1825 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1830 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1833 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1834 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1836 /* zero means "self" (but not in vendorclass options.) */
1838 memcpy(p
, &context
->local
, INADDRSZ
);
1840 memcpy(p
, a
, INADDRSZ
);
1845 /* empty string may be extended to "\0" by null_term */
1846 memcpy(p
, opt
->val
? opt
->val
: (unsigned char *)"", len
);
1851 static int in_list(unsigned char *list
, int opt
)
1855 /* If no requested options, send everything, not nothing. */
1859 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1866 static struct dhcp_opt
*option_find2(int opt
)
1868 struct dhcp_opt
*opts
;
1870 for (opts
= daemon
->dhcp_opts
; opts
; opts
= opts
->next
)
1871 if (opts
->opt
== opt
&& (opts
->flags
& DHOPT_TAGOK
))
1877 /* mark vendor-encapsulated options which match the client-supplied or
1878 config-supplied vendor class */
1879 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1881 for (; dopt
; dopt
= dopt
->next
)
1883 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1884 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1887 if (dopt
->u
.vendor_class
)
1888 len
= strlen((char *)dopt
->u
.vendor_class
);
1889 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1890 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1892 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1899 static int do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1900 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1902 int len
, enc_len
, ret
= 0;
1903 struct dhcp_opt
*start
;
1906 /* find size in advance */
1907 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1908 if (opt
->flags
& flag
)
1910 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1912 if (enc_len
+ new <= 255)
1916 p
= free_space(mess
, end
, encap
, enc_len
);
1917 for (; start
&& start
!= opt
; start
= start
->next
)
1918 if (p
&& (start
->flags
& flag
))
1920 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1921 *(p
++) = start
->opt
;
1931 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
1933 for (; start
; start
= start
->next
)
1934 if (start
->flags
& flag
)
1936 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1937 *(p
++) = start
->opt
;
1947 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
1951 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
1952 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
1953 memcpy(p
, uuid
, 17);
1956 static int prune_vendor_opts(struct dhcp_netid
*netid
)
1959 struct dhcp_opt
*opt
;
1961 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1962 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
1963 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1965 if (!match_netid(opt
->netid
, netid
, 1))
1966 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1967 else if (opt
->flags
& DHOPT_FORCE
)
1973 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
)
1977 unsigned char *p
, *q
;
1978 struct pxe_service
*service
;
1979 static struct dhcp_opt
*o
, *ret
;
1980 int i
, j
= NUM_OPTS
- 1;
1981 struct in_addr boot_server
;
1983 /* We pass back references to these, hence they are declared static */
1984 static unsigned char discovery_control
;
1985 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
1986 static struct dhcp_opt
*fake_opts
= NULL
;
1988 /* Disable multicast, since we don't support it, and broadcast
1989 unless we need it */
1990 discovery_control
= 3;
1992 ret
= daemon
->dhcp_opts
;
1994 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
1997 for (i
= 0; i
< NUM_OPTS
; i
++)
1999 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
2000 fake_opts
[i
].netid
= NULL
;
2001 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
2004 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2005 p
= (unsigned char *)daemon
->dhcp_buff
;
2006 q
= (unsigned char *)daemon
->dhcp_buff3
;
2008 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
2009 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
2011 size_t len
= strlen(service
->menu
);
2012 /* opt 43 max size is 255. encapsulated option has type and length
2013 bytes, so its max size is 253. */
2014 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
2016 *(p
++) = service
->type
>> 8;
2017 *(p
++) = service
->type
;
2019 memcpy(p
, service
->menu
, len
);
2026 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
2027 return daemon
->dhcp_opts
;
2030 boot_server
= service
->basename
? local
:
2031 (service
->sname
? a_record_from_hosts(service
->sname
, now
) : service
->server
);
2033 if (boot_server
.s_addr
!= 0)
2035 if (q
- (unsigned char *)daemon
->dhcp_buff3
+ 3 + INADDRSZ
>= 253)
2038 /* Boot service with known address - give it */
2039 *(q
++) = service
->type
>> 8;
2040 *(q
++) = service
->type
;
2042 /* dest misaligned */
2043 memcpy(q
, &boot_server
.s_addr
, INADDRSZ
);
2046 else if (service
->type
!= 0)
2047 /* We don't know the server for a service type, so we'll
2048 allow the client to broadcast for it */
2049 discovery_control
= 2;
2052 /* if no prompt, wait forever if there's a choice */
2053 fake_prompt
[0] = (i
> 1) ? 255 : 0;
2056 discovery_control
= 8; /* no menu - just use use mess->filename */
2059 ret
= &fake_opts
[j
--];
2060 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
2061 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
2062 ret
->opt
= SUBOPT_PXE_MENU
;
2064 if (q
- (unsigned char *)daemon
->dhcp_buff3
!= 0)
2066 ret
= &fake_opts
[j
--];
2067 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff3
;
2068 ret
->val
= (unsigned char *)daemon
->dhcp_buff3
;
2069 ret
->opt
= SUBOPT_PXE_SERVERS
;
2073 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
2074 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
2079 ret
= &fake_opts
[j
--];
2080 ret
->len
= sizeof(fake_prompt
);
2081 ret
->val
= fake_prompt
;
2082 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
2085 ret
= &fake_opts
[j
--];
2087 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
2088 ret
->val
= &discovery_control
;
2093 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
2095 memset(mess
->sname
, 0, sizeof(mess
->sname
));
2096 memset(mess
->file
, 0, sizeof(mess
->file
));
2097 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
2098 mess
->siaddr
.s_addr
= 0;
2101 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
2103 struct dhcp_boot
*boot
;
2105 /* decide which dhcp-boot option we're using */
2106 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2107 if (match_netid(boot
->netid
, netid
, 0))
2110 /* No match, look for one without a netid */
2111 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2112 if (match_netid(boot
->netid
, netid
, 1))
2118 static void do_options(struct dhcp_context
*context
,
2119 struct dhcp_packet
*mess
,
2121 unsigned char *req_options
,
2124 struct dhcp_netid
*netid
,
2125 struct in_addr subnet_addr
,
2126 unsigned char fqdn_flags
,
2127 int null_term
, int pxe_arch
,
2128 unsigned char *uuid
,
2129 int vendor_class_len
,
2131 unsigned int lease_time
,
2132 unsigned short fuzz
)
2134 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2135 struct dhcp_boot
*boot
;
2137 int i
, len
, force_encap
= 0;
2138 unsigned char f0
= 0, s0
= 0;
2139 int done_file
= 0, done_server
= 0;
2140 int done_vendor_class
= 0;
2141 struct dhcp_netid
*tagif
;
2142 struct dhcp_netid_list
*id_list
;
2144 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2146 context
->netid
.next
= NULL
;
2147 tagif
= option_filter(netid
, context
&& context
->netid
.net
? &context
->netid
: NULL
, config_opts
);
2150 if (option_bool(OPT_LOG_OPTS
) && req_options
)
2152 char *q
= daemon
->namebuff
;
2153 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2155 char *s
= option_string(AF_INET
, req_options
[i
], NULL
, 0, NULL
, 0);
2156 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2159 strlen(s
) != 0 ? ":" : "",
2161 req_options
[i
+1] == OPTION_END
? "" : ", ");
2162 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2164 q
= daemon
->namebuff
;
2165 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2170 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
2171 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
2174 mess
->flags
|= htons(0x8000); /* force broadcast */
2177 mess
->siaddr
= context
->local
;
2179 /* See if we can send the boot stuff as options.
2180 To do this we need a requested option list, BOOTP
2181 and very old DHCP clients won't have this, we also
2182 provide an manual option to disable it.
2183 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2184 names, so we always send those. */
2185 if ((boot
= find_boot(tagif
)))
2189 if (!option_bool(OPT_NO_OVERRIDE
) &&
2191 in_list(req_options
, OPTION_SNAME
))
2192 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2194 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2199 if (!option_bool(OPT_NO_OVERRIDE
) &&
2201 in_list(req_options
, OPTION_FILENAME
))
2202 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2204 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2207 if (boot
->next_server
.s_addr
)
2208 mess
->siaddr
= boot
->next_server
;
2209 else if (boot
->tftp_sname
)
2210 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
2213 /* Use the values of the relevant options if no dhcp-boot given and
2214 they're not explicitly asked for as options. OPTION_END is used
2215 as an internal way to specify siaddr without using dhcp-boot, for use in
2218 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
2219 (opt
= option_find2(OPTION_FILENAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2221 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2225 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2226 (opt
= option_find2(OPTION_SNAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2228 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2232 if ((opt
= option_find2(OPTION_END
)))
2233 mess
->siaddr
.s_addr
= ((struct in_addr
*)opt
->val
)->s_addr
;
2236 /* We don't want to do option-overload for BOOTP, so make the file and sname
2237 fields look like they are in use, even when they aren't. This gets restored
2238 at the end of this function. */
2240 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2244 s0
= mess
->sname
[0];
2248 /* At this point, if mess->sname or mess->file are zeroed, they are available
2249 for option overload, reserve space for the overload option. */
2250 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2253 /* rfc3011 says this doesn't need to be in the requested options list. */
2254 if (subnet_addr
.s_addr
)
2255 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2257 if (lease_time
!= 0xffffffff)
2259 unsigned int t1val
= lease_time
/2;
2260 unsigned int t2val
= (lease_time
*7)/8;
2263 /* If set by user, sanity check, so not longer than lease. */
2264 if ((opt
= option_find2(OPTION_T1
)))
2266 hval
= ntohl(*((unsigned int *)opt
->val
));
2267 if (hval
< lease_time
&& hval
> 2)
2271 if ((opt
= option_find2(OPTION_T2
)))
2273 hval
= ntohl(*((unsigned int *)opt
->val
));
2274 if (hval
< lease_time
&& hval
> 2)
2278 /* ensure T1 is still < T2 */
2282 while (fuzz
> (t1val
/8))
2288 option_put(mess
, end
, OPTION_T1
, 4, t1val
);
2289 option_put(mess
, end
, OPTION_T2
, 4, t2val
);
2292 /* replies to DHCPINFORM may not have a valid context */
2295 if (!option_find2(OPTION_NETMASK
))
2296 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2298 /* May not have a "guessed" broadcast address if we got no packets via a relay
2299 from this net yet (ie just unicast renewals after a restart */
2300 if (context
->broadcast
.s_addr
&&
2301 !option_find2(OPTION_BROADCAST
))
2302 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2304 /* Same comments as broadcast apply, and also may not be able to get a sensible
2305 default when using subnet select. User must configure by steam in that case. */
2306 if (context
->router
.s_addr
&&
2307 in_list(req_options
, OPTION_ROUTER
) &&
2308 !option_find2(OPTION_ROUTER
))
2309 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2311 if (daemon
->port
== NAMESERVER_PORT
&&
2312 in_list(req_options
, OPTION_DNSSERVER
) &&
2313 !option_find2(OPTION_DNSSERVER
))
2314 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2317 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2318 !option_find2(OPTION_DOMAINNAME
))
2319 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2321 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2324 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2325 !option_find2(OPTION_HOSTNAME
))
2326 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2328 if (fqdn_flags
!= 0)
2330 len
= strlen(hostname
) + 3;
2332 if (fqdn_flags
& 0x04)
2338 len
+= strlen(domain
) + 1;
2339 else if (fqdn_flags
& 0x04)
2342 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2344 *(p
++) = fqdn_flags
& 0x0f; /* MBZ bits to zero */
2348 if (fqdn_flags
& 0x04)
2350 p
= do_rfc1035_name(p
, hostname
);
2353 p
= do_rfc1035_name(p
, domain
);
2359 memcpy(p
, hostname
, strlen(hostname
));
2360 p
+= strlen(hostname
);
2364 memcpy(p
, domain
, strlen(domain
));
2365 p
+= strlen(domain
);
2374 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2376 int optno
= opt
->opt
;
2378 /* netids match and not encapsulated? */
2379 if (!(opt
->flags
& DHOPT_TAGOK
))
2382 /* was it asked for, or are we sending it anyway? */
2383 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2386 /* prohibit some used-internally options. T1 and T2 already handled. */
2387 if (optno
== OPTION_CLIENT_FQDN
||
2388 optno
== OPTION_MAXMESSAGE
||
2389 optno
== OPTION_OVERLOAD
||
2390 optno
== OPTION_PAD
||
2391 optno
== OPTION_END
||
2392 optno
== OPTION_T1
||
2396 if (optno
== OPTION_SNAME
&& done_server
)
2399 if (optno
== OPTION_FILENAME
&& done_file
)
2402 /* For the options we have default values on
2403 dhc-option=<optionno> means "don't include this option"
2404 not "include a zero-length option" */
2405 if (opt
->len
== 0 &&
2406 (optno
== OPTION_NETMASK
||
2407 optno
== OPTION_BROADCAST
||
2408 optno
== OPTION_ROUTER
||
2409 optno
== OPTION_DNSSERVER
||
2410 optno
== OPTION_DOMAINNAME
||
2411 optno
== OPTION_HOSTNAME
))
2414 /* vendor-class comes from elsewhere for PXE */
2415 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2418 /* always force null-term for filename and servername - buggy PXE again. */
2419 len
= do_opt(opt
, NULL
, context
,
2420 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2422 if ((p
= free_space(mess
, end
, optno
, len
)))
2424 do_opt(opt
, p
, context
,
2425 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2427 /* If we send a vendor-id, revisit which vendor-ops we consider
2428 it appropriate to send. */
2429 if (optno
== OPTION_VENDOR_ID
)
2431 match_vendor_opts(p
- 2, config_opts
);
2432 done_vendor_class
= 1;
2437 /* Now send options to be encapsulated in arbitrary options,
2438 eg dhcp-option=encap:172,17,.......
2439 Also handle vendor-identifying vendor-encapsulated options,
2440 dhcp-option = vi-encap:13,17,.......
2441 The may be more that one "outer" to do, so group
2442 all the options which match each outer in turn. */
2443 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2444 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2446 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2450 if ((flags
= (opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_RFC3925
))))
2455 if (opt
->flags
& DHOPT_ENCAP_DONE
)
2458 for (len
= 0, o
= config_opts
; o
; o
= o
->next
)
2460 int outer
= flags
& DHOPT_ENCAPSULATE
? o
->u
.encap
: OPTION_VENDOR_IDENT_OPT
;
2462 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2464 if (!(o
->flags
& flags
) || opt
->u
.encap
!= o
->u
.encap
)
2467 o
->flags
|= DHOPT_ENCAP_DONE
;
2468 if (match_netid(o
->netid
, tagif
, 1) &&
2469 ((o
->flags
& DHOPT_FORCE
) || in_list(req_options
, outer
)))
2471 o
->flags
|= DHOPT_ENCAP_MATCH
;
2473 len
+= do_opt(o
, NULL
, NULL
, 0) + 2;
2479 if (flags
& DHOPT_ENCAPSULATE
)
2480 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2482 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt
->u
.encap
);
2483 else if ((p
= free_space(mess
, end
, OPTION_VENDOR_IDENT_OPT
, len
+ 5)))
2485 int swap_ent
= htonl(opt
->u
.encap
);
2486 memcpy(p
, &swap_ent
, 4);
2489 for (o
= config_opts
; o
; o
= o
->next
)
2490 if (o
->flags
& DHOPT_ENCAP_MATCH
)
2492 len
= do_opt(o
, p
+ 2, NULL
, 0);
2502 force_encap
= prune_vendor_opts(tagif
);
2504 if (context
&& pxe_arch
!= -1)
2506 pxe_misc(mess
, end
, uuid
);
2507 config_opts
= pxe_opts(pxe_arch
, tagif
, context
->local
, now
);
2510 if ((force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
)) &&
2511 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
) &&
2512 pxe_arch
== -1 && !done_vendor_class
&& vendor_class_len
!= 0 &&
2513 (p
= free_space(mess
, end
, OPTION_VENDOR_ID
, vendor_class_len
)))
2514 /* If we send vendor encapsulated options, and haven't already sent option 60,
2515 echo back the value we got from the client. */
2516 memcpy(p
, daemon
->dhcp_buff3
, vendor_class_len
);
2518 /* restore BOOTP anti-overload hack */
2519 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2522 mess
->sname
[0] = s0
;