1 /* dnsmasq is Copyright (c) 2000-2009 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_END 255
59 #define SUBOPT_CIRCUIT_ID 1
60 #define SUBOPT_REMOTE_ID 2
61 #define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */
62 #define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */
63 #define SUBOPT_SERVER_OR 11 /* RFC 5107 */
65 #define SUBOPT_PXE_BOOT_ITEM 71 /* PXE standard */
66 #define SUBOPT_PXE_DISCOVERY 6
67 #define SUBOPT_PXE_SERVERS 8
68 #define SUBOPT_PXE_MENU 9
69 #define SUBOPT_PXE_MENU_PROMPT 10
71 #define DHCPDISCOVER 1
80 #define have_config(config, mask) ((config) && ((config)->flags & (mask)))
81 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
82 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
84 static int sanitise(unsigned char *opt
, char *buf
);
85 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
);
86 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
);
87 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
88 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
89 int opt
, char *string
, int null_term
);
90 static struct in_addr
option_addr(unsigned char *opt
);
91 static struct in_addr
option_addr_arr(unsigned char *opt
, int offset
);
92 static unsigned int option_uint(unsigned char *opt
, int i
, int size
);
93 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
94 int mac_len
, char *interface
, char *string
, u32 xid
);
95 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
96 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
97 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
,
98 unsigned char *agent_id
, unsigned char *real_end
);
99 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
100 static void do_options(struct dhcp_context
*context
,
101 struct dhcp_packet
*mess
,
102 unsigned char *real_end
,
103 unsigned char *req_options
,
105 char *domain
, char *config_domain
,
106 struct dhcp_netid
*netid
,
107 struct in_addr subnet_addr
,
108 unsigned char fqdn_flags
,
109 int null_term
, int pxearch
,
110 unsigned char *uuid
);
113 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
114 static void do_encap_opts(struct dhcp_opt
*opts
, int encap
, int flag
, struct dhcp_packet
*mess
, unsigned char *end
, int null_term
);
115 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
);
116 static int prune_vendor_opts(struct dhcp_netid
*netid
);
117 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
);
118 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
);
121 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
122 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
)
124 unsigned char *opt
, *clid
= NULL
;
125 struct dhcp_lease
*ltmp
, *lease
= NULL
;
126 struct dhcp_vendor
*vendor
;
127 struct dhcp_mac
*mac
;
128 struct dhcp_netid_list
*id_list
;
129 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0, pxearch
= -1;
130 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
131 unsigned char *end
= (unsigned char *)(mess
+ 1);
132 unsigned char *real_end
= (unsigned char *)(mess
+ 1);
133 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
, *domain
= NULL
;
134 int hostname_auth
= 0, borken_opt
= 0;
135 unsigned char *req_options
= NULL
;
136 char *message
= NULL
;
138 struct dhcp_config
*config
;
139 struct dhcp_netid
*netid
;
140 struct in_addr subnet_addr
, fallback
, override
;
141 unsigned short fuzz
= 0;
142 unsigned int mess_type
= 0;
143 unsigned char fqdn_flags
= 0;
144 unsigned char *agent_id
= NULL
, *uuid
= NULL
;
145 unsigned char *emac
= NULL
;
147 struct dhcp_netid known_id
, iface_id
;
149 unsigned char pxe_uuid
[17];
151 subnet_addr
.s_addr
= override
.s_addr
= 0;
153 /* set tag with name == interface */
154 iface_id
.net
= iface_name
;
155 iface_id
.next
= NULL
;
158 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
161 if (mess
->htype
== 0 && mess
->hlen
!= 0)
164 /* check for DHCP rather than BOOTP */
165 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
167 mess_type
= option_uint(opt
, 0, 1);
169 /* only insist on a cookie for DHCP. */
170 if (*((u32
*)&mess
->options
) != htonl(DHCP_COOKIE
))
173 /* two things to note here: expand_buf may move the packet,
174 so reassign mess from daemon->packet. Also, the size
175 sent includes the IP and UDP headers, hence the magic "-28" */
176 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
178 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
180 if (size
> DHCP_PACKET_MAX
)
181 size
= DHCP_PACKET_MAX
;
182 else if (size
< sizeof(struct dhcp_packet
))
183 size
= sizeof(struct dhcp_packet
);
185 if (expand_buf(&daemon
->dhcp_packet
, size
))
187 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
188 real_end
= end
= ((unsigned char *)mess
) + size
;
192 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
193 it can affect the context-determination code. */
194 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
195 mess
->ciaddr
.s_addr
= 0;
197 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
199 /* Any agent-id needs to be copied back out, verbatim, as the last option
200 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
201 get overwritten, then it will be shuffled back at the end of processing.
202 Note that the incoming options must not be overwritten here, so there has to
203 be enough free space at the end of the packet to copy the option. */
205 unsigned int total
= option_len(opt
) + 2;
206 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
207 if (last_opt
&& last_opt
< end
- total
)
211 memcpy(agent_id
, opt
, total
);
214 /* look for RFC3527 Link selection sub-option */
215 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
216 subnet_addr
= option_addr(sopt
);
218 /* look for RFC5107 server-identifier-override */
219 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
220 override
= option_addr(sopt
);
222 /* if a circuit-id or remote-is option is provided, exact-match to options. */
223 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
227 if (vendor
->match_type
== MATCH_CIRCUIT
)
228 search
= SUBOPT_CIRCUIT_ID
;
229 else if (vendor
->match_type
== MATCH_REMOTE
)
230 search
= SUBOPT_REMOTE_ID
;
231 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
232 search
= SUBOPT_SUBSCR_ID
;
236 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
237 vendor
->len
== option_len(sopt
) &&
238 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
240 vendor
->netid
.next
= netid
;
241 netid
= &vendor
->netid
;
247 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
248 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
249 subnet_addr
= option_addr(opt
);
251 /* If there is no client identifier option, use the hardware address */
252 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
254 clid_len
= option_len(opt
);
255 clid
= option_ptr(opt
, 0);
258 /* do we have a lease in store? */
259 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
261 /* If this request is missing a clid, but we've seen one before,
262 use it again for option matching etc. */
263 if (lease
&& !clid
&& lease
->clid
)
265 clid_len
= lease
->clid_len
;
269 /* find mac to use for logging and hashing */
270 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
273 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
274 if (mac
->hwaddr_len
== mess
->hlen
&&
275 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
276 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
278 mac
->netid
.next
= netid
;
282 /* Determine network for this packet. Our caller will have already linked all the
283 contexts which match the addresses of the receiving interface but if the
284 machine has an address already, or came via a relay, or we have a subnet selector,
285 we search again. If we don't have have a giaddr or explicit subnet selector,
286 use the ciaddr. This is necessary because a machine which got a lease via a
287 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
288 from the physical network, continue using that to allow correct DHCPNAK generation later. */
289 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
291 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
295 if (subnet_addr
.s_addr
)
300 else if (mess
->giaddr
.s_addr
)
307 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
309 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
310 if (context_tmp
->netmask
.s_addr
&&
311 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
312 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
314 context_new
= context
;
320 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
321 if (context_tmp
->netmask
.s_addr
&&
322 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
323 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
325 context_tmp
->current
= context_new
;
326 context_new
= context_tmp
;
329 if (context_new
|| force
)
330 context
= context_new
;
336 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
337 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
338 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
342 /* keep _a_ local address available. */
343 fallback
= context
->local
;
345 if (daemon
->options
& OPT_LOG_OPTS
)
347 struct dhcp_context
*context_tmp
;
348 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
350 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
351 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
352 my_syslog(MS_DHCP
| LOG_INFO
, _("%u Available DHCP subnet: %s/%s"),
353 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
355 my_syslog(MS_DHCP
| LOG_INFO
, _("%u Available DHCP range: %s -- %s"),
356 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
360 mess
->op
= BOOTREPLY
;
362 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
363 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
365 /* set "known" tag for known hosts */
368 known_id
.net
= "known";
369 known_id
.next
= netid
;
376 struct dhcp_netid id
, bootp_id
;
377 struct in_addr
*logaddr
= NULL
;
379 /* must have a MAC addr for bootp */
380 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
383 if (have_config(config
, CONFIG_DISABLE
))
384 message
= _("disabled");
386 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
388 if (have_config(config
, CONFIG_NAME
))
390 hostname
= config
->hostname
;
391 domain
= config
->domain
;
394 if (have_config(config
, CONFIG_NETID
))
396 config
->netid
.next
= netid
;
397 netid
= &config
->netid
;
400 /* Match incoming filename field as a netid. */
403 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
404 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
405 id
.net
= (char *)daemon
->dhcp_buff2
;
410 /* Add "bootp" as a tag to allow different options, address ranges etc
412 bootp_id
.net
= "bootp";
413 bootp_id
.next
= netid
;
416 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
417 if (match_netid(id_list
->list
, netid
, 0))
418 message
= _("disabled");
424 if (have_config(config
, CONFIG_ADDR
))
427 logaddr
= &config
->addr
;
428 mess
->yiaddr
= config
->addr
;
429 if ((lease
= lease_find_by_addr(config
->addr
)) &&
430 (lease
->hwaddr_len
!= mess
->hlen
||
431 lease
->hwaddr_type
!= mess
->htype
||
432 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
433 message
= _("address in use");
437 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
438 !address_available(context
, lease
->addr
, netid
))
442 /* lease exists, wrong network. */
443 lease_prune(lease
, now
);
446 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, netid
, now
))
447 message
= _("no address available");
450 mess
->yiaddr
= lease
->addr
;
453 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
454 message
= _("wrong network");
455 else if (context
->netid
.net
)
457 context
->netid
.next
= netid
;
458 netid
= &context
->netid
;
461 if (!message
&& !nailed
)
463 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
464 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
467 message
= _("no address configured");
472 (!(lease
= lease_allocate(mess
->yiaddr
))))
473 message
= _("no leases left");
477 logaddr
= &mess
->yiaddr
;
479 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0);
481 lease_set_hostname(lease
, hostname
, 1);
482 /* infinite lease unless nailed in dhcp-host line. */
483 lease_set_expires(lease
,
484 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
486 lease_set_interface(lease
, int_index
);
488 clear_packet(mess
, end
);
489 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
490 domain
, netid
, subnet_addr
, 0, 0, 0, NULL
);
494 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
, mess
->xid
);
496 return message
? 0 : dhcp_packet_size(mess
, netid
, agent_id
, real_end
);
499 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
501 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
502 int len
= option_len(opt
);
503 char *pq
= daemon
->dhcp_buff
;
504 unsigned char *pp
, *op
= option_ptr(opt
, 0);
511 /* Always force update, since the client has no way to do it itself. */
512 if (!(fqdn_flags
& 0x01))
518 if (fqdn_flags
& 0x04)
519 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
521 memcpy(pq
, op
+1, *op
);
529 if (len
> 0 && op
[len
-1] == 0)
534 if (pq
!= daemon
->dhcp_buff
)
539 if (canonicalise(daemon
->dhcp_buff
))
540 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
542 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
544 int len
= option_len(opt
);
545 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
546 /* Microsoft clients are broken, and need zero-terminated strings
547 in options. We detect this state here, and do the same in
548 any options we send */
549 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
552 daemon
->dhcp_buff
[len
] = 0;
553 if (canonicalise(daemon
->dhcp_buff
))
554 client_hostname
= daemon
->dhcp_buff
;
557 if (client_hostname
&& daemon
->options
& OPT_LOG_OPTS
)
558 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
560 if (have_config(config
, CONFIG_NAME
))
562 hostname
= config
->hostname
;
563 domain
= config
->domain
;
565 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
566 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
567 offer_hostname
= hostname
;
569 else if (client_hostname
)
571 domain
= strip_hostname(client_hostname
);
573 if (strlen(client_hostname
) != 0)
575 hostname
= client_hostname
;
578 /* Search again now we have a hostname.
579 Only accept configs without CLID and HWADDR here, (they won't match)
580 to avoid impersonation by name. */
581 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
582 mess
->chaddr
, mess
->hlen
,
583 mess
->htype
, hostname
);
584 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
587 /* set "known" tag for known hosts */
588 known_id
.net
= "known";
589 known_id
.next
= netid
;
596 if (have_config(config
, CONFIG_NETID
))
598 config
->netid
.next
= netid
;
599 netid
= &config
->netid
;
602 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
603 Otherwise assume the option is an array, and look for a matching element.
604 If no data given, existance of the option is enough. */
605 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
609 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)) ||
610 o
->len
> option_len(opt
))
615 else if (o
->flags
& DHOPT_HEX
)
617 if (memcmp_masked(o
->val
, option_ptr(opt
, 0), o
->len
, o
->u
.wildcard_mask
))
621 for (i
= 0; i
<= (option_len(opt
) - o
->len
); )
623 if (memcmp(o
->val
, option_ptr(opt
, i
), o
->len
) == 0)
629 if (o
->flags
& DHOPT_STRING
)
637 o
->netid
->next
= netid
;
642 /* user-class options are, according to RFC3004, supposed to contain
643 a set of counted strings. Here we check that this is so (by seeing
644 if the counts are consistent with the overall option length) and if
645 so zero the counts so that we don't get spurious matches between
646 the vendor string and the counts. If the lengths don't add up, we
647 assume that the option is a single string and non RFC3004 compliant
648 and just do the substring match. dhclient provides these broken options.
649 The code, later, which sends user-class data to the lease-change script
650 relies on the transformation done here.
653 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
655 unsigned char *ucp
= option_ptr(opt
, 0);
657 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
658 if (j
== option_len(opt
))
659 for (j
= 0; j
< option_len(opt
); j
= tmp
)
661 tmp
= j
+ ucp
[j
] + 1;
666 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
670 if (vendor
->match_type
== MATCH_VENDOR
)
671 mopt
= OPTION_VENDOR_ID
;
672 else if (vendor
->match_type
== MATCH_USER
)
673 mopt
= OPTION_USER_CLASS
;
677 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
680 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
681 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
683 vendor
->netid
.next
= netid
;
684 netid
= &vendor
->netid
;
690 /* mark vendor-encapsulated options which match the client-supplied vendor class */
691 match_vendor_opts(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->dhcp_opts
);
693 if (daemon
->options
& OPT_LOG_OPTS
)
695 if (sanitise(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->namebuff
))
696 my_syslog(MS_DHCP
| LOG_INFO
, _("%u Vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
697 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
698 my_syslog(MS_DHCP
| LOG_INFO
, _("%u User class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
701 /* if all the netids in the ignore list are present, ignore this client */
702 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
703 if (match_netid(id_list
->list
, netid
, 0))
706 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
707 if (have_config(config
, CONFIG_NOCLID
))
710 /* Check if client is PXE client. */
711 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
712 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
714 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
716 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
720 /* Check if this is really a PXE bootserver request, and handle specially if so. */
721 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
722 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
723 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
725 struct pxe_service
*service
;
726 int type
= option_uint(opt
, 0, 2);
727 int layer
= option_uint(opt
, 2, 2);
728 unsigned char save71
[4];
729 struct dhcp_opt opt71
;
733 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
737 memcpy(save71
, option_ptr(opt
, 0), 4);
739 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
740 if (service
->type
== type
)
743 if (!service
|| !service
->basename
)
746 clear_packet(mess
, end
);
748 mess
->yiaddr
= mess
->ciaddr
;
749 mess
->ciaddr
.s_addr
= 0;
750 if (service
->server
.s_addr
!= 0)
751 mess
->siaddr
= service
->server
;
753 mess
->siaddr
= context
->local
;
755 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
756 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
757 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
758 pxe_misc(mess
, end
, uuid
);
760 prune_vendor_opts(netid
);
762 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
764 opt71
.flags
= DHOPT_VENDOR_MATCH
;
766 opt71
.next
= daemon
->dhcp_opts
;
767 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
769 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, mess
->xid
);
770 return dhcp_packet_size(mess
, netid
, agent_id
, real_end
);
773 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
775 pxearch
= option_uint(opt
, 0, 2);
777 /* proxy DHCP here. The DHCPREQUEST stuff is for gPXE */
778 if ((mess_type
== DHCPDISCOVER
|| mess_type
== DHCPREQUEST
) &&
779 (context
->flags
& CONTEXT_PROXY
))
781 struct dhcp_boot
*boot
= find_boot(netid
);
783 mess
->yiaddr
.s_addr
= 0;
784 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
786 mess
->ciaddr
.s_addr
= 0;
787 mess
->flags
|= htons(0x8000); /* broadcast */
790 clear_packet(mess
, end
);
792 /* Provide the bootfile here, for gPXE, and in case we have no menu items
793 and set discovery_control = 8 */
796 if (boot
->next_server
.s_addr
)
797 mess
->siaddr
= boot
->next_server
;
800 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
803 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
804 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
805 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
806 pxe_misc(mess
, end
, uuid
);
807 prune_vendor_opts(netid
);
808 do_encap_opts(pxe_opts(pxearch
, netid
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
810 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, "proxy", mess
->xid
);
811 return dhcp_packet_size(mess
, netid
, agent_id
, real_end
);
816 /* if we're just a proxy server, go no further */
817 if (context
->flags
& CONTEXT_PROXY
)
820 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
822 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
823 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
824 req_options
[option_len(opt
)] = OPTION_END
;
830 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
831 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
834 /* sanitise any message. Paranoid? Moi? */
835 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
837 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
840 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
, mess
->xid
);
842 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
843 lease_prune(lease
, now
);
845 if (have_config(config
, CONFIG_ADDR
) &&
846 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
848 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
849 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
850 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
851 config
->flags
|= CONFIG_DECLINED
;
852 config
->decline_time
= now
;
855 /* make sure this host gets a different address next time. */
856 for (; context
; context
= context
->current
)
857 context
->addr_epoch
++;
862 if (!(context
= narrow_context(context
, mess
->ciaddr
, netid
)) ||
863 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
864 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
867 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
868 lease_prune(lease
, now
);
870 message
= _("unknown lease");
872 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
877 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
879 message
= _("ignored");
884 struct in_addr addr
, conf
;
886 addr
.s_addr
= conf
.s_addr
= 0;
888 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
889 addr
= option_addr(opt
);
891 if (have_config(config
, CONFIG_ADDR
))
893 char *addrs
= inet_ntoa(config
->addr
);
895 if ((ltmp
= lease_find_by_addr(config
->addr
)) &&
897 !config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
900 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
901 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
902 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
903 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
907 struct dhcp_context
*tmp
;
908 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
909 if (context
->router
.s_addr
== config
->addr
.s_addr
)
912 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
913 else if (have_config(config
, CONFIG_DECLINED
) &&
914 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
915 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
924 address_available(context
, lease
->addr
, netid
) &&
925 !config_find_by_address(daemon
->dhcp_conf
, lease
->addr
))
926 mess
->yiaddr
= lease
->addr
;
927 else if (opt
&& address_available(context
, addr
, netid
) && !lease_find_by_addr(addr
) &&
928 !config_find_by_address(daemon
->dhcp_conf
, addr
))
930 else if (emac_len
== 0)
931 message
= _("no unique-id");
932 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, netid
, now
))
933 message
= _("no address available");
936 log_packet("DHCPDISCOVER", opt
? option_ptr(opt
, 0) : NULL
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
938 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
941 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
943 if (context
->netid
.net
)
945 context
->netid
.next
= netid
;
946 netid
= &context
->netid
;
949 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
950 clear_packet(mess
, end
);
951 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
952 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
953 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
954 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
955 if (time
!= 0xffffffff)
957 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
958 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
960 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
961 domain
, netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
);
963 return dhcp_packet_size(mess
, netid
, agent_id
, real_end
);
966 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
968 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
970 /* SELECTING or INIT_REBOOT */
971 mess
->yiaddr
= option_addr(opt
);
973 /* send vendor and user class info for new or recreated lease */
976 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
981 if (override
.s_addr
!= 0)
983 if (option_addr(opt
).s_addr
!= override
.s_addr
)
988 for (; context
; context
= context
->current
)
989 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
994 /* In auth mode, a REQUEST sent to the wrong server
995 should be faulted, so that the client establishes
996 communication with us, otherwise, silently ignore. */
997 if (!(daemon
->options
& OPT_AUTHORITATIVE
))
999 message
= _("wrong server-ID");
1003 /* If a lease exists for this host and another address, squash it. */
1004 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1006 lease_prune(lease
, now
);
1013 if (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
))
1016 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1018 message
= _("wrong address");
1019 /* avoid loops when client brain-dead */
1020 lease_prune(lease
, now
);
1027 /* RENEWING or REBINDING */
1028 /* Check existing lease for this address.
1029 We allow it to be missing if dhcp-authoritative mode
1030 as long as we can allocate the lease now - checked below.
1031 This makes for a smooth recovery from a lost lease DB */
1032 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1033 (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
)))
1035 message
= _("lease not found");
1036 /* ensure we broadcast NAK */
1039 /* desynchronise renewals */
1041 mess
->yiaddr
= mess
->ciaddr
;
1044 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1048 struct dhcp_config
*addr_config
;
1049 struct dhcp_context
*tmp
= NULL
;
1051 if (have_config(config
, CONFIG_ADDR
))
1052 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1053 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1056 if (!(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
1058 /* If a machine moves networks whilst it has a lease, we catch that here. */
1059 message
= _("wrong network");
1060 /* ensure we broadcast NAK */
1064 /* Check for renewal of a lease which is outside the allowed range. */
1065 else if (!address_available(context
, mess
->yiaddr
, netid
) &&
1066 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1067 message
= _("address not available");
1069 /* Check if a new static address has been configured. Be very sure that
1070 when the client does DISCOVER, it will get the static address, otherwise
1071 an endless protocol loop will ensue. */
1072 else if (!tmp
&& !selecting
&&
1073 have_config(config
, CONFIG_ADDR
) &&
1074 (!have_config(config
, CONFIG_DECLINED
) ||
1075 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1076 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1077 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1078 message
= _("static lease available");
1080 /* Check to see if the address is reserved as a static address for another host */
1081 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1082 message
= _("address reserved");
1084 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1086 /* If a host is configured with more than one MAC address, it's OK to 'nix
1087 a lease from one of it's MACs to give the address to another. */
1088 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1090 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1091 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1092 inet_ntoa(ltmp
->addr
));
1096 message
= _("address in use");
1102 message
= _("no unique-id");
1106 if ((lease
= lease_allocate(mess
->yiaddr
)))
1109 message
= _("no leases left");
1116 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1118 mess
->yiaddr
.s_addr
= 0;
1119 clear_packet(mess
, end
);
1120 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1121 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1122 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1123 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1124 a distant subnet which unicast a REQ to us won't work. */
1125 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1126 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1128 mess
->flags
|= htons(0x8000); /* broadcast */
1129 mess
->ciaddr
.s_addr
= 0;
1137 /* copy user-class and vendor class into new lease, for the script */
1138 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1140 int len
= option_len(opt
);
1141 unsigned char *ucp
= option_ptr(opt
, 0);
1142 /* If the user-class option started as counted strings, the first byte will be zero. */
1143 if (len
!= 0 && ucp
[0] == 0)
1145 free(lease
->userclass
);
1146 if ((lease
->userclass
= whine_malloc(len
+1)))
1148 memcpy(lease
->userclass
, ucp
, len
);
1149 lease
->userclass
[len
] = 0;
1150 lease
->userclass_len
= len
+1;
1153 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
1155 int len
= option_len(opt
);
1156 unsigned char *ucp
= option_ptr(opt
, 0);
1157 free(lease
->vendorclass
);
1158 if ((lease
->vendorclass
= whine_malloc(len
+1)))
1160 memcpy(lease
->vendorclass
, ucp
, len
);
1161 lease
->vendorclass
[len
] = 0;
1162 lease
->vendorclass_len
= len
+1;
1167 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1169 hostname
= client_hostname
;
1173 if (context
->netid
.net
)
1175 context
->netid
.next
= netid
;
1176 netid
= &context
->netid
;
1179 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1180 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
);
1182 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1185 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1186 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
1192 lease_set_hostname(lease
, hostname
, hostname_auth
);
1194 lease_set_expires(lease
, time
, now
);
1195 lease_set_interface(lease
, int_index
);
1197 if (override
.s_addr
!= 0)
1198 lease
->override
= override
;
1200 override
= lease
->override
;
1202 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1204 clear_packet(mess
, end
);
1205 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1206 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1207 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1208 if (time
!= 0xffffffff)
1210 while (fuzz
> (time
/16))
1212 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
1213 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
1215 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1216 domain
, netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
);
1219 return dhcp_packet_size(mess
, netid
, agent_id
, real_end
);
1222 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1223 message
= _("ignored");
1225 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1227 if (message
|| mess
->ciaddr
.s_addr
== 0)
1230 /* For DHCPINFORM only, cope without a valid context */
1231 context
= narrow_context(context
, mess
->ciaddr
, netid
);
1233 /* Find a least based on IP address if we didn't
1234 get one from MAC address/client-d */
1236 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1238 hostname
= lease
->hostname
;
1241 hostname
= host_from_dns(mess
->ciaddr
);
1243 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1245 if (context
&& context
->netid
.net
)
1247 context
->netid
.next
= netid
;
1248 netid
= &context
->netid
;
1253 if (override
.s_addr
!= 0)
1254 lease
->override
= override
;
1256 override
= lease
->override
;
1259 clear_packet(mess
, end
);
1260 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1261 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1265 if (lease
->expires
== 0)
1268 time
= (unsigned int)difftime(lease
->expires
, now
);
1269 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1270 lease_set_interface(lease
, int_index
);
1273 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1274 domain
, netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
);
1276 *is_inform
= 1; /* handle reply differently */
1277 return dhcp_packet_size(mess
, netid
, agent_id
, real_end
);
1283 /* find a good value to use as MAC address for logging and address-allocation hashing.
1284 This is normally just the chaddr field from the DHCP packet,
1285 but eg Firewire will have hlen == 0 and use the client-id instead.
1286 This could be anything, but will normally be EUI64 for Firewire.
1287 We assume that if the first byte of the client-id equals the htype byte
1288 then the client-id is using the usual encoding and use the rest of the
1289 client-id: if not we can use the whole client-id. This should give
1290 sane MAC address logs. */
1291 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1292 int clid_len
, unsigned char *clid
, int *len_out
)
1294 if (hwlen
== 0 && clid
&& clid_len
> 3)
1296 if (clid
[0] == hwtype
)
1298 *len_out
= clid_len
- 1 ;
1302 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1303 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1305 *len_out
= clid_len
- 1 ;
1310 *len_out
= clid_len
;
1318 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1320 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1324 unsigned int req_time
= option_uint(opt
, 0, 4);
1325 if (req_time
< 120 )
1326 req_time
= 120; /* sanity */
1327 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1334 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1336 if (override
.s_addr
!= 0)
1339 return context
->local
;
1344 static int sanitise(unsigned char *opt
, char *buf
)
1354 p
= option_ptr(opt
, 0);
1356 for (i
= option_len(opt
); i
> 0; i
--)
1359 if (isprint((int)c
))
1362 *buf
= 0; /* add terminator */
1367 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1368 int mac_len
, char *interface
, char *string
, u32 xid
)
1370 /* !!TB - reduce excessive logging for DHCP packets */
1371 if ((type
) && !(daemon
->options
& OPT_LOG_OPTS
))
1376 /* addr may be misaligned */
1378 memcpy(&a
, addr
, sizeof(a
));
1380 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1382 if(daemon
->options
& OPT_LOG_OPTS
)
1383 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s",
1387 addr
? inet_ntoa(a
) : "",
1390 string
? string
: "");
1392 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s",
1395 addr
? inet_ntoa(a
) : "",
1398 string
? string
: "");
1401 static void log_options(unsigned char *start
, u32 xid
)
1403 while (*start
!= OPTION_END
)
1405 int is_ip
, is_name
, i
;
1406 char *text
= option_string(start
[0], &is_ip
, &is_name
);
1407 unsigned char trunc
= option_len(start
);
1410 for (daemon
->namebuff
[0]= 0, i
= 0; i
<= trunc
- INADDRSZ
; i
+= INADDRSZ
)
1413 strncat(daemon
->namebuff
, ", ", 256 - strlen(daemon
->namebuff
));
1414 strncat(daemon
->namebuff
, inet_ntoa(option_addr_arr(start
, i
)), 256 - strlen(daemon
->namebuff
));
1416 else if (!is_name
|| !sanitise(start
, daemon
->namebuff
))
1420 print_mac(daemon
->namebuff
, option_ptr(start
, 0), trunc
);
1423 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d%s%s%s%s%s",
1424 ntohl(xid
), option_len(start
), start
[0],
1425 text
? ":" : "", text
? text
: "",
1426 trunc
== 0 ? "" : " ",
1427 trunc
== 0 ? "" : daemon
->namebuff
,
1428 trunc
== option_len(start
) ? "" : "...");
1429 start
+= start
[1] + 2;
1433 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1439 else if (*p
== OPTION_END
)
1440 return opt
== OPTION_END
? p
: NULL
;
1441 else if (*p
== OPTION_PAD
)
1447 return NULL
; /* malformed packet */
1448 opt_len
= option_len(p
);
1449 if (p
> end
- (2 + opt_len
))
1450 return NULL
; /* malformed packet */
1451 if (*p
== opt
&& opt_len
>= minsize
)
1458 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1460 unsigned char *ret
, *overload
;
1462 /* skip over DHCP cookie; */
1463 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1466 /* look for overload option. */
1467 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1470 /* Can we look in filename area ? */
1471 if ((overload
[2] & 1) &&
1472 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1475 /* finally try sname area */
1476 if ((overload
[2] & 2) &&
1477 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1483 static struct in_addr
option_addr_arr(unsigned char *opt
, int offset
)
1485 /* this worries about unaligned data in the option. */
1486 /* struct in_addr is network byte order */
1489 memcpy(&ret
, option_ptr(opt
, offset
), INADDRSZ
);
1494 static struct in_addr
option_addr(unsigned char *opt
)
1496 return option_addr_arr(opt
, 0);
1499 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1501 /* this worries about unaligned data and byte order */
1502 unsigned int ret
= 0;
1504 unsigned char *p
= option_ptr(opt
, offset
);
1506 for (i
= 0; i
< size
; i
++)
1507 ret
= (ret
<< 8) | *p
++;
1512 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1515 start
+= start
[1] + 2;
1519 /* only for use when building packet: doesn't check for bad data. */
1520 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1522 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1526 if (*p
== OPTION_OVERLOAD
)
1533 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
,
1534 unsigned char *agent_id
, unsigned char *real_end
)
1536 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1537 unsigned char *overload
;
1539 struct dhcp_netid_list
*id_list
;
1540 struct dhcp_netid
*n
;
1542 /* move agent_id back down to the end of the packet */
1545 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1546 memmove(p
, agent_id
, real_end
- agent_id
);
1547 p
+= real_end
- agent_id
;
1548 memset(p
, 0, real_end
- p
); /* in case of overlap */
1551 /* We do logging too */
1552 if (netid
&& (daemon
->options
& OPT_LOG_OPTS
))
1554 char *p
= daemon
->namebuff
;
1556 for (; netid
; netid
= netid
->next
)
1559 for (n
= netid
->next
; n
; n
= n
->next
)
1560 if (strcmp(netid
->net
, n
->net
) == 0)
1565 strncat (p
, netid
->net
, MAXDNAME
);
1567 strncat (p
, ", ", MAXDNAME
);
1570 p
[MAXDNAME
- 1] = 0;
1571 my_syslog(MS_DHCP
| LOG_INFO
, _("%u tags: %s"), ntohl(mess
->xid
), p
);
1574 /* add END options to the regions. */
1575 overload
= find_overload(mess
);
1577 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1579 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1580 if (daemon
->options
& OPT_LOG_OPTS
)
1581 log_options(mess
->file
, mess
->xid
);
1583 else if ((daemon
->options
& OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1584 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1586 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1588 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1589 if (daemon
->options
& OPT_LOG_OPTS
)
1590 log_options(mess
->sname
, mess
->xid
);
1592 else if ((daemon
->options
& OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1593 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1598 if (daemon
->options
& OPT_LOG_OPTS
)
1600 if (mess
->siaddr
.s_addr
!= 0)
1601 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1603 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1606 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
1607 if (match_netid(id_list
->list
, netid
, 0))
1608 mess
->flags
|= htons(0x8000); /* force broadcast */
1610 ret
= (size_t)(p
- (unsigned char *)mess
);
1612 if (ret
< MIN_PACKETSZ
)
1618 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1620 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1622 if (p
+ len
+ 3 >= end
)
1623 /* not enough space in options area, try and use overload, if poss */
1625 unsigned char *overload
;
1627 if (!(overload
= find_overload(mess
)) &&
1628 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1630 /* attempt to overload fname and sname areas, we've reserved space for the
1631 overflow option previuously. */
1633 *(p
++) = OPTION_OVERLOAD
;
1639 /* using filename field ? */
1642 if (mess
->file
[0] == 0)
1645 if (overload
[2] & 1)
1647 p
= dhcp_skip_opts(mess
->file
);
1648 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1654 /* try to bring sname into play (it may be already) */
1655 if (mess
->sname
[0] == 0)
1658 if (overload
[2] & 2)
1660 p
= dhcp_skip_opts(mess
->sname
);
1661 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1668 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1680 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1683 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1686 for (i
= 0; i
< len
; i
++)
1687 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1690 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1691 char *string
, int null_term
)
1694 size_t len
= strlen(string
);
1696 if (null_term
&& len
!= 255)
1699 if ((p
= free_space(mess
, end
, opt
, len
)))
1700 memcpy(p
, string
, len
);
1703 /* return length, note this only does the data part */
1704 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1708 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1713 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1716 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1717 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1719 /* zero means "self" (but not in vendorclass options.) */
1721 memcpy(p
, &context
->local
, INADDRSZ
);
1723 memcpy(p
, a
, INADDRSZ
);
1728 memcpy(p
, opt
->val
, len
);
1733 static int in_list(unsigned char *list
, int opt
)
1737 /* If no requested options, send everything, not nothing. */
1741 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1748 static struct dhcp_opt
*option_find2(struct dhcp_netid
*netid
, struct dhcp_opt
*opts
, int opt
)
1750 struct dhcp_opt
*tmp
;
1751 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
1752 if (tmp
->opt
== opt
&& !(tmp
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
)))
1753 if (match_netid(tmp
->netid
, netid
, netid
? 0 : 1))
1756 return netid
? option_find2(NULL
, opts
, opt
) : NULL
;
1759 /* mark vendor-encapsulated options which match the client-supplied or
1760 config-supplied vendor class */
1761 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1763 for (; dopt
; dopt
= dopt
->next
)
1765 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1766 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1769 if (dopt
->u
.vendor_class
)
1770 len
= strlen((char *)dopt
->u
.vendor_class
);
1771 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1772 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1774 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1781 static void do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1782 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1785 struct dhcp_opt
*start
;
1788 /* find size in advance */
1789 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1790 if (opt
->flags
& flag
)
1792 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1793 if (enc_len
+ new <= 255)
1797 p
= free_space(mess
, end
, encap
, enc_len
);
1798 for (; start
&& start
!= opt
; start
= start
->next
)
1799 if (p
&& (start
->flags
& flag
))
1801 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1802 *(p
++) = start
->opt
;
1812 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
1814 for (; start
; start
= start
->next
)
1815 if (start
->flags
& flag
)
1817 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1818 *(p
++) = start
->opt
;
1826 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
1830 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
1831 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
1832 memcpy(p
, uuid
, 17);
1835 static int prune_vendor_opts(struct dhcp_netid
*netid
)
1838 struct dhcp_opt
*opt
;
1840 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1841 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
1842 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1844 if (!match_netid(opt
->netid
, netid
, 1))
1845 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1846 else if (opt
->flags
& DHOPT_FORCE
)
1852 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
)
1856 unsigned char *p
, *q
;
1857 struct pxe_service
*service
;
1858 static struct dhcp_opt
*o
, *ret
;
1859 int i
, j
= NUM_OPTS
- 1;
1861 /* We pass back references to these, hence they are declared static */
1862 static unsigned char discovery_control
;
1863 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
1864 static struct dhcp_opt
*fake_opts
= NULL
;
1866 /* We are found by broadcast, so disable multicast. It gets switched on again
1867 if we point to other servers and don't give a unicast address. Note that
1868 we don't provide our own address for services we are the boot server for because unicast
1869 discovery is to port 4011 and we don't listen there. If you are using proxy DHCP
1870 and DHCP relays, the relay will need to forward to the proxy too. */
1871 discovery_control
= 2;
1873 ret
= daemon
->dhcp_opts
;
1875 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
1878 for (i
= 0; i
< NUM_OPTS
; i
++)
1880 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
1881 fake_opts
[i
].netid
= NULL
;
1882 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
1885 /* create the data for the PXE_MENU and PXE_SERVERS options. */
1886 p
= (unsigned char *)daemon
->dhcp_buff
;
1887 q
= (unsigned char *)daemon
->dhcp_buff2
;
1889 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
1890 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
1892 size_t len
= strlen(service
->menu
);
1893 /* opt 43 max size is 255. encapsulated option has type and length
1894 bytes, so its max size is 253. */
1895 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
1897 *(p
++) = service
->type
>> 8;
1898 *(p
++) = service
->type
;
1900 memcpy(p
, service
->menu
, len
);
1907 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
1908 return daemon
->dhcp_opts
;
1911 if (!service
->basename
)
1913 if (service
->server
.s_addr
!= 0)
1915 if (q
- (unsigned char *)daemon
->dhcp_buff2
+ 3 + INADDRSZ
>= 253)
1918 /* Boot service with known address - give it */
1919 *(q
++) = service
->type
>> 8;
1920 *(q
++) = service
->type
;
1922 /* dest misaligned */
1923 memcpy(q
, &service
->server
.s_addr
, INADDRSZ
);
1926 else if (service
->type
!= 0)
1927 /* We're not supplying a server, so let the client multicast.
1928 type zero is "local boot" so no need for M/C on that. */
1929 discovery_control
= 0;
1933 /* if no prompt, wait forever if there's a choice */
1934 fake_prompt
[0] = (i
> 1) ? 255 : 0;
1937 discovery_control
= 8; /* no menu - just use use mess->filename */
1940 ret
= &fake_opts
[j
--];
1941 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
1942 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
1943 ret
->opt
= SUBOPT_PXE_MENU
;
1945 if (q
- (unsigned char *)daemon
->dhcp_buff2
!= 0)
1947 ret
= &fake_opts
[j
--];
1948 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff2
;
1949 ret
->val
= (unsigned char *)daemon
->dhcp_buff2
;
1950 ret
->opt
= SUBOPT_PXE_SERVERS
;
1954 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
1955 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
1960 ret
= &fake_opts
[j
--];
1961 ret
->len
= sizeof(fake_prompt
);
1962 ret
->val
= fake_prompt
;
1963 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
1966 if (discovery_control
!= 0)
1968 ret
= &fake_opts
[j
--];
1970 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
1971 ret
->val
= &discovery_control
;
1977 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
1979 memset(mess
->sname
, 0, sizeof(mess
->sname
));
1980 memset(mess
->file
, 0, sizeof(mess
->file
));
1981 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
1982 mess
->siaddr
.s_addr
= 0;
1985 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
1987 struct dhcp_boot
*boot
;
1989 /* decide which dhcp-boot option we're using */
1990 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1991 if (match_netid(boot
->netid
, netid
, 0))
1994 /* No match, look for one without a netid */
1995 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1996 if (match_netid(boot
->netid
, netid
, 1))
2002 static void do_options(struct dhcp_context
*context
,
2003 struct dhcp_packet
*mess
,
2005 unsigned char *req_options
,
2007 char *domain
, char *config_domain
,
2008 struct dhcp_netid
*netid
,
2009 struct in_addr subnet_addr
,
2010 unsigned char fqdn_flags
,
2011 int null_term
, int pxe_arch
,
2012 unsigned char *uuid
)
2014 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2015 struct dhcp_boot
*boot
;
2017 int i
, len
, force_encap
= 0;
2018 unsigned char f0
= 0, s0
= 0;
2019 int done_file
= 0, done_server
= 0;
2021 if (config_domain
&& (!domain
|| !hostname_isequal(domain
, config_domain
)))
2022 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), config_domain
, hostname
);
2025 if ((daemon
->options
& OPT_LOG_OPTS
) && req_options
)
2027 char *q
= daemon
->namebuff
;
2028 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2030 char *s
= option_string(req_options
[i
], NULL
, NULL
);
2031 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2036 req_options
[i
+1] == OPTION_END
? "" : ", ");
2037 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2039 q
= daemon
->namebuff
;
2040 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2046 mess
->siaddr
= context
->local
;
2048 /* See if we can send the boot stuff as options.
2049 To do this we need a requested option list, BOOTP
2050 and very old DHCP clients won't have this, we also
2051 provide an manual option to disable it.
2052 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2053 names, so we always send those. */
2054 if ((boot
= find_boot(netid
)))
2058 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
2060 in_list(req_options
, OPTION_SNAME
))
2061 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2063 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2068 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
2070 in_list(req_options
, OPTION_FILENAME
))
2071 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2073 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2076 if (boot
->next_server
.s_addr
)
2077 mess
->siaddr
= boot
->next_server
;
2080 /* Use the values of the relevant options if no dhcp-boot given and
2081 they're not explicitly asked for as options. */
2083 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) && mess
->file
[0] == 0 &&
2084 (opt
= option_find2(netid
, config_opts
, OPTION_FILENAME
)))
2086 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2090 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2091 (opt
= option_find2(netid
, config_opts
, OPTION_SNAME
)))
2093 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2098 /* We don't want to do option-overload for BOOTP, so make the file and sname
2099 fields look like they are in use, even when they aren't. This gets restored
2100 at the end of this function. */
2102 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
2106 s0
= mess
->sname
[0];
2110 /* At this point, if mess->sname or mess->file are zeroed, they are available
2111 for option overload, reserve space for the overload option. */
2112 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2115 /* rfc3011 says this doesn't need to be in the requested options list. */
2116 if (subnet_addr
.s_addr
)
2117 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2119 /* replies to DHCPINFORM may not have a valid context */
2122 if (!option_find2(netid
, config_opts
, OPTION_NETMASK
))
2123 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2125 /* May not have a "guessed" broadcast address if we got no packets via a relay
2126 from this net yet (ie just unicast renewals after a restart */
2127 if (context
->broadcast
.s_addr
&&
2128 !option_find2(netid
, config_opts
, OPTION_BROADCAST
))
2129 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2131 /* Same comments as broadcast apply, and also may not be able to get a sensible
2132 default when using subnet select. User must configure by steam in that case. */
2133 if (context
->router
.s_addr
&&
2134 in_list(req_options
, OPTION_ROUTER
) &&
2135 !option_find2(netid
, config_opts
, OPTION_ROUTER
))
2136 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2138 if (in_list(req_options
, OPTION_DNSSERVER
) &&
2139 !option_find2(netid
, config_opts
, OPTION_DNSSERVER
))
2140 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2143 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2144 !option_find2(netid
, config_opts
, OPTION_DOMAINNAME
))
2145 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2147 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2150 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2151 !option_find2(netid
, config_opts
, OPTION_HOSTNAME
))
2152 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2154 if (fqdn_flags
!= 0)
2156 len
= strlen(hostname
) + 3;
2158 if (fqdn_flags
& 0x04)
2164 len
+= strlen(domain
) + 1;
2166 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2168 *(p
++) = fqdn_flags
;
2172 if (fqdn_flags
& 0x04)
2174 p
= do_rfc1035_name(p
, hostname
);
2176 p
= do_rfc1035_name(p
, domain
);
2181 memcpy(p
, hostname
, strlen(hostname
));
2182 p
+= strlen(hostname
);
2186 memcpy(p
, domain
, strlen(domain
));
2187 p
+= strlen(domain
);
2196 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2198 int optno
= opt
->opt
;
2200 /* was it asked for, or are we sending it anyway? */
2201 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2204 /* prohibit some used-internally options */
2205 if (optno
== OPTION_CLIENT_FQDN
||
2206 optno
== OPTION_MAXMESSAGE
||
2207 optno
== OPTION_OVERLOAD
||
2208 optno
== OPTION_PAD
||
2209 optno
== OPTION_END
)
2212 if (optno
== OPTION_SNAME
&& done_server
)
2215 if (optno
== OPTION_FILENAME
&& done_file
)
2218 /* netids match and not encapsulated? */
2219 if (opt
!= option_find2(netid
, config_opts
, optno
))
2222 /* For the options we have default values on
2223 dhc-option=<optionno> means "don't include this option"
2224 not "include a zero-length option" */
2225 if (opt
->len
== 0 &&
2226 (optno
== OPTION_NETMASK
||
2227 optno
== OPTION_BROADCAST
||
2228 optno
== OPTION_ROUTER
||
2229 optno
== OPTION_DNSSERVER
||
2230 optno
== OPTION_DOMAINNAME
||
2231 optno
== OPTION_HOSTNAME
))
2234 /* vendor-class comes from elsewhere for PXE */
2235 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2238 /* always force null-term for filename and servername - buggy PXE again. */
2239 len
= do_opt(opt
, NULL
, context
,
2240 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2242 if ((p
= free_space(mess
, end
, optno
, len
)))
2244 do_opt(opt
, p
, context
,
2245 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2247 /* If we send a vendor-id, revisit which vendor-ops we consider
2248 it appropriate to send. */
2249 if (optno
== OPTION_VENDOR_ID
)
2250 match_vendor_opts(p
- 2, config_opts
);
2254 /* Now send options to be encapsulated in arbitrary options,
2255 eg dhcp-option=encap:172,17,.......
2256 The may be more that one "outer" to do, so group
2257 all the options which match each outer in turn. */
2258 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2259 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2261 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2262 if ((opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_ENCAP_DONE
)) == DHOPT_ENCAPSULATE
)
2267 for (o
= config_opts
; o
; o
= o
->next
)
2269 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2270 if ((o
->flags
& DHOPT_ENCAPSULATE
) && opt
->u
.encap
== o
->u
.encap
)
2272 o
->flags
|= DHOPT_ENCAP_DONE
;
2273 if (match_netid(o
->netid
, netid
, 1) &&
2274 (o
->flags
& DHOPT_FORCE
|| in_list(req_options
, o
->u
.encap
)))
2276 o
->flags
|= DHOPT_ENCAP_MATCH
;
2283 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2286 /* Must precede pxe_opts, since it overwrites req_options */
2287 force_encap
= prune_vendor_opts(netid
);
2288 if (in_list(req_options
, OPTION_VENDOR_CLASS_OPT
))
2293 pxe_misc(mess
, end
, uuid
);
2294 config_opts
= pxe_opts(pxe_arch
, netid
);
2298 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
);
2300 /* restore BOOTP anti-overload hack */
2301 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
2304 mess
->sname
[0] = s0
;