]>
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.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
17 #define DHCP_COOKIE 0x63825363
19 /* The Linux in-kernel DHCP client silently ignores any packet
20 smaller than this. Sigh........... */
21 #define MIN_PACKETSZ 300
24 #define OPTION_NETMASK 1
25 #define OPTION_ROUTER 3
26 #define OPTION_DNSSERVER 6
27 #define OPTION_HOSTNAME 12
28 #define OPTION_DOMAINNAME 15
29 #define OPTION_BROADCAST 28
30 #define OPTION_VENDOR_CLASS_OPT 43
31 #define OPTION_REQUESTED_IP 50
32 #define OPTION_LEASE_TIME 51
33 #define OPTION_OVERLOAD 52
34 #define OPTION_MESSAGE_TYPE 53
35 #define OPTION_SERVER_IDENTIFIER 54
36 #define OPTION_REQUESTED_OPTIONS 55
37 #define OPTION_MESSAGE 56
38 #define OPTION_MAXMESSAGE 57
41 #define OPTION_VENDOR_ID 60
42 #define OPTION_CLIENT_ID 61
43 #define OPTION_SNAME 66
44 #define OPTION_FILENAME 67
45 #define OPTION_USER_CLASS 77
46 #define OPTION_CLIENT_FQDN 81
47 #define OPTION_AGENT_ID 82
48 #define OPTION_SUBNET_SELECT 118
49 #define OPTION_END 255
51 #define SUBOPT_CIRCUIT_ID 1
52 #define SUBOPT_REMOTE_ID 2
53 #define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */
54 #define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */
56 #define DHCPDISCOVER 1
65 #define have_config(config, mask) ((config) && ((config)->flags & (mask)))
66 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
67 #define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2]))
69 static int sanitise(unsigned char *opt
, char *buf
);
70 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
,
71 struct dhcp_lease
*lease
, unsigned char *opt
, time_t now
);
72 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
);
73 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
,
74 int opt
, char *string
, int null_term
);
75 static struct in_addr
option_addr(unsigned char *opt
);
76 static unsigned int option_uint(unsigned char *opt
, int size
);
77 static void log_packet(char *type
, void *addr
,
78 unsigned char *ext_mac
, int mac_len
, char *interface
, char *string
);
79 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
);
80 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
);
81 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
);
82 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
);
83 static void do_options(struct dhcp_context
*context
,
84 struct dhcp_packet
*mess
,
85 unsigned char *real_end
,
86 unsigned char *req_options
,
88 struct dhcp_netid
*netid
,
89 struct in_addr subnet_addr
,
90 unsigned char fqdn_flags
,
92 unsigned char *agent_id
);
93 static unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
94 int clid_len
, unsigned char *clid
, int *len_out
);
95 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
);
98 size_t dhcp_reply(struct dhcp_context
*context
, char *iface_name
,
99 size_t sz
, time_t now
, int unicast_dest
, int *is_inform
)
101 unsigned char *opt
, *clid
= NULL
;
102 struct dhcp_lease
*ltmp
, *lease
= NULL
;
103 struct dhcp_vendor
*vendor
;
104 struct dhcp_mac
*mac
;
105 struct dhcp_netid_list
*id_list
;
106 int clid_len
= 0, ignore
= 0, do_classes
= 0, selecting
= 0;
107 struct dhcp_packet
*mess
= daemon
->dhcp_packet
.iov_base
;
108 unsigned char *end
= (unsigned char *)(mess
+ 1);
109 char *hostname
= NULL
, *offer_hostname
= NULL
, *client_hostname
= NULL
;
110 int hostname_auth
= 0, borken_opt
= 0;
111 unsigned char *req_options
= NULL
;
112 char *message
= NULL
;
114 struct dhcp_config
*config
;
115 struct dhcp_netid
*netid
= NULL
;
116 struct in_addr subnet_addr
, fallback
;
117 unsigned short fuzz
= 0;
118 unsigned int mess_type
= 0;
119 unsigned char fqdn_flags
= 0;
120 unsigned char *agent_id
= NULL
;
121 unsigned char *emac
= NULL
;
123 struct dhcp_netid known_id
;
125 subnet_addr
.s_addr
= 0;
127 if (mess
->op
!= BOOTREQUEST
|| mess
->hlen
> DHCP_CHADDR_MAX
)
130 if (mess
->htype
== 0 && mess
->hlen
!= 0)
133 /* check for DHCP rather than BOOTP */
134 if ((opt
= option_find(mess
, sz
, OPTION_MESSAGE_TYPE
, 1)))
136 mess_type
= option_uint(opt
, 1);
138 /* only insist on a cookie for DHCP. */
139 if (*((u32
*)&mess
->options
) != htonl(DHCP_COOKIE
))
142 /* two things to note here: expand_buf may move the packet,
143 so reassign mess from daemon->packet. Also, the size
144 sent includes the IP and UDP headers, hence the magic "-28" */
145 if ((opt
= option_find(mess
, sz
, OPTION_MAXMESSAGE
, 2)))
147 size_t size
= (size_t)option_uint(opt
, 2) - 28;
149 if (size
> DHCP_PACKET_MAX
)
150 size
= DHCP_PACKET_MAX
;
151 else if (size
< sizeof(struct dhcp_packet
))
152 size
= sizeof(struct dhcp_packet
);
154 if (expand_buf(&daemon
->dhcp_packet
, size
))
156 mess
= daemon
->dhcp_packet
.iov_base
;
157 end
= ((unsigned char *)mess
) + size
;
161 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
162 it can affect the context-determination code. */
163 if ((option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
) || mess_type
== DHCPDISCOVER
))
164 mess
->ciaddr
.s_addr
= 0;
166 if ((opt
= option_find(mess
, sz
, OPTION_AGENT_ID
, 1)))
168 /* Any agent-id needs to be copied back out, verbatim, as the last option
169 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
170 get overwritten, then it will be shuffled back at the end of processing.
171 Note that the incoming options must not be overwritten here, so there has to
172 be enough free space at the end of the packet to copy the option. */
174 unsigned int total
= option_len(opt
) + 2;
175 unsigned char *last_opt
= option_find(mess
, sz
, OPTION_END
, 0);
176 if (last_opt
&& last_opt
< end
- total
)
178 agent_id
= end
- total
;
179 memcpy(agent_id
, opt
, total
);
182 /* look for RFC3527 Link selection sub-option */
183 if ((sopt
= option_find1(option_ptr(opt
), option_ptr(opt
) + option_len(opt
), SUBOPT_SUBNET_SELECT
, INADDRSZ
)))
184 subnet_addr
= option_addr(sopt
);
186 /* if a circuit-id or remote-is option is provided, exact-match to options. */
187 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
191 if (vendor
->match_type
== MATCH_CIRCUIT
)
192 search
= SUBOPT_CIRCUIT_ID
;
193 else if (vendor
->match_type
== MATCH_REMOTE
)
194 search
= SUBOPT_REMOTE_ID
;
195 else if (vendor
->match_type
== MATCH_SUBSCRIBER
)
196 search
= SUBOPT_SUBSCR_ID
;
200 if ((sopt
= option_find1(option_ptr(opt
), option_ptr(opt
) + option_len(opt
), search
, 1)) &&
201 vendor
->len
== option_len(sopt
) &&
202 memcmp(option_ptr(sopt
), vendor
->data
, vendor
->len
) == 0)
204 vendor
->netid
.next
= netid
;
205 netid
= &vendor
->netid
;
211 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
212 if (subnet_addr
.s_addr
== 0 && (opt
= option_find(mess
, sz
, OPTION_SUBNET_SELECT
, INADDRSZ
)))
213 subnet_addr
= option_addr(opt
);
215 /* If there is no client identifier option, use the hardware address */
216 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_ID
, 1)))
218 clid_len
= option_len(opt
);
219 clid
= option_ptr(opt
);
222 /* do we have a lease in store? */
223 lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, clid
, clid_len
);
225 /* If this request is missing a clid, but we've seen one before,
226 use it again for option matching etc. */
227 if (lease
&& !clid
&& lease
->clid
)
229 clid_len
= lease
->clid_len
;
233 /* find mac to use for logging and hashing */
234 emac
= extended_hwaddr(mess
->htype
, mess
->hlen
, mess
->chaddr
, clid_len
, clid
, &emac_len
);
237 for (mac
= daemon
->dhcp_macs
; mac
; mac
= mac
->next
)
238 if (mac
->hwaddr_len
== mess
->hlen
&&
239 (mac
->hwaddr_type
== mess
->htype
|| mac
->hwaddr_type
== 0) &&
240 memcmp_masked(mac
->hwaddr
, mess
->chaddr
, mess
->hlen
, mac
->mask
))
242 mac
->netid
.next
= netid
;
246 /* Determine network for this packet. Our caller will have already linked all the
247 contexts which match the addresses of the receiving interface but if the
248 machine has an address already, or came via a relay, or we have a subnet selector,
249 we search again. If we don't have have a giaddr or explicit subnet selector,
250 use the ciaddr. This is necessary because a machine which got a lease via a
251 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
252 from the physical network, continue using that to allow correct DHCPNAK generation later. */
253 if (mess
->giaddr
.s_addr
|| subnet_addr
.s_addr
|| mess
->ciaddr
.s_addr
)
255 struct dhcp_context
*context_tmp
, *context_new
= NULL
;
259 if (subnet_addr
.s_addr
)
264 else if (mess
->giaddr
.s_addr
)
271 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
273 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
274 if (context_tmp
->netmask
.s_addr
&&
275 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
276 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
278 context_new
= context
;
284 for (context_tmp
= daemon
->dhcp
; context_tmp
; context_tmp
= context_tmp
->next
)
285 if (context_tmp
->netmask
.s_addr
&&
286 is_same_net(addr
, context_tmp
->start
, context_tmp
->netmask
) &&
287 is_same_net(addr
, context_tmp
->end
, context_tmp
->netmask
))
289 context_tmp
->current
= context_new
;
290 context_new
= context_tmp
;
293 if (context_new
|| force
)
294 context
= context_new
;
300 my_syslog(LOG_WARNING
, _("no address range available for DHCP request %s %s"),
301 subnet_addr
.s_addr
? _("with subnet selector") : _("via"),
302 subnet_addr
.s_addr
? inet_ntoa(subnet_addr
) : (mess
->giaddr
.s_addr
? inet_ntoa(mess
->giaddr
) : iface_name
));
306 /* keep _a_ local address available. */
307 fallback
= context
->local
;
309 if (daemon
->options
& OPT_LOG_OPTS
)
311 struct dhcp_context
*context_tmp
;
312 my_syslog(LOG_INFO
, _("DHCP packet: transaction-id is %u"), mess
->xid
);
313 for (context_tmp
= context
; context_tmp
; context_tmp
= context_tmp
->current
)
315 strcpy(daemon
->namebuff
, inet_ntoa(context_tmp
->start
));
316 if (context_tmp
->flags
& CONTEXT_STATIC
)
317 my_syslog(LOG_INFO
, _("Available DHCP subnet: %s/%s"), daemon
->namebuff
, inet_ntoa(context_tmp
->netmask
));
319 my_syslog(LOG_INFO
, _("Available DHCP range: %s -- %s"), daemon
->namebuff
, inet_ntoa(context_tmp
->end
));
323 mess
->op
= BOOTREPLY
;
325 config
= find_config(daemon
->dhcp_conf
, context
, clid
, clid_len
,
326 mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
);
328 /* set "known" tag for known hosts */
331 known_id
.net
= "known";
332 known_id
.next
= netid
;
339 struct dhcp_netid id
, bootp_id
;
340 struct in_addr
*logaddr
= NULL
;
342 /* must have a MAC addr for bootp */
343 if (mess
->htype
== 0 || mess
->hlen
== 0)
346 if (have_config(config
, CONFIG_DISABLE
))
347 message
= _("disabled");
349 end
= mess
->options
+ 64; /* BOOTP vend area is only 64 bytes */
351 if (have_config(config
, CONFIG_NAME
))
352 hostname
= config
->hostname
;
354 if (have_config(config
, CONFIG_NETID
))
356 config
->netid
.next
= netid
;
357 netid
= &config
->netid
;
360 /* Match incoming filename field as a netid. */
363 memcpy(daemon
->dhcp_buff2
, mess
->file
, sizeof(mess
->file
));
364 daemon
->dhcp_buff2
[sizeof(mess
->file
) + 1] = 0; /* ensure zero term. */
365 id
.net
= (char *)daemon
->dhcp_buff2
;
370 /* Add "bootp" as a tag to allow different options, address ranges etc
372 bootp_id
.net
= "bootp";
373 bootp_id
.next
= netid
;
376 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
377 if (match_netid(id_list
->list
, netid
, 0))
378 message
= _("disabled");
382 if (have_config(config
, CONFIG_ADDR
))
384 logaddr
= &config
->addr
;
385 mess
->yiaddr
= config
->addr
;
386 if ((lease
= lease_find_by_addr(config
->addr
)) &&
387 (lease
->hwaddr_len
!= mess
->hlen
||
388 lease
->hwaddr_type
!= mess
->htype
||
389 memcmp(lease
->hwaddr
, mess
->chaddr
, lease
->hwaddr_len
) != 0))
390 message
= _("address in use");
392 else if (!(daemon
->options
& OPT_BOOTP_DYNAMIC
))
393 message
= _("no address configured");
396 if (!(lease
= lease_find_by_client(mess
->chaddr
, mess
->hlen
, mess
->htype
, NULL
, 0)) ||
397 !address_available(context
, lease
->addr
))
401 /* lease exists, wrong network. */
402 lease_prune(lease
, now
);
405 if (!address_allocate(context
, &mess
->yiaddr
, mess
->chaddr
, mess
->hlen
, netid
, now
))
406 message
= _("no address available");
409 mess
->yiaddr
= lease
->addr
;
414 (!(lease
= lease_allocate(mess
->yiaddr
))))
416 my_syslog(LOG_WARNING
, _("Limit of %d leases exceeded."), daemon
->dhcp_max
);
417 message
= _("no leases left");
420 if (!message
&& !(context
= narrow_context(context
, mess
->yiaddr
)))
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 */
438 clear_packet(mess
, end
);
439 do_options(context
, mess
, end
, NULL
,
440 hostname
, netid
, subnet_addr
, 0, 0, NULL
);
444 log_packet(NULL
, logaddr
, mess
->chaddr
, mess
->hlen
, iface_name
, message
);
446 return message
? 0 : dhcp_packet_size(mess
, netid
);
449 if ((opt
= option_find(mess
, sz
, OPTION_CLIENT_FQDN
, 4)))
451 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
452 int len
= option_len(opt
);
453 char *pq
= daemon
->dhcp_buff
;
454 unsigned char *pp
, *op
= option_ptr(opt
);
461 /* Always force update, since the client has no way to do it itself. */
462 if (!(fqdn_flags
& 0x01))
468 if (fqdn_flags
& 0x04)
469 while (*op
!= 0 && ((op
+ (*op
) + 1) - pp
) < len
)
471 memcpy(pq
, op
+1, *op
);
479 if (len
> 0 && op
[len
-1] == 0)
484 if (pq
!= daemon
->dhcp_buff
)
489 if (canonicalise(daemon
->dhcp_buff
))
490 offer_hostname
= client_hostname
= daemon
->dhcp_buff
;
492 else if ((opt
= option_find(mess
, sz
, OPTION_HOSTNAME
, 1)))
494 int len
= option_len(opt
);
495 memcpy(daemon
->dhcp_buff
, option_ptr(opt
), len
);
496 /* Microsoft clients are broken, and need zero-terminated strings
497 in options. We detect this state here, and do the same in
498 any options we send */
499 if (len
> 0 && daemon
->dhcp_buff
[len
-1] == 0)
502 daemon
->dhcp_buff
[len
] = 0;
503 if (canonicalise(daemon
->dhcp_buff
))
504 client_hostname
= daemon
->dhcp_buff
;
507 if (have_config(config
, CONFIG_NAME
))
509 hostname
= config
->hostname
;
511 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
512 if (fqdn_flags
!= 0 || !client_hostname
|| hostname_isequal(hostname
, client_hostname
))
513 offer_hostname
= hostname
;
515 else if (client_hostname
)
517 char *d
= strip_hostname(client_hostname
);
519 my_syslog(LOG_WARNING
, _("Ignoring domain %s for DHCP host name %s"), d
, client_hostname
);
521 if (strlen(client_hostname
) != 0)
523 hostname
= client_hostname
;
526 /* Search again now we have a hostname.
527 Only accept configs without CLID and HWADDR here, (they won't match)
528 to avoid impersonation by name. */
529 struct dhcp_config
*new = find_config(daemon
->dhcp_conf
, context
, NULL
, 0,
530 mess
->chaddr
, mess
->hlen
,
531 mess
->htype
, hostname
);
532 if (!have_config(new, CONFIG_CLID
) && !have_config(new, CONFIG_HWADDR
))
538 if (have_config(config
, CONFIG_NETID
))
540 config
->netid
.next
= netid
;
541 netid
= &config
->netid
;
544 /* user-class options are, according to RFC3004, supposed to contain
545 a set of counted strings. Here we check that this is so (by seeing
546 if the counts are consistent with the overall option length) and if
547 so zero the counts so that we don't get spurious matches between
548 the vendor string and the counts. If the lengths don't add up, we
549 assume that the option is a single string and non RFC3004 compliant
550 and just do the substring match. dhclient provides these broken options.
551 The code, later, which sends user-class data to the lease-change script
552 relies on the transformation done here.
555 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
557 unsigned char *ucp
= option_ptr(opt
);
559 for (j
= 0; j
< option_len(opt
); j
+= ucp
[j
] + 1);
560 if (j
== option_len(opt
))
561 for (j
= 0; j
< option_len(opt
); j
= tmp
)
563 tmp
= j
+ ucp
[j
] + 1;
568 for (vendor
= daemon
->dhcp_vendors
; vendor
; vendor
= vendor
->next
)
572 if (vendor
->match_type
== MATCH_VENDOR
)
573 mopt
= OPTION_VENDOR_ID
;
574 else if (vendor
->match_type
== MATCH_USER
)
575 mopt
= OPTION_USER_CLASS
;
579 if ((opt
= option_find(mess
, sz
, mopt
, 1)))
582 for (i
= 0; i
<= (option_len(opt
) - vendor
->len
); i
++)
583 if (memcmp(vendor
->data
, option_ptr(opt
)+i
, vendor
->len
) == 0)
585 vendor
->netid
.next
= netid
;
586 netid
= &vendor
->netid
;
592 /* mark vendor-encapsulated options which match the client-supplied vendor class */
593 match_vendor_opts(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->dhcp_opts
);
595 if (daemon
->options
& OPT_LOG_OPTS
)
597 if (sanitise(option_find(mess
, sz
, OPTION_VENDOR_ID
, 1), daemon
->namebuff
))
598 my_syslog(LOG_INFO
, _("Vendor class: %s"), daemon
->namebuff
);
599 if (sanitise(option_find(mess
, sz
, OPTION_USER_CLASS
, 1), daemon
->namebuff
))
600 my_syslog(LOG_INFO
, _("User class: %s"), daemon
->namebuff
);
603 /* if all the netids in the ignore list are present, ignore this client */
604 for (id_list
= daemon
->dhcp_ignore
; id_list
; id_list
= id_list
->next
)
605 if (match_netid(id_list
->list
, netid
, 0))
608 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
609 if (have_config(config
, CONFIG_NOCLID
))
612 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_OPTIONS
, 0)))
614 req_options
= (unsigned char *)daemon
->dhcp_buff2
;
615 memcpy(req_options
, option_ptr(opt
), option_len(opt
));
616 req_options
[option_len(opt
)] = OPTION_END
;
622 if (!(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
623 (context
->local
.s_addr
!= option_addr(opt
).s_addr
))
626 /* sanitise any message. Paranoid? Moi? */
627 sanitise(option_find(mess
, sz
, OPTION_MESSAGE
, 1), daemon
->dhcp_buff
);
629 if (!(opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
632 log_packet("DECLINE", option_ptr(opt
), emac
, emac_len
, iface_name
, daemon
->dhcp_buff
);
634 if (lease
&& lease
->addr
.s_addr
== option_addr(opt
).s_addr
)
635 lease_prune(lease
, now
);
637 if (have_config(config
, CONFIG_ADDR
) &&
638 config
->addr
.s_addr
== option_addr(opt
).s_addr
)
640 prettyprint_time(daemon
->dhcp_buff
, DECLINE_BACKOFF
);
641 my_syslog(LOG_WARNING
, _("disabling DHCP static address %s for %s"),
642 inet_ntoa(config
->addr
), daemon
->dhcp_buff
);
643 config
->flags
|= CONFIG_DECLINED
;
644 config
->decline_time
= now
;
647 /* make sure this host gets a different address next time. */
648 for (; context
; context
= context
->current
)
649 context
->addr_epoch
++;
654 if (!(context
= narrow_context(context
, mess
->ciaddr
)) ||
655 !(opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)) ||
656 (context
->local
.s_addr
!= option_addr(opt
).s_addr
))
659 if (lease
&& lease
->addr
.s_addr
== mess
->ciaddr
.s_addr
)
660 lease_prune(lease
, now
);
662 message
= _("unknown lease");
664 log_packet("RELEASE", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
);
669 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
671 message
= _("ignored");
676 struct in_addr addr
, conf
;
678 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
679 addr
= option_addr(opt
);
682 if (have_config(config
, CONFIG_ADDR
))
684 char *addrs
= inet_ntoa(config
->addr
);
686 if ((ltmp
= lease_find_by_addr(config
->addr
)) && ltmp
!= lease
)
689 unsigned char *mac
= extended_hwaddr(ltmp
->hwaddr_type
, ltmp
->hwaddr_len
,
690 ltmp
->hwaddr
, ltmp
->clid_len
, ltmp
->clid
, &len
);
691 my_syslog(LOG_WARNING
, _("not using configured address %s because it is leased to %s"),
692 addrs
, print_mac(daemon
->namebuff
, mac
, len
));
696 struct dhcp_context
*tmp
;
697 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
698 if (context
->router
.s_addr
== config
->addr
.s_addr
)
701 my_syslog(LOG_WARNING
, _("not using configured address %s because it is in use by the server or relay"), addrs
);
702 else if (have_config(config
, CONFIG_DECLINED
) &&
703 difftime(now
, config
->decline_time
) < (float)DECLINE_BACKOFF
)
704 my_syslog(LOG_WARNING
, _("not using configured address %s because it was previously declined"), addrs
);
712 else if (lease
&& address_available(context
, lease
->addr
))
713 mess
->yiaddr
= lease
->addr
;
714 else if (opt
&& address_available(context
, addr
) && !lease_find_by_addr(addr
) &&
715 !config_find_by_address(daemon
->dhcp_conf
, addr
))
717 else if (emac_len
== 0)
718 message
= _("no unique-id");
719 else if (!address_allocate(context
, &mess
->yiaddr
, emac
, emac_len
, netid
, now
))
720 message
= _("no address available");
723 log_packet("DISCOVER", opt
? option_ptr(opt
) : NULL
, emac
, emac_len
, iface_name
, message
);
725 if (message
|| !(context
= narrow_context(context
, mess
->yiaddr
)))
728 log_packet("OFFER" , &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
);
730 if (context
->netid
.net
)
732 context
->netid
.next
= netid
;
733 netid
= &context
->netid
;
736 time
= calc_time(context
, config
, lease
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4), now
);
737 clear_packet(mess
, end
);
738 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPOFFER
);
739 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
740 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
741 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
742 if (time
!= 0xffffffff)
744 option_put(mess
, end
, OPTION_T1
, 4, (time
/2));
745 option_put(mess
, end
, OPTION_T2
, 4, (time
*7)/8);
747 do_options(context
, mess
, end
, req_options
, offer_hostname
,
748 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
750 return dhcp_packet_size(mess
, netid
);
753 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
755 if ((opt
= option_find(mess
, sz
, OPTION_REQUESTED_IP
, INADDRSZ
)))
757 /* SELECTING or INIT_REBOOT */
758 mess
->yiaddr
= option_addr(opt
);
760 /* send vendor and user class info for new or recreated lease */
763 if ((opt
= option_find(mess
, sz
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
)))
768 for (; context
; context
= context
->current
)
769 if (context
->local
.s_addr
== option_addr(opt
).s_addr
)
775 /* If a lease exists for this host and another address, squash it. */
776 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
778 lease_prune(lease
, now
);
785 if (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
))
788 if (lease
&& lease
->addr
.s_addr
!= mess
->yiaddr
.s_addr
)
789 message
= _("wrong address");
794 /* RENEWING or REBINDING */
795 /* Check existing lease for this address.
796 We allow it to be missing if dhcp-authoritative mode
797 as long as we can allocate the lease now - checked below.
798 This makes for a smooth recovery from a lost lease DB */
799 if ((lease
&& mess
->ciaddr
.s_addr
!= lease
->addr
.s_addr
) ||
800 (!lease
&& !(daemon
->options
& OPT_AUTHORITATIVE
)))
802 message
= _("lease not found");
803 /* ensure we broadcast NAK */
806 /* desynchronise renewals */
808 mess
->yiaddr
= mess
->ciaddr
;
811 log_packet("REQUEST", &mess
->yiaddr
, emac
, emac_len
, iface_name
, NULL
);
815 struct dhcp_config
*addr_config
;
816 struct dhcp_context
*tmp
= NULL
;
818 if (have_config(config
, CONFIG_ADDR
))
819 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
820 if (context
->router
.s_addr
== config
->addr
.s_addr
)
823 if (!(context
= narrow_context(context
, mess
->yiaddr
)))
825 /* If a machine moves networks whilst it has a lease, we catch that here. */
826 message
= _("wrong network");
827 /* ensure we broadcast NAK */
831 /* Check for renewal of a lease which is outside the allowed range. */
832 else if (!address_available(context
, mess
->yiaddr
) &&
833 (!have_config(config
, CONFIG_ADDR
) || config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
))
834 message
= _("address not available");
836 /* Check if a new static address has been configured. Be very sure that
837 when the client does DISCOVER, it will get the static address, otherwise
838 an endless protocol loop will ensue. */
839 else if (!tmp
&& !selecting
&&
840 have_config(config
, CONFIG_ADDR
) &&
841 (!have_config(config
, CONFIG_DECLINED
) ||
842 difftime(now
, config
->decline_time
) > (float)DECLINE_BACKOFF
) &&
843 config
->addr
.s_addr
!= mess
->yiaddr
.s_addr
&&
844 (!(ltmp
= lease_find_by_addr(config
->addr
)) || ltmp
== lease
))
845 message
= _("static lease available");
847 /* Check to see if the address is reserved as a static address for another host */
848 else if ((addr_config
= config_find_by_address(daemon
->dhcp_conf
, mess
->yiaddr
)) && addr_config
!= config
)
849 message
= _("address reserved");
851 else if ((ltmp
= lease_find_by_addr(mess
->yiaddr
)) && ltmp
!= lease
)
852 message
= _("address in use");
854 else if (emac_len
== 0)
855 message
= _("no unique-id");
859 if ((lease
= lease_allocate(mess
->yiaddr
)))
862 message
= _("no leases left");
868 log_packet("NAK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, message
);
870 mess
->yiaddr
.s_addr
= 0;
871 clear_packet(mess
, end
);
872 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPNAK
);
873 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
,
874 ntohl(context
? context
->local
.s_addr
: fallback
.s_addr
));
875 option_put_string(mess
, end
, OPTION_MESSAGE
, message
, borken_opt
);
876 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
877 a distant subnet which unicast a REQ to us won't work. */
878 if (!unicast_dest
|| mess
->giaddr
.s_addr
!= 0 ||
879 mess
->ciaddr
.s_addr
== 0 || is_same_net(context
->local
, mess
->ciaddr
, context
->netmask
))
881 mess
->flags
|= htons(0x8000); /* broadcast */
882 mess
->ciaddr
.s_addr
= 0;
890 /* copy user-class and vendor class into new lease, for the script */
891 if ((opt
= option_find(mess
, sz
, OPTION_USER_CLASS
, 1)))
893 int len
= option_len(opt
);
894 unsigned char *ucp
= option_ptr(opt
);
895 /* If the user-class option started as counted strings, the first byte will be zero. */
896 if (len
!= 0 && ucp
[0] == 0)
898 free(lease
->userclass
);
899 if ((lease
->userclass
= whine_malloc(len
+1)))
901 memcpy(lease
->userclass
, ucp
, len
);
902 lease
->userclass
[len
] = 0;
903 lease
->userclass_len
= len
+1;
906 if ((opt
= option_find(mess
, sz
, OPTION_VENDOR_ID
, 1)))
908 int len
= option_len(opt
);
909 unsigned char *ucp
= option_ptr(opt
);
910 free(lease
->vendorclass
);
911 if ((lease
->vendorclass
= whine_malloc(len
+1)))
913 memcpy(lease
->vendorclass
, ucp
, len
);
914 lease
->vendorclass
[len
] = 0;
915 lease
->vendorclass_len
= len
+1;
920 if (!hostname_auth
&& (client_hostname
= host_from_dns(mess
->yiaddr
)))
922 hostname
= client_hostname
;
926 if (context
->netid
.net
)
928 context
->netid
.next
= netid
;
929 netid
= &context
->netid
;
932 time
= calc_time(context
, config
, NULL
, option_find(mess
, sz
, OPTION_LEASE_TIME
, 4), now
);
933 lease_set_hwaddr(lease
, mess
->chaddr
, clid
, mess
->hlen
, mess
->htype
, clid_len
);
935 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
938 for (id_list
= daemon
->dhcp_ignore_names
; id_list
; id_list
= id_list
->next
)
939 if ((!id_list
->list
) || match_netid(id_list
->list
, netid
, 0))
945 lease_set_hostname(lease
, hostname
, daemon
->domain_suffix
, hostname_auth
);
947 lease_set_expires(lease
, time
, now
);
949 log_packet("ACK", &mess
->yiaddr
, emac
, emac_len
, iface_name
, hostname
);
951 clear_packet(mess
, end
);
952 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
953 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
954 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
955 if (time
!= 0xffffffff)
957 while (fuzz
> (time
/16))
959 option_put(mess
, end
, OPTION_T1
, 4, (time
/2) - fuzz
);
960 option_put(mess
, end
, OPTION_T2
, 4, ((time
/8)*7) - fuzz
);
962 do_options(context
, mess
, end
, req_options
, hostname
,
963 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
966 return dhcp_packet_size(mess
, netid
);
969 if (ignore
|| have_config(config
, CONFIG_DISABLE
))
970 message
= _("ignored");
972 log_packet("INFORM", &mess
->ciaddr
, emac
, emac_len
, iface_name
, message
);
974 if (message
|| mess
->ciaddr
.s_addr
== 0 ||
975 !(context
= narrow_context(context
, mess
->ciaddr
)))
978 /* Find a least based on IP address if we didn't
979 get one from MAC address/client-d */
981 (lease
= lease_find_by_addr(mess
->ciaddr
)) &&
983 hostname
= lease
->hostname
;
986 hostname
= host_from_dns(mess
->ciaddr
);
988 log_packet("ACK", &mess
->ciaddr
, emac
, emac_len
, iface_name
, hostname
);
990 if (context
->netid
.net
)
992 context
->netid
.next
= netid
;
993 netid
= &context
->netid
;
996 clear_packet(mess
, end
);
997 option_put(mess
, end
, OPTION_MESSAGE_TYPE
, 1, DHCPACK
);
998 option_put(mess
, end
, OPTION_SERVER_IDENTIFIER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
1002 if (lease
->expires
== 0)
1005 time
= (unsigned int)difftime(lease
->expires
, now
);
1006 option_put(mess
, end
, OPTION_LEASE_TIME
, 4, time
);
1008 do_options(context
, mess
, end
, req_options
, hostname
,
1009 netid
, subnet_addr
, fqdn_flags
, borken_opt
, agent_id
);
1011 *is_inform
= 1; /* handle reply differently */
1012 return dhcp_packet_size(mess
, netid
);
1018 /* find a good value to use as MAC address for logging and address-allocation hashing.
1019 This is normally just the chaddr field from the DHCP packet,
1020 but eg Firewire will have hlen == 0 and use the client-id instead.
1021 This could be anything, but will normally be EUI64 for Firewire.
1022 We assume that if the first byte of the client-id equals the htype byte
1023 then the client-id is using the usual encoding and use the rest of the
1024 client-id: if not we can use the whole client-id. This should give
1025 sane MAC address logs. */
1026 static unsigned char *extended_hwaddr(int hwtype
, int hwlen
, unsigned char *hwaddr
,
1027 int clid_len
, unsigned char *clid
, int *len_out
)
1029 if (hwlen
== 0 && clid
&& clid_len
> 3)
1031 if (clid
[0] == hwtype
)
1033 *len_out
= clid_len
- 1 ;
1037 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1038 if (clid
[0] == ARPHRD_EUI64
&& hwtype
== ARPHRD_IEEE1394
)
1040 *len_out
= clid_len
- 1 ;
1045 *len_out
= clid_len
;
1053 static unsigned int calc_time(struct dhcp_context
*context
, struct dhcp_config
*config
,
1054 struct dhcp_lease
*lease
, unsigned char *opt
, time_t now
)
1056 unsigned int time
= have_config(config
, CONFIG_TIME
) ? config
->lease_time
: context
->lease_time
;
1060 unsigned int req_time
= option_uint(opt
, 4);
1061 if (req_time
< 120 )
1062 req_time
= 120; /* sanity */
1063 if (time
== 0xffffffff || (req_time
!= 0xffffffff && req_time
< time
))
1066 else if (lease
&& lease
->expires
!= 0 && difftime(lease
->expires
, now
) > 0.0)
1068 unsigned int lease_time
= (unsigned int)difftime(lease
->expires
, now
);
1070 /* put a floor on lease-remaining time. */
1071 if (lease_time
< 360 )
1074 if (time
> lease_time
)
1081 static int sanitise(unsigned char *opt
, char *buf
)
1091 p
= option_ptr(opt
);
1093 for (i
= option_len(opt
); i
> 0; i
--)
1099 *buf
= 0; /* add terminator */
1104 static void log_packet(char *type
, void *addr
, unsigned char *ext_mac
,
1105 int mac_len
, char *interface
, char *string
)
1109 /* addr may be misaligned */
1111 memcpy(&a
, addr
, sizeof(a
));
1113 my_syslog(LOG_INFO
, "%s%s(%s) %s%s%s %s",
1114 type
? "DHCP" : "BOOTP",
1117 addr
? inet_ntoa(a
) : "",
1119 print_mac(daemon
->namebuff
, ext_mac
, mac_len
),
1120 string
? string
: "");
1123 static void log_options(unsigned char *start
)
1125 while (*start
!= OPTION_END
)
1127 char *text
= option_string(start
[0]);
1128 unsigned char trunc
= start
[1] < 13 ? start
[1] : 13;
1129 my_syslog(LOG_INFO
, "sent size:%3d option:%3d%s%s%s%s%s",
1131 text
? ":" : "", text
? text
: "",
1132 start
[1] == 0 ? "" : " ",
1133 start
[1] == 0 ? "" : print_mac(daemon
->namebuff
, &start
[2], trunc
),
1134 trunc
== start
[1] ? "" : "...");
1135 start
+= start
[1] + 2;
1139 static unsigned char *option_find1(unsigned char *p
, unsigned char *end
, int opt
, int minsize
)
1141 while (*p
!= OPTION_END
)
1144 return NULL
; /* malformed packet */
1145 else if (*p
== OPTION_PAD
)
1151 return NULL
; /* malformed packet */
1152 opt_len
= option_len(p
);
1153 if (p
>= end
- (2 + opt_len
))
1154 return NULL
; /* malformed packet */
1155 if (*p
== opt
&& opt_len
>= minsize
)
1161 return opt
== OPTION_END
? p
: NULL
;
1164 static unsigned char *option_find(struct dhcp_packet
*mess
, size_t size
, int opt_type
, int minsize
)
1166 unsigned char *ret
, *overload
;
1168 /* skip over DHCP cookie; */
1169 if ((ret
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, opt_type
, minsize
)))
1172 /* look for overload option. */
1173 if (!(overload
= option_find1(&mess
->options
[0] + sizeof(u32
), ((unsigned char *)mess
) + size
, OPTION_OVERLOAD
, 1)))
1176 /* Can we look in filename area ? */
1177 if ((overload
[2] & 1) &&
1178 (ret
= option_find1(&mess
->file
[0], &mess
->file
[128], opt_type
, minsize
)))
1181 /* finally try sname area */
1182 if ((overload
[2] & 2) &&
1183 (ret
= option_find1(&mess
->sname
[0], &mess
->sname
[64], opt_type
, minsize
)))
1189 static struct in_addr
option_addr(unsigned char *opt
)
1191 /* this worries about unaligned data in the option. */
1192 /* struct in_addr is network byte order */
1195 memcpy(&ret
, option_ptr(opt
), INADDRSZ
);
1200 static unsigned int option_uint(unsigned char *opt
, int size
)
1202 /* this worries about unaligned data and byte order */
1203 unsigned int ret
= 0;
1205 unsigned char *p
= option_ptr(opt
);
1207 for (i
= 0; i
< size
; i
++)
1208 ret
= (ret
<< 8) | *p
++;
1213 static unsigned char *dhcp_skip_opts(unsigned char *start
)
1216 start
+= start
[1] + 2;
1220 /* only for use when building packet: doesn't check for bad data. */
1221 static unsigned char *find_overload(struct dhcp_packet
*mess
)
1223 unsigned char *p
= &mess
->options
[0] + sizeof(u32
);
1227 if (*p
== OPTION_OVERLOAD
)
1234 static size_t dhcp_packet_size(struct dhcp_packet
*mess
, struct dhcp_netid
*netid
)
1236 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1237 unsigned char *overload
;
1240 /* We do logging too */
1241 if (netid
&& (daemon
->options
& OPT_LOG_OPTS
))
1243 char *p
= daemon
->namebuff
;
1245 for (; netid
; netid
= netid
->next
)
1247 strncat (p
, netid
->net
, MAXDNAME
);
1249 strncat (p
, ", ", MAXDNAME
);
1251 p
[MAXDNAME
- 1] = 0;
1252 my_syslog(LOG_INFO
, _("tags: %s"), p
);
1255 /* add END options to the regions. */
1256 if ((overload
= find_overload(mess
)))
1258 if (option_uint(overload
, 1) & 1)
1260 *dhcp_skip_opts(mess
->file
) = OPTION_END
;
1261 if (daemon
->options
& OPT_LOG_OPTS
)
1262 log_options(mess
->file
);
1264 if (option_uint(overload
, 1) & 2)
1266 *dhcp_skip_opts(mess
->sname
) = OPTION_END
;
1267 if (daemon
->options
& OPT_LOG_OPTS
)
1268 log_options(mess
->sname
);
1273 if (daemon
->options
& OPT_LOG_OPTS
)
1274 log_options(&mess
->options
[0] + sizeof(u32
));
1276 ret
= (size_t)(p
- (unsigned char *)mess
);
1278 if (ret
< MIN_PACKETSZ
)
1284 static unsigned char *free_space(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
)
1286 unsigned char *p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1288 if (p
+ len
+ 3 >= end
)
1289 /* not enough space in options area, try and use overload, if poss */
1291 unsigned char *overload
;
1293 if (!(overload
= find_overload(mess
)) &&
1294 (mess
->file
[0] == 0 || mess
->sname
[0] == 0))
1296 /* attempt to overload fname and sname areas, we've reserved space for the
1297 overflow option previuously. */
1299 *(p
++) = OPTION_OVERLOAD
;
1305 /* using filename field ? */
1308 if (mess
->file
[0] == 0)
1311 if (overload
[2] & 1)
1313 p
= dhcp_skip_opts(mess
->file
);
1314 if (p
+ len
+ 3 >= mess
->file
+ sizeof(mess
->file
))
1320 /* try to bring sname into play (it may be already) */
1321 if (mess
->sname
[0] == 0)
1324 if (overload
[2] & 2)
1326 p
= dhcp_skip_opts(mess
->sname
);
1327 if (p
+ len
+ 3 >= mess
->sname
+ sizeof(mess
->file
))
1334 my_syslog(LOG_WARNING
, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt
);
1346 static void option_put(struct dhcp_packet
*mess
, unsigned char *end
, int opt
, int len
, unsigned int val
)
1349 unsigned char *p
= free_space(mess
, end
, opt
, len
);
1352 for (i
= 0; i
< len
; i
++)
1353 *(p
++) = val
>> (8 * (len
- (i
+ 1)));
1356 static void option_put_string(struct dhcp_packet
*mess
, unsigned char *end
, int opt
,
1357 char *string
, int null_term
)
1360 size_t len
= strlen(string
);
1362 if (null_term
&& len
!= 255)
1365 if ((p
= free_space(mess
, end
, opt
, len
)))
1366 memcpy(p
, string
, len
);
1369 /* return length, note this only does the data part */
1370 static int do_opt(struct dhcp_opt
*opt
, unsigned char *p
, struct in_addr local
, int null_term
)
1374 if ((opt
->flags
& DHOPT_STRING
) && null_term
&& len
!= 255)
1379 if ((opt
->flags
& DHOPT_ADDR
) && !(opt
->flags
& DHOPT_ENCAPSULATE
))
1382 struct in_addr
*a
= (struct in_addr
*)opt
->val
;
1383 for (j
= 0; j
< opt
->len
; j
+=INADDRSZ
, a
++)
1385 /* zero means "self" (but not in vendorclass options.) */
1387 memcpy(p
, &local
, INADDRSZ
);
1389 memcpy(p
, a
, INADDRSZ
);
1394 memcpy(p
, opt
->val
, len
);
1399 static int in_list(unsigned char *list
, int opt
)
1403 /* If no requested options, send everything, not nothing. */
1407 for (i
= 0; list
[i
] != OPTION_END
; i
++)
1414 static struct dhcp_opt
*option_find2(struct dhcp_netid
*netid
, struct dhcp_opt
*opts
, int opt
)
1416 struct dhcp_opt
*tmp
;
1417 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
1418 if (tmp
->opt
== opt
&& !(tmp
->flags
& DHOPT_ENCAPSULATE
))
1419 if (match_netid(tmp
->netid
, netid
, 1) || match_netid(tmp
->netid
, netid
, 0))
1422 return netid
? option_find2(NULL
, opts
, opt
) : NULL
;
1425 /* mark vendor-encapsulated options which match the client-supplied or
1426 config-supplied vendor class */
1427 static void match_vendor_opts(unsigned char *opt
, struct dhcp_opt
*dopt
)
1429 for (; dopt
; dopt
= dopt
->next
)
1431 dopt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1432 if (opt
&& (dopt
->flags
& DHOPT_ENCAPSULATE
))
1435 if (dopt
->vendor_class
)
1436 len
= strlen((char *)dopt
->vendor_class
);
1437 for (i
= 0; i
<= (option_len(opt
) - len
); i
++)
1438 if (len
== 0 || memcmp(dopt
->vendor_class
, option_ptr(opt
)+i
, len
) == 0)
1440 dopt
->flags
|= DHOPT_VENDOR_MATCH
;
1447 static void clear_packet(struct dhcp_packet
*mess
, unsigned char *end
)
1449 memset(mess
->sname
, 0, sizeof(mess
->sname
));
1450 memset(mess
->file
, 0, sizeof(mess
->file
));
1451 memset(&mess
->options
[0] + sizeof(u32
), 0, end
- (&mess
->options
[0] + sizeof(u32
)));
1452 mess
->siaddr
.s_addr
= 0;
1455 static void do_options(struct dhcp_context
*context
,
1456 struct dhcp_packet
*mess
,
1457 unsigned char *real_end
,
1458 unsigned char *req_options
,
1460 struct dhcp_netid
*netid
,
1461 struct in_addr subnet_addr
,
1462 unsigned char fqdn_flags
,
1464 unsigned char *agent_id
)
1466 struct dhcp_opt
*opt
, *config_opts
= daemon
->dhcp_opts
;
1467 struct dhcp_boot
*boot
;
1468 unsigned char *p
, *end
= agent_id
? agent_id
: real_end
;
1469 int i
, len
, force_encap
= 0;
1470 unsigned char f0
= 0, s0
= 0;
1473 if ((daemon
->options
& OPT_LOG_OPTS
) && req_options
)
1475 char *q
= daemon
->namebuff
;
1476 for (i
= 0; req_options
[i
] != OPTION_END
; i
++)
1478 char *s
= option_string(req_options
[i
]);
1479 q
+=snprintf(q
, MAXDNAME
- (q
- daemon
->namebuff
),
1484 req_options
[i
+1] == OPTION_END
? "" : ", ");
1485 if (req_options
[i
+1] == OPTION_END
|| (q
- daemon
->namebuff
) > 40)
1487 q
= daemon
->namebuff
;
1488 my_syslog(LOG_INFO
, _("requested options: %s"), daemon
->namebuff
);
1493 /* decide which dhcp-boot option we're using */
1494 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1495 if (match_netid(boot
->netid
, netid
, 0))
1498 /* No match, look for one without a netid */
1499 for (boot
= daemon
->boot_config
; boot
; boot
= boot
->next
)
1500 if (match_netid(boot
->netid
, netid
, 1))
1503 mess
->siaddr
= context
->local
;
1505 /* See if we can send the boot stuff as options.
1506 To do this we need a requested option list, BOOTP
1507 and very old DHCP clients won't have this.
1508 Some PXE ROMs have bugs (surprise!) and need zero-terminated
1509 names, so we always send those. */
1514 if (req_options
&& in_list(req_options
, OPTION_SNAME
))
1515 option_put_string(mess
, end
, OPTION_SNAME
, boot
->sname
, 1);
1518 if (daemon
->options
& OPT_LOG_OPTS
)
1519 my_syslog(LOG_INFO
, _("server name: %s"), boot
->sname
);
1520 strncpy((char *)mess
->sname
, boot
->sname
, sizeof(mess
->sname
)-1);
1526 if (req_options
&& in_list(req_options
, OPTION_FILENAME
))
1527 option_put_string(mess
, end
, OPTION_FILENAME
, boot
->file
, 1);
1530 if (daemon
->options
& OPT_LOG_OPTS
)
1531 my_syslog(LOG_INFO
, _("bootfile name: %s"), boot
->file
);
1532 strncpy((char *)mess
->file
, boot
->file
, sizeof(mess
->file
)-1);
1536 if (boot
->next_server
.s_addr
)
1537 mess
->siaddr
= boot
->next_server
;
1539 if (daemon
->options
& OPT_LOG_OPTS
)
1540 my_syslog(LOG_INFO
, _("next server: %s"), inet_ntoa(mess
->siaddr
));
1543 /* We don't want to do option-overload for BOOTP, so make the file and sname
1544 fields look like they are in use, even when they aren't. This gets restored
1545 at the end of this function. */
1551 s0
= mess
->sname
[0];
1555 /* At this point, if mess->sname or mess->file are zeroed, they are available
1556 for option overload, reserve space for the overload option. */
1557 if (mess
->file
[0] == 0 || mess
->sname
[0] == 0)
1560 /* rfc3011 says this doesn't need to be in the requested options list. */
1561 if (subnet_addr
.s_addr
)
1562 option_put(mess
, end
, OPTION_SUBNET_SELECT
, INADDRSZ
, ntohl(subnet_addr
.s_addr
));
1564 if (!option_find2(netid
, config_opts
, OPTION_NETMASK
))
1565 option_put(mess
, end
, OPTION_NETMASK
, INADDRSZ
, ntohl(context
->netmask
.s_addr
));
1567 /* May not have a "guessed" broadcast address if we got no packets via a relay
1568 from this net yet (ie just unicast renewals after a restart */
1569 if (context
->broadcast
.s_addr
&&
1570 !option_find2(netid
, config_opts
, OPTION_BROADCAST
))
1571 option_put(mess
, end
, OPTION_BROADCAST
, INADDRSZ
, ntohl(context
->broadcast
.s_addr
));
1573 /* Same comments as broadcast apply, and also may not be able to get a sensible
1574 default when using subnet select. User must configure by steam in that case. */
1575 if (context
->router
.s_addr
&&
1576 in_list(req_options
, OPTION_ROUTER
) &&
1577 !option_find2(netid
, config_opts
, OPTION_ROUTER
))
1578 option_put(mess
, end
, OPTION_ROUTER
, INADDRSZ
, ntohl(context
->router
.s_addr
));
1580 if (in_list(req_options
, OPTION_DNSSERVER
) &&
1581 !option_find2(netid
, config_opts
, OPTION_DNSSERVER
))
1582 option_put(mess
, end
, OPTION_DNSSERVER
, INADDRSZ
, ntohl(context
->local
.s_addr
));
1584 if (daemon
->domain_suffix
&& in_list(req_options
, OPTION_DOMAINNAME
) &&
1585 !option_find2(netid
, config_opts
, OPTION_DOMAINNAME
))
1586 option_put_string(mess
, end
, OPTION_DOMAINNAME
, daemon
->domain_suffix
, null_term
);
1588 /* Note that we ignore attempts to set the hostname using
1589 --dhcp-option=12,<name> and the fqdn using
1590 --dhc-option=81,<name> */
1593 if (in_list(req_options
, OPTION_HOSTNAME
))
1594 option_put_string(mess
, end
, OPTION_HOSTNAME
, hostname
, null_term
);
1596 if (fqdn_flags
!= 0)
1598 int len
= strlen(hostname
) + 3;
1599 if (fqdn_flags
& 0x04)
1604 if (daemon
->domain_suffix
)
1605 len
+= strlen(daemon
->domain_suffix
) + 1;
1607 if ((p
= free_space(mess
, end
, OPTION_CLIENT_FQDN
, len
)))
1609 *(p
++) = fqdn_flags
;
1613 if (fqdn_flags
& 0x04)
1615 p
= do_rfc1035_name(p
, hostname
);
1616 if (daemon
->domain_suffix
)
1617 p
= do_rfc1035_name(p
, daemon
->domain_suffix
);
1622 memcpy(p
, hostname
, strlen(hostname
));
1623 p
+= strlen(hostname
);
1624 if (daemon
->domain_suffix
)
1627 memcpy(p
, daemon
->domain_suffix
, strlen(daemon
->domain_suffix
));
1628 p
+= strlen(daemon
->domain_suffix
);
1637 for (opt
= config_opts
; opt
; opt
= opt
->next
)
1639 /* was it asked for, or are we sending it anyway? */
1640 if (!(opt
->flags
& DHOPT_FORCE
) && !in_list(req_options
, opt
->opt
))
1643 /* prohibit some used-internally options */
1644 if (opt
->opt
== OPTION_HOSTNAME
||
1645 opt
->opt
== OPTION_CLIENT_FQDN
||
1646 opt
->opt
== OPTION_MAXMESSAGE
||
1647 opt
->opt
== OPTION_OVERLOAD
||
1648 opt
->opt
== OPTION_PAD
||
1649 opt
->opt
== OPTION_END
)
1652 /* netids match and not encapsulated? */
1653 if (opt
!= option_find2(netid
, config_opts
, opt
->opt
))
1656 /* For the options we have default values on
1657 dhc-option=<optionno> means "don't include this option"
1658 not "include a zero-length option" */
1659 if (opt
->len
== 0 &&
1660 (opt
->opt
== OPTION_NETMASK
||
1661 opt
->opt
== OPTION_BROADCAST
||
1662 opt
->opt
== OPTION_ROUTER
||
1663 opt
->opt
== OPTION_DNSSERVER
))
1666 len
= do_opt(opt
, NULL
, context
->local
, null_term
);
1667 if ((p
= free_space(mess
, end
, opt
->opt
, len
)))
1669 do_opt(opt
, p
, context
->local
, null_term
);
1671 /* If we send a vendor-id, revisit which vendor-ops we consider
1672 it appropriate to send. */
1673 if (opt
->opt
== OPTION_VENDOR_ID
)
1674 match_vendor_opts(p
- 2, config_opts
);
1678 /* prune encapsulated options based on netid, and look if we're forcing them to be sent */
1679 for (opt
= config_opts
; opt
; opt
= opt
->next
)
1680 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1682 if (!match_netid(opt
->netid
, netid
, 1) && !match_netid(opt
->netid
, netid
, 0))
1683 opt
->flags
&= ~DHOPT_VENDOR_MATCH
;
1684 else if (opt
->flags
& DHOPT_FORCE
)
1688 if (force_encap
|| in_list(req_options
, OPTION_VENDOR_CLASS_OPT
))
1691 struct dhcp_opt
*start
;
1693 /* find size in advance */
1694 for (start
= opt
= config_opts
; opt
; opt
= opt
->next
)
1695 if (opt
->flags
& DHOPT_VENDOR_MATCH
)
1697 int new = do_opt(opt
, NULL
, context
->local
, null_term
) + 2;
1698 if (enc_len
+ new <= 255)
1702 p
= free_space(mess
, end
, OPTION_VENDOR_CLASS_OPT
, enc_len
);
1703 for (; start
&& start
!= opt
; start
= start
->next
)
1704 if (p
&& (start
->flags
& DHOPT_VENDOR_MATCH
))
1706 len
= do_opt(start
, p
+ 2, context
->local
, null_term
);
1707 *(p
++) = start
->opt
;
1717 (p
= free_space(mess
, end
, OPTION_VENDOR_CLASS_OPT
, enc_len
+ 1)))
1719 for (; start
; start
= start
->next
)
1720 if (start
->flags
& DHOPT_VENDOR_MATCH
)
1722 len
= do_opt(start
, p
+ 2, context
->local
, null_term
);
1723 *(p
++) = start
->opt
;
1731 /* move agent_id back down to the end of the packet */
1734 p
= dhcp_skip_opts(&mess
->options
[0] + sizeof(u32
));
1735 memmove(p
, agent_id
, real_end
- agent_id
);
1736 p
+= real_end
- agent_id
;
1737 memset(p
, 0, real_end
- p
); /* in case of overlap */
1740 /* restore BOOTP anti-overload hack */
1744 mess
->sname
[0] = s0
;