dnsmasq: update to 2.73 (23.06.2015)
[tomato.git] / release / src / router / dnsmasq / src / rfc2131.c
blobf78cebd4630ecf649a9a227bb2096887a726fc9d
1 /* dnsmasq is Copyright (c) 2000-2015 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/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_DHCP
21 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
22 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
24 #ifdef HAVE_SCRIPT
25 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
26 #endif
28 static int sanitise(unsigned char *opt, char *buf);
29 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
30 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
31 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
32 static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
33 int opt, char *string, int null_term);
34 static struct in_addr option_addr(unsigned char *opt);
35 static unsigned int option_uint(unsigned char *opt, int i, int size);
36 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
37 int mac_len, char *interface, char *string, char *err, u32 xid);
38 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
39 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
40 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
41 static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
42 static int in_list(unsigned char *list, int opt);
43 static void do_options(struct dhcp_context *context,
44 struct dhcp_packet *mess,
45 unsigned char *real_end,
46 unsigned char *req_options,
47 char *hostname,
48 char *config_domain,
49 struct dhcp_netid *netid,
50 struct in_addr subnet_addr,
51 unsigned char fqdn_flags,
52 int null_term, int pxearch,
53 unsigned char *uuid,
54 int vendor_class_len,
55 time_t now,
56 unsigned int lease_time,
57 unsigned short fuzz);
60 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
61 static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
62 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
63 static int prune_vendor_opts(struct dhcp_netid *netid);
64 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
65 struct dhcp_boot *find_boot(struct dhcp_netid *netid);
68 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
69 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe, struct in_addr fallback)
71 unsigned char *opt, *clid = NULL;
72 struct dhcp_lease *ltmp, *lease = NULL;
73 struct dhcp_vendor *vendor;
74 struct dhcp_mac *mac;
75 struct dhcp_netid_list *id_list;
76 int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
77 struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
78 unsigned char *end = (unsigned char *)(mess + 1);
79 unsigned char *real_end = (unsigned char *)(mess + 1);
80 char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
81 int hostname_auth = 0, borken_opt = 0;
82 unsigned char *req_options = NULL;
83 char *message = NULL;
84 unsigned int time;
85 struct dhcp_config *config;
86 struct dhcp_netid *netid, *tagif_netid;
87 struct in_addr subnet_addr, override;
88 unsigned short fuzz = 0;
89 unsigned int mess_type = 0;
90 unsigned char fqdn_flags = 0;
91 unsigned char *agent_id = NULL, *uuid = NULL;
92 unsigned char *emac = NULL;
93 int vendor_class_len = 0, emac_len = 0;
94 struct dhcp_netid known_id, iface_id, cpewan_id;
95 struct dhcp_opt *o;
96 unsigned char pxe_uuid[17];
97 unsigned char *oui = NULL, *serial = NULL;
98 #ifdef HAVE_SCRIPT
99 unsigned char *class = NULL;
100 #endif
102 subnet_addr.s_addr = override.s_addr = 0;
104 /* set tag with name == interface */
105 iface_id.net = iface_name;
106 iface_id.next = NULL;
107 netid = &iface_id;
109 if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
110 return 0;
112 if (mess->htype == 0 && mess->hlen != 0)
113 return 0;
115 /* check for DHCP rather than BOOTP */
116 if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
118 u32 cookie = htonl(DHCP_COOKIE);
120 /* only insist on a cookie for DHCP. */
121 if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
122 return 0;
124 mess_type = option_uint(opt, 0, 1);
126 /* two things to note here: expand_buf may move the packet,
127 so reassign mess from daemon->packet. Also, the size
128 sent includes the IP and UDP headers, hence the magic "-28" */
129 if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
131 size_t size = (size_t)option_uint(opt, 0, 2) - 28;
133 if (size > DHCP_PACKET_MAX)
134 size = DHCP_PACKET_MAX;
135 else if (size < sizeof(struct dhcp_packet))
136 size = sizeof(struct dhcp_packet);
138 if (expand_buf(&daemon->dhcp_packet, size))
140 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
141 real_end = end = ((unsigned char *)mess) + size;
145 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
146 it can affect the context-determination code. */
147 if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
148 mess->ciaddr.s_addr = 0;
150 /* search for device identity from CPEWAN devices, we pass this through to the script */
151 if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
153 unsigned int elen, offset, len = option_len(opt);
155 for (offset = 0; offset < (len - 5); offset += elen + 5)
157 elen = option_uint(opt, offset + 4 , 1);
158 if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
160 unsigned char *x = option_ptr(opt, offset + 5);
161 unsigned char *y = option_ptr(opt, offset + elen + 5);
162 oui = option_find1(x, y, 1, 1);
163 serial = option_find1(x, y, 2, 1);
164 #ifdef HAVE_SCRIPT
165 class = option_find1(x, y, 3, 1);
166 #endif
167 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
168 the gateway id back. Note that the device class is optional */
169 if (oui && serial)
171 cpewan_id.net = "cpewan-id";
172 cpewan_id.next = netid;
173 netid = &cpewan_id;
175 break;
180 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
182 /* Any agent-id needs to be copied back out, verbatim, as the last option
183 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
184 get overwritten, then it will be shuffled back at the end of processing.
185 Note that the incoming options must not be overwritten here, so there has to
186 be enough free space at the end of the packet to copy the option. */
187 unsigned char *sopt;
188 unsigned int total = option_len(opt) + 2;
189 unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
190 if (last_opt && last_opt < end - total)
192 end -= total;
193 agent_id = end;
194 memcpy(agent_id, opt, total);
197 /* look for RFC3527 Link selection sub-option */
198 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
199 subnet_addr = option_addr(sopt);
201 /* look for RFC5107 server-identifier-override */
202 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
203 override = option_addr(sopt);
205 /* if a circuit-id or remote-is option is provided, exact-match to options. */
206 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
208 int search;
210 if (vendor->match_type == MATCH_CIRCUIT)
211 search = SUBOPT_CIRCUIT_ID;
212 else if (vendor->match_type == MATCH_REMOTE)
213 search = SUBOPT_REMOTE_ID;
214 else if (vendor->match_type == MATCH_SUBSCRIBER)
215 search = SUBOPT_SUBSCR_ID;
216 else
217 continue;
219 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
220 vendor->len == option_len(sopt) &&
221 memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
223 vendor->netid.next = netid;
224 netid = &vendor->netid;
229 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
230 if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
231 subnet_addr = option_addr(opt);
233 /* If there is no client identifier option, use the hardware address */
234 if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
236 clid_len = option_len(opt);
237 clid = option_ptr(opt, 0);
240 /* do we have a lease in store? */
241 lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
243 /* If this request is missing a clid, but we've seen one before,
244 use it again for option matching etc. */
245 if (lease && !clid && lease->clid)
247 clid_len = lease->clid_len;
248 clid = lease->clid;
251 /* find mac to use for logging and hashing */
252 emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
255 for (mac = daemon->dhcp_macs; mac; mac = mac->next)
256 if (mac->hwaddr_len == mess->hlen &&
257 (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
258 memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
260 mac->netid.next = netid;
261 netid = &mac->netid;
264 /* Determine network for this packet. Our caller will have already linked all the
265 contexts which match the addresses of the receiving interface but if the
266 machine has an address already, or came via a relay, or we have a subnet selector,
267 we search again. If we don't have have a giaddr or explicit subnet selector,
268 use the ciaddr. This is necessary because a machine which got a lease via a
269 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
270 from the physical network, continue using that to allow correct DHCPNAK generation later. */
271 if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
273 struct dhcp_context *context_tmp, *context_new = NULL;
274 struct in_addr addr;
275 int force = 0;
277 if (subnet_addr.s_addr)
279 addr = subnet_addr;
280 force = 1;
282 else if (mess->giaddr.s_addr)
284 addr = mess->giaddr;
285 force = 1;
287 else
289 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
290 addr = mess->ciaddr;
291 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
292 if (context_tmp->netmask.s_addr &&
293 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
294 is_same_net(addr, context_tmp->end, context_tmp->netmask))
296 context_new = context;
297 break;
301 if (!context_new)
302 for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
304 struct in_addr netmask = context_tmp->netmask;
306 /* guess the netmask for relayed networks */
307 if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
309 if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
310 netmask.s_addr = htonl(0xff000000);
311 else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
312 netmask.s_addr = htonl(0xffff0000);
313 else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
314 netmask.s_addr = htonl(0xffffff00);
317 /* This section fills in context mainly when a client which is on a remote (relayed)
318 network renews a lease without using the relay, after dnsmasq has restarted. */
319 if (netmask.s_addr != 0 &&
320 is_same_net(addr, context_tmp->start, netmask) &&
321 is_same_net(addr, context_tmp->end, netmask))
323 context_tmp->netmask = netmask;
324 if (context_tmp->local.s_addr == 0)
325 context_tmp->local = fallback;
326 if (context_tmp->router.s_addr == 0)
327 context_tmp->router = mess->giaddr;
329 /* fill in missing broadcast addresses for relayed ranges */
330 if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
331 context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
333 context_tmp->current = context_new;
334 context_new = context_tmp;
338 if (context_new || force)
339 context = context_new;
342 if (!context)
344 my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
345 subnet_addr.s_addr ? _("with subnet selector") : _("via"),
346 subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
347 return 0;
350 if (option_bool(OPT_LOG_OPTS))
352 struct dhcp_context *context_tmp;
353 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
355 strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
356 if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
357 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
358 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
359 else
360 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
361 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
365 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
366 Otherwise assume the option is an array, and look for a matching element.
367 If no data given, existance of the option is enough. This code handles
368 rfc3925 V-I classes too. */
369 for (o = daemon->dhcp_match; o; o = o->next)
371 unsigned int len, elen, match = 0;
372 size_t offset, o2;
374 if (o->flags & DHOPT_RFC3925)
376 if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
377 continue;
379 for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
381 len = option_uint(opt, offset + 4 , 1);
382 /* Need to take care that bad data can't run us off the end of the packet */
383 if ((offset + len + 5 <= (option_len(opt))) &&
384 (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
385 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
387 elen = option_uint(opt, o2, 1);
388 if ((o2 + elen + 1 <= option_len(opt)) &&
389 (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
390 break;
392 if (match)
393 break;
396 else
398 if (!(opt = option_find(mess, sz, o->opt, 1)))
399 continue;
401 match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
404 if (match)
406 o->netid->next = netid;
407 netid = o->netid;
411 /* user-class options are, according to RFC3004, supposed to contain
412 a set of counted strings. Here we check that this is so (by seeing
413 if the counts are consistent with the overall option length) and if
414 so zero the counts so that we don't get spurious matches between
415 the vendor string and the counts. If the lengths don't add up, we
416 assume that the option is a single string and non RFC3004 compliant
417 and just do the substring match. dhclient provides these broken options.
418 The code, later, which sends user-class data to the lease-change script
419 relies on the transformation done here.
422 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
424 unsigned char *ucp = option_ptr(opt, 0);
425 int tmp, j;
426 for (j = 0; j < option_len(opt); j += ucp[j] + 1);
427 if (j == option_len(opt))
428 for (j = 0; j < option_len(opt); j = tmp)
430 tmp = j + ucp[j] + 1;
431 ucp[j] = 0;
435 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
437 int mopt;
439 if (vendor->match_type == MATCH_VENDOR)
440 mopt = OPTION_VENDOR_ID;
441 else if (vendor->match_type == MATCH_USER)
442 mopt = OPTION_USER_CLASS;
443 else
444 continue;
446 if ((opt = option_find(mess, sz, mopt, 1)))
448 int i;
449 for (i = 0; i <= (option_len(opt) - vendor->len); i++)
450 if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
452 vendor->netid.next = netid;
453 netid = &vendor->netid;
454 break;
459 /* mark vendor-encapsulated options which match the client-supplied vendor class,
460 save client-supplied vendor class */
461 if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
463 memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
464 vendor_class_len = option_len(opt);
466 match_vendor_opts(opt, daemon->dhcp_opts);
468 if (option_bool(OPT_LOG_OPTS))
470 if (sanitise(opt, daemon->namebuff))
471 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
472 if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
473 my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
476 mess->op = BOOTREPLY;
478 config = find_config(daemon->dhcp_conf, context, clid, clid_len,
479 mess->chaddr, mess->hlen, mess->htype, NULL);
481 /* set "known" tag for known hosts */
482 if (config)
484 known_id.net = "known";
485 known_id.next = netid;
486 netid = &known_id;
489 if (mess_type == 0 && !pxe)
491 /* BOOTP request */
492 struct dhcp_netid id, bootp_id;
493 struct in_addr *logaddr = NULL;
495 /* must have a MAC addr for bootp */
496 if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
497 return 0;
499 if (have_config(config, CONFIG_DISABLE))
500 message = _("disabled");
502 end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
504 if (have_config(config, CONFIG_NAME))
506 hostname = config->hostname;
507 domain = config->domain;
510 if (config)
512 struct dhcp_netid_list *list;
514 for (list = config->netid; list; list = list->next)
516 list->list->next = netid;
517 netid = list->list;
521 /* Match incoming filename field as a netid. */
522 if (mess->file[0])
524 memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
525 daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
526 id.net = (char *)daemon->dhcp_buff2;
527 id.next = netid;
528 netid = &id;
531 /* Add "bootp" as a tag to allow different options, address ranges etc
532 for BOOTP clients */
533 bootp_id.net = "bootp";
534 bootp_id.next = netid;
535 netid = &bootp_id;
537 tagif_netid = run_tag_if(netid);
539 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
540 if (match_netid(id_list->list, tagif_netid, 0))
541 message = _("ignored");
543 if (!message)
545 int nailed = 0;
547 if (have_config(config, CONFIG_ADDR))
549 nailed = 1;
550 logaddr = &config->addr;
551 mess->yiaddr = config->addr;
552 if ((lease = lease_find_by_addr(config->addr)) &&
553 (lease->hwaddr_len != mess->hlen ||
554 lease->hwaddr_type != mess->htype ||
555 memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
556 message = _("address in use");
558 else
560 if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
561 !address_available(context, lease->addr, tagif_netid))
563 if (lease)
565 /* lease exists, wrong network. */
566 lease_prune(lease, now);
567 lease = NULL;
569 if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
570 message = _("no address available");
572 else
573 mess->yiaddr = lease->addr;
576 if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
577 message = _("wrong network");
578 else if (context->netid.net)
580 context->netid.next = netid;
581 tagif_netid = run_tag_if(&context->netid);
584 log_tags(tagif_netid, ntohl(mess->xid));
586 if (!message && !nailed)
588 for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
589 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
590 break;
591 if (!id_list)
592 message = _("no address configured");
595 if (!message &&
596 !lease &&
597 (!(lease = lease4_allocate(mess->yiaddr))))
598 message = _("no leases left");
600 if (!message)
602 logaddr = &mess->yiaddr;
604 lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
605 if (hostname)
606 lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain);
607 /* infinite lease unless nailed in dhcp-host line. */
608 lease_set_expires(lease,
609 have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
610 now);
611 lease_set_interface(lease, int_index, now);
613 clear_packet(mess, end);
614 do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
615 netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0);
619 log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
621 return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
624 if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 3)))
626 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
627 int len = option_len(opt);
628 char *pq = daemon->dhcp_buff;
629 unsigned char *pp, *op = option_ptr(opt, 0);
631 fqdn_flags = *op;
632 len -= 3;
633 op += 3;
634 pp = op;
636 /* NB, the following always sets at least one bit */
637 if (option_bool(OPT_FQDN_UPDATE))
639 if (fqdn_flags & 0x01)
641 fqdn_flags |= 0x02; /* set O */
642 fqdn_flags &= ~0x01; /* clear S */
644 fqdn_flags |= 0x08; /* set N */
646 else
648 if (!(fqdn_flags & 0x01))
649 fqdn_flags |= 0x03; /* set S and O */
650 fqdn_flags &= ~0x08; /* clear N */
653 if (fqdn_flags & 0x04)
654 while (*op != 0 && ((op + (*op)) - pp) < len)
656 memcpy(pq, op+1, *op);
657 pq += *op;
658 op += (*op)+1;
659 *(pq++) = '.';
661 else
663 memcpy(pq, op, len);
664 if (len > 0 && op[len-1] == 0)
665 borken_opt = 1;
666 pq += len + 1;
669 if (pq != daemon->dhcp_buff)
670 pq--;
672 *pq = 0;
674 if (legal_hostname(daemon->dhcp_buff))
675 offer_hostname = client_hostname = daemon->dhcp_buff;
677 else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
679 int len = option_len(opt);
680 memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
681 /* Microsoft clients are broken, and need zero-terminated strings
682 in options. We detect this state here, and do the same in
683 any options we send */
684 if (len > 0 && daemon->dhcp_buff[len-1] == 0)
685 borken_opt = 1;
686 else
687 daemon->dhcp_buff[len] = 0;
688 if (legal_hostname(daemon->dhcp_buff))
689 client_hostname = daemon->dhcp_buff;
692 if (client_hostname && option_bool(OPT_LOG_OPTS))
693 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
695 if (have_config(config, CONFIG_NAME))
697 hostname = config->hostname;
698 domain = config->domain;
699 hostname_auth = 1;
700 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
701 if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
702 offer_hostname = hostname;
704 else if (client_hostname)
706 domain = strip_hostname(client_hostname);
708 if (strlen(client_hostname) != 0)
710 hostname = client_hostname;
711 if (!config)
713 /* Search again now we have a hostname.
714 Only accept configs without CLID and HWADDR here, (they won't match)
715 to avoid impersonation by name. */
716 struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
717 mess->chaddr, mess->hlen,
718 mess->htype, hostname);
719 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
721 config = new;
722 /* set "known" tag for known hosts */
723 known_id.net = "known";
724 known_id.next = netid;
725 netid = &known_id;
731 if (config)
733 struct dhcp_netid_list *list;
735 for (list = config->netid; list; list = list->next)
737 list->list->next = netid;
738 netid = list->list;
742 tagif_netid = run_tag_if(netid);
744 /* if all the netids in the ignore list are present, ignore this client */
745 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
746 if (match_netid(id_list->list, tagif_netid, 0))
747 ignore = 1;
749 /* If configured, we can override the server-id to be the address of the relay,
750 so that all traffic goes via the relay and can pick up agent-id info. This can be
751 configured for all relays, or by address. */
752 if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
754 if (!daemon->override_relays)
755 override = mess->giaddr;
756 else
758 struct addr_list *l;
759 for (l = daemon->override_relays; l; l = l->next)
760 if (l->addr.s_addr == mess->giaddr.s_addr)
761 break;
762 if (l)
763 override = mess->giaddr;
767 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
768 if (have_config(config, CONFIG_NOCLID))
769 clid = NULL;
771 /* Check if client is PXE client. */
772 if (daemon->enable_pxe &&
773 (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
774 strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
776 if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
778 memcpy(pxe_uuid, option_ptr(opt, 0), 17);
779 uuid = pxe_uuid;
782 /* Check if this is really a PXE bootserver request, and handle specially if so. */
783 if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
784 (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
785 (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
787 struct pxe_service *service;
788 int type = option_uint(opt, 0, 2);
789 int layer = option_uint(opt, 2, 2);
790 unsigned char save71[4];
791 struct dhcp_opt opt71;
793 if (ignore)
794 return 0;
796 if (layer & 0x8000)
798 my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
799 return 0;
802 memcpy(save71, option_ptr(opt, 0), 4);
804 for (service = daemon->pxe_services; service; service = service->next)
805 if (service->type == type)
806 break;
808 for (; context; context = context->current)
809 if (match_netid(context->filter, tagif_netid, 1) &&
810 is_same_net(mess->ciaddr, context->start, context->netmask))
811 break;
813 if (!service || !service->basename || !context)
814 return 0;
816 clear_packet(mess, end);
818 mess->yiaddr = mess->ciaddr;
819 mess->ciaddr.s_addr = 0;
820 if (service->sname)
821 mess->siaddr = a_record_from_hosts(service->sname, now);
822 else if (service->server.s_addr != 0)
823 mess->siaddr = service->server;
824 else
825 mess->siaddr = context->local;
827 snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
828 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
829 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
830 pxe_misc(mess, end, uuid);
832 prune_vendor_opts(tagif_netid);
833 opt71.val = save71;
834 opt71.opt = SUBOPT_PXE_BOOT_ITEM;
835 opt71.len = 4;
836 opt71.flags = DHOPT_VENDOR_MATCH;
837 opt71.netid = NULL;
838 opt71.next = daemon->dhcp_opts;
839 do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
841 log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
842 log_tags(tagif_netid, ntohl(mess->xid));
843 return dhcp_packet_size(mess, agent_id, real_end);
846 if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
848 pxearch = option_uint(opt, 0, 2);
850 /* proxy DHCP here. */
851 if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
853 struct dhcp_context *tmp;
855 for (tmp = context; tmp; tmp = tmp->current)
856 if ((tmp->flags & CONTEXT_PROXY) &&
857 match_netid(tmp->filter, tagif_netid, 1))
858 break;
860 if (tmp)
862 struct dhcp_boot *boot;
864 if (tmp->netid.net)
866 tmp->netid.next = netid;
867 tagif_netid = run_tag_if(&tmp->netid);
870 boot = find_boot(tagif_netid);
872 mess->yiaddr.s_addr = 0;
873 if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
875 mess->ciaddr.s_addr = 0;
876 mess->flags |= htons(0x8000); /* broadcast */
879 clear_packet(mess, end);
881 /* Provide the bootfile here, for gPXE, and in case we have no menu items
882 and set discovery_control = 8 */
883 if (boot)
885 if (boot->next_server.s_addr)
886 mess->siaddr = boot->next_server;
887 else if (boot->tftp_sname)
888 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
890 if (boot->file)
891 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
894 option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
895 mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
896 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
897 pxe_misc(mess, end, uuid);
898 prune_vendor_opts(tagif_netid);
899 do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
901 log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
902 log_tags(tagif_netid, ntohl(mess->xid));
903 return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
909 /* if we're just a proxy server, go no further */
910 if ((context->flags & CONTEXT_PROXY) || pxe)
911 return 0;
913 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
915 req_options = (unsigned char *)daemon->dhcp_buff2;
916 memcpy(req_options, option_ptr(opt, 0), option_len(opt));
917 req_options[option_len(opt)] = OPTION_END;
920 switch (mess_type)
922 case DHCPDECLINE:
923 if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
924 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
925 return 0;
927 /* sanitise any message. Paranoid? Moi? */
928 sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
930 if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
931 return 0;
933 log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
935 if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
936 lease_prune(lease, now);
938 if (have_config(config, CONFIG_ADDR) &&
939 config->addr.s_addr == option_addr(opt).s_addr)
941 prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
942 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
943 inet_ntoa(config->addr), daemon->dhcp_buff);
944 config->flags |= CONFIG_DECLINED;
945 config->decline_time = now;
947 else
948 /* make sure this host gets a different address next time. */
949 for (; context; context = context->current)
950 context->addr_epoch++;
952 return 0;
954 case DHCPRELEASE:
955 if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
956 !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
957 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
958 return 0;
960 if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
961 lease_prune(lease, now);
962 else
963 message = _("unknown lease");
965 log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
967 return 0;
969 case DHCPDISCOVER:
970 if (ignore || have_config(config, CONFIG_DISABLE))
972 if (option_bool(OPT_QUIET_DHCP))
973 return 0;
974 message = _("ignored");
975 opt = NULL;
977 else
979 struct in_addr addr, conf;
981 addr.s_addr = conf.s_addr = 0;
983 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
984 addr = option_addr(opt);
986 if (have_config(config, CONFIG_ADDR))
988 char *addrs = inet_ntoa(config->addr);
990 if ((ltmp = lease_find_by_addr(config->addr)) &&
991 ltmp != lease &&
992 !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
994 int len;
995 unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
996 ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
997 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
998 addrs, print_mac(daemon->namebuff, mac, len));
1000 else
1002 struct dhcp_context *tmp;
1003 for (tmp = context; tmp; tmp = tmp->current)
1004 if (context->router.s_addr == config->addr.s_addr)
1005 break;
1006 if (tmp)
1007 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
1008 else if (have_config(config, CONFIG_DECLINED) &&
1009 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
1010 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
1011 else
1012 conf = config->addr;
1016 if (conf.s_addr)
1017 mess->yiaddr = conf;
1018 else if (lease &&
1019 address_available(context, lease->addr, tagif_netid) &&
1020 !config_find_by_address(daemon->dhcp_conf, lease->addr))
1021 mess->yiaddr = lease->addr;
1022 else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
1023 !config_find_by_address(daemon->dhcp_conf, addr))
1024 mess->yiaddr = addr;
1025 else if (emac_len == 0)
1026 message = _("no unique-id");
1027 else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
1028 message = _("no address available");
1031 log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
1033 if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1034 return 0;
1036 if (context->netid.net)
1038 context->netid.next = netid;
1039 tagif_netid = run_tag_if(&context->netid);
1042 log_tags(tagif_netid, ntohl(mess->xid));
1044 log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1046 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1047 clear_packet(mess, end);
1048 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
1049 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1050 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1051 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1052 do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
1053 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
1055 return dhcp_packet_size(mess, agent_id, real_end);
1057 case DHCPREQUEST:
1058 if (ignore || have_config(config, CONFIG_DISABLE))
1059 return 0;
1060 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1062 /* SELECTING or INIT_REBOOT */
1063 mess->yiaddr = option_addr(opt);
1065 /* send vendor and user class info for new or recreated lease */
1066 do_classes = 1;
1068 if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
1070 /* SELECTING */
1071 selecting = 1;
1073 if (override.s_addr != 0)
1075 if (option_addr(opt).s_addr != override.s_addr)
1076 return 0;
1078 else
1080 for (; context; context = context->current)
1081 if (context->local.s_addr == option_addr(opt).s_addr)
1082 break;
1084 if (!context)
1086 /* Handle very strange configs where clients have more than one route to the server.
1087 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1088 Have to set override to make sure we echo back the correct server-id */
1089 struct irec *intr;
1091 enumerate_interfaces(0);
1093 for (intr = daemon->interfaces; intr; intr = intr->next)
1094 if (intr->addr.sa.sa_family == AF_INET &&
1095 intr->addr.in.sin_addr.s_addr == option_addr(opt).s_addr &&
1096 intr->tftp_ok)
1097 break;
1099 if (intr)
1100 override = intr->addr.in.sin_addr;
1101 else
1103 /* In auth mode, a REQUEST sent to the wrong server
1104 should be faulted, so that the client establishes
1105 communication with us, otherwise, silently ignore. */
1106 if (!option_bool(OPT_AUTHORITATIVE))
1107 return 0;
1108 message = _("wrong server-ID");
1113 /* If a lease exists for this host and another address, squash it. */
1114 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1116 lease_prune(lease, now);
1117 lease = NULL;
1120 else
1122 /* INIT-REBOOT */
1123 if (!lease && !option_bool(OPT_AUTHORITATIVE))
1124 return 0;
1126 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1127 message = _("wrong address");
1130 else
1132 /* RENEWING or REBINDING */
1133 /* Check existing lease for this address.
1134 We allow it to be missing if dhcp-authoritative mode
1135 as long as we can allocate the lease now - checked below.
1136 This makes for a smooth recovery from a lost lease DB */
1137 if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1138 (!lease && !option_bool(OPT_AUTHORITATIVE)))
1140 /* A client rebinding will broadcast the request, so we may see it even
1141 if the lease is held by another server. Just ignore it in that case.
1142 If the request is unicast to us, then somethings wrong, NAK */
1143 if (!unicast_dest)
1144 return 0;
1145 message = _("lease not found");
1146 /* ensure we broadcast NAK */
1147 unicast_dest = 0;
1150 /* desynchronise renewals */
1151 fuzz = rand16();
1152 mess->yiaddr = mess->ciaddr;
1155 log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1157 if (!message)
1159 struct dhcp_config *addr_config;
1160 struct dhcp_context *tmp = NULL;
1162 if (have_config(config, CONFIG_ADDR))
1163 for (tmp = context; tmp; tmp = tmp->current)
1164 if (context->router.s_addr == config->addr.s_addr)
1165 break;
1167 if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1169 /* If a machine moves networks whilst it has a lease, we catch that here. */
1170 message = _("wrong network");
1171 /* ensure we broadcast NAK */
1172 unicast_dest = 0;
1175 /* Check for renewal of a lease which is outside the allowed range. */
1176 else if (!address_available(context, mess->yiaddr, tagif_netid) &&
1177 (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1178 message = _("address not available");
1180 /* Check if a new static address has been configured. Be very sure that
1181 when the client does DISCOVER, it will get the static address, otherwise
1182 an endless protocol loop will ensue. */
1183 else if (!tmp && !selecting &&
1184 have_config(config, CONFIG_ADDR) &&
1185 (!have_config(config, CONFIG_DECLINED) ||
1186 difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1187 config->addr.s_addr != mess->yiaddr.s_addr &&
1188 (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1189 message = _("static lease available");
1191 /* Check to see if the address is reserved as a static address for another host */
1192 else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1193 message = _("address reserved");
1195 else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1197 /* If a host is configured with more than one MAC address, it's OK to 'nix
1198 a lease from one of it's MACs to give the address to another. */
1199 if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1201 my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1202 print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
1203 inet_ntoa(ltmp->addr));
1204 lease = ltmp;
1206 else
1207 message = _("address in use");
1210 if (!message)
1212 if (emac_len == 0)
1213 message = _("no unique-id");
1215 else if (!lease)
1217 if ((lease = lease4_allocate(mess->yiaddr)))
1218 do_classes = 1;
1219 else
1220 message = _("no leases left");
1225 if (message)
1227 log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
1229 mess->yiaddr.s_addr = 0;
1230 clear_packet(mess, end);
1231 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1232 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1233 option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1234 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1235 a distant subnet which unicast a REQ to us won't work. */
1236 if (!unicast_dest || mess->giaddr.s_addr != 0 ||
1237 mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1239 mess->flags |= htons(0x8000); /* broadcast */
1240 mess->ciaddr.s_addr = 0;
1243 else
1245 if (context->netid.net)
1247 context->netid.next = netid;
1248 tagif_netid = run_tag_if( &context->netid);
1251 log_tags(tagif_netid, ntohl(mess->xid));
1253 if (do_classes)
1255 /* pick up INIT-REBOOT events. */
1256 lease->flags |= LEASE_CHANGED;
1258 #ifdef HAVE_SCRIPT
1259 if (daemon->lease_change_command)
1261 struct dhcp_netid *n;
1263 if (mess->giaddr.s_addr)
1264 lease->giaddr = mess->giaddr;
1266 free(lease->extradata);
1267 lease->extradata = NULL;
1268 lease->extradata_size = lease->extradata_len = 0;
1270 add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
1271 add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
1272 add_extradata_opt(lease, oui);
1273 add_extradata_opt(lease, serial);
1274 add_extradata_opt(lease, class);
1276 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
1278 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
1279 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
1280 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
1282 else
1284 add_extradata_opt(lease, NULL);
1285 add_extradata_opt(lease, NULL);
1286 add_extradata_opt(lease, NULL);
1289 /* space-concat tag set */
1290 if (!tagif_netid)
1291 add_extradata_opt(lease, NULL);
1292 else
1293 for (n = tagif_netid; n; n = n->next)
1295 struct dhcp_netid *n1;
1296 /* kill dupes */
1297 for (n1 = n->next; n1; n1 = n1->next)
1298 if (strcmp(n->net, n1->net) == 0)
1299 break;
1300 if (!n1)
1301 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
1304 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1306 int len = option_len(opt);
1307 unsigned char *ucp = option_ptr(opt, 0);
1308 /* If the user-class option started as counted strings, the first byte will be zero. */
1309 if (len != 0 && ucp[0] == 0)
1310 ucp++, len--;
1311 lease_add_extradata(lease, ucp, len, 0);
1314 #endif
1317 if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1319 domain = get_domain(mess->yiaddr);
1320 hostname = client_hostname;
1321 hostname_auth = 1;
1324 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1325 lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
1327 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1328 if (!hostname_auth)
1330 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1331 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1332 break;
1333 if (id_list)
1334 hostname = NULL;
1337 /* Last ditch, if configured, generate hostname from mac address */
1338 if (!hostname && emac_len != 0)
1340 for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
1341 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1342 break;
1343 if (id_list)
1345 int i;
1347 hostname = daemon->dhcp_buff;
1348 /* buffer is 256 bytes, 3 bytes per octet */
1349 for (i = 0; (i < emac_len) && (i < 80); i++)
1350 hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
1351 hostname = daemon->dhcp_buff;
1355 if (hostname)
1356 lease_set_hostname(lease, hostname, hostname_auth, get_domain(lease->addr), domain);
1358 lease_set_expires(lease, time, now);
1359 lease_set_interface(lease, int_index, now);
1361 if (override.s_addr != 0)
1362 lease->override = override;
1363 else
1364 override = lease->override;
1366 log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1368 clear_packet(mess, end);
1369 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1370 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1371 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1372 do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
1373 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
1376 return dhcp_packet_size(mess, agent_id, real_end);
1378 case DHCPINFORM:
1379 if (ignore || have_config(config, CONFIG_DISABLE))
1380 message = _("ignored");
1382 log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
1384 if (message || mess->ciaddr.s_addr == 0)
1385 return 0;
1387 /* For DHCPINFORM only, cope without a valid context */
1388 context = narrow_context(context, mess->ciaddr, tagif_netid);
1390 /* Find a least based on IP address if we didn't
1391 get one from MAC address/client-d */
1392 if (!lease &&
1393 (lease = lease_find_by_addr(mess->ciaddr)) &&
1394 lease->hostname)
1395 hostname = lease->hostname;
1397 if (!hostname)
1398 hostname = host_from_dns(mess->ciaddr);
1400 if (context && context->netid.net)
1402 context->netid.next = netid;
1403 tagif_netid = run_tag_if(&context->netid);
1406 log_tags(tagif_netid, ntohl(mess->xid));
1408 log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1410 if (lease)
1412 lease_set_interface(lease, int_index, now);
1413 if (override.s_addr != 0)
1414 lease->override = override;
1415 else
1416 override = lease->override;
1419 clear_packet(mess, end);
1420 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1421 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1423 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1424 we supply a utility which makes DHCPINFORM requests to get this information.
1425 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1426 which won't be true for ordinary clients, but will be true for the
1427 dhcp_lease_time utility. */
1428 if (lease && in_list(req_options, OPTION_LEASE_TIME))
1430 if (lease->expires == 0)
1431 time = 0xffffffff;
1432 else
1433 time = (unsigned int)difftime(lease->expires, now);
1434 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1437 do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1438 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0);
1440 *is_inform = 1; /* handle reply differently */
1441 return dhcp_packet_size(mess, agent_id, real_end);
1444 return 0;
1447 /* find a good value to use as MAC address for logging and address-allocation hashing.
1448 This is normally just the chaddr field from the DHCP packet,
1449 but eg Firewire will have hlen == 0 and use the client-id instead.
1450 This could be anything, but will normally be EUI64 for Firewire.
1451 We assume that if the first byte of the client-id equals the htype byte
1452 then the client-id is using the usual encoding and use the rest of the
1453 client-id: if not we can use the whole client-id. This should give
1454 sane MAC address logs. */
1455 unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
1456 int clid_len, unsigned char *clid, int *len_out)
1458 if (hwlen == 0 && clid && clid_len > 3)
1460 if (clid[0] == hwtype)
1462 *len_out = clid_len - 1 ;
1463 return clid + 1;
1466 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1467 if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1469 *len_out = clid_len - 1 ;
1470 return clid + 1;
1472 #endif
1474 *len_out = clid_len;
1475 return clid;
1478 *len_out = hwlen;
1479 return hwaddr;
1482 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1484 unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1486 if (opt)
1488 unsigned int req_time = option_uint(opt, 0, 4);
1489 if (req_time < 120 )
1490 req_time = 120; /* sanity */
1491 if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1492 time = req_time;
1495 return time;
1498 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1500 if (override.s_addr != 0)
1501 return override;
1502 else if (context && context->local.s_addr != 0)
1503 return context->local;
1504 else
1505 return fallback;
1508 static int sanitise(unsigned char *opt, char *buf)
1510 char *p;
1511 int i;
1513 *buf = 0;
1515 if (!opt)
1516 return 0;
1518 p = option_ptr(opt, 0);
1520 for (i = option_len(opt); i > 0; i--)
1522 char c = *p++;
1523 if (isprint((int)c))
1524 *buf++ = c;
1526 *buf = 0; /* add terminator */
1528 return 1;
1531 #ifdef HAVE_SCRIPT
1532 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
1534 if (!opt)
1535 lease_add_extradata(lease, NULL, 0, 0);
1536 else
1537 lease_add_extradata(lease, option_ptr(opt, 0), option_len(opt), 0);
1539 #endif
1541 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
1542 int mac_len, char *interface, char *string, char *err, u32 xid)
1544 struct in_addr a;
1547 if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
1548 return;
1550 /* addr may be misaligned */
1551 if (addr)
1552 memcpy(&a, addr, sizeof(a));
1554 print_mac(daemon->namebuff, ext_mac, mac_len);
1556 if(option_bool(OPT_LOG_OPTS))
1557 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
1558 ntohl(xid),
1559 type,
1560 interface,
1561 addr ? inet_ntoa(a) : "",
1562 addr ? " " : "",
1563 daemon->namebuff,
1564 string ? string : "",
1565 err ? err : "");
1566 else
1567 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
1568 type,
1569 interface,
1570 addr ? inet_ntoa(a) : "",
1571 addr ? " " : "",
1572 daemon->namebuff,
1573 string ? string : "",
1574 err ? err : "");
1577 static void log_options(unsigned char *start, u32 xid)
1579 while (*start != OPTION_END)
1581 char *optname = option_string(AF_INET, start[0], option_ptr(start, 0), option_len(start), daemon->namebuff, MAXDNAME);
1583 my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d %s %s",
1584 ntohl(xid), option_len(start), start[0], optname, daemon->namebuff);
1585 start += start[1] + 2;
1589 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1591 while (1)
1593 if (p > end)
1594 return NULL;
1595 else if (*p == OPTION_END)
1596 return opt == OPTION_END ? p : NULL;
1597 else if (*p == OPTION_PAD)
1598 p++;
1599 else
1601 int opt_len;
1602 if (p > end - 2)
1603 return NULL; /* malformed packet */
1604 opt_len = option_len(p);
1605 if (p > end - (2 + opt_len))
1606 return NULL; /* malformed packet */
1607 if (*p == opt && opt_len >= minsize)
1608 return p;
1609 p += opt_len + 2;
1614 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1616 unsigned char *ret, *overload;
1618 /* skip over DHCP cookie; */
1619 if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1620 return ret;
1622 /* look for overload option. */
1623 if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1624 return NULL;
1626 /* Can we look in filename area ? */
1627 if ((overload[2] & 1) &&
1628 (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1629 return ret;
1631 /* finally try sname area */
1632 if ((overload[2] & 2) &&
1633 (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1634 return ret;
1636 return NULL;
1639 static struct in_addr option_addr(unsigned char *opt)
1641 /* this worries about unaligned data in the option. */
1642 /* struct in_addr is network byte order */
1643 struct in_addr ret;
1645 memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
1647 return ret;
1650 static unsigned int option_uint(unsigned char *opt, int offset, int size)
1652 /* this worries about unaligned data and byte order */
1653 unsigned int ret = 0;
1654 int i;
1655 unsigned char *p = option_ptr(opt, offset);
1657 for (i = 0; i < size; i++)
1658 ret = (ret << 8) | *p++;
1660 return ret;
1663 static unsigned char *dhcp_skip_opts(unsigned char *start)
1665 while (*start != 0)
1666 start += start[1] + 2;
1667 return start;
1670 /* only for use when building packet: doesn't check for bad data. */
1671 static unsigned char *find_overload(struct dhcp_packet *mess)
1673 unsigned char *p = &mess->options[0] + sizeof(u32);
1675 while (*p != 0)
1677 if (*p == OPTION_OVERLOAD)
1678 return p;
1679 p += p[1] + 2;
1681 return NULL;
1684 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end)
1686 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1687 unsigned char *overload;
1688 size_t ret;
1690 /* move agent_id back down to the end of the packet */
1691 if (agent_id)
1693 memmove(p, agent_id, real_end - agent_id);
1694 p += real_end - agent_id;
1695 memset(p, 0, real_end - p); /* in case of overlap */
1698 /* add END options to the regions. */
1699 overload = find_overload(mess);
1701 if (overload && (option_uint(overload, 0, 1) & 1))
1703 *dhcp_skip_opts(mess->file) = OPTION_END;
1704 if (option_bool(OPT_LOG_OPTS))
1705 log_options(mess->file, mess->xid);
1707 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1708 my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1710 if (overload && (option_uint(overload, 0, 1) & 2))
1712 *dhcp_skip_opts(mess->sname) = OPTION_END;
1713 if (option_bool(OPT_LOG_OPTS))
1714 log_options(mess->sname, mess->xid);
1716 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1717 my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1720 *p++ = OPTION_END;
1722 if (option_bool(OPT_LOG_OPTS))
1724 if (mess->siaddr.s_addr != 0)
1725 my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
1727 if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
1728 my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
1730 log_options(&mess->options[0] + sizeof(u32), mess->xid);
1733 ret = (size_t)(p - (unsigned char *)mess);
1735 if (ret < MIN_PACKETSZ)
1736 ret = MIN_PACKETSZ;
1738 return ret;
1741 static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1743 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1745 if (p + len + 3 >= end)
1746 /* not enough space in options area, try and use overload, if poss */
1748 unsigned char *overload;
1750 if (!(overload = find_overload(mess)) &&
1751 (mess->file[0] == 0 || mess->sname[0] == 0))
1753 /* attempt to overload fname and sname areas, we've reserved space for the
1754 overflow option previuously. */
1755 overload = p;
1756 *(p++) = OPTION_OVERLOAD;
1757 *(p++) = 1;
1760 p = NULL;
1762 /* using filename field ? */
1763 if (overload)
1765 if (mess->file[0] == 0)
1766 overload[2] |= 1;
1768 if (overload[2] & 1)
1770 p = dhcp_skip_opts(mess->file);
1771 if (p + len + 3 >= mess->file + sizeof(mess->file))
1772 p = NULL;
1775 if (!p)
1777 /* try to bring sname into play (it may be already) */
1778 if (mess->sname[0] == 0)
1779 overload[2] |= 2;
1781 if (overload[2] & 2)
1783 p = dhcp_skip_opts(mess->sname);
1784 if (p + len + 3 >= mess->sname + sizeof(mess->sname))
1785 p = NULL;
1790 if (!p)
1791 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1794 if (p)
1796 *(p++) = opt;
1797 *(p++) = len;
1800 return p;
1803 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1805 int i;
1806 unsigned char *p = free_space(mess, end, opt, len);
1808 if (p)
1809 for (i = 0; i < len; i++)
1810 *(p++) = val >> (8 * (len - (i + 1)));
1813 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
1814 char *string, int null_term)
1816 unsigned char *p;
1817 size_t len = strlen(string);
1819 if (null_term && len != 255)
1820 len++;
1822 if ((p = free_space(mess, end, opt, len)))
1823 memcpy(p, string, len);
1826 /* return length, note this only does the data part */
1827 static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1829 int len = opt->len;
1831 if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1832 len++;
1834 if (p && len != 0)
1836 if (context && (opt->flags & DHOPT_ADDR))
1838 int j;
1839 struct in_addr *a = (struct in_addr *)opt->val;
1840 for (j = 0; j < opt->len; j+=INADDRSZ, a++)
1842 /* zero means "self" (but not in vendorclass options.) */
1843 if (a->s_addr == 0)
1844 memcpy(p, &context->local, INADDRSZ);
1845 else
1846 memcpy(p, a, INADDRSZ);
1847 p += INADDRSZ;
1850 else
1851 /* empty string may be extended to "\0" by null_term */
1852 memcpy(p, opt->val ? opt->val : (unsigned char *)"", len);
1854 return len;
1857 static int in_list(unsigned char *list, int opt)
1859 int i;
1861 /* If no requested options, send everything, not nothing. */
1862 if (!list)
1863 return 1;
1865 for (i = 0; list[i] != OPTION_END; i++)
1866 if (opt == list[i])
1867 return 1;
1869 return 0;
1872 static struct dhcp_opt *option_find2(int opt)
1874 struct dhcp_opt *opts;
1876 for (opts = daemon->dhcp_opts; opts; opts = opts->next)
1877 if (opts->opt == opt && (opts->flags & DHOPT_TAGOK))
1878 return opts;
1880 return NULL;
1883 /* mark vendor-encapsulated options which match the client-supplied or
1884 config-supplied vendor class */
1885 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
1887 for (; dopt; dopt = dopt->next)
1889 dopt->flags &= ~DHOPT_VENDOR_MATCH;
1890 if (opt && (dopt->flags & DHOPT_VENDOR))
1892 int i, len = 0;
1893 if (dopt->u.vendor_class)
1894 len = strlen((char *)dopt->u.vendor_class);
1895 for (i = 0; i <= (option_len(opt) - len); i++)
1896 if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
1898 dopt->flags |= DHOPT_VENDOR_MATCH;
1899 break;
1905 static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
1906 struct dhcp_packet *mess, unsigned char *end, int null_term)
1908 int len, enc_len, ret = 0;
1909 struct dhcp_opt *start;
1910 unsigned char *p;
1912 /* find size in advance */
1913 for (enc_len = 0, start = opt; opt; opt = opt->next)
1914 if (opt->flags & flag)
1916 int new = do_opt(opt, NULL, NULL, null_term) + 2;
1917 ret = 1;
1918 if (enc_len + new <= 255)
1919 enc_len += new;
1920 else
1922 p = free_space(mess, end, encap, enc_len);
1923 for (; start && start != opt; start = start->next)
1924 if (p && (start->flags & flag))
1926 len = do_opt(start, p + 2, NULL, null_term);
1927 *(p++) = start->opt;
1928 *(p++) = len;
1929 p += len;
1931 enc_len = new;
1932 start = opt;
1936 if (enc_len != 0 &&
1937 (p = free_space(mess, end, encap, enc_len + 1)))
1939 for (; start; start = start->next)
1940 if (start->flags & flag)
1942 len = do_opt(start, p + 2, NULL, null_term);
1943 *(p++) = start->opt;
1944 *(p++) = len;
1945 p += len;
1947 *p = OPTION_END;
1950 return ret;
1953 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
1955 unsigned char *p;
1957 option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
1958 if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
1959 memcpy(p, uuid, 17);
1962 static int prune_vendor_opts(struct dhcp_netid *netid)
1964 int force = 0;
1965 struct dhcp_opt *opt;
1967 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1968 for (opt = daemon->dhcp_opts; opt; opt = opt->next)
1969 if (opt->flags & DHOPT_VENDOR_MATCH)
1971 if (!match_netid(opt->netid, netid, 1))
1972 opt->flags &= ~DHOPT_VENDOR_MATCH;
1973 else if (opt->flags & DHOPT_FORCE)
1974 force = 1;
1976 return force;
1979 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
1981 #define NUM_OPTS 4
1983 unsigned char *p, *q;
1984 struct pxe_service *service;
1985 static struct dhcp_opt *o, *ret;
1986 int i, j = NUM_OPTS - 1;
1987 struct in_addr boot_server;
1989 /* We pass back references to these, hence they are declared static */
1990 static unsigned char discovery_control;
1991 static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' };
1992 static struct dhcp_opt *fake_opts = NULL;
1994 /* Disable multicast, since we don't support it, and broadcast
1995 unless we need it */
1996 discovery_control = 3;
1998 ret = daemon->dhcp_opts;
2000 if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
2001 return ret;
2003 for (i = 0; i < NUM_OPTS; i++)
2005 fake_opts[i].flags = DHOPT_VENDOR_MATCH;
2006 fake_opts[i].netid = NULL;
2007 fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
2010 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2011 p = (unsigned char *)daemon->dhcp_buff;
2012 q = (unsigned char *)daemon->dhcp_buff3;
2014 for (i = 0, service = daemon->pxe_services; service; service = service->next)
2015 if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
2017 size_t len = strlen(service->menu);
2018 /* opt 43 max size is 255. encapsulated option has type and length
2019 bytes, so its max size is 253. */
2020 if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
2022 *(p++) = service->type >> 8;
2023 *(p++) = service->type;
2024 *(p++) = len;
2025 memcpy(p, service->menu, len);
2026 p += len;
2027 i++;
2029 else
2031 toobig:
2032 my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
2033 return daemon->dhcp_opts;
2036 boot_server = service->basename ? local :
2037 (service->sname ? a_record_from_hosts(service->sname, now) : service->server);
2039 if (boot_server.s_addr != 0)
2041 if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
2042 goto toobig;
2044 /* Boot service with known address - give it */
2045 *(q++) = service->type >> 8;
2046 *(q++) = service->type;
2047 *(q++) = 1;
2048 /* dest misaligned */
2049 memcpy(q, &boot_server.s_addr, INADDRSZ);
2050 q += INADDRSZ;
2052 else if (service->type != 0)
2053 /* We don't know the server for a service type, so we'll
2054 allow the client to broadcast for it */
2055 discovery_control = 2;
2058 /* if no prompt, wait forever if there's a choice */
2059 fake_prompt[0] = (i > 1) ? 255 : 0;
2061 if (i == 0)
2062 discovery_control = 8; /* no menu - just use use mess->filename */
2063 else
2065 ret = &fake_opts[j--];
2066 ret->len = p - (unsigned char *)daemon->dhcp_buff;
2067 ret->val = (unsigned char *)daemon->dhcp_buff;
2068 ret->opt = SUBOPT_PXE_MENU;
2070 if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
2072 ret = &fake_opts[j--];
2073 ret->len = q - (unsigned char *)daemon->dhcp_buff3;
2074 ret->val = (unsigned char *)daemon->dhcp_buff3;
2075 ret->opt = SUBOPT_PXE_SERVERS;
2079 for (o = daemon->dhcp_opts; o; o = o->next)
2080 if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
2081 break;
2083 if (!o)
2085 ret = &fake_opts[j--];
2086 ret->len = sizeof(fake_prompt);
2087 ret->val = fake_prompt;
2088 ret->opt = SUBOPT_PXE_MENU_PROMPT;
2091 ret = &fake_opts[j--];
2092 ret->len = 1;
2093 ret->opt = SUBOPT_PXE_DISCOVERY;
2094 ret->val= &discovery_control;
2096 return ret;
2099 static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
2101 memset(mess->sname, 0, sizeof(mess->sname));
2102 memset(mess->file, 0, sizeof(mess->file));
2103 memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
2104 mess->siaddr.s_addr = 0;
2107 struct dhcp_boot *find_boot(struct dhcp_netid *netid)
2109 struct dhcp_boot *boot;
2111 /* decide which dhcp-boot option we're using */
2112 for (boot = daemon->boot_config; boot; boot = boot->next)
2113 if (match_netid(boot->netid, netid, 0))
2114 break;
2115 if (!boot)
2116 /* No match, look for one without a netid */
2117 for (boot = daemon->boot_config; boot; boot = boot->next)
2118 if (match_netid(boot->netid, netid, 1))
2119 break;
2121 return boot;
2124 static void do_options(struct dhcp_context *context,
2125 struct dhcp_packet *mess,
2126 unsigned char *end,
2127 unsigned char *req_options,
2128 char *hostname,
2129 char *domain,
2130 struct dhcp_netid *netid,
2131 struct in_addr subnet_addr,
2132 unsigned char fqdn_flags,
2133 int null_term, int pxe_arch,
2134 unsigned char *uuid,
2135 int vendor_class_len,
2136 time_t now,
2137 unsigned int lease_time,
2138 unsigned short fuzz)
2140 struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2141 struct dhcp_boot *boot;
2142 unsigned char *p;
2143 int i, len, force_encap = 0;
2144 unsigned char f0 = 0, s0 = 0;
2145 int done_file = 0, done_server = 0;
2146 int done_vendor_class = 0;
2147 struct dhcp_netid *tagif;
2148 struct dhcp_netid_list *id_list;
2150 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2151 if (context)
2152 context->netid.next = NULL;
2153 tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
2155 /* logging */
2156 if (option_bool(OPT_LOG_OPTS) && req_options)
2158 char *q = daemon->namebuff;
2159 for (i = 0; req_options[i] != OPTION_END; i++)
2161 char *s = option_string(AF_INET, req_options[i], NULL, 0, NULL, 0);
2162 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2163 "%d%s%s%s",
2164 req_options[i],
2165 strlen(s) != 0 ? ":" : "",
2167 req_options[i+1] == OPTION_END ? "" : ", ");
2168 if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2170 q = daemon->namebuff;
2171 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2176 for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
2177 if ((!id_list->list) || match_netid(id_list->list, netid, 0))
2178 break;
2179 if (id_list)
2180 mess->flags |= htons(0x8000); /* force broadcast */
2182 if (context)
2183 mess->siaddr = context->local;
2185 /* See if we can send the boot stuff as options.
2186 To do this we need a requested option list, BOOTP
2187 and very old DHCP clients won't have this, we also
2188 provide an manual option to disable it.
2189 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2190 names, so we always send those. */
2191 if ((boot = find_boot(tagif)))
2193 if (boot->sname)
2195 if (!option_bool(OPT_NO_OVERRIDE) &&
2196 req_options &&
2197 in_list(req_options, OPTION_SNAME))
2198 option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2199 else
2200 strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
2203 if (boot->file)
2205 if (!option_bool(OPT_NO_OVERRIDE) &&
2206 req_options &&
2207 in_list(req_options, OPTION_FILENAME))
2208 option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2209 else
2210 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
2213 if (boot->next_server.s_addr)
2214 mess->siaddr = boot->next_server;
2215 else if (boot->tftp_sname)
2216 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
2218 else
2219 /* Use the values of the relevant options if no dhcp-boot given and
2220 they're not explicitly asked for as options. OPTION_END is used
2221 as an internal way to specify siaddr without using dhcp-boot, for use in
2222 dhcp-optsfile. */
2224 if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
2225 (opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2227 strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
2228 done_file = 1;
2231 if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2232 (opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2234 strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
2235 done_server = 1;
2238 if ((opt = option_find2(OPTION_END)))
2239 mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
2242 /* We don't want to do option-overload for BOOTP, so make the file and sname
2243 fields look like they are in use, even when they aren't. This gets restored
2244 at the end of this function. */
2246 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2248 f0 = mess->file[0];
2249 mess->file[0] = 1;
2250 s0 = mess->sname[0];
2251 mess->sname[0] = 1;
2254 /* At this point, if mess->sname or mess->file are zeroed, they are available
2255 for option overload, reserve space for the overload option. */
2256 if (mess->file[0] == 0 || mess->sname[0] == 0)
2257 end -= 3;
2259 /* rfc3011 says this doesn't need to be in the requested options list. */
2260 if (subnet_addr.s_addr)
2261 option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2263 if (lease_time != 0xffffffff)
2265 unsigned int t1val = lease_time/2;
2266 unsigned int t2val = (lease_time*7)/8;
2267 unsigned int hval;
2269 /* If set by user, sanity check, so not longer than lease. */
2270 if ((opt = option_find2(OPTION_T1)))
2272 hval = ntohl(*((unsigned int *)opt->val));
2273 if (hval < lease_time && hval > 2)
2274 t1val = hval;
2277 if ((opt = option_find2(OPTION_T2)))
2279 hval = ntohl(*((unsigned int *)opt->val));
2280 if (hval < lease_time && hval > 2)
2281 t2val = hval;
2284 /* ensure T1 is still < T2 */
2285 if (t2val <= t1val)
2286 t1val = t2val - 1;
2288 while (fuzz > (t1val/8))
2289 fuzz = fuzz/2;
2291 t1val -= fuzz;
2292 t2val -= fuzz;
2294 option_put(mess, end, OPTION_T1, 4, t1val);
2295 option_put(mess, end, OPTION_T2, 4, t2val);
2298 /* replies to DHCPINFORM may not have a valid context */
2299 if (context)
2301 if (!option_find2(OPTION_NETMASK))
2302 option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2304 /* May not have a "guessed" broadcast address if we got no packets via a relay
2305 from this net yet (ie just unicast renewals after a restart */
2306 if (context->broadcast.s_addr &&
2307 !option_find2(OPTION_BROADCAST))
2308 option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2310 /* Same comments as broadcast apply, and also may not be able to get a sensible
2311 default when using subnet select. User must configure by steam in that case. */
2312 if (context->router.s_addr &&
2313 in_list(req_options, OPTION_ROUTER) &&
2314 !option_find2(OPTION_ROUTER))
2315 option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2317 if (daemon->port == NAMESERVER_PORT &&
2318 in_list(req_options, OPTION_DNSSERVER) &&
2319 !option_find2(OPTION_DNSSERVER))
2320 option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2323 if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
2324 !option_find2(OPTION_DOMAINNAME))
2325 option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2327 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2328 if (hostname)
2330 if (in_list(req_options, OPTION_HOSTNAME) &&
2331 !option_find2(OPTION_HOSTNAME))
2332 option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2334 if (fqdn_flags != 0)
2336 len = strlen(hostname) + 3;
2338 if (fqdn_flags & 0x04)
2339 len += 2;
2340 else if (null_term)
2341 len++;
2343 if (domain)
2344 len += strlen(domain) + 1;
2345 else if (fqdn_flags & 0x04)
2346 len--;
2348 if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2350 *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */
2351 *(p++) = 255;
2352 *(p++) = 255;
2354 if (fqdn_flags & 0x04)
2356 p = do_rfc1035_name(p, hostname);
2357 if (domain)
2359 p = do_rfc1035_name(p, domain);
2360 *p++ = 0;
2363 else
2365 memcpy(p, hostname, strlen(hostname));
2366 p += strlen(hostname);
2367 if (domain)
2369 *(p++) = '.';
2370 memcpy(p, domain, strlen(domain));
2371 p += strlen(domain);
2373 if (null_term)
2374 *(p++) = 0;
2380 for (opt = config_opts; opt; opt = opt->next)
2382 int optno = opt->opt;
2384 /* netids match and not encapsulated? */
2385 if (!(opt->flags & DHOPT_TAGOK))
2386 continue;
2388 /* was it asked for, or are we sending it anyway? */
2389 if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2390 continue;
2392 /* prohibit some used-internally options. T1 and T2 already handled. */
2393 if (optno == OPTION_CLIENT_FQDN ||
2394 optno == OPTION_MAXMESSAGE ||
2395 optno == OPTION_OVERLOAD ||
2396 optno == OPTION_PAD ||
2397 optno == OPTION_END ||
2398 optno == OPTION_T1 ||
2399 optno == OPTION_T2)
2400 continue;
2402 if (optno == OPTION_SNAME && done_server)
2403 continue;
2405 if (optno == OPTION_FILENAME && done_file)
2406 continue;
2408 /* For the options we have default values on
2409 dhc-option=<optionno> means "don't include this option"
2410 not "include a zero-length option" */
2411 if (opt->len == 0 &&
2412 (optno == OPTION_NETMASK ||
2413 optno == OPTION_BROADCAST ||
2414 optno == OPTION_ROUTER ||
2415 optno == OPTION_DNSSERVER ||
2416 optno == OPTION_DOMAINNAME ||
2417 optno == OPTION_HOSTNAME))
2418 continue;
2420 /* vendor-class comes from elsewhere for PXE */
2421 if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2422 continue;
2424 /* always force null-term for filename and servername - buggy PXE again. */
2425 len = do_opt(opt, NULL, context,
2426 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2428 if ((p = free_space(mess, end, optno, len)))
2430 do_opt(opt, p, context,
2431 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2433 /* If we send a vendor-id, revisit which vendor-ops we consider
2434 it appropriate to send. */
2435 if (optno == OPTION_VENDOR_ID)
2437 match_vendor_opts(p - 2, config_opts);
2438 done_vendor_class = 1;
2443 /* Now send options to be encapsulated in arbitrary options,
2444 eg dhcp-option=encap:172,17,.......
2445 Also handle vendor-identifying vendor-encapsulated options,
2446 dhcp-option = vi-encap:13,17,.......
2447 The may be more that one "outer" to do, so group
2448 all the options which match each outer in turn. */
2449 for (opt = config_opts; opt; opt = opt->next)
2450 opt->flags &= ~DHOPT_ENCAP_DONE;
2452 for (opt = config_opts; opt; opt = opt->next)
2454 int flags;
2456 if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
2458 int found = 0;
2459 struct dhcp_opt *o;
2461 if (opt->flags & DHOPT_ENCAP_DONE)
2462 continue;
2464 for (len = 0, o = config_opts; o; o = o->next)
2466 int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
2468 o->flags &= ~DHOPT_ENCAP_MATCH;
2470 if (!(o->flags & flags) || opt->u.encap != o->u.encap)
2471 continue;
2473 o->flags |= DHOPT_ENCAP_DONE;
2474 if (match_netid(o->netid, tagif, 1) &&
2475 ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
2477 o->flags |= DHOPT_ENCAP_MATCH;
2478 found = 1;
2479 len += do_opt(o, NULL, NULL, 0) + 2;
2483 if (found)
2485 if (flags & DHOPT_ENCAPSULATE)
2486 do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2487 else if (len > 250)
2488 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
2489 else if ((p = free_space(mess, end, OPTION_VENDOR_IDENT_OPT, len + 5)))
2491 int swap_ent = htonl(opt->u.encap);
2492 memcpy(p, &swap_ent, 4);
2493 p += 4;
2494 *(p++) = len;
2495 for (o = config_opts; o; o = o->next)
2496 if (o->flags & DHOPT_ENCAP_MATCH)
2498 len = do_opt(o, p + 2, NULL, 0);
2499 *(p++) = o->opt;
2500 *(p++) = len;
2501 p += len;
2508 force_encap = prune_vendor_opts(tagif);
2510 if (context && pxe_arch != -1)
2512 pxe_misc(mess, end, uuid);
2513 config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
2516 if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
2517 do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) &&
2518 pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
2519 (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
2520 /* If we send vendor encapsulated options, and haven't already sent option 60,
2521 echo back the value we got from the client. */
2522 memcpy(p, daemon->dhcp_buff3, vendor_class_len);
2524 /* restore BOOTP anti-overload hack */
2525 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2527 mess->file[0] = f0;
2528 mess->sname[0] = s0;
2532 #endif