Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnsmasq / src / rfc2131.c
blob50453b0893d4586e9cdf7f7a2b658b33fc0977f4
1 /* dnsmasq is Copyright (c) 2000-2013 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, 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);
58 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
59 static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
60 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
61 static int prune_vendor_opts(struct dhcp_netid *netid);
62 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
63 struct dhcp_boot *find_boot(struct dhcp_netid *netid);
66 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
67 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe, struct in_addr fallback)
69 unsigned char *opt, *clid = NULL;
70 struct dhcp_lease *ltmp, *lease = NULL;
71 struct dhcp_vendor *vendor;
72 struct dhcp_mac *mac;
73 struct dhcp_netid_list *id_list;
74 int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
75 struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
76 unsigned char *end = (unsigned char *)(mess + 1);
77 unsigned char *real_end = (unsigned char *)(mess + 1);
78 char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
79 int hostname_auth = 0, borken_opt = 0;
80 unsigned char *req_options = NULL;
81 char *message = NULL;
82 unsigned int time;
83 struct dhcp_config *config;
84 struct dhcp_netid *netid, *tagif_netid;
85 struct in_addr subnet_addr, override;
86 unsigned short fuzz = 0;
87 unsigned int mess_type = 0;
88 unsigned char fqdn_flags = 0;
89 unsigned char *agent_id = NULL, *uuid = NULL;
90 unsigned char *emac = NULL;
91 int vendor_class_len = 0, emac_len = 0;
92 struct dhcp_netid known_id, iface_id, cpewan_id;
93 struct dhcp_opt *o;
94 unsigned char pxe_uuid[17];
95 unsigned char *oui = NULL, *serial = NULL, *class = NULL;
97 subnet_addr.s_addr = override.s_addr = 0;
99 /* set tag with name == interface */
100 iface_id.net = iface_name;
101 iface_id.next = NULL;
102 netid = &iface_id;
104 if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
105 return 0;
107 if (mess->htype == 0 && mess->hlen != 0)
108 return 0;
110 /* check for DHCP rather than BOOTP */
111 if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
113 u32 cookie = htonl(DHCP_COOKIE);
115 /* only insist on a cookie for DHCP. */
116 if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
117 return 0;
119 mess_type = option_uint(opt, 0, 1);
121 /* two things to note here: expand_buf may move the packet,
122 so reassign mess from daemon->packet. Also, the size
123 sent includes the IP and UDP headers, hence the magic "-28" */
124 if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
126 size_t size = (size_t)option_uint(opt, 0, 2) - 28;
128 if (size > DHCP_PACKET_MAX)
129 size = DHCP_PACKET_MAX;
130 else if (size < sizeof(struct dhcp_packet))
131 size = sizeof(struct dhcp_packet);
133 if (expand_buf(&daemon->dhcp_packet, size))
135 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
136 real_end = end = ((unsigned char *)mess) + size;
140 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
141 it can affect the context-determination code. */
142 if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
143 mess->ciaddr.s_addr = 0;
145 /* search for device identity from CPEWAN devices, we pass this through to the script */
146 if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
148 unsigned int elen, offset, len = option_len(opt);
150 for (offset = 0; offset < (len - 5); offset += elen + 5)
152 elen = option_uint(opt, offset + 4 , 1);
153 if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
155 unsigned char *x = option_ptr(opt, offset + 5);
156 unsigned char *y = option_ptr(opt, offset + elen + 5);
157 oui = option_find1(x, y, 1, 1);
158 serial = option_find1(x, y, 2, 1);
159 class = option_find1(x, y, 3, 1);
161 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
162 the gateway id back. Note that the device class is optional */
163 if (oui && serial)
165 cpewan_id.net = "cpewan-id";
166 cpewan_id.next = netid;
167 netid = &cpewan_id;
169 break;
174 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
176 /* Any agent-id needs to be copied back out, verbatim, as the last option
177 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
178 get overwritten, then it will be shuffled back at the end of processing.
179 Note that the incoming options must not be overwritten here, so there has to
180 be enough free space at the end of the packet to copy the option. */
181 unsigned char *sopt;
182 unsigned int total = option_len(opt) + 2;
183 unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
184 if (last_opt && last_opt < end - total)
186 end -= total;
187 agent_id = end;
188 memcpy(agent_id, opt, total);
191 /* look for RFC3527 Link selection sub-option */
192 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
193 subnet_addr = option_addr(sopt);
195 /* look for RFC5107 server-identifier-override */
196 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
197 override = option_addr(sopt);
199 /* if a circuit-id or remote-is option is provided, exact-match to options. */
200 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
202 int search;
204 if (vendor->match_type == MATCH_CIRCUIT)
205 search = SUBOPT_CIRCUIT_ID;
206 else if (vendor->match_type == MATCH_REMOTE)
207 search = SUBOPT_REMOTE_ID;
208 else if (vendor->match_type == MATCH_SUBSCRIBER)
209 search = SUBOPT_SUBSCR_ID;
210 else
211 continue;
213 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
214 vendor->len == option_len(sopt) &&
215 memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
217 vendor->netid.next = netid;
218 netid = &vendor->netid;
223 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
224 if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
225 subnet_addr = option_addr(opt);
227 /* If there is no client identifier option, use the hardware address */
228 if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
230 clid_len = option_len(opt);
231 clid = option_ptr(opt, 0);
234 /* do we have a lease in store? */
235 lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
237 /* If this request is missing a clid, but we've seen one before,
238 use it again for option matching etc. */
239 if (lease && !clid && lease->clid)
241 clid_len = lease->clid_len;
242 clid = lease->clid;
245 /* find mac to use for logging and hashing */
246 emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
249 for (mac = daemon->dhcp_macs; mac; mac = mac->next)
250 if (mac->hwaddr_len == mess->hlen &&
251 (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
252 memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
254 mac->netid.next = netid;
255 netid = &mac->netid;
258 /* Determine network for this packet. Our caller will have already linked all the
259 contexts which match the addresses of the receiving interface but if the
260 machine has an address already, or came via a relay, or we have a subnet selector,
261 we search again. If we don't have have a giaddr or explicit subnet selector,
262 use the ciaddr. This is necessary because a machine which got a lease via a
263 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
264 from the physical network, continue using that to allow correct DHCPNAK generation later. */
265 if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
267 struct dhcp_context *context_tmp, *context_new = NULL;
268 struct in_addr addr;
269 int force = 0;
271 if (subnet_addr.s_addr)
273 addr = subnet_addr;
274 force = 1;
276 else if (mess->giaddr.s_addr)
278 addr = mess->giaddr;
279 force = 1;
281 else
283 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
284 addr = mess->ciaddr;
285 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
286 if (context_tmp->netmask.s_addr &&
287 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
288 is_same_net(addr, context_tmp->end, context_tmp->netmask))
290 context_new = context;
291 break;
295 if (!context_new)
296 for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
298 struct in_addr netmask = context_tmp->netmask;
300 /* guess the netmask for relayed networks */
301 if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
303 if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
304 netmask.s_addr = htonl(0xff000000);
305 else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
306 netmask.s_addr = htonl(0xffff0000);
307 else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
308 netmask.s_addr = htonl(0xffffff00);
311 /* This section fills in context mainly when a client which is on a remote (relayed)
312 network renews a lease without using the relay, after dnsmasq has restarted. */
313 if (netmask.s_addr != 0 &&
314 is_same_net(addr, context_tmp->start, netmask) &&
315 is_same_net(addr, context_tmp->end, netmask))
317 context_tmp->netmask = netmask;
318 if (context_tmp->local.s_addr == 0)
319 context_tmp->local = fallback;
320 if (context_tmp->router.s_addr == 0)
321 context_tmp->router = mess->giaddr;
323 /* fill in missing broadcast addresses for relayed ranges */
324 if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
325 context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
327 context_tmp->current = context_new;
328 context_new = context_tmp;
332 if (context_new || force)
333 context = context_new;
336 if (!context)
338 my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
339 subnet_addr.s_addr ? _("with subnet selector") : _("via"),
340 subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
341 return 0;
344 if (option_bool(OPT_LOG_OPTS))
346 struct dhcp_context *context_tmp;
347 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
349 strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
350 if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
351 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
352 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
353 else
354 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
355 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
359 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
360 Otherwise assume the option is an array, and look for a matching element.
361 If no data given, existance of the option is enough. This code handles
362 rfc3925 V-I classes too. */
363 for (o = daemon->dhcp_match; o; o = o->next)
365 unsigned int len, elen, match = 0;
366 size_t offset, o2;
368 if (o->flags & DHOPT_RFC3925)
370 if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
371 continue;
373 for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
375 len = option_uint(opt, offset + 4 , 1);
376 /* Need to take care that bad data can't run us off the end of the packet */
377 if ((offset + len + 5 <= (option_len(opt))) &&
378 (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
379 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
381 elen = option_uint(opt, o2, 1);
382 if ((o2 + elen + 1 <= option_len(opt)) &&
383 (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
384 break;
386 if (match)
387 break;
390 else
392 if (!(opt = option_find(mess, sz, o->opt, 1)))
393 continue;
395 match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
398 if (match)
400 o->netid->next = netid;
401 netid = o->netid;
405 /* user-class options are, according to RFC3004, supposed to contain
406 a set of counted strings. Here we check that this is so (by seeing
407 if the counts are consistent with the overall option length) and if
408 so zero the counts so that we don't get spurious matches between
409 the vendor string and the counts. If the lengths don't add up, we
410 assume that the option is a single string and non RFC3004 compliant
411 and just do the substring match. dhclient provides these broken options.
412 The code, later, which sends user-class data to the lease-change script
413 relies on the transformation done here.
416 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
418 unsigned char *ucp = option_ptr(opt, 0);
419 int tmp, j;
420 for (j = 0; j < option_len(opt); j += ucp[j] + 1);
421 if (j == option_len(opt))
422 for (j = 0; j < option_len(opt); j = tmp)
424 tmp = j + ucp[j] + 1;
425 ucp[j] = 0;
429 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
431 int mopt;
433 if (vendor->match_type == MATCH_VENDOR)
434 mopt = OPTION_VENDOR_ID;
435 else if (vendor->match_type == MATCH_USER)
436 mopt = OPTION_USER_CLASS;
437 else
438 continue;
440 if ((opt = option_find(mess, sz, mopt, 1)))
442 int i;
443 for (i = 0; i <= (option_len(opt) - vendor->len); i++)
444 if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
446 vendor->netid.next = netid;
447 netid = &vendor->netid;
448 break;
453 /* mark vendor-encapsulated options which match the client-supplied vendor class,
454 save client-supplied vendor class */
455 if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
457 memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
458 vendor_class_len = option_len(opt);
460 match_vendor_opts(opt, daemon->dhcp_opts);
462 if (option_bool(OPT_LOG_OPTS))
464 if (sanitise(opt, daemon->namebuff))
465 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
466 if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
467 my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
470 mess->op = BOOTREPLY;
472 config = find_config(daemon->dhcp_conf, context, clid, clid_len,
473 mess->chaddr, mess->hlen, mess->htype, NULL);
475 /* set "known" tag for known hosts */
476 if (config)
478 known_id.net = "known";
479 known_id.next = netid;
480 netid = &known_id;
483 if (mess_type == 0 && !pxe)
485 /* BOOTP request */
486 struct dhcp_netid id, bootp_id;
487 struct in_addr *logaddr = NULL;
489 /* must have a MAC addr for bootp */
490 if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
491 return 0;
493 if (have_config(config, CONFIG_DISABLE))
494 message = _("disabled");
496 end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
498 if (have_config(config, CONFIG_NAME))
500 hostname = config->hostname;
501 domain = config->domain;
504 if (config)
506 struct dhcp_netid_list *list;
508 for (list = config->netid; list; list = list->next)
510 list->list->next = netid;
511 netid = list->list;
515 /* Match incoming filename field as a netid. */
516 if (mess->file[0])
518 memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
519 daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
520 id.net = (char *)daemon->dhcp_buff2;
521 id.next = netid;
522 netid = &id;
525 /* Add "bootp" as a tag to allow different options, address ranges etc
526 for BOOTP clients */
527 bootp_id.net = "bootp";
528 bootp_id.next = netid;
529 netid = &bootp_id;
531 tagif_netid = run_tag_if(netid);
533 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
534 if (match_netid(id_list->list, tagif_netid, 0))
535 message = _("ignored");
537 if (!message)
539 int nailed = 0;
541 if (have_config(config, CONFIG_ADDR))
543 nailed = 1;
544 logaddr = &config->addr;
545 mess->yiaddr = config->addr;
546 if ((lease = lease_find_by_addr(config->addr)) &&
547 (lease->hwaddr_len != mess->hlen ||
548 lease->hwaddr_type != mess->htype ||
549 memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
550 message = _("address in use");
552 else
554 if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
555 !address_available(context, lease->addr, tagif_netid))
557 if (lease)
559 /* lease exists, wrong network. */
560 lease_prune(lease, now);
561 lease = NULL;
563 if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
564 message = _("no address available");
566 else
567 mess->yiaddr = lease->addr;
570 if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
571 message = _("wrong network");
572 else if (context->netid.net)
574 context->netid.next = netid;
575 tagif_netid = run_tag_if(&context->netid);
578 log_tags(tagif_netid, ntohl(mess->xid));
580 if (!message && !nailed)
582 for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
583 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
584 break;
585 if (!id_list)
586 message = _("no address configured");
589 if (!message &&
590 !lease &&
591 (!(lease = lease4_allocate(mess->yiaddr))))
592 message = _("no leases left");
594 if (!message)
596 logaddr = &mess->yiaddr;
598 lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
599 if (hostname)
600 lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain);
601 /* infinite lease unless nailed in dhcp-host line. */
602 lease_set_expires(lease,
603 have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
604 now);
605 lease_set_interface(lease, int_index, now);
607 clear_packet(mess, end);
608 do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
609 netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
613 log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
615 return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
618 if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
620 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
621 int len = option_len(opt);
622 char *pq = daemon->dhcp_buff;
623 unsigned char *pp, *op = option_ptr(opt, 0);
625 fqdn_flags = *op;
626 len -= 3;
627 op += 3;
628 pp = op;
630 /* NB, the following always sets at least one bit */
631 if (option_bool(OPT_FQDN_UPDATE))
633 if (fqdn_flags & 0x01)
635 fqdn_flags |= 0x02; /* set O */
636 fqdn_flags &= ~0x01; /* clear S */
638 fqdn_flags |= 0x08; /* set N */
640 else
642 if (!(fqdn_flags & 0x01))
643 fqdn_flags |= 0x03; /* set S and O */
644 fqdn_flags &= ~0x08; /* clear N */
647 if (fqdn_flags & 0x04)
648 while (*op != 0 && ((op + (*op) + 1) - pp) < len)
650 memcpy(pq, op+1, *op);
651 pq += *op;
652 op += (*op)+1;
653 *(pq++) = '.';
655 else
657 memcpy(pq, op, len);
658 if (len > 0 && op[len-1] == 0)
659 borken_opt = 1;
660 pq += len + 1;
663 if (pq != daemon->dhcp_buff)
664 pq--;
666 *pq = 0;
668 if (legal_hostname(daemon->dhcp_buff))
669 offer_hostname = client_hostname = daemon->dhcp_buff;
671 else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
673 int len = option_len(opt);
674 memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
675 /* Microsoft clients are broken, and need zero-terminated strings
676 in options. We detect this state here, and do the same in
677 any options we send */
678 if (len > 0 && daemon->dhcp_buff[len-1] == 0)
679 borken_opt = 1;
680 else
681 daemon->dhcp_buff[len] = 0;
682 if (legal_hostname(daemon->dhcp_buff))
683 client_hostname = daemon->dhcp_buff;
686 if (client_hostname && option_bool(OPT_LOG_OPTS))
687 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
689 if (have_config(config, CONFIG_NAME))
691 hostname = config->hostname;
692 domain = config->domain;
693 hostname_auth = 1;
694 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
695 if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
696 offer_hostname = hostname;
698 else if (client_hostname)
700 domain = strip_hostname(client_hostname);
702 if (strlen(client_hostname) != 0)
704 hostname = client_hostname;
705 if (!config)
707 /* Search again now we have a hostname.
708 Only accept configs without CLID and HWADDR here, (they won't match)
709 to avoid impersonation by name. */
710 struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
711 mess->chaddr, mess->hlen,
712 mess->htype, hostname);
713 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
715 config = new;
716 /* set "known" tag for known hosts */
717 known_id.net = "known";
718 known_id.next = netid;
719 netid = &known_id;
725 if (config)
727 struct dhcp_netid_list *list;
729 for (list = config->netid; list; list = list->next)
731 list->list->next = netid;
732 netid = list->list;
736 tagif_netid = run_tag_if(netid);
738 /* if all the netids in the ignore list are present, ignore this client */
739 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
740 if (match_netid(id_list->list, tagif_netid, 0))
741 ignore = 1;
743 /* If configured, we can override the server-id to be the address of the relay,
744 so that all traffic goes via the relay and can pick up agent-id info. This can be
745 configured for all relays, or by address. */
746 if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
748 if (!daemon->override_relays)
749 override = mess->giaddr;
750 else
752 struct addr_list *l;
753 for (l = daemon->override_relays; l; l = l->next)
754 if (l->addr.s_addr == mess->giaddr.s_addr)
755 break;
756 if (l)
757 override = mess->giaddr;
761 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
762 if (have_config(config, CONFIG_NOCLID))
763 clid = NULL;
765 /* Check if client is PXE client. */
766 if (daemon->enable_pxe &&
767 (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
768 strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
770 if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
772 memcpy(pxe_uuid, option_ptr(opt, 0), 17);
773 uuid = pxe_uuid;
776 /* Check if this is really a PXE bootserver request, and handle specially if so. */
777 if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
778 (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
779 (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
781 struct pxe_service *service;
782 int type = option_uint(opt, 0, 2);
783 int layer = option_uint(opt, 2, 2);
784 unsigned char save71[4];
785 struct dhcp_opt opt71;
787 if (ignore)
788 return 0;
790 if (layer & 0x8000)
792 my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
793 return 0;
796 memcpy(save71, option_ptr(opt, 0), 4);
798 for (service = daemon->pxe_services; service; service = service->next)
799 if (service->type == type)
800 break;
802 if (!service || !service->basename)
803 return 0;
805 clear_packet(mess, end);
807 mess->yiaddr = mess->ciaddr;
808 mess->ciaddr.s_addr = 0;
809 if (service->sname)
810 mess->siaddr = a_record_from_hosts(service->sname, now);
811 else if (service->server.s_addr != 0)
812 mess->siaddr = service->server;
813 else
814 mess->siaddr = context->local;
816 snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
817 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
818 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
819 pxe_misc(mess, end, uuid);
821 prune_vendor_opts(tagif_netid);
822 opt71.val = save71;
823 opt71.opt = SUBOPT_PXE_BOOT_ITEM;
824 opt71.len = 4;
825 opt71.flags = DHOPT_VENDOR_MATCH;
826 opt71.netid = NULL;
827 opt71.next = daemon->dhcp_opts;
828 do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
830 log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);
831 log_tags(tagif_netid, ntohl(mess->xid));
832 return dhcp_packet_size(mess, agent_id, real_end);
835 if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
837 pxearch = option_uint(opt, 0, 2);
839 /* proxy DHCP here. */
840 if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
842 struct dhcp_context *tmp;
844 for (tmp = context; tmp; tmp = tmp->current)
845 if ((tmp->flags & CONTEXT_PROXY) &&
846 match_netid(tmp->filter, tagif_netid, 1))
847 break;
849 if (tmp)
851 struct dhcp_boot *boot = find_boot(tagif_netid);
853 mess->yiaddr.s_addr = 0;
854 if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
856 mess->ciaddr.s_addr = 0;
857 mess->flags |= htons(0x8000); /* broadcast */
860 clear_packet(mess, end);
862 /* Provide the bootfile here, for gPXE, and in case we have no menu items
863 and set discovery_control = 8 */
864 if (boot)
866 if (boot->next_server.s_addr)
867 mess->siaddr = boot->next_server;
868 else if (boot->tftp_sname)
869 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
871 if (boot->file)
872 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
875 option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
876 mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
877 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
878 pxe_misc(mess, end, uuid);
879 prune_vendor_opts(tagif_netid);
880 do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
882 log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid);
883 log_tags(tagif_netid, ntohl(mess->xid));
884 return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
890 /* if we're just a proxy server, go no further */
891 if ((context->flags & CONTEXT_PROXY) || pxe)
892 return 0;
894 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
896 req_options = (unsigned char *)daemon->dhcp_buff2;
897 memcpy(req_options, option_ptr(opt, 0), option_len(opt));
898 req_options[option_len(opt)] = OPTION_END;
901 switch (mess_type)
903 case DHCPDECLINE:
904 if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
905 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
906 return 0;
908 /* sanitise any message. Paranoid? Moi? */
909 sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
911 if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
912 return 0;
914 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
915 if (!option_bool(OPT_QUIET_DHCP))
916 #endif
917 log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid);
919 if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
920 lease_prune(lease, now);
922 if (have_config(config, CONFIG_ADDR) &&
923 config->addr.s_addr == option_addr(opt).s_addr)
925 prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
926 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
927 inet_ntoa(config->addr), daemon->dhcp_buff);
928 config->flags |= CONFIG_DECLINED;
929 config->decline_time = now;
931 else
932 /* make sure this host gets a different address next time. */
933 for (; context; context = context->current)
934 context->addr_epoch++;
936 return 0;
938 case DHCPRELEASE:
939 if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
940 !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
941 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
942 return 0;
944 if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
945 lease_prune(lease, now);
946 else
947 message = _("unknown lease");
949 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
950 if (!option_bool(OPT_QUIET_DHCP))
951 #endif
952 log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
954 return 0;
956 case DHCPDISCOVER:
957 if (ignore || have_config(config, CONFIG_DISABLE))
959 message = _("ignored");
960 opt = NULL;
962 else
964 struct in_addr addr, conf;
966 addr.s_addr = conf.s_addr = 0;
968 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
969 addr = option_addr(opt);
971 if (have_config(config, CONFIG_ADDR))
973 char *addrs = inet_ntoa(config->addr);
975 if ((ltmp = lease_find_by_addr(config->addr)) &&
976 ltmp != lease &&
977 !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
979 int len;
980 unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
981 ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
982 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
983 addrs, print_mac(daemon->namebuff, mac, len));
985 else
987 struct dhcp_context *tmp;
988 for (tmp = context; tmp; tmp = tmp->current)
989 if (context->router.s_addr == config->addr.s_addr)
990 break;
991 if (tmp)
992 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
993 else if (have_config(config, CONFIG_DECLINED) &&
994 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
995 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
996 else
997 conf = config->addr;
1001 if (conf.s_addr)
1002 mess->yiaddr = conf;
1003 else if (lease &&
1004 address_available(context, lease->addr, tagif_netid) &&
1005 !config_find_by_address(daemon->dhcp_conf, lease->addr))
1006 mess->yiaddr = lease->addr;
1007 else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
1008 !config_find_by_address(daemon->dhcp_conf, addr))
1009 mess->yiaddr = addr;
1010 else if (emac_len == 0)
1011 message = _("no unique-id");
1012 else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
1013 message = _("no address available");
1016 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1017 if (!option_bool(OPT_QUIET_DHCP))
1018 #endif
1019 log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid);
1021 if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1022 return 0;
1024 if (context->netid.net)
1026 context->netid.next = netid;
1027 tagif_netid = run_tag_if(&context->netid);
1030 log_tags(tagif_netid, ntohl(mess->xid));
1032 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1033 if (!option_bool(OPT_QUIET_DHCP))
1034 #endif
1035 log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
1037 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1038 clear_packet(mess, end);
1039 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
1040 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1041 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1042 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1043 if (time != 0xffffffff)
1045 option_put(mess, end, OPTION_T1, 4, (time/2));
1046 option_put(mess, end, OPTION_T2, 4, (time*7)/8);
1048 do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
1049 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
1051 return dhcp_packet_size(mess, agent_id, real_end);
1053 case DHCPREQUEST:
1054 if (ignore || have_config(config, CONFIG_DISABLE))
1055 return 0;
1056 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1058 /* SELECTING or INIT_REBOOT */
1059 mess->yiaddr = option_addr(opt);
1061 /* send vendor and user class info for new or recreated lease */
1062 do_classes = 1;
1064 if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
1066 /* SELECTING */
1067 selecting = 1;
1069 if (override.s_addr != 0)
1071 if (option_addr(opt).s_addr != override.s_addr)
1072 return 0;
1074 else
1076 for (; context; context = context->current)
1077 if (context->local.s_addr == option_addr(opt).s_addr)
1078 break;
1080 if (!context)
1082 /* Handle very strange configs where clients have more than one route to the server.
1083 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1084 Have to set override to make sure we echo back the correct server-id */
1085 struct irec *intr;
1087 enumerate_interfaces(0);
1089 for (intr = daemon->interfaces; intr; intr = intr->next)
1090 if (intr->addr.sa.sa_family == AF_INET &&
1091 intr->addr.in.sin_addr.s_addr == option_addr(opt).s_addr &&
1092 intr->tftp_ok)
1093 break;
1095 if (intr)
1096 override = intr->addr.in.sin_addr;
1097 else
1099 /* In auth mode, a REQUEST sent to the wrong server
1100 should be faulted, so that the client establishes
1101 communication with us, otherwise, silently ignore. */
1102 if (!option_bool(OPT_AUTHORITATIVE))
1103 return 0;
1104 message = _("wrong server-ID");
1109 /* If a lease exists for this host and another address, squash it. */
1110 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1112 lease_prune(lease, now);
1113 lease = NULL;
1116 else
1118 /* INIT-REBOOT */
1119 if (!lease && !option_bool(OPT_AUTHORITATIVE))
1120 return 0;
1122 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1123 message = _("wrong address");
1126 else
1128 /* RENEWING or REBINDING */
1129 /* Check existing lease for this address.
1130 We allow it to be missing if dhcp-authoritative mode
1131 as long as we can allocate the lease now - checked below.
1132 This makes for a smooth recovery from a lost lease DB */
1133 if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1134 (!lease && !option_bool(OPT_AUTHORITATIVE)))
1136 /* A client rebinding will broadcast the request, so we may see it even
1137 if the lease is held by another server. Just ignore it in that case.
1138 If the request is unicast to us, then somethings wrong, NAK */
1139 if (!unicast_dest)
1140 return 0;
1141 message = _("lease not found");
1142 /* ensure we broadcast NAK */
1143 unicast_dest = 0;
1146 /* desynchronise renewals */
1147 fuzz = rand16();
1148 mess->yiaddr = mess->ciaddr;
1151 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1152 if (!option_bool(OPT_QUIET_DHCP))
1153 #endif
1154 log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
1156 if (!message)
1158 struct dhcp_config *addr_config;
1159 struct dhcp_context *tmp = NULL;
1161 if (have_config(config, CONFIG_ADDR))
1162 for (tmp = context; tmp; tmp = tmp->current)
1163 if (context->router.s_addr == config->addr.s_addr)
1164 break;
1166 if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1168 /* If a machine moves networks whilst it has a lease, we catch that here. */
1169 message = _("wrong network");
1170 /* ensure we broadcast NAK */
1171 unicast_dest = 0;
1174 /* Check for renewal of a lease which is outside the allowed range. */
1175 else if (!address_available(context, mess->yiaddr, tagif_netid) &&
1176 (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1177 message = _("address not available");
1179 /* Check if a new static address has been configured. Be very sure that
1180 when the client does DISCOVER, it will get the static address, otherwise
1181 an endless protocol loop will ensue. */
1182 else if (!tmp && !selecting &&
1183 have_config(config, CONFIG_ADDR) &&
1184 (!have_config(config, CONFIG_DECLINED) ||
1185 difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1186 config->addr.s_addr != mess->yiaddr.s_addr &&
1187 (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1188 message = _("static lease available");
1190 /* Check to see if the address is reserved as a static address for another host */
1191 else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1192 message = _("address reserved");
1194 else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1196 /* If a host is configured with more than one MAC address, it's OK to 'nix
1197 a lease from one of it's MACs to give the address to another. */
1198 if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1200 my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1201 print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
1202 inet_ntoa(ltmp->addr));
1203 lease = ltmp;
1205 else
1206 message = _("address in use");
1209 if (!message)
1211 if (emac_len == 0)
1212 message = _("no unique-id");
1214 else if (!lease)
1216 if ((lease = lease4_allocate(mess->yiaddr)))
1217 do_classes = 1;
1218 else
1219 message = _("no leases left");
1224 if (message)
1226 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1227 if (!option_bool(OPT_QUIET_DHCP))
1228 #endif
1229 log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid);
1231 mess->yiaddr.s_addr = 0;
1232 clear_packet(mess, end);
1233 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1234 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1235 option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1236 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1237 a distant subnet which unicast a REQ to us won't work. */
1238 if (!unicast_dest || mess->giaddr.s_addr != 0 ||
1239 mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1241 mess->flags |= htons(0x8000); /* broadcast */
1242 mess->ciaddr.s_addr = 0;
1245 else
1247 if (context->netid.net)
1249 context->netid.next = netid;
1250 tagif_netid = run_tag_if( &context->netid);
1253 log_tags(tagif_netid, ntohl(mess->xid));
1255 if (do_classes)
1257 /* pick up INIT-REBOOT events. */
1258 lease->flags |= LEASE_CHANGED;
1260 #ifdef HAVE_SCRIPT
1261 if (daemon->lease_change_command)
1263 struct dhcp_netid *n;
1265 if (mess->giaddr.s_addr)
1266 lease->giaddr = mess->giaddr;
1268 free(lease->extradata);
1269 lease->extradata = NULL;
1270 lease->extradata_size = lease->extradata_len = 0;
1272 add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
1273 add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
1274 add_extradata_opt(lease, oui);
1275 add_extradata_opt(lease, serial);
1276 add_extradata_opt(lease, class);
1278 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
1280 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
1281 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
1282 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
1284 else
1286 add_extradata_opt(lease, NULL);
1287 add_extradata_opt(lease, NULL);
1288 add_extradata_opt(lease, NULL);
1291 /* space-concat tag set */
1292 if (!tagif_netid)
1293 add_extradata_opt(lease, NULL);
1294 else
1295 for (n = tagif_netid; n; n = n->next)
1297 struct dhcp_netid *n1;
1298 /* kill dupes */
1299 for (n1 = n->next; n1; n1 = n1->next)
1300 if (strcmp(n->net, n1->net) == 0)
1301 break;
1302 if (!n1)
1303 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
1306 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1308 int len = option_len(opt);
1309 unsigned char *ucp = option_ptr(opt, 0);
1310 /* If the user-class option started as counted strings, the first byte will be zero. */
1311 if (len != 0 && ucp[0] == 0)
1312 ucp++, len--;
1313 lease_add_extradata(lease, ucp, len, 0);
1316 #endif
1319 if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1321 domain = get_domain(mess->yiaddr);
1322 hostname = client_hostname;
1323 hostname_auth = 1;
1326 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1327 lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
1329 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1330 if (!hostname_auth)
1332 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1333 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1334 break;
1335 if (id_list)
1336 hostname = NULL;
1339 /* Last ditch, if configured, generate hostname from mac address */
1340 if (!hostname && emac_len != 0)
1342 for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
1343 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1344 break;
1345 if (id_list)
1347 int i;
1349 hostname = daemon->dhcp_buff;
1350 /* buffer is 256 bytes, 3 bytes per octet */
1351 for (i = 0; (i < emac_len) && (i < 80); i++)
1352 hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
1353 hostname = daemon->dhcp_buff;
1357 if (hostname)
1358 lease_set_hostname(lease, hostname, hostname_auth, get_domain(lease->addr), domain);
1360 lease_set_expires(lease, time, now);
1361 lease_set_interface(lease, int_index, now);
1363 if (override.s_addr != 0)
1364 lease->override = override;
1365 else
1366 override = lease->override;
1368 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1369 if (!option_bool(OPT_QUIET_DHCP))
1370 #endif
1371 log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid);
1373 clear_packet(mess, end);
1374 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1375 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1376 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1377 if (time != 0xffffffff)
1379 while (fuzz > (time/16))
1380 fuzz = fuzz/2;
1381 option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
1382 option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
1384 do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
1385 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
1388 return dhcp_packet_size(mess, agent_id, real_end);
1390 case DHCPINFORM:
1391 if (ignore || have_config(config, CONFIG_DISABLE))
1392 message = _("ignored");
1394 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1395 if (!option_bool(OPT_QUIET_DHCP))
1396 #endif
1397 log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
1399 if (message || mess->ciaddr.s_addr == 0)
1400 return 0;
1402 /* For DHCPINFORM only, cope without a valid context */
1403 context = narrow_context(context, mess->ciaddr, tagif_netid);
1405 /* Find a least based on IP address if we didn't
1406 get one from MAC address/client-d */
1407 if (!lease &&
1408 (lease = lease_find_by_addr(mess->ciaddr)) &&
1409 lease->hostname)
1410 hostname = lease->hostname;
1412 if (!hostname && (hostname = host_from_dns(mess->ciaddr)))
1413 domain = get_domain(mess->ciaddr);
1415 if (context && context->netid.net)
1417 context->netid.next = netid;
1418 tagif_netid = run_tag_if(&context->netid);
1421 log_tags(tagif_netid, ntohl(mess->xid));
1423 #ifdef HAVE_QUIET_DHCP //originally a TOMATO option
1424 if (!option_bool(OPT_QUIET_DHCP))
1425 #endif
1426 log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);
1428 if (lease)
1430 lease_set_interface(lease, int_index, now);
1431 if (override.s_addr != 0)
1432 lease->override = override;
1433 else
1434 override = lease->override;
1437 clear_packet(mess, end);
1438 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1439 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1441 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1442 we supply a utility which makes DHCPINFORM requests to get this information.
1443 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1444 which won't be true for ordinary clients, but will be true for the
1445 dhcp_lease_time utility. */
1446 if (lease && in_list(req_options, OPTION_LEASE_TIME))
1448 if (lease->expires == 0)
1449 time = 0xffffffff;
1450 else
1451 time = (unsigned int)difftime(lease->expires, now);
1452 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1455 do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1456 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
1458 *is_inform = 1; /* handle reply differently */
1459 return dhcp_packet_size(mess, agent_id, real_end);
1462 return 0;
1465 /* find a good value to use as MAC address for logging and address-allocation hashing.
1466 This is normally just the chaddr field from the DHCP packet,
1467 but eg Firewire will have hlen == 0 and use the client-id instead.
1468 This could be anything, but will normally be EUI64 for Firewire.
1469 We assume that if the first byte of the client-id equals the htype byte
1470 then the client-id is using the usual encoding and use the rest of the
1471 client-id: if not we can use the whole client-id. This should give
1472 sane MAC address logs. */
1473 unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
1474 int clid_len, unsigned char *clid, int *len_out)
1476 if (hwlen == 0 && clid && clid_len > 3)
1478 if (clid[0] == hwtype)
1480 *len_out = clid_len - 1 ;
1481 return clid + 1;
1484 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1485 if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1487 *len_out = clid_len - 1 ;
1488 return clid + 1;
1490 #endif
1492 *len_out = clid_len;
1493 return clid;
1496 *len_out = hwlen;
1497 return hwaddr;
1500 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1502 unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1504 if (opt)
1506 unsigned int req_time = option_uint(opt, 0, 4);
1507 if (req_time < 120 )
1508 req_time = 120; /* sanity */
1509 if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1510 time = req_time;
1513 return time;
1516 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1518 if (override.s_addr != 0)
1519 return override;
1520 else if (context && context->local.s_addr != 0)
1521 return context->local;
1522 else
1523 return fallback;
1526 static int sanitise(unsigned char *opt, char *buf)
1528 char *p;
1529 int i;
1531 *buf = 0;
1533 if (!opt)
1534 return 0;
1536 p = option_ptr(opt, 0);
1538 for (i = option_len(opt); i > 0; i--)
1540 char c = *p++;
1541 if (isprint((int)c))
1542 *buf++ = c;
1544 *buf = 0; /* add terminator */
1546 return 1;
1549 #ifdef HAVE_SCRIPT
1550 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
1552 if (!opt)
1553 lease_add_extradata(lease, NULL, 0, 0);
1554 else
1555 lease_add_extradata(lease, option_ptr(opt, 0), option_len(opt), 0);
1557 #endif
1559 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
1560 int mac_len, char *interface, char *string, u32 xid)
1562 struct in_addr a;
1565 /* addr may be misaligned */
1566 if (addr)
1567 memcpy(&a, addr, sizeof(a));
1569 print_mac(daemon->namebuff, ext_mac, mac_len);
1571 if(option_bool(OPT_LOG_OPTS))
1572 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s",
1573 ntohl(xid),
1574 type,
1575 interface,
1576 addr ? inet_ntoa(a) : "",
1577 addr ? " " : "",
1578 daemon->namebuff,
1579 string ? string : "");
1580 else
1581 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s",
1582 type,
1583 interface,
1584 addr ? inet_ntoa(a) : "",
1585 addr ? " " : "",
1586 daemon->namebuff,
1587 string ? string : "");
1590 static void log_options(unsigned char *start, u32 xid)
1592 while (*start != OPTION_END)
1594 char *optname = option_string(AF_INET, start[0], option_ptr(start, 0), option_len(start), daemon->namebuff, MAXDNAME);
1596 my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d %s %s",
1597 ntohl(xid), option_len(start), start[0], optname, daemon->namebuff);
1598 start += start[1] + 2;
1602 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1604 while (1)
1606 if (p > end)
1607 return NULL;
1608 else if (*p == OPTION_END)
1609 return opt == OPTION_END ? p : NULL;
1610 else if (*p == OPTION_PAD)
1611 p++;
1612 else
1614 int opt_len;
1615 if (p > end - 2)
1616 return NULL; /* malformed packet */
1617 opt_len = option_len(p);
1618 if (p > end - (2 + opt_len))
1619 return NULL; /* malformed packet */
1620 if (*p == opt && opt_len >= minsize)
1621 return p;
1622 p += opt_len + 2;
1627 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1629 unsigned char *ret, *overload;
1631 /* skip over DHCP cookie; */
1632 if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1633 return ret;
1635 /* look for overload option. */
1636 if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1637 return NULL;
1639 /* Can we look in filename area ? */
1640 if ((overload[2] & 1) &&
1641 (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1642 return ret;
1644 /* finally try sname area */
1645 if ((overload[2] & 2) &&
1646 (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1647 return ret;
1649 return NULL;
1652 static struct in_addr option_addr(unsigned char *opt)
1654 /* this worries about unaligned data in the option. */
1655 /* struct in_addr is network byte order */
1656 struct in_addr ret;
1658 memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
1660 return ret;
1663 static unsigned int option_uint(unsigned char *opt, int offset, int size)
1665 /* this worries about unaligned data and byte order */
1666 unsigned int ret = 0;
1667 int i;
1668 unsigned char *p = option_ptr(opt, offset);
1670 for (i = 0; i < size; i++)
1671 ret = (ret << 8) | *p++;
1673 return ret;
1676 static unsigned char *dhcp_skip_opts(unsigned char *start)
1678 while (*start != 0)
1679 start += start[1] + 2;
1680 return start;
1683 /* only for use when building packet: doesn't check for bad data. */
1684 static unsigned char *find_overload(struct dhcp_packet *mess)
1686 unsigned char *p = &mess->options[0] + sizeof(u32);
1688 while (*p != 0)
1690 if (*p == OPTION_OVERLOAD)
1691 return p;
1692 p += p[1] + 2;
1694 return NULL;
1697 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end)
1699 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1700 unsigned char *overload;
1701 size_t ret;
1703 /* move agent_id back down to the end of the packet */
1704 if (agent_id)
1706 memmove(p, agent_id, real_end - agent_id);
1707 p += real_end - agent_id;
1708 memset(p, 0, real_end - p); /* in case of overlap */
1711 /* add END options to the regions. */
1712 overload = find_overload(mess);
1714 if (overload && (option_uint(overload, 0, 1) & 1))
1716 *dhcp_skip_opts(mess->file) = OPTION_END;
1717 if (option_bool(OPT_LOG_OPTS))
1718 log_options(mess->file, mess->xid);
1720 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1721 my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1723 if (overload && (option_uint(overload, 0, 1) & 2))
1725 *dhcp_skip_opts(mess->sname) = OPTION_END;
1726 if (option_bool(OPT_LOG_OPTS))
1727 log_options(mess->sname, mess->xid);
1729 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1730 my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1733 *p++ = OPTION_END;
1735 if (option_bool(OPT_LOG_OPTS))
1737 if (mess->siaddr.s_addr != 0)
1738 my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
1740 if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
1741 my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
1743 log_options(&mess->options[0] + sizeof(u32), mess->xid);
1746 ret = (size_t)(p - (unsigned char *)mess);
1748 if (ret < MIN_PACKETSZ)
1749 ret = MIN_PACKETSZ;
1751 return ret;
1754 static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1756 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1758 if (p + len + 3 >= end)
1759 /* not enough space in options area, try and use overload, if poss */
1761 unsigned char *overload;
1763 if (!(overload = find_overload(mess)) &&
1764 (mess->file[0] == 0 || mess->sname[0] == 0))
1766 /* attempt to overload fname and sname areas, we've reserved space for the
1767 overflow option previuously. */
1768 overload = p;
1769 *(p++) = OPTION_OVERLOAD;
1770 *(p++) = 1;
1773 p = NULL;
1775 /* using filename field ? */
1776 if (overload)
1778 if (mess->file[0] == 0)
1779 overload[2] |= 1;
1781 if (overload[2] & 1)
1783 p = dhcp_skip_opts(mess->file);
1784 if (p + len + 3 >= mess->file + sizeof(mess->file))
1785 p = NULL;
1788 if (!p)
1790 /* try to bring sname into play (it may be already) */
1791 if (mess->sname[0] == 0)
1792 overload[2] |= 2;
1794 if (overload[2] & 2)
1796 p = dhcp_skip_opts(mess->sname);
1797 if (p + len + 3 >= mess->sname + sizeof(mess->sname))
1798 p = NULL;
1803 if (!p)
1804 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1807 if (p)
1809 *(p++) = opt;
1810 *(p++) = len;
1813 return p;
1816 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1818 int i;
1819 unsigned char *p = free_space(mess, end, opt, len);
1821 if (p)
1822 for (i = 0; i < len; i++)
1823 *(p++) = val >> (8 * (len - (i + 1)));
1826 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
1827 char *string, int null_term)
1829 unsigned char *p;
1830 size_t len = strlen(string);
1832 if (null_term && len != 255)
1833 len++;
1835 if ((p = free_space(mess, end, opt, len)))
1836 memcpy(p, string, len);
1839 /* return length, note this only does the data part */
1840 static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1842 int len = opt->len;
1844 if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1845 len++;
1847 if (p && len != 0)
1849 if (context && (opt->flags & DHOPT_ADDR))
1851 int j;
1852 struct in_addr *a = (struct in_addr *)opt->val;
1853 for (j = 0; j < opt->len; j+=INADDRSZ, a++)
1855 /* zero means "self" (but not in vendorclass options.) */
1856 if (a->s_addr == 0)
1857 memcpy(p, &context->local, INADDRSZ);
1858 else
1859 memcpy(p, a, INADDRSZ);
1860 p += INADDRSZ;
1863 else
1864 memcpy(p, opt->val, len);
1866 return len;
1869 static int in_list(unsigned char *list, int opt)
1871 int i;
1873 /* If no requested options, send everything, not nothing. */
1874 if (!list)
1875 return 1;
1877 for (i = 0; list[i] != OPTION_END; i++)
1878 if (opt == list[i])
1879 return 1;
1881 return 0;
1884 static struct dhcp_opt *option_find2(int opt)
1886 struct dhcp_opt *opts;
1888 for (opts = daemon->dhcp_opts; opts; opts = opts->next)
1889 if (opts->opt == opt && (opts->flags & DHOPT_TAGOK))
1890 return opts;
1892 return NULL;
1895 /* mark vendor-encapsulated options which match the client-supplied or
1896 config-supplied vendor class */
1897 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
1899 for (; dopt; dopt = dopt->next)
1901 dopt->flags &= ~DHOPT_VENDOR_MATCH;
1902 if (opt && (dopt->flags & DHOPT_VENDOR))
1904 int i, len = 0;
1905 if (dopt->u.vendor_class)
1906 len = strlen((char *)dopt->u.vendor_class);
1907 for (i = 0; i <= (option_len(opt) - len); i++)
1908 if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
1910 dopt->flags |= DHOPT_VENDOR_MATCH;
1911 break;
1917 static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
1918 struct dhcp_packet *mess, unsigned char *end, int null_term)
1920 int len, enc_len, ret = 0;
1921 struct dhcp_opt *start;
1922 unsigned char *p;
1924 /* find size in advance */
1925 for (enc_len = 0, start = opt; opt; opt = opt->next)
1926 if (opt->flags & flag)
1928 int new = do_opt(opt, NULL, NULL, null_term) + 2;
1929 ret = 1;
1930 if (enc_len + new <= 255)
1931 enc_len += new;
1932 else
1934 p = free_space(mess, end, encap, enc_len);
1935 for (; start && start != opt; start = start->next)
1936 if (p && (start->flags & flag))
1938 len = do_opt(start, p + 2, NULL, null_term);
1939 *(p++) = start->opt;
1940 *(p++) = len;
1941 p += len;
1943 enc_len = new;
1944 start = opt;
1948 if (enc_len != 0 &&
1949 (p = free_space(mess, end, encap, enc_len + 1)))
1951 for (; start; start = start->next)
1952 if (start->flags & flag)
1954 len = do_opt(start, p + 2, NULL, null_term);
1955 *(p++) = start->opt;
1956 *(p++) = len;
1957 p += len;
1959 *p = OPTION_END;
1962 return ret;
1965 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
1967 unsigned char *p;
1969 option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
1970 if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
1971 memcpy(p, uuid, 17);
1974 static int prune_vendor_opts(struct dhcp_netid *netid)
1976 int force = 0;
1977 struct dhcp_opt *opt;
1979 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1980 for (opt = daemon->dhcp_opts; opt; opt = opt->next)
1981 if (opt->flags & DHOPT_VENDOR_MATCH)
1983 if (!match_netid(opt->netid, netid, 1))
1984 opt->flags &= ~DHOPT_VENDOR_MATCH;
1985 else if (opt->flags & DHOPT_FORCE)
1986 force = 1;
1988 return force;
1991 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
1993 #define NUM_OPTS 4
1995 unsigned char *p, *q;
1996 struct pxe_service *service;
1997 static struct dhcp_opt *o, *ret;
1998 int i, j = NUM_OPTS - 1;
1999 struct in_addr boot_server;
2001 /* We pass back references to these, hence they are declared static */
2002 static unsigned char discovery_control;
2003 static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' };
2004 static struct dhcp_opt *fake_opts = NULL;
2006 /* Disable multicast, since we don't support it, and broadcast
2007 unless we need it */
2008 discovery_control = 3;
2010 ret = daemon->dhcp_opts;
2012 if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
2013 return ret;
2015 for (i = 0; i < NUM_OPTS; i++)
2017 fake_opts[i].flags = DHOPT_VENDOR_MATCH;
2018 fake_opts[i].netid = NULL;
2019 fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
2022 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2023 p = (unsigned char *)daemon->dhcp_buff;
2024 q = (unsigned char *)daemon->dhcp_buff3;
2026 for (i = 0, service = daemon->pxe_services; service; service = service->next)
2027 if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
2029 size_t len = strlen(service->menu);
2030 /* opt 43 max size is 255. encapsulated option has type and length
2031 bytes, so its max size is 253. */
2032 if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
2034 *(p++) = service->type >> 8;
2035 *(p++) = service->type;
2036 *(p++) = len;
2037 memcpy(p, service->menu, len);
2038 p += len;
2039 i++;
2041 else
2043 toobig:
2044 my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
2045 return daemon->dhcp_opts;
2048 boot_server = service->basename ? local :
2049 (service->sname ? a_record_from_hosts(service->sname, now) : service->server);
2051 if (boot_server.s_addr != 0)
2053 if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
2054 goto toobig;
2056 /* Boot service with known address - give it */
2057 *(q++) = service->type >> 8;
2058 *(q++) = service->type;
2059 *(q++) = 1;
2060 /* dest misaligned */
2061 memcpy(q, &boot_server.s_addr, INADDRSZ);
2062 q += INADDRSZ;
2064 else if (service->type != 0)
2065 /* We don't know the server for a service type, so we'll
2066 allow the client to broadcast for it */
2067 discovery_control = 2;
2070 /* if no prompt, wait forever if there's a choice */
2071 fake_prompt[0] = (i > 1) ? 255 : 0;
2073 if (i == 0)
2074 discovery_control = 8; /* no menu - just use use mess->filename */
2075 else
2077 ret = &fake_opts[j--];
2078 ret->len = p - (unsigned char *)daemon->dhcp_buff;
2079 ret->val = (unsigned char *)daemon->dhcp_buff;
2080 ret->opt = SUBOPT_PXE_MENU;
2082 if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
2084 ret = &fake_opts[j--];
2085 ret->len = q - (unsigned char *)daemon->dhcp_buff3;
2086 ret->val = (unsigned char *)daemon->dhcp_buff3;
2087 ret->opt = SUBOPT_PXE_SERVERS;
2091 for (o = daemon->dhcp_opts; o; o = o->next)
2092 if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
2093 break;
2095 if (!o)
2097 ret = &fake_opts[j--];
2098 ret->len = sizeof(fake_prompt);
2099 ret->val = fake_prompt;
2100 ret->opt = SUBOPT_PXE_MENU_PROMPT;
2103 ret = &fake_opts[j--];
2104 ret->len = 1;
2105 ret->opt = SUBOPT_PXE_DISCOVERY;
2106 ret->val= &discovery_control;
2108 return ret;
2111 static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
2113 memset(mess->sname, 0, sizeof(mess->sname));
2114 memset(mess->file, 0, sizeof(mess->file));
2115 memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
2116 mess->siaddr.s_addr = 0;
2119 struct dhcp_boot *find_boot(struct dhcp_netid *netid)
2121 struct dhcp_boot *boot;
2123 /* decide which dhcp-boot option we're using */
2124 for (boot = daemon->boot_config; boot; boot = boot->next)
2125 if (match_netid(boot->netid, netid, 0))
2126 break;
2127 if (!boot)
2128 /* No match, look for one without a netid */
2129 for (boot = daemon->boot_config; boot; boot = boot->next)
2130 if (match_netid(boot->netid, netid, 1))
2131 break;
2133 return boot;
2136 static void do_options(struct dhcp_context *context,
2137 struct dhcp_packet *mess,
2138 unsigned char *end,
2139 unsigned char *req_options,
2140 char *hostname,
2141 char *domain,
2142 struct dhcp_netid *netid,
2143 struct in_addr subnet_addr,
2144 unsigned char fqdn_flags,
2145 int null_term, int pxe_arch,
2146 unsigned char *uuid,
2147 int vendor_class_len,
2148 time_t now)
2150 struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2151 struct dhcp_boot *boot;
2152 unsigned char *p;
2153 int i, len, force_encap = 0;
2154 unsigned char f0 = 0, s0 = 0;
2155 int done_file = 0, done_server = 0;
2156 int done_vendor_class = 0;
2157 struct dhcp_netid *tagif;
2158 struct dhcp_netid_list *id_list;
2160 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2161 if (context)
2162 context->netid.next = NULL;
2163 tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
2165 /* logging */
2166 if (option_bool(OPT_LOG_OPTS) && req_options)
2168 char *q = daemon->namebuff;
2169 for (i = 0; req_options[i] != OPTION_END; i++)
2171 char *s = option_string(AF_INET, req_options[i], NULL, 0, NULL, 0);
2172 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2173 "%d%s%s%s",
2174 req_options[i],
2175 strlen(s) != 0 ? ":" : "",
2177 req_options[i+1] == OPTION_END ? "" : ", ");
2178 if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2180 q = daemon->namebuff;
2181 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2186 for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
2187 if ((!id_list->list) || match_netid(id_list->list, netid, 0))
2188 break;
2189 if (id_list)
2190 mess->flags |= htons(0x8000); /* force broadcast */
2192 if (context)
2193 mess->siaddr = context->local;
2195 /* See if we can send the boot stuff as options.
2196 To do this we need a requested option list, BOOTP
2197 and very old DHCP clients won't have this, we also
2198 provide an manual option to disable it.
2199 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2200 names, so we always send those. */
2201 if ((boot = find_boot(tagif)))
2203 if (boot->sname)
2205 if (!option_bool(OPT_NO_OVERRIDE) &&
2206 req_options &&
2207 in_list(req_options, OPTION_SNAME))
2208 option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2209 else
2210 strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
2213 if (boot->file)
2215 if (!option_bool(OPT_NO_OVERRIDE) &&
2216 req_options &&
2217 in_list(req_options, OPTION_FILENAME))
2218 option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2219 else
2220 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
2223 if (boot->next_server.s_addr)
2224 mess->siaddr = boot->next_server;
2225 else if (boot->tftp_sname)
2226 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
2228 else
2229 /* Use the values of the relevant options if no dhcp-boot given and
2230 they're not explicitly asked for as options. OPTION_END is used
2231 as an internal way to specify siaddr without using dhcp-boot, for use in
2232 dhcp-optsfile. */
2234 if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
2235 (opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2237 strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
2238 done_file = 1;
2241 if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2242 (opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2244 strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
2245 done_server = 1;
2248 if ((opt = option_find2(OPTION_END)))
2249 mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
2252 /* We don't want to do option-overload for BOOTP, so make the file and sname
2253 fields look like they are in use, even when they aren't. This gets restored
2254 at the end of this function. */
2256 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2258 f0 = mess->file[0];
2259 mess->file[0] = 1;
2260 s0 = mess->sname[0];
2261 mess->sname[0] = 1;
2264 /* At this point, if mess->sname or mess->file are zeroed, they are available
2265 for option overload, reserve space for the overload option. */
2266 if (mess->file[0] == 0 || mess->sname[0] == 0)
2267 end -= 3;
2269 /* rfc3011 says this doesn't need to be in the requested options list. */
2270 if (subnet_addr.s_addr)
2271 option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2273 /* replies to DHCPINFORM may not have a valid context */
2274 if (context)
2276 if (!option_find2(OPTION_NETMASK))
2277 option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2279 /* May not have a "guessed" broadcast address if we got no packets via a relay
2280 from this net yet (ie just unicast renewals after a restart */
2281 if (context->broadcast.s_addr &&
2282 !option_find2(OPTION_BROADCAST))
2283 option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2285 /* Same comments as broadcast apply, and also may not be able to get a sensible
2286 default when using subnet select. User must configure by steam in that case. */
2287 if (context->router.s_addr &&
2288 in_list(req_options, OPTION_ROUTER) &&
2289 !option_find2(OPTION_ROUTER))
2290 option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2292 if (daemon->port == NAMESERVER_PORT &&
2293 in_list(req_options, OPTION_DNSSERVER) &&
2294 !option_find2(OPTION_DNSSERVER))
2295 option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2298 if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
2299 !option_find2(OPTION_DOMAINNAME))
2300 option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2302 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2303 if (hostname)
2305 if (in_list(req_options, OPTION_HOSTNAME) &&
2306 !option_find2(OPTION_HOSTNAME))
2307 option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2309 if (fqdn_flags != 0)
2311 len = strlen(hostname) + 3;
2313 if (fqdn_flags & 0x04)
2314 len += 2;
2315 else if (null_term)
2316 len++;
2318 if (domain)
2319 len += strlen(domain) + 1;
2321 if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2323 *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */
2324 *(p++) = 255;
2325 *(p++) = 255;
2327 if (fqdn_flags & 0x04)
2329 p = do_rfc1035_name(p, hostname);
2330 if (domain)
2331 p = do_rfc1035_name(p, domain);
2332 *p++ = 0;
2334 else
2336 memcpy(p, hostname, strlen(hostname));
2337 p += strlen(hostname);
2338 if (domain)
2340 *(p++) = '.';
2341 memcpy(p, domain, strlen(domain));
2342 p += strlen(domain);
2344 if (null_term)
2345 *(p++) = 0;
2351 for (opt = config_opts; opt; opt = opt->next)
2353 int optno = opt->opt;
2355 /* netids match and not encapsulated? */
2356 if (!(opt->flags & DHOPT_TAGOK))
2357 continue;
2359 /* was it asked for, or are we sending it anyway? */
2360 if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2361 continue;
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)
2369 continue;
2371 if (optno == OPTION_SNAME && done_server)
2372 continue;
2374 if (optno == OPTION_FILENAME && done_file)
2375 continue;
2377 /* For the options we have default values on
2378 dhc-option=<optionno> means "don't include this option"
2379 not "include a zero-length option" */
2380 if (opt->len == 0 &&
2381 (optno == OPTION_NETMASK ||
2382 optno == OPTION_BROADCAST ||
2383 optno == OPTION_ROUTER ||
2384 optno == OPTION_DNSSERVER ||
2385 optno == OPTION_DOMAINNAME ||
2386 optno == OPTION_HOSTNAME))
2387 continue;
2389 /* vendor-class comes from elsewhere for PXE */
2390 if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2391 continue;
2393 /* always force null-term for filename and servername - buggy PXE again. */
2394 len = do_opt(opt, NULL, context,
2395 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2397 if ((p = free_space(mess, end, optno, len)))
2399 do_opt(opt, p, context,
2400 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2402 /* If we send a vendor-id, revisit which vendor-ops we consider
2403 it appropriate to send. */
2404 if (optno == OPTION_VENDOR_ID)
2406 match_vendor_opts(p - 2, config_opts);
2407 done_vendor_class = 1;
2412 /* Now send options to be encapsulated in arbitrary options,
2413 eg dhcp-option=encap:172,17,.......
2414 Also handle vendor-identifying vendor-encapsulated options,
2415 dhcp-option = vi-encap:13,17,.......
2416 The may be more that one "outer" to do, so group
2417 all the options which match each outer in turn. */
2418 for (opt = config_opts; opt; opt = opt->next)
2419 opt->flags &= ~DHOPT_ENCAP_DONE;
2421 for (opt = config_opts; opt; opt = opt->next)
2423 int flags;
2425 if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
2427 int found = 0;
2428 struct dhcp_opt *o;
2430 if (opt->flags & DHOPT_ENCAP_DONE)
2431 continue;
2433 for (len = 0, o = config_opts; o; o = o->next)
2435 int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
2437 o->flags &= ~DHOPT_ENCAP_MATCH;
2439 if (!(o->flags & flags) || opt->u.encap != o->u.encap)
2440 continue;
2442 o->flags |= DHOPT_ENCAP_DONE;
2443 if (match_netid(o->netid, tagif, 1) &&
2444 ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
2446 o->flags |= DHOPT_ENCAP_MATCH;
2447 found = 1;
2448 len += do_opt(o, NULL, NULL, 0) + 2;
2452 if (found)
2454 if (flags & DHOPT_ENCAPSULATE)
2455 do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2456 else if (len > 250)
2457 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
2458 else if ((p = free_space(mess, end, OPTION_VENDOR_IDENT_OPT, len + 5)))
2460 int swap_ent = htonl(opt->u.encap);
2461 memcpy(p, &swap_ent, 4);
2462 p += 4;
2463 *(p++) = len;
2464 for (o = config_opts; o; o = o->next)
2465 if (o->flags & DHOPT_ENCAP_MATCH)
2467 len = do_opt(o, p + 2, NULL, 0);
2468 *(p++) = o->opt;
2469 *(p++) = len;
2470 p += len;
2477 force_encap = prune_vendor_opts(tagif);
2479 if (context && pxe_arch != -1)
2481 pxe_misc(mess, end, uuid);
2482 config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
2485 if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
2486 do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) &&
2487 pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
2488 (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
2489 /* If we send vendor encapsulated options, and haven't already sent option 60,
2490 echo back the value we got from the client. */
2491 memcpy(p, daemon->dhcp_buff3, vendor_class_len);
2493 /* restore BOOTP anti-overload hack */
2494 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2496 mess->file[0] = f0;
2497 mess->sname[0] = s0;
2501 #endif