dnsmasq 2.71
[tomato.git] / release / src / router / dnsmasq / src / rfc2131.c
blob5c9040892f1de2fba6d0a6835456f7374d5856ee
1 /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_DHCP
21 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
22 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
24 #ifdef HAVE_SCRIPT
25 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
26 #endif
28 static int sanitise(unsigned char *opt, char *buf);
29 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
30 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
31 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
32 static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
33 int opt, char *string, int null_term);
34 static struct in_addr option_addr(unsigned char *opt);
35 static unsigned int option_uint(unsigned char *opt, int i, int size);
36 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
37 int mac_len, char *interface, char *string, char *err, u32 xid);
38 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
39 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
40 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
41 static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
42 static int in_list(unsigned char *list, int opt);
43 static void do_options(struct dhcp_context *context,
44 struct dhcp_packet *mess,
45 unsigned char *real_end,
46 unsigned char *req_options,
47 char *hostname,
48 char *config_domain,
49 struct dhcp_netid *netid,
50 struct in_addr subnet_addr,
51 unsigned char fqdn_flags,
52 int null_term, int pxearch,
53 unsigned char *uuid,
54 int vendor_class_len,
55 time_t now);
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;
96 #ifdef HAVE_SCRIPT
97 unsigned char *class = NULL;
98 #endif
100 subnet_addr.s_addr = override.s_addr = 0;
102 /* set tag with name == interface */
103 iface_id.net = iface_name;
104 iface_id.next = NULL;
105 netid = &iface_id;
107 if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
108 return 0;
110 if (mess->htype == 0 && mess->hlen != 0)
111 return 0;
113 /* check for DHCP rather than BOOTP */
114 if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
116 u32 cookie = htonl(DHCP_COOKIE);
118 /* only insist on a cookie for DHCP. */
119 if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
120 return 0;
122 mess_type = option_uint(opt, 0, 1);
124 /* two things to note here: expand_buf may move the packet,
125 so reassign mess from daemon->packet. Also, the size
126 sent includes the IP and UDP headers, hence the magic "-28" */
127 if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
129 size_t size = (size_t)option_uint(opt, 0, 2) - 28;
131 if (size > DHCP_PACKET_MAX)
132 size = DHCP_PACKET_MAX;
133 else if (size < sizeof(struct dhcp_packet))
134 size = sizeof(struct dhcp_packet);
136 if (expand_buf(&daemon->dhcp_packet, size))
138 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
139 real_end = end = ((unsigned char *)mess) + size;
143 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
144 it can affect the context-determination code. */
145 if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
146 mess->ciaddr.s_addr = 0;
148 /* search for device identity from CPEWAN devices, we pass this through to the script */
149 if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
151 unsigned int elen, offset, len = option_len(opt);
153 for (offset = 0; offset < (len - 5); offset += elen + 5)
155 elen = option_uint(opt, offset + 4 , 1);
156 if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
158 unsigned char *x = option_ptr(opt, offset + 5);
159 unsigned char *y = option_ptr(opt, offset + elen + 5);
160 oui = option_find1(x, y, 1, 1);
161 serial = option_find1(x, y, 2, 1);
162 #ifdef HAVE_SCRIPT
163 class = option_find1(x, y, 3, 1);
164 #endif
165 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
166 the gateway id back. Note that the device class is optional */
167 if (oui && serial)
169 cpewan_id.net = "cpewan-id";
170 cpewan_id.next = netid;
171 netid = &cpewan_id;
173 break;
178 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
180 /* Any agent-id needs to be copied back out, verbatim, as the last option
181 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
182 get overwritten, then it will be shuffled back at the end of processing.
183 Note that the incoming options must not be overwritten here, so there has to
184 be enough free space at the end of the packet to copy the option. */
185 unsigned char *sopt;
186 unsigned int total = option_len(opt) + 2;
187 unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
188 if (last_opt && last_opt < end - total)
190 end -= total;
191 agent_id = end;
192 memcpy(agent_id, opt, total);
195 /* look for RFC3527 Link selection sub-option */
196 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
197 subnet_addr = option_addr(sopt);
199 /* look for RFC5107 server-identifier-override */
200 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
201 override = option_addr(sopt);
203 /* if a circuit-id or remote-is option is provided, exact-match to options. */
204 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
206 int search;
208 if (vendor->match_type == MATCH_CIRCUIT)
209 search = SUBOPT_CIRCUIT_ID;
210 else if (vendor->match_type == MATCH_REMOTE)
211 search = SUBOPT_REMOTE_ID;
212 else if (vendor->match_type == MATCH_SUBSCRIBER)
213 search = SUBOPT_SUBSCR_ID;
214 else
215 continue;
217 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
218 vendor->len == option_len(sopt) &&
219 memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
221 vendor->netid.next = netid;
222 netid = &vendor->netid;
227 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
228 if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
229 subnet_addr = option_addr(opt);
231 /* If there is no client identifier option, use the hardware address */
232 if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
234 clid_len = option_len(opt);
235 clid = option_ptr(opt, 0);
238 /* do we have a lease in store? */
239 lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
241 /* If this request is missing a clid, but we've seen one before,
242 use it again for option matching etc. */
243 if (lease && !clid && lease->clid)
245 clid_len = lease->clid_len;
246 clid = lease->clid;
249 /* find mac to use for logging and hashing */
250 emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
253 for (mac = daemon->dhcp_macs; mac; mac = mac->next)
254 if (mac->hwaddr_len == mess->hlen &&
255 (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
256 memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
258 mac->netid.next = netid;
259 netid = &mac->netid;
262 /* Determine network for this packet. Our caller will have already linked all the
263 contexts which match the addresses of the receiving interface but if the
264 machine has an address already, or came via a relay, or we have a subnet selector,
265 we search again. If we don't have have a giaddr or explicit subnet selector,
266 use the ciaddr. This is necessary because a machine which got a lease via a
267 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
268 from the physical network, continue using that to allow correct DHCPNAK generation later. */
269 if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
271 struct dhcp_context *context_tmp, *context_new = NULL;
272 struct in_addr addr;
273 int force = 0;
275 if (subnet_addr.s_addr)
277 addr = subnet_addr;
278 force = 1;
280 else if (mess->giaddr.s_addr)
282 addr = mess->giaddr;
283 force = 1;
285 else
287 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
288 addr = mess->ciaddr;
289 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
290 if (context_tmp->netmask.s_addr &&
291 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
292 is_same_net(addr, context_tmp->end, context_tmp->netmask))
294 context_new = context;
295 break;
299 if (!context_new)
300 for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
302 struct in_addr netmask = context_tmp->netmask;
304 /* guess the netmask for relayed networks */
305 if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
307 if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
308 netmask.s_addr = htonl(0xff000000);
309 else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
310 netmask.s_addr = htonl(0xffff0000);
311 else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
312 netmask.s_addr = htonl(0xffffff00);
315 /* This section fills in context mainly when a client which is on a remote (relayed)
316 network renews a lease without using the relay, after dnsmasq has restarted. */
317 if (netmask.s_addr != 0 &&
318 is_same_net(addr, context_tmp->start, netmask) &&
319 is_same_net(addr, context_tmp->end, netmask))
321 context_tmp->netmask = netmask;
322 if (context_tmp->local.s_addr == 0)
323 context_tmp->local = fallback;
324 if (context_tmp->router.s_addr == 0)
325 context_tmp->router = mess->giaddr;
327 /* fill in missing broadcast addresses for relayed ranges */
328 if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
329 context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
331 context_tmp->current = context_new;
332 context_new = context_tmp;
336 if (context_new || force)
337 context = context_new;
340 if (!context)
342 my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
343 subnet_addr.s_addr ? _("with subnet selector") : _("via"),
344 subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
345 return 0;
348 if (option_bool(OPT_LOG_OPTS))
350 struct dhcp_context *context_tmp;
351 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
353 strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
354 if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
355 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
356 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
357 else
358 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
359 ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
363 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
364 Otherwise assume the option is an array, and look for a matching element.
365 If no data given, existance of the option is enough. This code handles
366 rfc3925 V-I classes too. */
367 for (o = daemon->dhcp_match; o; o = o->next)
369 unsigned int len, elen, match = 0;
370 size_t offset, o2;
372 if (o->flags & DHOPT_RFC3925)
374 if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
375 continue;
377 for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
379 len = option_uint(opt, offset + 4 , 1);
380 /* Need to take care that bad data can't run us off the end of the packet */
381 if ((offset + len + 5 <= (option_len(opt))) &&
382 (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
383 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
385 elen = option_uint(opt, o2, 1);
386 if ((o2 + elen + 1 <= option_len(opt)) &&
387 (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
388 break;
390 if (match)
391 break;
394 else
396 if (!(opt = option_find(mess, sz, o->opt, 1)))
397 continue;
399 match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
402 if (match)
404 o->netid->next = netid;
405 netid = o->netid;
409 /* user-class options are, according to RFC3004, supposed to contain
410 a set of counted strings. Here we check that this is so (by seeing
411 if the counts are consistent with the overall option length) and if
412 so zero the counts so that we don't get spurious matches between
413 the vendor string and the counts. If the lengths don't add up, we
414 assume that the option is a single string and non RFC3004 compliant
415 and just do the substring match. dhclient provides these broken options.
416 The code, later, which sends user-class data to the lease-change script
417 relies on the transformation done here.
420 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
422 unsigned char *ucp = option_ptr(opt, 0);
423 int tmp, j;
424 for (j = 0; j < option_len(opt); j += ucp[j] + 1);
425 if (j == option_len(opt))
426 for (j = 0; j < option_len(opt); j = tmp)
428 tmp = j + ucp[j] + 1;
429 ucp[j] = 0;
433 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
435 int mopt;
437 if (vendor->match_type == MATCH_VENDOR)
438 mopt = OPTION_VENDOR_ID;
439 else if (vendor->match_type == MATCH_USER)
440 mopt = OPTION_USER_CLASS;
441 else
442 continue;
444 if ((opt = option_find(mess, sz, mopt, 1)))
446 int i;
447 for (i = 0; i <= (option_len(opt) - vendor->len); i++)
448 if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
450 vendor->netid.next = netid;
451 netid = &vendor->netid;
452 break;
457 /* mark vendor-encapsulated options which match the client-supplied vendor class,
458 save client-supplied vendor class */
459 if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
461 memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
462 vendor_class_len = option_len(opt);
464 match_vendor_opts(opt, daemon->dhcp_opts);
466 if (option_bool(OPT_LOG_OPTS))
468 if (sanitise(opt, daemon->namebuff))
469 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
470 if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
471 my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
474 mess->op = BOOTREPLY;
476 config = find_config(daemon->dhcp_conf, context, clid, clid_len,
477 mess->chaddr, mess->hlen, mess->htype, NULL);
479 /* set "known" tag for known hosts */
480 if (config)
482 known_id.net = "known";
483 known_id.next = netid;
484 netid = &known_id;
487 if (mess_type == 0 && !pxe)
489 /* BOOTP request */
490 struct dhcp_netid id, bootp_id;
491 struct in_addr *logaddr = NULL;
493 /* must have a MAC addr for bootp */
494 if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
495 return 0;
497 if (have_config(config, CONFIG_DISABLE))
498 message = _("disabled");
500 end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
502 if (have_config(config, CONFIG_NAME))
504 hostname = config->hostname;
505 domain = config->domain;
508 if (config)
510 struct dhcp_netid_list *list;
512 for (list = config->netid; list; list = list->next)
514 list->list->next = netid;
515 netid = list->list;
519 /* Match incoming filename field as a netid. */
520 if (mess->file[0])
522 memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
523 daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
524 id.net = (char *)daemon->dhcp_buff2;
525 id.next = netid;
526 netid = &id;
529 /* Add "bootp" as a tag to allow different options, address ranges etc
530 for BOOTP clients */
531 bootp_id.net = "bootp";
532 bootp_id.next = netid;
533 netid = &bootp_id;
535 tagif_netid = run_tag_if(netid);
537 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
538 if (match_netid(id_list->list, tagif_netid, 0))
539 message = _("ignored");
541 if (!message)
543 int nailed = 0;
545 if (have_config(config, CONFIG_ADDR))
547 nailed = 1;
548 logaddr = &config->addr;
549 mess->yiaddr = config->addr;
550 if ((lease = lease_find_by_addr(config->addr)) &&
551 (lease->hwaddr_len != mess->hlen ||
552 lease->hwaddr_type != mess->htype ||
553 memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
554 message = _("address in use");
556 else
558 if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
559 !address_available(context, lease->addr, tagif_netid))
561 if (lease)
563 /* lease exists, wrong network. */
564 lease_prune(lease, now);
565 lease = NULL;
567 if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
568 message = _("no address available");
570 else
571 mess->yiaddr = lease->addr;
574 if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
575 message = _("wrong network");
576 else if (context->netid.net)
578 context->netid.next = netid;
579 tagif_netid = run_tag_if(&context->netid);
582 log_tags(tagif_netid, ntohl(mess->xid));
584 if (!message && !nailed)
586 for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
587 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
588 break;
589 if (!id_list)
590 message = _("no address configured");
593 if (!message &&
594 !lease &&
595 (!(lease = lease4_allocate(mess->yiaddr))))
596 message = _("no leases left");
598 if (!message)
600 logaddr = &mess->yiaddr;
602 lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
603 if (hostname)
604 lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain);
605 /* infinite lease unless nailed in dhcp-host line. */
606 lease_set_expires(lease,
607 have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
608 now);
609 lease_set_interface(lease, int_index, now);
611 clear_packet(mess, end);
612 do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
613 netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
617 log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
619 return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
622 if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 3)))
624 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
625 int len = option_len(opt);
626 char *pq = daemon->dhcp_buff;
627 unsigned char *pp, *op = option_ptr(opt, 0);
629 fqdn_flags = *op;
630 len -= 3;
631 op += 3;
632 pp = op;
634 /* NB, the following always sets at least one bit */
635 if (option_bool(OPT_FQDN_UPDATE))
637 if (fqdn_flags & 0x01)
639 fqdn_flags |= 0x02; /* set O */
640 fqdn_flags &= ~0x01; /* clear S */
642 fqdn_flags |= 0x08; /* set N */
644 else
646 if (!(fqdn_flags & 0x01))
647 fqdn_flags |= 0x03; /* set S and O */
648 fqdn_flags &= ~0x08; /* clear N */
651 if (fqdn_flags & 0x04)
652 while (*op != 0 && ((op + (*op)) - pp) < len)
654 memcpy(pq, op+1, *op);
655 pq += *op;
656 op += (*op)+1;
657 *(pq++) = '.';
659 else
661 memcpy(pq, op, len);
662 if (len > 0 && op[len-1] == 0)
663 borken_opt = 1;
664 pq += len + 1;
667 if (pq != daemon->dhcp_buff)
668 pq--;
670 *pq = 0;
672 if (legal_hostname(daemon->dhcp_buff))
673 offer_hostname = client_hostname = daemon->dhcp_buff;
675 else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
677 int len = option_len(opt);
678 memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
679 /* Microsoft clients are broken, and need zero-terminated strings
680 in options. We detect this state here, and do the same in
681 any options we send */
682 if (len > 0 && daemon->dhcp_buff[len-1] == 0)
683 borken_opt = 1;
684 else
685 daemon->dhcp_buff[len] = 0;
686 if (legal_hostname(daemon->dhcp_buff))
687 client_hostname = daemon->dhcp_buff;
690 if (client_hostname && option_bool(OPT_LOG_OPTS))
691 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
693 if (have_config(config, CONFIG_NAME))
695 hostname = config->hostname;
696 domain = config->domain;
697 hostname_auth = 1;
698 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
699 if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
700 offer_hostname = hostname;
702 else if (client_hostname)
704 domain = strip_hostname(client_hostname);
706 if (strlen(client_hostname) != 0)
708 hostname = client_hostname;
709 if (!config)
711 /* Search again now we have a hostname.
712 Only accept configs without CLID and HWADDR here, (they won't match)
713 to avoid impersonation by name. */
714 struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
715 mess->chaddr, mess->hlen,
716 mess->htype, hostname);
717 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
719 config = new;
720 /* set "known" tag for known hosts */
721 known_id.net = "known";
722 known_id.next = netid;
723 netid = &known_id;
729 if (config)
731 struct dhcp_netid_list *list;
733 for (list = config->netid; list; list = list->next)
735 list->list->next = netid;
736 netid = list->list;
740 tagif_netid = run_tag_if(netid);
742 /* if all the netids in the ignore list are present, ignore this client */
743 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
744 if (match_netid(id_list->list, tagif_netid, 0))
745 ignore = 1;
747 /* If configured, we can override the server-id to be the address of the relay,
748 so that all traffic goes via the relay and can pick up agent-id info. This can be
749 configured for all relays, or by address. */
750 if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
752 if (!daemon->override_relays)
753 override = mess->giaddr;
754 else
756 struct addr_list *l;
757 for (l = daemon->override_relays; l; l = l->next)
758 if (l->addr.s_addr == mess->giaddr.s_addr)
759 break;
760 if (l)
761 override = mess->giaddr;
765 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
766 if (have_config(config, CONFIG_NOCLID))
767 clid = NULL;
769 /* Check if client is PXE client. */
770 if (daemon->enable_pxe &&
771 (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
772 strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
774 if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
776 memcpy(pxe_uuid, option_ptr(opt, 0), 17);
777 uuid = pxe_uuid;
780 /* Check if this is really a PXE bootserver request, and handle specially if so. */
781 if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
782 (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
783 (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
785 struct pxe_service *service;
786 int type = option_uint(opt, 0, 2);
787 int layer = option_uint(opt, 2, 2);
788 unsigned char save71[4];
789 struct dhcp_opt opt71;
791 if (ignore)
792 return 0;
794 if (layer & 0x8000)
796 my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
797 return 0;
800 memcpy(save71, option_ptr(opt, 0), 4);
802 for (service = daemon->pxe_services; service; service = service->next)
803 if (service->type == type)
804 break;
806 if (!service || !service->basename)
807 return 0;
809 clear_packet(mess, end);
811 mess->yiaddr = mess->ciaddr;
812 mess->ciaddr.s_addr = 0;
813 if (service->sname)
814 mess->siaddr = a_record_from_hosts(service->sname, now);
815 else if (service->server.s_addr != 0)
816 mess->siaddr = service->server;
817 else
818 mess->siaddr = context->local;
820 snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
821 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
822 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
823 pxe_misc(mess, end, uuid);
825 prune_vendor_opts(tagif_netid);
826 opt71.val = save71;
827 opt71.opt = SUBOPT_PXE_BOOT_ITEM;
828 opt71.len = 4;
829 opt71.flags = DHOPT_VENDOR_MATCH;
830 opt71.netid = NULL;
831 opt71.next = daemon->dhcp_opts;
832 do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
834 log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
835 log_tags(tagif_netid, ntohl(mess->xid));
836 return dhcp_packet_size(mess, agent_id, real_end);
839 if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
841 pxearch = option_uint(opt, 0, 2);
843 /* proxy DHCP here. */
844 if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
846 struct dhcp_context *tmp;
848 for (tmp = context; tmp; tmp = tmp->current)
849 if ((tmp->flags & CONTEXT_PROXY) &&
850 match_netid(tmp->filter, tagif_netid, 1))
851 break;
853 if (tmp)
855 struct dhcp_boot *boot;
857 if (tmp->netid.net)
859 tmp->netid.next = netid;
860 tagif_netid = run_tag_if(&tmp->netid);
863 boot = find_boot(tagif_netid);
865 mess->yiaddr.s_addr = 0;
866 if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
868 mess->ciaddr.s_addr = 0;
869 mess->flags |= htons(0x8000); /* broadcast */
872 clear_packet(mess, end);
874 /* Provide the bootfile here, for gPXE, and in case we have no menu items
875 and set discovery_control = 8 */
876 if (boot)
878 if (boot->next_server.s_addr)
879 mess->siaddr = boot->next_server;
880 else if (boot->tftp_sname)
881 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
883 if (boot->file)
884 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
887 option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
888 mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
889 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
890 pxe_misc(mess, end, uuid);
891 prune_vendor_opts(tagif_netid);
892 do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
894 log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
895 log_tags(tagif_netid, ntohl(mess->xid));
896 return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
902 /* if we're just a proxy server, go no further */
903 if ((context->flags & CONTEXT_PROXY) || pxe)
904 return 0;
906 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
908 req_options = (unsigned char *)daemon->dhcp_buff2;
909 memcpy(req_options, option_ptr(opt, 0), option_len(opt));
910 req_options[option_len(opt)] = OPTION_END;
913 switch (mess_type)
915 case DHCPDECLINE:
916 if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
917 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
918 return 0;
920 /* sanitise any message. Paranoid? Moi? */
921 sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
923 if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
924 return 0;
926 log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
928 if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
929 lease_prune(lease, now);
931 if (have_config(config, CONFIG_ADDR) &&
932 config->addr.s_addr == option_addr(opt).s_addr)
934 prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
935 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
936 inet_ntoa(config->addr), daemon->dhcp_buff);
937 config->flags |= CONFIG_DECLINED;
938 config->decline_time = now;
940 else
941 /* make sure this host gets a different address next time. */
942 for (; context; context = context->current)
943 context->addr_epoch++;
945 return 0;
947 case DHCPRELEASE:
948 if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
949 !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
950 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
951 return 0;
953 if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
954 lease_prune(lease, now);
955 else
956 message = _("unknown lease");
958 log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
960 return 0;
962 case DHCPDISCOVER:
963 if (ignore || have_config(config, CONFIG_DISABLE))
965 if (option_bool(OPT_QUIET_DHCP))
966 return 0;
967 message = _("ignored");
968 opt = NULL;
970 else
972 struct in_addr addr, conf;
974 addr.s_addr = conf.s_addr = 0;
976 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
977 addr = option_addr(opt);
979 if (have_config(config, CONFIG_ADDR))
981 char *addrs = inet_ntoa(config->addr);
983 if ((ltmp = lease_find_by_addr(config->addr)) &&
984 ltmp != lease &&
985 !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
987 int len;
988 unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
989 ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
990 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
991 addrs, print_mac(daemon->namebuff, mac, len));
993 else
995 struct dhcp_context *tmp;
996 for (tmp = context; tmp; tmp = tmp->current)
997 if (context->router.s_addr == config->addr.s_addr)
998 break;
999 if (tmp)
1000 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
1001 else if (have_config(config, CONFIG_DECLINED) &&
1002 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
1003 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
1004 else
1005 conf = config->addr;
1009 if (conf.s_addr)
1010 mess->yiaddr = conf;
1011 else if (lease &&
1012 address_available(context, lease->addr, tagif_netid) &&
1013 !config_find_by_address(daemon->dhcp_conf, lease->addr))
1014 mess->yiaddr = lease->addr;
1015 else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
1016 !config_find_by_address(daemon->dhcp_conf, addr))
1017 mess->yiaddr = addr;
1018 else if (emac_len == 0)
1019 message = _("no unique-id");
1020 else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
1021 message = _("no address available");
1024 log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
1026 if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1027 return 0;
1029 if (context->netid.net)
1031 context->netid.next = netid;
1032 tagif_netid = run_tag_if(&context->netid);
1035 log_tags(tagif_netid, ntohl(mess->xid));
1037 log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1039 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1040 clear_packet(mess, end);
1041 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
1042 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1043 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1044 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1045 if (time != 0xffffffff)
1047 option_put(mess, end, OPTION_T1, 4, (time/2));
1048 option_put(mess, end, OPTION_T2, 4, (time*7)/8);
1050 do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
1051 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
1053 return dhcp_packet_size(mess, agent_id, real_end);
1055 case DHCPREQUEST:
1056 if (ignore || have_config(config, CONFIG_DISABLE))
1057 return 0;
1058 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1060 /* SELECTING or INIT_REBOOT */
1061 mess->yiaddr = option_addr(opt);
1063 /* send vendor and user class info for new or recreated lease */
1064 do_classes = 1;
1066 if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
1068 /* SELECTING */
1069 selecting = 1;
1071 if (override.s_addr != 0)
1073 if (option_addr(opt).s_addr != override.s_addr)
1074 return 0;
1076 else
1078 for (; context; context = context->current)
1079 if (context->local.s_addr == option_addr(opt).s_addr)
1080 break;
1082 if (!context)
1084 /* Handle very strange configs where clients have more than one route to the server.
1085 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1086 Have to set override to make sure we echo back the correct server-id */
1087 struct irec *intr;
1089 enumerate_interfaces(0);
1091 for (intr = daemon->interfaces; intr; intr = intr->next)
1092 if (intr->addr.sa.sa_family == AF_INET &&
1093 intr->addr.in.sin_addr.s_addr == option_addr(opt).s_addr &&
1094 intr->tftp_ok)
1095 break;
1097 if (intr)
1098 override = intr->addr.in.sin_addr;
1099 else
1101 /* In auth mode, a REQUEST sent to the wrong server
1102 should be faulted, so that the client establishes
1103 communication with us, otherwise, silently ignore. */
1104 if (!option_bool(OPT_AUTHORITATIVE))
1105 return 0;
1106 message = _("wrong server-ID");
1111 /* If a lease exists for this host and another address, squash it. */
1112 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1114 lease_prune(lease, now);
1115 lease = NULL;
1118 else
1120 /* INIT-REBOOT */
1121 if (!lease && !option_bool(OPT_AUTHORITATIVE))
1122 return 0;
1124 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1125 message = _("wrong address");
1128 else
1130 /* RENEWING or REBINDING */
1131 /* Check existing lease for this address.
1132 We allow it to be missing if dhcp-authoritative mode
1133 as long as we can allocate the lease now - checked below.
1134 This makes for a smooth recovery from a lost lease DB */
1135 if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1136 (!lease && !option_bool(OPT_AUTHORITATIVE)))
1138 /* A client rebinding will broadcast the request, so we may see it even
1139 if the lease is held by another server. Just ignore it in that case.
1140 If the request is unicast to us, then somethings wrong, NAK */
1141 if (!unicast_dest)
1142 return 0;
1143 message = _("lease not found");
1144 /* ensure we broadcast NAK */
1145 unicast_dest = 0;
1148 /* desynchronise renewals */
1149 fuzz = rand16();
1150 mess->yiaddr = mess->ciaddr;
1153 log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1155 if (!message)
1157 struct dhcp_config *addr_config;
1158 struct dhcp_context *tmp = NULL;
1160 if (have_config(config, CONFIG_ADDR))
1161 for (tmp = context; tmp; tmp = tmp->current)
1162 if (context->router.s_addr == config->addr.s_addr)
1163 break;
1165 if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1167 /* If a machine moves networks whilst it has a lease, we catch that here. */
1168 message = _("wrong network");
1169 /* ensure we broadcast NAK */
1170 unicast_dest = 0;
1173 /* Check for renewal of a lease which is outside the allowed range. */
1174 else if (!address_available(context, mess->yiaddr, tagif_netid) &&
1175 (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1176 message = _("address not available");
1178 /* Check if a new static address has been configured. Be very sure that
1179 when the client does DISCOVER, it will get the static address, otherwise
1180 an endless protocol loop will ensue. */
1181 else if (!tmp && !selecting &&
1182 have_config(config, CONFIG_ADDR) &&
1183 (!have_config(config, CONFIG_DECLINED) ||
1184 difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1185 config->addr.s_addr != mess->yiaddr.s_addr &&
1186 (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1187 message = _("static lease available");
1189 /* Check to see if the address is reserved as a static address for another host */
1190 else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1191 message = _("address reserved");
1193 else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1195 /* If a host is configured with more than one MAC address, it's OK to 'nix
1196 a lease from one of it's MACs to give the address to another. */
1197 if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1199 my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1200 print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
1201 inet_ntoa(ltmp->addr));
1202 lease = ltmp;
1204 else
1205 message = _("address in use");
1208 if (!message)
1210 if (emac_len == 0)
1211 message = _("no unique-id");
1213 else if (!lease)
1215 if ((lease = lease4_allocate(mess->yiaddr)))
1216 do_classes = 1;
1217 else
1218 message = _("no leases left");
1223 if (message)
1225 log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
1227 mess->yiaddr.s_addr = 0;
1228 clear_packet(mess, end);
1229 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1230 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1231 option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1232 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1233 a distant subnet which unicast a REQ to us won't work. */
1234 if (!unicast_dest || mess->giaddr.s_addr != 0 ||
1235 mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1237 mess->flags |= htons(0x8000); /* broadcast */
1238 mess->ciaddr.s_addr = 0;
1241 else
1243 if (context->netid.net)
1245 context->netid.next = netid;
1246 tagif_netid = run_tag_if( &context->netid);
1249 log_tags(tagif_netid, ntohl(mess->xid));
1251 if (do_classes)
1253 /* pick up INIT-REBOOT events. */
1254 lease->flags |= LEASE_CHANGED;
1256 #ifdef HAVE_SCRIPT
1257 if (daemon->lease_change_command)
1259 struct dhcp_netid *n;
1261 if (mess->giaddr.s_addr)
1262 lease->giaddr = mess->giaddr;
1264 free(lease->extradata);
1265 lease->extradata = NULL;
1266 lease->extradata_size = lease->extradata_len = 0;
1268 add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
1269 add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
1270 add_extradata_opt(lease, oui);
1271 add_extradata_opt(lease, serial);
1272 add_extradata_opt(lease, class);
1274 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
1276 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
1277 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
1278 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
1280 else
1282 add_extradata_opt(lease, NULL);
1283 add_extradata_opt(lease, NULL);
1284 add_extradata_opt(lease, NULL);
1287 /* space-concat tag set */
1288 if (!tagif_netid)
1289 add_extradata_opt(lease, NULL);
1290 else
1291 for (n = tagif_netid; n; n = n->next)
1293 struct dhcp_netid *n1;
1294 /* kill dupes */
1295 for (n1 = n->next; n1; n1 = n1->next)
1296 if (strcmp(n->net, n1->net) == 0)
1297 break;
1298 if (!n1)
1299 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
1302 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1304 int len = option_len(opt);
1305 unsigned char *ucp = option_ptr(opt, 0);
1306 /* If the user-class option started as counted strings, the first byte will be zero. */
1307 if (len != 0 && ucp[0] == 0)
1308 ucp++, len--;
1309 lease_add_extradata(lease, ucp, len, 0);
1312 #endif
1315 if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1317 domain = get_domain(mess->yiaddr);
1318 hostname = client_hostname;
1319 hostname_auth = 1;
1322 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1323 lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
1325 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1326 if (!hostname_auth)
1328 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1329 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1330 break;
1331 if (id_list)
1332 hostname = NULL;
1335 /* Last ditch, if configured, generate hostname from mac address */
1336 if (!hostname && emac_len != 0)
1338 for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
1339 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1340 break;
1341 if (id_list)
1343 int i;
1345 hostname = daemon->dhcp_buff;
1346 /* buffer is 256 bytes, 3 bytes per octet */
1347 for (i = 0; (i < emac_len) && (i < 80); i++)
1348 hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
1349 hostname = daemon->dhcp_buff;
1353 if (hostname)
1354 lease_set_hostname(lease, hostname, hostname_auth, get_domain(lease->addr), domain);
1356 lease_set_expires(lease, time, now);
1357 lease_set_interface(lease, int_index, now);
1359 if (override.s_addr != 0)
1360 lease->override = override;
1361 else
1362 override = lease->override;
1364 log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1366 clear_packet(mess, end);
1367 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1368 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1369 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1370 if (time != 0xffffffff)
1372 while (fuzz > (time/16))
1373 fuzz = fuzz/2;
1374 option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
1375 option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
1377 do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
1378 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
1381 return dhcp_packet_size(mess, agent_id, real_end);
1383 case DHCPINFORM:
1384 if (ignore || have_config(config, CONFIG_DISABLE))
1385 message = _("ignored");
1387 log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
1389 if (message || mess->ciaddr.s_addr == 0)
1390 return 0;
1392 /* For DHCPINFORM only, cope without a valid context */
1393 context = narrow_context(context, mess->ciaddr, tagif_netid);
1395 /* Find a least based on IP address if we didn't
1396 get one from MAC address/client-d */
1397 if (!lease &&
1398 (lease = lease_find_by_addr(mess->ciaddr)) &&
1399 lease->hostname)
1400 hostname = lease->hostname;
1402 if (!hostname)
1403 hostname = host_from_dns(mess->ciaddr);
1405 if (context && context->netid.net)
1407 context->netid.next = netid;
1408 tagif_netid = run_tag_if(&context->netid);
1411 log_tags(tagif_netid, ntohl(mess->xid));
1413 log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1415 if (lease)
1417 lease_set_interface(lease, int_index, now);
1418 if (override.s_addr != 0)
1419 lease->override = override;
1420 else
1421 override = lease->override;
1424 clear_packet(mess, end);
1425 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1426 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1428 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1429 we supply a utility which makes DHCPINFORM requests to get this information.
1430 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1431 which won't be true for ordinary clients, but will be true for the
1432 dhcp_lease_time utility. */
1433 if (lease && in_list(req_options, OPTION_LEASE_TIME))
1435 if (lease->expires == 0)
1436 time = 0xffffffff;
1437 else
1438 time = (unsigned int)difftime(lease->expires, now);
1439 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1442 do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1443 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
1445 *is_inform = 1; /* handle reply differently */
1446 return dhcp_packet_size(mess, agent_id, real_end);
1449 return 0;
1452 /* find a good value to use as MAC address for logging and address-allocation hashing.
1453 This is normally just the chaddr field from the DHCP packet,
1454 but eg Firewire will have hlen == 0 and use the client-id instead.
1455 This could be anything, but will normally be EUI64 for Firewire.
1456 We assume that if the first byte of the client-id equals the htype byte
1457 then the client-id is using the usual encoding and use the rest of the
1458 client-id: if not we can use the whole client-id. This should give
1459 sane MAC address logs. */
1460 unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
1461 int clid_len, unsigned char *clid, int *len_out)
1463 if (hwlen == 0 && clid && clid_len > 3)
1465 if (clid[0] == hwtype)
1467 *len_out = clid_len - 1 ;
1468 return clid + 1;
1471 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1472 if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1474 *len_out = clid_len - 1 ;
1475 return clid + 1;
1477 #endif
1479 *len_out = clid_len;
1480 return clid;
1483 *len_out = hwlen;
1484 return hwaddr;
1487 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1489 unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1491 if (opt)
1493 unsigned int req_time = option_uint(opt, 0, 4);
1494 if (req_time < 120 )
1495 req_time = 120; /* sanity */
1496 if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1497 time = req_time;
1500 return time;
1503 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1505 if (override.s_addr != 0)
1506 return override;
1507 else if (context && context->local.s_addr != 0)
1508 return context->local;
1509 else
1510 return fallback;
1513 static int sanitise(unsigned char *opt, char *buf)
1515 char *p;
1516 int i;
1518 *buf = 0;
1520 if (!opt)
1521 return 0;
1523 p = option_ptr(opt, 0);
1525 for (i = option_len(opt); i > 0; i--)
1527 char c = *p++;
1528 if (isprint((int)c))
1529 *buf++ = c;
1531 *buf = 0; /* add terminator */
1533 return 1;
1536 #ifdef HAVE_SCRIPT
1537 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
1539 if (!opt)
1540 lease_add_extradata(lease, NULL, 0, 0);
1541 else
1542 lease_add_extradata(lease, option_ptr(opt, 0), option_len(opt), 0);
1544 #endif
1546 static void log_packet(char *type, void *addr, unsigned char *ext_mac,
1547 int mac_len, char *interface, char *string, char *err, u32 xid)
1549 struct in_addr a;
1551 if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
1552 return;
1554 /* addr may be misaligned */
1555 if (addr)
1556 memcpy(&a, addr, sizeof(a));
1558 print_mac(daemon->namebuff, ext_mac, mac_len);
1560 if(option_bool(OPT_LOG_OPTS))
1561 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
1562 ntohl(xid),
1563 type,
1564 interface,
1565 addr ? inet_ntoa(a) : "",
1566 addr ? " " : "",
1567 daemon->namebuff,
1568 string ? string : "",
1569 err ? err : "");
1570 else
1571 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
1572 type,
1573 interface,
1574 addr ? inet_ntoa(a) : "",
1575 addr ? " " : "",
1576 daemon->namebuff,
1577 string ? string : "",
1578 err ? err : "");
1581 static void log_options(unsigned char *start, u32 xid)
1583 while (*start != OPTION_END)
1585 char *optname = option_string(AF_INET, start[0], option_ptr(start, 0), option_len(start), daemon->namebuff, MAXDNAME);
1587 my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d %s %s",
1588 ntohl(xid), option_len(start), start[0], optname, daemon->namebuff);
1589 start += start[1] + 2;
1593 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1595 while (1)
1597 if (p > end)
1598 return NULL;
1599 else if (*p == OPTION_END)
1600 return opt == OPTION_END ? p : NULL;
1601 else if (*p == OPTION_PAD)
1602 p++;
1603 else
1605 int opt_len;
1606 if (p > end - 2)
1607 return NULL; /* malformed packet */
1608 opt_len = option_len(p);
1609 if (p > end - (2 + opt_len))
1610 return NULL; /* malformed packet */
1611 if (*p == opt && opt_len >= minsize)
1612 return p;
1613 p += opt_len + 2;
1618 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1620 unsigned char *ret, *overload;
1622 /* skip over DHCP cookie; */
1623 if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1624 return ret;
1626 /* look for overload option. */
1627 if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1628 return NULL;
1630 /* Can we look in filename area ? */
1631 if ((overload[2] & 1) &&
1632 (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1633 return ret;
1635 /* finally try sname area */
1636 if ((overload[2] & 2) &&
1637 (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1638 return ret;
1640 return NULL;
1643 static struct in_addr option_addr(unsigned char *opt)
1645 /* this worries about unaligned data in the option. */
1646 /* struct in_addr is network byte order */
1647 struct in_addr ret;
1649 memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
1651 return ret;
1654 static unsigned int option_uint(unsigned char *opt, int offset, int size)
1656 /* this worries about unaligned data and byte order */
1657 unsigned int ret = 0;
1658 int i;
1659 unsigned char *p = option_ptr(opt, offset);
1661 for (i = 0; i < size; i++)
1662 ret = (ret << 8) | *p++;
1664 return ret;
1667 static unsigned char *dhcp_skip_opts(unsigned char *start)
1669 while (*start != 0)
1670 start += start[1] + 2;
1671 return start;
1674 /* only for use when building packet: doesn't check for bad data. */
1675 static unsigned char *find_overload(struct dhcp_packet *mess)
1677 unsigned char *p = &mess->options[0] + sizeof(u32);
1679 while (*p != 0)
1681 if (*p == OPTION_OVERLOAD)
1682 return p;
1683 p += p[1] + 2;
1685 return NULL;
1688 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end)
1690 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1691 unsigned char *overload;
1692 size_t ret;
1694 /* move agent_id back down to the end of the packet */
1695 if (agent_id)
1697 memmove(p, agent_id, real_end - agent_id);
1698 p += real_end - agent_id;
1699 memset(p, 0, real_end - p); /* in case of overlap */
1702 /* add END options to the regions. */
1703 overload = find_overload(mess);
1705 if (overload && (option_uint(overload, 0, 1) & 1))
1707 *dhcp_skip_opts(mess->file) = OPTION_END;
1708 if (option_bool(OPT_LOG_OPTS))
1709 log_options(mess->file, mess->xid);
1711 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1712 my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1714 if (overload && (option_uint(overload, 0, 1) & 2))
1716 *dhcp_skip_opts(mess->sname) = OPTION_END;
1717 if (option_bool(OPT_LOG_OPTS))
1718 log_options(mess->sname, mess->xid);
1720 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1721 my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1724 *p++ = OPTION_END;
1726 if (option_bool(OPT_LOG_OPTS))
1728 if (mess->siaddr.s_addr != 0)
1729 my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
1731 if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
1732 my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
1734 log_options(&mess->options[0] + sizeof(u32), mess->xid);
1737 ret = (size_t)(p - (unsigned char *)mess);
1739 if (ret < MIN_PACKETSZ)
1740 ret = MIN_PACKETSZ;
1742 return ret;
1745 static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1747 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1749 if (p + len + 3 >= end)
1750 /* not enough space in options area, try and use overload, if poss */
1752 unsigned char *overload;
1754 if (!(overload = find_overload(mess)) &&
1755 (mess->file[0] == 0 || mess->sname[0] == 0))
1757 /* attempt to overload fname and sname areas, we've reserved space for the
1758 overflow option previuously. */
1759 overload = p;
1760 *(p++) = OPTION_OVERLOAD;
1761 *(p++) = 1;
1764 p = NULL;
1766 /* using filename field ? */
1767 if (overload)
1769 if (mess->file[0] == 0)
1770 overload[2] |= 1;
1772 if (overload[2] & 1)
1774 p = dhcp_skip_opts(mess->file);
1775 if (p + len + 3 >= mess->file + sizeof(mess->file))
1776 p = NULL;
1779 if (!p)
1781 /* try to bring sname into play (it may be already) */
1782 if (mess->sname[0] == 0)
1783 overload[2] |= 2;
1785 if (overload[2] & 2)
1787 p = dhcp_skip_opts(mess->sname);
1788 if (p + len + 3 >= mess->sname + sizeof(mess->sname))
1789 p = NULL;
1794 if (!p)
1795 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1798 if (p)
1800 *(p++) = opt;
1801 *(p++) = len;
1804 return p;
1807 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1809 int i;
1810 unsigned char *p = free_space(mess, end, opt, len);
1812 if (p)
1813 for (i = 0; i < len; i++)
1814 *(p++) = val >> (8 * (len - (i + 1)));
1817 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
1818 char *string, int null_term)
1820 unsigned char *p;
1821 size_t len = strlen(string);
1823 if (null_term && len != 255)
1824 len++;
1826 if ((p = free_space(mess, end, opt, len)))
1827 memcpy(p, string, len);
1830 /* return length, note this only does the data part */
1831 static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1833 int len = opt->len;
1835 if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1836 len++;
1838 if (p && len != 0)
1840 if (context && (opt->flags & DHOPT_ADDR))
1842 int j;
1843 struct in_addr *a = (struct in_addr *)opt->val;
1844 for (j = 0; j < opt->len; j+=INADDRSZ, a++)
1846 /* zero means "self" (but not in vendorclass options.) */
1847 if (a->s_addr == 0)
1848 memcpy(p, &context->local, INADDRSZ);
1849 else
1850 memcpy(p, a, INADDRSZ);
1851 p += INADDRSZ;
1854 else
1855 /* empty string may be extended to "\0" by null_term */
1856 memcpy(p, opt->val ? opt->val : (unsigned char *)"", len);
1858 return len;
1861 static int in_list(unsigned char *list, int opt)
1863 int i;
1865 /* If no requested options, send everything, not nothing. */
1866 if (!list)
1867 return 1;
1869 for (i = 0; list[i] != OPTION_END; i++)
1870 if (opt == list[i])
1871 return 1;
1873 return 0;
1876 static struct dhcp_opt *option_find2(int opt)
1878 struct dhcp_opt *opts;
1880 for (opts = daemon->dhcp_opts; opts; opts = opts->next)
1881 if (opts->opt == opt && (opts->flags & DHOPT_TAGOK))
1882 return opts;
1884 return NULL;
1887 /* mark vendor-encapsulated options which match the client-supplied or
1888 config-supplied vendor class */
1889 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
1891 for (; dopt; dopt = dopt->next)
1893 dopt->flags &= ~DHOPT_VENDOR_MATCH;
1894 if (opt && (dopt->flags & DHOPT_VENDOR))
1896 int i, len = 0;
1897 if (dopt->u.vendor_class)
1898 len = strlen((char *)dopt->u.vendor_class);
1899 for (i = 0; i <= (option_len(opt) - len); i++)
1900 if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
1902 dopt->flags |= DHOPT_VENDOR_MATCH;
1903 break;
1909 static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
1910 struct dhcp_packet *mess, unsigned char *end, int null_term)
1912 int len, enc_len, ret = 0;
1913 struct dhcp_opt *start;
1914 unsigned char *p;
1916 /* find size in advance */
1917 for (enc_len = 0, start = opt; opt; opt = opt->next)
1918 if (opt->flags & flag)
1920 int new = do_opt(opt, NULL, NULL, null_term) + 2;
1921 ret = 1;
1922 if (enc_len + new <= 255)
1923 enc_len += new;
1924 else
1926 p = free_space(mess, end, encap, enc_len);
1927 for (; start && start != opt; start = start->next)
1928 if (p && (start->flags & flag))
1930 len = do_opt(start, p + 2, NULL, null_term);
1931 *(p++) = start->opt;
1932 *(p++) = len;
1933 p += len;
1935 enc_len = new;
1936 start = opt;
1940 if (enc_len != 0 &&
1941 (p = free_space(mess, end, encap, enc_len + 1)))
1943 for (; start; start = start->next)
1944 if (start->flags & flag)
1946 len = do_opt(start, p + 2, NULL, null_term);
1947 *(p++) = start->opt;
1948 *(p++) = len;
1949 p += len;
1951 *p = OPTION_END;
1954 return ret;
1957 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
1959 unsigned char *p;
1961 option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
1962 if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
1963 memcpy(p, uuid, 17);
1966 static int prune_vendor_opts(struct dhcp_netid *netid)
1968 int force = 0;
1969 struct dhcp_opt *opt;
1971 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1972 for (opt = daemon->dhcp_opts; opt; opt = opt->next)
1973 if (opt->flags & DHOPT_VENDOR_MATCH)
1975 if (!match_netid(opt->netid, netid, 1))
1976 opt->flags &= ~DHOPT_VENDOR_MATCH;
1977 else if (opt->flags & DHOPT_FORCE)
1978 force = 1;
1980 return force;
1983 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
1985 #define NUM_OPTS 4
1987 unsigned char *p, *q;
1988 struct pxe_service *service;
1989 static struct dhcp_opt *o, *ret;
1990 int i, j = NUM_OPTS - 1;
1991 struct in_addr boot_server;
1993 /* We pass back references to these, hence they are declared static */
1994 static unsigned char discovery_control;
1995 static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' };
1996 static struct dhcp_opt *fake_opts = NULL;
1998 /* Disable multicast, since we don't support it, and broadcast
1999 unless we need it */
2000 discovery_control = 3;
2002 ret = daemon->dhcp_opts;
2004 if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
2005 return ret;
2007 for (i = 0; i < NUM_OPTS; i++)
2009 fake_opts[i].flags = DHOPT_VENDOR_MATCH;
2010 fake_opts[i].netid = NULL;
2011 fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
2014 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2015 p = (unsigned char *)daemon->dhcp_buff;
2016 q = (unsigned char *)daemon->dhcp_buff3;
2018 for (i = 0, service = daemon->pxe_services; service; service = service->next)
2019 if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
2021 size_t len = strlen(service->menu);
2022 /* opt 43 max size is 255. encapsulated option has type and length
2023 bytes, so its max size is 253. */
2024 if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
2026 *(p++) = service->type >> 8;
2027 *(p++) = service->type;
2028 *(p++) = len;
2029 memcpy(p, service->menu, len);
2030 p += len;
2031 i++;
2033 else
2035 toobig:
2036 my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
2037 return daemon->dhcp_opts;
2040 boot_server = service->basename ? local :
2041 (service->sname ? a_record_from_hosts(service->sname, now) : service->server);
2043 if (boot_server.s_addr != 0)
2045 if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
2046 goto toobig;
2048 /* Boot service with known address - give it */
2049 *(q++) = service->type >> 8;
2050 *(q++) = service->type;
2051 *(q++) = 1;
2052 /* dest misaligned */
2053 memcpy(q, &boot_server.s_addr, INADDRSZ);
2054 q += INADDRSZ;
2056 else if (service->type != 0)
2057 /* We don't know the server for a service type, so we'll
2058 allow the client to broadcast for it */
2059 discovery_control = 2;
2062 /* if no prompt, wait forever if there's a choice */
2063 fake_prompt[0] = (i > 1) ? 255 : 0;
2065 if (i == 0)
2066 discovery_control = 8; /* no menu - just use use mess->filename */
2067 else
2069 ret = &fake_opts[j--];
2070 ret->len = p - (unsigned char *)daemon->dhcp_buff;
2071 ret->val = (unsigned char *)daemon->dhcp_buff;
2072 ret->opt = SUBOPT_PXE_MENU;
2074 if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
2076 ret = &fake_opts[j--];
2077 ret->len = q - (unsigned char *)daemon->dhcp_buff3;
2078 ret->val = (unsigned char *)daemon->dhcp_buff3;
2079 ret->opt = SUBOPT_PXE_SERVERS;
2083 for (o = daemon->dhcp_opts; o; o = o->next)
2084 if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
2085 break;
2087 if (!o)
2089 ret = &fake_opts[j--];
2090 ret->len = sizeof(fake_prompt);
2091 ret->val = fake_prompt;
2092 ret->opt = SUBOPT_PXE_MENU_PROMPT;
2095 ret = &fake_opts[j--];
2096 ret->len = 1;
2097 ret->opt = SUBOPT_PXE_DISCOVERY;
2098 ret->val= &discovery_control;
2100 return ret;
2103 static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
2105 memset(mess->sname, 0, sizeof(mess->sname));
2106 memset(mess->file, 0, sizeof(mess->file));
2107 memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
2108 mess->siaddr.s_addr = 0;
2111 struct dhcp_boot *find_boot(struct dhcp_netid *netid)
2113 struct dhcp_boot *boot;
2115 /* decide which dhcp-boot option we're using */
2116 for (boot = daemon->boot_config; boot; boot = boot->next)
2117 if (match_netid(boot->netid, netid, 0))
2118 break;
2119 if (!boot)
2120 /* No match, look for one without a netid */
2121 for (boot = daemon->boot_config; boot; boot = boot->next)
2122 if (match_netid(boot->netid, netid, 1))
2123 break;
2125 return boot;
2128 static void do_options(struct dhcp_context *context,
2129 struct dhcp_packet *mess,
2130 unsigned char *end,
2131 unsigned char *req_options,
2132 char *hostname,
2133 char *domain,
2134 struct dhcp_netid *netid,
2135 struct in_addr subnet_addr,
2136 unsigned char fqdn_flags,
2137 int null_term, int pxe_arch,
2138 unsigned char *uuid,
2139 int vendor_class_len,
2140 time_t now)
2142 struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2143 struct dhcp_boot *boot;
2144 unsigned char *p;
2145 int i, len, force_encap = 0;
2146 unsigned char f0 = 0, s0 = 0;
2147 int done_file = 0, done_server = 0;
2148 int done_vendor_class = 0;
2149 struct dhcp_netid *tagif;
2150 struct dhcp_netid_list *id_list;
2152 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2153 if (context)
2154 context->netid.next = NULL;
2155 tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
2157 /* logging */
2158 if (option_bool(OPT_LOG_OPTS) && req_options)
2160 char *q = daemon->namebuff;
2161 for (i = 0; req_options[i] != OPTION_END; i++)
2163 char *s = option_string(AF_INET, req_options[i], NULL, 0, NULL, 0);
2164 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2165 "%d%s%s%s",
2166 req_options[i],
2167 strlen(s) != 0 ? ":" : "",
2169 req_options[i+1] == OPTION_END ? "" : ", ");
2170 if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2172 q = daemon->namebuff;
2173 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2178 for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
2179 if ((!id_list->list) || match_netid(id_list->list, netid, 0))
2180 break;
2181 if (id_list)
2182 mess->flags |= htons(0x8000); /* force broadcast */
2184 if (context)
2185 mess->siaddr = context->local;
2187 /* See if we can send the boot stuff as options.
2188 To do this we need a requested option list, BOOTP
2189 and very old DHCP clients won't have this, we also
2190 provide an manual option to disable it.
2191 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2192 names, so we always send those. */
2193 if ((boot = find_boot(tagif)))
2195 if (boot->sname)
2197 if (!option_bool(OPT_NO_OVERRIDE) &&
2198 req_options &&
2199 in_list(req_options, OPTION_SNAME))
2200 option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2201 else
2202 strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
2205 if (boot->file)
2207 if (!option_bool(OPT_NO_OVERRIDE) &&
2208 req_options &&
2209 in_list(req_options, OPTION_FILENAME))
2210 option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2211 else
2212 strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
2215 if (boot->next_server.s_addr)
2216 mess->siaddr = boot->next_server;
2217 else if (boot->tftp_sname)
2218 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
2220 else
2221 /* Use the values of the relevant options if no dhcp-boot given and
2222 they're not explicitly asked for as options. OPTION_END is used
2223 as an internal way to specify siaddr without using dhcp-boot, for use in
2224 dhcp-optsfile. */
2226 if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
2227 (opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2229 strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
2230 done_file = 1;
2233 if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2234 (opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2236 strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
2237 done_server = 1;
2240 if ((opt = option_find2(OPTION_END)))
2241 mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
2244 /* We don't want to do option-overload for BOOTP, so make the file and sname
2245 fields look like they are in use, even when they aren't. This gets restored
2246 at the end of this function. */
2248 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2250 f0 = mess->file[0];
2251 mess->file[0] = 1;
2252 s0 = mess->sname[0];
2253 mess->sname[0] = 1;
2256 /* At this point, if mess->sname or mess->file are zeroed, they are available
2257 for option overload, reserve space for the overload option. */
2258 if (mess->file[0] == 0 || mess->sname[0] == 0)
2259 end -= 3;
2261 /* rfc3011 says this doesn't need to be in the requested options list. */
2262 if (subnet_addr.s_addr)
2263 option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2265 /* replies to DHCPINFORM may not have a valid context */
2266 if (context)
2268 if (!option_find2(OPTION_NETMASK))
2269 option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2271 /* May not have a "guessed" broadcast address if we got no packets via a relay
2272 from this net yet (ie just unicast renewals after a restart */
2273 if (context->broadcast.s_addr &&
2274 !option_find2(OPTION_BROADCAST))
2275 option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2277 /* Same comments as broadcast apply, and also may not be able to get a sensible
2278 default when using subnet select. User must configure by steam in that case. */
2279 if (context->router.s_addr &&
2280 in_list(req_options, OPTION_ROUTER) &&
2281 !option_find2(OPTION_ROUTER))
2282 option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2284 if (daemon->port == NAMESERVER_PORT &&
2285 in_list(req_options, OPTION_DNSSERVER) &&
2286 !option_find2(OPTION_DNSSERVER))
2287 option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2290 if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
2291 !option_find2(OPTION_DOMAINNAME))
2292 option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2294 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2295 if (hostname)
2297 if (in_list(req_options, OPTION_HOSTNAME) &&
2298 !option_find2(OPTION_HOSTNAME))
2299 option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2301 if (fqdn_flags != 0)
2303 len = strlen(hostname) + 3;
2305 if (fqdn_flags & 0x04)
2306 len += 2;
2307 else if (null_term)
2308 len++;
2310 if (domain)
2311 len += strlen(domain) + 1;
2312 else if (fqdn_flags & 0x04)
2313 len--;
2315 if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2317 *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */
2318 *(p++) = 255;
2319 *(p++) = 255;
2321 if (fqdn_flags & 0x04)
2323 p = do_rfc1035_name(p, hostname);
2324 if (domain)
2326 p = do_rfc1035_name(p, domain);
2327 *p++ = 0;
2330 else
2332 memcpy(p, hostname, strlen(hostname));
2333 p += strlen(hostname);
2334 if (domain)
2336 *(p++) = '.';
2337 memcpy(p, domain, strlen(domain));
2338 p += strlen(domain);
2340 if (null_term)
2341 *(p++) = 0;
2347 for (opt = config_opts; opt; opt = opt->next)
2349 int optno = opt->opt;
2351 /* netids match and not encapsulated? */
2352 if (!(opt->flags & DHOPT_TAGOK))
2353 continue;
2355 /* was it asked for, or are we sending it anyway? */
2356 if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2357 continue;
2359 /* prohibit some used-internally options */
2360 if (optno == OPTION_CLIENT_FQDN ||
2361 optno == OPTION_MAXMESSAGE ||
2362 optno == OPTION_OVERLOAD ||
2363 optno == OPTION_PAD ||
2364 optno == OPTION_END)
2365 continue;
2367 if (optno == OPTION_SNAME && done_server)
2368 continue;
2370 if (optno == OPTION_FILENAME && done_file)
2371 continue;
2373 /* For the options we have default values on
2374 dhc-option=<optionno> means "don't include this option"
2375 not "include a zero-length option" */
2376 if (opt->len == 0 &&
2377 (optno == OPTION_NETMASK ||
2378 optno == OPTION_BROADCAST ||
2379 optno == OPTION_ROUTER ||
2380 optno == OPTION_DNSSERVER ||
2381 optno == OPTION_DOMAINNAME ||
2382 optno == OPTION_HOSTNAME))
2383 continue;
2385 /* vendor-class comes from elsewhere for PXE */
2386 if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2387 continue;
2389 /* always force null-term for filename and servername - buggy PXE again. */
2390 len = do_opt(opt, NULL, context,
2391 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2393 if ((p = free_space(mess, end, optno, len)))
2395 do_opt(opt, p, context,
2396 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2398 /* If we send a vendor-id, revisit which vendor-ops we consider
2399 it appropriate to send. */
2400 if (optno == OPTION_VENDOR_ID)
2402 match_vendor_opts(p - 2, config_opts);
2403 done_vendor_class = 1;
2408 /* Now send options to be encapsulated in arbitrary options,
2409 eg dhcp-option=encap:172,17,.......
2410 Also handle vendor-identifying vendor-encapsulated options,
2411 dhcp-option = vi-encap:13,17,.......
2412 The may be more that one "outer" to do, so group
2413 all the options which match each outer in turn. */
2414 for (opt = config_opts; opt; opt = opt->next)
2415 opt->flags &= ~DHOPT_ENCAP_DONE;
2417 for (opt = config_opts; opt; opt = opt->next)
2419 int flags;
2421 if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
2423 int found = 0;
2424 struct dhcp_opt *o;
2426 if (opt->flags & DHOPT_ENCAP_DONE)
2427 continue;
2429 for (len = 0, o = config_opts; o; o = o->next)
2431 int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
2433 o->flags &= ~DHOPT_ENCAP_MATCH;
2435 if (!(o->flags & flags) || opt->u.encap != o->u.encap)
2436 continue;
2438 o->flags |= DHOPT_ENCAP_DONE;
2439 if (match_netid(o->netid, tagif, 1) &&
2440 ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
2442 o->flags |= DHOPT_ENCAP_MATCH;
2443 found = 1;
2444 len += do_opt(o, NULL, NULL, 0) + 2;
2448 if (found)
2450 if (flags & DHOPT_ENCAPSULATE)
2451 do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2452 else if (len > 250)
2453 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
2454 else if ((p = free_space(mess, end, OPTION_VENDOR_IDENT_OPT, len + 5)))
2456 int swap_ent = htonl(opt->u.encap);
2457 memcpy(p, &swap_ent, 4);
2458 p += 4;
2459 *(p++) = len;
2460 for (o = config_opts; o; o = o->next)
2461 if (o->flags & DHOPT_ENCAP_MATCH)
2463 len = do_opt(o, p + 2, NULL, 0);
2464 *(p++) = o->opt;
2465 *(p++) = len;
2466 p += len;
2473 force_encap = prune_vendor_opts(tagif);
2475 if (context && pxe_arch != -1)
2477 pxe_misc(mess, end, uuid);
2478 config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
2481 if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
2482 do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) &&
2483 pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
2484 (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
2485 /* If we send vendor encapsulated options, and haven't already sent option 60,
2486 echo back the value we got from the client. */
2487 memcpy(p, daemon->dhcp_buff3, vendor_class_len);
2489 /* restore BOOTP anti-overload hack */
2490 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2492 mess->file[0] = f0;
2493 mess->sname[0] = s0;
2497 #endif