]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc2131.c
1 /* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
22 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
25 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
);
28 static int sanitise(unsigned char *opt
, char *buf
);
29 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
);
30 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
);
31 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
32 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
33 int opt
, char *string
, int null_term
);
34 static struct in_addr
option_addr(unsigned char *opt
);
35 static unsigned int option_uint(unsigned char *opt
, int i
, int size
);
36 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
37 int mac_len
, char *interface
, char *string
, u32 xid
);
38 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
39 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
40 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
);
41 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
42 static void do_options(struct dhcp_context
*context
,
43 struct dhcp_packet
*mess
,
44 unsigned char *real_end
,
45 unsigned char *req_options
,
48 struct dhcp_netid
*netid
,
49 struct in_addr subnet_addr
,
50 unsigned char fqdn_flags
,
51 int null_term
, int pxearch
,
57 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
58 static int do_encap_opts(struct dhcp_opt
*opts
, int encap
, int flag
, struct dhcp_packet
*mess
, unsigned char *end
, int null_term
);
59 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
);
60 static int prune_vendor_opts(struct dhcp_netid
*netid
);
61 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
);
62 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
);
65 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
66 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
, int pxe
, struct in_addr fallback
)
68 unsigned char *opt
, *clid
= NULL
;
69 struct dhcp_lease
*ltmp
, *lease
= NULL
;
70 struct dhcp_vendor
*vendor
;
72 struct dhcp_netid_list
*id_list
;
73 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0, pxearch
= -1;
74 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
75 unsigned char *end
= (unsigned char *)(mess
+ 1);
76 unsigned char *real_end
= (unsigned char *)(mess
+ 1);
77 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
, *domain
= NULL
;
78 int hostname_auth
= 0, borken_opt
= 0;
79 unsigned char *req_options
= NULL
;
82 struct dhcp_config
*config
;
83 struct dhcp_netid
*netid
, *tagif_netid
;
84 struct in_addr subnet_addr
, override
;
85 unsigned short fuzz
= 0;
86 unsigned int mess_type
= 0;
87 unsigned char fqdn_flags
= 0;
88 unsigned char *agent_id
= NULL
, *uuid
= NULL
;
89 unsigned char *emac
= NULL
;
90 int vendor_class_len
= 0, emac_len
= 0;
91 struct dhcp_netid known_id
, iface_id
, cpewan_id
;
93 unsigned char pxe_uuid
[17];
94 unsigned char *oui
= NULL
, *serial
= NULL
, *class = NULL
;
96 subnet_addr
.s_addr
= override
.s_addr
= 0;
98 /* set tag with name == interface */
99 iface_id
.net
= iface_name
;
100 iface_id
.next
= NULL
;
103 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
106 if (mess
->htype
== 0 && mess
->hlen
!= 0)
109 /* check for DHCP rather than BOOTP */
110 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
112 u32 cookie
= htonl(DHCP_COOKIE
);
114 /* only insist on a cookie for DHCP. */
115 if (memcmp(mess
->options
, &cookie
, sizeof(u32
)) != 0)
118 mess_type
= option_uint(opt
, 0, 1);
120 /* two things to note here: expand_buf may move the packet,
121 so reassign mess from daemon->packet. Also, the size
122 sent includes the IP and UDP headers, hence the magic "-28" */
123 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
125 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
127 if (size
> DHCP_PACKET_MAX
)
128 size
= DHCP_PACKET_MAX
;
129 else if (size
< sizeof(struct dhcp_packet
))
130 size
= sizeof(struct dhcp_packet
);
132 if (expand_buf(&daemon
->dhcp_packet
, size
))
134 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
135 real_end
= end
= ((unsigned char *)mess
) + size
;
139 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
140 it can affect the context-determination code. */
141 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
142 mess
->ciaddr
.s_addr
= 0;
144 /* search for device identity from CPEWAN devices, we pass this through to the script */
145 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT_OPT
, 5)))
147 unsigned int elen
, offset
, len
= option_len(opt
);
149 for (offset
= 0; offset
< (len
- 5); offset
+= elen
+ 5)
151 elen
= option_uint(opt
, offset
+ 4 , 1);
152 if (option_uint(opt
, offset
, 4) == BRDBAND_FORUM_IANA
)
154 unsigned char *x
= option_ptr(opt
, offset
+ 5);
155 unsigned char *y
= option_ptr(opt
, offset
+ elen
+ 5);
156 oui
= option_find1(x
, y
, 1, 1);
157 serial
= option_find1(x
, y
, 2, 1);
158 class = option_find1(x
, y
, 3, 1);
160 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
161 the gateway id back. Note that the device class is optional */
164 cpewan_id
.net
= "cpewan-id";
165 cpewan_id
.next
= netid
;
173 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
175 /* Any agent-id needs to be copied back out, verbatim, as the last option
176 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
177 get overwritten, then it will be shuffled back at the end of processing.
178 Note that the incoming options must not be overwritten here, so there has to
179 be enough free space at the end of the packet to copy the option. */
181 unsigned int total
= option_len(opt
) + 2;
182 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
183 if (last_opt
&& last_opt
< end
- total
)
187 memcpy(agent_id
, opt
, total
);
190 /* look for RFC3527 Link selection sub-option */
191 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
192 subnet_addr
= option_addr(sopt
);
194 /* look for RFC5107 server-identifier-override */
195 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
196 override
= option_addr(sopt
);
198 /* if a circuit-id or remote-is option is provided, exact-match to options. */
199 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
203 if (vendor
->match_type
== MATCH_CIRCUIT
)
204 search
= SUBOPT_CIRCUIT_ID
;
205 else if (vendor
->match_type
== MATCH_REMOTE
)
206 search
= SUBOPT_REMOTE_ID
;
207 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
208 search
= SUBOPT_SUBSCR_ID
;
212 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
213 vendor
->len
== option_len(sopt
) &&
214 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
216 vendor
->netid
.next
= netid
;
217 netid
= &vendor
->netid
;
222 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
223 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
224 subnet_addr
= option_addr(opt
);
226 /* If there is no client identifier option, use the hardware address */
227 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
229 clid_len
= option_len(opt
);
230 clid
= option_ptr(opt
, 0);
233 /* do we have a lease in store? */
234 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
236 /* If this request is missing a clid, but we've seen one before,
237 use it again for option matching etc. */
238 if (lease
&& !clid
&& lease
->clid
)
240 clid_len
= lease
->clid_len
;
244 /* find mac to use for logging and hashing */
245 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
248 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
249 if (mac
->hwaddr_len
== mess
->hlen
&&
250 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
251 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
253 mac
->netid
.next
= netid
;
257 /* Determine network for this packet. Our caller will have already linked all the
258 contexts which match the addresses of the receiving interface but if the
259 machine has an address already, or came via a relay, or we have a subnet selector,
260 we search again. If we don't have have a giaddr or explicit subnet selector,
261 use the ciaddr. This is necessary because a machine which got a lease via a
262 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
263 from the physical network, continue using that to allow correct DHCPNAK generation later. */
264 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
266 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
270 if (subnet_addr
.s_addr
)
275 else if (mess
->giaddr
.s_addr
)
282 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
284 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
285 if (context_tmp
->netmask
.s_addr
&&
286 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
287 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
289 context_new
= context
;
295 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
297 struct in_addr netmask
= context_tmp
->netmask
;
299 /* guess the netmask for relayed networks */
300 if (!(context_tmp
->flags
& CONTEXT_NETMASK
) && context_tmp
->netmask
.s_addr
== 0)
302 if (IN_CLASSA(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSA(ntohl(context_tmp
->end
.s_addr
)))
303 netmask
.s_addr
= htonl(0xff000000);
304 else if (IN_CLASSB(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSB(ntohl(context_tmp
->end
.s_addr
)))
305 netmask
.s_addr
= htonl(0xffff0000);
306 else if (IN_CLASSC(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSC(ntohl(context_tmp
->end
.s_addr
)))
307 netmask
.s_addr
= htonl(0xffffff00);
310 /* This section fills in context mainly when a client which is on a remote (relayed)
311 network renews a lease without using the relay, after dnsmasq has restarted. */
312 if (netmask
.s_addr
!= 0 &&
313 is_same_net(addr
, context_tmp
->start
, netmask
) &&
314 is_same_net(addr
, context_tmp
->end
, netmask
))
316 context_tmp
->netmask
= netmask
;
317 if (context_tmp
->local
.s_addr
== 0)
318 context_tmp
->local
= fallback
;
319 if (context_tmp
->router
.s_addr
== 0)
320 context_tmp
->router
= mess
->giaddr
;
322 /* fill in missing broadcast addresses for relayed ranges */
323 if (!(context_tmp
->flags
& CONTEXT_BRDCAST
) && context_tmp
->broadcast
.s_addr
== 0 )
324 context_tmp
->broadcast
.s_addr
= context_tmp
->start
.s_addr
| ~context_tmp
->netmask
.s_addr
;
326 context_tmp
->current
= context_new
;
327 context_new
= context_tmp
;
331 if (context_new
|| force
)
332 context
= context_new
;
337 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
338 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
339 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
343 if (option_bool(OPT_LOG_OPTS
))
345 struct dhcp_context
*context_tmp
;
346 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
348 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
349 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
350 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP subnet: %s/%s"),
351 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
353 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
354 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
358 mess
->op
= BOOTREPLY
;
360 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
361 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
363 /* set "known" tag for known hosts */
366 known_id
.net
= "known";
367 known_id
.next
= netid
;
371 if (mess_type
== 0 && !pxe
)
374 struct dhcp_netid id
, bootp_id
;
375 struct in_addr
*logaddr
= NULL
;
377 /* must have a MAC addr for bootp */
378 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
381 if (have_config(config
, CONFIG_DISABLE
))
382 message
= _("disabled");
384 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
386 if (have_config(config
, CONFIG_NAME
))
388 hostname
= config
->hostname
;
389 domain
= config
->domain
;
394 struct dhcp_netid_list
*list
;
396 for (list
= config
->netid
; list
; list
= list
->next
)
398 list
->list
->next
= netid
;
403 /* Match incoming filename field as a netid. */
406 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
407 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
408 id
.net
= (char *)daemon
->dhcp_buff2
;
413 /* Add "bootp" as a tag to allow different options, address ranges etc
415 bootp_id
.net
= "bootp";
416 bootp_id
.next
= netid
;
419 tagif_netid
= run_tag_if(netid
);
421 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
422 if (match_netid(id_list
->list
, tagif_netid
, 0))
423 message
= _("ignored");
429 if (have_config(config
, CONFIG_ADDR
))
432 logaddr
= &config
->addr
;
433 mess
->yiaddr
= config
->addr
;
434 if ((lease
= lease_find_by_addr(config
->addr
)) &&
435 (lease
->hwaddr_len
!= mess
->hlen
||
436 lease
->hwaddr_type
!= mess
->htype
||
437 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
438 message
= _("address in use");
442 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
443 !address_available(context
, lease
->addr
, tagif_netid
))
447 /* lease exists, wrong network. */
448 lease_prune(lease
, now
);
451 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, tagif_netid
, now
))
452 message
= _("no address available");
455 mess
->yiaddr
= lease
->addr
;
458 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
459 message
= _("wrong network");
460 else if (context
->netid
.net
)
462 context
->netid
.next
= netid
;
463 tagif_netid
= run_tag_if(&context
->netid
);
466 log_tags(tagif_netid
, ntohl(mess
->xid
));
468 if (!message
&& !nailed
)
470 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
471 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
474 message
= _("no address configured");
479 (!(lease
= lease4_allocate(mess
->yiaddr
))))
480 message
= _("no leases left");
484 logaddr
= &mess
->yiaddr
;
486 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0, now
, 1);
488 lease_set_hostname(lease
, hostname
, 1, get_domain(lease
->addr
), domain
);
489 /* infinite lease unless nailed in dhcp-host line. */
490 lease_set_expires(lease
,
491 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
493 lease_set_interface(lease
, int_index
, now
);
495 clear_packet(mess
, end
);
496 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
497 netid
, subnet_addr
, 0, 0, 0, NULL
, 0, now
);
501 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
, mess
->xid
);
503 return message
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
506 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
508 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
509 int len
= option_len(opt
);
510 char *pq
= daemon
->dhcp_buff
;
511 unsigned char *pp
, *op
= option_ptr(opt
, 0);
518 /* NB, the following always sets at least one bit */
519 if (option_bool(OPT_FQDN_UPDATE
))
521 if (fqdn_flags
& 0x01)
523 fqdn_flags
|= 0x02; /* set O */
524 fqdn_flags
&= ~0x01; /* clear S */
526 fqdn_flags
|= 0x08; /* set N */
530 if (!(fqdn_flags
& 0x01))
531 fqdn_flags
|= 0x03; /* set S and O */
532 fqdn_flags
&= ~0x08; /* clear N */
535 if (fqdn_flags
& 0x04)
536 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
538 memcpy(pq
, op
+1, *op
);
546 if (len
> 0 && op
[len
-1] == 0)
551 if (pq
!= daemon
->dhcp_buff
)
556 if (legal_hostname(daemon
->dhcp_buff
))
557 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
559 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
561 int len
= option_len(opt
);
562 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
563 /* Microsoft clients are broken, and need zero-terminated strings
564 in options. We detect this state here, and do the same in
565 any options we send */
566 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
569 daemon
->dhcp_buff
[len
] = 0;
570 if (legal_hostname(daemon
->dhcp_buff
))
571 client_hostname
= daemon
->dhcp_buff
;
574 if (client_hostname
&& option_bool(OPT_LOG_OPTS
))
575 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
577 if (have_config(config
, CONFIG_NAME
))
579 hostname
= config
->hostname
;
580 domain
= config
->domain
;
582 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
583 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
584 offer_hostname
= hostname
;
586 else if (client_hostname
)
588 domain
= strip_hostname(client_hostname
);
590 if (strlen(client_hostname
) != 0)
592 hostname
= client_hostname
;
595 /* Search again now we have a hostname.
596 Only accept configs without CLID and HWADDR here, (they won't match)
597 to avoid impersonation by name. */
598 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
599 mess
->chaddr
, mess
->hlen
,
600 mess
->htype
, hostname
);
601 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
604 /* set "known" tag for known hosts */
605 known_id
.net
= "known";
606 known_id
.next
= netid
;
615 struct dhcp_netid_list
*list
;
617 for (list
= config
->netid
; list
; list
= list
->next
)
619 list
->list
->next
= netid
;
624 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
625 Otherwise assume the option is an array, and look for a matching element.
626 If no data given, existance of the option is enough. This code handles
627 rfc3925 V-I classes too. */
628 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
630 unsigned int len
, elen
, match
= 0;
633 if (o
->flags
& DHOPT_RFC3925
)
635 if (!(opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT
, 5)))
638 for (offset
= 0; offset
< (option_len(opt
) - 5u); offset
+= len
+ 5)
640 len
= option_uint(opt
, offset
+ 4 , 1);
641 /* Need to take care that bad data can't run us off the end of the packet */
642 if ((offset
+ len
+ 5 <= (option_len(opt
))) &&
643 (option_uint(opt
, offset
, 4) == (unsigned int)o
->u
.encap
))
644 for (o2
= offset
+ 5; o2
< offset
+ len
+ 5; o2
+= elen
+ 1)
646 elen
= option_uint(opt
, o2
, 1);
647 if ((o2
+ elen
+ 1 <= option_len(opt
)) &&
648 (match
= match_bytes(o
, option_ptr(opt
, o2
+ 1), elen
)))
657 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)))
660 match
= match_bytes(o
, option_ptr(opt
, 0), option_len(opt
));
665 o
->netid
->next
= netid
;
670 /* user-class options are, according to RFC3004, supposed to contain
671 a set of counted strings. Here we check that this is so (by seeing
672 if the counts are consistent with the overall option length) and if
673 so zero the counts so that we don't get spurious matches between
674 the vendor string and the counts. If the lengths don't add up, we
675 assume that the option is a single string and non RFC3004 compliant
676 and just do the substring match. dhclient provides these broken options.
677 The code, later, which sends user-class data to the lease-change script
678 relies on the transformation done here.
681 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
683 unsigned char *ucp
= option_ptr(opt
, 0);
685 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
686 if (j
== option_len(opt
))
687 for (j
= 0; j
< option_len(opt
); j
= tmp
)
689 tmp
= j
+ ucp
[j
] + 1;
694 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
698 if (vendor
->match_type
== MATCH_VENDOR
)
699 mopt
= OPTION_VENDOR_ID
;
700 else if (vendor
->match_type
== MATCH_USER
)
701 mopt
= OPTION_USER_CLASS
;
705 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
708 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
709 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
711 vendor
->netid
.next
= netid
;
712 netid
= &vendor
->netid
;
718 /* mark vendor-encapsulated options which match the client-supplied vendor class,
719 save client-supplied vendor class */
720 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
722 memcpy(daemon
->dhcp_buff3
, option_ptr(opt
, 0), option_len(opt
));
723 vendor_class_len
= option_len(opt
);
725 match_vendor_opts(opt
, daemon
->dhcp_opts
);
727 if (option_bool(OPT_LOG_OPTS
))
729 if (sanitise(opt
, daemon
->namebuff
))
730 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
731 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
732 my_syslog(MS_DHCP
| LOG_INFO
, _("%u user class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
735 tagif_netid
= run_tag_if(netid
);
737 /* if all the netids in the ignore list are present, ignore this client */
738 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
739 if (match_netid(id_list
->list
, tagif_netid
, 0))
742 /* If configured, we can override the server-id to be the address of the relay,
743 so that all traffic goes via the relay and can pick up agent-id info. This can be
744 configured for all relays, or by address. */
745 if (daemon
->override
&& mess
->giaddr
.s_addr
!= 0 && override
.s_addr
== 0)
747 if (!daemon
->override_relays
)
748 override
= mess
->giaddr
;
752 for (l
= daemon
->override_relays
; l
; l
= l
->next
)
753 if (l
->addr
.s_addr
== mess
->giaddr
.s_addr
)
756 override
= mess
->giaddr
;
760 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
761 if (have_config(config
, CONFIG_NOCLID
))
764 /* Check if client is PXE client. */
765 if (daemon
->enable_pxe
&&
766 (opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
767 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
769 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
771 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
775 /* Check if this is really a PXE bootserver request, and handle specially if so. */
776 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
777 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
778 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
780 struct pxe_service
*service
;
781 int type
= option_uint(opt
, 0, 2);
782 int layer
= option_uint(opt
, 2, 2);
783 unsigned char save71
[4];
784 struct dhcp_opt opt71
;
791 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
795 memcpy(save71
, option_ptr(opt
, 0), 4);
797 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
798 if (service
->type
== type
)
801 if (!service
|| !service
->basename
)
804 clear_packet(mess
, end
);
806 mess
->yiaddr
= mess
->ciaddr
;
807 mess
->ciaddr
.s_addr
= 0;
809 mess
->siaddr
= a_record_from_hosts(service
->sname
, now
);
810 else if (service
->server
.s_addr
!= 0)
811 mess
->siaddr
= service
->server
;
813 mess
->siaddr
= context
->local
;
815 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
816 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
817 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
818 pxe_misc(mess
, end
, uuid
);
820 prune_vendor_opts(tagif_netid
);
822 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
824 opt71
.flags
= DHOPT_VENDOR_MATCH
;
826 opt71
.next
= daemon
->dhcp_opts
;
827 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
829 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, mess
->xid
);
830 log_tags(tagif_netid
, ntohl(mess
->xid
));
831 return dhcp_packet_size(mess
, agent_id
, real_end
);
834 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
836 pxearch
= option_uint(opt
, 0, 2);
838 /* proxy DHCP here. */
839 if ((mess_type
== DHCPDISCOVER
|| (pxe
&& mess_type
== DHCPREQUEST
)))
841 struct dhcp_context
*tmp
;
843 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
844 if ((tmp
->flags
& CONTEXT_PROXY
) &&
845 match_netid(tmp
->filter
, tagif_netid
, 1))
850 struct dhcp_boot
*boot
= find_boot(tagif_netid
);
852 mess
->yiaddr
.s_addr
= 0;
853 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
855 mess
->ciaddr
.s_addr
= 0;
856 mess
->flags
|= htons(0x8000); /* broadcast */
859 clear_packet(mess
, end
);
861 /* Provide the bootfile here, for gPXE, and in case we have no menu items
862 and set discovery_control = 8 */
865 if (boot
->next_server
.s_addr
)
866 mess
->siaddr
= boot
->next_server
;
867 else if (boot
->tftp_sname
)
868 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
871 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
874 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
875 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
876 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
877 pxe_misc(mess
, end
, uuid
);
878 prune_vendor_opts(tagif_netid
);
879 do_encap_opts(pxe_opts(pxearch
, tagif_netid
, context
->local
, now
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
881 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, ignore
? "proxy-ignored" : "proxy", mess
->xid
);
882 log_tags(tagif_netid
, ntohl(mess
->xid
));
883 return ignore
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
889 /* if we're just a proxy server, go no further */
890 if ((context
->flags
& CONTEXT_PROXY
) || pxe
)
893 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
895 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
896 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
897 req_options
[option_len(opt
)] = OPTION_END
;
903 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
904 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
907 /* sanitise any message. Paranoid? Moi? */
908 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
910 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
913 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
, mess
->xid
);
915 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
916 lease_prune(lease
, now
);
918 if (have_config(config
, CONFIG_ADDR
) &&
919 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
921 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
922 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
923 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
924 config
->flags
|= CONFIG_DECLINED
;
925 config
->decline_time
= now
;
928 /* make sure this host gets a different address next time. */
929 for (; context
; context
= context
->current
)
930 context
->addr_epoch
++;
935 if (!(context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
)) ||
936 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
937 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
940 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
941 lease_prune(lease
, now
);
943 message
= _("unknown lease");
945 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
950 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
952 message
= _("ignored");
957 struct in_addr addr
, conf
;
959 addr
.s_addr
= conf
.s_addr
= 0;
961 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
962 addr
= option_addr(opt
);
964 if (have_config(config
, CONFIG_ADDR
))
966 char *addrs
= inet_ntoa(config
->addr
);
968 if ((ltmp
= lease_find_by_addr(config
->addr
)) &&
970 !config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
973 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
974 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
975 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
976 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
980 struct dhcp_context
*tmp
;
981 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
982 if (context
->router
.s_addr
== config
->addr
.s_addr
)
985 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
986 else if (have_config(config
, CONFIG_DECLINED
) &&
987 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
988 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
997 address_available(context
, lease
->addr
, tagif_netid
) &&
998 !config_find_by_address(daemon
->dhcp_conf
, lease
->addr
))
999 mess
->yiaddr
= lease
->addr
;
1000 else if (opt
&& address_available(context
, addr
, tagif_netid
) && !lease_find_by_addr(addr
) &&
1001 !config_find_by_address(daemon
->dhcp_conf
, addr
))
1002 mess
->yiaddr
= addr
;
1003 else if (emac_len
== 0)
1004 message
= _("no unique-id");
1005 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, tagif_netid
, now
))
1006 message
= _("no address available");
1009 log_packet("DHCPDISCOVER", opt
? option_ptr(opt
, 0) : NULL
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1011 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1014 if (context
->netid
.net
)
1016 context
->netid
.next
= netid
;
1017 tagif_netid
= run_tag_if(&context
->netid
);
1020 log_tags(tagif_netid
, ntohl(mess
->xid
));
1022 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1024 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1025 clear_packet(mess
, end
);
1026 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
1027 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1028 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1029 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1030 if (time
!= 0xffffffff)
1032 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
1033 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
1035 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
1036 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1038 return dhcp_packet_size(mess
, agent_id
, real_end
);
1041 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1043 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
1045 /* SELECTING or INIT_REBOOT */
1046 mess
->yiaddr
= option_addr(opt
);
1048 /* send vendor and user class info for new or recreated lease */
1051 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
1056 if (override
.s_addr
!= 0)
1058 if (option_addr(opt
).s_addr
!= override
.s_addr
)
1063 for (; context
; context
= context
->current
)
1064 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
1069 /* Handle very strange configs where clients have more than one route to the server.
1070 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1071 Have to set override to make sure we echo back the correct server-id */
1074 enumerate_interfaces();
1076 for (intr
= daemon
->interfaces
; intr
; intr
= intr
->next
)
1077 if (intr
->addr
.sa
.sa_family
== AF_INET
&&
1078 intr
->addr
.in
.sin_addr
.s_addr
== option_addr(opt
).s_addr
&&
1083 override
= intr
->addr
.in
.sin_addr
;
1086 /* In auth mode, a REQUEST sent to the wrong server
1087 should be faulted, so that the client establishes
1088 communication with us, otherwise, silently ignore. */
1089 if (!option_bool(OPT_AUTHORITATIVE
))
1091 message
= _("wrong server-ID");
1096 /* If a lease exists for this host and another address, squash it. */
1097 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1099 lease_prune(lease
, now
);
1106 if (!lease
&& !option_bool(OPT_AUTHORITATIVE
))
1109 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1110 message
= _("wrong address");
1115 /* RENEWING or REBINDING */
1116 /* Check existing lease for this address.
1117 We allow it to be missing if dhcp-authoritative mode
1118 as long as we can allocate the lease now - checked below.
1119 This makes for a smooth recovery from a lost lease DB */
1120 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1121 (!lease
&& !option_bool(OPT_AUTHORITATIVE
)))
1123 /* A client rebinding will broadcast the request, so we may see it even
1124 if the lease is held by another server. Just ignore it in that case.
1125 If the request is unicast to us, then somethings wrong, NAK */
1128 message
= _("lease not found");
1129 /* ensure we broadcast NAK */
1133 /* desynchronise renewals */
1135 mess
->yiaddr
= mess
->ciaddr
;
1138 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1142 struct dhcp_config
*addr_config
;
1143 struct dhcp_context
*tmp
= NULL
;
1145 if (have_config(config
, CONFIG_ADDR
))
1146 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1147 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1150 if (!(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1152 /* If a machine moves networks whilst it has a lease, we catch that here. */
1153 message
= _("wrong network");
1154 /* ensure we broadcast NAK */
1158 /* Check for renewal of a lease which is outside the allowed range. */
1159 else if (!address_available(context
, mess
->yiaddr
, tagif_netid
) &&
1160 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1161 message
= _("address not available");
1163 /* Check if a new static address has been configured. Be very sure that
1164 when the client does DISCOVER, it will get the static address, otherwise
1165 an endless protocol loop will ensue. */
1166 else if (!tmp
&& !selecting
&&
1167 have_config(config
, CONFIG_ADDR
) &&
1168 (!have_config(config
, CONFIG_DECLINED
) ||
1169 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1170 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1171 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1172 message
= _("static lease available");
1174 /* Check to see if the address is reserved as a static address for another host */
1175 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1176 message
= _("address reserved");
1178 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1180 /* If a host is configured with more than one MAC address, it's OK to 'nix
1181 a lease from one of it's MACs to give the address to another. */
1182 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1184 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1185 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1186 inet_ntoa(ltmp
->addr
));
1190 message
= _("address in use");
1196 message
= _("no unique-id");
1200 if ((lease
= lease4_allocate(mess
->yiaddr
)))
1203 message
= _("no leases left");
1210 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1212 mess
->yiaddr
.s_addr
= 0;
1213 clear_packet(mess
, end
);
1214 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1215 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1216 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1217 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1218 a distant subnet which unicast a REQ to us won't work. */
1219 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1220 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1222 mess
->flags
|= htons(0x8000); /* broadcast */
1223 mess
->ciaddr
.s_addr
= 0;
1228 if (context
->netid
.net
)
1230 context
->netid
.next
= netid
;
1231 tagif_netid
= run_tag_if( &context
->netid
);
1234 log_tags(tagif_netid
, ntohl(mess
->xid
));
1238 /* pick up INIT-REBOOT events. */
1239 lease
->flags
|= LEASE_CHANGED
;
1242 if (daemon
->lease_change_command
)
1244 struct dhcp_netid
*n
;
1246 if (mess
->giaddr
.s_addr
)
1247 lease
->giaddr
= mess
->giaddr
;
1249 free(lease
->extradata
);
1250 lease
->extradata
= NULL
;
1251 lease
->extradata_size
= lease
->extradata_len
= 0;
1253 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_VENDOR_ID
, 1));
1254 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_HOSTNAME
, 1));
1255 add_extradata_opt(lease
, oui
);
1256 add_extradata_opt(lease
, serial
);
1257 add_extradata_opt(lease
, class);
1259 /* space-concat tag set */
1261 add_extradata_opt(lease
, NULL
);
1263 for (n
= tagif_netid
; n
; n
= n
->next
)
1265 struct dhcp_netid
*n1
;
1267 for (n1
= n
->next
; n1
; n1
= n1
->next
)
1268 if (strcmp(n
->net
, n1
->net
) == 0)
1271 lease_add_extradata(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
1274 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1276 int len
= option_len(opt
);
1277 unsigned char *ucp
= option_ptr(opt
, 0);
1278 /* If the user-class option started as counted strings, the first byte will be zero. */
1279 if (len
!= 0 && ucp
[0] == 0)
1281 lease_add_extradata(lease
, ucp
, len
, 0);
1287 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1289 domain
= get_domain(mess
->yiaddr
);
1290 hostname
= client_hostname
;
1294 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1295 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
, now
, do_classes
);
1297 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1300 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1301 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1307 /* Last ditch, if configured, generate hostname from mac address */
1308 if (!hostname
&& emac_len
!= 0)
1310 for (id_list
= daemon
->dhcp_gen_names
; id_list
; id_list
= id_list
->next
)
1311 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1317 hostname
= daemon
->dhcp_buff
;
1318 /* buffer is 256 bytes, 3 bytes per octet */
1319 for (i
= 0; (i
< emac_len
) && (i
< 80); i
++)
1320 hostname
+= sprintf(hostname
, "%.2x%s", emac
[i
], (i
== emac_len
- 1) ? "" : "-");
1321 hostname
= daemon
->dhcp_buff
;
1326 lease_set_hostname(lease
, hostname
, hostname_auth
, get_domain(lease
->addr
), domain
);
1328 lease_set_expires(lease
, time
, now
);
1329 lease_set_interface(lease
, int_index
, now
);
1331 if (override
.s_addr
!= 0)
1332 lease
->override
= override
;
1334 override
= lease
->override
;
1336 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1338 clear_packet(mess
, end
);
1339 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1340 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1341 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1342 if (time
!= 0xffffffff)
1344 while (fuzz
> (time
/16))
1346 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
1347 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
1349 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1350 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1353 return dhcp_packet_size(mess
, agent_id
, real_end
);
1356 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1357 message
= _("ignored");
1359 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1361 if (message
|| mess
->ciaddr
.s_addr
== 0)
1364 /* For DHCPINFORM only, cope without a valid context */
1365 context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
);
1367 /* Find a least based on IP address if we didn't
1368 get one from MAC address/client-d */
1370 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1372 hostname
= lease
->hostname
;
1374 if (!hostname
&& (hostname
= host_from_dns(mess
->ciaddr
)))
1375 domain
= get_domain(mess
->ciaddr
);
1377 if (context
&& context
->netid
.net
)
1379 context
->netid
.next
= netid
;
1380 tagif_netid
= run_tag_if(&context
->netid
);
1383 log_tags(tagif_netid
, ntohl(mess
->xid
));
1385 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1389 if (override
.s_addr
!= 0)
1390 lease
->override
= override
;
1392 override
= lease
->override
;
1395 clear_packet(mess
, end
);
1396 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1397 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1401 if (lease
->expires
== 0)
1404 time
= (unsigned int)difftime(lease
->expires
, now
);
1405 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1406 lease_set_interface(lease
, int_index
, now
);
1409 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1410 netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1412 *is_inform
= 1; /* handle reply differently */
1413 return dhcp_packet_size(mess
, agent_id
, real_end
);
1419 /* find a good value to use as MAC address for logging and address-allocation hashing.
1420 This is normally just the chaddr field from the DHCP packet,
1421 but eg Firewire will have hlen == 0 and use the client-id instead.
1422 This could be anything, but will normally be EUI64 for Firewire.
1423 We assume that if the first byte of the client-id equals the htype byte
1424 then the client-id is using the usual encoding and use the rest of the
1425 client-id: if not we can use the whole client-id. This should give
1426 sane MAC address logs. */
1427 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1428 int clid_len
, unsigned char *clid
, int *len_out
)
1430 if (hwlen
== 0 && clid
&& clid_len
> 3)
1432 if (clid
[0] == hwtype
)
1434 *len_out
= clid_len
- 1 ;
1438 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1439 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1441 *len_out
= clid_len
- 1 ;
1446 *len_out
= clid_len
;
1454 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1456 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1460 unsigned int req_time
= option_uint(opt
, 0, 4);
1461 if (req_time
< 120 )
1462 req_time
= 120; /* sanity */
1463 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1470 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1472 if (override
.s_addr
!= 0)
1474 else if (context
&& context
->local
.s_addr
!= 0)
1475 return context
->local
;
1480 static int sanitise(unsigned char *opt
, char *buf
)
1490 p
= option_ptr(opt
, 0);
1492 for (i
= option_len(opt
); i
> 0; i
--)
1495 if (isprint((int)c
))
1498 *buf
= 0; /* add terminator */
1504 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
)
1507 lease_add_extradata(lease
, NULL
, 0, 0);
1509 lease_add_extradata(lease
, option_ptr(opt
, 0), option_len(opt
), 0);
1513 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1514 int mac_len
, char *interface
, char *string
, u32 xid
)
1518 /* addr may be misaligned */
1520 memcpy(&a
, addr
, sizeof(a
));
1522 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1524 if(option_bool(OPT_LOG_OPTS
))
1525 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s",
1529 addr
? inet_ntoa(a
) : "",
1532 string
? string
: "");
1534 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s",
1537 addr
? inet_ntoa(a
) : "",
1540 string
? string
: "");
1543 static void log_options(unsigned char *start
, u32 xid
)
1545 while (*start
!= OPTION_END
)
1547 char *optname
= option_string(AF_INET
, start
[0], option_ptr(start
, 0), option_len(start
), daemon
->namebuff
, MAXDNAME
);
1549 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d %s %s",
1550 ntohl(xid
), option_len(start
), start
[0], optname
, daemon
->namebuff
);
1551 start
+= start
[1] + 2;
1555 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1561 else if (*p
== OPTION_END
)
1562 return opt
== OPTION_END
? p
: NULL
;
1563 else if (*p
== OPTION_PAD
)
1569 return NULL
; /* malformed packet */
1570 opt_len
= option_len(p
);
1571 if (p
> end
- (2 + opt_len
))
1572 return NULL
; /* malformed packet */
1573 if (*p
== opt
&& opt_len
>= minsize
)
1580 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1582 unsigned char *ret
, *overload
;
1584 /* skip over DHCP cookie; */
1585 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1588 /* look for overload option. */
1589 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1592 /* Can we look in filename area ? */
1593 if ((overload
[2] & 1) &&
1594 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1597 /* finally try sname area */
1598 if ((overload
[2] & 2) &&
1599 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1605 static struct in_addr
option_addr(unsigned char *opt
)
1607 /* this worries about unaligned data in the option. */
1608 /* struct in_addr is network byte order */
1611 memcpy(&ret
, option_ptr(opt
, 0), INADDRSZ
);
1616 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1618 /* this worries about unaligned data and byte order */
1619 unsigned int ret
= 0;
1621 unsigned char *p
= option_ptr(opt
, offset
);
1623 for (i
= 0; i
< size
; i
++)
1624 ret
= (ret
<< 8) | *p
++;
1629 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1632 start
+= start
[1] + 2;
1636 /* only for use when building packet: doesn't check for bad data. */
1637 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1639 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1643 if (*p
== OPTION_OVERLOAD
)
1650 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
)
1652 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1653 unsigned char *overload
;
1656 /* move agent_id back down to the end of the packet */
1659 memmove(p
, agent_id
, real_end
- agent_id
);
1660 p
+= real_end
- agent_id
;
1661 memset(p
, 0, real_end
- p
); /* in case of overlap */
1664 /* add END options to the regions. */
1665 overload
= find_overload(mess
);
1667 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1669 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1670 if (option_bool(OPT_LOG_OPTS
))
1671 log_options(mess
->file
, mess
->xid
);
1673 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1674 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1676 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1678 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1679 if (option_bool(OPT_LOG_OPTS
))
1680 log_options(mess
->sname
, mess
->xid
);
1682 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1683 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1688 if (option_bool(OPT_LOG_OPTS
))
1690 if (mess
->siaddr
.s_addr
!= 0)
1691 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1693 if ((mess
->flags
& htons(0x8000)) && mess
->ciaddr
.s_addr
== 0)
1694 my_syslog(MS_DHCP
| LOG_INFO
, _("%u broadcast response"), ntohl(mess
->xid
));
1696 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1699 ret
= (size_t)(p
- (unsigned char *)mess
);
1701 if (ret
< MIN_PACKETSZ
)
1707 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1709 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1711 if (p
+ len
+ 3 >= end
)
1712 /* not enough space in options area, try and use overload, if poss */
1714 unsigned char *overload
;
1716 if (!(overload
= find_overload(mess
)) &&
1717 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1719 /* attempt to overload fname and sname areas, we've reserved space for the
1720 overflow option previuously. */
1722 *(p
++) = OPTION_OVERLOAD
;
1728 /* using filename field ? */
1731 if (mess
->file
[0] == 0)
1734 if (overload
[2] & 1)
1736 p
= dhcp_skip_opts(mess
->file
);
1737 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1743 /* try to bring sname into play (it may be already) */
1744 if (mess
->sname
[0] == 0)
1747 if (overload
[2] & 2)
1749 p
= dhcp_skip_opts(mess
->sname
);
1750 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1757 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1769 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1772 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1775 for (i
= 0; i
< len
; i
++)
1776 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1779 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1780 char *string
, int null_term
)
1783 size_t len
= strlen(string
);
1785 if (null_term
&& len
!= 255)
1788 if ((p
= free_space(mess
, end
, opt
, len
)))
1789 memcpy(p
, string
, len
);
1792 /* return length, note this only does the data part */
1793 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1797 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1802 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1805 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1806 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1808 /* zero means "self" (but not in vendorclass options.) */
1810 memcpy(p
, &context
->local
, INADDRSZ
);
1812 memcpy(p
, a
, INADDRSZ
);
1817 memcpy(p
, opt
->val
, len
);
1822 static int in_list(unsigned char *list
, int opt
)
1826 /* If no requested options, send everything, not nothing. */
1830 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1837 static struct dhcp_opt
*option_find2(int opt
)
1839 struct dhcp_opt
*opts
;
1841 for (opts
= daemon
->dhcp_opts
; opts
; opts
= opts
->next
)
1842 if (opts
->opt
== opt
&& (opts
->flags
& DHOPT_TAGOK
))
1848 /* mark vendor-encapsulated options which match the client-supplied or
1849 config-supplied vendor class */
1850 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1852 for (; dopt
; dopt
= dopt
->next
)
1854 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1855 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1858 if (dopt
->u
.vendor_class
)
1859 len
= strlen((char *)dopt
->u
.vendor_class
);
1860 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1861 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1863 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1870 static int do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1871 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1873 int len
, enc_len
, ret
= 0;
1874 struct dhcp_opt
*start
;
1877 /* find size in advance */
1878 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1879 if (opt
->flags
& flag
)
1881 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1883 if (enc_len
+ new <= 255)
1887 p
= free_space(mess
, end
, encap
, enc_len
);
1888 for (; start
&& start
!= opt
; start
= start
->next
)
1889 if (p
&& (start
->flags
& flag
))
1891 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1892 *(p
++) = start
->opt
;
1902 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
1904 for (; start
; start
= start
->next
)
1905 if (start
->flags
& flag
)
1907 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1908 *(p
++) = start
->opt
;
1918 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
1922 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
1923 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
1924 memcpy(p
, uuid
, 17);
1927 static int prune_vendor_opts(struct dhcp_netid
*netid
)
1930 struct dhcp_opt
*opt
;
1932 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1933 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
1934 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1936 if (!match_netid(opt
->netid
, netid
, 1))
1937 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1938 else if (opt
->flags
& DHOPT_FORCE
)
1944 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
, time_t now
)
1948 unsigned char *p
, *q
;
1949 struct pxe_service
*service
;
1950 static struct dhcp_opt
*o
, *ret
;
1951 int i
, j
= NUM_OPTS
- 1;
1952 struct in_addr boot_server
;
1954 /* We pass back references to these, hence they are declared static */
1955 static unsigned char discovery_control
;
1956 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
1957 static struct dhcp_opt
*fake_opts
= NULL
;
1959 /* Disable multicast, since we don't support it, and broadcast
1960 unless we need it */
1961 discovery_control
= 3;
1963 ret
= daemon
->dhcp_opts
;
1965 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
1968 for (i
= 0; i
< NUM_OPTS
; i
++)
1970 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
1971 fake_opts
[i
].netid
= NULL
;
1972 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
1975 /* create the data for the PXE_MENU and PXE_SERVERS options. */
1976 p
= (unsigned char *)daemon
->dhcp_buff
;
1977 q
= (unsigned char *)daemon
->dhcp_buff3
;
1979 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
1980 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
1982 size_t len
= strlen(service
->menu
);
1983 /* opt 43 max size is 255. encapsulated option has type and length
1984 bytes, so its max size is 253. */
1985 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
1987 *(p
++) = service
->type
>> 8;
1988 *(p
++) = service
->type
;
1990 memcpy(p
, service
->menu
, len
);
1997 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
1998 return daemon
->dhcp_opts
;
2001 boot_server
= service
->basename
? local
:
2002 (service
->sname
? a_record_from_hosts(service
->sname
, now
) : service
->server
);
2004 if (boot_server
.s_addr
!= 0)
2006 if (q
- (unsigned char *)daemon
->dhcp_buff3
+ 3 + INADDRSZ
>= 253)
2009 /* Boot service with known address - give it */
2010 *(q
++) = service
->type
>> 8;
2011 *(q
++) = service
->type
;
2013 /* dest misaligned */
2014 memcpy(q
, &boot_server
.s_addr
, INADDRSZ
);
2017 else if (service
->type
!= 0)
2018 /* We don't know the server for a service type, so we'll
2019 allow the client to broadcast for it */
2020 discovery_control
= 2;
2023 /* if no prompt, wait forever if there's a choice */
2024 fake_prompt
[0] = (i
> 1) ? 255 : 0;
2027 discovery_control
= 8; /* no menu - just use use mess->filename */
2030 ret
= &fake_opts
[j
--];
2031 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
2032 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
2033 ret
->opt
= SUBOPT_PXE_MENU
;
2035 if (q
- (unsigned char *)daemon
->dhcp_buff3
!= 0)
2037 ret
= &fake_opts
[j
--];
2038 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff3
;
2039 ret
->val
= (unsigned char *)daemon
->dhcp_buff3
;
2040 ret
->opt
= SUBOPT_PXE_SERVERS
;
2044 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
2045 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
2050 ret
= &fake_opts
[j
--];
2051 ret
->len
= sizeof(fake_prompt
);
2052 ret
->val
= fake_prompt
;
2053 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
2056 ret
= &fake_opts
[j
--];
2058 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
2059 ret
->val
= &discovery_control
;
2064 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
2066 memset(mess
->sname
, 0, sizeof(mess
->sname
));
2067 memset(mess
->file
, 0, sizeof(mess
->file
));
2068 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
2069 mess
->siaddr
.s_addr
= 0;
2072 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
2074 struct dhcp_boot
*boot
;
2076 /* decide which dhcp-boot option we're using */
2077 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2078 if (match_netid(boot
->netid
, netid
, 0))
2081 /* No match, look for one without a netid */
2082 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2083 if (match_netid(boot
->netid
, netid
, 1))
2089 static void do_options(struct dhcp_context
*context
,
2090 struct dhcp_packet
*mess
,
2092 unsigned char *req_options
,
2095 struct dhcp_netid
*netid
,
2096 struct in_addr subnet_addr
,
2097 unsigned char fqdn_flags
,
2098 int null_term
, int pxe_arch
,
2099 unsigned char *uuid
,
2100 int vendor_class_len
,
2103 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2104 struct dhcp_boot
*boot
;
2106 int i
, len
, force_encap
= 0;
2107 unsigned char f0
= 0, s0
= 0;
2108 int done_file
= 0, done_server
= 0;
2109 int done_vendor_class
= 0;
2110 struct dhcp_netid
*tagif
;
2111 struct dhcp_netid_list
*id_list
;
2113 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2115 context
->netid
.next
= NULL
;
2116 tagif
= option_filter(netid
, context
&& context
->netid
.net
? &context
->netid
: NULL
, config_opts
);
2119 if (option_bool(OPT_LOG_OPTS
) && req_options
)
2121 char *q
= daemon
->namebuff
;
2122 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2124 char *s
= option_string(AF_INET
, req_options
[i
], NULL
, 0, NULL
, 0);
2125 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2128 strlen(s
) != 0 ? ":" : "",
2130 req_options
[i
+1] == OPTION_END
? "" : ", ");
2131 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2133 q
= daemon
->namebuff
;
2134 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2139 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
2140 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
2143 mess
->flags
|= htons(0x8000); /* force broadcast */
2146 mess
->siaddr
= context
->local
;
2148 /* See if we can send the boot stuff as options.
2149 To do this we need a requested option list, BOOTP
2150 and very old DHCP clients won't have this, we also
2151 provide an manual option to disable it.
2152 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2153 names, so we always send those. */
2154 if ((boot
= find_boot(tagif
)))
2158 if (!option_bool(OPT_NO_OVERRIDE
) &&
2160 in_list(req_options
, OPTION_SNAME
))
2161 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2163 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2168 if (!option_bool(OPT_NO_OVERRIDE
) &&
2170 in_list(req_options
, OPTION_FILENAME
))
2171 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2173 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2176 if (boot
->next_server
.s_addr
)
2177 mess
->siaddr
= boot
->next_server
;
2178 else if (boot
->tftp_sname
)
2179 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
2182 /* Use the values of the relevant options if no dhcp-boot given and
2183 they're not explicitly asked for as options. OPTION_END is used
2184 as an internal way to specify siaddr without using dhcp-boot, for use in
2187 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
2188 (opt
= option_find2(OPTION_FILENAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2190 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2194 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2195 (opt
= option_find2(OPTION_SNAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2197 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2201 if ((opt
= option_find2(OPTION_END
)))
2202 mess
->siaddr
.s_addr
= ((struct in_addr
*)opt
->val
)->s_addr
;
2205 /* We don't want to do option-overload for BOOTP, so make the file and sname
2206 fields look like they are in use, even when they aren't. This gets restored
2207 at the end of this function. */
2209 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2213 s0
= mess
->sname
[0];
2217 /* At this point, if mess->sname or mess->file are zeroed, they are available
2218 for option overload, reserve space for the overload option. */
2219 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2222 /* rfc3011 says this doesn't need to be in the requested options list. */
2223 if (subnet_addr
.s_addr
)
2224 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2226 /* replies to DHCPINFORM may not have a valid context */
2229 if (!option_find2(OPTION_NETMASK
))
2230 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2232 /* May not have a "guessed" broadcast address if we got no packets via a relay
2233 from this net yet (ie just unicast renewals after a restart */
2234 if (context
->broadcast
.s_addr
&&
2235 !option_find2(OPTION_BROADCAST
))
2236 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2238 /* Same comments as broadcast apply, and also may not be able to get a sensible
2239 default when using subnet select. User must configure by steam in that case. */
2240 if (context
->router
.s_addr
&&
2241 in_list(req_options
, OPTION_ROUTER
) &&
2242 !option_find2(OPTION_ROUTER
))
2243 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2245 if (in_list(req_options
, OPTION_DNSSERVER
) &&
2246 !option_find2(OPTION_DNSSERVER
))
2247 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2250 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2251 !option_find2(OPTION_DOMAINNAME
))
2252 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2254 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2257 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2258 !option_find2(OPTION_HOSTNAME
))
2259 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2261 if (fqdn_flags
!= 0)
2263 len
= strlen(hostname
) + 3;
2265 if (fqdn_flags
& 0x04)
2271 len
+= strlen(domain
) + 1;
2273 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2275 *(p
++) = fqdn_flags
& 0x0f; /* MBZ bits to zero */
2279 if (fqdn_flags
& 0x04)
2281 p
= do_rfc1035_name(p
, hostname
);
2283 p
= do_rfc1035_name(p
, domain
);
2288 memcpy(p
, hostname
, strlen(hostname
));
2289 p
+= strlen(hostname
);
2293 memcpy(p
, domain
, strlen(domain
));
2294 p
+= strlen(domain
);
2303 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2305 int optno
= opt
->opt
;
2307 /* netids match and not encapsulated? */
2308 if (!(opt
->flags
& DHOPT_TAGOK
))
2311 /* was it asked for, or are we sending it anyway? */
2312 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2315 /* prohibit some used-internally options */
2316 if (optno
== OPTION_CLIENT_FQDN
||
2317 optno
== OPTION_MAXMESSAGE
||
2318 optno
== OPTION_OVERLOAD
||
2319 optno
== OPTION_PAD
||
2320 optno
== OPTION_END
)
2323 if (optno
== OPTION_SNAME
&& done_server
)
2326 if (optno
== OPTION_FILENAME
&& done_file
)
2329 /* For the options we have default values on
2330 dhc-option=<optionno> means "don't include this option"
2331 not "include a zero-length option" */
2332 if (opt
->len
== 0 &&
2333 (optno
== OPTION_NETMASK
||
2334 optno
== OPTION_BROADCAST
||
2335 optno
== OPTION_ROUTER
||
2336 optno
== OPTION_DNSSERVER
||
2337 optno
== OPTION_DOMAINNAME
||
2338 optno
== OPTION_HOSTNAME
))
2341 /* vendor-class comes from elsewhere for PXE */
2342 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2345 /* always force null-term for filename and servername - buggy PXE again. */
2346 len
= do_opt(opt
, NULL
, context
,
2347 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2349 if ((p
= free_space(mess
, end
, optno
, len
)))
2351 do_opt(opt
, p
, context
,
2352 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2354 /* If we send a vendor-id, revisit which vendor-ops we consider
2355 it appropriate to send. */
2356 if (optno
== OPTION_VENDOR_ID
)
2358 match_vendor_opts(p
- 2, config_opts
);
2359 done_vendor_class
= 1;
2364 /* Now send options to be encapsulated in arbitrary options,
2365 eg dhcp-option=encap:172,17,.......
2366 Also handle vendor-identifying vendor-encapsulated options,
2367 dhcp-option = vi-encap:13,17,.......
2368 The may be more that one "outer" to do, so group
2369 all the options which match each outer in turn. */
2370 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2371 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2373 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2377 if ((flags
= (opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_RFC3925
))))
2382 if (opt
->flags
& DHOPT_ENCAP_DONE
)
2385 for (len
= 0, o
= config_opts
; o
; o
= o
->next
)
2387 int outer
= flags
& DHOPT_ENCAPSULATE
? o
->u
.encap
: OPTION_VENDOR_IDENT_OPT
;
2389 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2391 if (!(o
->flags
& flags
) || opt
->u
.encap
!= o
->u
.encap
)
2394 o
->flags
|= DHOPT_ENCAP_DONE
;
2395 if (match_netid(o
->netid
, tagif
, 1) &&
2396 ((o
->flags
& DHOPT_FORCE
) || in_list(req_options
, outer
)))
2398 o
->flags
|= DHOPT_ENCAP_MATCH
;
2400 len
+= do_opt(o
, NULL
, NULL
, 0) + 2;
2406 if (flags
& DHOPT_ENCAPSULATE
)
2407 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2409 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt
->u
.encap
);
2410 else if ((p
= free_space(mess
, end
, OPTION_VENDOR_IDENT_OPT
, len
+ 5)))
2412 int swap_ent
= htonl(opt
->u
.encap
);
2413 memcpy(p
, &swap_ent
, 4);
2416 for (o
= config_opts
; o
; o
= o
->next
)
2417 if (o
->flags
& DHOPT_ENCAP_MATCH
)
2419 len
= do_opt(o
, p
+ 2, NULL
, 0);
2429 force_encap
= prune_vendor_opts(tagif
);
2431 if (context
&& pxe_arch
!= -1)
2433 pxe_misc(mess
, end
, uuid
);
2434 config_opts
= pxe_opts(pxe_arch
, tagif
, context
->local
, now
);
2437 if ((force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
)) &&
2438 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
) &&
2439 pxe_arch
== -1 && !done_vendor_class
&& vendor_class_len
!= 0 &&
2440 (p
= free_space(mess
, end
, OPTION_VENDOR_ID
, vendor_class_len
)))
2441 /* If we send vendor encapsulated options, and haven't already sent option 60,
2442 echo back the value we got from the client. */
2443 memcpy(p
, daemon
->dhcp_buff3
, vendor_class_len
);
2445 /* restore BOOTP anti-overload hack */
2446 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2449 mess
->sname
[0] = s0
;