]>
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
, unsigned char *agent_id
);
86 static void restore_agent_id(unsigned char *agent_id
, struct dhcp_packet
*mess
, unsigned char *real_end
);
87 static void do_options(struct dhcp_context
*context
,
88 struct dhcp_packet
*mess
,
89 unsigned char *real_end
,
90 unsigned char *req_options
,
92 struct dhcp_netid
*netid
,
93 struct in_addr subnet_addr
,
94 unsigned char fqdn_flags
,
96 unsigned char *agent_id
);
97 static unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
98 int clid_len
, unsigned char *clid
, int *len_out
);
99 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
102 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
, int int_index
,
103 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
)
105 unsigned char *opt
, *clid
= NULL
;
106 struct dhcp_lease
*ltmp
, *lease
= NULL
;
107 struct dhcp_vendor
*vendor
;
108 struct dhcp_mac
*mac
;
109 struct dhcp_netid_list
*id_list
;
110 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0;
111 struct dhcp_packet
*mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
112 unsigned char *end
= (unsigned char *)(mess
+ 1);
113 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
;
114 int hostname_auth
= 0, borken_opt
= 0;
115 unsigned char *req_options
= NULL
;
116 char *message
= NULL
;
118 struct dhcp_config
*config
;
119 struct dhcp_netid
*netid
= NULL
;
120 struct in_addr subnet_addr
, fallback
;
121 unsigned short fuzz
= 0;
122 unsigned int mess_type
= 0;
123 unsigned char fqdn_flags
= 0;
124 unsigned char *agent_id
= NULL
;
125 unsigned char *emac
= NULL
;
127 struct dhcp_netid known_id
;
129 subnet_addr
.s_addr
= 0;
131 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
134 if (mess
->htype
== 0 && mess
->hlen
!= 0)
137 /* check for DHCP rather than BOOTP */
138 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
140 mess_type
= option_uint(opt
, 1);
142 /* only insist on a cookie for DHCP. */
143 if (*((u32
*)&mess
->options
) != htonl(DHCP_COOKIE
))
146 /* two things to note here: expand_buf may move the packet,
147 so reassign mess from daemon->packet. Also, the size
148 sent includes the IP and UDP headers, hence the magic "-28" */
149 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
151 size_t size
= (size_t)option_uint(opt
, 2) - 28;
153 if (size
> DHCP_PACKET_MAX
)
154 size
= DHCP_PACKET_MAX
;
155 else if (size
< sizeof(struct dhcp_packet
))
156 size
= sizeof(struct dhcp_packet
);
158 if (expand_buf(&daemon
->dhcp_packet
, size
))
160 mess
= (struct dhcp_packet
*)daemon
->dhcp_packet
.iov_base
;
161 end
= ((unsigned char *)mess
) + size
;
165 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
166 it can affect the context-determination code. */
167 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
168 mess
->ciaddr
.s_addr
= 0;
170 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
172 /* Any agent-id needs to be copied back out, verbatim, as the last option
173 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
174 get overwritten, then it will be shuffled back at the end of processing.
175 Note that the incoming options must not be overwritten here, so there has to
176 be enough free space at the end of the packet to copy the option. */
178 unsigned int total
= option_len(opt
) + 2;
179 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
180 if (last_opt
&& last_opt
< end
- total
)
182 agent_id
= end
- total
;
183 memcpy(agent_id
, opt
, total
);
186 /* look for RFC3527 Link selection sub-option */
187 if ((sopt
= option_find1(option_ptr(opt
), option_ptr(opt
) + option_len(opt
), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
188 subnet_addr
= option_addr(sopt
);
190 /* if a circuit-id or remote-is option is provided, exact-match to options. */
191 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
195 if (vendor
->match_type
== MATCH_CIRCUIT
)
196 search
= SUBOPT_CIRCUIT_ID
;
197 else if (vendor
->match_type
== MATCH_REMOTE
)
198 search
= SUBOPT_REMOTE_ID
;
199 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
200 search
= SUBOPT_SUBSCR_ID
;
204 if ((sopt
= option_find1(option_ptr(opt
), option_ptr(opt
) + option_len(opt
), search
, 1)) &&
205 vendor
->len
== option_len(sopt
) &&
206 memcmp(option_ptr(sopt
), vendor
->data
, vendor
->len
) == 0)
208 vendor
->netid
.next
= netid
;
209 netid
= &vendor
->netid
;
215 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
216 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
217 subnet_addr
= option_addr(opt
);
219 /* If there is no client identifier option, use the hardware address */
220 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
222 clid_len
= option_len(opt
);
223 clid
= option_ptr(opt
);
226 /* do we have a lease in store? */
227 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
229 /* If this request is missing a clid, but we've seen one before,
230 use it again for option matching etc. */
231 if (lease
&& !clid
&& lease
->clid
)
233 clid_len
= lease
->clid_len
;
237 /* find mac to use for logging and hashing */
238 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
241 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
242 if (mac
->hwaddr_len
== mess
->hlen
&&
243 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
244 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
246 mac
->netid
.next
= netid
;
250 /* Determine network for this packet. Our caller will have already linked all the
251 contexts which match the addresses of the receiving interface but if the
252 machine has an address already, or came via a relay, or we have a subnet selector,
253 we search again. If we don't have have a giaddr or explicit subnet selector,
254 use the ciaddr. This is necessary because a machine which got a lease via a
255 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
256 from the physical network, continue using that to allow correct DHCPNAK generation later. */
257 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
259 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
263 if (subnet_addr
.s_addr
)
268 else if (mess
->giaddr
.s_addr
)
275 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
277 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
278 if (context_tmp
->netmask
.s_addr
&&
279 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
280 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
282 context_new
= context
;
288 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
289 if (context_tmp
->netmask
.s_addr
&&
290 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
291 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
293 context_tmp
->current
= context_new
;
294 context_new
= context_tmp
;
297 if (context_new
|| force
)
298 context
= context_new
;
304 my_syslog(LOG_WARNING
, _("no address range available for DHCP request %s %s"),
305 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
306 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
310 /* keep _a_ local address available. */
311 fallback
= context
->local
;
313 if (daemon
->options
& OPT_LOG_OPTS
)
315 struct dhcp_context
*context_tmp
;
316 my_syslog(LOG_INFO
, _("DHCP packet: transaction-id is %u"), mess
->xid
);
317 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
319 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
320 if (context_tmp
->flags
& CONTEXT_STATIC
)
321 my_syslog(LOG_INFO
, _("Available DHCP subnet: %s/%s"), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
323 my_syslog(LOG_INFO
, _("Available DHCP range: %s -- %s"), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
327 mess
->op
= BOOTREPLY
;
329 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
330 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
332 /* set "known" tag for known hosts */
335 known_id
.net
= "known";
336 known_id
.next
= netid
;
343 struct dhcp_netid id
, bootp_id
;
344 struct in_addr
*logaddr
= NULL
;
346 /* must have a MAC addr for bootp */
347 if (mess
->htype
== 0 || mess
->hlen
== 0)
350 if (have_config(config
, CONFIG_DISABLE
))
351 message
= _("disabled");
353 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
355 if (have_config(config
, CONFIG_NAME
))
356 hostname
= config
->hostname
;
358 if (have_config(config
, CONFIG_NETID
))
360 config
->netid
.next
= netid
;
361 netid
= &config
->netid
;
364 /* Match incoming filename field as a netid. */
367 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
368 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
369 id
.net
= (char *)daemon
->dhcp_buff2
;
374 /* Add "bootp" as a tag to allow different options, address ranges etc
376 bootp_id
.net
= "bootp";
377 bootp_id
.next
= netid
;
380 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
381 if (match_netid(id_list
->list
, netid
, 0))
382 message
= _("disabled");
386 if (have_config(config
, CONFIG_ADDR
))
388 logaddr
= &config
->addr
;
389 mess
->yiaddr
= config
->addr
;
390 if ((lease
= lease_find_by_addr(config
->addr
)) &&
391 (lease
->hwaddr_len
!= mess
->hlen
||
392 lease
->hwaddr_type
!= mess
->htype
||
393 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
394 message
= _("address in use");
396 else if (!(daemon
->options
& OPT_BOOTP_DYNAMIC
))
397 message
= _("no address configured");
400 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
401 !address_available(context
, lease
->addr
, netid
))
405 /* lease exists, wrong network. */
406 lease_prune(lease
, now
);
409 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, netid
, now
))
410 message
= _("no address available");
413 mess
->yiaddr
= lease
->addr
;
418 (!(lease
= lease_allocate(mess
->yiaddr
))))
419 message
= _("no leases left");
421 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
422 message
= _("wrong network");
426 logaddr
= &mess
->yiaddr
;
428 if (context
->netid
.net
)
430 context
->netid
.next
= netid
;
431 netid
= &context
->netid
;
434 lease_set_hwaddr(lease
, mess
->chaddr
, NULL
, mess
->hlen
, mess
->htype
, 0);
436 lease_set_hostname(lease
, hostname
, daemon
->domain_suffix
, 1);
437 lease_set_expires(lease
, 0xffffffff, now
); /* infinite lease */
438 lease_set_interface(lease
, int_index
);
440 clear_packet(mess
, end
, NULL
);
441 do_options(context
, mess
, end
, NULL
,
442 hostname
, netid
, subnet_addr
, 0, 0, NULL
);
446 log_packet(NULL
, logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
);
448 return message
? 0 : dhcp_packet_size(mess
, netid
);
451 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
453 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
454 int len
= option_len(opt
);
455 char *pq
= daemon
->dhcp_buff
;
456 unsigned char *pp
, *op
= option_ptr(opt
);
463 /* Always force update, since the client has no way to do it itself. */
464 if (!(fqdn_flags
& 0x01))
470 if (fqdn_flags
& 0x04)
471 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
473 memcpy(pq
, op
+1, *op
);
481 if (len
> 0 && op
[len
-1] == 0)
486 if (pq
!= daemon
->dhcp_buff
)
491 if (canonicalise(daemon
->dhcp_buff
))
492 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
494 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
496 int len
= option_len(opt
);
497 memcpy(daemon
->dhcp_buff
, option_ptr(opt
), len
);
498 /* Microsoft clients are broken, and need zero-terminated strings
499 in options. We detect this state here, and do the same in
500 any options we send */
501 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
504 daemon
->dhcp_buff
[len
] = 0;
505 if (canonicalise(daemon
->dhcp_buff
))
506 client_hostname
= daemon
->dhcp_buff
;
509 if (have_config(config
, CONFIG_NAME
))
511 hostname
= config
->hostname
;
513 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
514 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
515 offer_hostname
= hostname
;
517 else if (client_hostname
)
519 char *d
= strip_hostname(client_hostname
);
521 my_syslog(LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), d
, client_hostname
);
523 if (strlen(client_hostname
) != 0)
525 hostname
= client_hostname
;
528 /* Search again now we have a hostname.
529 Only accept configs without CLID and HWADDR here, (they won't match)
530 to avoid impersonation by name. */
531 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
532 mess
->chaddr
, mess
->hlen
,
533 mess
->htype
, hostname
);
534 if (new && !have_config(new, CONFIG_CLID
) && !have_config(new, CONFIG_HWADDR
))
537 /* set "known" tag for known hosts */
538 known_id
.net
= "known";
539 known_id
.next
= netid
;
546 if (have_config(config
, CONFIG_NETID
))
548 config
->netid
.next
= netid
;
549 netid
= &config
->netid
;
552 /* user-class options are, according to RFC3004, supposed to contain
553 a set of counted strings. Here we check that this is so (by seeing
554 if the counts are consistent with the overall option length) and if
555 so zero the counts so that we don't get spurious matches between
556 the vendor string and the counts. If the lengths don't add up, we
557 assume that the option is a single string and non RFC3004 compliant
558 and just do the substring match. dhclient provides these broken options.
559 The code, later, which sends user-class data to the lease-change script
560 relies on the transformation done here.
563 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
565 unsigned char *ucp
= option_ptr(opt
);
567 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
568 if (j
== option_len(opt
))
569 for (j
= 0; j
< option_len(opt
); j
= tmp
)
571 tmp
= j
+ ucp
[j
] + 1;
576 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
580 if (vendor
->match_type
== MATCH_VENDOR
)
581 mopt
= OPTION_VENDOR_ID
;
582 else if (vendor
->match_type
== MATCH_USER
)
583 mopt
= OPTION_USER_CLASS
;
584 else if (vendor
->match_type
== MATCH_OPTION
)
586 if (option_find(mess
, sz
, vendor
->option
, 1))
588 vendor
->netid
.next
= netid
;
589 netid
= &vendor
->netid
;
596 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
599 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
600 if (memcmp(vendor
->data
, option_ptr(opt
)+i
, vendor
->len
) == 0)
602 vendor
->netid
.next
= netid
;
603 netid
= &vendor
->netid
;
609 /* mark vendor-encapsulated options which match the client-supplied vendor class */
610 match_vendor_opts(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->dhcp_opts
);
612 if (daemon
->options
& OPT_LOG_OPTS
)
614 if (sanitise(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->namebuff
))
615 my_syslog(LOG_INFO
, _("Vendor class: %s"), daemon
->namebuff
);
616 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
617 my_syslog(LOG_INFO
, _("User class: %s"), daemon
->namebuff
);
620 /* if all the netids in the ignore list are present, ignore this client */
621 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
622 if (match_netid(id_list
->list
, netid
, 0))
625 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
626 if (have_config(config
, CONFIG_NOCLID
))
629 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
631 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
632 memcpy(req_options
, option_ptr(opt
), option_len(opt
));
633 req_options
[option_len(opt
)] = OPTION_END
;
639 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
640 (context
->local
.s_addr
!= option_addr(opt
).s_addr
))
643 /* sanitise any message. Paranoid? Moi? */
644 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
646 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
649 log_packet("DECLINE", option_ptr(opt
), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
);
651 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
652 lease_prune(lease
, now
);
654 if (have_config(config
, CONFIG_ADDR
) &&
655 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
657 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
658 my_syslog(LOG_WARNING
, _("disabling DHCP static address %s for %s"),
659 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
660 config
->flags
|= CONFIG_DECLINED
;
661 config
->decline_time
= now
;
664 /* make sure this host gets a different address next time. */
665 for (; context
; context
= context
->current
)
666 context
->addr_epoch
++;
671 if (!(context
= narrow_context(context
, mess
->ciaddr
, netid
)) ||
672 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
673 (context
->local
.s_addr
!= option_addr(opt
).s_addr
))
676 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
677 lease_prune(lease
, now
);
679 message
= _("unknown lease");
681 log_packet("RELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
);
686 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
688 message
= _("ignored");
693 struct in_addr addr
, conf
;
695 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
696 addr
= option_addr(opt
);
699 if (have_config(config
, CONFIG_ADDR
))
701 char *addrs
= inet_ntoa(config
->addr
);
703 if ((ltmp
= lease_find_by_addr(config
->addr
)) && ltmp
!= lease
)
706 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
707 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
708 my_syslog(LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
709 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
713 struct dhcp_context
*tmp
;
714 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
715 if (context
->router
.s_addr
== config
->addr
.s_addr
)
718 my_syslog(LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
719 else if (have_config(config
, CONFIG_DECLINED
) &&
720 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
721 my_syslog(LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
729 else if (lease
&& address_available(context
, lease
->addr
, netid
))
730 mess
->yiaddr
= lease
->addr
;
731 else if (opt
&& address_available(context
, addr
, netid
) && !lease_find_by_addr(addr
) &&
732 !config_find_by_address(daemon
->dhcp_conf
, addr
))
734 else if (emac_len
== 0)
735 message
= _("no unique-id");
736 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, netid
, now
))
737 message
= _("no address available");
740 log_packet("DISCOVER", opt
? option_ptr(opt
) : NULL
, emac
, emac_len
, iface_name
, message
);
742 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
745 log_packet("OFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
);
747 if (context
->netid
.net
)
749 context
->netid
.next
= netid
;
750 netid
= &context
->netid
;
753 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
754 clear_packet(mess
, end
, agent_id
);
755 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
756 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
757 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
758 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
759 if (time
!= 0xffffffff)
761 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
762 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
764 do_options(context
, mess
, end
, req_options
, offer_hostname
,
765 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
767 return dhcp_packet_size(mess
, netid
);
770 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
772 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
774 /* SELECTING or INIT_REBOOT */
775 mess
->yiaddr
= option_addr(opt
);
777 /* send vendor and user class info for new or recreated lease */
780 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
785 for (; context
; context
= context
->current
)
786 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
792 /* If a lease exists for this host and another address, squash it. */
793 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
795 lease_prune(lease
, now
);
802 if (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
))
805 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
807 message
= _("wrong address");
808 /* avoid loops when client brain-dead */
809 lease_prune(lease
, now
);
816 /* RENEWING or REBINDING */
817 /* Check existing lease for this address.
818 We allow it to be missing if dhcp-authoritative mode
819 as long as we can allocate the lease now - checked below.
820 This makes for a smooth recovery from a lost lease DB */
821 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
822 (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
)))
824 message
= _("lease not found");
825 /* ensure we broadcast NAK */
828 /* desynchronise renewals */
830 mess
->yiaddr
= mess
->ciaddr
;
833 log_packet("REQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
);
837 struct dhcp_config
*addr_config
;
838 struct dhcp_context
*tmp
= NULL
;
840 if (have_config(config
, CONFIG_ADDR
))
841 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
842 if (context
->router
.s_addr
== config
->addr
.s_addr
)
845 if (!(context
= narrow_context(context
, mess
->yiaddr
, netid
)))
847 /* If a machine moves networks whilst it has a lease, we catch that here. */
848 message
= _("wrong network");
849 /* ensure we broadcast NAK */
853 /* Check for renewal of a lease which is outside the allowed range. */
854 else if (!address_available(context
, mess
->yiaddr
, netid
) &&
855 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
856 message
= _("address not available");
858 /* Check if a new static address has been configured. Be very sure that
859 when the client does DISCOVER, it will get the static address, otherwise
860 an endless protocol loop will ensue. */
861 else if (!tmp
&& !selecting
&&
862 have_config(config
, CONFIG_ADDR
) &&
863 (!have_config(config
, CONFIG_DECLINED
) ||
864 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
865 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
866 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
867 message
= _("static lease available");
869 /* Check to see if the address is reserved as a static address for another host */
870 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
871 message
= _("address reserved");
873 else if ((ltmp
= lease_find_by_addr(mess
->yiaddr
)) && ltmp
!= lease
)
874 message
= _("address in use");
876 else if (emac_len
== 0)
877 message
= _("no unique-id");
881 if ((lease
= lease_allocate(mess
->yiaddr
)))
884 message
= _("no leases left");
890 log_packet("NAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
);
892 mess
->yiaddr
.s_addr
= 0;
893 clear_packet(mess
, end
, agent_id
);
894 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
895 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
,
896 ntohl(context
? context
->local
.s_addr
: fallback
.s_addr
));
897 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
898 /* DHCPNAK gets agent-id too */
899 restore_agent_id(agent_id
, mess
, end
);
900 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
901 a distant subnet which unicast a REQ to us won't work. */
902 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
903 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
905 mess
->flags
|= htons(0x8000); /* broadcast */
906 mess
->ciaddr
.s_addr
= 0;
914 /* copy user-class and vendor class into new lease, for the script */
915 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
917 int len
= option_len(opt
);
918 unsigned char *ucp
= option_ptr(opt
);
919 /* If the user-class option started as counted strings, the first byte will be zero. */
920 if (len
!= 0 && ucp
[0] == 0)
922 free(lease
->userclass
);
923 if ((lease
->userclass
= whine_malloc(len
+1)))
925 memcpy(lease
->userclass
, ucp
, len
);
926 lease
->userclass
[len
] = 0;
927 lease
->userclass_len
= len
+1;
930 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
932 int len
= option_len(opt
);
933 unsigned char *ucp
= option_ptr(opt
);
934 free(lease
->vendorclass
);
935 if ((lease
->vendorclass
= whine_malloc(len
+1)))
937 memcpy(lease
->vendorclass
, ucp
, len
);
938 lease
->vendorclass
[len
] = 0;
939 lease
->vendorclass_len
= len
+1;
944 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
946 hostname
= client_hostname
;
950 if (context
->netid
.net
)
952 context
->netid
.next
= netid
;
953 netid
= &context
->netid
;
956 time
= calc_time(context
, config
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4));
957 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
);
959 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
962 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
963 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
969 lease_set_hostname(lease
, hostname
, daemon
->domain_suffix
, hostname_auth
);
971 lease_set_expires(lease
, time
, now
);
972 lease_set_interface(lease
, int_index
);
974 log_packet("ACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
);
976 clear_packet(mess
, end
, agent_id
);
977 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
978 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
979 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
980 if (time
!= 0xffffffff)
982 while (fuzz
> (time
/16))
984 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
985 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
987 do_options(context
, mess
, end
, req_options
, hostname
,
988 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
991 return dhcp_packet_size(mess
, netid
);
994 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
995 message
= _("ignored");
997 log_packet("INFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
);
999 if (message
|| mess
->ciaddr
.s_addr
== 0 ||
1000 !(context
= narrow_context(context
, mess
->ciaddr
, netid
)))
1003 /* Find a least based on IP address if we didn't
1004 get one from MAC address/client-d */
1006 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
1008 hostname
= lease
->hostname
;
1011 hostname
= host_from_dns(mess
->ciaddr
);
1013 log_packet("ACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
);
1015 if (context
->netid
.net
)
1017 context
->netid
.next
= netid
;
1018 netid
= &context
->netid
;
1021 clear_packet(mess
, end
, agent_id
);
1022 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
1023 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
1027 if (lease
->expires
== 0)
1030 time
= (unsigned int)difftime(lease
->expires
, now
);
1031 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1032 lease_set_interface(lease
, int_index
);
1035 do_options(context
, mess
, end
, req_options
, hostname
,
1036 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
1038 *is_inform
= 1; /* handle reply differently */
1039 return dhcp_packet_size(mess
, netid
);
1045 /* find a good value to use as MAC address for logging and address-allocation hashing.
1046 This is normally just the chaddr field from the DHCP packet,
1047 but eg Firewire will have hlen == 0 and use the client-id instead.
1048 This could be anything, but will normally be EUI64 for Firewire.
1049 We assume that if the first byte of the client-id equals the htype byte
1050 then the client-id is using the usual encoding and use the rest of the
1051 client-id: if not we can use the whole client-id. This should give
1052 sane MAC address logs. */
1053 static unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1054 int clid_len
, unsigned char *clid
, int *len_out
)
1056 if (hwlen
== 0 && clid
&& clid_len
> 3)
1058 if (clid
[0] == hwtype
)
1060 *len_out
= clid_len
- 1 ;
1064 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1065 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1067 *len_out
= clid_len
- 1 ;
1072 *len_out
= clid_len
;
1080 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
, unsigned char *opt
)
1082 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1086 unsigned int req_time
= option_uint(opt
, 4);
1087 if (req_time
< 120 )
1088 req_time
= 120; /* sanity */
1089 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1096 static int sanitise(unsigned char *opt
, char *buf
)
1106 p
= option_ptr(opt
);
1108 for (i
= option_len(opt
); i
> 0; i
--)
1111 if (isprint((int)c
))
1114 *buf
= 0; /* add terminator */
1119 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1120 int mac_len
, char *interface
, char *string
)
1124 /* addr may be misaligned */
1126 memcpy(&a
, addr
, sizeof(a
));
1128 my_syslog(LOG_INFO
, "%s%s(%s) %s%s%s %s",
1129 type
? "DHCP" : "BOOTP",
1132 addr
? inet_ntoa(a
) : "",
1134 print_mac(daemon
->namebuff
, ext_mac
, mac_len
),
1135 string
? string
: "");
1138 static void log_options(unsigned char *start
)
1140 while (*start
!= OPTION_END
)
1142 char *text
= option_string(start
[0]);
1143 unsigned char trunc
= start
[1] < 13 ? start
[1] : 13;
1144 my_syslog(LOG_INFO
, "sent size:%3d option:%3d%s%s%s%s%s",
1146 text
? ":" : "", text
? text
: "",
1147 start
[1] == 0 ? "" : " ",
1148 start
[1] == 0 ? "" : print_mac(daemon
->namebuff
, &start
[2], trunc
),
1149 trunc
== start
[1] ? "" : "...");
1150 start
+= start
[1] + 2;
1154 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1156 while (*p
!= OPTION_END
)
1159 return NULL
; /* malformed packet */
1160 else if (*p
== OPTION_PAD
)
1166 return NULL
; /* malformed packet */
1167 opt_len
= option_len(p
);
1168 if (p
>= end
- (2 + opt_len
))
1169 return NULL
; /* malformed packet */
1170 if (*p
== opt
&& opt_len
>= minsize
)
1176 return opt
== OPTION_END
? p
: NULL
;
1179 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1181 unsigned char *ret
, *overload
;
1183 /* skip over DHCP cookie; */
1184 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1187 /* look for overload option. */
1188 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1191 /* Can we look in filename area ? */
1192 if ((overload
[2] & 1) &&
1193 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1196 /* finally try sname area */
1197 if ((overload
[2] & 2) &&
1198 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1204 static struct in_addr
option_addr(unsigned char *opt
)
1206 /* this worries about unaligned data in the option. */
1207 /* struct in_addr is network byte order */
1210 memcpy(&ret
, option_ptr(opt
), INADDRSZ
);
1215 static unsigned int option_uint(unsigned char *opt
, int size
)
1217 /* this worries about unaligned data and byte order */
1218 unsigned int ret
= 0;
1220 unsigned char *p
= option_ptr(opt
);
1222 for (i
= 0; i
< size
; i
++)
1223 ret
= (ret
<< 8) | *p
++;
1228 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1231 start
+= start
[1] + 2;
1235 /* only for use when building packet: doesn't check for bad data. */
1236 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1238 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1242 if (*p
== OPTION_OVERLOAD
)
1249 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
)
1251 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1252 unsigned char *overload
;
1254 struct dhcp_netid_list
*id_list
;
1256 /* We do logging too */
1257 if (netid
&& (daemon
->options
& OPT_LOG_OPTS
))
1259 char *p
= daemon
->namebuff
;
1261 for (; netid
; netid
= netid
->next
)
1263 strncat (p
, netid
->net
, MAXDNAME
);
1265 strncat (p
, ", ", MAXDNAME
);
1267 p
[MAXDNAME
- 1] = 0;
1268 my_syslog(LOG_INFO
, _("tags: %s"), p
);
1271 /* add END options to the regions. */
1272 if ((overload
= find_overload(mess
)))
1274 if (option_uint(overload
, 1) & 1)
1276 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1277 if (daemon
->options
& OPT_LOG_OPTS
)
1278 log_options(mess
->file
);
1280 if (option_uint(overload
, 1) & 2)
1282 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1283 if (daemon
->options
& OPT_LOG_OPTS
)
1284 log_options(mess
->sname
);
1290 if (daemon
->options
& OPT_LOG_OPTS
)
1291 log_options(&mess
->options
[0] + sizeof(u32
));
1293 for (id_list
= daemon
->force_broadcast
; id_list
; id_list
= id_list
->next
)
1294 if (match_netid(id_list
->list
, netid
, 0))
1295 mess
->flags
|= htons(0x8000); /* force broadcast */
1297 ret
= (size_t)(p
- (unsigned char *)mess
);
1299 if (ret
< MIN_PACKETSZ
)
1305 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1307 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1309 if (p
+ len
+ 3 >= end
)
1310 /* not enough space in options area, try and use overload, if poss */
1312 unsigned char *overload
;
1314 if (!(overload
= find_overload(mess
)) &&
1315 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1317 /* attempt to overload fname and sname areas, we've reserved space for the
1318 overflow option previuously. */
1320 *(p
++) = OPTION_OVERLOAD
;
1326 /* using filename field ? */
1329 if (mess
->file
[0] == 0)
1332 if (overload
[2] & 1)
1334 p
= dhcp_skip_opts(mess
->file
);
1335 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1341 /* try to bring sname into play (it may be already) */
1342 if (mess
->sname
[0] == 0)
1345 if (overload
[2] & 2)
1347 p
= dhcp_skip_opts(mess
->sname
);
1348 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1355 my_syslog(LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1367 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1370 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1373 for (i
= 0; i
< len
; i
++)
1374 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1377 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1378 char *string
, int null_term
)
1381 size_t len
= strlen(string
);
1383 if (null_term
&& len
!= 255)
1386 if ((p
= free_space(mess
, end
, opt
, len
)))
1387 memcpy(p
, string
, len
);
1390 /* return length, note this only does the data part */
1391 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct in_addr local
, int null_term
)
1395 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1400 if ((opt
->flags
& DHOPT_ADDR
) && !(opt
->flags
& DHOPT_ENCAPSULATE
))
1403 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1404 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1406 /* zero means "self" (but not in vendorclass options.) */
1408 memcpy(p
, &local
, INADDRSZ
);
1410 memcpy(p
, a
, INADDRSZ
);
1415 memcpy(p
, opt
->val
, len
);
1420 static int in_list(unsigned char *list
, int opt
)
1424 /* If no requested options, send everything, not nothing. */
1428 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1435 static struct dhcp_opt
*option_find2(struct dhcp_netid
*netid
, struct dhcp_opt
*opts
, int opt
)
1437 struct dhcp_opt
*tmp
;
1438 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
1439 if (tmp
->opt
== opt
&& !(tmp
->flags
& DHOPT_ENCAPSULATE
))
1440 if (match_netid(tmp
->netid
, netid
, 1) || match_netid(tmp
->netid
, netid
, 0))
1443 return netid
? option_find2(NULL
, opts
, opt
) : NULL
;
1446 /* mark vendor-encapsulated options which match the client-supplied or
1447 config-supplied vendor class */
1448 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1450 for (; dopt
; dopt
= dopt
->next
)
1452 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1453 if (opt
&& (dopt
->flags
& DHOPT_ENCAPSULATE
))
1456 if (dopt
->vendor_class
)
1457 len
= strlen((char *)dopt
->vendor_class
);
1458 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1459 if (len
== 0 || memcmp(dopt
->vendor_class
, option_ptr(opt
)+i
, len
) == 0)
1461 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1468 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
, unsigned char *agent_id
)
1470 /* don't clear agent_id */
1474 memset(mess
->sname
, 0, sizeof(mess
->sname
));
1475 memset(mess
->file
, 0, sizeof(mess
->file
));
1476 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
1477 mess
->siaddr
.s_addr
= 0;
1480 static void restore_agent_id(unsigned char *agent_id
, struct dhcp_packet
*mess
, unsigned char *real_end
)
1484 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1485 memmove(p
, agent_id
, real_end
- agent_id
);
1486 p
+= real_end
- agent_id
;
1487 memset(p
, 0, real_end
- p
); /* in case of overlap */
1491 static void do_options(struct dhcp_context
*context
,
1492 struct dhcp_packet
*mess
,
1493 unsigned char *real_end
,
1494 unsigned char *req_options
,
1496 struct dhcp_netid
*netid
,
1497 struct in_addr subnet_addr
,
1498 unsigned char fqdn_flags
,
1500 unsigned char *agent_id
)
1502 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
1503 struct dhcp_boot
*boot
;
1504 unsigned char *p
, *end
= agent_id
? agent_id
: real_end
;
1505 int i
, len
, force_encap
= 0;
1506 unsigned char f0
= 0, s0
= 0;
1507 int done_file
= 0, done_server
= 0;
1510 if ((daemon
->options
& OPT_LOG_OPTS
) && req_options
)
1512 char *q
= daemon
->namebuff
;
1513 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
1515 char *s
= option_string(req_options
[i
]);
1516 q
+= snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
1521 req_options
[i
+1] == OPTION_END
? "" : ", ");
1522 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
1524 q
= daemon
->namebuff
;
1525 my_syslog(LOG_INFO
, _("requested options: %s"), daemon
->namebuff
);
1530 /* decide which dhcp-boot option we're using */
1531 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1532 if (match_netid(boot
->netid
, netid
, 0))
1535 /* No match, look for one without a netid */
1536 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1537 if (match_netid(boot
->netid
, netid
, 1))
1540 mess
->siaddr
= context
->local
;
1542 /* See if we can send the boot stuff as options.
1543 To do this we need a requested option list, BOOTP
1544 and very old DHCP clients won't have this, we also
1545 provide an manual option to disable it.
1546 Some PXE ROMs have bugs (surprise!) and need zero-terminated
1547 names, so we always send those. */
1552 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
1554 in_list(req_options
, OPTION_SNAME
))
1555 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
1557 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
1562 if (!(daemon
->options
& OPT_NO_OVERRIDE
) &&
1564 in_list(req_options
, OPTION_FILENAME
))
1565 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
1567 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
1570 if (boot
->next_server
.s_addr
)
1571 mess
->siaddr
= boot
->next_server
;
1573 if (daemon
->options
& OPT_LOG_OPTS
)
1574 my_syslog(LOG_INFO
, _("next server: %s"), inet_ntoa(mess
->siaddr
));
1577 /* Use the values of the relevant options if no dhcp-boot given and
1578 they're no explicitly asked for as options. */
1580 if ((!req_options
|| !in_list(req_options
, OPTION_FILENAME
)) &&
1581 (opt
= option_find2(netid
, config_opts
, OPTION_FILENAME
)))
1583 strncpy((char *)mess
->file
, (char *)opt
->val
, sizeof(mess
->file
)-1);
1587 if ((!req_options
|| !in_list(req_options
, OPTION_SNAME
)) &&
1588 (opt
= option_find2(netid
, config_opts
, OPTION_SNAME
)))
1590 strncpy((char *)mess
->sname
, (char *)opt
->val
, sizeof(mess
->sname
)-1);
1595 if (daemon
->options
& OPT_LOG_OPTS
)
1597 if (strlen((char *)mess
->file
) != 0)
1598 my_syslog(LOG_INFO
, _("bootfile name: %s"), (char *)mess
->file
);
1600 if (strlen((char *)mess
->sname
) != 0)
1601 my_syslog(LOG_INFO
, _("server name: %s"), (char *)mess
->sname
);
1604 /* We don't want to do option-overload for BOOTP, so make the file and sname
1605 fields look like they are in use, even when they aren't. This gets restored
1606 at the end of this function. */
1608 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
1612 s0
= mess
->sname
[0];
1616 /* At this point, if mess->sname or mess->file are zeroed, they are available
1617 for option overload, reserve space for the overload option. */
1618 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
1621 /* rfc3011 says this doesn't need to be in the requested options list. */
1622 if (subnet_addr
.s_addr
)
1623 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
1625 if (!option_find2(netid
, config_opts
, OPTION_NETMASK
))
1626 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
1628 /* May not have a "guessed" broadcast address if we got no packets via a relay
1629 from this net yet (ie just unicast renewals after a restart */
1630 if (context
->broadcast
.s_addr
&&
1631 !option_find2(netid
, config_opts
, OPTION_BROADCAST
))
1632 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
1634 /* Same comments as broadcast apply, and also may not be able to get a sensible
1635 default when using subnet select. User must configure by steam in that case. */
1636 if (context
->router
.s_addr
&&
1637 in_list(req_options
, OPTION_ROUTER
) &&
1638 !option_find2(netid
, config_opts
, OPTION_ROUTER
))
1639 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
1641 if (in_list(req_options
, OPTION_DNSSERVER
) &&
1642 !option_find2(netid
, config_opts
, OPTION_DNSSERVER
))
1643 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
1645 if (daemon
->domain_suffix
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
1646 !option_find2(netid
, config_opts
, OPTION_DOMAINNAME
))
1647 option_put_string(mess
, end
, OPTION_DOMAINNAME
, daemon
->domain_suffix
, null_term
);
1649 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
1652 if (in_list(req_options
, OPTION_HOSTNAME
) &&
1653 !option_find2(netid
, config_opts
, OPTION_HOSTNAME
))
1654 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
1656 if (fqdn_flags
!= 0)
1658 int len
= strlen(hostname
) + 3;
1659 if (fqdn_flags
& 0x04)
1664 if (daemon
->domain_suffix
)
1665 len
+= strlen(daemon
->domain_suffix
) + 1;
1667 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
1669 *(p
++) = fqdn_flags
;
1673 if (fqdn_flags
& 0x04)
1675 p
= do_rfc1035_name(p
, hostname
);
1676 if (daemon
->domain_suffix
)
1677 p
= do_rfc1035_name(p
, daemon
->domain_suffix
);
1682 memcpy(p
, hostname
, strlen(hostname
));
1683 p
+= strlen(hostname
);
1684 if (daemon
->domain_suffix
)
1687 memcpy(p
, daemon
->domain_suffix
, strlen(daemon
->domain_suffix
));
1688 p
+= strlen(daemon
->domain_suffix
);
1697 for (opt
= config_opts
; opt
; opt
= opt
->next
)
1699 int optno
= opt
->opt
;
1701 /* was it asked for, or are we sending it anyway? */
1702 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, optno
))
1705 /* prohibit some used-internally options */
1706 if (optno
== OPTION_CLIENT_FQDN
||
1707 optno
== OPTION_MAXMESSAGE
||
1708 optno
== OPTION_OVERLOAD
||
1709 optno
== OPTION_PAD
||
1710 optno
== OPTION_END
)
1713 if (optno
== OPTION_SNAME
&& done_server
)
1716 if (optno
== OPTION_FILENAME
&& done_file
)
1719 /* netids match and not encapsulated? */
1720 if (opt
!= option_find2(netid
, config_opts
, optno
))
1723 /* For the options we have default values on
1724 dhc-option=<optionno> means "don't include this option"
1725 not "include a zero-length option" */
1726 if (opt
->len
== 0 &&
1727 (optno
== OPTION_NETMASK
||
1728 optno
== OPTION_BROADCAST
||
1729 optno
== OPTION_ROUTER
||
1730 optno
== OPTION_DNSSERVER
||
1731 optno
== OPTION_DOMAINNAME
||
1732 optno
== OPTION_HOSTNAME
))
1735 /* always force null-term for filename ans servername - buggy PXE again. */
1736 len
= do_opt(opt
, NULL
, context
->local
,
1737 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
1739 if ((p
= free_space(mess
, end
, optno
, len
)))
1741 do_opt(opt
, p
, context
->local
,
1742 (optno
== OPTION_SNAME
|| optno
== OPTION_FILENAME
) ? 1 : null_term
);
1744 /* If we send a vendor-id, revisit which vendor-ops we consider
1745 it appropriate to send. */
1746 if (optno
== OPTION_VENDOR_ID
)
1747 match_vendor_opts(p
- 2, config_opts
);
1751 /* prune encapsulated options based on netid, and look if we're forcing them to be sent */
1752 for (opt
= config_opts
; opt
; opt
= opt
->next
)
1753 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1755 if (!match_netid(opt
->netid
, netid
, 1) && !match_netid(opt
->netid
, netid
, 0))
1756 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1757 else if (opt
->flags
& DHOPT_FORCE
)
1761 if (force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
))
1764 struct dhcp_opt
*start
;
1766 /* find size in advance */
1767 for (start
= opt
= config_opts
; opt
; opt
= opt
->next
)
1768 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1770 int new = do_opt(opt
, NULL
, context
->local
, null_term
) + 2;
1771 if (enc_len
+ new <= 255)
1775 p
= free_space(mess
, end
, OPTION_VENDOR_CLASS_OPT
, enc_len
);
1776 for (; start
&& start
!= opt
; start
= start
->next
)
1777 if (p
&& (start
->flags
& DHOPT_VENDOR_MATCH
))
1779 len
= do_opt(start
, p
+ 2, context
->local
, null_term
);
1780 *(p
++) = start
->opt
;
1790 (p
= free_space(mess
, end
, OPTION_VENDOR_CLASS_OPT
, enc_len
+ 1)))
1792 for (; start
; start
= start
->next
)
1793 if (start
->flags
& DHOPT_VENDOR_MATCH
)
1795 len
= do_opt(start
, p
+ 2, context
->local
, null_term
);
1796 *(p
++) = start
->opt
;
1804 /* move agent_id back down to the end of the packet */
1805 restore_agent_id(agent_id
, mess
, real_end
);
1807 /* restore BOOTP anti-overload hack */
1808 if (!req_options
|| (daemon
->options
& OPT_NO_OVERRIDE
))
1811 mess
->sname
[0] = s0
;