]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc2131.c
1 /* dnsmasq is Copyright (c) 2000-2007 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 DHCP_COOKIE 0x63825363
23 /* The Linux in-kernel DHCP client silently ignores any packet
24 smaller than this. Sigh........... */
25 #define MIN_PACKETSZ 300
28 #define OPTION_NETMASK 1
29 #define OPTION_ROUTER 3
30 #define OPTION_DNSSERVER 6
31 #define OPTION_HOSTNAME 12
32 #define OPTION_DOMAINNAME 15
33 #define OPTION_BROADCAST 28
34 #define OPTION_VENDOR_CLASS_OPT 43
35 #define OPTION_REQUESTED_IP 50
36 #define OPTION_LEASE_TIME 51
37 #define OPTION_OVERLOAD 52
38 #define OPTION_MESSAGE_TYPE 53
39 #define OPTION_SERVER_IDENTIFIER 54
40 #define OPTION_REQUESTED_OPTIONS 55
41 #define OPTION_MESSAGE 56
42 #define OPTION_MAXMESSAGE 57
45 #define OPTION_VENDOR_ID 60
46 #define OPTION_CLIENT_ID 61
47 #define OPTION_SNAME 66
48 #define OPTION_FILENAME 67
49 #define OPTION_USER_CLASS 77
50 #define OPTION_CLIENT_FQDN 81
51 #define OPTION_AGENT_ID 82
52 #define OPTION_SUBNET_SELECT 118
53 #define OPTION_END 255
55 #define SUBOPT_CIRCUIT_ID 1
56 #define SUBOPT_REMOTE_ID 2
57 #define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */
58 #define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */
60 #define DHCPDISCOVER 1
69 #define have_config(config, mask) ((config) && ((config)->flags & (mask)))
70 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
71 #define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2]))
73 static int sanitise(unsigned char *opt
, char *buf
);
74 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
);
75 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
76 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
77 int opt
, char *string
, int null_term
);
78 static struct in_addr
option_addr(unsigned char *opt
);
79 static unsigned int option_uint(unsigned char *opt
, int size
);
80 static void log_packet(char *type
, void *addr
,
81 unsigned char *ext_mac
, int mac_len
, char *interface
, char *string
);
82 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
83 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
84 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
);
85 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
86 static void do_options(struct dhcp_context
*context
,
87 struct dhcp_packet
*mess
,
88 unsigned char *real_end
,
89 unsigned char *req_options
,
91 struct dhcp_netid
*netid
,
92 struct in_addr subnet_addr
,
93 unsigned char fqdn_flags
,
95 unsigned char *agent_id
);
96 static unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
97 int clid_len
, unsigned char *clid
, int *len_out
);
98 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
101 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
102 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
)
104 unsigned char *opt
, *clid
= NULL
;
105 struct dhcp_lease
*ltmp
, *lease
= NULL
;
106 struct dhcp_vendor
*vendor
;
107 struct dhcp_mac
*mac
;
108 struct dhcp_netid_list
*id_list
;
109 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0;
110 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
111 unsigned char *end
= (unsigned char *)(mess
+ 1);
112 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
;
113 int hostname_auth
= 0, borken_opt
= 0;
114 unsigned char *req_options
= NULL
;
115 char *message
= NULL
;
117 struct dhcp_config
*config
;
118 struct dhcp_netid
*netid
= NULL
;
119 struct in_addr subnet_addr
, fallback
;
120 unsigned short fuzz
= 0;
121 unsigned int mess_type
= 0;
122 unsigned char fqdn_flags
= 0;
123 unsigned char *agent_id
= NULL
;
124 unsigned char *emac
= NULL
;
126 struct dhcp_netid known_id
;
128 subnet_addr
.s_addr
= 0;
130 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
133 if (mess
->htype
== 0 && mess
->hlen
!= 0)
136 /* check for DHCP rather than BOOTP */
137 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
139 mess_type
= option_uint(opt
, 1);
141 /* only insist on a cookie for DHCP. */
142 if (*((u32
*)&mess
->options
) != htonl(DHCP_COOKIE
))
145 /* two things to note here: expand_buf may move the packet,
146 so reassign mess from daemon->packet. Also, the size
147 sent includes the IP and UDP headers, hence the magic "-28" */
148 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
150 size_t size
= (size_t)option_uint(opt
, 2) - 28;
152 if (size
> DHCP_PACKET_MAX
)
153 size
= DHCP_PACKET_MAX
;
154 else if (size
< sizeof(struct dhcp_packet
))
155 size
= sizeof(struct dhcp_packet
);
157 if (expand_buf(&daemon
->dhcp_packet
, size
))
159 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
160 end
= ((unsigned char *)mess
) + size
;
164 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
165 it can affect the context-determination code. */
166 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
167 mess
->ciaddr
.s_addr
= 0;
169 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
171 /* Any agent-id needs to be copied back out, verbatim, as the last option
172 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
173 get overwritten, then it will be shuffled back at the end of processing.
174 Note that the incoming options must not be overwritten here, so there has to
175 be enough free space at the end of the packet to copy the option. */
177 unsigned int total
= option_len(opt
) + 2;
178 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
179 if (last_opt
&& last_opt
< end
- total
)
181 agent_id
= end
- total
;
182 memcpy(agent_id
, opt
, total
);
185 /* look for RFC3527 Link selection sub-option */
186 if ((sopt
= option_find1(option_ptr(opt
), option_ptr(opt
) + option_len(opt
), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
187 subnet_addr
= option_addr(sopt
);
189 /* if a circuit-id or remote-is option is provided, exact-match to options. */
190 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
194 if (vendor
->match_type
== MATCH_CIRCUIT
)
195 search
= SUBOPT_CIRCUIT_ID
;
196 else if (vendor
->match_type
== MATCH_REMOTE
)
197 search
= SUBOPT_REMOTE_ID
;
198 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
199 search
= SUBOPT_SUBSCR_ID
;
203 if ((sopt
= option_find1(option_ptr(opt
), option_ptr(opt
) + option_len(opt
), search
, 1)) &&
204 vendor
->len
== option_len(sopt
) &&
205 memcmp(option_ptr(sopt
), vendor
->data
, vendor
->len
) == 0)
207 vendor
->netid
.next
= netid
;
208 netid
= &vendor
->netid
;
214 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
215 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
216 subnet_addr
= option_addr(opt
);
218 /* If there is no client identifier option, use the hardware address */
219 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
221 clid_len
= option_len(opt
);
222 clid
= option_ptr(opt
);
225 /* do we have a lease in store? */
226 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
228 /* If this request is missing a clid, but we've seen one before,
229 use it again for option matching etc. */
230 if (lease
&& !clid
&& lease
->clid
)
232 clid_len
= lease
->clid_len
;
236 /* find mac to use for logging and hashing */
237 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
240 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
241 if (mac
->hwaddr_len
== mess
->hlen
&&
242 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
243 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
245 mac
->netid
.next
= netid
;
249 /* Determine network for this packet. Our caller will have already linked all the
250 contexts which match the addresses of the receiving interface but if the
251 machine has an address already, or came via a relay, or we have a subnet selector,
252 we search again. If we don't have have a giaddr or explicit subnet selector,
253 use the ciaddr. This is necessary because a machine which got a lease via a
254 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
255 from the physical network, continue using that to allow correct DHCPNAK generation later. */
256 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
258 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
262 if (subnet_addr
.s_addr
)
267 else if (mess
->giaddr
.s_addr
)
274 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
276 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
277 if (context_tmp
->netmask
.s_addr
&&
278 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
279 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
281 context_new
= context
;
287 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
288 if (context_tmp
->netmask
.s_addr
&&
289 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
290 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
292 context_tmp
->current
= context_new
;
293 context_new
= context_tmp
;
296 if (context_new
|| force
)
297 context
= context_new
;
303 my_syslog(LOG_WARNING
, _("no address range available for DHCP request %s %s"),
304 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
305 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
309 /* keep _a_ local address available. */
310 fallback
= context
->local
;
312 if (daemon
->options
& OPT_LOG_OPTS
)
314 struct dhcp_context
*context_tmp
;
315 my_syslog(LOG_INFO
, _("DHCP packet: transaction-id is %u"), mess
->xid
);
316 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
318 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
319 if (context_tmp
->flags
& CONTEXT_STATIC
)
320 my_syslog(LOG_INFO
, _("Available DHCP subnet: %s/%s"), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
322 my_syslog(LOG_INFO
, _("Available DHCP range: %s -- %s"), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
326 mess
->op
= BOOTREPLY
;
328 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
329 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
331 /* set "known" tag for known hosts */
334 known_id
.net
= "known";
335 known_id
.next
= netid
;
342 struct dhcp_netid id
, bootp_id
;
343 struct in_addr
*logaddr
= NULL
;
345 /* must have a MAC addr for bootp */
346 if (mess
->htype
== 0 || mess
->hlen
== 0)
349 if (have_config(config
, CONFIG_DISABLE
))
350 message
= _("disabled");
352 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
354 if (have_config(config
, CONFIG_NAME
))
355 hostname
= config
->hostname
;
357 if (have_config(config
, CONFIG_NETID
))
359 config
->netid
.next
= netid
;
360 netid
= &config
->netid
;
363 /* Match incoming filename field as a netid. */
366 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
367 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
368 id
.net
= (char *)daemon
->dhcp_buff2
;
373 /* Add "bootp" as a tag to allow different options, address ranges etc
375 bootp_id
.net
= "bootp";
376 bootp_id
.next
= netid
;
379 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
380 if (match_netid(id_list
->list
, netid
, 0))
381 message
= _("disabled");
385 if (have_config(config
, CONFIG_ADDR
))
387 logaddr
= &config
->addr
;
388 mess
->yiaddr
= config
->addr
;
389 if ((lease
= lease_find_by_addr(config
->addr
)) &&
390 (lease
->hwaddr_len
!= mess
->hlen
||
391 lease
->hwaddr_type
!= mess
->htype
||
392 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
393 message
= _("address in use");
395 else if (!(daemon
->options
& OPT_BOOTP_DYNAMIC
))
396 message
= _("no address configured");
399 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
400 !address_available(context
, lease
->addr
, netid
))
404 /* lease exists, wrong network. */
405 lease_prune(lease
, now
);
408 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, netid
, now
))
409 message
= _("no address available");
412 mess
->yiaddr
= lease
->addr
;
417 (!(lease
= lease_allocate(mess
->yiaddr
))))
418 message
= _("no leases left");
420 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
421 message
= _("wrong network");
425 logaddr
= &mess
->yiaddr
;
427 if (context
->netid
.net
)
429 context
->netid
.next
= netid
;
430 netid
= &context
->netid
;
433 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0);
435 lease_set_hostname(lease
, hostname
, daemon
->domain_suffix
, 1);
436 lease_set_expires(lease
, 0xffffffff, now
); /* infinite lease */
437 lease_set_interface(lease
, int_index
);
439 clear_packet(mess
, end
);
440 do_options(context
, mess
, end
, NULL
,
441 hostname
, netid
, subnet_addr
, 0, 0, NULL
);
445 log_packet(NULL
, logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
);
447 return message
? 0 : dhcp_packet_size(mess
, netid
);
450 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
452 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
453 int len
= option_len(opt
);
454 char *pq
= daemon
->dhcp_buff
;
455 unsigned char *pp
, *op
= option_ptr(opt
);
462 /* Always force update, since the client has no way to do it itself. */
463 if (!(fqdn_flags
& 0x01))
469 if (fqdn_flags
& 0x04)
470 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
472 memcpy(pq
, op
+1, *op
);
480 if (len
> 0 && op
[len
-1] == 0)
485 if (pq
!= daemon
->dhcp_buff
)
490 if (canonicalise(daemon
->dhcp_buff
))
491 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
493 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
495 int len
= option_len(opt
);
496 memcpy(daemon
->dhcp_buff
, option_ptr(opt
), len
);
497 /* Microsoft clients are broken, and need zero-terminated strings
498 in options. We detect this state here, and do the same in
499 any options we send */
500 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
503 daemon
->dhcp_buff
[len
] = 0;
504 if (canonicalise(daemon
->dhcp_buff
))
505 client_hostname
= daemon
->dhcp_buff
;
508 if (have_config(config
, CONFIG_NAME
))
510 hostname
= config
->hostname
;
512 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
513 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
514 offer_hostname
= hostname
;
516 else if (client_hostname
)
518 char *d
= strip_hostname(client_hostname
);
520 my_syslog(LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), d
, client_hostname
);
522 if (strlen(client_hostname
) != 0)
524 hostname
= client_hostname
;
527 /* Search again now we have a hostname.
528 Only accept configs without CLID and HWADDR here, (they won't match)
529 to avoid impersonation by name. */
530 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
531 mess
->chaddr
, mess
->hlen
,
532 mess
->htype
, hostname
);
533 if (new && !have_config(new, CONFIG_CLID
) && !have_config(new, CONFIG_HWADDR
))
536 /* set "known" tag for known hosts */
537 known_id
.net
= "known";
538 known_id
.next
= netid
;
545 if (have_config(config
, CONFIG_NETID
))
547 config
->netid
.next
= netid
;
548 netid
= &config
->netid
;
551 /* user-class options are, according to RFC3004, supposed to contain
552 a set of counted strings. Here we check that this is so (by seeing
553 if the counts are consistent with the overall option length) and if
554 so zero the counts so that we don't get spurious matches between
555 the vendor string and the counts. If the lengths don't add up, we
556 assume that the option is a single string and non RFC3004 compliant
557 and just do the substring match. dhclient provides these broken options.
558 The code, later, which sends user-class data to the lease-change script
559 relies on the transformation done here.
562 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
564 unsigned char *ucp
= option_ptr(opt
);
566 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
567 if (j
== option_len(opt
))
568 for (j
= 0; j
< option_len(opt
); j
= tmp
)
570 tmp
= j
+ ucp
[j
] + 1;
575 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
579 if (vendor
->match_type
== MATCH_VENDOR
)
580 mopt
= OPTION_VENDOR_ID
;
581 else if (vendor
->match_type
== MATCH_USER
)
582 mopt
= OPTION_USER_CLASS
;
583 else if (vendor
->match_type
== MATCH_OPTION
)
585 if (option_find(mess
, sz
, vendor
->option
, 1))
587 vendor
->netid
.next
= netid
;
588 netid
= &vendor
->netid
;
595 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
598 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
599 if (memcmp(vendor
->data
, option_ptr(opt
)+i
, vendor
->len
) == 0)
601 vendor
->netid
.next
= netid
;
602 netid
= &vendor
->netid
;
608 /* mark vendor-encapsulated options which match the client-supplied vendor class */
609 match_vendor_opts(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->dhcp_opts
);
611 if (daemon
->options
& OPT_LOG_OPTS
)
613 if (sanitise(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->namebuff
))
614 my_syslog(LOG_INFO
, _("Vendor class: %s"), daemon
->namebuff
);
615 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
616 my_syslog(LOG_INFO
, _("User class: %s"), daemon
->namebuff
);
619 /* if all the netids in the ignore list are present, ignore this client */
620 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
621 if (match_netid(id_list
->list
, netid
, 0))
624 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
625 if (have_config(config
, CONFIG_NOCLID
))
628 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
630 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
631 memcpy(req_options
, option_ptr(opt
), option_len(opt
));
632 req_options
[option_len(opt
)] = OPTION_END
;
638 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
639 (context
->local
.s_addr
!= option_addr(opt
).s_addr
))
642 /* sanitise any message. Paranoid? Moi? */
643 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
645 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
648 log_packet("DECLINE", option_ptr(opt
), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
);
650 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
651 lease_prune(lease
, now
);
653 if (have_config(config
, CONFIG_ADDR
) &&
654 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
656 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
657 my_syslog(LOG_WARNING
, _("disabling DHCP static address %s for %s"),
658 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
659 config
->flags
|= CONFIG_DECLINED
;
660 config
->decline_time
= now
;
663 /* make sure this host gets a different address next time. */
664 for (; context
; context
= context
->current
)
665 context
->addr_epoch
++;
670 if (!(context
= narrow_context(context
, mess
->ciaddr
, netid
)) ||
671 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
672 (context
->local
.s_addr
!= option_addr(opt
).s_addr
))
675 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
676 lease_prune(lease
, now
);
678 message
= _("unknown lease");
680 log_packet("RELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
);
685 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
687 message
= _("ignored");
692 struct in_addr addr
, conf
;
694 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
695 addr
= option_addr(opt
);
698 if (have_config(config
, CONFIG_ADDR
))
700 char *addrs
= inet_ntoa(config
->addr
);
702 if ((ltmp
= lease_find_by_addr(config
->addr
)) && ltmp
!= lease
)
705 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
706 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
707 my_syslog(LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
708 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
712 struct dhcp_context
*tmp
;
713 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
714 if (context
->router
.s_addr
== config
->addr
.s_addr
)
717 my_syslog(LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
718 else if (have_config(config
, CONFIG_DECLINED
) &&
719 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
720 my_syslog(LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
728 else if (lease
&& address_available(context
, lease
->addr
, netid
))
729 mess
->yiaddr
= lease
->addr
;
730 else if (opt
&& address_available(context
, addr
, netid
) && !lease_find_by_addr(addr
) &&
731 !config_find_by_address(daemon
->dhcp_conf
, addr
))
733 else if (emac_len
== 0)
734 message
= _("no unique-id");
735 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, netid
, now
))
736 message
= _("no address available");
739 log_packet("DISCOVER", opt
? option_ptr(opt
) : NULL
, emac
, emac_len
, iface_name
, message
);
741 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
744 log_packet("OFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
);
746 if (context
->netid
.net
)
748 context
->netid
.next
= netid
;
749 netid
= &context
->netid
;
752 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
753 clear_packet(mess
, end
);
754 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
755 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
756 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
757 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
758 if (time
!= 0xffffffff)
760 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
761 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
763 do_options(context
, mess
, end
, req_options
, offer_hostname
,
764 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
766 return dhcp_packet_size(mess
, netid
);
769 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
771 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
773 /* SELECTING or INIT_REBOOT */
774 mess
->yiaddr
= option_addr(opt
);
776 /* send vendor and user class info for new or recreated lease */
779 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
784 for (; context
; context
= context
->current
)
785 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
791 /* If a lease exists for this host and another address, squash it. */
792 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
794 lease_prune(lease
, now
);
801 if (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
))
804 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
806 message
= _("wrong address");
807 /* avoid loops when client brain-dead */
808 lease_prune(lease
, now
);
815 /* RENEWING or REBINDING */
816 /* Check existing lease for this address.
817 We allow it to be missing if dhcp-authoritative mode
818 as long as we can allocate the lease now - checked below.
819 This makes for a smooth recovery from a lost lease DB */
820 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
821 (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
)))
823 message
= _("lease not found");
824 /* ensure we broadcast NAK */
827 /* desynchronise renewals */
829 mess
->yiaddr
= mess
->ciaddr
;
832 log_packet("REQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
);
836 struct dhcp_config
*addr_config
;
837 struct dhcp_context
*tmp
= NULL
;
839 if (have_config(config
, CONFIG_ADDR
))
840 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
841 if (context
->router
.s_addr
== config
->addr
.s_addr
)
844 if (!(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
846 /* If a machine moves networks whilst it has a lease, we catch that here. */
847 message
= _("wrong network");
848 /* ensure we broadcast NAK */
852 /* Check for renewal of a lease which is outside the allowed range. */
853 else if (!address_available(context
, mess
->yiaddr
, netid
) &&
854 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
855 message
= _("address not available");
857 /* Check if a new static address has been configured. Be very sure that
858 when the client does DISCOVER, it will get the static address, otherwise
859 an endless protocol loop will ensue. */
860 else if (!tmp
&& !selecting
&&
861 have_config(config
, CONFIG_ADDR
) &&
862 (!have_config(config
, CONFIG_DECLINED
) ||
863 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
864 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
865 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
866 message
= _("static lease available");
868 /* Check to see if the address is reserved as a static address for another host */
869 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
870 message
= _("address reserved");
872 else if ((ltmp
= lease_find_by_addr(mess
->yiaddr
)) && ltmp
!= lease
)
873 message
= _("address in use");
875 else if (emac_len
== 0)
876 message
= _("no unique-id");
880 if ((lease
= lease_allocate(mess
->yiaddr
)))
883 message
= _("no leases left");
889 log_packet("NAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
);
891 mess
->yiaddr
.s_addr
= 0;
892 clear_packet(mess
, end
);
893 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
894 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
,
895 ntohl(context
? context
->local
.s_addr
: fallback
.s_addr
));
896 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
897 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
898 a distant subnet which unicast a REQ to us won't work. */
899 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
900 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
902 mess
->flags
|= htons(0x8000); /* broadcast */
903 mess
->ciaddr
.s_addr
= 0;
911 /* copy user-class and vendor class into new lease, for the script */
912 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
914 int len
= option_len(opt
);
915 unsigned char *ucp
= option_ptr(opt
);
916 /* If the user-class option started as counted strings, the first byte will be zero. */
917 if (len
!= 0 && ucp
[0] == 0)
919 free(lease
->userclass
);
920 if ((lease
->userclass
= whine_malloc(len
+1)))
922 memcpy(lease
->userclass
, ucp
, len
);
923 lease
->userclass
[len
] = 0;
924 lease
->userclass_len
= len
+1;
927 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
929 int len
= option_len(opt
);
930 unsigned char *ucp
= option_ptr(opt
);
931 free(lease
->vendorclass
);
932 if ((lease
->vendorclass
= whine_malloc(len
+1)))
934 memcpy(lease
->vendorclass
, ucp
, len
);
935 lease
->vendorclass
[len
] = 0;
936 lease
->vendorclass_len
= len
+1;
941 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
943 hostname
= client_hostname
;
947 if (context
->netid
.net
)
949 context
->netid
.next
= netid
;
950 netid
= &context
->netid
;
953 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
954 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
);
956 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
959 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
960 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
966 lease_set_hostname(lease
, hostname
, daemon
->domain_suffix
, hostname_auth
);
968 lease_set_expires(lease
, time
, now
);
969 lease_set_interface(lease
, int_index
);
971 log_packet("ACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
);
973 clear_packet(mess
, end
);
974 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
975 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
976 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
977 if (time
!= 0xffffffff)
979 while (fuzz
> (time
/16))
981 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
982 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
984 do_options(context
, mess
, end
, req_options
, hostname
,
985 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
988 return dhcp_packet_size(mess
, netid
);
991 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
992 message
= _("ignored");
994 log_packet("INFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
);
996 if (message
|| mess
->ciaddr
.s_addr
== 0 ||
997 !(context
= narrow_context(context
, mess
->ciaddr
, netid
)))
1000 /* Find a least based on IP address if we didn't
1001 get one from MAC address/client-d */
1003 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1005 hostname
= lease
->hostname
;
1008 hostname
= host_from_dns(mess
->ciaddr
);
1010 log_packet("ACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
);
1012 if (context
->netid
.net
)
1014 context
->netid
.next
= netid
;
1015 netid
= &context
->netid
;
1018 clear_packet(mess
, end
);
1019 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1020 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
1024 if (lease
->expires
== 0)
1027 time
= (unsigned int)difftime(lease
->expires
, now
);
1028 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1029 lease_set_interface(lease
, int_index
);
1032 do_options(context
, mess
, end
, req_options
, hostname
,
1033 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
1035 *is_inform
= 1; /* handle reply differently */
1036 return dhcp_packet_size(mess
, netid
);
1042 /* find a good value to use as MAC address for logging and address-allocation hashing.
1043 This is normally just the chaddr field from the DHCP packet,
1044 but eg Firewire will have hlen == 0 and use the client-id instead.
1045 This could be anything, but will normally be EUI64 for Firewire.
1046 We assume that if the first byte of the client-id equals the htype byte
1047 then the client-id is using the usual encoding and use the rest of the
1048 client-id: if not we can use the whole client-id. This should give
1049 sane MAC address logs. */
1050 static unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1051 int clid_len
, unsigned char *clid
, int *len_out
)
1053 if (hwlen
== 0 && clid
&& clid_len
> 3)
1055 if (clid
[0] == hwtype
)
1057 *len_out
= clid_len
- 1 ;
1061 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1062 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1064 *len_out
= clid_len
- 1 ;
1069 *len_out
= clid_len
;
1077 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1079 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1083 unsigned int req_time
= option_uint(opt
, 4);
1084 if (req_time
< 120 )
1085 req_time
= 120; /* sanity */
1086 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1093 static int sanitise(unsigned char *opt
, char *buf
)
1103 p
= option_ptr(opt
);
1105 for (i
= option_len(opt
); i
> 0; i
--)
1108 if (isprint((int)c
))
1111 *buf
= 0; /* add terminator */
1116 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1117 int mac_len
, char *interface
, char *string
)
1121 /* addr may be misaligned */
1123 memcpy(&a
, addr
, sizeof(a
));
1125 my_syslog(LOG_INFO
, "%s%s(%s) %s%s%s %s",
1126 type
? "DHCP" : "BOOTP",
1129 addr
? inet_ntoa(a
) : "",
1131 print_mac(daemon
->namebuff
, ext_mac
, mac_len
),
1132 string
? string
: "");
1135 static void log_options(unsigned char *start
)
1137 while (*start
!= OPTION_END
)
1139 char *text
= option_string(start
[0]);
1140 unsigned char trunc
= start
[1] < 13 ? start
[1] : 13;
1141 my_syslog(LOG_INFO
, "sent size:%3d option:%3d%s%s%s%s%s",
1143 text
? ":" : "", text
? text
: "",
1144 start
[1] == 0 ? "" : " ",
1145 start
[1] == 0 ? "" : print_mac(daemon
->namebuff
, &start
[2], trunc
),
1146 trunc
== start
[1] ? "" : "...");
1147 start
+= start
[1] + 2;
1151 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1153 while (*p
!= OPTION_END
)
1156 return NULL
; /* malformed packet */
1157 else if (*p
== OPTION_PAD
)
1163 return NULL
; /* malformed packet */
1164 opt_len
= option_len(p
);
1165 if (p
>= end
- (2 + opt_len
))
1166 return NULL
; /* malformed packet */
1167 if (*p
== opt
&& opt_len
>= minsize
)
1173 return opt
== OPTION_END
? p
: NULL
;
1176 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1178 unsigned char *ret
, *overload
;
1180 /* skip over DHCP cookie; */
1181 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1184 /* look for overload option. */
1185 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1188 /* Can we look in filename area ? */
1189 if ((overload
[2] & 1) &&
1190 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1193 /* finally try sname area */
1194 if ((overload
[2] & 2) &&
1195 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1201 static struct in_addr
option_addr(unsigned char *opt
)
1203 /* this worries about unaligned data in the option. */
1204 /* struct in_addr is network byte order */
1207 memcpy(&ret
, option_ptr(opt
), INADDRSZ
);
1212 static unsigned int option_uint(unsigned char *opt
, int size
)
1214 /* this worries about unaligned data and byte order */
1215 unsigned int ret
= 0;
1217 unsigned char *p
= option_ptr(opt
);
1219 for (i
= 0; i
< size
; i
++)
1220 ret
= (ret
<< 8) | *p
++;
1225 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1228 start
+= start
[1] + 2;
1232 /* only for use when building packet: doesn't check for bad data. */
1233 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1235 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1239 if (*p
== OPTION_OVERLOAD
)
1246 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
)
1248 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1249 unsigned char *overload
;
1251 struct dhcp_netid_list
*id_list
;
1253 /* We do logging too */
1254 if (netid
&& (daemon
->options
& OPT_LOG_OPTS
))
1256 char *p
= daemon
->namebuff
;
1258 for (; netid
; netid
= netid
->next
)
1260 strncat (p
, netid
->net
, MAXDNAME
);
1262 strncat (p
, ", ", MAXDNAME
);
1264 p
[MAXDNAME
- 1] = 0;
1265 my_syslog(LOG_INFO
, _("tags: %s"), p
);
1268 /* add END options to the regions. */
1269 if ((overload
= find_overload(mess
)))
1271 if (option_uint(overload
, 1) & 1)
1273 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1274 if (daemon
->options
& OPT_LOG_OPTS
)
1275 log_options(mess
->file
);
1277 if (option_uint(overload
, 1) & 2)
1279 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1280 if (daemon
->options
& OPT_LOG_OPTS
)
1281 log_options(mess
->sname
);
1287 if (daemon
->options
& OPT_LOG_OPTS
)
1288 log_options(&mess
->options
[0] + sizeof(u32
));
1290 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
1291 if (match_netid(id_list
->list
, netid
, 0))
1292 mess
->flags
|= htons(0x8000); /* force broadcast */
1294 ret
= (size_t)(p
- (unsigned char *)mess
);
1296 if (ret
< MIN_PACKETSZ
)
1302 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1304 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1306 if (p
+ len
+ 3 >= end
)
1307 /* not enough space in options area, try and use overload, if poss */
1309 unsigned char *overload
;
1311 if (!(overload
= find_overload(mess
)) &&
1312 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1314 /* attempt to overload fname and sname areas, we've reserved space for the
1315 overflow option previuously. */
1317 *(p
++) = OPTION_OVERLOAD
;
1323 /* using filename field ? */
1326 if (mess
->file
[0] == 0)
1329 if (overload
[2] & 1)
1331 p
= dhcp_skip_opts(mess
->file
);
1332 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1338 /* try to bring sname into play (it may be already) */
1339 if (mess
->sname
[0] == 0)
1342 if (overload
[2] & 2)
1344 p
= dhcp_skip_opts(mess
->sname
);
1345 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1352 my_syslog(LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1364 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1367 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1370 for (i
= 0; i
< len
; i
++)
1371 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1374 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1375 char *string
, int null_term
)
1378 size_t len
= strlen(string
);
1380 if (null_term
&& len
!= 255)
1383 if ((p
= free_space(mess
, end
, opt
, len
)))
1384 memcpy(p
, string
, len
);
1387 /* return length, note this only does the data part */
1388 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct in_addr local
, int null_term
)
1392 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1397 if ((opt
->flags
& DHOPT_ADDR
) && !(opt
->flags
& DHOPT_ENCAPSULATE
))
1400 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1401 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1403 /* zero means "self" (but not in vendorclass options.) */
1405 memcpy(p
, &local
, INADDRSZ
);
1407 memcpy(p
, a
, INADDRSZ
);
1412 memcpy(p
, opt
->val
, len
);
1417 static int in_list(unsigned char *list
, int opt
)
1421 /* If no requested options, send everything, not nothing. */
1425 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1432 static struct dhcp_opt
*option_find2(struct dhcp_netid
*netid
, struct dhcp_opt
*opts
, int opt
)
1434 struct dhcp_opt
*tmp
;
1435 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
1436 if (tmp
->opt
== opt
&& !(tmp
->flags
& DHOPT_ENCAPSULATE
))
1437 if (match_netid(tmp
->netid
, netid
, 1) || match_netid(tmp
->netid
, netid
, 0))
1440 return netid
? option_find2(NULL
, opts
, opt
) : NULL
;
1443 /* mark vendor-encapsulated options which match the client-supplied or
1444 config-supplied vendor class */
1445 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1447 for (; dopt
; dopt
= dopt
->next
)
1449 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1450 if (opt
&& (dopt
->flags
& DHOPT_ENCAPSULATE
))
1453 if (dopt
->vendor_class
)
1454 len
= strlen((char *)dopt
->vendor_class
);
1455 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1456 if (len
== 0 || memcmp(dopt
->vendor_class
, option_ptr(opt
)+i
, len
) == 0)
1458 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1465 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
1467 memset(mess
->sname
, 0, sizeof(mess
->sname
));
1468 memset(mess
->file
, 0, sizeof(mess
->file
));
1469 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
1470 mess
->siaddr
.s_addr
= 0;
1473 static void do_options(struct dhcp_context
*context
,
1474 struct dhcp_packet
*mess
,
1475 unsigned char *real_end
,
1476 unsigned char *req_options
,
1478 struct dhcp_netid
*netid
,
1479 struct in_addr subnet_addr
,
1480 unsigned char fqdn_flags
,
1482 unsigned char *agent_id
)
1484 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
1485 struct dhcp_boot
*boot
;
1486 unsigned char *p
, *end
= agent_id
? agent_id
: real_end
;
1487 int i
, len
, force_encap
= 0;
1488 unsigned char f0
= 0, s0
= 0;
1489 int done_file
= 0, done_server
= 0;
1492 if ((daemon
->options
& OPT_LOG_OPTS
) && req_options
)
1494 char *q
= daemon
->namebuff
;
1495 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
1497 char *s
= option_string(req_options
[i
]);
1498 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
1503 req_options
[i
+1] == OPTION_END
? "" : ", ");
1504 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
1506 q
= daemon
->namebuff
;
1507 my_syslog(LOG_INFO
, _("requested options: %s"), daemon
->namebuff
);
1512 /* decide which dhcp-boot option we're using */
1513 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1514 if (match_netid(boot
->netid
, netid
, 0))
1517 /* No match, look for one without a netid */
1518 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1519 if (match_netid(boot
->netid
, netid
, 1))
1522 mess
->siaddr
= context
->local
;
1524 /* See if we can send the boot stuff as options.
1525 To do this we need a requested option list, BOOTP
1526 and very old DHCP clients won't have this, we also
1527 provide an manual option to disable it.
1528 Some PXE ROMs have bugs (surprise!) and need zero-terminated
1529 names, so we always send those. */
1534 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
1536 in_list(req_options
, OPTION_SNAME
))
1537 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
1539 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
1544 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
1546 in_list(req_options
, OPTION_FILENAME
))
1547 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
1549 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
1552 if (boot
->next_server
.s_addr
)
1553 mess
->siaddr
= boot
->next_server
;
1555 if (daemon
->options
& OPT_LOG_OPTS
)
1556 my_syslog(LOG_INFO
, _("next server: %s"), inet_ntoa(mess
->siaddr
));
1559 /* Use the values of the relevant options if no dhcp-boot given and
1560 they're no explicitly asked for as options. */
1562 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
1563 (opt
= option_find2(netid
, config_opts
, OPTION_FILENAME
)))
1565 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
1569 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
1570 (opt
= option_find2(netid
, config_opts
, OPTION_SNAME
)))
1572 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
1577 if (daemon
->options
& OPT_LOG_OPTS
)
1579 if (strlen((char *)mess
->file
) != 0)
1580 my_syslog(LOG_INFO
, _("bootfile name: %s"), (char *)mess
->file
);
1582 if (strlen((char *)mess
->sname
) != 0)
1583 my_syslog(LOG_INFO
, _("server name: %s"), (char *)mess
->sname
);
1586 /* We don't want to do option-overload for BOOTP, so make the file and sname
1587 fields look like they are in use, even when they aren't. This gets restored
1588 at the end of this function. */
1590 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
1594 s0
= mess
->sname
[0];
1598 /* At this point, if mess->sname or mess->file are zeroed, they are available
1599 for option overload, reserve space for the overload option. */
1600 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
1603 /* rfc3011 says this doesn't need to be in the requested options list. */
1604 if (subnet_addr
.s_addr
)
1605 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
1607 if (!option_find2(netid
, config_opts
, OPTION_NETMASK
))
1608 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
1610 /* May not have a "guessed" broadcast address if we got no packets via a relay
1611 from this net yet (ie just unicast renewals after a restart */
1612 if (context
->broadcast
.s_addr
&&
1613 !option_find2(netid
, config_opts
, OPTION_BROADCAST
))
1614 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
1616 /* Same comments as broadcast apply, and also may not be able to get a sensible
1617 default when using subnet select. User must configure by steam in that case. */
1618 if (context
->router
.s_addr
&&
1619 in_list(req_options
, OPTION_ROUTER
) &&
1620 !option_find2(netid
, config_opts
, OPTION_ROUTER
))
1621 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
1623 if (in_list(req_options
, OPTION_DNSSERVER
) &&
1624 !option_find2(netid
, config_opts
, OPTION_DNSSERVER
))
1625 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
1627 if (daemon
->domain_suffix
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
1628 !option_find2(netid
, config_opts
, OPTION_DOMAINNAME
))
1629 option_put_string(mess
, end
, OPTION_DOMAINNAME
, daemon
->domain_suffix
, null_term
);
1631 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
1634 if (in_list(req_options
, OPTION_HOSTNAME
) &&
1635 !option_find2(netid
, config_opts
, OPTION_HOSTNAME
))
1636 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
1638 if (fqdn_flags
!= 0)
1640 int len
= strlen(hostname
) + 3;
1641 if (fqdn_flags
& 0x04)
1646 if (daemon
->domain_suffix
)
1647 len
+= strlen(daemon
->domain_suffix
) + 1;
1649 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
1651 *(p
++) = fqdn_flags
;
1655 if (fqdn_flags
& 0x04)
1657 p
= do_rfc1035_name(p
, hostname
);
1658 if (daemon
->domain_suffix
)
1659 p
= do_rfc1035_name(p
, daemon
->domain_suffix
);
1664 memcpy(p
, hostname
, strlen(hostname
));
1665 p
+= strlen(hostname
);
1666 if (daemon
->domain_suffix
)
1669 memcpy(p
, daemon
->domain_suffix
, strlen(daemon
->domain_suffix
));
1670 p
+= strlen(daemon
->domain_suffix
);
1679 for (opt
= config_opts
; opt
; opt
= opt
->next
)
1681 int optno
= opt
->opt
;
1683 /* was it asked for, or are we sending it anyway? */
1684 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
1687 /* prohibit some used-internally options */
1688 if (optno
== OPTION_CLIENT_FQDN
||
1689 optno
== OPTION_MAXMESSAGE
||
1690 optno
== OPTION_OVERLOAD
||
1691 optno
== OPTION_PAD
||
1692 optno
== OPTION_END
)
1695 if (optno
== OPTION_SNAME
&& done_server
)
1698 if (optno
== OPTION_FILENAME
&& done_file
)
1701 /* netids match and not encapsulated? */
1702 if (opt
!= option_find2(netid
, config_opts
, optno
))
1705 /* For the options we have default values on
1706 dhc-option=<optionno> means "don't include this option"
1707 not "include a zero-length option" */
1708 if (opt
->len
== 0 &&
1709 (optno
== OPTION_NETMASK
||
1710 optno
== OPTION_BROADCAST
||
1711 optno
== OPTION_ROUTER
||
1712 optno
== OPTION_DNSSERVER
||
1713 optno
== OPTION_DOMAINNAME
||
1714 optno
== OPTION_HOSTNAME
))
1717 /* always force null-term for filename ans servername - buggy PXE again. */
1718 len
= do_opt(opt
, NULL
, context
->local
,
1719 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
1721 if ((p
= free_space(mess
, end
, optno
, len
)))
1723 do_opt(opt
, p
, context
->local
,
1724 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
1726 /* If we send a vendor-id, revisit which vendor-ops we consider
1727 it appropriate to send. */
1728 if (optno
== OPTION_VENDOR_ID
)
1729 match_vendor_opts(p
- 2, config_opts
);
1733 /* prune encapsulated options based on netid, and look if we're forcing them to be sent */
1734 for (opt
= config_opts
; opt
; opt
= opt
->next
)
1735 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1737 if (!match_netid(opt
->netid
, netid
, 1) && !match_netid(opt
->netid
, netid
, 0))
1738 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1739 else if (opt
->flags
& DHOPT_FORCE
)
1743 if (force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
))
1746 struct dhcp_opt
*start
;
1748 /* find size in advance */
1749 for (start
= opt
= config_opts
; opt
; opt
= opt
->next
)
1750 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1752 int new = do_opt(opt
, NULL
, context
->local
, null_term
) + 2;
1753 if (enc_len
+ new <= 255)
1757 p
= free_space(mess
, end
, OPTION_VENDOR_CLASS_OPT
, enc_len
);
1758 for (; start
&& start
!= opt
; start
= start
->next
)
1759 if (p
&& (start
->flags
& DHOPT_VENDOR_MATCH
))
1761 len
= do_opt(start
, p
+ 2, context
->local
, null_term
);
1762 *(p
++) = start
->opt
;
1772 (p
= free_space(mess
, end
, OPTION_VENDOR_CLASS_OPT
, enc_len
+ 1)))
1774 for (; start
; start
= start
->next
)
1775 if (start
->flags
& DHOPT_VENDOR_MATCH
)
1777 len
= do_opt(start
, p
+ 2, context
->local
, null_term
);
1778 *(p
++) = start
->opt
;
1786 /* move agent_id back down to the end of the packet */
1789 p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1790 memmove(p
, agent_id
, real_end
- agent_id
);
1791 p
+= real_end
- agent_id
;
1792 memset(p
, 0, real_end
- p
); /* in case of overlap */
1795 /* restore BOOTP anti-overload hack */
1796 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
1799 mess
->sname
[0] = s0
;