1 /* dnsmasq is Copyright (c) 2000-2010 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/>.
23 #define DHCP_COOKIE 0x63825363
25 /* The Linux in-kernel DHCP client silently ignores any packet
26 smaller than this. Sigh........... */
27 #define MIN_PACKETSZ 300
30 #define OPTION_NETMASK 1
31 #define OPTION_ROUTER 3
32 #define OPTION_DNSSERVER 6
33 #define OPTION_HOSTNAME 12
34 #define OPTION_DOMAINNAME 15
35 #define OPTION_BROADCAST 28
36 #define OPTION_VENDOR_CLASS_OPT 43
37 #define OPTION_REQUESTED_IP 50
38 #define OPTION_LEASE_TIME 51
39 #define OPTION_OVERLOAD 52
40 #define OPTION_MESSAGE_TYPE 53
41 #define OPTION_SERVER_IDENTIFIER 54
42 #define OPTION_REQUESTED_OPTIONS 55
43 #define OPTION_MESSAGE 56
44 #define OPTION_MAXMESSAGE 57
47 #define OPTION_VENDOR_ID 60
48 #define OPTION_CLIENT_ID 61
49 #define OPTION_SNAME 66
50 #define OPTION_FILENAME 67
51 #define OPTION_USER_CLASS 77
52 #define OPTION_CLIENT_FQDN 81
53 #define OPTION_AGENT_ID 82
54 #define OPTION_ARCH 93
55 #define OPTION_PXE_UUID 97
56 #define OPTION_SUBNET_SELECT 118
57 #define OPTION_VENDOR_IDENT 124
58 #define OPTION_VENDOR_IDENT_OPT 125
59 #define OPTION_END 255
61 #define SUBOPT_CIRCUIT_ID 1
62 #define SUBOPT_REMOTE_ID 2
63 #define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */
64 #define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */
65 #define SUBOPT_SERVER_OR 11 /* RFC 5107 */
67 #define SUBOPT_PXE_BOOT_ITEM 71 /* PXE standard */
68 #define SUBOPT_PXE_DISCOVERY 6
69 #define SUBOPT_PXE_SERVERS 8
70 #define SUBOPT_PXE_MENU 9
71 #define SUBOPT_PXE_MENU_PROMPT 10
73 #define DHCPDISCOVER 1
82 #define BRDBAND_FORUM_IANA 3561 /* Broadband forum IANA enterprise */
84 #define have_config(config, mask) ((config) && ((config)->flags & (mask)))
85 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
86 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
89 static void add_extradata_data(struct dhcp_lease
*lease
, unsigned char *data
, size_t len
, int delim
);
90 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
);
92 static int match_bytes(struct dhcp_opt
*o
, unsigned char *p
, int len
);
93 static int sanitise(unsigned char *opt
, char *buf
);
94 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
);
95 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
);
96 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
97 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
98 int opt
, char *string
, int null_term
);
99 static struct in_addr
option_addr(unsigned char *opt
);
100 static struct in_addr
option_addr_arr(unsigned char *opt
, int offset
);
101 static unsigned int option_uint(unsigned char *opt
, int i
, int size
);
102 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
103 int mac_len
, char *interface
, char *string
, u32 xid
);
104 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
105 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
106 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
,
107 unsigned char *agent_id
, unsigned char *real_end
);
108 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
109 static void do_options(struct dhcp_context
*context
,
110 struct dhcp_packet
*mess
,
111 unsigned char *real_end
,
112 unsigned char *req_options
,
114 char *domain
, char *config_domain
,
115 struct dhcp_netid
*netid
,
116 struct in_addr subnet_addr
,
117 unsigned char fqdn_flags
,
118 int null_term
, int pxearch
,
120 int vendor_class_len
);
123 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
124 static int do_encap_opts(struct dhcp_opt
*opts
, int encap
, int flag
, struct dhcp_packet
*mess
, unsigned char *end
, int null_term
);
125 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
);
126 static int prune_vendor_opts(struct dhcp_netid
*netid
);
127 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
);
128 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
);
131 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
132 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
, int pxe
)
134 unsigned char *opt
, *clid
= NULL
;
135 struct dhcp_lease
*ltmp
, *lease
= NULL
;
136 struct dhcp_vendor
*vendor
;
137 struct dhcp_mac
*mac
;
138 struct dhcp_netid_list
*id_list
;
139 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0, pxearch
= -1;
140 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
141 unsigned char *end
= (unsigned char *)(mess
+ 1);
142 unsigned char *real_end
= (unsigned char *)(mess
+ 1);
143 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
, *domain
= NULL
;
144 int hostname_auth
= 0, borken_opt
= 0;
145 unsigned char *req_options
= NULL
;
146 char *message
= NULL
;
148 struct dhcp_config
*config
;
149 struct dhcp_netid
*netid
, *tagif_netid
;
150 struct in_addr subnet_addr
, fallback
, override
;
151 unsigned short fuzz
= 0;
152 unsigned int mess_type
= 0;
153 unsigned char fqdn_flags
= 0;
154 unsigned char *agent_id
= NULL
, *uuid
= NULL
;
155 unsigned char *emac
= NULL
;
156 int vendor_class_len
= 0, emac_len
= 0;
157 struct dhcp_netid known_id
, iface_id
, cpewan_id
;
159 unsigned char pxe_uuid
[17];
160 unsigned char *oui
= NULL
, *serial
= NULL
, *class = NULL
;
162 subnet_addr
.s_addr
= override
.s_addr
= 0;
164 /* set tag with name == interface */
165 iface_id
.net
= iface_name
;
166 iface_id
.next
= NULL
;
169 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
172 if (mess
->htype
== 0 && mess
->hlen
!= 0)
175 /* check for DHCP rather than BOOTP */
176 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
178 u32 cookie
= htonl(DHCP_COOKIE
);
180 /* only insist on a cookie for DHCP. */
181 if (memcmp(mess
->options
, &cookie
, sizeof(u32
)) != 0)
184 mess_type
= option_uint(opt
, 0, 1);
186 /* two things to note here: expand_buf may move the packet,
187 so reassign mess from daemon->packet. Also, the size
188 sent includes the IP and UDP headers, hence the magic "-28" */
189 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
191 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
193 if (size
> DHCP_PACKET_MAX
)
194 size
= DHCP_PACKET_MAX
;
195 else if (size
< sizeof(struct dhcp_packet
))
196 size
= sizeof(struct dhcp_packet
);
198 if (expand_buf(&daemon
->dhcp_packet
, size
))
200 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
201 real_end
= end
= ((unsigned char *)mess
) + size
;
205 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
206 it can affect the context-determination code. */
207 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
208 mess
->ciaddr
.s_addr
= 0;
210 /* search for device identity from CPEWAN devices, we pass this through to the script */
211 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT_OPT
, 5)))
213 unsigned int elen
, offset
, len
= option_len(opt
);
215 for (offset
= 0; offset
< (len
- 5); offset
+= elen
+ 5)
217 elen
= option_uint(opt
, offset
+ 4 , 1);
218 if (option_uint(opt
, offset
, 4) == BRDBAND_FORUM_IANA
)
220 unsigned char *x
= option_ptr(opt
, offset
+ 5);
221 unsigned char *y
= option_ptr(opt
, offset
+ elen
+ 5);
222 oui
= option_find1(x
, y
, 1, 1);
223 serial
= option_find1(x
, y
, 2, 1);
224 class = option_find1(x
, y
, 3, 1);
226 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
227 the gateway id back. Note that the device class is optional */
230 cpewan_id
.net
= "cpewan-id";
231 cpewan_id
.next
= netid
;
239 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
241 /* Any agent-id needs to be copied back out, verbatim, as the last option
242 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
243 get overwritten, then it will be shuffled back at the end of processing.
244 Note that the incoming options must not be overwritten here, so there has to
245 be enough free space at the end of the packet to copy the option. */
247 unsigned int total
= option_len(opt
) + 2;
248 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
249 if (last_opt
&& last_opt
< end
- total
)
253 memcpy(agent_id
, opt
, total
);
256 /* look for RFC3527 Link selection sub-option */
257 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
258 subnet_addr
= option_addr(sopt
);
260 /* look for RFC5107 server-identifier-override */
261 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
262 override
= option_addr(sopt
);
264 /* if a circuit-id or remote-is option is provided, exact-match to options. */
265 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
269 if (vendor
->match_type
== MATCH_CIRCUIT
)
270 search
= SUBOPT_CIRCUIT_ID
;
271 else if (vendor
->match_type
== MATCH_REMOTE
)
272 search
= SUBOPT_REMOTE_ID
;
273 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
274 search
= SUBOPT_SUBSCR_ID
;
278 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
279 vendor
->len
== option_len(sopt
) &&
280 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
282 vendor
->netid
.next
= netid
;
283 netid
= &vendor
->netid
;
288 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
289 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
290 subnet_addr
= option_addr(opt
);
292 /* If there is no client identifier option, use the hardware address */
293 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
295 clid_len
= option_len(opt
);
296 clid
= option_ptr(opt
, 0);
299 /* do we have a lease in store? */
300 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
302 /* If this request is missing a clid, but we've seen one before,
303 use it again for option matching etc. */
304 if (lease
&& !clid
&& lease
->clid
)
306 clid_len
= lease
->clid_len
;
310 /* find mac to use for logging and hashing */
311 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
314 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
315 if (mac
->hwaddr_len
== mess
->hlen
&&
316 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
317 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
319 mac
->netid
.next
= netid
;
323 /* Determine network for this packet. Our caller will have already linked all the
324 contexts which match the addresses of the receiving interface but if the
325 machine has an address already, or came via a relay, or we have a subnet selector,
326 we search again. If we don't have have a giaddr or explicit subnet selector,
327 use the ciaddr. This is necessary because a machine which got a lease via a
328 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
329 from the physical network, continue using that to allow correct DHCPNAK generation later. */
330 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
332 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
336 if (subnet_addr
.s_addr
)
341 else if (mess
->giaddr
.s_addr
)
348 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
350 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
351 if (context_tmp
->netmask
.s_addr
&&
352 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
353 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
355 context_new
= context
;
361 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
362 if (context_tmp
->netmask
.s_addr
&&
363 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
364 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
366 context_tmp
->current
= context_new
;
367 context_new
= context_tmp
;
370 if (context_new
|| force
)
371 context
= context_new
;
377 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
378 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
379 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
383 /* keep _a_ local address available. */
384 fallback
= context
->local
;
386 if (daemon
->options
& OPT_LOG_OPTS
)
388 struct dhcp_context
*context_tmp
;
389 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
391 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
392 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
393 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP subnet: %s/%s"),
394 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
396 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
397 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
401 mess
->op
= BOOTREPLY
;
403 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
404 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
406 /* set "known" tag for known hosts */
409 known_id
.net
= "known";
410 known_id
.next
= netid
;
414 if (mess_type
== 0 && !pxe
)
417 struct dhcp_netid id
, bootp_id
;
418 struct in_addr
*logaddr
= NULL
;
420 /* must have a MAC addr for bootp */
421 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
424 if (have_config(config
, CONFIG_DISABLE
))
425 message
= _("disabled");
427 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
429 if (have_config(config
, CONFIG_NAME
))
431 hostname
= config
->hostname
;
432 domain
= config
->domain
;
437 struct dhcp_netid_list
*list
;
439 for (list
= config
->netid
; list
; list
= list
->next
)
441 list
->list
->next
= netid
;
446 /* Match incoming filename field as a netid. */
449 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
450 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
451 id
.net
= (char *)daemon
->dhcp_buff2
;
456 /* Add "bootp" as a tag to allow different options, address ranges etc
458 bootp_id
.net
= "bootp";
459 bootp_id
.next
= netid
;
462 tagif_netid
= run_tag_if(netid
);
464 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
465 if (match_netid(id_list
->list
, tagif_netid
, 0))
466 message
= _("ignored");
472 if (have_config(config
, CONFIG_ADDR
))
475 logaddr
= &config
->addr
;
476 mess
->yiaddr
= config
->addr
;
477 if ((lease
= lease_find_by_addr(config
->addr
)) &&
478 (lease
->hwaddr_len
!= mess
->hlen
||
479 lease
->hwaddr_type
!= mess
->htype
||
480 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
481 message
= _("address in use");
485 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
486 !address_available(context
, lease
->addr
, tagif_netid
))
490 /* lease exists, wrong network. */
491 lease_prune(lease
, now
);
494 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, tagif_netid
, now
))
495 message
= _("no address available");
498 mess
->yiaddr
= lease
->addr
;
501 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
502 message
= _("wrong network");
503 else if (context
->netid
.net
)
505 context
->netid
.next
= netid
;
506 netid
= &context
->netid
;
507 tagif_netid
= run_tag_if(netid
);
510 if (!message
&& !nailed
)
512 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
513 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
516 message
= _("no address configured");
521 (!(lease
= lease_allocate(mess
->yiaddr
))))
522 message
= _("no leases left");
526 logaddr
= &mess
->yiaddr
;
528 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0);
530 lease_set_hostname(lease
, hostname
, 1);
531 /* infinite lease unless nailed in dhcp-host line. */
532 lease_set_expires(lease
,
533 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
535 lease_set_interface(lease
, int_index
);
537 clear_packet(mess
, end
);
538 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
539 domain
, tagif_netid
, subnet_addr
, 0, 0, 0, NULL
, 0);
543 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
, mess
->xid
);
545 return message
? 0 : dhcp_packet_size(mess
, tagif_netid
, agent_id
, real_end
);
548 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
550 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
551 int len
= option_len(opt
);
552 char *pq
= daemon
->dhcp_buff
;
553 unsigned char *pp
, *op
= option_ptr(opt
, 0);
560 /* Always force update, since the client has no way to do it itself. */
561 if (!(fqdn_flags
& 0x01))
567 if (fqdn_flags
& 0x04)
568 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
570 memcpy(pq
, op
+1, *op
);
578 if (len
> 0 && op
[len
-1] == 0)
583 if (pq
!= daemon
->dhcp_buff
)
588 if (legal_hostname(daemon
->dhcp_buff
))
589 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
591 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
593 int len
= option_len(opt
);
594 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
595 /* Microsoft clients are broken, and need zero-terminated strings
596 in options. We detect this state here, and do the same in
597 any options we send */
598 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
601 daemon
->dhcp_buff
[len
] = 0;
602 if (legal_hostname(daemon
->dhcp_buff
))
603 client_hostname
= daemon
->dhcp_buff
;
606 if (client_hostname
&& daemon
->options
& OPT_LOG_OPTS
)
607 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
609 if (have_config(config
, CONFIG_NAME
))
611 hostname
= config
->hostname
;
612 domain
= config
->domain
;
614 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
615 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
616 offer_hostname
= hostname
;
618 else if (client_hostname
)
620 domain
= strip_hostname(client_hostname
);
622 if (strlen(client_hostname
) != 0)
624 hostname
= client_hostname
;
627 /* Search again now we have a hostname.
628 Only accept configs without CLID and HWADDR here, (they won't match)
629 to avoid impersonation by name. */
630 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
631 mess
->chaddr
, mess
->hlen
,
632 mess
->htype
, hostname
);
633 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
636 /* set "known" tag for known hosts */
637 known_id
.net
= "known";
638 known_id
.next
= netid
;
647 struct dhcp_netid_list
*list
;
649 for (list
= config
->netid
; list
; list
= list
->next
)
651 list
->list
->next
= netid
;
656 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
657 Otherwise assume the option is an array, and look for a matching element.
658 If no data given, existance of the option is enough. This code handles
659 rfc3925 V-I classes too. */
660 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
662 unsigned int len
, elen
, match
= 0;
665 if (o
->flags
& DHOPT_RFC3925
)
667 if (!(opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT
, 5)))
670 for (offset
= 0; offset
< (option_len(opt
) - 5u); offset
+= len
+ 5)
672 len
= option_uint(opt
, offset
+ 4 , 1);
673 /* Need to take care that bad data can't run us off the end of the packet */
674 if ((offset
+ len
+ 5 <= (option_len(opt
))) &&
675 (option_uint(opt
, offset
, 4) == (unsigned int)o
->u
.encap
))
676 for (o2
= offset
+ 5; o2
< offset
+ len
+ 5; o2
+= elen
+ 1)
678 elen
= option_uint(opt
, o2
, 1);
679 if ((o2
+ elen
+ 1 <= option_len(opt
)) &&
680 (match
= match_bytes(o
, option_ptr(opt
, o2
+ 1), elen
)))
689 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)))
692 match
= match_bytes(o
, option_ptr(opt
, 0), option_len(opt
));
697 o
->netid
->next
= netid
;
702 /* user-class options are, according to RFC3004, supposed to contain
703 a set of counted strings. Here we check that this is so (by seeing
704 if the counts are consistent with the overall option length) and if
705 so zero the counts so that we don't get spurious matches between
706 the vendor string and the counts. If the lengths don't add up, we
707 assume that the option is a single string and non RFC3004 compliant
708 and just do the substring match. dhclient provides these broken options.
709 The code, later, which sends user-class data to the lease-change script
710 relies on the transformation done here.
713 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
715 unsigned char *ucp
= option_ptr(opt
, 0);
717 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
718 if (j
== option_len(opt
))
719 for (j
= 0; j
< option_len(opt
); j
= tmp
)
721 tmp
= j
+ ucp
[j
] + 1;
726 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
730 if (vendor
->match_type
== MATCH_VENDOR
)
731 mopt
= OPTION_VENDOR_ID
;
732 else if (vendor
->match_type
== MATCH_USER
)
733 mopt
= OPTION_USER_CLASS
;
737 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
740 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
741 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
743 vendor
->netid
.next
= netid
;
744 netid
= &vendor
->netid
;
750 /* mark vendor-encapsulated options which match the client-supplied vendor class,
751 save client-supplied vendor class */
752 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
754 memcpy(daemon
->dhcp_buff3
, option_ptr(opt
, 0), option_len(opt
));
755 vendor_class_len
= option_len(opt
);
757 match_vendor_opts(opt
, daemon
->dhcp_opts
);
759 if (daemon
->options
& OPT_LOG_OPTS
)
761 if (sanitise(opt
, daemon
->namebuff
))
762 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
763 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
764 my_syslog(MS_DHCP
| LOG_INFO
, _("%u user class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
767 tagif_netid
= run_tag_if(netid
);
769 /* if all the netids in the ignore list are present, ignore this client */
770 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
771 if (match_netid(id_list
->list
, tagif_netid
, 0))
774 /* If configured, we can override the server-id to be the address of the relay,
775 so that all traffic goes via the relay and can pick up agent-id info. This can be
776 configured for all relays, or by address. */
777 if (daemon
->override
&& mess
->giaddr
.s_addr
!= 0 && override
.s_addr
== 0)
779 if (!daemon
->override_relays
)
780 override
= mess
->giaddr
;
784 for (l
= daemon
->override_relays
; l
; l
= l
->next
)
785 if (l
->addr
.s_addr
== mess
->giaddr
.s_addr
)
788 override
= mess
->giaddr
;
792 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
793 if (have_config(config
, CONFIG_NOCLID
))
796 /* Check if client is PXE client. */
797 if (daemon
->enable_pxe
&&
798 (opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
799 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
801 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
803 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
807 /* Check if this is really a PXE bootserver request, and handle specially if so. */
808 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
809 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
810 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
812 struct pxe_service
*service
;
813 int type
= option_uint(opt
, 0, 2);
814 int layer
= option_uint(opt
, 2, 2);
815 unsigned char save71
[4];
816 struct dhcp_opt opt71
;
823 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
827 memcpy(save71
, option_ptr(opt
, 0), 4);
829 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
830 if (service
->type
== type
)
833 if (!service
|| !service
->basename
)
836 clear_packet(mess
, end
);
838 mess
->yiaddr
= mess
->ciaddr
;
839 mess
->ciaddr
.s_addr
= 0;
840 if (service
->server
.s_addr
!= 0)
841 mess
->siaddr
= service
->server
;
843 mess
->siaddr
= context
->local
;
845 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
846 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
847 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
848 pxe_misc(mess
, end
, uuid
);
850 prune_vendor_opts(tagif_netid
);
852 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
854 opt71
.flags
= DHOPT_VENDOR_MATCH
;
856 opt71
.next
= daemon
->dhcp_opts
;
857 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
859 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, mess
->xid
);
860 return dhcp_packet_size(mess
, tagif_netid
, agent_id
, real_end
);
863 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
865 pxearch
= option_uint(opt
, 0, 2);
867 /* proxy DHCP here. */
868 if ((mess_type
== DHCPDISCOVER
|| (pxe
&& mess_type
== DHCPREQUEST
)) &&
869 (context
->flags
& CONTEXT_PROXY
))
871 struct dhcp_boot
*boot
= find_boot(tagif_netid
);
873 mess
->yiaddr
.s_addr
= 0;
874 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
876 mess
->ciaddr
.s_addr
= 0;
877 mess
->flags
|= htons(0x8000); /* broadcast */
880 clear_packet(mess
, end
);
882 /* Provide the bootfile here, for gPXE, and in case we have no menu items
883 and set discovery_control = 8 */
886 if (boot
->next_server
.s_addr
)
887 mess
->siaddr
= boot
->next_server
;
890 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
893 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
894 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
895 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
896 pxe_misc(mess
, end
, uuid
);
897 prune_vendor_opts(tagif_netid
);
898 do_encap_opts(pxe_opts(pxearch
, tagif_netid
, context
->local
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
900 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, ignore
? "proxy-ignored" : "proxy", mess
->xid
);
901 return ignore
? 0 : dhcp_packet_size(mess
, tagif_netid
, agent_id
, real_end
);
906 /* if we're just a proxy server, go no further */
907 if ((context
->flags
& CONTEXT_PROXY
) || pxe
)
910 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
912 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
913 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
914 req_options
[option_len(opt
)] = OPTION_END
;
920 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
921 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
924 /* sanitise any message. Paranoid? Moi? */
925 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
927 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
930 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
, mess
->xid
);
932 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
933 lease_prune(lease
, now
);
935 if (have_config(config
, CONFIG_ADDR
) &&
936 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
938 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
939 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
940 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
941 config
->flags
|= CONFIG_DECLINED
;
942 config
->decline_time
= now
;
945 /* make sure this host gets a different address next time. */
946 for (; context
; context
= context
->current
)
947 context
->addr_epoch
++;
952 if (!(context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
)) ||
953 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
954 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
957 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
958 lease_prune(lease
, now
);
960 message
= _("unknown lease");
962 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
967 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
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
, message
, mess
->xid
);
1028 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1031 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1033 if (context
->netid
.net
)
1035 context
->netid
.next
= netid
;
1036 netid
= &context
->netid
;
1037 tagif_netid
= run_tag_if(netid
);
1040 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1041 clear_packet(mess
, end
);
1042 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
1043 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1044 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1045 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1046 if (time
!= 0xffffffff)
1048 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
1049 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
1051 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
1052 domain
, tagif_netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
);
1054 return dhcp_packet_size(mess
, tagif_netid
, agent_id
, real_end
);
1057 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1059 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
1061 /* SELECTING or INIT_REBOOT */
1062 mess
->yiaddr
= option_addr(opt
);
1064 /* send vendor and user class info for new or recreated lease */
1067 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
1072 if (override
.s_addr
!= 0)
1074 if (option_addr(opt
).s_addr
!= override
.s_addr
)
1079 for (; context
; context
= context
->current
)
1080 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
1085 /* In auth mode, a REQUEST sent to the wrong server
1086 should be faulted, so that the client establishes
1087 communication with us, otherwise, silently ignore. */
1088 if (!(daemon
->options
& OPT_AUTHORITATIVE
))
1090 message
= _("wrong server-ID");
1094 /* If a lease exists for this host and another address, squash it. */
1095 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1097 lease_prune(lease
, now
);
1104 if (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
))
1107 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1108 message
= _("wrong address");
1113 /* RENEWING or REBINDING */
1114 /* Check existing lease for this address.
1115 We allow it to be missing if dhcp-authoritative mode
1116 as long as we can allocate the lease now - checked below.
1117 This makes for a smooth recovery from a lost lease DB */
1118 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1119 (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
)))
1121 message
= _("lease not found");
1122 /* ensure we broadcast NAK */
1126 /* desynchronise renewals */
1128 mess
->yiaddr
= mess
->ciaddr
;
1131 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1135 struct dhcp_config
*addr_config
;
1136 struct dhcp_context
*tmp
= NULL
;
1138 if (have_config(config
, CONFIG_ADDR
))
1139 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1140 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1143 if (!(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1145 /* If a machine moves networks whilst it has a lease, we catch that here. */
1146 message
= _("wrong network");
1147 /* ensure we broadcast NAK */
1151 /* Check for renewal of a lease which is outside the allowed range. */
1152 else if (!address_available(context
, mess
->yiaddr
, tagif_netid
) &&
1153 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1154 message
= _("address not available");
1156 /* Check if a new static address has been configured. Be very sure that
1157 when the client does DISCOVER, it will get the static address, otherwise
1158 an endless protocol loop will ensue. */
1159 else if (!tmp
&& !selecting
&&
1160 have_config(config
, CONFIG_ADDR
) &&
1161 (!have_config(config
, CONFIG_DECLINED
) ||
1162 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1163 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1164 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1165 message
= _("static lease available");
1167 /* Check to see if the address is reserved as a static address for another host */
1168 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1169 message
= _("address reserved");
1171 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1173 /* If a host is configured with more than one MAC address, it's OK to 'nix
1174 a lease from one of it's MACs to give the address to another. */
1175 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1177 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1178 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1179 inet_ntoa(ltmp
->addr
));
1183 message
= _("address in use");
1189 message
= _("no unique-id");
1193 if ((lease
= lease_allocate(mess
->yiaddr
)))
1196 message
= _("no leases left");
1203 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1205 mess
->yiaddr
.s_addr
= 0;
1206 clear_packet(mess
, end
);
1207 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1208 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1209 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1210 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1211 a distant subnet which unicast a REQ to us won't work. */
1212 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1213 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1215 mess
->flags
|= htons(0x8000); /* broadcast */
1216 mess
->ciaddr
.s_addr
= 0;
1221 if (context
->netid
.net
)
1223 context
->netid
.next
= netid
;
1224 netid
= &context
->netid
;
1225 tagif_netid
= run_tag_if(netid
);
1229 if (do_classes
&& daemon
->lease_change_command
)
1231 struct dhcp_netid
*n
;
1233 if (mess
->giaddr
.s_addr
)
1234 lease
->giaddr
= mess
->giaddr
;
1237 free(lease
->extradata
);
1238 lease
->extradata_size
= lease
->extradata_len
= 0;
1240 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_VENDOR_ID
, 1));
1241 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_HOSTNAME
, 1));
1242 add_extradata_opt(lease
, oui
);
1243 add_extradata_opt(lease
, serial
);
1244 add_extradata_opt(lease
, class);
1246 /* space-concat tag set */
1248 add_extradata_opt(lease
, NULL
);
1250 for (n
= tagif_netid
; n
; n
= n
->next
)
1251 add_extradata_data(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
1253 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1255 int len
= option_len(opt
);
1256 unsigned char *ucp
= option_ptr(opt
, 0);
1257 /* If the user-class option started as counted strings, the first byte will be zero. */
1258 if (len
!= 0 && ucp
[0] == 0)
1260 add_extradata_data(lease
, ucp
, len
, 0);
1265 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1267 domain
= get_domain(mess
->yiaddr
);
1268 hostname
= client_hostname
;
1272 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1273 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
);
1275 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1278 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1279 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1285 /* Last ditch, if configured, generate hostname from mac address */
1286 if (!hostname
&& emac_len
!= 0)
1288 for (id_list
= daemon
->dhcp_gen_names
; id_list
; id_list
= id_list
->next
)
1289 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1295 hostname
= daemon
->dhcp_buff
;
1296 /* buffer is 256 bytes, 3 bytes per octet */
1297 for (i
= 0; (i
< emac_len
) && (i
< 80); i
++)
1298 hostname
+= sprintf(hostname
, "%.2x%s", emac
[i
], (i
== emac_len
- 1) ? "" : "-");
1299 hostname
= daemon
->dhcp_buff
;
1304 lease_set_hostname(lease
, hostname
, hostname_auth
);
1306 lease_set_expires(lease
, time
, now
);
1307 lease_set_interface(lease
, int_index
);
1309 if (override
.s_addr
!= 0)
1310 lease
->override
= override
;
1312 override
= lease
->override
;
1314 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1316 clear_packet(mess
, end
);
1317 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1318 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1319 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1320 if (time
!= 0xffffffff)
1322 while (fuzz
> (time
/16))
1324 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
1325 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
1327 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1328 domain
, tagif_netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
);
1331 return dhcp_packet_size(mess
, tagif_netid
, agent_id
, real_end
);
1334 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1335 message
= _("ignored");
1337 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1339 if (message
|| mess
->ciaddr
.s_addr
== 0)
1342 /* For DHCPINFORM only, cope without a valid context */
1343 context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
);
1345 /* Find a least based on IP address if we didn't
1346 get one from MAC address/client-d */
1348 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1350 hostname
= lease
->hostname
;
1352 if (!hostname
&& (hostname
= host_from_dns(mess
->ciaddr
)))
1353 domain
= get_domain(mess
->ciaddr
);
1355 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1357 if (context
&& context
->netid
.net
)
1359 context
->netid
.next
= netid
;
1360 netid
= &context
->netid
;
1361 tagif_netid
= run_tag_if(netid
);
1366 if (override
.s_addr
!= 0)
1367 lease
->override
= override
;
1369 override
= lease
->override
;
1372 clear_packet(mess
, end
);
1373 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1374 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1378 if (lease
->expires
== 0)
1381 time
= (unsigned int)difftime(lease
->expires
, now
);
1382 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1383 lease_set_interface(lease
, int_index
);
1386 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1387 domain
, tagif_netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
);
1389 *is_inform
= 1; /* handle reply differently */
1390 return dhcp_packet_size(mess
, tagif_netid
, agent_id
, real_end
);
1396 static int match_bytes(struct dhcp_opt
*o
, unsigned char *p
, int len
)
1406 if (o
->flags
& DHOPT_HEX
)
1408 if (memcmp_masked(o
->val
, p
, o
->len
, o
->u
.wildcard_mask
))
1412 for (i
= 0; i
<= (len
- o
->len
); )
1414 if (memcmp(o
->val
, p
+ i
, o
->len
) == 0)
1417 if (o
->flags
& DHOPT_STRING
)
1427 /* find a good value to use as MAC address for logging and address-allocation hashing.
1428 This is normally just the chaddr field from the DHCP packet,
1429 but eg Firewire will have hlen == 0 and use the client-id instead.
1430 This could be anything, but will normally be EUI64 for Firewire.
1431 We assume that if the first byte of the client-id equals the htype byte
1432 then the client-id is using the usual encoding and use the rest of the
1433 client-id: if not we can use the whole client-id. This should give
1434 sane MAC address logs. */
1435 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1436 int clid_len
, unsigned char *clid
, int *len_out
)
1438 if (hwlen
== 0 && clid
&& clid_len
> 3)
1440 if (clid
[0] == hwtype
)
1442 *len_out
= clid_len
- 1 ;
1446 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1447 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1449 *len_out
= clid_len
- 1 ;
1454 *len_out
= clid_len
;
1462 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1464 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1468 unsigned int req_time
= option_uint(opt
, 0, 4);
1469 if (req_time
< 120 )
1470 req_time
= 120; /* sanity */
1471 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1478 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1480 if (override
.s_addr
!= 0)
1483 return context
->local
;
1488 static int sanitise(unsigned char *opt
, char *buf
)
1498 p
= option_ptr(opt
, 0);
1500 for (i
= option_len(opt
); i
> 0; i
--)
1503 if (isprint((int)c
))
1506 *buf
= 0; /* add terminator */
1512 static void add_extradata_data(struct dhcp_lease
*lease
, unsigned char *data
, size_t len
, int delim
)
1514 if ((lease
->extradata_size
- lease
->extradata_len
) < (len
+ 1))
1516 size_t newsz
= lease
->extradata_len
+ len
+ 100;
1517 unsigned char *new = whine_malloc(newsz
);
1522 if (lease
->extradata
)
1524 memcpy(new, lease
->extradata
, lease
->extradata_len
);
1525 free(lease
->extradata
);
1528 lease
->extradata
= new;
1529 lease
->extradata_size
= newsz
;
1533 memcpy(lease
->extradata
+ lease
->extradata_len
, data
, len
);
1534 lease
->extradata
[lease
->extradata_len
+ len
] = delim
;
1535 lease
->extradata_len
+= len
+ 1;
1538 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
)
1541 add_extradata_data(lease
, NULL
, 0, 0);
1544 size_t i
, len
= option_len(opt
);
1545 unsigned char *ucp
= option_ptr(opt
, 0);
1547 /* check for embeded NULLs */
1548 for (i
= 0; i
< len
; i
++)
1555 add_extradata_data(lease
, ucp
, len
, 0);
1560 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1561 int mac_len
, char *interface
, char *string
, u32 xid
)
1565 /* addr may be misaligned */
1567 memcpy(&a
, addr
, sizeof(a
));
1569 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1571 if(daemon
->options
& OPT_LOG_OPTS
)
1572 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s",
1576 addr
? inet_ntoa(a
) : "",
1579 string
? string
: "");
1581 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s",
1584 addr
? inet_ntoa(a
) : "",
1587 string
? string
: "");
1590 static void log_options(unsigned char *start
, u32 xid
)
1592 while (*start
!= OPTION_END
)
1594 int is_ip
, is_name
, i
;
1595 char *text
= option_string(start
[0], &is_ip
, &is_name
);
1596 unsigned char trunc
= option_len(start
);
1599 for (daemon
->namebuff
[0]= 0, i
= 0; i
<= trunc
- INADDRSZ
; i
+= INADDRSZ
)
1602 strncat(daemon
->namebuff
, ", ", 256 - strlen(daemon
->namebuff
));
1603 strncat(daemon
->namebuff
, inet_ntoa(option_addr_arr(start
, i
)), 256 - strlen(daemon
->namebuff
));
1605 else if (!is_name
|| !sanitise(start
, daemon
->namebuff
))
1609 print_mac(daemon
->namebuff
, option_ptr(start
, 0), trunc
);
1612 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d%s%s%s%s%s",
1613 ntohl(xid
), option_len(start
), start
[0],
1614 text
? ":" : "", text
? text
: "",
1615 trunc
== 0 ? "" : " ",
1616 trunc
== 0 ? "" : daemon
->namebuff
,
1617 trunc
== option_len(start
) ? "" : "...");
1618 start
+= start
[1] + 2;
1622 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1628 else if (*p
== OPTION_END
)
1629 return opt
== OPTION_END
? p
: NULL
;
1630 else if (*p
== OPTION_PAD
)
1636 return NULL
; /* malformed packet */
1637 opt_len
= option_len(p
);
1638 if (p
> end
- (2 + opt_len
))
1639 return NULL
; /* malformed packet */
1640 if (*p
== opt
&& opt_len
>= minsize
)
1647 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1649 unsigned char *ret
, *overload
;
1651 /* skip over DHCP cookie; */
1652 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1655 /* look for overload option. */
1656 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1659 /* Can we look in filename area ? */
1660 if ((overload
[2] & 1) &&
1661 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1664 /* finally try sname area */
1665 if ((overload
[2] & 2) &&
1666 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1672 static struct in_addr
option_addr_arr(unsigned char *opt
, int offset
)
1674 /* this worries about unaligned data in the option. */
1675 /* struct in_addr is network byte order */
1678 memcpy(&ret
, option_ptr(opt
, offset
), INADDRSZ
);
1683 static struct in_addr
option_addr(unsigned char *opt
)
1685 return option_addr_arr(opt
, 0);
1688 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1690 /* this worries about unaligned data and byte order */
1691 unsigned int ret
= 0;
1693 unsigned char *p
= option_ptr(opt
, offset
);
1695 for (i
= 0; i
< size
; i
++)
1696 ret
= (ret
<< 8) | *p
++;
1701 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1704 start
+= start
[1] + 2;
1708 /* only for use when building packet: doesn't check for bad data. */
1709 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1711 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1715 if (*p
== OPTION_OVERLOAD
)
1722 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
,
1723 unsigned char *agent_id
, unsigned char *real_end
)
1725 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1726 unsigned char *overload
;
1728 struct dhcp_netid_list
*id_list
;
1729 struct dhcp_netid
*n
;
1731 /* move agent_id back down to the end of the packet */
1734 memmove(p
, agent_id
, real_end
- agent_id
);
1735 p
+= real_end
- agent_id
;
1736 memset(p
, 0, real_end
- p
); /* in case of overlap */
1739 /* We do logging too */
1740 if (netid
&& (daemon
->options
& OPT_LOG_OPTS
))
1742 char *s
= daemon
->namebuff
;
1743 for (*s
= 0; netid
; netid
= netid
->next
)
1746 for (n
= netid
->next
; n
; n
= n
->next
)
1747 if (strcmp(netid
->net
, n
->net
) == 0)
1752 strncat (s
, netid
->net
, (MAXDNAME
-1) - strlen(s
));
1754 strncat (s
, ", ", (MAXDNAME
-1) - strlen(s
));
1757 my_syslog(MS_DHCP
| LOG_INFO
, _("%u tags: %s"), ntohl(mess
->xid
), s
);
1760 /* add END options to the regions. */
1761 overload
= find_overload(mess
);
1763 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1765 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1766 if (daemon
->options
& OPT_LOG_OPTS
)
1767 log_options(mess
->file
, mess
->xid
);
1769 else if ((daemon
->options
& OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1770 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1772 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1774 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1775 if (daemon
->options
& OPT_LOG_OPTS
)
1776 log_options(mess
->sname
, mess
->xid
);
1778 else if ((daemon
->options
& OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1779 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1784 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
1785 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
1788 mess
->flags
|= htons(0x8000); /* force broadcast */
1790 if (daemon
->options
& OPT_LOG_OPTS
)
1792 if (mess
->siaddr
.s_addr
!= 0)
1793 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1795 if ((mess
->flags
& htons(0x8000)) && mess
->ciaddr
.s_addr
== 0)
1796 my_syslog(MS_DHCP
| LOG_INFO
, _("%u broadcast response"), ntohl(mess
->xid
));
1798 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1801 ret
= (size_t)(p
- (unsigned char *)mess
);
1803 if (ret
< MIN_PACKETSZ
)
1809 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1811 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1813 if (p
+ len
+ 3 >= end
)
1814 /* not enough space in options area, try and use overload, if poss */
1816 unsigned char *overload
;
1818 if (!(overload
= find_overload(mess
)) &&
1819 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1821 /* attempt to overload fname and sname areas, we've reserved space for the
1822 overflow option previuously. */
1824 *(p
++) = OPTION_OVERLOAD
;
1830 /* using filename field ? */
1833 if (mess
->file
[0] == 0)
1836 if (overload
[2] & 1)
1838 p
= dhcp_skip_opts(mess
->file
);
1839 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1845 /* try to bring sname into play (it may be already) */
1846 if (mess
->sname
[0] == 0)
1849 if (overload
[2] & 2)
1851 p
= dhcp_skip_opts(mess
->sname
);
1852 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1859 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1871 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1874 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1877 for (i
= 0; i
< len
; i
++)
1878 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1881 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1882 char *string
, int null_term
)
1885 size_t len
= strlen(string
);
1887 if (null_term
&& len
!= 255)
1890 if ((p
= free_space(mess
, end
, opt
, len
)))
1891 memcpy(p
, string
, len
);
1894 /* return length, note this only does the data part */
1895 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1899 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1904 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1907 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1908 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1910 /* zero means "self" (but not in vendorclass options.) */
1912 memcpy(p
, &context
->local
, INADDRSZ
);
1914 memcpy(p
, a
, INADDRSZ
);
1919 memcpy(p
, opt
->val
, len
);
1924 static int in_list(unsigned char *list
, int opt
)
1928 /* If no requested options, send everything, not nothing. */
1932 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1939 static struct dhcp_opt
*option_find2(struct dhcp_netid
*netid
, struct dhcp_opt
*opts
, int opt
)
1941 struct dhcp_opt
*tmp
;
1942 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
1943 if (tmp
->opt
== opt
&& !(tmp
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)))
1944 if (match_netid(tmp
->netid
, netid
, 0))
1947 /* No match, look for one without a netid */
1948 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
1949 if (tmp
->opt
== opt
&& !(tmp
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)))
1950 if (match_netid(tmp
->netid
, netid
, 1))
1956 /* mark vendor-encapsulated options which match the client-supplied or
1957 config-supplied vendor class */
1958 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1960 for (; dopt
; dopt
= dopt
->next
)
1962 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1963 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1966 if (dopt
->u
.vendor_class
)
1967 len
= strlen((char *)dopt
->u
.vendor_class
);
1968 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1969 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1971 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1978 static int do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1979 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1981 int len
, enc_len
, ret
= 0;
1982 struct dhcp_opt
*start
;
1985 /* find size in advance */
1986 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1987 if (opt
->flags
& flag
)
1989 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1991 if (enc_len
+ new <= 255)
1995 p
= free_space(mess
, end
, encap
, enc_len
);
1996 for (; start
&& start
!= opt
; start
= start
->next
)
1997 if (p
&& (start
->flags
& flag
))
1999 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
2000 *(p
++) = start
->opt
;
2010 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
2012 for (; start
; start
= start
->next
)
2013 if (start
->flags
& flag
)
2015 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
2016 *(p
++) = start
->opt
;
2026 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
2030 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
2031 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
2032 memcpy(p
, uuid
, 17);
2035 static int prune_vendor_opts(struct dhcp_netid
*netid
)
2038 struct dhcp_opt
*opt
;
2040 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
2041 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
2042 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
2044 if (!match_netid(opt
->netid
, netid
, 1))
2045 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
2046 else if (opt
->flags
& DHOPT_FORCE
)
2052 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
)
2056 unsigned char *p
, *q
;
2057 struct pxe_service
*service
;
2058 static struct dhcp_opt
*o
, *ret
;
2059 int i
, j
= NUM_OPTS
- 1;
2060 struct in_addr boot_server
;
2062 /* We pass back references to these, hence they are declared static */
2063 static unsigned char discovery_control
;
2064 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
2065 static struct dhcp_opt
*fake_opts
= NULL
;
2067 /* Disable multicast, since we don't support it, and broadcast
2068 unless we need it */
2069 discovery_control
= 3;
2071 ret
= daemon
->dhcp_opts
;
2073 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
2076 for (i
= 0; i
< NUM_OPTS
; i
++)
2078 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
2079 fake_opts
[i
].netid
= NULL
;
2080 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
2083 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2084 p
= (unsigned char *)daemon
->dhcp_buff
;
2085 q
= (unsigned char *)daemon
->dhcp_buff3
;
2087 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
2088 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
2090 size_t len
= strlen(service
->menu
);
2091 /* opt 43 max size is 255. encapsulated option has type and length
2092 bytes, so its max size is 253. */
2093 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
2095 *(p
++) = service
->type
>> 8;
2096 *(p
++) = service
->type
;
2098 memcpy(p
, service
->menu
, len
);
2105 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
2106 return daemon
->dhcp_opts
;
2109 boot_server
= service
->basename
? local
: service
->server
;
2111 if (boot_server
.s_addr
!= 0)
2113 if (q
- (unsigned char *)daemon
->dhcp_buff3
+ 3 + INADDRSZ
>= 253)
2116 /* Boot service with known address - give it */
2117 *(q
++) = service
->type
>> 8;
2118 *(q
++) = service
->type
;
2120 /* dest misaligned */
2121 memcpy(q
, &boot_server
.s_addr
, INADDRSZ
);
2124 else if (service
->type
!= 0)
2125 /* We don't know the server for a service type, so we'll
2126 allow the client to broadcast for it */
2127 discovery_control
= 2;
2130 /* if no prompt, wait forever if there's a choice */
2131 fake_prompt
[0] = (i
> 1) ? 255 : 0;
2134 discovery_control
= 8; /* no menu - just use use mess->filename */
2137 ret
= &fake_opts
[j
--];
2138 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
2139 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
2140 ret
->opt
= SUBOPT_PXE_MENU
;
2142 if (q
- (unsigned char *)daemon
->dhcp_buff3
!= 0)
2144 ret
= &fake_opts
[j
--];
2145 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff3
;
2146 ret
->val
= (unsigned char *)daemon
->dhcp_buff3
;
2147 ret
->opt
= SUBOPT_PXE_SERVERS
;
2151 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
2152 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
2157 ret
= &fake_opts
[j
--];
2158 ret
->len
= sizeof(fake_prompt
);
2159 ret
->val
= fake_prompt
;
2160 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
2163 ret
= &fake_opts
[j
--];
2165 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
2166 ret
->val
= &discovery_control
;
2171 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
2173 memset(mess
->sname
, 0, sizeof(mess
->sname
));
2174 memset(mess
->file
, 0, sizeof(mess
->file
));
2175 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
2176 mess
->siaddr
.s_addr
= 0;
2179 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
2181 struct dhcp_boot
*boot
;
2183 /* decide which dhcp-boot option we're using */
2184 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2185 if (match_netid(boot
->netid
, netid
, 0))
2188 /* No match, look for one without a netid */
2189 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2190 if (match_netid(boot
->netid
, netid
, 1))
2196 static void do_options(struct dhcp_context
*context
,
2197 struct dhcp_packet
*mess
,
2199 unsigned char *req_options
,
2201 char *domain
, char *config_domain
,
2202 struct dhcp_netid
*netid
,
2203 struct in_addr subnet_addr
,
2204 unsigned char fqdn_flags
,
2205 int null_term
, int pxe_arch
,
2206 unsigned char *uuid
,
2207 int vendor_class_len
)
2209 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2210 struct dhcp_boot
*boot
;
2212 int i
, len
, force_encap
= 0;
2213 unsigned char f0
= 0, s0
= 0;
2214 int done_file
= 0, done_server
= 0;
2215 int done_vendor_class
= 0;
2217 if (config_domain
&& (!domain
|| !hostname_isequal(domain
, config_domain
)))
2218 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), config_domain
, hostname
);
2221 if ((daemon
->options
& OPT_LOG_OPTS
) && req_options
)
2223 char *q
= daemon
->namebuff
;
2224 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2226 char *s
= option_string(req_options
[i
], NULL
, NULL
);
2227 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2232 req_options
[i
+1] == OPTION_END
? "" : ", ");
2233 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2235 q
= daemon
->namebuff
;
2236 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2242 mess
->siaddr
= context
->local
;
2244 /* See if we can send the boot stuff as options.
2245 To do this we need a requested option list, BOOTP
2246 and very old DHCP clients won't have this, we also
2247 provide an manual option to disable it.
2248 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2249 names, so we always send those. */
2250 if ((boot
= find_boot(netid
)))
2254 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
2256 in_list(req_options
, OPTION_SNAME
))
2257 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2259 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2264 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
2266 in_list(req_options
, OPTION_FILENAME
))
2267 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2269 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2272 if (boot
->next_server
.s_addr
)
2273 mess
->siaddr
= boot
->next_server
;
2276 /* Use the values of the relevant options if no dhcp-boot given and
2277 they're not explicitly asked for as options. OPTION_END is used
2278 as an internal way to specify siaddr without using dhcp-boot, for use in
2281 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
2282 (opt
= option_find2(netid
, config_opts
, OPTION_FILENAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2284 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2288 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2289 (opt
= option_find2(netid
, config_opts
, OPTION_SNAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2291 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2295 if ((opt
= option_find2(netid
, config_opts
, OPTION_END
)))
2296 mess
->siaddr
.s_addr
= ((struct in_addr
*)opt
->val
)->s_addr
;
2299 /* We don't want to do option-overload for BOOTP, so make the file and sname
2300 fields look like they are in use, even when they aren't. This gets restored
2301 at the end of this function. */
2303 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
2307 s0
= mess
->sname
[0];
2311 /* At this point, if mess->sname or mess->file are zeroed, they are available
2312 for option overload, reserve space for the overload option. */
2313 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2316 /* rfc3011 says this doesn't need to be in the requested options list. */
2317 if (subnet_addr
.s_addr
)
2318 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2320 /* replies to DHCPINFORM may not have a valid context */
2323 if (!option_find2(netid
, config_opts
, OPTION_NETMASK
))
2324 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2326 /* May not have a "guessed" broadcast address if we got no packets via a relay
2327 from this net yet (ie just unicast renewals after a restart */
2328 if (context
->broadcast
.s_addr
&&
2329 !option_find2(netid
, config_opts
, OPTION_BROADCAST
))
2330 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2332 /* Same comments as broadcast apply, and also may not be able to get a sensible
2333 default when using subnet select. User must configure by steam in that case. */
2334 if (context
->router
.s_addr
&&
2335 in_list(req_options
, OPTION_ROUTER
) &&
2336 !option_find2(netid
, config_opts
, OPTION_ROUTER
))
2337 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2339 if (in_list(req_options
, OPTION_DNSSERVER
) &&
2340 !option_find2(netid
, config_opts
, OPTION_DNSSERVER
))
2341 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2344 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2345 !option_find2(netid
, config_opts
, OPTION_DOMAINNAME
))
2346 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2348 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2351 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2352 !option_find2(netid
, config_opts
, OPTION_HOSTNAME
))
2353 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2355 if (fqdn_flags
!= 0)
2357 len
= strlen(hostname
) + 3;
2359 if (fqdn_flags
& 0x04)
2365 len
+= strlen(domain
) + 1;
2367 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2369 *(p
++) = fqdn_flags
;
2373 if (fqdn_flags
& 0x04)
2375 p
= do_rfc1035_name(p
, hostname
);
2377 p
= do_rfc1035_name(p
, domain
);
2382 memcpy(p
, hostname
, strlen(hostname
));
2383 p
+= strlen(hostname
);
2387 memcpy(p
, domain
, strlen(domain
));
2388 p
+= strlen(domain
);
2397 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2399 int optno
= opt
->opt
;
2401 /* was it asked for, or are we sending it anyway? */
2402 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2405 /* prohibit some used-internally options */
2406 if (optno
== OPTION_CLIENT_FQDN
||
2407 optno
== OPTION_MAXMESSAGE
||
2408 optno
== OPTION_OVERLOAD
||
2409 optno
== OPTION_PAD
||
2410 optno
== OPTION_END
)
2413 if (optno
== OPTION_SNAME
&& done_server
)
2416 if (optno
== OPTION_FILENAME
&& done_file
)
2419 /* netids match and not encapsulated? */
2420 if (opt
!= option_find2(netid
, config_opts
, optno
))
2423 /* For the options we have default values on
2424 dhc-option=<optionno> means "don't include this option"
2425 not "include a zero-length option" */
2426 if (opt
->len
== 0 &&
2427 (optno
== OPTION_NETMASK
||
2428 optno
== OPTION_BROADCAST
||
2429 optno
== OPTION_ROUTER
||
2430 optno
== OPTION_DNSSERVER
||
2431 optno
== OPTION_DOMAINNAME
||
2432 optno
== OPTION_HOSTNAME
))
2435 /* vendor-class comes from elsewhere for PXE */
2436 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2439 /* always force null-term for filename and servername - buggy PXE again. */
2440 len
= do_opt(opt
, NULL
, context
,
2441 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2443 if ((p
= free_space(mess
, end
, optno
, len
)))
2445 do_opt(opt
, p
, context
,
2446 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2448 /* If we send a vendor-id, revisit which vendor-ops we consider
2449 it appropriate to send. */
2450 if (optno
== OPTION_VENDOR_ID
)
2452 match_vendor_opts(p
- 2, config_opts
);
2453 done_vendor_class
= 1;
2458 /* Now send options to be encapsulated in arbitrary options,
2459 eg dhcp-option=encap:172,17,.......
2460 Also hand vendor-identifying vendor-encapsulated options,
2461 dhcp-option = rfc3925-encap:13,17,.......
2462 The may be more that one "outer" to do, so group
2463 all the options which match each outer in turn. */
2464 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2465 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2467 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2471 if ((flags
= (opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_RFC3925
))))
2476 if (opt
->flags
& DHOPT_ENCAP_DONE
)
2479 for (len
= 0, o
= config_opts
; o
; o
= o
->next
)
2481 int outer
= flags
& DHOPT_ENCAPSULATE
? o
->u
.encap
: OPTION_VENDOR_IDENT_OPT
;
2483 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2485 if (!(o
->flags
& flags
) || opt
->u
.encap
!= o
->u
.encap
)
2488 o
->flags
|= DHOPT_ENCAP_DONE
;
2489 if (match_netid(o
->netid
, netid
, 1) &&
2490 ((o
->flags
& DHOPT_FORCE
) || in_list(req_options
, outer
)))
2492 o
->flags
|= DHOPT_ENCAP_MATCH
;
2494 len
+= do_opt(o
, NULL
, NULL
, 0) + 2;
2500 if (flags
& DHOPT_ENCAPSULATE
)
2501 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2503 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt
->u
.encap
);
2504 else if ((p
= free_space(mess
, end
, OPTION_VENDOR_IDENT_OPT
, len
+ 5)))
2506 int swap_ent
= htonl(opt
->u
.encap
);
2507 memcpy(p
, &swap_ent
, 4);
2510 for (o
= config_opts
; o
; o
= o
->next
)
2511 if (o
->flags
& DHOPT_ENCAP_MATCH
)
2513 len
= do_opt(o
, p
+ 2, NULL
, 0);
2523 force_encap
= prune_vendor_opts(netid
);
2525 if (context
&& pxe_arch
!= -1)
2527 pxe_misc(mess
, end
, uuid
);
2528 config_opts
= pxe_opts(pxe_arch
, netid
, context
->local
);
2531 if ((force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
)) &&
2532 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
) &&
2533 pxe_arch
== -1 && !done_vendor_class
&& vendor_class_len
!= 0 &&
2534 (p
= free_space(mess
, end
, OPTION_VENDOR_ID
, vendor_class_len
)))
2535 /* If we send vendor encapsulated options, and haven't already sent option 60,
2536 echo back the value we got from the client. */
2537 memcpy(p
, daemon
->dhcp_buff3
, vendor_class_len
);
2539 /* restore BOOTP anti-overload hack */
2540 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
2543 mess
->sname
[0] = s0
;