1/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2
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.
7
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.
12
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/>.
15*/
16
17#include "dnsmasq.h"
18
19#ifdef HAVE_DHCP
20
21#define BOOTREQUEST              1
22#define BOOTREPLY                2
23#define DHCP_COOKIE              0x63825363
24
25/* The Linux in-kernel DHCP client silently ignores any packet
26   smaller than this. Sigh...........   */
27#define MIN_PACKETSZ             300
28
29#define OPTION_PAD               0
30#define OPTION_NETMASK           1
31#define OPTION_ROUTER            3
32#define OPTION_DNSSERVER         6
33#define OPTION_HOSTNAME          12
34#define OPTION_DOMAINNAME        15
35#define OPTION_BROADCAST         28
36#define OPTION_VENDOR_CLASS_OPT  43
37#define OPTION_REQUESTED_IP      50
38#define OPTION_LEASE_TIME        51
39#define OPTION_OVERLOAD          52
40#define OPTION_MESSAGE_TYPE      53
41#define OPTION_SERVER_IDENTIFIER 54
42#define OPTION_REQUESTED_OPTIONS 55
43#define OPTION_MESSAGE           56
44#define OPTION_MAXMESSAGE        57
45#define OPTION_T1                58
46#define OPTION_T2                59
47#define OPTION_VENDOR_ID         60
48#define OPTION_CLIENT_ID         61
49#define OPTION_SNAME             66
50#define OPTION_FILENAME          67
51#define OPTION_USER_CLASS        77
52#define OPTION_CLIENT_FQDN       81
53#define OPTION_AGENT_ID          82
54#define OPTION_ARCH              93
55#define OPTION_PXE_UUID          97
56#define OPTION_SUBNET_SELECT     118
57#define OPTION_END               255
58
59#define SUBOPT_CIRCUIT_ID        1
60#define SUBOPT_REMOTE_ID         2
61#define SUBOPT_SUBNET_SELECT     5     /* RFC 3527 */
62#define SUBOPT_SUBSCR_ID         6     /* RFC 3393 */
63#define SUBOPT_SERVER_OR         11    /* RFC 5107 */
64
65#define SUBOPT_PXE_BOOT_ITEM     71    /* PXE standard */
66#define SUBOPT_PXE_DISCOVERY     6
67#define SUBOPT_PXE_SERVERS       8
68#define SUBOPT_PXE_MENU          9
69#define SUBOPT_PXE_MENU_PROMPT   10
70
71#define DHCPDISCOVER             1
72#define DHCPOFFER                2
73#define DHCPREQUEST              3
74#define DHCPDECLINE              4
75#define DHCPACK                  5
76#define DHCPNAK                  6
77#define DHCPRELEASE              7
78#define DHCPINFORM               8
79
80#define have_config(config, mask) ((config) && ((config)->flags & (mask)))
81#define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
82#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
83
84static int sanitise(unsigned char *opt, char *buf);
85static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
86static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
87static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
88static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
89			      int opt, char *string, int null_term);
90static struct in_addr option_addr(unsigned char *opt);
91static struct in_addr option_addr_arr(unsigned char *opt, int offset);
92static unsigned int option_uint(unsigned char *opt, int i, int size);
93static void log_packet(char *type, void *addr, unsigned char *ext_mac,
94		       int mac_len, char *interface, char *string, u32 xid);
95static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
96static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
97static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid,
98			       unsigned char *agent_id, unsigned char *real_end);
99static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
100static void do_options(struct dhcp_context *context,
101		       struct dhcp_packet *mess,
102		       unsigned char *real_end,
103		       unsigned char *req_options,
104		       char *hostname,
105		       char *domain, char *config_domain,
106		       struct dhcp_netid *netid,
107		       struct in_addr subnet_addr,
108		       unsigned char fqdn_flags,
109		       int null_term, int pxearch,
110		       unsigned char *uuid);
111
112
113static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
114static void do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
115static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
116static int prune_vendor_opts(struct dhcp_netid *netid);
117static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid);
118struct dhcp_boot *find_boot(struct dhcp_netid *netid);
119
120
121size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
122		  size_t sz, time_t now, int unicast_dest, int *is_inform)
123{
124  unsigned char *opt, *clid = NULL;
125  struct dhcp_lease *ltmp, *lease = NULL;
126  struct dhcp_vendor *vendor;
127  struct dhcp_mac *mac;
128  struct dhcp_netid_list *id_list;
129  int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
130  struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
131  unsigned char *end = (unsigned char *)(mess + 1);
132  unsigned char *real_end = (unsigned char *)(mess + 1);
133  char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
134  int hostname_auth = 0, borken_opt = 0;
135  unsigned char *req_options = NULL;
136  char *message = NULL;
137  unsigned int time;
138  struct dhcp_config *config;
139  struct dhcp_netid *netid;
140  struct in_addr subnet_addr, fallback, override;
141  unsigned short fuzz = 0;
142  unsigned int mess_type = 0;
143  unsigned char fqdn_flags = 0;
144  unsigned char *agent_id = NULL, *uuid = NULL;
145  unsigned char *emac = NULL;
146  int emac_len = 0;
147  struct dhcp_netid known_id, iface_id;
148  struct dhcp_opt *o;
149  unsigned char pxe_uuid[17];
150
151  subnet_addr.s_addr = override.s_addr = 0;
152
153  /* set tag with name == interface */
154  iface_id.net = iface_name;
155  iface_id.next = NULL;
156  netid = &iface_id;
157
158  if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
159    return 0;
160
161  if (mess->htype == 0 && mess->hlen != 0)
162    return 0;
163
164  /* check for DHCP rather than BOOTP */
165  if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
166    {
167      mess_type = option_uint(opt, 0, 1);
168
169      /* only insist on a cookie for DHCP. */
170      if (*((u32 *)&mess->options) != htonl(DHCP_COOKIE))
171	return 0;
172
173      /* two things to note here: expand_buf may move the packet,
174	 so reassign mess from daemon->packet. Also, the size
175	 sent includes the IP and UDP headers, hence the magic "-28" */
176      if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
177	{
178	  size_t size = (size_t)option_uint(opt, 0, 2) - 28;
179
180	  if (size > DHCP_PACKET_MAX)
181	    size = DHCP_PACKET_MAX;
182	  else if (size < sizeof(struct dhcp_packet))
183	    size = sizeof(struct dhcp_packet);
184
185	  if (expand_buf(&daemon->dhcp_packet, size))
186	    {
187	      mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
188	      real_end = end = ((unsigned char *)mess) + size;
189	    }
190	}
191
192      /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
193	 it can affect the context-determination code. */
194      if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
195	mess->ciaddr.s_addr = 0;
196
197      if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
198	{
199	  /* Any agent-id needs to be copied back out, verbatim, as the last option
200	     in the packet. Here, we shift it to the very end of the buffer, if it doesn't
201	     get overwritten, then it will be shuffled back at the end of processing.
202	     Note that the incoming options must not be overwritten here, so there has to
203	     be enough free space at the end of the packet to copy the option. */
204	  unsigned char *sopt;
205	  unsigned int total = option_len(opt) + 2;
206	  unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
207	  if (last_opt && last_opt < end - total)
208	    {
209	      end -= total;
210	      agent_id = end;
211	      memcpy(agent_id, opt, total);
212	    }
213
214	  /* look for RFC3527 Link selection sub-option */
215	  if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
216	    subnet_addr = option_addr(sopt);
217
218	  /* look for RFC5107 server-identifier-override */
219	  if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
220	    override = option_addr(sopt);
221
222	  /* if a circuit-id or remote-is option is provided, exact-match to options. */
223	  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
224	    {
225	      int search;
226
227	      if (vendor->match_type == MATCH_CIRCUIT)
228		search = SUBOPT_CIRCUIT_ID;
229	      else if (vendor->match_type == MATCH_REMOTE)
230		search = SUBOPT_REMOTE_ID;
231	      else if (vendor->match_type == MATCH_SUBSCRIBER)
232		search = SUBOPT_SUBSCR_ID;
233	      else
234		continue;
235
236	      if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
237		  vendor->len == option_len(sopt) &&
238		  memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
239		{
240		  vendor->netid.next = netid;
241		  netid = &vendor->netid;
242		  break;
243		}
244	    }
245	}
246
247      /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
248      if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
249	subnet_addr = option_addr(opt);
250
251      /* If there is no client identifier option, use the hardware address */
252      if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
253	{
254	  clid_len = option_len(opt);
255	  clid = option_ptr(opt, 0);
256	}
257
258      /* do we have a lease in store? */
259      lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
260
261      /* If this request is missing a clid, but we've seen one before,
262	 use it again for option matching etc. */
263      if (lease && !clid && lease->clid)
264	{
265	  clid_len = lease->clid_len;
266	  clid = lease->clid;
267	}
268
269      /* find mac to use for logging and hashing */
270      emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
271    }
272
273  for (mac = daemon->dhcp_macs; mac; mac = mac->next)
274    if (mac->hwaddr_len == mess->hlen &&
275	(mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
276	memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
277      {
278	mac->netid.next = netid;
279	netid = &mac->netid;
280      }
281
282  /* Determine network for this packet. Our caller will have already linked all the
283     contexts which match the addresses of the receiving interface but if the
284     machine has an address already, or came via a relay, or we have a subnet selector,
285     we search again. If we don't have have a giaddr or explicit subnet selector,
286     use the ciaddr. This is necessary because a  machine which got a lease via a
287     relay won't use the relay to renew. If matching a ciaddr fails but we have a context
288     from the physical network, continue using that to allow correct DHCPNAK generation later. */
289  if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
290    {
291      struct dhcp_context *context_tmp, *context_new = NULL;
292      struct in_addr addr;
293      int force = 0;
294
295      if (subnet_addr.s_addr)
296	{
297	  addr = subnet_addr;
298	  force = 1;
299	}
300      else if (mess->giaddr.s_addr)
301	{
302	  addr = mess->giaddr;
303	  force = 1;
304	}
305      else
306	{
307	  /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
308	  addr = mess->ciaddr;
309	  for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
310	    if (context_tmp->netmask.s_addr &&
311		is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
312		is_same_net(addr, context_tmp->end, context_tmp->netmask))
313	      {
314		context_new = context;
315		break;
316	      }
317	}
318
319      if (!context_new)
320	for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
321	  if (context_tmp->netmask.s_addr  &&
322	      is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
323	      is_same_net(addr, context_tmp->end, context_tmp->netmask))
324	    {
325	      context_tmp->current = context_new;
326	      context_new = context_tmp;
327	    }
328
329      if (context_new || force)
330	context = context_new;
331
332    }
333
334  if (!context)
335    {
336//      my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
337//		subnet_addr.s_addr ? _("with subnet selector") : _("via"),
338//		subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
339      return 0;
340    }
341
342  /* keep _a_ local address available. */
343  fallback = context->local;
344
345  if (daemon->options & OPT_LOG_OPTS)
346    {
347      struct dhcp_context *context_tmp;
348      for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
349	{
350	  strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
351	  if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
352	    my_syslog(MS_DHCP | LOG_INFO, _("%u Available DHCP subnet: %s/%s"),
353		      ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
354	  else
355	    my_syslog(MS_DHCP | LOG_INFO, _("%u Available DHCP range: %s -- %s"),
356		      ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
357	}
358    }
359
360  mess->op = BOOTREPLY;
361
362  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
363		       mess->chaddr, mess->hlen, mess->htype, NULL);
364
365  /* set "known" tag for known hosts */
366  if (config)
367    {
368      known_id.net = "known";
369      known_id.next = netid;
370      netid = &known_id;
371    }
372
373  if (mess_type == 0)
374    {
375      /* BOOTP request */
376      struct dhcp_netid id, bootp_id;
377      struct in_addr *logaddr = NULL;
378
379      /* must have a MAC addr for bootp */
380      if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
381	return 0;
382
383      if (have_config(config, CONFIG_DISABLE))
384	message = _("disabled");
385
386      end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
387
388      if (have_config(config, CONFIG_NAME))
389	{
390	  hostname = config->hostname;
391	  domain = config->domain;
392	}
393
394      if (have_config(config, CONFIG_NETID))
395	{
396	  config->netid.next = netid;
397	  netid = &config->netid;
398	}
399
400      /* Match incoming filename field as a netid. */
401      if (mess->file[0])
402	{
403	  memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
404	  daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
405	  id.net = (char *)daemon->dhcp_buff2;
406	  id.next = netid;
407	  netid = &id;
408	}
409
410      /* Add "bootp" as a tag to allow different options, address ranges etc
411	 for BOOTP clients */
412      bootp_id.net = "bootp";
413      bootp_id.next = netid;
414      netid = &bootp_id;
415
416      for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
417	if (match_netid(id_list->list, netid, 0))
418	  message = _("ignored");
419
420      if (!message)
421	{
422	  int nailed = 0;
423
424	  if (have_config(config, CONFIG_ADDR))
425	    {
426	      nailed = 1;
427	      logaddr = &config->addr;
428	      mess->yiaddr = config->addr;
429	      if ((lease = lease_find_by_addr(config->addr)) &&
430		  (lease->hwaddr_len != mess->hlen ||
431		   lease->hwaddr_type != mess->htype ||
432		   memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
433		message = _("address in use");
434	    }
435	  else
436	    {
437	      if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
438		  !address_available(context, lease->addr, netid))
439		{
440		   if (lease)
441		     {
442		       /* lease exists, wrong network. */
443		       lease_prune(lease, now);
444		       lease = NULL;
445		     }
446		   if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, netid, now))
447		     message = _("no address available");
448		}
449	      else
450		mess->yiaddr = lease->addr;
451	    }
452
453	  if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
454	    message = _("wrong network");
455	  else if (context->netid.net)
456	    {
457	      context->netid.next = netid;
458	      netid = &context->netid;
459	    }
460
461	  if (!message && !nailed)
462	    {
463	      for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
464		if ((!id_list->list) || match_netid(id_list->list, netid, 0))
465		  break;
466	      if (!id_list)
467		message = _("no address configured");
468	    }
469
470	  if (!message &&
471	      !lease &&
472	      (!(lease = lease_allocate(mess->yiaddr))))
473	    message = _("no leases left");
474
475	  if (!message)
476	    {
477	      logaddr = &mess->yiaddr;
478
479	      lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
480	      if (hostname)
481		lease_set_hostname(lease, hostname, 1);
482	      /* infinite lease unless nailed in dhcp-host line. */
483	      lease_set_expires(lease,
484				have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
485				now);
486	      lease_set_interface(lease, int_index);
487
488	      clear_packet(mess, end);
489	      do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
490			 domain, netid, subnet_addr, 0, 0, 0, NULL);
491	    }
492	}
493
494      log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
495
496      return message ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
497    }
498
499  if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
500    {
501      /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
502      int len = option_len(opt);
503      char *pq = daemon->dhcp_buff;
504      unsigned char *pp, *op = option_ptr(opt, 0);
505
506      fqdn_flags = *op;
507      len -= 3;
508      op += 3;
509      pp = op;
510
511      /* Always force update, since the client has no way to do it itself. */
512      if (!(fqdn_flags & 0x01))
513	fqdn_flags |= 0x02;
514
515      fqdn_flags &= ~0x08;
516      fqdn_flags |= 0x01;
517
518      if (fqdn_flags & 0x04)
519	while (*op != 0 && ((op + (*op) + 1) - pp) < len)
520	  {
521	    memcpy(pq, op+1, *op);
522	    pq += *op;
523	    op += (*op)+1;
524	    *(pq++) = '.';
525	  }
526      else
527	{
528	  memcpy(pq, op, len);
529	  if (len > 0 && op[len-1] == 0)
530	    borken_opt = 1;
531	  pq += len + 1;
532	}
533
534      if (pq != daemon->dhcp_buff)
535	pq--;
536
537      *pq = 0;
538
539      if (legal_hostname(daemon->dhcp_buff))
540	offer_hostname = client_hostname = daemon->dhcp_buff;
541    }
542  else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
543    {
544      int len = option_len(opt);
545      memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
546      /* Microsoft clients are broken, and need zero-terminated strings
547	 in options. We detect this state here, and do the same in
548	 any options we send */
549      if (len > 0 && daemon->dhcp_buff[len-1] == 0)
550	borken_opt = 1;
551      else
552	daemon->dhcp_buff[len] = 0;
553      if (legal_hostname(daemon->dhcp_buff))
554	client_hostname = daemon->dhcp_buff;
555    }
556
557  if (client_hostname && daemon->options & OPT_LOG_OPTS)
558    my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
559
560  if (have_config(config, CONFIG_NAME))
561    {
562      hostname = config->hostname;
563      domain = config->domain;
564      hostname_auth = 1;
565      /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
566      if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
567        offer_hostname = hostname;
568    }
569  else if (client_hostname)
570    {
571      domain = strip_hostname(client_hostname);
572
573      if (strlen(client_hostname) != 0)
574	{
575	  hostname = client_hostname;
576	  if (!config)
577	    {
578	      /* Search again now we have a hostname.
579		 Only accept configs without CLID and HWADDR here, (they won't match)
580		 to avoid impersonation by name. */
581	      struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
582						    mess->chaddr, mess->hlen,
583						    mess->htype, hostname);
584	      if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
585		{
586		  config = new;
587		  /* set "known" tag for known hosts */
588		  known_id.net = "known";
589		  known_id.next = netid;
590		  netid = &known_id;
591		}
592	    }
593	}
594    }
595
596  if (have_config(config, CONFIG_NETID))
597    {
598      config->netid.next = netid;
599      netid = &config->netid;
600    }
601
602  /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
603     Otherwise assume the option is an array, and look for a matching element.
604     If no data given, existance of the option is enough. */
605  for (o = daemon->dhcp_match; o; o = o->next)
606    {
607      int i, matched = 0;
608
609      if (!(opt = option_find(mess, sz, o->opt, 1)) ||
610	  o->len > option_len(opt))
611	continue;
612
613      if (o->len == 0)
614	matched = 1;
615      else if (o->flags & DHOPT_HEX)
616	{
617	  if (memcmp_masked(o->val, option_ptr(opt, 0), o->len, o->u.wildcard_mask))
618	    matched = 1;
619	}
620      else
621	for (i = 0; i <= (option_len(opt) - o->len); )
622	  {
623	    if (memcmp(o->val, option_ptr(opt, i), o->len) == 0)
624	      {
625		matched = 1;
626		break;
627	      }
628
629	    if (o->flags & DHOPT_STRING)
630	      i++;
631	    else
632	      i += o->len;
633	  }
634
635      if (matched)
636	{
637	  o->netid->next = netid;
638	  netid = o->netid;
639	}
640    }
641
642  /* user-class options are, according to RFC3004, supposed to contain
643     a set of counted strings. Here we check that this is so (by seeing
644     if the counts are consistent with the overall option length) and if
645     so zero the counts so that we don't get spurious matches between
646     the vendor string and the counts. If the lengths don't add up, we
647     assume that the option is a single string and non RFC3004 compliant
648     and just do the substring match. dhclient provides these broken options.
649     The code, later, which sends user-class data to the lease-change script
650     relies on the transformation done here.
651  */
652
653  if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
654    {
655      unsigned char *ucp = option_ptr(opt, 0);
656      int tmp, j;
657      for (j = 0; j < option_len(opt); j += ucp[j] + 1);
658      if (j == option_len(opt))
659	for (j = 0; j < option_len(opt); j = tmp)
660	  {
661	    tmp = j + ucp[j] + 1;
662	    ucp[j] = 0;
663	  }
664    }
665
666  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
667    {
668      int mopt;
669
670      if (vendor->match_type == MATCH_VENDOR)
671	mopt = OPTION_VENDOR_ID;
672      else if (vendor->match_type == MATCH_USER)
673	mopt = OPTION_USER_CLASS;
674      else
675	continue;
676
677      if ((opt = option_find(mess, sz, mopt, 1)))
678	{
679	  int i;
680	  for (i = 0; i <= (option_len(opt) - vendor->len); i++)
681	    if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
682	      {
683		vendor->netid.next = netid;
684		netid = &vendor->netid;
685		break;
686	      }
687	}
688    }
689
690  /* mark vendor-encapsulated options which match the client-supplied vendor class */
691  match_vendor_opts(option_find(mess, sz, OPTION_VENDOR_ID, 1), daemon->dhcp_opts);
692
693  if (daemon->options & OPT_LOG_OPTS)
694    {
695      if (sanitise(option_find(mess, sz, OPTION_VENDOR_ID, 1), daemon->namebuff))
696	my_syslog(MS_DHCP | LOG_INFO, _("%u Vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
697      if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
698	my_syslog(MS_DHCP | LOG_INFO, _("%u User class: %s"), ntohl(mess->xid), daemon->namebuff);
699    }
700
701  /* if all the netids in the ignore list are present, ignore this client */
702  for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
703    if (match_netid(id_list->list, netid, 0))
704      ignore = 1;
705
706  /* Can have setting to ignore the client ID for a particular MAC address or hostname */
707  if (have_config(config, CONFIG_NOCLID))
708    clid = NULL;
709
710  /* Check if client is PXE client. */
711  if (daemon->enable_pxe &&
712      (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
713      strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
714    {
715      if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
716	{
717	  memcpy(pxe_uuid, option_ptr(opt, 0), 17);
718	  uuid = pxe_uuid;
719	}
720
721      /* Check if this is really a PXE bootserver request, and handle specially if so. */
722      if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
723	  (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
724	  (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
725	{
726	  struct pxe_service *service;
727	  int type = option_uint(opt, 0, 2);
728	  int layer = option_uint(opt, 2, 2);
729	  unsigned char save71[4];
730	  struct dhcp_opt opt71;
731
732	  if (ignore)
733	    return 0;
734
735	  if (layer & 0x8000)
736	    {
737	      my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
738	      return 0;
739	    }
740
741	  memcpy(save71, option_ptr(opt, 0), 4);
742
743	  for (service = daemon->pxe_services; service; service = service->next)
744	    if (service->type == type)
745	      break;
746
747	  if (!service || !service->basename)
748	    return 0;
749
750	  clear_packet(mess, end);
751
752	  mess->yiaddr = mess->ciaddr;
753	  mess->ciaddr.s_addr = 0;
754	  if (service->server.s_addr != 0)
755	    mess->siaddr = service->server;
756	  else
757	    mess->siaddr = context->local;
758
759	  snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
760	  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
761	  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
762	  pxe_misc(mess, end, uuid);
763
764	  prune_vendor_opts(netid);
765	  opt71.val = save71;
766	  opt71.opt = SUBOPT_PXE_BOOT_ITEM;
767	  opt71.len = 4;
768	  opt71.flags = DHOPT_VENDOR_MATCH;
769	  opt71.netid = NULL;
770	  opt71.next = daemon->dhcp_opts;
771	  do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
772
773	  log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);
774	  return dhcp_packet_size(mess, netid, agent_id, real_end);
775	}
776
777      if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
778	{
779	  pxearch = option_uint(opt, 0, 2);
780
781	  /* proxy DHCP here. The DHCPREQUEST stuff is for gPXE */
782	  if ((mess_type == DHCPDISCOVER || mess_type == DHCPREQUEST) &&
783	      (context->flags & CONTEXT_PROXY))
784	    {
785	      struct dhcp_boot *boot = find_boot(netid);
786
787	      mess->yiaddr.s_addr = 0;
788	      if  (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
789		{
790		  mess->ciaddr.s_addr = 0;
791		  mess->flags |= htons(0x8000); /* broadcast */
792		}
793
794	      clear_packet(mess, end);
795
796	      /* Provide the bootfile here, for gPXE, and in case we have no menu items
797		 and set discovery_control = 8 */
798	      if (boot)
799		{
800		  if (boot->next_server.s_addr)
801		    mess->siaddr = boot->next_server;
802
803		  if (boot->file)
804		    strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
805		}
806
807	      option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
808			 mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
809	      option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
810	      pxe_misc(mess, end, uuid);
811	      prune_vendor_opts(netid);
812	      do_encap_opts(pxe_opts(pxearch, netid), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
813
814	      log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy" : "proxy-ignored", mess->xid);
815	      return ignore ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
816	    }
817	}
818    }
819
820  /* if we're just a proxy server, go no further */
821  if (context->flags & CONTEXT_PROXY)
822    return 0;
823
824  if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
825    {
826      req_options = (unsigned char *)daemon->dhcp_buff2;
827      memcpy(req_options, option_ptr(opt, 0), option_len(opt));
828      req_options[option_len(opt)] = OPTION_END;
829    }
830
831  switch (mess_type)
832    {
833    case DHCPDECLINE:
834      if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
835	  option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
836	return 0;
837
838      /* sanitise any message. Paranoid? Moi? */
839      sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
840
841      if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
842	return 0;
843
844      log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid);
845
846      if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
847	lease_prune(lease, now);
848
849      if (have_config(config, CONFIG_ADDR) &&
850	  config->addr.s_addr == option_addr(opt).s_addr)
851	{
852	  prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
853	  my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
854		    inet_ntoa(config->addr), daemon->dhcp_buff);
855	  config->flags |= CONFIG_DECLINED;
856	  config->decline_time = now;
857	}
858      else
859	/* make sure this host gets a different address next time. */
860	for (; context; context = context->current)
861	  context->addr_epoch++;
862
863      return 0;
864
865    case DHCPRELEASE:
866      if (!(context = narrow_context(context, mess->ciaddr, netid)) ||
867	  !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
868	  option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
869	return 0;
870
871      if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
872	lease_prune(lease, now);
873      else
874	message = _("unknown lease");
875
876      log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
877
878      return 0;
879
880    case DHCPDISCOVER:
881      if (ignore || have_config(config, CONFIG_DISABLE))
882	{
883	  message = _("ignored");
884	  opt = NULL;
885	}
886      else
887	{
888	  struct in_addr addr, conf;
889
890	  addr.s_addr = conf.s_addr = 0;
891
892	  if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
893	    addr = option_addr(opt);
894
895	  if (have_config(config, CONFIG_ADDR))
896	    {
897	      char *addrs = inet_ntoa(config->addr);
898
899	      if ((ltmp = lease_find_by_addr(config->addr)) &&
900		  ltmp != lease &&
901		  !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
902		{
903		  int len;
904		  unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
905						       ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
906		  my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
907			    addrs, print_mac(daemon->namebuff, mac, len));
908		}
909	      else
910		{
911		  struct dhcp_context *tmp;
912		  for (tmp = context; tmp; tmp = tmp->current)
913		    if (context->router.s_addr == config->addr.s_addr)
914		      break;
915		  if (tmp)
916		    my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
917		  else if (have_config(config, CONFIG_DECLINED) &&
918			   difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
919		    my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
920		  else
921		    conf = config->addr;
922		}
923	    }
924
925	  if (conf.s_addr)
926	    mess->yiaddr = conf;
927	  else if (lease &&
928		   address_available(context, lease->addr, netid) &&
929		   !config_find_by_address(daemon->dhcp_conf, lease->addr))
930	    mess->yiaddr = lease->addr;
931	  else if (opt && address_available(context, addr, netid) && !lease_find_by_addr(addr) &&
932		   !config_find_by_address(daemon->dhcp_conf, addr))
933	    mess->yiaddr = addr;
934	  else if (emac_len == 0)
935	    message = _("no unique-id");
936	  else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, netid, now))
937	    message = _("no address available");
938	}
939
940      log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid);
941
942      if (message || !(context = narrow_context(context, mess->yiaddr, netid)))
943	return 0;
944
945      log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
946
947      if (context->netid.net)
948	{
949	  context->netid.next = netid;
950	  netid = &context->netid;
951	}
952
953      time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
954      clear_packet(mess, end);
955      option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
956      option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
957      option_put(mess, end, OPTION_LEASE_TIME, 4, time);
958      /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
959      if (time != 0xffffffff)
960	{
961	  option_put(mess, end, OPTION_T1, 4, (time/2));
962	  option_put(mess, end, OPTION_T2, 4, (time*7)/8);
963	}
964      do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
965		 domain, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
966
967      return dhcp_packet_size(mess, netid, agent_id, real_end);
968
969    case DHCPREQUEST:
970      if (ignore || have_config(config, CONFIG_DISABLE))
971	return 0;
972      if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
973	{
974	  /* SELECTING  or INIT_REBOOT */
975	  mess->yiaddr = option_addr(opt);
976
977	  /* send vendor and user class info for new or recreated lease */
978	  do_classes = 1;
979
980	  if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
981	    {
982	      /* SELECTING */
983	      selecting = 1;
984
985	      if (override.s_addr != 0)
986		{
987		  if (option_addr(opt).s_addr != override.s_addr)
988		    return 0;
989		}
990	      else
991		{
992		  for (; context; context = context->current)
993		    if (context->local.s_addr == option_addr(opt).s_addr)
994		      break;
995
996		  if (!context)
997		    {
998		      /* In auth mode, a REQUEST sent to the wrong server
999			 should be faulted, so that the client establishes
1000			 communication with us, otherwise, silently ignore. */
1001		      if (!(daemon->options & OPT_AUTHORITATIVE))
1002			return 0;
1003		      message = _("wrong server-ID");
1004		    }
1005		}
1006
1007	      /* If a lease exists for this host and another address, squash it. */
1008	      if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1009		{
1010		  lease_prune(lease, now);
1011		  lease = NULL;
1012		}
1013	    }
1014	  else
1015	    {
1016	      /* INIT-REBOOT */
1017	      if (!lease && !(daemon->options & OPT_AUTHORITATIVE))
1018		return 0;
1019
1020	      if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1021		{
1022		  message = _("wrong address");
1023		  /* avoid loops when client brain-dead */
1024		  lease_prune(lease, now);
1025		  lease = NULL;
1026		}
1027	    }
1028	}
1029      else
1030	{
1031	  /* RENEWING or REBINDING */
1032	  /* Check existing lease for this address.
1033	     We allow it to be missing if dhcp-authoritative mode
1034	     as long as we can allocate the lease now - checked below.
1035	     This makes for a smooth recovery from a lost lease DB */
1036	  if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1037	      (!lease && !(daemon->options & OPT_AUTHORITATIVE)))
1038	    {
1039	      message = _("lease not found");
1040	      /* ensure we broadcast NAK */
1041	      unicast_dest = 0;
1042	    }
1043	  /* desynchronise renewals */
1044	  fuzz = rand16();
1045	  mess->yiaddr = mess->ciaddr;
1046	}
1047
1048      log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
1049
1050      if (!message)
1051	{
1052	  struct dhcp_config *addr_config;
1053	  struct dhcp_context *tmp = NULL;
1054
1055	  if (have_config(config, CONFIG_ADDR))
1056	    for (tmp = context; tmp; tmp = tmp->current)
1057	      if (context->router.s_addr == config->addr.s_addr)
1058		break;
1059
1060	  if (!(context = narrow_context(context, mess->yiaddr, netid)))
1061	    {
1062	      /* If a machine moves networks whilst it has a lease, we catch that here. */
1063	      message = _("wrong network");
1064	      /* ensure we broadcast NAK */
1065	      unicast_dest = 0;
1066	    }
1067
1068	  /* Check for renewal of a lease which is outside the allowed range. */
1069	  else if (!address_available(context, mess->yiaddr, netid) &&
1070		   (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1071	    message = _("address not available");
1072
1073	  /* Check if a new static address has been configured. Be very sure that
1074	     when the client does DISCOVER, it will get the static address, otherwise
1075	     an endless protocol loop will ensue. */
1076	  else if (!tmp && !selecting &&
1077		   have_config(config, CONFIG_ADDR) &&
1078		   (!have_config(config, CONFIG_DECLINED) ||
1079		    difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1080		   config->addr.s_addr != mess->yiaddr.s_addr &&
1081		   (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1082	    message = _("static lease available");
1083
1084	  /* Check to see if the address is reserved as a static address for another host */
1085	  else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1086	    message = _("address reserved");
1087
1088	  else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1089	    {
1090	      /* If a host is configured with more than one MAC address, it's OK to 'nix
1091		 a lease from one of it's MACs to give the address to another. */
1092	      if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1093		{
1094		  my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1095			    print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
1096			    inet_ntoa(ltmp->addr));
1097		  lease = ltmp;
1098		}
1099	      else
1100		message = _("address in use");
1101	    }
1102
1103	  if (!message)
1104	    {
1105	      if (emac_len == 0)
1106		message = _("no unique-id");
1107
1108	      else if (!lease)
1109		{
1110		  if ((lease = lease_allocate(mess->yiaddr)))
1111		    do_classes = 1;
1112		  else
1113		    message = _("no leases left");
1114		}
1115	    }
1116	}
1117
1118      if (message)
1119	{
1120	  log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid);
1121
1122	  mess->yiaddr.s_addr = 0;
1123	  clear_packet(mess, end);
1124	  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1125	  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1126	  option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1127	  /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1128	     a distant subnet which unicast a REQ to us won't work. */
1129	  if (!unicast_dest || mess->giaddr.s_addr != 0 ||
1130	      mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1131	    {
1132	      mess->flags |= htons(0x8000); /* broadcast */
1133	      mess->ciaddr.s_addr = 0;
1134	    }
1135	}
1136      else
1137	{
1138	   if (do_classes)
1139	     {
1140	       if (mess->giaddr.s_addr)
1141		 lease->giaddr = mess->giaddr;
1142
1143	       lease->changed = 1;
1144	       /* copy user-class and vendor class into new lease, for the script */
1145	       if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1146		 {
1147		   int len = option_len(opt);
1148		   unsigned char *ucp = option_ptr(opt, 0);
1149		   /* If the user-class option started as counted strings, the first byte will be zero. */
1150		   if (len != 0 && ucp[0] == 0)
1151		     ucp++, len--;
1152		   free(lease->userclass);
1153		   if ((lease->userclass = whine_malloc(len+1)))
1154		     {
1155		       memcpy(lease->userclass, ucp, len);
1156		       lease->userclass[len] = 0;
1157		       lease->userclass_len = len+1;
1158		     }
1159		 }
1160	       if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
1161		 {
1162		   int len = option_len(opt);
1163		   unsigned char *ucp = option_ptr(opt, 0);
1164		   free(lease->vendorclass);
1165		   if ((lease->vendorclass = whine_malloc(len+1)))
1166		     {
1167		       memcpy(lease->vendorclass, ucp, len);
1168		       lease->vendorclass[len] = 0;
1169		       lease->vendorclass_len = len+1;
1170		     }
1171		 }
1172	       if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
1173		 {
1174		   int len = option_len(opt);
1175		   unsigned char *ucp = option_ptr(opt, 0);
1176		   free(lease->supplied_hostname);
1177		   if ((lease->supplied_hostname = whine_malloc(len+1)))
1178		     {
1179		       memcpy(lease->supplied_hostname, ucp, len);
1180		       lease->supplied_hostname[len] = 0;
1181		       lease->supplied_hostname_len = len+1;
1182		     }
1183		 }
1184	     }
1185
1186	   if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1187	     {
1188	      hostname = client_hostname;
1189	      hostname_auth = 1;
1190	    }
1191
1192	  if (context->netid.net)
1193	    {
1194	      context->netid.next = netid;
1195	      netid = &context->netid;
1196	    }
1197
1198	  time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1199	  lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len);
1200
1201	  /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1202	  if (!hostname_auth)
1203	    {
1204	      for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1205		if ((!id_list->list) || match_netid(id_list->list, netid, 0))
1206		  break;
1207	      if (id_list)
1208		hostname = NULL;
1209	    }
1210	  if (hostname)
1211	    lease_set_hostname(lease, hostname, hostname_auth);
1212
1213	  lease_set_expires(lease, time, now);
1214	  lease_set_interface(lease, int_index);
1215
1216	  if (override.s_addr != 0)
1217	    lease->override = override;
1218	  else
1219	    override = lease->override;
1220
1221	  log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid);
1222
1223	  clear_packet(mess, end);
1224	  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1225	  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1226	  option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1227	  if (time != 0xffffffff)
1228	    {
1229	      while (fuzz > (time/16))
1230		fuzz = fuzz/2;
1231	      option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
1232	      option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
1233	    }
1234	  do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
1235		     domain, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
1236	}
1237
1238      return dhcp_packet_size(mess, netid, agent_id, real_end);
1239
1240    case DHCPINFORM:
1241      if (ignore || have_config(config, CONFIG_DISABLE))
1242	message = _("ignored");
1243
1244      log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
1245
1246      if (message || mess->ciaddr.s_addr == 0)
1247	return 0;
1248
1249      /* For DHCPINFORM only, cope without a valid context */
1250      context = narrow_context(context, mess->ciaddr, netid);
1251
1252      /* Find a least based on IP address if we didn't
1253	 get one from MAC address/client-d */
1254      if (!lease &&
1255	  (lease = lease_find_by_addr(mess->ciaddr)) &&
1256	  lease->hostname)
1257	hostname = lease->hostname;
1258
1259      if (!hostname)
1260	hostname = host_from_dns(mess->ciaddr);
1261
1262      log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);
1263
1264      if (context && context->netid.net)
1265	{
1266	  context->netid.next = netid;
1267	  netid = &context->netid;
1268	}
1269
1270      if (lease)
1271	{
1272	  if (override.s_addr != 0)
1273	    lease->override = override;
1274	  else
1275	    override = lease->override;
1276	}
1277
1278      clear_packet(mess, end);
1279      option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1280      option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1281
1282      if (lease)
1283	{
1284	  if (lease->expires == 0)
1285	    time = 0xffffffff;
1286	  else
1287	    time = (unsigned int)difftime(lease->expires, now);
1288	  option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1289	  lease_set_interface(lease, int_index);
1290	}
1291
1292      do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1293		 domain, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
1294
1295      *is_inform = 1; /* handle reply differently */
1296      return dhcp_packet_size(mess, netid, agent_id, real_end);
1297    }
1298
1299  return 0;
1300}
1301
1302/* find a good value to use as MAC address for logging and address-allocation hashing.
1303   This is normally just the chaddr field from the DHCP packet,
1304   but eg Firewire will have hlen == 0 and use the client-id instead.
1305   This could be anything, but will normally be EUI64 for Firewire.
1306   We assume that if the first byte of the client-id equals the htype byte
1307   then the client-id is using the usual encoding and use the rest of the
1308   client-id: if not we can use the whole client-id. This should give
1309   sane MAC address logs. */
1310unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
1311				      int clid_len, unsigned char *clid, int *len_out)
1312{
1313  if (hwlen == 0 && clid && clid_len > 3)
1314    {
1315      if (clid[0]  == hwtype)
1316	{
1317	  *len_out = clid_len - 1 ;
1318	  return clid + 1;
1319	}
1320
1321#if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1322      if (clid[0] ==  ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1323	{
1324	  *len_out = clid_len - 1 ;
1325	  return clid + 1;
1326	}
1327#endif
1328
1329      *len_out = clid_len;
1330      return clid;
1331    }
1332
1333  *len_out = hwlen;
1334  return hwaddr;
1335}
1336
1337static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1338{
1339  unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1340
1341  if (opt)
1342    {
1343      unsigned int req_time = option_uint(opt, 0, 4);
1344      if (req_time < 120 )
1345	req_time = 120; /* sanity */
1346      if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1347	time = req_time;
1348    }
1349
1350  return time;
1351}
1352
1353static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1354{
1355  if (override.s_addr != 0)
1356    return override;
1357  else if (context)
1358    return context->local;
1359  else
1360    return fallback;
1361}
1362
1363static int sanitise(unsigned char *opt, char *buf)
1364{
1365  char *p;
1366  int i;
1367
1368  *buf = 0;
1369
1370  if (!opt)
1371    return 0;
1372
1373  p = option_ptr(opt, 0);
1374
1375  for (i = option_len(opt); i > 0; i--)
1376    {
1377      char c = *p++;
1378      if (isprint((int)c))
1379	*buf++ = c;
1380    }
1381  *buf = 0; /* add terminator */
1382
1383  return 1;
1384}
1385
1386static void log_packet(char *type, void *addr, unsigned char *ext_mac,
1387		       int mac_len, char *interface, char *string, u32 xid)
1388{
1389  struct in_addr a;
1390
1391  /* addr may be misaligned */
1392  if (addr)
1393    memcpy(&a, addr, sizeof(a));
1394
1395  print_mac(daemon->namebuff, ext_mac, mac_len);
1396
1397  if(daemon->options & OPT_LOG_OPTS)
1398     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s",
1399	       ntohl(xid),
1400	       type,
1401	       interface,
1402	       addr ? inet_ntoa(a) : "",
1403	       addr ? " " : "",
1404	       daemon->namebuff,
1405	       string ? string : "");
1406  else
1407    my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s",
1408	      type,
1409	      interface,
1410	      addr ? inet_ntoa(a) : "",
1411	      addr ? " " : "",
1412	      daemon->namebuff,
1413	      string ? string : "");
1414}
1415
1416static void log_options(unsigned char *start, u32 xid)
1417{
1418  while (*start != OPTION_END)
1419    {
1420      int is_ip, is_name, i;
1421      char *text = option_string(start[0], &is_ip, &is_name);
1422      unsigned char trunc = option_len(start);
1423
1424      if (is_ip)
1425	for (daemon->namebuff[0]= 0, i = 0; i <= trunc - INADDRSZ; i += INADDRSZ)
1426	  {
1427	    if (i != 0)
1428	      strncat(daemon->namebuff, ", ", 256 - strlen(daemon->namebuff));
1429	    strncat(daemon->namebuff, inet_ntoa(option_addr_arr(start, i)), 256 - strlen(daemon->namebuff));
1430	  }
1431      else if (!is_name || !sanitise(start, daemon->namebuff))
1432	{
1433	  if (trunc > 13)
1434	    trunc = 13;
1435	  print_mac(daemon->namebuff, option_ptr(start, 0), trunc);
1436	}
1437
1438      my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d%s%s%s%s%s",
1439		ntohl(xid), option_len(start), start[0],
1440		text ? ":" : "", text ? text : "",
1441		trunc == 0 ? "" : "  ",
1442		trunc == 0 ? "" : daemon->namebuff,
1443		trunc == option_len(start) ? "" : "...");
1444      start += start[1] + 2;
1445    }
1446}
1447
1448static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1449{
1450  while (1)
1451    {
1452      if (p > end)
1453	return NULL;
1454      else if (*p == OPTION_END)
1455	return opt == OPTION_END ? p : NULL;
1456      else if (*p == OPTION_PAD)
1457	p++;
1458      else
1459	{
1460	  int opt_len;
1461	  if (p > end - 2)
1462	    return NULL; /* malformed packet */
1463	  opt_len = option_len(p);
1464	  if (p > end - (2 + opt_len))
1465	    return NULL; /* malformed packet */
1466	  if (*p == opt && opt_len >= minsize)
1467	    return p;
1468	  p += opt_len + 2;
1469	}
1470    }
1471}
1472
1473static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1474{
1475  unsigned char *ret, *overload;
1476
1477  /* skip over DHCP cookie; */
1478  if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1479    return ret;
1480
1481  /* look for overload option. */
1482  if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1483    return NULL;
1484
1485  /* Can we look in filename area ? */
1486  if ((overload[2] & 1) &&
1487      (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1488    return ret;
1489
1490  /* finally try sname area */
1491  if ((overload[2] & 2) &&
1492      (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1493    return ret;
1494
1495  return NULL;
1496}
1497
1498static struct in_addr option_addr_arr(unsigned char *opt, int offset)
1499{
1500  /* this worries about unaligned data in the option. */
1501  /* struct in_addr is network byte order */
1502  struct in_addr ret;
1503
1504  memcpy(&ret, option_ptr(opt, offset), INADDRSZ);
1505
1506  return ret;
1507}
1508
1509static struct in_addr option_addr(unsigned char *opt)
1510{
1511  return option_addr_arr(opt, 0);
1512}
1513
1514static unsigned int option_uint(unsigned char *opt, int offset, int size)
1515{
1516  /* this worries about unaligned data and byte order */
1517  unsigned int ret = 0;
1518  int i;
1519  unsigned char *p = option_ptr(opt, offset);
1520
1521  for (i = 0; i < size; i++)
1522    ret = (ret << 8) | *p++;
1523
1524  return ret;
1525}
1526
1527static unsigned char *dhcp_skip_opts(unsigned char *start)
1528{
1529  while (*start != 0)
1530    start += start[1] + 2;
1531  return start;
1532}
1533
1534/* only for use when building packet: doesn't check for bad data. */
1535static unsigned char *find_overload(struct dhcp_packet *mess)
1536{
1537  unsigned char *p = &mess->options[0] + sizeof(u32);
1538
1539  while (*p != 0)
1540    {
1541      if (*p == OPTION_OVERLOAD)
1542	return p;
1543      p += p[1] + 2;
1544    }
1545  return NULL;
1546}
1547
1548static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid,
1549			       unsigned char *agent_id, unsigned char *real_end)
1550{
1551  unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1552  unsigned char *overload;
1553  size_t ret;
1554  struct dhcp_netid_list *id_list;
1555  struct dhcp_netid *n;
1556
1557  /* move agent_id back down to the end of the packet */
1558  if (agent_id)
1559    {
1560      memmove(p, agent_id, real_end - agent_id);
1561      p += real_end - agent_id;
1562      memset(p, 0, real_end - p); /* in case of overlap */
1563    }
1564
1565  /* We do logging too */
1566  if (netid && (daemon->options & OPT_LOG_OPTS))
1567    {
1568      char *s = daemon->namebuff;
1569      for (*s = 0; netid; netid = netid->next)
1570	{
1571	  /* kill dupes. */
1572	  for (n = netid->next; n; n = n->next)
1573	    if (strcmp(netid->net, n->net) == 0)
1574	      break;
1575
1576	  if (!n)
1577	    {
1578	      strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
1579	      if (netid->next)
1580		strncat (s, ", ", (MAXDNAME-1) - strlen(s));
1581	    }
1582	}
1583      my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s);
1584    }
1585
1586  /* add END options to the regions. */
1587  overload = find_overload(mess);
1588
1589  if (overload && (option_uint(overload, 0, 1) & 1))
1590    {
1591      *dhcp_skip_opts(mess->file) = OPTION_END;
1592      if (daemon->options & OPT_LOG_OPTS)
1593	log_options(mess->file, mess->xid);
1594    }
1595  else if ((daemon->options & OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1596    my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1597
1598  if (overload && (option_uint(overload, 0, 1) & 2))
1599    {
1600      *dhcp_skip_opts(mess->sname) = OPTION_END;
1601      if (daemon->options & OPT_LOG_OPTS)
1602	log_options(mess->sname, mess->xid);
1603    }
1604  else if ((daemon->options & OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1605    my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1606
1607
1608  *p++ = OPTION_END;
1609
1610  if (daemon->options & OPT_LOG_OPTS)
1611    {
1612      if (mess->siaddr.s_addr != 0)
1613	my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
1614
1615      log_options(&mess->options[0] + sizeof(u32), mess->xid);
1616    }
1617
1618  for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
1619    if (match_netid(id_list->list, netid, 0))
1620      mess->flags |= htons(0x8000); /* force broadcast */
1621
1622  ret = (size_t)(p - (unsigned char *)mess);
1623
1624  if (ret < MIN_PACKETSZ)
1625    ret = MIN_PACKETSZ;
1626
1627  return ret;
1628}
1629
1630static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1631{
1632  unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1633
1634  if (p + len + 3 >= end)
1635    /* not enough space in options area, try and use overload, if poss */
1636    {
1637      unsigned char *overload;
1638
1639      if (!(overload = find_overload(mess)) &&
1640	  (mess->file[0] == 0 || mess->sname[0] == 0))
1641	{
1642	  /* attempt to overload fname and sname areas, we've reserved space for the
1643	     overflow option previuously. */
1644	  overload = p;
1645	  *(p++) = OPTION_OVERLOAD;
1646	  *(p++) = 1;
1647	}
1648
1649      p = NULL;
1650
1651      /* using filename field ? */
1652      if (overload)
1653	{
1654	  if (mess->file[0] == 0)
1655	    overload[2] |= 1;
1656
1657	  if (overload[2] & 1)
1658	    {
1659	      p = dhcp_skip_opts(mess->file);
1660	      if (p + len + 3 >= mess->file + sizeof(mess->file))
1661		p = NULL;
1662	    }
1663
1664	  if (!p)
1665	    {
1666	      /* try to bring sname into play (it may be already) */
1667	      if (mess->sname[0] == 0)
1668		overload[2] |= 2;
1669
1670	      if (overload[2] & 2)
1671		{
1672		  p = dhcp_skip_opts(mess->sname);
1673		  if (p + len + 3 >= mess->sname + sizeof(mess->file))
1674		    p = NULL;
1675		}
1676	    }
1677	}
1678
1679      if (!p)
1680	my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1681    }
1682
1683  if (p)
1684    {
1685      *(p++) = opt;
1686      *(p++) = len;
1687    }
1688
1689  return p;
1690}
1691
1692static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1693{
1694  int i;
1695  unsigned char *p = free_space(mess, end, opt, len);
1696
1697  if (p)
1698    for (i = 0; i < len; i++)
1699      *(p++) = val >> (8 * (len - (i + 1)));
1700}
1701
1702static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
1703			      char *string, int null_term)
1704{
1705  unsigned char *p;
1706  size_t len = strlen(string);
1707
1708  if (null_term && len != 255)
1709    len++;
1710
1711  if ((p = free_space(mess, end, opt, len)))
1712    memcpy(p, string, len);
1713}
1714
1715/* return length, note this only does the data part */
1716static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1717{
1718  int len = opt->len;
1719
1720  if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1721    len++;
1722
1723  if (p && len != 0)
1724    {
1725      if (context && (opt->flags & DHOPT_ADDR))
1726	{
1727	  int j;
1728	  struct in_addr *a = (struct in_addr *)opt->val;
1729	  for (j = 0; j < opt->len; j+=INADDRSZ, a++)
1730	    {
1731	      /* zero means "self" (but not in vendorclass options.) */
1732	      if (a->s_addr == 0)
1733		memcpy(p, &context->local, INADDRSZ);
1734	      else
1735		memcpy(p, a, INADDRSZ);
1736	      p += INADDRSZ;
1737	    }
1738	}
1739      else
1740	memcpy(p, opt->val, len);
1741    }
1742  return len;
1743}
1744
1745static int in_list(unsigned char *list, int opt)
1746{
1747  int i;
1748
1749   /* If no requested options, send everything, not nothing. */
1750  if (!list)
1751    return 1;
1752
1753  for (i = 0; list[i] != OPTION_END; i++)
1754    if (opt == list[i])
1755      return 1;
1756
1757  return 0;
1758}
1759
1760static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *opts, int opt)
1761{
1762  struct dhcp_opt *tmp;
1763  for (tmp = opts; tmp; tmp = tmp->next)
1764    if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)))
1765      if (match_netid(tmp->netid, netid, netid ? 0 : 1))
1766	return tmp;
1767
1768  return netid ? option_find2(NULL, opts, opt) : NULL;
1769}
1770
1771/* mark vendor-encapsulated options which match the client-supplied  or
1772   config-supplied vendor class */
1773static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
1774{
1775  for (; dopt; dopt = dopt->next)
1776    {
1777      dopt->flags &= ~DHOPT_VENDOR_MATCH;
1778      if (opt && (dopt->flags & DHOPT_VENDOR))
1779	{
1780	  int i, len = 0;
1781	  if (dopt->u.vendor_class)
1782	    len = strlen((char *)dopt->u.vendor_class);
1783	  for (i = 0; i <= (option_len(opt) - len); i++)
1784	    if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
1785	      {
1786		dopt->flags |= DHOPT_VENDOR_MATCH;
1787		break;
1788	      }
1789	}
1790    }
1791}
1792
1793static void do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
1794			  struct dhcp_packet *mess, unsigned char *end, int null_term)
1795{
1796  int len, enc_len;
1797  struct dhcp_opt *start;
1798  unsigned char *p;
1799
1800  /* find size in advance */
1801  for (enc_len = 0, start = opt; opt; opt = opt->next)
1802    if (opt->flags & flag)
1803      {
1804	int new = do_opt(opt, NULL, NULL, null_term) + 2;
1805	if (enc_len + new <= 255)
1806	  enc_len += new;
1807	else
1808	  {
1809	    p = free_space(mess, end, encap, enc_len);
1810	    for (; start && start != opt; start = start->next)
1811	      if (p && (start->flags & flag))
1812		{
1813		  len = do_opt(start, p + 2, NULL, null_term);
1814		  *(p++) = start->opt;
1815		  *(p++) = len;
1816		  p += len;
1817		}
1818	    enc_len = new;
1819	    start = opt;
1820	  }
1821      }
1822
1823  if (enc_len != 0 &&
1824      (p = free_space(mess, end, encap, enc_len + 1)))
1825    {
1826      for (; start; start = start->next)
1827	if (start->flags & flag)
1828	  {
1829	    len = do_opt(start, p + 2, NULL, null_term);
1830	    *(p++) = start->opt;
1831	    *(p++) = len;
1832	    p += len;
1833	  }
1834      *p = OPTION_END;
1835    }
1836}
1837
1838static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
1839{
1840  unsigned char *p;
1841
1842  option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
1843  if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
1844    memcpy(p, uuid, 17);
1845}
1846
1847static int prune_vendor_opts(struct dhcp_netid *netid)
1848{
1849  int force = 0;
1850  struct dhcp_opt *opt;
1851
1852  /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
1853  for (opt = daemon->dhcp_opts; opt; opt = opt->next)
1854    if (opt->flags & DHOPT_VENDOR_MATCH)
1855      {
1856	if (!match_netid(opt->netid, netid, 1))
1857	  opt->flags &= ~DHOPT_VENDOR_MATCH;
1858	else if (opt->flags & DHOPT_FORCE)
1859	  force = 1;
1860      }
1861  return force;
1862}
1863
1864static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid)
1865{
1866#define NUM_OPTS 4
1867
1868  unsigned  char *p, *q;
1869  struct pxe_service *service;
1870  static struct dhcp_opt *o, *ret;
1871  int i, j = NUM_OPTS - 1;
1872
1873  /* We pass back references to these, hence they are declared static */
1874  static unsigned char discovery_control;
1875  static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' };
1876  static struct dhcp_opt *fake_opts = NULL;
1877
1878  /* We are found by broadcast, so disable multicast. It gets switched on again
1879     if we point to other servers and don't give a unicast address. Note that
1880     we don't provide our own address for services we are the boot server for because unicast
1881     discovery is to port 4011 and we don't listen there. If you are using proxy DHCP
1882     and DHCP relays, the relay will need to forward to the proxy too. */
1883  discovery_control = 2;
1884
1885  ret = daemon->dhcp_opts;
1886
1887  if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
1888    return ret;
1889
1890  for (i = 0; i < NUM_OPTS; i++)
1891    {
1892      fake_opts[i].flags = DHOPT_VENDOR_MATCH;
1893      fake_opts[i].netid = NULL;
1894      fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
1895    }
1896
1897  /* create the data for the PXE_MENU and PXE_SERVERS options. */
1898  p = (unsigned char *)daemon->dhcp_buff;
1899  q = (unsigned char *)daemon->dhcp_buff2;
1900
1901  for (i = 0, service = daemon->pxe_services; service; service = service->next)
1902    if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
1903      {
1904	size_t len = strlen(service->menu);
1905	/* opt 43 max size is 255. encapsulated option has type and length
1906	   bytes, so its max size is 253. */
1907	if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
1908	  {
1909	    *(p++) = service->type >> 8;
1910	    *(p++) = service->type;
1911	    *(p++) = len;
1912	    memcpy(p, service->menu, len);
1913	    p += len;
1914	    i++;
1915	  }
1916	else
1917	  {
1918	  toobig:
1919	    my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
1920	    return daemon->dhcp_opts;
1921	  }
1922
1923	if (!service->basename)
1924	  {
1925	    if (service->server.s_addr != 0)
1926	      {
1927		if (q - (unsigned char *)daemon->dhcp_buff2 + 3 + INADDRSZ >= 253)
1928		  goto toobig;
1929
1930		/* Boot service with known address - give it */
1931		*(q++) = service->type >> 8;
1932		*(q++) = service->type;
1933		*(q++) = 1;
1934		/* dest misaligned */
1935		memcpy(q, &service->server.s_addr, INADDRSZ);
1936		q += INADDRSZ;
1937	      }
1938	    else if (service->type != 0)
1939	      /* We're not supplying a server, so let the client multicast.
1940		 type zero is "local boot" so no need for M/C on that. */
1941	      discovery_control = 0;
1942	  }
1943      }
1944
1945  /* if no prompt, wait forever if there's a choice */
1946  fake_prompt[0] = (i > 1) ? 255 : 0;
1947
1948  if (i == 0)
1949    discovery_control = 8; /* no menu - just use use mess->filename */
1950  else
1951    {
1952      ret = &fake_opts[j--];
1953      ret->len = p - (unsigned char *)daemon->dhcp_buff;
1954      ret->val = (unsigned char *)daemon->dhcp_buff;
1955      ret->opt = SUBOPT_PXE_MENU;
1956
1957      if (q - (unsigned char *)daemon->dhcp_buff2 != 0)
1958	{
1959	  ret = &fake_opts[j--];
1960	  ret->len = q - (unsigned char *)daemon->dhcp_buff2;
1961	  ret->val = (unsigned char *)daemon->dhcp_buff2;
1962	  ret->opt = SUBOPT_PXE_SERVERS;
1963	}
1964    }
1965
1966  for (o = daemon->dhcp_opts; o; o = o->next)
1967    if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
1968      break;
1969
1970  if (!o)
1971    {
1972      ret = &fake_opts[j--];
1973      ret->len = sizeof(fake_prompt);
1974      ret->val = fake_prompt;
1975      ret->opt = SUBOPT_PXE_MENU_PROMPT;
1976    }
1977
1978  if (discovery_control != 0)
1979    {
1980      ret = &fake_opts[j--];
1981      ret->len = 1;
1982      ret->opt = SUBOPT_PXE_DISCOVERY;
1983      ret->val= &discovery_control;
1984    }
1985
1986  return ret;
1987}
1988
1989static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
1990{
1991  memset(mess->sname, 0, sizeof(mess->sname));
1992  memset(mess->file, 0, sizeof(mess->file));
1993  memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
1994  mess->siaddr.s_addr = 0;
1995}
1996
1997struct dhcp_boot *find_boot(struct dhcp_netid *netid)
1998{
1999  struct dhcp_boot *boot;
2000
2001  /* decide which dhcp-boot option we're using */
2002  for (boot = daemon->boot_config; boot; boot = boot->next)
2003    if (match_netid(boot->netid, netid, 0))
2004      break;
2005  if (!boot)
2006    /* No match, look for one without a netid */
2007    for (boot = daemon->boot_config; boot; boot = boot->next)
2008      if (match_netid(boot->netid, netid, 1))
2009	break;
2010
2011  return boot;
2012}
2013
2014static void do_options(struct dhcp_context *context,
2015		       struct dhcp_packet *mess,
2016		       unsigned char *end,
2017		       unsigned char *req_options,
2018		       char *hostname,
2019		       char *domain, char *config_domain,
2020		       struct dhcp_netid *netid,
2021		       struct in_addr subnet_addr,
2022		       unsigned char fqdn_flags,
2023		       int null_term, int pxe_arch,
2024		       unsigned char *uuid)
2025{
2026  struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2027  struct dhcp_boot *boot;
2028  unsigned char *p;
2029  int i, len, force_encap = 0;
2030  unsigned char f0 = 0, s0 = 0;
2031  int done_file = 0, done_server = 0;
2032
2033  if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
2034    my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname);
2035
2036  /* logging */
2037  if ((daemon->options & OPT_LOG_OPTS) && req_options)
2038    {
2039      char *q = daemon->namebuff;
2040      for (i = 0; req_options[i] != OPTION_END; i++)
2041	{
2042	  char *s = option_string(req_options[i], NULL, NULL);
2043	  q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2044			"%d%s%s%s",
2045			req_options[i],
2046			s ? ":" : "",
2047			s ? s : "",
2048			req_options[i+1] == OPTION_END ? "" : ", ");
2049	  if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2050	    {
2051	      q = daemon->namebuff;
2052	      my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2053	    }
2054	}
2055    }
2056
2057  if (context)
2058    mess->siaddr = context->local;
2059
2060  /* See if we can send the boot stuff as options.
2061     To do this we need a requested option list, BOOTP
2062     and very old DHCP clients won't have this, we also
2063     provide an manual option to disable it.
2064     Some PXE ROMs have bugs (surprise!) and need zero-terminated
2065     names, so we always send those.  */
2066  if ((boot = find_boot(netid)))
2067    {
2068      if (boot->sname)
2069	{
2070	  if (!(daemon->options & OPT_NO_OVERRIDE) &&
2071	      req_options &&
2072	      in_list(req_options, OPTION_SNAME))
2073	    option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2074	  else
2075	    strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
2076	}
2077
2078      if (boot->file)
2079	{
2080	  if (!(daemon->options & OPT_NO_OVERRIDE) &&
2081	      req_options &&
2082	      in_list(req_options, OPTION_FILENAME))
2083	    option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2084	  else
2085	    strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
2086	}
2087
2088      if (boot->next_server.s_addr)
2089	mess->siaddr = boot->next_server;
2090    }
2091  else
2092    /* Use the values of the relevant options if no dhcp-boot given and
2093       they're not explicitly asked for as options. OPTION_END is used
2094       as an internal way to specify siaddr without using dhcp-boot, for use in
2095       dhcp-optsfile. */
2096    {
2097      if ((!req_options || !in_list(req_options, OPTION_FILENAME)) && mess->file[0] == 0 &&
2098	  (opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2099	{
2100	  strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
2101	  done_file = 1;
2102	}
2103
2104      if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2105	  (opt = option_find2(netid, config_opts, OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2106	{
2107	  strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
2108	  done_server = 1;
2109	}
2110
2111      if ((opt = option_find2(netid, config_opts, OPTION_END)))
2112	mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
2113    }
2114
2115  /* We don't want to do option-overload for BOOTP, so make the file and sname
2116     fields look like they are in use, even when they aren't. This gets restored
2117     at the end of this function. */
2118
2119  if (!req_options || (daemon->options & OPT_NO_OVERRIDE))
2120    {
2121      f0 = mess->file[0];
2122      mess->file[0] = 1;
2123      s0 = mess->sname[0];
2124      mess->sname[0] = 1;
2125    }
2126
2127  /* At this point, if mess->sname or mess->file are zeroed, they are available
2128     for option overload, reserve space for the overload option. */
2129  if (mess->file[0] == 0 || mess->sname[0] == 0)
2130    end -= 3;
2131
2132  /* rfc3011 says this doesn't need to be in the requested options list. */
2133  if (subnet_addr.s_addr)
2134    option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2135
2136  /* replies to DHCPINFORM may not have a valid context */
2137  if (context)
2138    {
2139      if (!option_find2(netid, config_opts, OPTION_NETMASK))
2140	option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2141
2142      /* May not have a "guessed" broadcast address if we got no packets via a relay
2143	 from this net yet (ie just unicast renewals after a restart */
2144      if (context->broadcast.s_addr &&
2145	  !option_find2(netid, config_opts, OPTION_BROADCAST))
2146	option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2147
2148      /* Same comments as broadcast apply, and also may not be able to get a sensible
2149	 default when using subnet select.  User must configure by steam in that case. */
2150      if (context->router.s_addr &&
2151	  in_list(req_options, OPTION_ROUTER) &&
2152	  !option_find2(netid, config_opts, OPTION_ROUTER))
2153	option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2154
2155      if (in_list(req_options, OPTION_DNSSERVER) &&
2156	  !option_find2(netid, config_opts, OPTION_DNSSERVER))
2157	option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2158    }
2159
2160  if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
2161      !option_find2(netid, config_opts, OPTION_DOMAINNAME))
2162    option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2163
2164  /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2165  if (hostname)
2166    {
2167      if (in_list(req_options, OPTION_HOSTNAME) &&
2168	  !option_find2(netid, config_opts, OPTION_HOSTNAME))
2169	option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2170
2171      if (fqdn_flags != 0)
2172	{
2173	  len = strlen(hostname) + 3;
2174
2175	  if (fqdn_flags & 0x04)
2176	    len += 2;
2177	  else if (null_term)
2178	    len++;
2179
2180	  if (domain)
2181	    len += strlen(domain) + 1;
2182
2183	  if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2184	    {
2185	      *(p++) = fqdn_flags;
2186	      *(p++) = 255;
2187	      *(p++) = 255;
2188
2189	      if (fqdn_flags & 0x04)
2190		{
2191		  p = do_rfc1035_name(p, hostname);
2192		  if (domain)
2193		    p = do_rfc1035_name(p, domain);
2194		  *p++ = 0;
2195		}
2196	      else
2197		{
2198		  memcpy(p, hostname, strlen(hostname));
2199		  p += strlen(hostname);
2200		  if (domain)
2201		    {
2202		      *(p++) = '.';
2203		      memcpy(p, domain, strlen(domain));
2204		      p += strlen(domain);
2205		    }
2206		  if (null_term)
2207		    *(p++) = 0;
2208		}
2209	    }
2210	}
2211    }
2212
2213  for (opt = config_opts; opt; opt = opt->next)
2214    {
2215      int optno = opt->opt;
2216
2217      /* was it asked for, or are we sending it anyway? */
2218      if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2219	continue;
2220
2221      /* prohibit some used-internally options */
2222      if (optno == OPTION_CLIENT_FQDN ||
2223	  optno == OPTION_MAXMESSAGE ||
2224	  optno == OPTION_OVERLOAD ||
2225	  optno == OPTION_PAD ||
2226	  optno == OPTION_END)
2227	continue;
2228
2229      if (optno == OPTION_SNAME && done_server)
2230	continue;
2231
2232      if (optno == OPTION_FILENAME && done_file)
2233	continue;
2234
2235      /* netids match and not encapsulated? */
2236      if (opt != option_find2(netid, config_opts, optno))
2237	continue;
2238
2239      /* For the options we have default values on
2240	 dhc-option=<optionno> means "don't include this option"
2241	 not "include a zero-length option" */
2242      if (opt->len == 0 &&
2243	  (optno == OPTION_NETMASK ||
2244	   optno == OPTION_BROADCAST ||
2245	   optno == OPTION_ROUTER ||
2246	   optno == OPTION_DNSSERVER ||
2247	   optno == OPTION_DOMAINNAME ||
2248	   optno == OPTION_HOSTNAME))
2249	continue;
2250
2251      /* vendor-class comes from elsewhere for PXE */
2252      if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2253	continue;
2254
2255      /* always force null-term for filename and servername - buggy PXE again. */
2256      len = do_opt(opt, NULL, context,
2257		   (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2258
2259      if ((p = free_space(mess, end, optno, len)))
2260	{
2261	  do_opt(opt, p, context,
2262		 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2263
2264	  /* If we send a vendor-id, revisit which vendor-ops we consider
2265	     it appropriate to send. */
2266	  if (optno == OPTION_VENDOR_ID)
2267	    match_vendor_opts(p - 2, config_opts);
2268	}
2269    }
2270
2271  /* Now send options to be encapsulated in arbitrary options,
2272     eg dhcp-option=encap:172,17,.......
2273     The may be more that one "outer" to do, so group
2274     all the options which match each outer in turn. */
2275  for (opt = config_opts; opt; opt = opt->next)
2276    opt->flags &= ~DHOPT_ENCAP_DONE;
2277
2278  for (opt = config_opts; opt; opt = opt->next)
2279    if ((opt->flags & (DHOPT_ENCAPSULATE | DHOPT_ENCAP_DONE)) ==  DHOPT_ENCAPSULATE)
2280      {
2281	struct dhcp_opt *o;
2282	int found = 0;
2283
2284	for (o = config_opts; o; o = o->next)
2285	  {
2286	    o->flags &= ~DHOPT_ENCAP_MATCH;
2287	    if ((o->flags & DHOPT_ENCAPSULATE) && opt->u.encap == o->u.encap)
2288	      {
2289		o->flags |= DHOPT_ENCAP_DONE;
2290		if (match_netid(o->netid, netid, 1) &&
2291		    (o->flags & DHOPT_FORCE || in_list(req_options, o->u.encap)))
2292		  {
2293		    o->flags |= DHOPT_ENCAP_MATCH;
2294		    found = 1;
2295		  }
2296	      }
2297	  }
2298
2299	if (found)
2300	  do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2301      }
2302
2303  /* Must precede pxe_opts, since it overwrites req_options */
2304  force_encap = prune_vendor_opts(netid);
2305  if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
2306    force_encap = 1;
2307
2308  if (pxe_arch != -1)
2309    {
2310      pxe_misc(mess, end, uuid);
2311      config_opts = pxe_opts(pxe_arch, netid);
2312    }
2313
2314  if (force_encap)
2315    do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term);
2316
2317   /* restore BOOTP anti-overload hack */
2318  if (!req_options || (daemon->options & OPT_NO_OVERRIDE))
2319    {
2320      mess->file[0] = f0;
2321      mess->sname[0] = s0;
2322    }
2323}
2324
2325#endif
2326