1 /* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #define have_config(config, mask) ((config) && ((config)->flags & (mask)))
22 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
23 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
26 static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim);
27 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
30 static int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
31 static int sanitise(unsigned char *opt, char *buf);
32 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
33 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
34 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
35 static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
36 int opt, char *string, int null_term);
37 static struct in_addr option_addr(unsigned char *opt);
38 static struct in_addr option_addr_arr(unsigned char *opt, int offset);
39 static unsigned int option_uint(unsigned char *opt, int i, int size);
40 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
41 int mac_len, char *interface, char *string, u32 xid);
42 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
43 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
44 static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid,
45 unsigned char *agent_id, unsigned char *real_end);
46 static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
47 static void do_options(struct dhcp_context *context,
48 struct dhcp_packet *mess,
49 unsigned char *real_end,
50 unsigned char *req_options,
52 char *domain, char *config_domain,
53 struct dhcp_netid *netid,
54 struct in_addr subnet_addr,
55 unsigned char fqdn_flags,
56 int null_term, int pxearch,
58 int vendor_class_len);
61 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
62 static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
63 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
64 static int prune_vendor_opts(struct dhcp_netid *netid);
65 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local);
66 struct dhcp_boot *find_boot(struct dhcp_netid *netid);
69 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
70 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe)
72 unsigned char *opt, *clid = NULL;
73 struct dhcp_lease *ltmp, *lease = NULL;
74 struct dhcp_vendor *vendor;
76 struct dhcp_netid_list *id_list;
77 int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
78 struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
79 unsigned char *end = (unsigned char *)(mess + 1);
80 unsigned char *real_end = (unsigned char *)(mess + 1);
81 char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
82 int hostname_auth = 0, borken_opt = 0;
83 unsigned char *req_options = NULL;
86 struct dhcp_config *config;
87 struct dhcp_netid *netid, *tagif_netid;
88 struct in_addr subnet_addr, fallback, override;
89 unsigned short fuzz = 0;
90 unsigned int mess_type = 0;
91 unsigned char fqdn_flags = 0;
92 unsigned char *agent_id = NULL, *uuid = NULL;
93 unsigned char *emac = NULL;
94 int vendor_class_len = 0, emac_len = 0;
95 struct dhcp_netid known_id, iface_id, cpewan_id;
97 unsigned char pxe_uuid[17];
98 unsigned char *oui = NULL, *serial = NULL, *class = NULL;
100 static time_t old_time = 0;
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;
109 if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
112 if (mess->htype == 0 && mess->hlen != 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)
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 class = option_find1(x, y, 3, 1);
166 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
167 the gateway id back. Note that the device class is optional */
170 cpewan_id.net = "cpewan-id";
171 cpewan_id.next = netid;
179 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
181 /* Any agent-id needs to be copied back out, verbatim, as the last option
182 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
183 get overwritten, then it will be shuffled back at the end of processing.
184 Note that the incoming options must not be overwritten here, so there has to
185 be enough free space at the end of the packet to copy the option. */
187 unsigned int total = option_len(opt) + 2;
188 unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
189 if (last_opt && last_opt < end - total)
193 memcpy(agent_id, opt, total);
196 /* look for RFC3527 Link selection sub-option */
197 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
198 subnet_addr = option_addr(sopt);
200 /* look for RFC5107 server-identifier-override */
201 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
202 override = option_addr(sopt);
204 /* if a circuit-id or remote-is option is provided, exact-match to options. */
205 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
209 if (vendor->match_type == MATCH_CIRCUIT)
210 search = SUBOPT_CIRCUIT_ID;
211 else if (vendor->match_type == MATCH_REMOTE)
212 search = SUBOPT_REMOTE_ID;
213 else if (vendor->match_type == MATCH_SUBSCRIBER)
214 search = SUBOPT_SUBSCR_ID;
218 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
219 vendor->len == option_len(sopt) &&
220 memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
222 vendor->netid.next = netid;
223 netid = &vendor->netid;
228 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
229 if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
230 subnet_addr = option_addr(opt);
232 /* If there is no client identifier option, use the hardware address */
233 if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
235 clid_len = option_len(opt);
236 clid = option_ptr(opt, 0);
239 /* do we have a lease in store? */
240 lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
242 /* If this request is missing a clid, but we've seen one before,
243 use it again for option matching etc. */
244 if (lease && !clid && lease->clid)
246 clid_len = lease->clid_len;
250 /* find mac to use for logging and hashing */
251 emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
254 for (mac = daemon->dhcp_macs; mac; mac = mac->next)
255 if (mac->hwaddr_len == mess->hlen &&
256 (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
257 memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
259 mac->netid.next = netid;
263 /* Determine network for this packet. Our caller will have already linked all the
264 contexts which match the addresses of the receiving interface but if the
265 machine has an address already, or came via a relay, or we have a subnet selector,
266 we search again. If we don't have have a giaddr or explicit subnet selector,
267 use the ciaddr. This is necessary because a machine which got a lease via a
268 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
269 from the physical network, continue using that to allow correct DHCPNAK generation later. */
270 if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
272 struct dhcp_context *context_tmp, *context_new = NULL;
276 if (subnet_addr.s_addr)
281 else if (mess->giaddr.s_addr)
288 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
290 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
291 if (context_tmp->netmask.s_addr &&
292 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
293 is_same_net(addr, context_tmp->end, context_tmp->netmask))
295 context_new = context;
301 for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
302 if (context_tmp->netmask.s_addr &&
303 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
304 is_same_net(addr, context_tmp->end, context_tmp->netmask))
306 context_tmp->current = context_new;
307 context_new = context_tmp;
310 if (context_new || force)
311 context = context_new;
317 my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
318 subnet_addr.s_addr ? _("with subnet selector") : _("via"),
319 subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
323 /* keep _a_ local address available. */
324 fallback = context->local;
326 if (option_bool(OPT_LOG_OPTS))
328 struct dhcp_context *context_tmp;
329 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
331 strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
332 if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
333 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
334 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
336 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
337 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
341 mess->op = BOOTREPLY;
343 config = find_config(daemon->dhcp_conf, context, clid, clid_len,
344 mess->chaddr, mess->hlen, mess->htype, NULL);
346 /* set "known" tag for known hosts */
349 known_id.net = "known";
350 known_id.next = netid;
354 if (mess_type == 0 && !pxe)
357 struct dhcp_netid id, bootp_id;
358 struct in_addr *logaddr = NULL;
360 /* must have a MAC addr for bootp */
361 if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
364 if (have_config(config, CONFIG_DISABLE))
365 message = _("disabled");
367 end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
369 if (have_config(config, CONFIG_NAME))
371 hostname = config->hostname;
372 domain = config->domain;
377 struct dhcp_netid_list *list;
379 for (list = config->netid; list; list = list->next)
381 list->list->next = netid;
386 /* Match incoming filename field as a netid. */
389 memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
390 daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
391 id.net = (char *)daemon->dhcp_buff2;
396 /* Add "bootp" as a tag to allow different options, address ranges etc
398 bootp_id.net = "bootp";
399 bootp_id.next = netid;
402 tagif_netid = run_tag_if(netid);
404 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
405 if (match_netid(id_list->list, tagif_netid, 0))
406 message = _("ignored");
412 if (have_config(config, CONFIG_ADDR))
415 logaddr = &config->addr;
416 mess->yiaddr = config->addr;
417 if ((lease = lease_find_by_addr(config->addr)) &&
418 (lease->hwaddr_len != mess->hlen ||
419 lease->hwaddr_type != mess->htype ||
420 memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
421 message = _("address in use");
425 if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
426 !address_available(context, lease->addr, tagif_netid))
430 /* lease exists, wrong network. */
431 lease_prune(lease, now);
434 if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
435 message = _("no address available");
438 mess->yiaddr = lease->addr;
441 if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
442 message = _("wrong network");
443 else if (context->netid.net)
445 context->netid.next = netid;
446 netid = &context->netid;
447 tagif_netid = run_tag_if(netid);
450 if (!message && !nailed)
452 for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
453 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
456 message = _("no address configured");
461 (!(lease = lease_allocate(mess->yiaddr))))
462 message = _("no leases left");
466 logaddr = &mess->yiaddr;
468 lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
470 lease_set_hostname(lease, hostname, 1);
471 /* infinite lease unless nailed in dhcp-host line. */
472 lease_set_expires(lease,
473 have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
475 lease_set_interface(lease, int_index);
477 clear_packet(mess, end);
478 do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
479 domain, tagif_netid, subnet_addr, 0, 0, 0, NULL, 0);
483 log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
485 return message ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
488 if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
490 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
491 int len = option_len(opt);
492 char *pq = daemon->dhcp_buff;
493 unsigned char *pp, *op = option_ptr(opt, 0);
500 /* Always force update, since the client has no way to do it itself. */
501 if (!(fqdn_flags & 0x01))
507 if (fqdn_flags & 0x04)
508 while (*op != 0 && ((op + (*op) + 1) - pp) < len)
510 memcpy(pq, op+1, *op);
518 if (len > 0 && op[len-1] == 0)
523 if (pq != daemon->dhcp_buff)
528 if (legal_hostname(daemon->dhcp_buff))
529 offer_hostname = client_hostname = daemon->dhcp_buff;
531 else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
533 int len = option_len(opt);
534 memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
535 /* Microsoft clients are broken, and need zero-terminated strings
536 in options. We detect this state here, and do the same in
537 any options we send */
538 if (len > 0 && daemon->dhcp_buff[len-1] == 0)
541 daemon->dhcp_buff[len] = 0;
542 if (legal_hostname(daemon->dhcp_buff))
543 client_hostname = daemon->dhcp_buff;
546 if (client_hostname && option_bool(OPT_LOG_OPTS))
547 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
549 if (have_config(config, CONFIG_NAME))
551 hostname = config->hostname;
552 domain = config->domain;
554 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
555 if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
556 offer_hostname = hostname;
558 else if (client_hostname)
560 domain = strip_hostname(client_hostname);
562 if (strlen(client_hostname) != 0)
564 hostname = client_hostname;
567 /* Search again now we have a hostname.
568 Only accept configs without CLID and HWADDR here, (they won't match)
569 to avoid impersonation by name. */
570 struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
571 mess->chaddr, mess->hlen,
572 mess->htype, hostname);
573 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
576 /* set "known" tag for known hosts */
577 known_id.net = "known";
578 known_id.next = netid;
587 struct dhcp_netid_list *list;
589 for (list = config->netid; list; list = list->next)
591 list->list->next = netid;
596 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
597 Otherwise assume the option is an array, and look for a matching element.
598 If no data given, existance of the option is enough. This code handles
599 rfc3925 V-I classes too. */
600 for (o = daemon->dhcp_match; o; o = o->next)
602 unsigned int len, elen, match = 0;
605 if (o->flags & DHOPT_RFC3925)
607 if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
610 for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
612 len = option_uint(opt, offset + 4 , 1);
613 /* Need to take care that bad data can't run us off the end of the packet */
614 if ((offset + len + 5 <= (option_len(opt))) &&
615 (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
616 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
618 elen = option_uint(opt, o2, 1);
619 if ((o2 + elen + 1 <= option_len(opt)) &&
620 (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
629 if (!(opt = option_find(mess, sz, o->opt, 1)))
632 match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
637 o->netid->next = netid;
642 /* user-class options are, according to RFC3004, supposed to contain
643 a set of counted strings. Here we check that this is so (by seeing
644 if the counts are consistent with the overall option length) and if
645 so zero the counts so that we don't get spurious matches between
646 the vendor string and the counts. If the lengths don't add up, we
647 assume that the option is a single string and non RFC3004 compliant
648 and just do the substring match. dhclient provides these broken options.
649 The code, later, which sends user-class data to the lease-change script
650 relies on the transformation done here.
653 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
655 unsigned char *ucp = option_ptr(opt, 0);
657 for (j = 0; j < option_len(opt); j += ucp[j] + 1);
658 if (j == option_len(opt))
659 for (j = 0; j < option_len(opt); j = tmp)
661 tmp = j + ucp[j] + 1;
666 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
670 if (vendor->match_type == MATCH_VENDOR)
671 mopt = OPTION_VENDOR_ID;
672 else if (vendor->match_type == MATCH_USER)
673 mopt = OPTION_USER_CLASS;
677 if ((opt = option_find(mess, sz, mopt, 1)))
680 for (i = 0; i <= (option_len(opt) - vendor->len); i++)
681 if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
683 vendor->netid.next = netid;
684 netid = &vendor->netid;
690 /* mark vendor-encapsulated options which match the client-supplied vendor class,
691 save client-supplied vendor class */
692 if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
694 memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
695 vendor_class_len = option_len(opt);
697 match_vendor_opts(opt, daemon->dhcp_opts);
699 if (option_bool(OPT_LOG_OPTS))
701 if (sanitise(opt, daemon->namebuff))
702 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
703 if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
704 my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
707 tagif_netid = run_tag_if(netid);
709 /* if all the netids in the ignore list are present, ignore this client */
710 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
711 if (match_netid(id_list->list, tagif_netid, 0))
714 /* If configured, we can override the server-id to be the address of the relay,
715 so that all traffic goes via the relay and can pick up agent-id info. This can be
716 configured for all relays, or by address. */
717 if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
719 if (!daemon->override_relays)
720 override = mess->giaddr;
724 for (l = daemon->override_relays; l; l = l->next)
725 if (l->addr.s_addr == mess->giaddr.s_addr)
728 override = mess->giaddr;
732 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
733 if (have_config(config, CONFIG_NOCLID))
736 /* Check if client is PXE client. */
737 if (daemon->enable_pxe &&
738 (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
739 strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
741 if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
743 memcpy(pxe_uuid, option_ptr(opt, 0), 17);
747 /* Check if this is really a PXE bootserver request, and handle specially if so. */
748 if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
749 (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
750 (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
752 struct pxe_service *service;
753 int type = option_uint(opt, 0, 2);
754 int layer = option_uint(opt, 2, 2);
755 unsigned char save71[4];
756 struct dhcp_opt opt71;
763 my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
767 memcpy(save71, option_ptr(opt, 0), 4);
769 for (service = daemon->pxe_services; service; service = service->next)
770 if (service->type == type)
773 if (!service || !service->basename)
776 clear_packet(mess, end);
778 mess->yiaddr = mess->ciaddr;
779 mess->ciaddr.s_addr = 0;
780 if (service->server.s_addr != 0)
781 mess->siaddr = service->server;
783 mess->siaddr = context->local;
785 snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
786 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
787 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
788 pxe_misc(mess, end, uuid);
790 prune_vendor_opts(tagif_netid);
792 opt71.opt = SUBOPT_PXE_BOOT_ITEM;
794 opt71.flags = DHOPT_VENDOR_MATCH;
796 opt71.next = daemon->dhcp_opts;
797 do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
799 log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);
800 return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
803 if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
805 pxearch = option_uint(opt, 0, 2);
807 /* proxy DHCP here. */
808 if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
810 struct dhcp_context *tmp;
812 for (tmp = context; tmp; tmp = tmp->current)
813 if ((tmp->flags & CONTEXT_PROXY) &&
814 match_netid(tmp->filter, tagif_netid, 1))
819 struct dhcp_boot *boot = find_boot(tagif_netid);
821 mess->yiaddr.s_addr = 0;
822 if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
824 mess->ciaddr.s_addr = 0;
825 mess->flags |= htons(0x8000); /* broadcast */
828 clear_packet(mess, end);
830 /* Provide the bootfile here, for gPXE, and in case we have no menu items
831 and set discovery_control = 8 */
834 if (boot->next_server.s_addr)
835 mess->siaddr = boot->next_server;
838 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
841 option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
842 mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
843 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
844 pxe_misc(mess, end, uuid);
845 prune_vendor_opts(tagif_netid);
846 do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
848 log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid);
849 return ignore ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
855 /* if we're just a proxy server, go no further */
856 if ((context->flags & CONTEXT_PROXY) || pxe)
859 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
861 req_options = (unsigned char *)daemon->dhcp_buff2;
862 memcpy(req_options, option_ptr(opt, 0), option_len(opt));
863 req_options[option_len(opt)] = OPTION_END;
869 if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
870 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
873 /* sanitise any message. Paranoid? Moi? */
874 sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
876 if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
879 log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid);
881 if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
882 lease_prune(lease, now);
884 if (have_config(config, CONFIG_ADDR) &&
885 config->addr.s_addr == option_addr(opt).s_addr)
887 prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
888 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
889 inet_ntoa(config->addr), daemon->dhcp_buff);
890 config->flags |= CONFIG_DECLINED;
891 config->decline_time = now;
894 /* make sure this host gets a different address next time. */
895 for (; context; context = context->current)
896 context->addr_epoch++;
901 if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
902 !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
903 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
906 if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
907 lease_prune(lease, now);
909 message = _("unknown lease");
911 log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
916 if (ignore || have_config(config, CONFIG_DISABLE))
918 message = _("ignored");
923 struct in_addr addr, conf;
925 addr.s_addr = conf.s_addr = 0;
927 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
928 addr = option_addr(opt);
930 if (have_config(config, CONFIG_ADDR))
932 char *addrs = inet_ntoa(config->addr);
934 if ((ltmp = lease_find_by_addr(config->addr)) &&
936 !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
939 unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
940 ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
941 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
942 addrs, print_mac(daemon->namebuff, mac, len));
946 struct dhcp_context *tmp;
947 for (tmp = context; tmp; tmp = tmp->current)
948 if (context->router.s_addr == config->addr.s_addr)
951 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
952 else if (have_config(config, CONFIG_DECLINED) &&
953 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
954 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
963 address_available(context, lease->addr, tagif_netid) &&
964 !config_find_by_address(daemon->dhcp_conf, lease->addr))
965 mess->yiaddr = lease->addr;
966 else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
967 !config_find_by_address(daemon->dhcp_conf, addr))
969 else if (emac_len == 0)
970 message = _("no unique-id");
971 else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
972 message = _("no address available");
975 log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid);
977 if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
980 log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
982 if (context->netid.net)
984 context->netid.next = netid;
985 netid = &context->netid;
986 tagif_netid = run_tag_if(netid);
989 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
990 clear_packet(mess, end);
991 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
992 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
993 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
994 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
995 if (time != 0xffffffff)
997 option_put(mess, end, OPTION_T1, 4, (time/2));
998 option_put(mess, end, OPTION_T2, 4, (time*7)/8);
1000 do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
1001 domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
1003 return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
1006 if (ignore || have_config(config, CONFIG_DISABLE))
1008 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1010 /* SELECTING or INIT_REBOOT */
1011 mess->yiaddr = option_addr(opt);
1013 /* send vendor and user class info for new or recreated lease */
1016 if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
1021 if (override.s_addr != 0)
1023 if (option_addr(opt).s_addr != override.s_addr)
1028 for (; context; context = context->current)
1029 if (context->local.s_addr == option_addr(opt).s_addr)
1034 /* In auth mode, a REQUEST sent to the wrong server
1035 should be faulted, so that the client establishes
1036 communication with us, otherwise, silently ignore. */
1037 if (!option_bool(OPT_AUTHORITATIVE))
1039 message = _("wrong server-ID");
1043 /* If a lease exists for this host and another address, squash it. */
1044 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1046 lease_prune(lease, now);
1053 if (!lease && !option_bool(OPT_AUTHORITATIVE))
1056 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1057 message = _("wrong address");
1062 /* RENEWING or REBINDING */
1063 /* Check existing lease for this address.
1064 We allow it to be missing if dhcp-authoritative mode
1065 as long as we can allocate the lease now - checked below.
1066 This makes for a smooth recovery from a lost lease DB */
1067 if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1068 (!lease && !option_bool(OPT_AUTHORITATIVE)))
1070 /* A client rebinding will broadcast the request, so we may see it even
1071 if the lease is held by another server. Just ignore it in that case.
1072 If the request is unicast to us, then somethings wrong, NAK */
1075 message = _("lease not found");
1076 /* ensure we broadcast NAK */
1080 /* desynchronise renewals */
1082 mess->yiaddr = mess->ciaddr;
1085 log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
1089 struct dhcp_config *addr_config;
1090 struct dhcp_context *tmp = NULL;
1092 if (have_config(config, CONFIG_ADDR))
1093 for (tmp = context; tmp; tmp = tmp->current)
1094 if (context->router.s_addr == config->addr.s_addr)
1097 if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1099 /* If a machine moves networks whilst it has a lease, we catch that here. */
1100 message = _("wrong network");
1101 /* ensure we broadcast NAK */
1105 /* Check for renewal of a lease which is outside the allowed range. */
1106 else if (!address_available(context, mess->yiaddr, tagif_netid) &&
1107 (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1108 message = _("address not available");
1110 /* Check if a new static address has been configured. Be very sure that
1111 when the client does DISCOVER, it will get the static address, otherwise
1112 an endless protocol loop will ensue. */
1113 else if (!tmp && !selecting &&
1114 have_config(config, CONFIG_ADDR) &&
1115 (!have_config(config, CONFIG_DECLINED) ||
1116 difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1117 config->addr.s_addr != mess->yiaddr.s_addr &&
1118 (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1119 message = _("static lease available");
1121 /* Check to see if the address is reserved as a static address for another host */
1122 else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1123 message = _("address reserved");
1125 else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1127 /* If a host is configured with more than one MAC address, it's OK to 'nix
1128 a lease from one of it's MACs to give the address to another. */
1129 if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1131 my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1132 print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
1133 inet_ntoa(ltmp->addr));
1137 message = _("address in use");
1143 message = _("no unique-id");
1147 if ((lease = lease_allocate(mess->yiaddr)))
1150 message = _("no leases left");
1157 log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid);
1159 mess->yiaddr.s_addr = 0;
1160 clear_packet(mess, end);
1161 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1162 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1163 option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1164 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1165 a distant subnet which unicast a REQ to us won't work. */
1166 if (!unicast_dest || mess->giaddr.s_addr != 0 ||
1167 mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1169 mess->flags |= htons(0x8000); /* broadcast */
1170 mess->ciaddr.s_addr = 0;
1175 if (context->netid.net)
1177 context->netid.next = netid;
1178 netid = &context->netid;
1179 tagif_netid = run_tag_if(netid);
1183 if (do_classes && daemon->lease_change_command)
1185 struct dhcp_netid *n;
1187 if (mess->giaddr.s_addr)
1188 lease->giaddr = mess->giaddr;
1191 free(lease->extradata);
1192 lease->extradata = NULL;
1193 lease->extradata_size = lease->extradata_len = 0;
1195 add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
1196 add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
1197 add_extradata_opt(lease, oui);
1198 add_extradata_opt(lease, serial);
1199 add_extradata_opt(lease, class);
1201 /* space-concat tag set */
1203 add_extradata_opt(lease, NULL);
1205 for (n = tagif_netid; n; n = n->next)
1206 add_extradata_data(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
1208 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1210 int len = option_len(opt);
1211 unsigned char *ucp = option_ptr(opt, 0);
1212 /* If the user-class option started as counted strings, the first byte will be zero. */
1213 if (len != 0 && ucp[0] == 0)
1215 add_extradata_data(lease, ucp, len, 0);
1220 if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1222 domain = get_domain(mess->yiaddr);
1223 hostname = client_hostname;
1227 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1228 lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len);
1230 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1233 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1234 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1240 /* Last ditch, if configured, generate hostname from mac address */
1241 if (!hostname && emac_len != 0)
1243 for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
1244 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1250 hostname = daemon->dhcp_buff;
1251 /* buffer is 256 bytes, 3 bytes per octet */
1252 for (i = 0; (i < emac_len) && (i < 80); i++)
1253 hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
1254 hostname = daemon->dhcp_buff;
1259 lease_set_hostname(lease, hostname, hostname_auth);
1261 lease_set_expires(lease, time, now);
1262 lease_set_interface(lease, int_index);
1264 if (override.s_addr != 0)
1265 lease->override = override;
1267 override = lease->override;
1269 log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid);
1270 if (difftime(now, old_time) > 7)
1271 emit_dbus_signal(ACTION_CONNECT, lease, hostname);
1274 clear_packet(mess, end);
1275 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1276 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1277 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1278 if (time != 0xffffffff)
1280 while (fuzz > (time/16))
1282 option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
1283 option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
1285 do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
1286 domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
1289 return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
1292 if (ignore || have_config(config, CONFIG_DISABLE))
1293 message = _("ignored");
1295 log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
1297 if (message || mess->ciaddr.s_addr == 0)
1300 /* For DHCPINFORM only, cope without a valid context */
1301 context = narrow_context(context, mess->ciaddr, tagif_netid);
1303 /* Find a least based on IP address if we didn't
1304 get one from MAC address/client-d */
1306 (lease = lease_find_by_addr(mess->ciaddr)) &&
1308 hostname = lease->hostname;
1310 if (!hostname && (hostname = host_from_dns(mess->ciaddr)))
1311 domain = get_domain(mess->ciaddr);
1313 log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);
1315 if (context && context->netid.net)
1317 context->netid.next = netid;
1318 netid = &context->netid;
1319 tagif_netid = run_tag_if(netid);
1324 if (override.s_addr != 0)
1325 lease->override = override;
1327 override = lease->override;
1330 clear_packet(mess, end);
1331 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1332 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1336 if (lease->expires == 0)
1339 time = (unsigned int)difftime(lease->expires, now);
1340 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1341 lease_set_interface(lease, int_index);
1344 do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1345 domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
1347 *is_inform = 1; /* handle reply differently */
1348 return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
1354 static int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
1364 if (o->flags & DHOPT_HEX)
1366 if (memcmp_masked(o->val, p, o->len, o->u.wildcard_mask))
1370 for (i = 0; i <= (len - o->len); )
1372 if (memcmp(o->val, p + i, o->len) == 0)
1375 if (o->flags & DHOPT_STRING)
1385 /* find a good value to use as MAC address for logging and address-allocation hashing.
1386 This is normally just the chaddr field from the DHCP packet,
1387 but eg Firewire will have hlen == 0 and use the client-id instead.
1388 This could be anything, but will normally be EUI64 for Firewire.
1389 We assume that if the first byte of the client-id equals the htype byte
1390 then the client-id is using the usual encoding and use the rest of the
1391 client-id: if not we can use the whole client-id. This should give
1392 sane MAC address logs. */
1393 unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
1394 int clid_len, unsigned char *clid, int *len_out)
1396 if (hwlen == 0 && clid && clid_len > 3)
1398 if (clid[0] == hwtype)
1400 *len_out = clid_len - 1 ;
1404 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1405 if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1407 *len_out = clid_len - 1 ;
1412 *len_out = clid_len;
1420 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1422 unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1426 unsigned int req_time = option_uint(opt, 0, 4);
1427 if (req_time < 120 )
1428 req_time = 120; /* sanity */
1429 if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1436 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1438 if (override.s_addr != 0)
1441 return context->local;
1446 static int sanitise(unsigned char *opt, char *buf)
1456 p = option_ptr(opt, 0);
1458 for (i = option_len(opt); i > 0; i--)
1461 if (isprint((int)c))
1464 *buf = 0; /* add terminator */
1470 static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim)
1472 if ((lease->extradata_size - lease->extradata_len) < (len + 1))
1474 size_t newsz = lease->extradata_len + len + 100;
1475 unsigned char *new = whine_malloc(newsz);
1480 if (lease->extradata)
1482 memcpy(new, lease->extradata, lease->extradata_len);
1483 free(lease->extradata);
1486 lease->extradata = new;
1487 lease->extradata_size = newsz;
1491 memcpy(lease->extradata + lease->extradata_len, data, len);
1492 lease->extradata[lease->extradata_len + len] = delim;
1493 lease->extradata_len += len + 1;
1496 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
1499 add_extradata_data(lease, NULL, 0, 0);
1502 size_t i, len = option_len(opt);
1503 unsigned char *ucp = option_ptr(opt, 0);
1505 /* check for embeded NULLs */
1506 for (i = 0; i < len; i++)
1513 add_extradata_data(lease, ucp, len, 0);
1518 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
1519 int mac_len, char *interface, char *string, u32 xid)
1523 /* addr may be misaligned */
1525 memcpy(&a, addr, sizeof(a));
1527 print_mac(daemon->namebuff, ext_mac, mac_len);
1529 if(option_bool(OPT_LOG_OPTS))
1530 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s",
1534 addr ? inet_ntoa(a) : "",
1537 string ? string : "");
1539 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s",
1542 addr ? inet_ntoa(a) : "",
1545 string ? string : "");
1548 static void log_options(unsigned char *start, u32 xid)
1550 while (*start != OPTION_END)
1552 int is_ip, is_name, i;
1553 char *text = option_string(start[0], &is_ip, &is_name);
1554 unsigned char trunc = option_len(start);
1557 for (daemon->namebuff[0]= 0, i = 0; i <= trunc - INADDRSZ; i += INADDRSZ)
1560 strncat(daemon->namebuff, ", ", 256 - strlen(daemon->namebuff));
1561 strncat(daemon->namebuff, inet_ntoa(option_addr_arr(start, i)), 256 - strlen(daemon->namebuff));
1563 else if (!is_name || !sanitise(start, daemon->namebuff))
1567 print_mac(daemon->namebuff, option_ptr(start, 0), trunc);
1570 my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d%s%s%s%s%s",
1571 ntohl(xid), option_len(start), start[0],
1572 text ? ":" : "", text ? text : "",
1573 trunc == 0 ? "" : " ",
1574 trunc == 0 ? "" : daemon->namebuff,
1575 trunc == option_len(start) ? "" : "...");
1576 start += start[1] + 2;
1580 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1586 else if (*p == OPTION_END)
1587 return opt == OPTION_END ? p : NULL;
1588 else if (*p == OPTION_PAD)
1594 return NULL; /* malformed packet */
1595 opt_len = option_len(p);
1596 if (p > end - (2 + opt_len))
1597 return NULL; /* malformed packet */
1598 if (*p == opt && opt_len >= minsize)
1605 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1607 unsigned char *ret, *overload;
1609 /* skip over DHCP cookie; */
1610 if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1613 /* look for overload option. */
1614 if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1617 /* Can we look in filename area ? */
1618 if ((overload[2] & 1) &&
1619 (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1622 /* finally try sname area */
1623 if ((overload[2] & 2) &&
1624 (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1630 static struct in_addr option_addr_arr(unsigned char *opt, int offset)
1632 /* this worries about unaligned data in the option. */
1633 /* struct in_addr is network byte order */
1636 memcpy(&ret, option_ptr(opt, offset), INADDRSZ);
1641 static struct in_addr option_addr(unsigned char *opt)
1643 return option_addr_arr(opt, 0);
1646 static unsigned int option_uint(unsigned char *opt, int offset, int size)
1648 /* this worries about unaligned data and byte order */
1649 unsigned int ret = 0;
1651 unsigned char *p = option_ptr(opt, offset);
1653 for (i = 0; i < size; i++)
1654 ret = (ret << 8) | *p++;
1659 static unsigned char *dhcp_skip_opts(unsigned char *start)
1662 start += start[1] + 2;
1666 /* only for use when building packet: doesn't check for bad data. */
1667 static unsigned char *find_overload(struct dhcp_packet *mess)
1669 unsigned char *p = &mess->options[0] + sizeof(u32);
1673 if (*p == OPTION_OVERLOAD)
1680 static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid,
1681 unsigned char *agent_id, unsigned char *real_end)
1683 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1684 unsigned char *overload;
1686 struct dhcp_netid_list *id_list;
1687 struct dhcp_netid *n;
1689 /* move agent_id back down to the end of the packet */
1692 memmove(p, agent_id, real_end - agent_id);
1693 p += real_end - agent_id;
1694 memset(p, 0, real_end - p); /* in case of overlap */
1697 /* We do logging too */
1698 if (netid && option_bool(OPT_LOG_OPTS))
1700 char *s = daemon->namebuff;
1701 for (*s = 0; netid; netid = netid->next)
1704 for (n = netid->next; n; n = n->next)
1705 if (strcmp(netid->net, n->net) == 0)
1710 strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
1712 strncat (s, ", ", (MAXDNAME-1) - strlen(s));
1715 my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s);
1718 /* add END options to the regions. */
1719 overload = find_overload(mess);
1721 if (overload && (option_uint(overload, 0, 1) & 1))
1723 *dhcp_skip_opts(mess->file) = OPTION_END;
1724 if (option_bool(OPT_LOG_OPTS))
1725 log_options(mess->file, mess->xid);
1727 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1728 my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1730 if (overload && (option_uint(overload, 0, 1) & 2))
1732 *dhcp_skip_opts(mess->sname) = OPTION_END;
1733 if (option_bool(OPT_LOG_OPTS))
1734 log_options(mess->sname, mess->xid);
1736 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1737 my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1742 for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
1743 if ((!id_list->list) || match_netid(id_list->list, netid, 0))
1746 mess->flags |= htons(0x8000); /* force broadcast */
1748 if (option_bool(OPT_LOG_OPTS))
1750 if (mess->siaddr.s_addr != 0)
1751 my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
1753 if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
1754 my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
1756 log_options(&mess->options[0] + sizeof(u32), mess->xid);
1759 ret = (size_t)(p - (unsigned char *)mess);
1761 if (ret < MIN_PACKETSZ)
1767 static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1769 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1771 if (p + len + 3 >= end)
1772 /* not enough space in options area, try and use overload, if poss */
1774 unsigned char *overload;
1776 if (!(overload = find_overload(mess)) &&
1777 (mess->file[0] == 0 || mess->sname[0] == 0))
1779 /* attempt to overload fname and sname areas, we've reserved space for the
1780 overflow option previuously. */
1782 *(p++) = OPTION_OVERLOAD;
1788 /* using filename field ? */
1791 if (mess->file[0] == 0)
1794 if (overload[2] & 1)
1796 p = dhcp_skip_opts(mess->file);
1797 if (p + len + 3 >= mess->file + sizeof(mess->file))
1803 /* try to bring sname into play (it may be already) */
1804 if (mess->sname[0] == 0)
1807 if (overload[2] & 2)
1809 p = dhcp_skip_opts(mess->sname);
1810 if (p + len + 3 >= mess->sname + sizeof(mess->file))
1817 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1829 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1832 unsigned char *p = free_space(mess, end, opt, len);
1835 for (i = 0; i < len; i++)
1836 *(p++) = val >> (8 * (len - (i + 1)));
1839 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
1840 char *string, int null_term)
1843 size_t len = strlen(string);
1845 if (null_term && len != 255)
1848 if ((p = free_space(mess, end, opt, len)))
1849 memcpy(p, string, len);
1852 /* return length, note this only does the data part */
1853 static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1857 if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1862 if (context && (opt->flags & DHOPT_ADDR))
1865 struct in_addr *a = (struct in_addr *)opt->val;
1866 for (j = 0; j < opt->len; j+=INADDRSZ, a++)
1868 /* zero means "self" (but not in vendorclass options.) */
1870 memcpy(p, &context->local, INADDRSZ);
1872 memcpy(p, a, INADDRSZ);
1877 memcpy(p, opt->val, len);
1882 static int in_list(unsigned char *list, int opt)
1886 /* If no requested options, send everything, not nothing. */
1890 for (i = 0; list[i] != OPTION_END; i++)
1897 static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *opts, int opt)
1899 struct dhcp_opt *tmp;
1900 for (tmp = opts; tmp; tmp = tmp->next)
1901 if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1902 if (match_netid(tmp->netid, netid, 0))
1905 /* No match, look for one without a netid */
1906 for (tmp = opts; tmp; tmp = tmp->next)
1907 if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1908 if (match_netid(tmp->netid, netid, 1))
1914 /* mark vendor-encapsulated options which match the client-supplied or
1915 config-supplied vendor class */
1916 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
1918 for (; dopt; dopt = dopt->next)
1920 dopt->flags &= ~DHOPT_VENDOR_MATCH;
1921 if (opt && (dopt->flags & DHOPT_VENDOR))
1924 if (dopt->u.vendor_class)
1925 len = strlen((char *)dopt->u.vendor_class);
1926 for (i = 0; i <= (option_len(opt) - len); i++)
1927 if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
1929 dopt->flags |= DHOPT_VENDOR_MATCH;
1936 static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
1937 struct dhcp_packet *mess, unsigned char *end, int null_term)
1939 int len, enc_len, ret = 0;
1940 struct dhcp_opt *start;
1943 /* find size in advance */
1944 for (enc_len = 0, start = opt; opt; opt = opt->next)
1945 if (opt->flags & flag)
1947 int new = do_opt(opt, NULL, NULL, null_term) + 2;
1949 if (enc_len + new <= 255)
1953 p = free_space(mess, end, encap, enc_len);
1954 for (; start && start != opt; start = start->next)
1955 if (p && (start->flags & flag))
1957 len = do_opt(start, p + 2, NULL, null_term);
1958 *(p++) = start->opt;
1968 (p = free_space(mess, end, encap, enc_len + 1)))
1970 for (; start; start = start->next)
1971 if (start->flags & flag)
1973 len = do_opt(start, p + 2, NULL, null_term);
1974 *(p++) = start->opt;
1984 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
1988 option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
1989 if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
1990 memcpy(p, uuid, 17);
1993 static int prune_vendor_opts(struct dhcp_netid *netid)
1996 struct dhcp_opt *opt;
1998 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1999 for (opt = daemon->dhcp_opts; opt; opt = opt->next)
2000 if (opt->flags & DHOPT_VENDOR_MATCH)
2002 if (!match_netid(opt->netid, netid, 1))
2003 opt->flags &= ~DHOPT_VENDOR_MATCH;
2004 else if (opt->flags & DHOPT_FORCE)
2010 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local)
2014 unsigned char *p, *q;
2015 struct pxe_service *service;
2016 static struct dhcp_opt *o, *ret;
2017 int i, j = NUM_OPTS - 1;
2018 struct in_addr boot_server;
2020 /* We pass back references to these, hence they are declared static */
2021 static unsigned char discovery_control;
2022 static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' };
2023 static struct dhcp_opt *fake_opts = NULL;
2025 /* Disable multicast, since we don't support it, and broadcast
2026 unless we need it */
2027 discovery_control = 3;
2029 ret = daemon->dhcp_opts;
2031 if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
2034 for (i = 0; i < NUM_OPTS; i++)
2036 fake_opts[i].flags = DHOPT_VENDOR_MATCH;
2037 fake_opts[i].netid = NULL;
2038 fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
2041 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2042 p = (unsigned char *)daemon->dhcp_buff;
2043 q = (unsigned char *)daemon->dhcp_buff3;
2045 for (i = 0, service = daemon->pxe_services; service; service = service->next)
2046 if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
2048 size_t len = strlen(service->menu);
2049 /* opt 43 max size is 255. encapsulated option has type and length
2050 bytes, so its max size is 253. */
2051 if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
2053 *(p++) = service->type >> 8;
2054 *(p++) = service->type;
2056 memcpy(p, service->menu, len);
2063 my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
2064 return daemon->dhcp_opts;
2067 boot_server = service->basename ? local : service->server;
2069 if (boot_server.s_addr != 0)
2071 if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
2074 /* Boot service with known address - give it */
2075 *(q++) = service->type >> 8;
2076 *(q++) = service->type;
2078 /* dest misaligned */
2079 memcpy(q, &boot_server.s_addr, INADDRSZ);
2082 else if (service->type != 0)
2083 /* We don't know the server for a service type, so we'll
2084 allow the client to broadcast for it */
2085 discovery_control = 2;
2088 /* if no prompt, wait forever if there's a choice */
2089 fake_prompt[0] = (i > 1) ? 255 : 0;
2092 discovery_control = 8; /* no menu - just use use mess->filename */
2095 ret = &fake_opts[j--];
2096 ret->len = p - (unsigned char *)daemon->dhcp_buff;
2097 ret->val = (unsigned char *)daemon->dhcp_buff;
2098 ret->opt = SUBOPT_PXE_MENU;
2100 if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
2102 ret = &fake_opts[j--];
2103 ret->len = q - (unsigned char *)daemon->dhcp_buff3;
2104 ret->val = (unsigned char *)daemon->dhcp_buff3;
2105 ret->opt = SUBOPT_PXE_SERVERS;
2109 for (o = daemon->dhcp_opts; o; o = o->next)
2110 if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
2115 ret = &fake_opts[j--];
2116 ret->len = sizeof(fake_prompt);
2117 ret->val = fake_prompt;
2118 ret->opt = SUBOPT_PXE_MENU_PROMPT;
2121 ret = &fake_opts[j--];
2123 ret->opt = SUBOPT_PXE_DISCOVERY;
2124 ret->val= &discovery_control;
2129 static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
2131 memset(mess->sname, 0, sizeof(mess->sname));
2132 memset(mess->file, 0, sizeof(mess->file));
2133 memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
2134 mess->siaddr.s_addr = 0;
2137 struct dhcp_boot *find_boot(struct dhcp_netid *netid)
2139 struct dhcp_boot *boot;
2141 /* decide which dhcp-boot option we're using */
2142 for (boot = daemon->boot_config; boot; boot = boot->next)
2143 if (match_netid(boot->netid, netid, 0))
2146 /* No match, look for one without a netid */
2147 for (boot = daemon->boot_config; boot; boot = boot->next)
2148 if (match_netid(boot->netid, netid, 1))
2154 static void do_options(struct dhcp_context *context,
2155 struct dhcp_packet *mess,
2157 unsigned char *req_options,
2159 char *domain, char *config_domain,
2160 struct dhcp_netid *netid,
2161 struct in_addr subnet_addr,
2162 unsigned char fqdn_flags,
2163 int null_term, int pxe_arch,
2164 unsigned char *uuid,
2165 int vendor_class_len)
2167 struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2168 struct dhcp_boot *boot;
2170 int i, len, force_encap = 0;
2171 unsigned char f0 = 0, s0 = 0;
2172 int done_file = 0, done_server = 0;
2173 int done_vendor_class = 0;
2175 if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
2176 my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname);
2179 if (option_bool(OPT_LOG_OPTS) && req_options)
2181 char *q = daemon->namebuff;
2182 for (i = 0; req_options[i] != OPTION_END; i++)
2184 char *s = option_string(req_options[i], NULL, NULL);
2185 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2190 req_options[i+1] == OPTION_END ? "" : ", ");
2191 if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2193 q = daemon->namebuff;
2194 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2200 mess->siaddr = context->local;
2202 /* See if we can send the boot stuff as options.
2203 To do this we need a requested option list, BOOTP
2204 and very old DHCP clients won't have this, we also
2205 provide an manual option to disable it.
2206 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2207 names, so we always send those. */
2208 if ((boot = find_boot(netid)))
2212 if (!option_bool(OPT_NO_OVERRIDE) &&
2214 in_list(req_options, OPTION_SNAME))
2215 option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2217 strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
2222 if (!option_bool(OPT_NO_OVERRIDE) &&
2224 in_list(req_options, OPTION_FILENAME))
2225 option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2227 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
2230 if (boot->next_server.s_addr)
2231 mess->siaddr = boot->next_server;
2234 /* Use the values of the relevant options if no dhcp-boot given and
2235 they're not explicitly asked for as options. OPTION_END is used
2236 as an internal way to specify siaddr without using dhcp-boot, for use in
2239 if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
2240 (opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2242 strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
2246 if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2247 (opt = option_find2(netid, config_opts, OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2249 strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
2253 if ((opt = option_find2(netid, config_opts, OPTION_END)))
2254 mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
2257 /* We don't want to do option-overload for BOOTP, so make the file and sname
2258 fields look like they are in use, even when they aren't. This gets restored
2259 at the end of this function. */
2261 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2265 s0 = mess->sname[0];
2269 /* At this point, if mess->sname or mess->file are zeroed, they are available
2270 for option overload, reserve space for the overload option. */
2271 if (mess->file[0] == 0 || mess->sname[0] == 0)
2274 /* rfc3011 says this doesn't need to be in the requested options list. */
2275 if (subnet_addr.s_addr)
2276 option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2278 /* replies to DHCPINFORM may not have a valid context */
2281 if (!option_find2(netid, config_opts, OPTION_NETMASK))
2282 option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2284 /* May not have a "guessed" broadcast address if we got no packets via a relay
2285 from this net yet (ie just unicast renewals after a restart */
2286 if (context->broadcast.s_addr &&
2287 !option_find2(netid, config_opts, OPTION_BROADCAST))
2288 option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2290 /* Same comments as broadcast apply, and also may not be able to get a sensible
2291 default when using subnet select. User must configure by steam in that case. */
2292 if (context->router.s_addr &&
2293 in_list(req_options, OPTION_ROUTER) &&
2294 !option_find2(netid, config_opts, OPTION_ROUTER))
2295 option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2297 if (in_list(req_options, OPTION_DNSSERVER) &&
2298 !option_find2(netid, config_opts, OPTION_DNSSERVER))
2299 option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2302 if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
2303 !option_find2(netid, config_opts, OPTION_DOMAINNAME))
2304 option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2306 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2309 if (in_list(req_options, OPTION_HOSTNAME) &&
2310 !option_find2(netid, config_opts, OPTION_HOSTNAME))
2311 option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2313 if (fqdn_flags != 0)
2315 len = strlen(hostname) + 3;
2317 if (fqdn_flags & 0x04)
2323 len += strlen(domain) + 1;
2325 if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2327 *(p++) = fqdn_flags;
2331 if (fqdn_flags & 0x04)
2333 p = do_rfc1035_name(p, hostname);
2335 p = do_rfc1035_name(p, domain);
2340 memcpy(p, hostname, strlen(hostname));
2341 p += strlen(hostname);
2345 memcpy(p, domain, strlen(domain));
2346 p += strlen(domain);
2355 for (opt = config_opts; opt; opt = opt->next)
2357 int optno = opt->opt;
2359 /* was it asked for, or are we sending it anyway? */
2360 if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2363 /* prohibit some used-internally options */
2364 if (optno == OPTION_CLIENT_FQDN ||
2365 optno == OPTION_MAXMESSAGE ||
2366 optno == OPTION_OVERLOAD ||
2367 optno == OPTION_PAD ||
2368 optno == OPTION_END)
2371 if (optno == OPTION_SNAME && done_server)
2374 if (optno == OPTION_FILENAME && done_file)
2377 /* netids match and not encapsulated? */
2378 if (opt != option_find2(netid, config_opts, optno))
2381 /* For the options we have default values on
2382 dhc-option=<optionno> means "don't include this option"
2383 not "include a zero-length option" */
2384 if (opt->len == 0 &&
2385 (optno == OPTION_NETMASK ||
2386 optno == OPTION_BROADCAST ||
2387 optno == OPTION_ROUTER ||
2388 optno == OPTION_DNSSERVER ||
2389 optno == OPTION_DOMAINNAME ||
2390 optno == OPTION_HOSTNAME))
2393 /* vendor-class comes from elsewhere for PXE */
2394 if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2397 /* always force null-term for filename and servername - buggy PXE again. */
2398 len = do_opt(opt, NULL, context,
2399 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2401 if ((p = free_space(mess, end, optno, len)))
2403 do_opt(opt, p, context,
2404 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2406 /* If we send a vendor-id, revisit which vendor-ops we consider
2407 it appropriate to send. */
2408 if (optno == OPTION_VENDOR_ID)
2410 match_vendor_opts(p - 2, config_opts);
2411 done_vendor_class = 1;
2416 /* Now send options to be encapsulated in arbitrary options,
2417 eg dhcp-option=encap:172,17,.......
2418 Also hand vendor-identifying vendor-encapsulated options,
2419 dhcp-option = rfc3925-encap:13,17,.......
2420 The may be more that one "outer" to do, so group
2421 all the options which match each outer in turn. */
2422 for (opt = config_opts; opt; opt = opt->next)
2423 opt->flags &= ~DHOPT_ENCAP_DONE;
2425 for (opt = config_opts; opt; opt = opt->next)
2429 if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
2434 if (opt->flags & DHOPT_ENCAP_DONE)
2437 for (len = 0, o = config_opts; o; o = o->next)
2439 int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
2441 o->flags &= ~DHOPT_ENCAP_MATCH;
2443 if (!(o->flags & flags) || opt->u.encap != o->u.encap)
2446 o->flags |= DHOPT_ENCAP_DONE;
2447 if (match_netid(o->netid, netid, 1) &&
2448 ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
2450 o->flags |= DHOPT_ENCAP_MATCH;
2452 len += do_opt(o, NULL, NULL, 0) + 2;
2458 if (flags & DHOPT_ENCAPSULATE)
2459 do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2461 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
2462 else if ((p = free_space(mess, end, OPTION_VENDOR_IDENT_OPT, len + 5)))
2464 int swap_ent = htonl(opt->u.encap);
2465 memcpy(p, &swap_ent, 4);
2468 for (o = config_opts; o; o = o->next)
2469 if (o->flags & DHOPT_ENCAP_MATCH)
2471 len = do_opt(o, p + 2, NULL, 0);
2481 force_encap = prune_vendor_opts(netid);
2483 if (context && pxe_arch != -1)
2485 pxe_misc(mess, end, uuid);
2486 config_opts = pxe_opts(pxe_arch, netid, context->local);
2489 if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
2490 do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) &&
2491 pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
2492 (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
2493 /* If we send vendor encapsulated options, and haven't already sent option 60,
2494 echo back the value we got from the client. */
2495 memcpy(p, daemon->dhcp_buff3, vendor_class_len);
2497 /* restore BOOTP anti-overload hack */
2498 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2501 mess->sname[0] = s0;