]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc2131.c
1 /* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #define have_config(config, mask) ((config) && ((config)->flags & (mask)))
22 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
23 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
26 static void add_extradata_data(struct dhcp_lease
*lease
, unsigned char *data
, size_t len
, int delim
);
27 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
);
30 static int match_bytes(struct dhcp_opt
*o
, unsigned char *p
, int len
);
31 static int sanitise(unsigned char *opt
, char *buf
);
32 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
);
33 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
);
34 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
35 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
36 int opt
, char *string
, int null_term
);
37 static struct in_addr
option_addr(unsigned char *opt
);
38 static struct in_addr
option_addr_arr(unsigned char *opt
, int offset
);
39 static unsigned int option_uint(unsigned char *opt
, int i
, int size
);
40 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
41 int mac_len
, char *interface
, char *string
, u32 xid
);
42 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
43 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
44 static void log_tags(struct dhcp_netid
*netid
, struct dhcp_packet
*mess
);
45 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
);
46 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
47 static void do_options(struct dhcp_context
*context
,
48 struct dhcp_packet
*mess
,
49 unsigned char *real_end
,
50 unsigned char *req_options
,
52 char *domain
, char *config_domain
,
53 struct dhcp_netid
*netid
,
54 struct in_addr subnet_addr
,
55 unsigned char fqdn_flags
,
56 int null_term
, int pxearch
,
62 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
63 static int do_encap_opts(struct dhcp_opt
*opts
, int encap
, int flag
, struct dhcp_packet
*mess
, unsigned char *end
, int null_term
);
64 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
);
65 static int prune_vendor_opts(struct dhcp_netid
*netid
);
66 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
);
67 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
);
70 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
71 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
, int pxe
, struct in_addr fallback
)
73 unsigned char *opt
, *clid
= NULL
;
74 struct dhcp_lease
*ltmp
, *lease
= NULL
;
75 struct dhcp_vendor
*vendor
;
77 struct dhcp_netid_list
*id_list
;
78 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0, pxearch
= -1;
79 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
80 unsigned char *end
= (unsigned char *)(mess
+ 1);
81 unsigned char *real_end
= (unsigned char *)(mess
+ 1);
82 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
, *domain
= NULL
;
83 int hostname_auth
= 0, borken_opt
= 0;
84 unsigned char *req_options
= NULL
;
87 struct dhcp_config
*config
;
88 struct dhcp_netid
*netid
, *tagif_netid
;
89 struct in_addr subnet_addr
, override
;
90 unsigned short fuzz
= 0;
91 unsigned int mess_type
= 0;
92 unsigned char fqdn_flags
= 0;
93 unsigned char *agent_id
= NULL
, *uuid
= NULL
;
94 unsigned char *emac
= NULL
;
95 int vendor_class_len
= 0, emac_len
= 0;
96 struct dhcp_netid known_id
, iface_id
, cpewan_id
;
98 unsigned char pxe_uuid
[17];
99 unsigned char *oui
= NULL
, *serial
= NULL
, *class = NULL
;
101 subnet_addr
.s_addr
= override
.s_addr
= 0;
103 /* set tag with name == interface */
104 iface_id
.net
= iface_name
;
105 iface_id
.next
= NULL
;
108 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
111 if (mess
->htype
== 0 && mess
->hlen
!= 0)
114 /* check for DHCP rather than BOOTP */
115 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
117 u32 cookie
= htonl(DHCP_COOKIE
);
119 /* only insist on a cookie for DHCP. */
120 if (memcmp(mess
->options
, &cookie
, sizeof(u32
)) != 0)
123 mess_type
= option_uint(opt
, 0, 1);
125 /* two things to note here: expand_buf may move the packet,
126 so reassign mess from daemon->packet. Also, the size
127 sent includes the IP and UDP headers, hence the magic "-28" */
128 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
130 size_t size
= (size_t)option_uint(opt
, 0, 2) - 28;
132 if (size
> DHCP_PACKET_MAX
)
133 size
= DHCP_PACKET_MAX
;
134 else if (size
< sizeof(struct dhcp_packet
))
135 size
= sizeof(struct dhcp_packet
);
137 if (expand_buf(&daemon
->dhcp_packet
, size
))
139 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
140 real_end
= end
= ((unsigned char *)mess
) + size
;
144 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
145 it can affect the context-determination code. */
146 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
147 mess
->ciaddr
.s_addr
= 0;
149 /* search for device identity from CPEWAN devices, we pass this through to the script */
150 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT_OPT
, 5)))
152 unsigned int elen
, offset
, len
= option_len(opt
);
154 for (offset
= 0; offset
< (len
- 5); offset
+= elen
+ 5)
156 elen
= option_uint(opt
, offset
+ 4 , 1);
157 if (option_uint(opt
, offset
, 4) == BRDBAND_FORUM_IANA
)
159 unsigned char *x
= option_ptr(opt
, offset
+ 5);
160 unsigned char *y
= option_ptr(opt
, offset
+ elen
+ 5);
161 oui
= option_find1(x
, y
, 1, 1);
162 serial
= option_find1(x
, y
, 2, 1);
163 class = option_find1(x
, y
, 3, 1);
165 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
166 the gateway id back. Note that the device class is optional */
169 cpewan_id
.net
= "cpewan-id";
170 cpewan_id
.next
= netid
;
178 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
180 /* Any agent-id needs to be copied back out, verbatim, as the last option
181 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
182 get overwritten, then it will be shuffled back at the end of processing.
183 Note that the incoming options must not be overwritten here, so there has to
184 be enough free space at the end of the packet to copy the option. */
186 unsigned int total
= option_len(opt
) + 2;
187 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
188 if (last_opt
&& last_opt
< end
- total
)
192 memcpy(agent_id
, opt
, total
);
195 /* look for RFC3527 Link selection sub-option */
196 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
197 subnet_addr
= option_addr(sopt
);
199 /* look for RFC5107 server-identifier-override */
200 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_SERVER_OR
, INADDRSZ
)))
201 override
= option_addr(sopt
);
203 /* if a circuit-id or remote-is option is provided, exact-match to options. */
204 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
208 if (vendor
->match_type
== MATCH_CIRCUIT
)
209 search
= SUBOPT_CIRCUIT_ID
;
210 else if (vendor
->match_type
== MATCH_REMOTE
)
211 search
= SUBOPT_REMOTE_ID
;
212 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
213 search
= SUBOPT_SUBSCR_ID
;
217 if ((sopt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), search
, 1)) &&
218 vendor
->len
== option_len(sopt
) &&
219 memcmp(option_ptr(sopt
, 0), vendor
->data
, vendor
->len
) == 0)
221 vendor
->netid
.next
= netid
;
222 netid
= &vendor
->netid
;
227 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
228 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
229 subnet_addr
= option_addr(opt
);
231 /* If there is no client identifier option, use the hardware address */
232 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
234 clid_len
= option_len(opt
);
235 clid
= option_ptr(opt
, 0);
238 /* do we have a lease in store? */
239 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
241 /* If this request is missing a clid, but we've seen one before,
242 use it again for option matching etc. */
243 if (lease
&& !clid
&& lease
->clid
)
245 clid_len
= lease
->clid_len
;
249 /* find mac to use for logging and hashing */
250 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
253 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
254 if (mac
->hwaddr_len
== mess
->hlen
&&
255 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
256 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
258 mac
->netid
.next
= netid
;
262 /* Determine network for this packet. Our caller will have already linked all the
263 contexts which match the addresses of the receiving interface but if the
264 machine has an address already, or came via a relay, or we have a subnet selector,
265 we search again. If we don't have have a giaddr or explicit subnet selector,
266 use the ciaddr. This is necessary because a machine which got a lease via a
267 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
268 from the physical network, continue using that to allow correct DHCPNAK generation later. */
269 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
271 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
275 if (subnet_addr
.s_addr
)
280 else if (mess
->giaddr
.s_addr
)
287 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
289 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
290 if (context_tmp
->netmask
.s_addr
&&
291 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
292 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
294 context_new
= context
;
300 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
302 struct in_addr netmask
= context_tmp
->netmask
;
304 /* guess the netmask for relayed networks */
305 if (!(context_tmp
->flags
& CONTEXT_NETMASK
) && context_tmp
->netmask
.s_addr
== 0)
307 if (IN_CLASSA(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSA(ntohl(context_tmp
->end
.s_addr
)))
308 netmask
.s_addr
= htonl(0xff000000);
309 else if (IN_CLASSB(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSB(ntohl(context_tmp
->end
.s_addr
)))
310 netmask
.s_addr
= htonl(0xffff0000);
311 else if (IN_CLASSC(ntohl(context_tmp
->start
.s_addr
)) && IN_CLASSC(ntohl(context_tmp
->end
.s_addr
)))
312 netmask
.s_addr
= htonl(0xffffff00);
315 /* This section fills in context mainly when a client which is on a remote (relayed)
316 network renews a lease without using the relay, after dnsmasq has restarted. */
317 if (netmask
.s_addr
!= 0 &&
318 is_same_net(addr
, context_tmp
->start
, netmask
) &&
319 is_same_net(addr
, context_tmp
->end
, netmask
))
321 context_tmp
->netmask
= netmask
;
322 if (context_tmp
->local
.s_addr
== 0)
323 context_tmp
->local
= fallback
;
324 if (context_tmp
->router
.s_addr
== 0)
325 context_tmp
->router
= mess
->giaddr
;
327 /* fill in missing broadcast addresses for relayed ranges */
328 if (!(context_tmp
->flags
& CONTEXT_BRDCAST
) && context_tmp
->broadcast
.s_addr
== 0 )
329 context_tmp
->broadcast
.s_addr
= context_tmp
->start
.s_addr
| ~context_tmp
->netmask
.s_addr
;
331 context_tmp
->current
= context_new
;
332 context_new
= context_tmp
;
336 if (context_new
|| force
)
337 context
= context_new
;
342 my_syslog(MS_DHCP
| LOG_WARNING
, _("no address range available for DHCP request %s %s"),
343 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
344 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
348 if (option_bool(OPT_LOG_OPTS
))
350 struct dhcp_context
*context_tmp
;
351 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
353 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
354 if (context_tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_PROXY
))
355 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP subnet: %s/%s"),
356 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
358 my_syslog(MS_DHCP
| LOG_INFO
, _("%u available DHCP range: %s -- %s"),
359 ntohl(mess
->xid
), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
363 mess
->op
= BOOTREPLY
;
365 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
366 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
368 /* set "known" tag for known hosts */
371 known_id
.net
= "known";
372 known_id
.next
= netid
;
376 if (mess_type
== 0 && !pxe
)
379 struct dhcp_netid id
, bootp_id
;
380 struct in_addr
*logaddr
= NULL
;
382 /* must have a MAC addr for bootp */
383 if (mess
->htype
== 0 || mess
->hlen
== 0 || (context
->flags
& CONTEXT_PROXY
))
386 if (have_config(config
, CONFIG_DISABLE
))
387 message
= _("disabled");
389 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
391 if (have_config(config
, CONFIG_NAME
))
393 hostname
= config
->hostname
;
394 domain
= config
->domain
;
399 struct dhcp_netid_list
*list
;
401 for (list
= config
->netid
; list
; list
= list
->next
)
403 list
->list
->next
= netid
;
408 /* Match incoming filename field as a netid. */
411 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
412 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
413 id
.net
= (char *)daemon
->dhcp_buff2
;
418 /* Add "bootp" as a tag to allow different options, address ranges etc
420 bootp_id
.net
= "bootp";
421 bootp_id
.next
= netid
;
424 tagif_netid
= run_tag_if(netid
);
426 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
427 if (match_netid(id_list
->list
, tagif_netid
, 0))
428 message
= _("ignored");
434 if (have_config(config
, CONFIG_ADDR
))
437 logaddr
= &config
->addr
;
438 mess
->yiaddr
= config
->addr
;
439 if ((lease
= lease_find_by_addr(config
->addr
)) &&
440 (lease
->hwaddr_len
!= mess
->hlen
||
441 lease
->hwaddr_type
!= mess
->htype
||
442 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
443 message
= _("address in use");
447 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
448 !address_available(context
, lease
->addr
, tagif_netid
))
452 /* lease exists, wrong network. */
453 lease_prune(lease
, now
);
456 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, tagif_netid
, now
))
457 message
= _("no address available");
460 mess
->yiaddr
= lease
->addr
;
463 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
464 message
= _("wrong network");
465 else if (context
->netid
.net
)
467 context
->netid
.next
= netid
;
468 tagif_netid
= run_tag_if(&context
->netid
);
471 log_tags(tagif_netid
, mess
);
473 if (!message
&& !nailed
)
475 for (id_list
= daemon
->bootp_dynamic
; id_list
; id_list
= id_list
->next
)
476 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
479 message
= _("no address configured");
484 (!(lease
= lease_allocate4(mess
->yiaddr
))))
485 message
= _("no leases left");
489 logaddr
= &mess
->yiaddr
;
491 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0);
493 lease_set_hostname(lease
, hostname
, 1);
494 /* infinite lease unless nailed in dhcp-host line. */
495 lease_set_expires(lease
,
496 have_config(config
, CONFIG_TIME
) ? config
->lease_time
: 0xffffffff,
498 lease_set_interface(lease
, int_index
);
500 clear_packet(mess
, end
);
501 do_options(context
, mess
, end
, NULL
, hostname
, get_domain(mess
->yiaddr
),
502 domain
, netid
, subnet_addr
, 0, 0, 0, NULL
, 0, now
);
506 log_packet("BOOTP", logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
, mess
->xid
);
508 return message
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
511 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
513 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
514 int len
= option_len(opt
);
515 char *pq
= daemon
->dhcp_buff
;
516 unsigned char *pp
, *op
= option_ptr(opt
, 0);
523 /* Always force update, since the client has no way to do it itself. */
524 if (!option_bool(OPT_FQDN_UPDATE
) && !(fqdn_flags
& 0x01))
529 if (fqdn_flags
& 0x04)
530 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
532 memcpy(pq
, op
+1, *op
);
540 if (len
> 0 && op
[len
-1] == 0)
545 if (pq
!= daemon
->dhcp_buff
)
550 if (legal_hostname(daemon
->dhcp_buff
))
551 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
553 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
555 int len
= option_len(opt
);
556 memcpy(daemon
->dhcp_buff
, option_ptr(opt
, 0), len
);
557 /* Microsoft clients are broken, and need zero-terminated strings
558 in options. We detect this state here, and do the same in
559 any options we send */
560 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
563 daemon
->dhcp_buff
[len
] = 0;
564 if (legal_hostname(daemon
->dhcp_buff
))
565 client_hostname
= daemon
->dhcp_buff
;
568 if (client_hostname
&& option_bool(OPT_LOG_OPTS
))
569 my_syslog(MS_DHCP
| LOG_INFO
, _("%u client provides name: %s"), ntohl(mess
->xid
), client_hostname
);
571 if (have_config(config
, CONFIG_NAME
))
573 hostname
= config
->hostname
;
574 domain
= config
->domain
;
576 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
577 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
578 offer_hostname
= hostname
;
580 else if (client_hostname
)
582 domain
= strip_hostname(client_hostname
);
584 if (strlen(client_hostname
) != 0)
586 hostname
= client_hostname
;
589 /* Search again now we have a hostname.
590 Only accept configs without CLID and HWADDR here, (they won't match)
591 to avoid impersonation by name. */
592 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
593 mess
->chaddr
, mess
->hlen
,
594 mess
->htype
, hostname
);
595 if (new && !have_config(new, CONFIG_CLID
) && !new->hwaddr
)
598 /* set "known" tag for known hosts */
599 known_id
.net
= "known";
600 known_id
.next
= netid
;
609 struct dhcp_netid_list
*list
;
611 for (list
= config
->netid
; list
; list
= list
->next
)
613 list
->list
->next
= netid
;
618 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
619 Otherwise assume the option is an array, and look for a matching element.
620 If no data given, existance of the option is enough. This code handles
621 rfc3925 V-I classes too. */
622 for (o
= daemon
->dhcp_match
; o
; o
= o
->next
)
624 unsigned int len
, elen
, match
= 0;
627 if (o
->flags
& DHOPT_RFC3925
)
629 if (!(opt
= option_find(mess
, sz
, OPTION_VENDOR_IDENT
, 5)))
632 for (offset
= 0; offset
< (option_len(opt
) - 5u); offset
+= len
+ 5)
634 len
= option_uint(opt
, offset
+ 4 , 1);
635 /* Need to take care that bad data can't run us off the end of the packet */
636 if ((offset
+ len
+ 5 <= (option_len(opt
))) &&
637 (option_uint(opt
, offset
, 4) == (unsigned int)o
->u
.encap
))
638 for (o2
= offset
+ 5; o2
< offset
+ len
+ 5; o2
+= elen
+ 1)
640 elen
= option_uint(opt
, o2
, 1);
641 if ((o2
+ elen
+ 1 <= option_len(opt
)) &&
642 (match
= match_bytes(o
, option_ptr(opt
, o2
+ 1), elen
)))
651 if (!(opt
= option_find(mess
, sz
, o
->opt
, 1)))
654 match
= match_bytes(o
, option_ptr(opt
, 0), option_len(opt
));
659 o
->netid
->next
= netid
;
664 /* user-class options are, according to RFC3004, supposed to contain
665 a set of counted strings. Here we check that this is so (by seeing
666 if the counts are consistent with the overall option length) and if
667 so zero the counts so that we don't get spurious matches between
668 the vendor string and the counts. If the lengths don't add up, we
669 assume that the option is a single string and non RFC3004 compliant
670 and just do the substring match. dhclient provides these broken options.
671 The code, later, which sends user-class data to the lease-change script
672 relies on the transformation done here.
675 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
677 unsigned char *ucp
= option_ptr(opt
, 0);
679 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
680 if (j
== option_len(opt
))
681 for (j
= 0; j
< option_len(opt
); j
= tmp
)
683 tmp
= j
+ ucp
[j
] + 1;
688 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
692 if (vendor
->match_type
== MATCH_VENDOR
)
693 mopt
= OPTION_VENDOR_ID
;
694 else if (vendor
->match_type
== MATCH_USER
)
695 mopt
= OPTION_USER_CLASS
;
699 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
702 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
703 if (memcmp(vendor
->data
, option_ptr(opt
, i
), vendor
->len
) == 0)
705 vendor
->netid
.next
= netid
;
706 netid
= &vendor
->netid
;
712 /* mark vendor-encapsulated options which match the client-supplied vendor class,
713 save client-supplied vendor class */
714 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
716 memcpy(daemon
->dhcp_buff3
, option_ptr(opt
, 0), option_len(opt
));
717 vendor_class_len
= option_len(opt
);
719 match_vendor_opts(opt
, daemon
->dhcp_opts
);
721 if (option_bool(OPT_LOG_OPTS
))
723 if (sanitise(opt
, daemon
->namebuff
))
724 my_syslog(MS_DHCP
| LOG_INFO
, _("%u vendor class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
725 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
726 my_syslog(MS_DHCP
| LOG_INFO
, _("%u user class: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
729 tagif_netid
= run_tag_if(netid
);
731 /* if all the netids in the ignore list are present, ignore this client */
732 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
733 if (match_netid(id_list
->list
, tagif_netid
, 0))
736 /* If configured, we can override the server-id to be the address of the relay,
737 so that all traffic goes via the relay and can pick up agent-id info. This can be
738 configured for all relays, or by address. */
739 if (daemon
->override
&& mess
->giaddr
.s_addr
!= 0 && override
.s_addr
== 0)
741 if (!daemon
->override_relays
)
742 override
= mess
->giaddr
;
746 for (l
= daemon
->override_relays
; l
; l
= l
->next
)
747 if (l
->addr
.s_addr
== mess
->giaddr
.s_addr
)
750 override
= mess
->giaddr
;
754 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
755 if (have_config(config
, CONFIG_NOCLID
))
758 /* Check if client is PXE client. */
759 if (daemon
->enable_pxe
&&
760 (opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 9)) &&
761 strncmp(option_ptr(opt
, 0), "PXEClient", 9) == 0)
763 if ((opt
= option_find(mess
, sz
, OPTION_PXE_UUID
, 17)))
765 memcpy(pxe_uuid
, option_ptr(opt
, 0), 17);
769 /* Check if this is really a PXE bootserver request, and handle specially if so. */
770 if ((mess_type
== DHCPREQUEST
|| mess_type
== DHCPINFORM
) &&
771 (opt
= option_find(mess
, sz
, OPTION_VENDOR_CLASS_OPT
, 1)) &&
772 (opt
= option_find1(option_ptr(opt
, 0), option_ptr(opt
, option_len(opt
)), SUBOPT_PXE_BOOT_ITEM
, 4)))
774 struct pxe_service
*service
;
775 int type
= option_uint(opt
, 0, 2);
776 int layer
= option_uint(opt
, 2, 2);
777 unsigned char save71
[4];
778 struct dhcp_opt opt71
;
785 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE BIS not supported"));
789 memcpy(save71
, option_ptr(opt
, 0), 4);
791 for (service
= daemon
->pxe_services
; service
; service
= service
->next
)
792 if (service
->type
== type
)
795 if (!service
|| !service
->basename
)
798 clear_packet(mess
, end
);
800 mess
->yiaddr
= mess
->ciaddr
;
801 mess
->ciaddr
.s_addr
= 0;
802 if (service
->server
.s_addr
!= 0)
803 mess
->siaddr
= service
->server
;
805 mess
->siaddr
= context
->local
;
807 snprintf((char *)mess
->file
, sizeof(mess
->file
), "%s.%d", service
->basename
, layer
);
808 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
809 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
810 pxe_misc(mess
, end
, uuid
);
812 prune_vendor_opts(tagif_netid
);
814 opt71
.opt
= SUBOPT_PXE_BOOT_ITEM
;
816 opt71
.flags
= DHOPT_VENDOR_MATCH
;
818 opt71
.next
= daemon
->dhcp_opts
;
819 do_encap_opts(&opt71
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
821 log_packet("PXE", &mess
->yiaddr
, emac
, emac_len
, iface_name
, (char *)mess
->file
, mess
->xid
);
822 log_tags(tagif_netid
, mess
);
823 return dhcp_packet_size(mess
, agent_id
, real_end
);
826 if ((opt
= option_find(mess
, sz
, OPTION_ARCH
, 2)))
828 pxearch
= option_uint(opt
, 0, 2);
830 /* proxy DHCP here. */
831 if ((mess_type
== DHCPDISCOVER
|| (pxe
&& mess_type
== DHCPREQUEST
)))
833 struct dhcp_context
*tmp
;
835 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
836 if ((tmp
->flags
& CONTEXT_PROXY
) &&
837 match_netid(tmp
->filter
, tagif_netid
, 1))
842 struct dhcp_boot
*boot
= find_boot(tagif_netid
);
844 mess
->yiaddr
.s_addr
= 0;
845 if (mess_type
== DHCPDISCOVER
|| mess
->ciaddr
.s_addr
== 0)
847 mess
->ciaddr
.s_addr
= 0;
848 mess
->flags
|= htons(0x8000); /* broadcast */
851 clear_packet(mess
, end
);
853 /* Provide the bootfile here, for gPXE, and in case we have no menu items
854 and set discovery_control = 8 */
857 if (boot
->next_server
.s_addr
)
858 mess
->siaddr
= boot
->next_server
;
859 else if (boot
->tftp_sname
)
860 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
863 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
866 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1,
867 mess_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
);
868 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, htonl(context
->local
.s_addr
));
869 pxe_misc(mess
, end
, uuid
);
870 prune_vendor_opts(tagif_netid
);
871 do_encap_opts(pxe_opts(pxearch
, tagif_netid
, context
->local
), OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, 0);
873 log_packet("PXE", NULL
, emac
, emac_len
, iface_name
, ignore
? "proxy-ignored" : "proxy", mess
->xid
);
874 log_tags(tagif_netid
, mess
);
875 return ignore
? 0 : dhcp_packet_size(mess
, agent_id
, real_end
);
881 /* if we're just a proxy server, go no further */
882 if ((context
->flags
& CONTEXT_PROXY
) || pxe
)
885 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
887 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
888 memcpy(req_options
, option_ptr(opt
, 0), option_len(opt
));
889 req_options
[option_len(opt
)] = OPTION_END
;
895 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
896 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
899 /* sanitise any message. Paranoid? Moi? */
900 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
902 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
905 log_packet("DHCPDECLINE", option_ptr(opt
, 0), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
, mess
->xid
);
907 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
908 lease_prune(lease
, now
);
910 if (have_config(config
, CONFIG_ADDR
) &&
911 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
913 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
914 my_syslog(MS_DHCP
| LOG_WARNING
, _("disabling DHCP static address %s for %s"),
915 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
916 config
->flags
|= CONFIG_DECLINED
;
917 config
->decline_time
= now
;
920 /* make sure this host gets a different address next time. */
921 for (; context
; context
= context
->current
)
922 context
->addr_epoch
++;
927 if (!(context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
)) ||
928 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
929 option_addr(opt
).s_addr
!= server_id(context
, override
, fallback
).s_addr
)
932 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
933 lease_prune(lease
, now
);
935 message
= _("unknown lease");
937 log_packet("DHCPRELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
942 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
944 message
= _("ignored");
949 struct in_addr addr
, conf
;
951 addr
.s_addr
= conf
.s_addr
= 0;
953 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
954 addr
= option_addr(opt
);
956 if (have_config(config
, CONFIG_ADDR
))
958 char *addrs
= inet_ntoa(config
->addr
);
960 if ((ltmp
= lease_find_by_addr(config
->addr
)) &&
962 !config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
965 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
966 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
967 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
968 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
972 struct dhcp_context
*tmp
;
973 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
974 if (context
->router
.s_addr
== config
->addr
.s_addr
)
977 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
978 else if (have_config(config
, CONFIG_DECLINED
) &&
979 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
980 my_syslog(MS_DHCP
| LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
989 address_available(context
, lease
->addr
, tagif_netid
) &&
990 !config_find_by_address(daemon
->dhcp_conf
, lease
->addr
))
991 mess
->yiaddr
= lease
->addr
;
992 else if (opt
&& address_available(context
, addr
, tagif_netid
) && !lease_find_by_addr(addr
) &&
993 !config_find_by_address(daemon
->dhcp_conf
, addr
))
995 else if (emac_len
== 0)
996 message
= _("no unique-id");
997 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, tagif_netid
, now
))
998 message
= _("no address available");
1001 log_packet("DHCPDISCOVER", opt
? option_ptr(opt
, 0) : NULL
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1003 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1006 if (context
->netid
.net
)
1008 context
->netid
.next
= netid
;
1009 tagif_netid
= run_tag_if(&context
->netid
);
1012 log_tags(tagif_netid
, mess
);
1014 log_packet("DHCPOFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1016 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1017 clear_packet(mess
, end
);
1018 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
1019 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1020 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1021 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1022 if (time
!= 0xffffffff)
1024 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
1025 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
1027 do_options(context
, mess
, end
, req_options
, offer_hostname
, get_domain(mess
->yiaddr
),
1028 domain
, netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1030 return dhcp_packet_size(mess
, agent_id
, real_end
);
1033 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1035 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
1037 /* SELECTING or INIT_REBOOT */
1038 mess
->yiaddr
= option_addr(opt
);
1040 /* send vendor and user class info for new or recreated lease */
1043 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
1048 if (override
.s_addr
!= 0)
1050 if (option_addr(opt
).s_addr
!= override
.s_addr
)
1055 for (; context
; context
= context
->current
)
1056 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
1061 /* Handle very strange configs where clients have more than one route to the server.
1062 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1063 Have to set override to make sure we echo back the correct server-id */
1066 enumerate_interfaces();
1068 for (intr
= daemon
->interfaces
; intr
; intr
= intr
->next
)
1069 if (intr
->addr
.sa
.sa_family
== AF_INET
&&
1070 intr
->addr
.in
.sin_addr
.s_addr
== option_addr(opt
).s_addr
&&
1075 override
= intr
->addr
.in
.sin_addr
;
1078 /* In auth mode, a REQUEST sent to the wrong server
1079 should be faulted, so that the client establishes
1080 communication with us, otherwise, silently ignore. */
1081 if (!option_bool(OPT_AUTHORITATIVE
))
1083 message
= _("wrong server-ID");
1088 /* If a lease exists for this host and another address, squash it. */
1089 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1091 lease_prune(lease
, now
);
1098 if (!lease
&& !option_bool(OPT_AUTHORITATIVE
))
1101 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
1102 message
= _("wrong address");
1107 /* RENEWING or REBINDING */
1108 /* Check existing lease for this address.
1109 We allow it to be missing if dhcp-authoritative mode
1110 as long as we can allocate the lease now - checked below.
1111 This makes for a smooth recovery from a lost lease DB */
1112 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
1113 (!lease
&& !option_bool(OPT_AUTHORITATIVE
)))
1115 /* A client rebinding will broadcast the request, so we may see it even
1116 if the lease is held by another server. Just ignore it in that case.
1117 If the request is unicast to us, then somethings wrong, NAK */
1120 message
= _("lease not found");
1121 /* ensure we broadcast NAK */
1125 /* desynchronise renewals */
1127 mess
->yiaddr
= mess
->ciaddr
;
1130 log_packet("DHCPREQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
, mess
->xid
);
1134 struct dhcp_config
*addr_config
;
1135 struct dhcp_context
*tmp
= NULL
;
1137 if (have_config(config
, CONFIG_ADDR
))
1138 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
1139 if (context
->router
.s_addr
== config
->addr
.s_addr
)
1142 if (!(context
= narrow_context(context
, mess
->yiaddr
, tagif_netid
)))
1144 /* If a machine moves networks whilst it has a lease, we catch that here. */
1145 message
= _("wrong network");
1146 /* ensure we broadcast NAK */
1150 /* Check for renewal of a lease which is outside the allowed range. */
1151 else if (!address_available(context
, mess
->yiaddr
, tagif_netid
) &&
1152 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
1153 message
= _("address not available");
1155 /* Check if a new static address has been configured. Be very sure that
1156 when the client does DISCOVER, it will get the static address, otherwise
1157 an endless protocol loop will ensue. */
1158 else if (!tmp
&& !selecting
&&
1159 have_config(config
, CONFIG_ADDR
) &&
1160 (!have_config(config
, CONFIG_DECLINED
) ||
1161 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
1162 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
1163 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
1164 message
= _("static lease available");
1166 /* Check to see if the address is reserved as a static address for another host */
1167 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
1168 message
= _("address reserved");
1170 else if (!lease
&& (ltmp
= lease_find_by_addr(mess
->yiaddr
)))
1172 /* If a host is configured with more than one MAC address, it's OK to 'nix
1173 a lease from one of it's MACs to give the address to another. */
1174 if (config
&& config_has_mac(config
, ltmp
->hwaddr
, ltmp
->hwaddr_len
, ltmp
->hwaddr_type
))
1176 my_syslog(MS_DHCP
| LOG_INFO
, _("abandoning lease to %s of %s"),
1177 print_mac(daemon
->namebuff
, ltmp
->hwaddr
, ltmp
->hwaddr_len
),
1178 inet_ntoa(ltmp
->addr
));
1182 message
= _("address in use");
1188 message
= _("no unique-id");
1192 if ((lease
= lease_allocate4(mess
->yiaddr
)))
1195 message
= _("no leases left");
1202 log_packet("DHCPNAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1204 mess
->yiaddr
.s_addr
= 0;
1205 clear_packet(mess
, end
);
1206 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
1207 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1208 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
1209 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1210 a distant subnet which unicast a REQ to us won't work. */
1211 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
1212 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
1214 mess
->flags
|= htons(0x8000); /* broadcast */
1215 mess
->ciaddr
.s_addr
= 0;
1220 if (context
->netid
.net
)
1222 context
->netid
.next
= netid
;
1223 tagif_netid
= run_tag_if( &context
->netid
);
1226 log_tags(tagif_netid
, mess
);
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
= NULL
;
1239 lease
->extradata_size
= lease
->extradata_len
= 0;
1241 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_VENDOR_ID
, 1));
1242 add_extradata_opt(lease
, option_find(mess
, sz
, OPTION_HOSTNAME
, 1));
1243 add_extradata_opt(lease
, oui
);
1244 add_extradata_opt(lease
, serial
);
1245 add_extradata_opt(lease
, class);
1247 /* space-concat tag set */
1249 add_extradata_opt(lease
, NULL
);
1251 for (n
= tagif_netid
; n
; n
= n
->next
)
1252 add_extradata_data(lease
, (unsigned char *)n
->net
, strlen(n
->net
), n
->next
? ' ' : 0);
1254 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
1256 int len
= option_len(opt
);
1257 unsigned char *ucp
= option_ptr(opt
, 0);
1258 /* If the user-class option started as counted strings, the first byte will be zero. */
1259 if (len
!= 0 && ucp
[0] == 0)
1261 add_extradata_data(lease
, ucp
, len
, 0);
1266 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
1268 domain
= get_domain(mess
->yiaddr
);
1269 hostname
= client_hostname
;
1273 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
1274 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
);
1276 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1279 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
1280 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1286 /* Last ditch, if configured, generate hostname from mac address */
1287 if (!hostname
&& emac_len
!= 0)
1289 for (id_list
= daemon
->dhcp_gen_names
; id_list
; id_list
= id_list
->next
)
1290 if ((!id_list
->list
) || match_netid(id_list
->list
, tagif_netid
, 0))
1296 hostname
= daemon
->dhcp_buff
;
1297 /* buffer is 256 bytes, 3 bytes per octet */
1298 for (i
= 0; (i
< emac_len
) && (i
< 80); i
++)
1299 hostname
+= sprintf(hostname
, "%.2x%s", emac
[i
], (i
== emac_len
- 1) ? "" : "-");
1300 hostname
= daemon
->dhcp_buff
;
1305 lease_set_hostname(lease
, hostname
, hostname_auth
);
1307 lease_set_expires(lease
, time
, now
);
1308 lease_set_interface(lease
, int_index
);
1310 if (override
.s_addr
!= 0)
1311 lease
->override
= override
;
1313 override
= lease
->override
;
1315 log_packet("DHCPACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1317 clear_packet(mess
, end
);
1318 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1319 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1320 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1321 if (time
!= 0xffffffff)
1323 while (fuzz
> (time
/16))
1325 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
1326 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
1328 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->yiaddr
),
1329 domain
, netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1332 return dhcp_packet_size(mess
, agent_id
, real_end
);
1335 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
1336 message
= _("ignored");
1338 log_packet("DHCPINFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
, mess
->xid
);
1340 if (message
|| mess
->ciaddr
.s_addr
== 0)
1343 /* For DHCPINFORM only, cope without a valid context */
1344 context
= narrow_context(context
, mess
->ciaddr
, tagif_netid
);
1346 /* Find a least based on IP address if we didn't
1347 get one from MAC address/client-d */
1349 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1351 hostname
= lease
->hostname
;
1353 if (!hostname
&& (hostname
= host_from_dns(mess
->ciaddr
)))
1354 domain
= get_domain(mess
->ciaddr
);
1356 if (context
&& context
->netid
.net
)
1358 context
->netid
.next
= netid
;
1359 tagif_netid
= run_tag_if( &context
->netid
);
1362 log_tags(tagif_netid
, mess
);
1364 log_packet("DHCPACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
, mess
->xid
);
1368 if (override
.s_addr
!= 0)
1369 lease
->override
= override
;
1371 override
= lease
->override
;
1374 clear_packet(mess
, end
);
1375 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1376 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(server_id(context
, override
, fallback
).s_addr
));
1380 if (lease
->expires
== 0)
1383 time
= (unsigned int)difftime(lease
->expires
, now
);
1384 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1385 lease_set_interface(lease
, int_index
);
1388 do_options(context
, mess
, end
, req_options
, hostname
, get_domain(mess
->ciaddr
),
1389 domain
, netid
, subnet_addr
, fqdn_flags
, borken_opt
, pxearch
, uuid
, vendor_class_len
, now
);
1391 *is_inform
= 1; /* handle reply differently */
1392 return dhcp_packet_size(mess
, agent_id
, real_end
);
1398 static int match_bytes(struct dhcp_opt
*o
, unsigned char *p
, int len
)
1408 if (o
->flags
& DHOPT_HEX
)
1410 if (memcmp_masked(o
->val
, p
, o
->len
, o
->u
.wildcard_mask
))
1414 for (i
= 0; i
<= (len
- o
->len
); )
1416 if (memcmp(o
->val
, p
+ i
, o
->len
) == 0)
1419 if (o
->flags
& DHOPT_STRING
)
1429 /* find a good value to use as MAC address for logging and address-allocation hashing.
1430 This is normally just the chaddr field from the DHCP packet,
1431 but eg Firewire will have hlen == 0 and use the client-id instead.
1432 This could be anything, but will normally be EUI64 for Firewire.
1433 We assume that if the first byte of the client-id equals the htype byte
1434 then the client-id is using the usual encoding and use the rest of the
1435 client-id: if not we can use the whole client-id. This should give
1436 sane MAC address logs. */
1437 unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1438 int clid_len
, unsigned char *clid
, int *len_out
)
1440 if (hwlen
== 0 && clid
&& clid_len
> 3)
1442 if (clid
[0] == hwtype
)
1444 *len_out
= clid_len
- 1 ;
1448 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1449 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1451 *len_out
= clid_len
- 1 ;
1456 *len_out
= clid_len
;
1464 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1466 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1470 unsigned int req_time
= option_uint(opt
, 0, 4);
1471 if (req_time
< 120 )
1472 req_time
= 120; /* sanity */
1473 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1480 static struct in_addr
server_id(struct dhcp_context
*context
, struct in_addr override
, struct in_addr fallback
)
1482 if (override
.s_addr
!= 0)
1484 else if (context
&& context
->local
.s_addr
!= 0)
1485 return context
->local
;
1490 static int sanitise(unsigned char *opt
, char *buf
)
1500 p
= option_ptr(opt
, 0);
1502 for (i
= option_len(opt
); i
> 0; i
--)
1505 if (isprint((int)c
))
1508 *buf
= 0; /* add terminator */
1514 static void add_extradata_data(struct dhcp_lease
*lease
, unsigned char *data
, size_t len
, int delim
)
1516 if ((lease
->extradata_size
- lease
->extradata_len
) < (len
+ 1))
1518 size_t newsz
= lease
->extradata_len
+ len
+ 100;
1519 unsigned char *new = whine_malloc(newsz
);
1524 if (lease
->extradata
)
1526 memcpy(new, lease
->extradata
, lease
->extradata_len
);
1527 free(lease
->extradata
);
1530 lease
->extradata
= new;
1531 lease
->extradata_size
= newsz
;
1535 memcpy(lease
->extradata
+ lease
->extradata_len
, data
, len
);
1536 lease
->extradata
[lease
->extradata_len
+ len
] = delim
;
1537 lease
->extradata_len
+= len
+ 1;
1540 static void add_extradata_opt(struct dhcp_lease
*lease
, unsigned char *opt
)
1543 add_extradata_data(lease
, NULL
, 0, 0);
1546 size_t i
, len
= option_len(opt
);
1547 unsigned char *ucp
= option_ptr(opt
, 0);
1549 /* check for embeded NULLs */
1550 for (i
= 0; i
< len
; i
++)
1557 add_extradata_data(lease
, ucp
, len
, 0);
1562 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1563 int mac_len
, char *interface
, char *string
, u32 xid
)
1567 /* addr may be misaligned */
1569 memcpy(&a
, addr
, sizeof(a
));
1571 print_mac(daemon
->namebuff
, ext_mac
, mac_len
);
1573 if(option_bool(OPT_LOG_OPTS
))
1574 my_syslog(MS_DHCP
| LOG_INFO
, "%u %s(%s) %s%s%s %s",
1578 addr
? inet_ntoa(a
) : "",
1581 string
? string
: "");
1583 my_syslog(MS_DHCP
| LOG_INFO
, "%s(%s) %s%s%s %s",
1586 addr
? inet_ntoa(a
) : "",
1589 string
? string
: "");
1592 static void log_options(unsigned char *start
, u32 xid
)
1594 while (*start
!= OPTION_END
)
1596 int is_ip
, is_name
, i
;
1597 char *text
= option_string(start
[0], &is_ip
, &is_name
);
1598 unsigned char trunc
= option_len(start
);
1601 for (daemon
->namebuff
[0]= 0, i
= 0; i
<= trunc
- INADDRSZ
; i
+= INADDRSZ
)
1604 strncat(daemon
->namebuff
, ", ", 256 - strlen(daemon
->namebuff
));
1605 strncat(daemon
->namebuff
, inet_ntoa(option_addr_arr(start
, i
)), 256 - strlen(daemon
->namebuff
));
1607 else if (!is_name
|| !sanitise(start
, daemon
->namebuff
))
1611 print_mac(daemon
->namebuff
, option_ptr(start
, 0), trunc
);
1614 my_syslog(MS_DHCP
| LOG_INFO
, "%u sent size:%3d option:%3d%s%s%s%s%s",
1615 ntohl(xid
), option_len(start
), start
[0],
1616 text
? ":" : "", text
? text
: "",
1617 trunc
== 0 ? "" : " ",
1618 trunc
== 0 ? "" : daemon
->namebuff
,
1619 trunc
== option_len(start
) ? "" : "...");
1620 start
+= start
[1] + 2;
1624 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1630 else if (*p
== OPTION_END
)
1631 return opt
== OPTION_END
? p
: NULL
;
1632 else if (*p
== OPTION_PAD
)
1638 return NULL
; /* malformed packet */
1639 opt_len
= option_len(p
);
1640 if (p
> end
- (2 + opt_len
))
1641 return NULL
; /* malformed packet */
1642 if (*p
== opt
&& opt_len
>= minsize
)
1649 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1651 unsigned char *ret
, *overload
;
1653 /* skip over DHCP cookie; */
1654 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1657 /* look for overload option. */
1658 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1661 /* Can we look in filename area ? */
1662 if ((overload
[2] & 1) &&
1663 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1666 /* finally try sname area */
1667 if ((overload
[2] & 2) &&
1668 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1674 static struct in_addr
option_addr_arr(unsigned char *opt
, int offset
)
1676 /* this worries about unaligned data in the option. */
1677 /* struct in_addr is network byte order */
1680 memcpy(&ret
, option_ptr(opt
, offset
), INADDRSZ
);
1685 static struct in_addr
option_addr(unsigned char *opt
)
1687 return option_addr_arr(opt
, 0);
1690 static unsigned int option_uint(unsigned char *opt
, int offset
, int size
)
1692 /* this worries about unaligned data and byte order */
1693 unsigned int ret
= 0;
1695 unsigned char *p
= option_ptr(opt
, offset
);
1697 for (i
= 0; i
< size
; i
++)
1698 ret
= (ret
<< 8) | *p
++;
1703 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1706 start
+= start
[1] + 2;
1710 /* only for use when building packet: doesn't check for bad data. */
1711 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1713 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1717 if (*p
== OPTION_OVERLOAD
)
1724 static void log_tags(struct dhcp_netid
*netid
, struct dhcp_packet
*mess
)
1726 if (netid
&& option_bool(OPT_LOG_OPTS
))
1728 char *s
= daemon
->namebuff
;
1729 for (*s
= 0; netid
; netid
= netid
->next
)
1732 struct dhcp_netid
*n
;
1734 for (n
= netid
->next
; n
; n
= n
->next
)
1735 if (strcmp(netid
->net
, n
->net
) == 0)
1740 strncat (s
, netid
->net
, (MAXDNAME
-1) - strlen(s
));
1742 strncat (s
, ", ", (MAXDNAME
-1) - strlen(s
));
1745 my_syslog(MS_DHCP
| LOG_INFO
, _("%u tags: %s"), ntohl(mess
->xid
), s
);
1749 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, unsigned char *agent_id
, unsigned char *real_end
)
1751 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1752 unsigned char *overload
;
1755 /* move agent_id back down to the end of the packet */
1758 memmove(p
, agent_id
, real_end
- agent_id
);
1759 p
+= real_end
- agent_id
;
1760 memset(p
, 0, real_end
- p
); /* in case of overlap */
1763 /* add END options to the regions. */
1764 overload
= find_overload(mess
);
1766 if (overload
&& (option_uint(overload
, 0, 1) & 1))
1768 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1769 if (option_bool(OPT_LOG_OPTS
))
1770 log_options(mess
->file
, mess
->xid
);
1772 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->file
) != 0)
1773 my_syslog(MS_DHCP
| LOG_INFO
, _("%u bootfile name: %s"), ntohl(mess
->xid
), (char *)mess
->file
);
1775 if (overload
&& (option_uint(overload
, 0, 1) & 2))
1777 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1778 if (option_bool(OPT_LOG_OPTS
))
1779 log_options(mess
->sname
, mess
->xid
);
1781 else if (option_bool(OPT_LOG_OPTS
) && strlen((char *)mess
->sname
) != 0)
1782 my_syslog(MS_DHCP
| LOG_INFO
, _("%u server name: %s"), ntohl(mess
->xid
), (char *)mess
->sname
);
1787 if (option_bool(OPT_LOG_OPTS
))
1789 if (mess
->siaddr
.s_addr
!= 0)
1790 my_syslog(MS_DHCP
| LOG_INFO
, _("%u next server: %s"), ntohl(mess
->xid
), inet_ntoa(mess
->siaddr
));
1792 if ((mess
->flags
& htons(0x8000)) && mess
->ciaddr
.s_addr
== 0)
1793 my_syslog(MS_DHCP
| LOG_INFO
, _("%u broadcast response"), ntohl(mess
->xid
));
1795 log_options(&mess
->options
[0] + sizeof(u32
), mess
->xid
);
1798 ret
= (size_t)(p
- (unsigned char *)mess
);
1800 if (ret
< MIN_PACKETSZ
)
1806 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1808 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1810 if (p
+ len
+ 3 >= end
)
1811 /* not enough space in options area, try and use overload, if poss */
1813 unsigned char *overload
;
1815 if (!(overload
= find_overload(mess
)) &&
1816 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1818 /* attempt to overload fname and sname areas, we've reserved space for the
1819 overflow option previuously. */
1821 *(p
++) = OPTION_OVERLOAD
;
1827 /* using filename field ? */
1830 if (mess
->file
[0] == 0)
1833 if (overload
[2] & 1)
1835 p
= dhcp_skip_opts(mess
->file
);
1836 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1842 /* try to bring sname into play (it may be already) */
1843 if (mess
->sname
[0] == 0)
1846 if (overload
[2] & 2)
1848 p
= dhcp_skip_opts(mess
->sname
);
1849 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1856 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1868 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1871 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1874 for (i
= 0; i
< len
; i
++)
1875 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1878 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1879 char *string
, int null_term
)
1882 size_t len
= strlen(string
);
1884 if (null_term
&& len
!= 255)
1887 if ((p
= free_space(mess
, end
, opt
, len
)))
1888 memcpy(p
, string
, len
);
1891 /* return length, note this only does the data part */
1892 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct dhcp_context
*context
, int null_term
)
1896 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1901 if (context
&& (opt
->flags
& DHOPT_ADDR
))
1904 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1905 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1907 /* zero means "self" (but not in vendorclass options.) */
1909 memcpy(p
, &context
->local
, INADDRSZ
);
1911 memcpy(p
, a
, INADDRSZ
);
1916 memcpy(p
, opt
->val
, len
);
1921 static int in_list(unsigned char *list
, int opt
)
1925 /* If no requested options, send everything, not nothing. */
1929 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1936 static struct dhcp_opt
*option_find2(int opt
)
1938 struct dhcp_opt
*opts
;
1940 for (opts
= daemon
->dhcp_opts
; opts
; opts
= opts
->next
)
1941 if (opts
->opt
== opt
&& (opts
->flags
& DHOPT_TAGOK
))
1947 /* mark vendor-encapsulated options which match the client-supplied or
1948 config-supplied vendor class */
1949 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1951 for (; dopt
; dopt
= dopt
->next
)
1953 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1954 if (opt
&& (dopt
->flags
& DHOPT_VENDOR
))
1957 if (dopt
->u
.vendor_class
)
1958 len
= strlen((char *)dopt
->u
.vendor_class
);
1959 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1960 if (len
== 0 || memcmp(dopt
->u
.vendor_class
, option_ptr(opt
, i
), len
) == 0)
1962 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1969 static int do_encap_opts(struct dhcp_opt
*opt
, int encap
, int flag
,
1970 struct dhcp_packet
*mess
, unsigned char *end
, int null_term
)
1972 int len
, enc_len
, ret
= 0;
1973 struct dhcp_opt
*start
;
1976 /* find size in advance */
1977 for (enc_len
= 0, start
= opt
; opt
; opt
= opt
->next
)
1978 if (opt
->flags
& flag
)
1980 int new = do_opt(opt
, NULL
, NULL
, null_term
) + 2;
1982 if (enc_len
+ new <= 255)
1986 p
= free_space(mess
, end
, encap
, enc_len
);
1987 for (; start
&& start
!= opt
; start
= start
->next
)
1988 if (p
&& (start
->flags
& flag
))
1990 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
1991 *(p
++) = start
->opt
;
2001 (p
= free_space(mess
, end
, encap
, enc_len
+ 1)))
2003 for (; start
; start
= start
->next
)
2004 if (start
->flags
& flag
)
2006 len
= do_opt(start
, p
+ 2, NULL
, null_term
);
2007 *(p
++) = start
->opt
;
2017 static void pxe_misc(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *uuid
)
2021 option_put_string(mess
, end
, OPTION_VENDOR_ID
, "PXEClient", 0);
2022 if (uuid
&& (p
= free_space(mess
, end
, OPTION_PXE_UUID
, 17)))
2023 memcpy(p
, uuid
, 17);
2026 static int prune_vendor_opts(struct dhcp_netid
*netid
)
2029 struct dhcp_opt
*opt
;
2031 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
2032 for (opt
= daemon
->dhcp_opts
; opt
; opt
= opt
->next
)
2033 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
2035 if (!match_netid(opt
->netid
, netid
, 1))
2036 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
2037 else if (opt
->flags
& DHOPT_FORCE
)
2043 static struct dhcp_opt
*pxe_opts(int pxe_arch
, struct dhcp_netid
*netid
, struct in_addr local
)
2047 unsigned char *p
, *q
;
2048 struct pxe_service
*service
;
2049 static struct dhcp_opt
*o
, *ret
;
2050 int i
, j
= NUM_OPTS
- 1;
2051 struct in_addr boot_server
;
2053 /* We pass back references to these, hence they are declared static */
2054 static unsigned char discovery_control
;
2055 static unsigned char fake_prompt
[] = { 0, 'P', 'X', 'E' };
2056 static struct dhcp_opt
*fake_opts
= NULL
;
2058 /* Disable multicast, since we don't support it, and broadcast
2059 unless we need it */
2060 discovery_control
= 3;
2062 ret
= daemon
->dhcp_opts
;
2064 if (!fake_opts
&& !(fake_opts
= whine_malloc(NUM_OPTS
* sizeof(struct dhcp_opt
))))
2067 for (i
= 0; i
< NUM_OPTS
; i
++)
2069 fake_opts
[i
].flags
= DHOPT_VENDOR_MATCH
;
2070 fake_opts
[i
].netid
= NULL
;
2071 fake_opts
[i
].next
= i
== (NUM_OPTS
- 1) ? ret
: &fake_opts
[i
+1];
2074 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2075 p
= (unsigned char *)daemon
->dhcp_buff
;
2076 q
= (unsigned char *)daemon
->dhcp_buff3
;
2078 for (i
= 0, service
= daemon
->pxe_services
; service
; service
= service
->next
)
2079 if (pxe_arch
== service
->CSA
&& match_netid(service
->netid
, netid
, 1))
2081 size_t len
= strlen(service
->menu
);
2082 /* opt 43 max size is 255. encapsulated option has type and length
2083 bytes, so its max size is 253. */
2084 if (p
- (unsigned char *)daemon
->dhcp_buff
+ len
+ 3 < 253)
2086 *(p
++) = service
->type
>> 8;
2087 *(p
++) = service
->type
;
2089 memcpy(p
, service
->menu
, len
);
2096 my_syslog(MS_DHCP
| LOG_ERR
, _("PXE menu too large"));
2097 return daemon
->dhcp_opts
;
2100 boot_server
= service
->basename
? local
: service
->server
;
2102 if (boot_server
.s_addr
!= 0)
2104 if (q
- (unsigned char *)daemon
->dhcp_buff3
+ 3 + INADDRSZ
>= 253)
2107 /* Boot service with known address - give it */
2108 *(q
++) = service
->type
>> 8;
2109 *(q
++) = service
->type
;
2111 /* dest misaligned */
2112 memcpy(q
, &boot_server
.s_addr
, INADDRSZ
);
2115 else if (service
->type
!= 0)
2116 /* We don't know the server for a service type, so we'll
2117 allow the client to broadcast for it */
2118 discovery_control
= 2;
2121 /* if no prompt, wait forever if there's a choice */
2122 fake_prompt
[0] = (i
> 1) ? 255 : 0;
2125 discovery_control
= 8; /* no menu - just use use mess->filename */
2128 ret
= &fake_opts
[j
--];
2129 ret
->len
= p
- (unsigned char *)daemon
->dhcp_buff
;
2130 ret
->val
= (unsigned char *)daemon
->dhcp_buff
;
2131 ret
->opt
= SUBOPT_PXE_MENU
;
2133 if (q
- (unsigned char *)daemon
->dhcp_buff3
!= 0)
2135 ret
= &fake_opts
[j
--];
2136 ret
->len
= q
- (unsigned char *)daemon
->dhcp_buff3
;
2137 ret
->val
= (unsigned char *)daemon
->dhcp_buff3
;
2138 ret
->opt
= SUBOPT_PXE_SERVERS
;
2142 for (o
= daemon
->dhcp_opts
; o
; o
= o
->next
)
2143 if ((o
->flags
& DHOPT_VENDOR_MATCH
) && o
->opt
== SUBOPT_PXE_MENU_PROMPT
)
2148 ret
= &fake_opts
[j
--];
2149 ret
->len
= sizeof(fake_prompt
);
2150 ret
->val
= fake_prompt
;
2151 ret
->opt
= SUBOPT_PXE_MENU_PROMPT
;
2154 ret
= &fake_opts
[j
--];
2156 ret
->opt
= SUBOPT_PXE_DISCOVERY
;
2157 ret
->val
= &discovery_control
;
2162 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
2164 memset(mess
->sname
, 0, sizeof(mess
->sname
));
2165 memset(mess
->file
, 0, sizeof(mess
->file
));
2166 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
2167 mess
->siaddr
.s_addr
= 0;
2170 struct dhcp_boot
*find_boot(struct dhcp_netid
*netid
)
2172 struct dhcp_boot
*boot
;
2174 /* decide which dhcp-boot option we're using */
2175 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2176 if (match_netid(boot
->netid
, netid
, 0))
2179 /* No match, look for one without a netid */
2180 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
2181 if (match_netid(boot
->netid
, netid
, 1))
2187 static void do_options(struct dhcp_context
*context
,
2188 struct dhcp_packet
*mess
,
2190 unsigned char *req_options
,
2192 char *domain
, char *config_domain
,
2193 struct dhcp_netid
*netid
,
2194 struct in_addr subnet_addr
,
2195 unsigned char fqdn_flags
,
2196 int null_term
, int pxe_arch
,
2197 unsigned char *uuid
,
2198 int vendor_class_len
,
2201 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
2202 struct dhcp_boot
*boot
;
2204 int i
, len
, force_encap
= 0;
2205 unsigned char f0
= 0, s0
= 0;
2206 int done_file
= 0, done_server
= 0;
2207 int done_vendor_class
= 0;
2208 struct dhcp_netid
*tagif
;
2209 struct dhcp_netid_list
*id_list
;
2211 /* flag options which are valid with the current tag set (sans context tags) */
2212 tagif
= run_tag_if(netid
);
2213 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2215 opt
->flags
&= ~DHOPT_TAGOK
;
2216 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)) &&
2217 match_netid(opt
->netid
, tagif
, 0))
2218 opt
->flags
|= DHOPT_TAGOK
;
2221 /* now flag options which are valid, including the context tags,
2222 otherwise valid options are inhibited if we found a higher priotity one above */
2223 if (context
&& context
->netid
.net
)
2225 context
->netid
.next
= netid
;
2226 tagif
= run_tag_if(&context
->netid
);
2228 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2229 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
| DHOPT_TAGOK
)) &&
2230 match_netid(opt
->netid
, tagif
, 0))
2232 struct dhcp_opt
*tmp
;
2233 for (tmp
= config_opts
; tmp
; tmp
= tmp
->next
)
2234 if (tmp
->opt
== opt
->opt
&& opt
->netid
&& (tmp
->flags
& DHOPT_TAGOK
))
2237 opt
->flags
|= DHOPT_TAGOK
;
2241 /* now flag untagged options which are not overridden by tagged ones */
2242 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2243 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
| DHOPT_TAGOK
)) && !opt
->netid
)
2245 struct dhcp_opt
*tmp
;
2246 for (tmp
= config_opts
; tmp
; tmp
= tmp
->next
)
2247 if (tmp
->opt
== opt
->opt
&& (tmp
->flags
& DHOPT_TAGOK
))
2250 opt
->flags
|= DHOPT_TAGOK
;
2251 else if (!tmp
->netid
)
2252 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring duplicate dhcp-option %d"), tmp
->opt
);
2255 if (config_domain
&& (!domain
|| !hostname_isequal(domain
, config_domain
)))
2256 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), config_domain
, hostname
);
2259 if (option_bool(OPT_LOG_OPTS
) && req_options
)
2261 char *q
= daemon
->namebuff
;
2262 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
2264 char *s
= option_string(req_options
[i
], NULL
, NULL
);
2265 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
2270 req_options
[i
+1] == OPTION_END
? "" : ", ");
2271 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
2273 q
= daemon
->namebuff
;
2274 my_syslog(MS_DHCP
| LOG_INFO
, _("%u requested options: %s"), ntohl(mess
->xid
), daemon
->namebuff
);
2279 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
2280 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
2283 mess
->flags
|= htons(0x8000); /* force broadcast */
2286 mess
->siaddr
= context
->local
;
2288 /* See if we can send the boot stuff as options.
2289 To do this we need a requested option list, BOOTP
2290 and very old DHCP clients won't have this, we also
2291 provide an manual option to disable it.
2292 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2293 names, so we always send those. */
2294 if ((boot
= find_boot(tagif
)))
2298 if (!option_bool(OPT_NO_OVERRIDE
) &&
2300 in_list(req_options
, OPTION_SNAME
))
2301 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
2303 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
2308 if (!option_bool(OPT_NO_OVERRIDE
) &&
2310 in_list(req_options
, OPTION_FILENAME
))
2311 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
2313 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
2316 if (boot
->next_server
.s_addr
)
2317 mess
->siaddr
= boot
->next_server
;
2318 else if (boot
->tftp_sname
)
2319 mess
->siaddr
= a_record_from_hosts(boot
->tftp_sname
, now
);
2322 /* Use the values of the relevant options if no dhcp-boot given and
2323 they're not explicitly asked for as options. OPTION_END is used
2324 as an internal way to specify siaddr without using dhcp-boot, for use in
2327 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
2328 (opt
= option_find2(OPTION_FILENAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2330 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
2334 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
2335 (opt
= option_find2(OPTION_SNAME
)) && !(opt
->flags
& DHOPT_FORCE
))
2337 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
2341 if ((opt
= option_find2(OPTION_END
)))
2342 mess
->siaddr
.s_addr
= ((struct in_addr
*)opt
->val
)->s_addr
;
2345 /* We don't want to do option-overload for BOOTP, so make the file and sname
2346 fields look like they are in use, even when they aren't. This gets restored
2347 at the end of this function. */
2349 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2353 s0
= mess
->sname
[0];
2357 /* At this point, if mess->sname or mess->file are zeroed, they are available
2358 for option overload, reserve space for the overload option. */
2359 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
2362 /* rfc3011 says this doesn't need to be in the requested options list. */
2363 if (subnet_addr
.s_addr
)
2364 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
2366 /* replies to DHCPINFORM may not have a valid context */
2369 if (!option_find2(OPTION_NETMASK
))
2370 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
2372 /* May not have a "guessed" broadcast address if we got no packets via a relay
2373 from this net yet (ie just unicast renewals after a restart */
2374 if (context
->broadcast
.s_addr
&&
2375 !option_find2(OPTION_BROADCAST
))
2376 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
2378 /* Same comments as broadcast apply, and also may not be able to get a sensible
2379 default when using subnet select. User must configure by steam in that case. */
2380 if (context
->router
.s_addr
&&
2381 in_list(req_options
, OPTION_ROUTER
) &&
2382 !option_find2(OPTION_ROUTER
))
2383 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
2385 if (in_list(req_options
, OPTION_DNSSERVER
) &&
2386 !option_find2(OPTION_DNSSERVER
))
2387 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
2390 if (domain
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
2391 !option_find2(OPTION_DOMAINNAME
))
2392 option_put_string(mess
, end
, OPTION_DOMAINNAME
, domain
, null_term
);
2394 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2397 if (in_list(req_options
, OPTION_HOSTNAME
) &&
2398 !option_find2(OPTION_HOSTNAME
))
2399 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
2401 if (fqdn_flags
!= 0)
2403 len
= strlen(hostname
) + 3;
2405 if (fqdn_flags
& 0x04)
2411 len
+= strlen(domain
) + 1;
2413 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
2415 *(p
++) = fqdn_flags
;
2419 if (fqdn_flags
& 0x04)
2421 p
= do_rfc1035_name(p
, hostname
);
2423 p
= do_rfc1035_name(p
, domain
);
2428 memcpy(p
, hostname
, strlen(hostname
));
2429 p
+= strlen(hostname
);
2433 memcpy(p
, domain
, strlen(domain
));
2434 p
+= strlen(domain
);
2443 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2445 int optno
= opt
->opt
;
2447 /* netids match and not encapsulated? */
2448 if (!(opt
->flags
& DHOPT_TAGOK
))
2451 /* was it asked for, or are we sending it anyway? */
2452 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
2455 /* prohibit some used-internally options */
2456 if (optno
== OPTION_CLIENT_FQDN
||
2457 optno
== OPTION_MAXMESSAGE
||
2458 optno
== OPTION_OVERLOAD
||
2459 optno
== OPTION_PAD
||
2460 optno
== OPTION_END
)
2463 if (optno
== OPTION_SNAME
&& done_server
)
2466 if (optno
== OPTION_FILENAME
&& done_file
)
2469 /* For the options we have default values on
2470 dhc-option=<optionno> means "don't include this option"
2471 not "include a zero-length option" */
2472 if (opt
->len
== 0 &&
2473 (optno
== OPTION_NETMASK
||
2474 optno
== OPTION_BROADCAST
||
2475 optno
== OPTION_ROUTER
||
2476 optno
== OPTION_DNSSERVER
||
2477 optno
== OPTION_DOMAINNAME
||
2478 optno
== OPTION_HOSTNAME
))
2481 /* vendor-class comes from elsewhere for PXE */
2482 if (pxe_arch
!= -1 && optno
== OPTION_VENDOR_ID
)
2485 /* always force null-term for filename and servername - buggy PXE again. */
2486 len
= do_opt(opt
, NULL
, context
,
2487 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2489 if ((p
= free_space(mess
, end
, optno
, len
)))
2491 do_opt(opt
, p
, context
,
2492 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
2494 /* If we send a vendor-id, revisit which vendor-ops we consider
2495 it appropriate to send. */
2496 if (optno
== OPTION_VENDOR_ID
)
2498 match_vendor_opts(p
- 2, config_opts
);
2499 done_vendor_class
= 1;
2504 /* Now send options to be encapsulated in arbitrary options,
2505 eg dhcp-option=encap:172,17,.......
2506 Also hand vendor-identifying vendor-encapsulated options,
2507 dhcp-option = rfc3925-encap:13,17,.......
2508 The may be more that one "outer" to do, so group
2509 all the options which match each outer in turn. */
2510 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2511 opt
->flags
&= ~DHOPT_ENCAP_DONE
;
2513 for (opt
= config_opts
; opt
; opt
= opt
->next
)
2517 if ((flags
= (opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_RFC3925
))))
2522 if (opt
->flags
& DHOPT_ENCAP_DONE
)
2525 for (len
= 0, o
= config_opts
; o
; o
= o
->next
)
2527 int outer
= flags
& DHOPT_ENCAPSULATE
? o
->u
.encap
: OPTION_VENDOR_IDENT_OPT
;
2529 o
->flags
&= ~DHOPT_ENCAP_MATCH
;
2531 if (!(o
->flags
& flags
) || opt
->u
.encap
!= o
->u
.encap
)
2534 o
->flags
|= DHOPT_ENCAP_DONE
;
2535 if (match_netid(o
->netid
, tagif
, 1) &&
2536 ((o
->flags
& DHOPT_FORCE
) || in_list(req_options
, outer
)))
2538 o
->flags
|= DHOPT_ENCAP_MATCH
;
2540 len
+= do_opt(o
, NULL
, NULL
, 0) + 2;
2546 if (flags
& DHOPT_ENCAPSULATE
)
2547 do_encap_opts(config_opts
, opt
->u
.encap
, DHOPT_ENCAP_MATCH
, mess
, end
, null_term
);
2549 my_syslog(MS_DHCP
| LOG_WARNING
, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt
->u
.encap
);
2550 else if ((p
= free_space(mess
, end
, OPTION_VENDOR_IDENT_OPT
, len
+ 5)))
2552 int swap_ent
= htonl(opt
->u
.encap
);
2553 memcpy(p
, &swap_ent
, 4);
2556 for (o
= config_opts
; o
; o
= o
->next
)
2557 if (o
->flags
& DHOPT_ENCAP_MATCH
)
2559 len
= do_opt(o
, p
+ 2, NULL
, 0);
2569 force_encap
= prune_vendor_opts(tagif
);
2571 if (context
&& pxe_arch
!= -1)
2573 pxe_misc(mess
, end
, uuid
);
2574 config_opts
= pxe_opts(pxe_arch
, tagif
, context
->local
);
2577 if ((force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
)) &&
2578 do_encap_opts(config_opts
, OPTION_VENDOR_CLASS_OPT
, DHOPT_VENDOR_MATCH
, mess
, end
, null_term
) &&
2579 pxe_arch
== -1 && !done_vendor_class
&& vendor_class_len
!= 0 &&
2580 (p
= free_space(mess
, end
, OPTION_VENDOR_ID
, vendor_class_len
)))
2581 /* If we send vendor encapsulated options, and haven't already sent option 60,
2582 echo back the value we got from the client. */
2583 memcpy(p
, daemon
->dhcp_buff3
, vendor_class_len
);
2585 /* restore BOOTP anti-overload hack */
2586 if (!req_options
|| option_bool(OPT_NO_OVERRIDE
))
2589 mess
->sname
[0] = s0
;