File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / rfc2131.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:02:07 2023 UTC (9 months, 2 weeks ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v8_2p1, HEAD
Version 8.2p1

    1: /* dnsmasq is Copyright (c) 2000-2022 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 option_len(opt) ((int)(((unsigned char *)(opt))[1]))
   22: #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
   23: 
   24: #ifdef HAVE_SCRIPT
   25: static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
   26: #endif
   27: 
   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, const 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 offset, 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 *end,
   46: 		       unsigned char *req_options,
   47: 		       char *hostname, 
   48: 		       char *domain,
   49: 		       struct dhcp_netid *netid,
   50: 		       struct in_addr subnet_addr, 
   51: 		       unsigned char fqdn_flags,
   52: 		       int null_term, int pxe_arch,
   53: 		       unsigned char *uuid,
   54: 		       int vendor_class_len,
   55: 		       time_t now,
   56: 		       unsigned int lease_time,
   57: 		       unsigned short fuzz,
   58: 		       const char *pxevendor);
   59: 
   60: 
   61: static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); 
   62: static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
   63: static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor);
   64: static int prune_vendor_opts(struct dhcp_netid *netid);
   65: static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
   66: struct dhcp_boot *find_boot(struct dhcp_netid *netid);
   67: static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
   68: static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
   69: static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor);
   70: 
   71: size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
   72: 		  size_t sz, time_t now, int unicast_dest, int loopback,
   73: 		  int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
   74: {
   75:   unsigned char *opt, *clid = NULL;
   76:   struct dhcp_lease *ltmp, *lease = NULL;
   77:   struct dhcp_vendor *vendor;
   78:   struct dhcp_mac *mac;
   79:   struct dhcp_netid_list *id_list;
   80:   int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
   81:   const char *pxevendor = NULL;
   82:   struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
   83:   unsigned char *end = (unsigned char *)(mess + 1); 
   84:   unsigned char *real_end = (unsigned char *)(mess + 1); 
   85:   char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
   86:   int hostname_auth = 0, borken_opt = 0;
   87:   unsigned char *req_options = NULL;
   88:   char *message = NULL;
   89:   unsigned int time;
   90:   struct dhcp_config *config;
   91:   struct dhcp_netid *netid, *tagif_netid;
   92:   struct in_addr subnet_addr, override;
   93:   unsigned short fuzz = 0;
   94:   unsigned int mess_type = 0;
   95:   unsigned char fqdn_flags = 0;
   96:   unsigned char *agent_id = NULL, *uuid = NULL;
   97:   unsigned char *emac = NULL;
   98:   int vendor_class_len = 0, emac_len = 0;
   99:   struct dhcp_netid known_id, iface_id, cpewan_id;
  100:   struct dhcp_opt *o;
  101:   unsigned char pxe_uuid[17];
  102:   unsigned char *oui = NULL, *serial = NULL;
  103: #ifdef HAVE_SCRIPT
  104:   unsigned char *class = NULL;
  105: #endif
  106: 
  107:   subnet_addr.s_addr = override.s_addr = 0;
  108: 
  109:   /* set tag with name == interface */
  110:   iface_id.net = iface_name;
  111:   iface_id.next = NULL;
  112:   netid = &iface_id; 
  113:   
  114:   if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
  115:     return 0;
  116:    
  117:   if (mess->htype == 0 && mess->hlen != 0)
  118:     return 0;
  119: 
  120:   /* check for DHCP rather than BOOTP */
  121:   if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
  122:     {
  123:       u32 cookie = htonl(DHCP_COOKIE);
  124:       
  125:       /* only insist on a cookie for DHCP. */
  126:       if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
  127: 	return 0;
  128:       
  129:       mess_type = option_uint(opt, 0, 1);
  130:       
  131:       /* two things to note here: expand_buf may move the packet,
  132: 	 so reassign mess from daemon->packet. Also, the size
  133: 	 sent includes the IP and UDP headers, hence the magic "-28" */
  134:       if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
  135: 	{
  136: 	  size_t size = (size_t)option_uint(opt, 0, 2) - 28;
  137: 	  
  138: 	  if (size > DHCP_PACKET_MAX)
  139: 	    size = DHCP_PACKET_MAX;
  140: 	  else if (size < sizeof(struct dhcp_packet))
  141: 	    size = sizeof(struct dhcp_packet);
  142: 	  
  143: 	  if (expand_buf(&daemon->dhcp_packet, size))
  144: 	    {
  145: 	      mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
  146: 	      real_end = end = ((unsigned char *)mess) + size;
  147: 	    }
  148: 	}
  149: 
  150:       /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
  151: 	 it can affect the context-determination code. */
  152:       if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
  153: 	mess->ciaddr.s_addr = 0;
  154: 
  155:       /* search for device identity from CPEWAN devices, we pass this through to the script */
  156:       if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
  157: 	{
  158: 	  unsigned  int elen, offset, len = option_len(opt);
  159: 	  
  160: 	  for (offset = 0; offset < (len - 5); offset += elen + 5)
  161: 	    {
  162: 	      elen = option_uint(opt, offset + 4 , 1);
  163: 	      if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
  164: 		{
  165: 		  unsigned char *x = option_ptr(opt, offset + 5);
  166: 		  unsigned char *y = option_ptr(opt, offset + elen + 5);
  167: 		  oui = option_find1(x, y, 1, 1);
  168: 		  serial = option_find1(x, y, 2, 1);
  169: #ifdef HAVE_SCRIPT
  170: 		  class = option_find1(x, y, 3, 1);		  
  171: #endif
  172: 		  /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing 
  173: 		     the gateway id back. Note that the device class is optional */
  174: 		  if (oui && serial)
  175: 		    {
  176: 		      cpewan_id.net = "cpewan-id";
  177: 		      cpewan_id.next = netid;
  178: 		      netid = &cpewan_id;
  179: 		    }
  180: 		  break;
  181: 		}
  182: 	    }
  183: 	}
  184:       
  185:       if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
  186: 	{
  187: 	  /* Any agent-id needs to be copied back out, verbatim, as the last option
  188: 	     in the packet. Here, we shift it to the very end of the buffer, if it doesn't
  189: 	     get overwritten, then it will be shuffled back at the end of processing.
  190: 	     Note that the incoming options must not be overwritten here, so there has to 
  191: 	     be enough free space at the end of the packet to copy the option. */
  192: 	  unsigned char *sopt;
  193: 	  unsigned int total = option_len(opt) + 2;
  194: 	  unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
  195: 						 OPTION_END, 0);
  196: 	  if (last_opt && last_opt < end - total)
  197: 	    {
  198: 	      end -= total;
  199: 	      agent_id = end;
  200: 	      memcpy(agent_id, opt, total);
  201: 	    }
  202: 
  203: 	  /* look for RFC3527 Link selection sub-option */
  204: 	  if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
  205: 	    subnet_addr = option_addr(sopt);
  206: 
  207: 	  /* look for RFC5107 server-identifier-override */
  208: 	  if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
  209: 	    override = option_addr(sopt);
  210: 	  
  211: 	  /* if a circuit-id or remote-is option is provided, exact-match to options. */ 
  212: 	  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
  213: 	    {
  214: 	      int search;
  215: 	      
  216: 	      if (vendor->match_type == MATCH_CIRCUIT)
  217: 		search = SUBOPT_CIRCUIT_ID;
  218: 	      else if (vendor->match_type == MATCH_REMOTE)
  219: 		search = SUBOPT_REMOTE_ID;
  220: 	      else if (vendor->match_type == MATCH_SUBSCRIBER)
  221: 		search = SUBOPT_SUBSCR_ID;
  222: 	      else 
  223: 		continue;
  224: 
  225: 	      if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
  226: 		  vendor->len == option_len(sopt) &&
  227: 		  memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
  228: 		{
  229: 		  vendor->netid.next = netid;
  230: 		  netid = &vendor->netid;
  231: 		} 
  232: 	    }
  233: 	}
  234: 
  235:       /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
  236:       if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
  237: 	subnet_addr = option_addr(opt);
  238:       
  239:       /* If there is no client identifier option, use the hardware address */
  240:       if (!option_bool(OPT_IGNORE_CLID) && (opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
  241: 	{
  242: 	  clid_len = option_len(opt);
  243: 	  clid = option_ptr(opt, 0);
  244: 	}
  245: 
  246:       /* do we have a lease in store? */
  247:       lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
  248: 
  249:       /* If this request is missing a clid, but we've seen one before, 
  250: 	 use it again for option matching etc. */
  251:       if (lease && !clid && lease->clid)
  252: 	{
  253: 	  clid_len = lease->clid_len;
  254: 	  clid = lease->clid;
  255: 	}
  256: 
  257:       /* find mac to use for logging and hashing */
  258:       emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
  259:     }
  260:   
  261:   for (mac = daemon->dhcp_macs; mac; mac = mac->next)
  262:     if (mac->hwaddr_len == mess->hlen &&
  263: 	(mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
  264: 	memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
  265:       {
  266: 	mac->netid.next = netid;
  267: 	netid = &mac->netid;
  268:       }
  269:   
  270:   /* Determine network for this packet. Our caller will have already linked all the 
  271:      contexts which match the addresses of the receiving interface but if the 
  272:      machine has an address already, or came via a relay, or we have a subnet selector, 
  273:      we search again. If we don't have have a giaddr or explicit subnet selector, 
  274:      use the ciaddr. This is necessary because a  machine which got a lease via a 
  275:      relay won't use the relay to renew. If matching a ciaddr fails but we have a context 
  276:      from the physical network, continue using that to allow correct DHCPNAK generation later. */
  277:   if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
  278:     {
  279:       struct dhcp_context *context_tmp, *context_new = NULL;
  280:       struct shared_network *share = NULL;
  281:       struct in_addr addr;
  282:       int force = 0, via_relay = 0;
  283:       
  284:       if (subnet_addr.s_addr)
  285: 	{
  286: 	  addr = subnet_addr;
  287: 	  force = 1;
  288: 	}
  289:       else if (mess->giaddr.s_addr)
  290: 	{
  291: 	  addr = mess->giaddr;
  292: 	  force = 1;
  293: 	  via_relay = 1;
  294: 	}
  295:       else
  296: 	{
  297: 	  /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
  298: 	  addr = mess->ciaddr;
  299: 	  for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
  300: 	    if (context_tmp->netmask.s_addr && 
  301: 		is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
  302: 		is_same_net(addr, context_tmp->end, context_tmp->netmask))
  303: 	      {
  304: 		context_new = context;
  305: 		break;
  306: 	      }
  307: 	} 
  308: 		
  309:       if (!context_new)
  310: 	{
  311: 	  for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
  312: 	    {
  313: 	      struct in_addr netmask = context_tmp->netmask;
  314: 	      
  315: 	      /* guess the netmask for relayed networks */
  316: 	      if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
  317: 		{
  318: 		  if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
  319: 		    netmask.s_addr = htonl(0xff000000);
  320: 		  else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
  321: 		    netmask.s_addr = htonl(0xffff0000);
  322: 		  else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
  323: 		    netmask.s_addr = htonl(0xffffff00); 
  324: 		}
  325: 
  326: 	      /* check to see is a context is OK because of a shared address on
  327: 		 the relayed subnet. */
  328: 	      if (via_relay)
  329: 		for (share = daemon->shared_networks; share; share = share->next)
  330: 		  {
  331: #ifdef HAVE_DHCP6
  332: 		    if (share->shared_addr.s_addr == 0)
  333: 		      continue;
  334: #endif
  335: 		    if (share->if_index != 0 ||
  336: 			share->match_addr.s_addr != mess->giaddr.s_addr)
  337: 		      continue;
  338: 		    
  339: 		    if (netmask.s_addr != 0  && 
  340: 			is_same_net(share->shared_addr, context_tmp->start, netmask) &&
  341: 			is_same_net(share->shared_addr, context_tmp->end, netmask))
  342: 		      break;
  343: 		  }
  344: 	      
  345: 	      /* This section fills in context mainly when a client which is on a remote (relayed)
  346: 		 network renews a lease without using the relay, after dnsmasq has restarted. */
  347: 	      if (share ||
  348: 		  (netmask.s_addr != 0  && 
  349: 		   is_same_net(addr, context_tmp->start, netmask) &&
  350: 		   is_same_net(addr, context_tmp->end, netmask)))
  351: 		{
  352: 		  context_tmp->netmask = netmask;
  353: 		  if (context_tmp->local.s_addr == 0)
  354: 		    context_tmp->local = fallback;
  355: 		  if (context_tmp->router.s_addr == 0 && !share)
  356: 		    context_tmp->router = mess->giaddr;
  357: 		  
  358: 		  /* fill in missing broadcast addresses for relayed ranges */
  359: 		  if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
  360: 		    context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
  361: 		  
  362: 		  context_tmp->current = context_new;
  363: 		  context_new = context_tmp;
  364: 		}
  365: 	      
  366: 	    }
  367: 	}
  368: 	  
  369:       if (context_new || force)
  370: 	context = context_new; 
  371:     }
  372:   
  373:   if (!context)
  374:     {
  375:       const char *via;
  376:       if (subnet_addr.s_addr)
  377: 	{
  378: 	  via = _("with subnet selector");
  379: 	  inet_ntop(AF_INET, &subnet_addr, daemon->addrbuff, ADDRSTRLEN);
  380: 	}
  381:       else
  382: 	{
  383: 	  via = _("via");
  384: 	  if (mess->giaddr.s_addr)
  385: 	    inet_ntop(AF_INET, &mess->giaddr, daemon->addrbuff, ADDRSTRLEN);
  386: 	  else
  387: 	    safe_strncpy(daemon->addrbuff, iface_name, ADDRSTRLEN);
  388: 	}
  389:       my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
  390: 		via, daemon->addrbuff);
  391:       return 0;
  392:     }
  393: 
  394:   if (option_bool(OPT_LOG_OPTS))
  395:     {
  396:       struct dhcp_context *context_tmp;
  397:       for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
  398: 	{
  399: 	  inet_ntop(AF_INET, &context_tmp->start, daemon->namebuff, MAXDNAME);
  400: 	  if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
  401: 	    {
  402: 	      inet_ntop(AF_INET, &context_tmp->netmask, daemon->addrbuff, ADDRSTRLEN);
  403: 	      my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
  404: 			ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
  405: 	    }
  406: 	  else
  407: 	    {
  408: 	      inet_ntop(AF_INET, &context_tmp->end, daemon->addrbuff, ADDRSTRLEN);
  409: 	      my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
  410: 			ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
  411: 	    }
  412: 	}
  413:     }
  414:   
  415:   /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
  416:      Otherwise assume the option is an array, and look for a matching element. 
  417:      If no data given, existence of the option is enough. This code handles 
  418:      rfc3925 V-I classes too. */
  419:   for (o = daemon->dhcp_match; o; o = o->next)
  420:     {
  421:       unsigned int len, elen, match = 0;
  422:       size_t offset, o2;
  423: 
  424:       if (o->flags & DHOPT_RFC3925)
  425: 	{
  426: 	  if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
  427: 	    continue;
  428: 	  
  429: 	  for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
  430: 	    {
  431: 	      len = option_uint(opt, offset + 4 , 1);
  432: 	      /* Need to take care that bad data can't run us off the end of the packet */
  433: 	      if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
  434: 		  (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
  435: 		for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
  436: 		  { 
  437: 		    elen = option_uint(opt, o2, 1);
  438: 		    if ((o2 + elen + 1 <= (unsigned)option_len(opt)) &&
  439: 			(match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
  440: 		      break;
  441: 		  }
  442: 	      if (match) 
  443: 		break;
  444: 	    }	  
  445: 	}
  446:       else
  447: 	{
  448: 	  if (!(opt = option_find(mess, sz, o->opt, 1)))
  449: 	    continue;
  450: 	  
  451: 	  match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
  452: 	} 
  453: 
  454:       if (match)
  455: 	{
  456: 	  o->netid->next = netid;
  457: 	  netid = o->netid;
  458: 	}
  459:     }
  460: 	
  461:   /* user-class options are, according to RFC3004, supposed to contain
  462:      a set of counted strings. Here we check that this is so (by seeing
  463:      if the counts are consistent with the overall option length) and if
  464:      so zero the counts so that we don't get spurious matches between 
  465:      the vendor string and the counts. If the lengths don't add up, we
  466:      assume that the option is a single string and non RFC3004 compliant 
  467:      and just do the substring match. dhclient provides these broken options.
  468:      The code, later, which sends user-class data to the lease-change script
  469:      relies on the transformation done here.
  470:   */
  471: 
  472:   if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
  473:     {
  474:       unsigned char *ucp = option_ptr(opt, 0);
  475:       int tmp, j;
  476:       for (j = 0; j < option_len(opt); j += ucp[j] + 1);
  477:       if (j == option_len(opt))
  478: 	for (j = 0; j < option_len(opt); j = tmp)
  479: 	  {
  480: 	    tmp = j + ucp[j] + 1;
  481: 	    ucp[j] = 0;
  482: 	  }
  483:     }
  484:     
  485:   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
  486:     {
  487:       int mopt;
  488:       
  489:       if (vendor->match_type == MATCH_VENDOR)
  490: 	mopt = OPTION_VENDOR_ID;
  491:       else if (vendor->match_type == MATCH_USER)
  492: 	mopt = OPTION_USER_CLASS; 
  493:       else
  494: 	continue;
  495: 
  496:       if ((opt = option_find(mess, sz, mopt, 1)))
  497: 	{
  498: 	  int i;
  499: 	  for (i = 0; i <= (option_len(opt) - vendor->len); i++)
  500: 	    if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
  501: 	      {
  502: 		vendor->netid.next = netid;
  503: 		netid = &vendor->netid;
  504: 		break;
  505: 	      }
  506: 	}
  507:     }
  508: 
  509:   /* mark vendor-encapsulated options which match the client-supplied vendor class,
  510:      save client-supplied vendor class */
  511:   if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
  512:     {
  513:       memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
  514:       vendor_class_len = option_len(opt);
  515:     }
  516:   match_vendor_opts(opt, daemon->dhcp_opts);
  517:   
  518:   if (option_bool(OPT_LOG_OPTS))
  519:     {
  520:       if (sanitise(opt, daemon->namebuff))
  521: 	my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
  522:       if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
  523: 	my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
  524:     }
  525: 
  526:   mess->op = BOOTREPLY;
  527:   
  528:   config = find_config(daemon->dhcp_conf, context, clid, clid_len, 
  529: 		       mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid));
  530: 
  531:   /* set "known" tag for known hosts */
  532:   if (config)
  533:     {
  534:       known_id.net = "known";
  535:       known_id.next = netid;
  536:       netid = &known_id;
  537:     }
  538:   else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len, 
  539: 		       mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid)))
  540:     {
  541:       known_id.net = "known-othernet";
  542:       known_id.next = netid;
  543:       netid = &known_id;
  544:     }
  545:   
  546:   if (mess_type == 0 && !pxe)
  547:     {
  548:       /* BOOTP request */
  549:       struct dhcp_netid id, bootp_id;
  550:       struct in_addr *logaddr = NULL;
  551: 
  552:       /* must have a MAC addr for bootp */
  553:       if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
  554: 	return 0;
  555:       
  556:       if (have_config(config, CONFIG_DISABLE))
  557: 	message = _("disabled");
  558: 
  559:       end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
  560:             
  561:       if (have_config(config, CONFIG_NAME))
  562: 	{
  563: 	  hostname = config->hostname;
  564: 	  domain = config->domain;
  565: 	}
  566: 
  567:       if (config)
  568: 	{
  569: 	  struct dhcp_netid_list *list;
  570: 
  571: 	  for (list = config->netid; list; list = list->next)
  572: 	    {
  573: 	      list->list->next = netid;
  574: 	      netid = list->list;
  575: 	    }
  576: 	}
  577: 
  578:       /* Match incoming filename field as a netid. */
  579:       if (mess->file[0])
  580: 	{
  581: 	  memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
  582: 	  daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
  583: 	  id.net = (char *)daemon->dhcp_buff2;
  584: 	  id.next = netid;
  585: 	  netid = &id;
  586: 	}
  587: 
  588:       /* Add "bootp" as a tag to allow different options, address ranges etc
  589: 	 for BOOTP clients */
  590:       bootp_id.net = "bootp";
  591:       bootp_id.next = netid;
  592:       netid = &bootp_id;
  593:       
  594:       tagif_netid = run_tag_if(netid);
  595: 
  596:       for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
  597: 	if (match_netid(id_list->list, tagif_netid, 0))
  598: 	  message = _("ignored");
  599:       
  600:       if (!message)
  601: 	{
  602: 	  int nailed = 0;
  603: 
  604: 	  if (have_config(config, CONFIG_ADDR))
  605: 	    {
  606: 	      nailed = 1;
  607: 	      logaddr = &config->addr;
  608: 	      mess->yiaddr = config->addr;
  609: 	      if ((lease = lease_find_by_addr(config->addr)) &&
  610: 		  (lease->hwaddr_len != mess->hlen ||
  611: 		   lease->hwaddr_type != mess->htype ||
  612: 		   memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
  613: 		message = _("address in use");
  614: 	    }
  615: 	  else
  616: 	    {
  617: 	      if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
  618: 		  !address_available(context, lease->addr, tagif_netid))
  619: 		{
  620: 		   if (lease)
  621: 		     {
  622: 		       /* lease exists, wrong network. */
  623: 		       lease_prune(lease, now);
  624: 		       lease = NULL;
  625: 		     }
  626: 		   if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
  627: 		     message = _("no address available");
  628: 		}
  629: 	      else
  630: 		mess->yiaddr = lease->addr;
  631: 	    }
  632: 	  
  633: 	  if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
  634: 	    message = _("wrong network");
  635: 	  else if (context->netid.net)
  636: 	    {
  637: 	      context->netid.next = netid;
  638: 	      tagif_netid = run_tag_if(&context->netid);
  639: 	    }
  640: 
  641: 	  log_tags(tagif_netid, ntohl(mess->xid));
  642: 	    
  643: 	  if (!message && !nailed)
  644: 	    {
  645: 	      for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
  646: 		if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
  647: 		  break;
  648: 	      if (!id_list)
  649: 		message = _("no address configured");
  650: 	    }
  651: 
  652: 	  if (!message && 
  653: 	      !lease && 
  654: 	      (!(lease = lease4_allocate(mess->yiaddr))))
  655: 	    message = _("no leases left");
  656: 	  
  657: 	  if (!message)
  658: 	    {
  659: 	      logaddr = &mess->yiaddr;
  660: 		
  661: 	      lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
  662: 	      if (hostname)
  663: 		lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain); 
  664: 	      /* infinite lease unless nailed in dhcp-host line. */
  665: 	      lease_set_expires(lease,  
  666: 				have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff, 
  667: 				now); 
  668: 	      lease_set_interface(lease, int_index, now);
  669: 	      
  670: 	      clear_packet(mess, end);
  671: 	      do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), 
  672: 			 netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0, NULL);
  673: 	    }
  674: 	}
  675:       
  676:       daemon->metrics[METRIC_BOOTP]++;
  677:       log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
  678:       
  679:       return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
  680:     }
  681:       
  682:   if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 3)))
  683:     {
  684:       /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
  685:       int len = option_len(opt);
  686:       char *pq = daemon->dhcp_buff;
  687:       unsigned char *pp, *op = option_ptr(opt, 0);
  688:       
  689:       fqdn_flags = *op;
  690:       len -= 3;
  691:       op += 3;
  692:       pp = op;
  693:       
  694:       /* NB, the following always sets at least one bit */
  695:       if (option_bool(OPT_FQDN_UPDATE))
  696: 	{
  697: 	  if (fqdn_flags & 0x01)
  698: 	    {
  699: 	      fqdn_flags |= 0x02; /* set O */
  700: 	      fqdn_flags &= ~0x01; /* clear S */
  701: 	    }
  702: 	  fqdn_flags |= 0x08; /* set N */
  703: 	}
  704:       else 
  705: 	{
  706: 	  if (!(fqdn_flags & 0x01))
  707: 	    fqdn_flags |= 0x03; /* set S and O */
  708: 	  fqdn_flags &= ~0x08; /* clear N */
  709: 	}
  710:       
  711:       if (fqdn_flags & 0x04)
  712: 	while (*op != 0 && ((op + (*op)) - pp) < len)
  713: 	  {
  714: 	    memcpy(pq, op+1, *op);
  715: 	    pq += *op;
  716: 	    op += (*op)+1;
  717: 	    *(pq++) = '.';
  718: 	  }
  719:       else
  720: 	{
  721: 	  memcpy(pq, op, len);
  722: 	  if (len > 0 && op[len-1] == 0)
  723: 	    borken_opt = 1;
  724: 	  pq += len + 1;
  725: 	}
  726:       
  727:       if (pq != daemon->dhcp_buff)
  728: 	pq--;
  729:       
  730:       *pq = 0;
  731:       
  732:       if (legal_hostname(daemon->dhcp_buff))
  733: 	offer_hostname = client_hostname = daemon->dhcp_buff;
  734:     }
  735:   else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
  736:     {
  737:       int len = option_len(opt);
  738:       memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
  739:       /* Microsoft clients are broken, and need zero-terminated strings
  740: 	 in options. We detect this state here, and do the same in
  741: 	 any options we send */
  742:       if (len > 0 && daemon->dhcp_buff[len-1] == 0)
  743: 	borken_opt = 1;
  744:       else
  745: 	daemon->dhcp_buff[len] = 0;
  746:       if (legal_hostname(daemon->dhcp_buff))
  747: 	client_hostname = daemon->dhcp_buff;
  748:     }
  749: 
  750:   if (client_hostname)
  751:     {
  752:       struct dhcp_match_name *m;
  753:       size_t nl = strlen(client_hostname);
  754:       
  755:       if (option_bool(OPT_LOG_OPTS))
  756: 	my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
  757:       for (m = daemon->dhcp_name_match; m; m = m->next)
  758: 	{
  759: 	  size_t ml = strlen(m->name);
  760: 	  char save = 0;
  761: 	  
  762: 	  if (nl < ml)
  763: 	    continue;
  764: 	  if (nl > ml)
  765: 	    {
  766: 	      save = client_hostname[ml];
  767: 	      client_hostname[ml] = 0;
  768: 	    }
  769: 	  
  770: 	  if (hostname_isequal(client_hostname, m->name) &&
  771: 	      (save == 0 || m->wildcard))
  772: 	    {
  773: 	      m->netid->next = netid;
  774: 	      netid = m->netid;
  775: 	    }
  776: 	  
  777: 	  if (save != 0)
  778: 	    client_hostname[ml] = save;
  779: 	}
  780:     }
  781:   
  782:   if (have_config(config, CONFIG_NAME))
  783:     {
  784:       hostname = config->hostname;
  785:       domain = config->domain;
  786:       hostname_auth = 1;
  787:       /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
  788:       if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
  789:         offer_hostname = hostname;
  790:     }
  791:   else if (client_hostname)
  792:     {
  793:       domain = strip_hostname(client_hostname);
  794:       
  795:       if (strlen(client_hostname) != 0)
  796: 	{
  797: 	  hostname = client_hostname;
  798: 	  
  799: 	  if (!config)
  800: 	    {
  801: 	      /* Search again now we have a hostname. 
  802: 		 Only accept configs without CLID and HWADDR here, (they won't match)
  803: 		 to avoid impersonation by name. */
  804: 	      struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
  805: 						    mess->chaddr, mess->hlen, 
  806: 						    mess->htype, hostname, run_tag_if(netid));
  807: 	      if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
  808: 		{
  809: 		  config = new;
  810: 		  /* set "known" tag for known hosts */
  811: 		  known_id.net = "known";
  812: 		  known_id.next = netid;
  813: 		  netid = &known_id;
  814: 		}
  815: 	    }
  816: 	}
  817:     }
  818:   
  819:   if (config)
  820:     {
  821:       struct dhcp_netid_list *list;
  822:       
  823:       for (list = config->netid; list; list = list->next)
  824: 	{
  825: 	  list->list->next = netid;
  826: 	  netid = list->list;
  827: 	}
  828:     }
  829:   
  830:   tagif_netid = run_tag_if(netid);
  831:   
  832:   /* if all the netids in the ignore list are present, ignore this client */
  833:   for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
  834:     if (match_netid(id_list->list, tagif_netid, 0))
  835:       ignore = 1;
  836: 
  837:   /* If configured, we can override the server-id to be the address of the relay, 
  838:      so that all traffic goes via the relay and can pick up agent-id info. This can be
  839:      configured for all relays, or by address. */
  840:   if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
  841:     {
  842:       if (!daemon->override_relays)
  843: 	override = mess->giaddr;
  844:       else
  845: 	{
  846: 	  struct addr_list *l;
  847: 	  for (l = daemon->override_relays; l; l = l->next)
  848: 	    if (l->addr.s_addr == mess->giaddr.s_addr)
  849: 	      break;
  850: 	  if (l)
  851: 	    override = mess->giaddr;
  852: 	}
  853:     }
  854: 
  855:   /* Can have setting to ignore the client ID for a particular MAC address or hostname */
  856:   if (have_config(config, CONFIG_NOCLID))
  857:     clid = NULL;
  858:           
  859:   /* Check if client is PXE client. */
  860:   if (daemon->enable_pxe &&
  861:       is_pxe_client(mess, sz, &pxevendor))
  862:     {
  863:       if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
  864: 	{
  865: 	  memcpy(pxe_uuid, option_ptr(opt, 0), 17);
  866: 	  uuid = pxe_uuid;
  867: 	}
  868: 
  869:       /* Check if this is really a PXE bootserver request, and handle specially if so. */
  870:       if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
  871: 	  (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
  872: 	  (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
  873: 	{
  874: 	  struct pxe_service *service;
  875: 	  int type = option_uint(opt, 0, 2);
  876: 	  int layer = option_uint(opt, 2, 2);
  877: 	  unsigned char save71[4];
  878: 	  struct dhcp_opt opt71;
  879: 
  880: 	  if (ignore)
  881: 	    return 0;
  882: 
  883: 	  if (layer & 0x8000)
  884: 	    {
  885: 	      my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
  886: 	      return 0;
  887: 	    }
  888: 
  889: 	  memcpy(save71, option_ptr(opt, 0), 4);
  890: 	  
  891: 	  for (service = daemon->pxe_services; service; service = service->next)
  892: 	    if (service->type == type)
  893: 	      break;
  894: 	  
  895: 	  for (; context; context = context->current)
  896: 	    if (match_netid(context->filter, tagif_netid, 1) &&
  897: 		is_same_net(mess->ciaddr, context->start, context->netmask))
  898: 	      break;
  899: 	  
  900: 	  if (!service || !service->basename || !context)
  901: 	    return 0;
  902: 	  	  
  903: 	  clear_packet(mess, end);
  904: 	  
  905: 	  mess->yiaddr = mess->ciaddr;
  906: 	  mess->ciaddr.s_addr = 0;
  907: 	  if (service->sname)
  908: 	    mess->siaddr = a_record_from_hosts(service->sname, now);
  909: 	  else if (service->server.s_addr != 0)
  910: 	    mess->siaddr = service->server; 
  911: 	  else
  912: 	    mess->siaddr = context->local; 
  913: 	  
  914: 	  if (strchr(service->basename, '.'))
  915: 	    snprintf((char *)mess->file, sizeof(mess->file),
  916: 		"%s", service->basename);
  917: 	  else
  918: 	    snprintf((char *)mess->file, sizeof(mess->file),
  919: 		"%s.%d", service->basename, layer);
  920: 	  
  921: 	  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
  922: 	  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
  923: 	  pxe_misc(mess, end, uuid, pxevendor);
  924: 	  
  925: 	  prune_vendor_opts(tagif_netid);
  926: 	  opt71.val = save71;
  927: 	  opt71.opt = SUBOPT_PXE_BOOT_ITEM;
  928: 	  opt71.len = 4;
  929: 	  opt71.flags = DHOPT_VENDOR_MATCH;
  930: 	  opt71.netid = NULL;
  931: 	  opt71.next = daemon->dhcp_opts;
  932: 	  do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
  933: 	  
  934: 	  log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
  935: 	  log_tags(tagif_netid, ntohl(mess->xid));
  936: 	  return dhcp_packet_size(mess, agent_id, real_end);	  
  937: 	}
  938:       
  939:       if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
  940: 	{
  941: 	  pxearch = option_uint(opt, 0, 2);
  942: 
  943: 	  /* proxy DHCP here. */
  944: 	  if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
  945: 	    {
  946: 	      struct dhcp_context *tmp;
  947: 	      int workaround = 0;
  948: 	      
  949: 	      for (tmp = context; tmp; tmp = tmp->current)
  950: 		if ((tmp->flags & CONTEXT_PROXY) &&
  951: 		    match_netid(tmp->filter, tagif_netid, 1))
  952: 		  break;
  953: 	      
  954: 	      if (tmp)
  955: 		{
  956: 		  struct dhcp_boot *boot;
  957: 		  int redirect4011 = 0;
  958: 
  959: 		  if (tmp->netid.net)
  960: 		    {
  961: 		      tmp->netid.next = netid;
  962: 		      tagif_netid = run_tag_if(&tmp->netid);
  963: 		    }
  964: 		  
  965: 		  boot = find_boot(tagif_netid);
  966: 		  
  967: 		  mess->yiaddr.s_addr = 0;
  968: 		  if  (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
  969: 		    {
  970: 		      mess->ciaddr.s_addr = 0;
  971: 		      mess->flags |= htons(0x8000); /* broadcast */
  972: 		    }
  973: 		  
  974: 		  clear_packet(mess, end);
  975: 		  
  976: 		  /* Redirect EFI clients to port 4011 */
  977: 		  if (pxearch >= 6)
  978: 		    {
  979: 		      redirect4011 = 1;
  980: 		      mess->siaddr = tmp->local;
  981: 		    }
  982: 		  
  983: 		  /* Returns true if only one matching service is available. On port 4011, 
  984: 		     it also inserts the boot file and server name. */
  985: 		  workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, tmp->local, now, pxe);
  986: 		  
  987: 		  if (!workaround && boot)
  988: 		    {
  989: 		      /* Provide the bootfile here, for iPXE, and in case we have no menu items
  990: 			 and set discovery_control = 8 */
  991: 		      if (boot->next_server.s_addr) 
  992: 			mess->siaddr = boot->next_server;
  993: 		      else if (boot->tftp_sname) 
  994: 			mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
  995: 		      
  996: 		      if (boot->file)
  997: 			safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
  998: 		    }
  999: 		  
 1000: 		  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, 
 1001: 			     mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
 1002: 		  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
 1003: 		  pxe_misc(mess, end, uuid, pxevendor);
 1004: 		  prune_vendor_opts(tagif_netid);
 1005: 		  if ((pxe && !workaround) || !redirect4011)
 1006: 		    do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
 1007: 	    
 1008: 		  daemon->metrics[METRIC_PXE]++;
 1009: 		  log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
 1010: 		  log_tags(tagif_netid, ntohl(mess->xid));
 1011: 		  if (!ignore)
 1012: 		    apply_delay(mess->xid, recvtime, tagif_netid);
 1013: 		  return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);	  
 1014: 		}
 1015: 	    }
 1016: 	}
 1017:     }
 1018: 
 1019:   /* if we're just a proxy server, go no further */
 1020:   if ((context->flags & CONTEXT_PROXY) || pxe)
 1021:     return 0;
 1022:   
 1023:   if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
 1024:     {
 1025:       req_options = (unsigned char *)daemon->dhcp_buff2;
 1026:       memcpy(req_options, option_ptr(opt, 0), option_len(opt));
 1027:       req_options[option_len(opt)] = OPTION_END;
 1028:     }
 1029:   
 1030:   switch (mess_type)
 1031:     {
 1032:     case DHCPDECLINE:
 1033:       if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
 1034: 	  option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
 1035: 	return 0;
 1036:       
 1037:       /* sanitise any message. Paranoid? Moi? */
 1038:       sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
 1039:       
 1040:       if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
 1041: 	return 0;
 1042:       
 1043:       daemon->metrics[METRIC_DHCPDECLINE]++;
 1044:       log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
 1045:       
 1046:       if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
 1047: 	lease_prune(lease, now);
 1048:       
 1049:       if (have_config(config, CONFIG_ADDR) && 
 1050: 	  config->addr.s_addr == option_addr(opt).s_addr)
 1051: 	{
 1052: 	  prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
 1053: 	  inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
 1054: 	  my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), 
 1055: 		    daemon->addrbuff, daemon->dhcp_buff);
 1056: 	  config->flags |= CONFIG_DECLINED;
 1057: 	  config->decline_time = now;
 1058: 	}
 1059:       else
 1060: 	/* make sure this host gets a different address next time. */
 1061: 	for (; context; context = context->current)
 1062: 	  context->addr_epoch++;
 1063:       
 1064:       return 0;
 1065: 
 1066:     case DHCPRELEASE:
 1067:       if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
 1068: 	  !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
 1069: 	  option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
 1070: 	return 0;
 1071:       
 1072:       if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
 1073: 	lease_prune(lease, now);
 1074:       else
 1075: 	message = _("unknown lease");
 1076: 
 1077:       daemon->metrics[METRIC_DHCPRELEASE]++;
 1078:       log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
 1079: 	
 1080:       return 0;
 1081:       
 1082:     case DHCPDISCOVER:
 1083:       if (ignore || have_config(config, CONFIG_DISABLE))
 1084: 	{
 1085: 	  if (option_bool(OPT_QUIET_DHCP))
 1086: 	    return 0;
 1087: 	  message = _("ignored");
 1088: 	  opt = NULL;
 1089: 	}
 1090:       else 
 1091: 	{
 1092: 	  struct in_addr addr, conf;
 1093: 	  
 1094: 	  addr.s_addr = conf.s_addr = 0;
 1095: 
 1096: 	  if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))	 
 1097: 	    addr = option_addr(opt);
 1098: 	  
 1099: 	  if (have_config(config, CONFIG_ADDR))
 1100: 	    {
 1101: 	      inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
 1102: 	      
 1103: 	      if ((ltmp = lease_find_by_addr(config->addr)) && 
 1104: 		  ltmp != lease &&
 1105: 		  !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
 1106: 		{
 1107: 		  int len;
 1108: 		  unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
 1109: 						       ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
 1110: 		  my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
 1111: 			    daemon->addrbuff, print_mac(daemon->namebuff, mac, len));
 1112: 		}
 1113: 	      else
 1114: 		{
 1115: 		  struct dhcp_context *tmp;
 1116: 		  for (tmp = context; tmp; tmp = tmp->current)
 1117: 		    if (context->router.s_addr == config->addr.s_addr)
 1118: 		      break;
 1119: 		  if (tmp)
 1120: 		    my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), daemon->addrbuff);
 1121: 		  else if (have_config(config, CONFIG_DECLINED) &&
 1122: 			   difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
 1123: 		    my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), daemon->addrbuff);
 1124: 		  else
 1125: 		    conf = config->addr;
 1126: 		}
 1127: 	    }
 1128: 	  
 1129: 	  if (conf.s_addr)
 1130: 	    mess->yiaddr = conf;
 1131: 	  else if (lease && 
 1132: 		   address_available(context, lease->addr, tagif_netid) && 
 1133: 		   !config_find_by_address(daemon->dhcp_conf, lease->addr))
 1134: 	    mess->yiaddr = lease->addr;
 1135: 	  else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) && 
 1136: 		   !config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
 1137: 	    mess->yiaddr = addr;
 1138: 	  else if (emac_len == 0)
 1139: 	    message = _("no unique-id");
 1140: 	  else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
 1141: 	    message = _("no address available");      
 1142: 	}
 1143:       
 1144:       daemon->metrics[METRIC_DHCPDISCOVER]++;
 1145:       log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid); 
 1146: 
 1147:       if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
 1148: 	return 0;
 1149: 
 1150:       if (context->netid.net)
 1151: 	{
 1152: 	  context->netid.next = netid;
 1153: 	  tagif_netid = run_tag_if(&context->netid);
 1154: 	}
 1155: 
 1156:       apply_delay(mess->xid, recvtime, tagif_netid);
 1157: 
 1158:       if (option_bool(OPT_RAPID_COMMIT) && option_find(mess, sz, OPTION_RAPID_COMMIT, 0))
 1159: 	{
 1160: 	  rapid_commit = 1;
 1161: 	  /* If a lease exists for this host and another address, squash it. */
 1162: 	  if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
 1163: 	    {
 1164: 	      lease_prune(lease, now);
 1165: 	      lease = NULL;
 1166: 	    }
 1167: 	  goto rapid_commit;
 1168: 	}
 1169:       
 1170:       log_tags(tagif_netid, ntohl(mess->xid));
 1171: 
 1172:       daemon->metrics[METRIC_DHCPOFFER]++;
 1173:       log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
 1174:       
 1175:       time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
 1176:       clear_packet(mess, end);
 1177:       option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
 1178:       option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
 1179:       option_put(mess, end, OPTION_LEASE_TIME, 4, time);
 1180:       /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
 1181:       do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr), 
 1182: 		 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
 1183:       
 1184:       return dhcp_packet_size(mess, agent_id, real_end);
 1185: 	
 1186: 
 1187:     case DHCPREQUEST:
 1188:       if (ignore || have_config(config, CONFIG_DISABLE))
 1189: 	return 0;
 1190:       if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
 1191: 	{
 1192: 	  /* SELECTING  or INIT_REBOOT */
 1193: 	  mess->yiaddr = option_addr(opt);
 1194: 	  
 1195: 	  /* send vendor and user class info for new or recreated lease */
 1196: 	  do_classes = 1;
 1197: 	  
 1198: 	  if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
 1199: 	    {
 1200: 	      /* SELECTING */
 1201: 	      selecting = 1;
 1202: 	      
 1203: 	      if (override.s_addr != 0)
 1204: 		{
 1205: 		  if (option_addr(opt).s_addr != override.s_addr)
 1206: 		    return 0;
 1207: 		}
 1208: 	      else 
 1209: 		{
 1210: 		  for (; context; context = context->current)
 1211: 		    if (context->local.s_addr == option_addr(opt).s_addr)
 1212: 		      break;
 1213: 		  
 1214: 		  if (!context)
 1215: 		    {
 1216: 		      /* Handle very strange configs where clients have more than one route to the server.
 1217: 			 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
 1218: 			 Have to set override to make sure we echo back the correct server-id */
 1219: 		      struct irec *intr;
 1220: 		      
 1221: 		      enumerate_interfaces(0);
 1222: 
 1223: 		      for (intr = daemon->interfaces; intr; intr = intr->next)
 1224: 			if (intr->addr.sa.sa_family == AF_INET &&
 1225: 			    intr->addr.in.sin_addr.s_addr == option_addr(opt).s_addr &&
 1226: 			    intr->tftp_ok)
 1227: 			  break;
 1228: 
 1229: 		      if (intr)
 1230: 			override = intr->addr.in.sin_addr;
 1231: 		      else
 1232: 			{
 1233: 			  /* In auth mode, a REQUEST sent to the wrong server
 1234: 			     should be faulted, so that the client establishes 
 1235: 			     communication with us, otherwise, silently ignore. */
 1236: 			  if (!option_bool(OPT_AUTHORITATIVE))
 1237: 			    return 0;
 1238: 			  message = _("wrong server-ID");
 1239: 			}
 1240: 		    }
 1241: 		}
 1242: 
 1243: 	      /* If a lease exists for this host and another address, squash it. */
 1244: 	      if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
 1245: 		{
 1246: 		  lease_prune(lease, now);
 1247: 		  lease = NULL;
 1248: 		}
 1249: 	    }
 1250: 	  else
 1251: 	    {
 1252: 	      /* INIT-REBOOT */
 1253: 	      if (!lease && !option_bool(OPT_AUTHORITATIVE))
 1254: 		return 0;
 1255: 	      
 1256: 	      if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
 1257: 		message = _("wrong address");
 1258: 	    }
 1259: 	}
 1260:       else
 1261: 	{
 1262: 	  /* RENEWING or REBINDING */ 
 1263: 	  /* Check existing lease for this address.
 1264: 	     We allow it to be missing if dhcp-authoritative mode
 1265: 	     as long as we can allocate the lease now - checked below.
 1266: 	     This makes for a smooth recovery from a lost lease DB */
 1267: 	  if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
 1268: 	      (!lease && !option_bool(OPT_AUTHORITATIVE)))
 1269: 	    {
 1270: 	      /* A client rebinding will broadcast the request, so we may see it even 
 1271: 		 if the lease is held by another server. Just ignore it in that case. 
 1272: 		 If the request is unicast to us, then somethings wrong, NAK */
 1273: 	      if (!unicast_dest)
 1274: 		return 0;
 1275: 	      message = _("lease not found");
 1276: 	      /* ensure we broadcast NAK */
 1277: 	      unicast_dest = 0;
 1278: 	    }
 1279: 
 1280: 	  /* desynchronise renewals */
 1281: 	  fuzz = rand16();
 1282: 	  mess->yiaddr = mess->ciaddr;
 1283: 	}
 1284: 
 1285:       daemon->metrics[METRIC_DHCPREQUEST]++;
 1286:       log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
 1287:       
 1288:     rapid_commit:
 1289:       if (!message)
 1290: 	{
 1291: 	  struct dhcp_config *addr_config;
 1292: 	  struct dhcp_context *tmp = NULL;
 1293: 	  
 1294: 	  if (have_config(config, CONFIG_ADDR))
 1295: 	    for (tmp = context; tmp; tmp = tmp->current)
 1296: 	      if (context->router.s_addr == config->addr.s_addr)
 1297: 		break;
 1298: 	  
 1299: 	  if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
 1300: 	    {
 1301: 	      /* If a machine moves networks whilst it has a lease, we catch that here. */
 1302: 	      message = _("wrong network");
 1303: 	      /* ensure we broadcast NAK */
 1304: 	      unicast_dest = 0;
 1305: 	    }
 1306: 	  
 1307: 	  /* Check for renewal of a lease which is outside the allowed range. */
 1308: 	  else if (!address_available(context, mess->yiaddr, tagif_netid) &&
 1309: 		   (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
 1310: 	    message = _("address not available");
 1311: 	  
 1312: 	  /* Check if a new static address has been configured. Be very sure that
 1313: 	     when the client does DISCOVER, it will get the static address, otherwise
 1314: 	     an endless protocol loop will ensue. */
 1315: 	  else if (!tmp && !selecting &&
 1316: 		   have_config(config, CONFIG_ADDR) && 
 1317: 		   (!have_config(config, CONFIG_DECLINED) ||
 1318: 		    difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
 1319: 		   config->addr.s_addr != mess->yiaddr.s_addr &&
 1320: 		   (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
 1321: 	    message = _("static lease available");
 1322: 
 1323: 	  /* Check to see if the address is reserved as a static address for another host */
 1324: 	  else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
 1325: 	    message = _("address reserved");
 1326: 
 1327: 	  else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
 1328: 	    {
 1329: 	      /* If a host is configured with more than one MAC address, it's OK to 'nix 
 1330: 		 a lease from one of it's MACs to give the address to another. */
 1331: 	      if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
 1332: 		{
 1333: 		  inet_ntop(AF_INET, &ltmp->addr, daemon->addrbuff, ADDRSTRLEN);
 1334: 		  my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
 1335: 			    print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len), 
 1336: 			    daemon->addrbuff);
 1337: 		  lease = ltmp;
 1338: 		}
 1339: 	      else
 1340: 		message = _("address in use");
 1341: 	    }
 1342: 
 1343: 	  if (!message)
 1344: 	    {
 1345: 	      if (emac_len == 0)
 1346: 		message = _("no unique-id");
 1347: 	      
 1348: 	      else if (!lease)
 1349: 		{	     
 1350: 		  if ((lease = lease4_allocate(mess->yiaddr)))
 1351: 		    do_classes = 1;
 1352: 		  else
 1353: 		    message = _("no leases left");
 1354: 		}
 1355: 	    }
 1356: 	}
 1357: 
 1358:       if (message)
 1359: 	{
 1360: 	  daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
 1361: 	  log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
 1362: 
 1363: 	  /* rapid commit case: lease allocate failed but don't send DHCPNAK */
 1364: 	  if (rapid_commit)
 1365: 	    return 0;
 1366: 	  
 1367: 	  mess->yiaddr.s_addr = 0;
 1368: 	  clear_packet(mess, end);
 1369: 	  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
 1370: 	  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
 1371: 	  option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
 1372: 	  /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on 
 1373: 	     a distant subnet which unicast a REQ to us won't work. */
 1374: 	  if (!unicast_dest || mess->giaddr.s_addr != 0 || 
 1375: 	      mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
 1376: 	    {
 1377: 	      mess->flags |= htons(0x8000); /* broadcast */
 1378: 	      mess->ciaddr.s_addr = 0;
 1379: 	    }
 1380: 	}
 1381:       else
 1382: 	{
 1383: 	  if (context->netid.net)
 1384: 	    {
 1385: 	      context->netid.next = netid;
 1386: 	      tagif_netid = run_tag_if( &context->netid);
 1387: 	    }
 1388: 
 1389: 	  log_tags(tagif_netid, ntohl(mess->xid));
 1390: 	  
 1391: 	  if (do_classes)
 1392: 	    {
 1393: 	      /* pick up INIT-REBOOT events. */
 1394: 	      lease->flags |= LEASE_CHANGED;
 1395: 
 1396: #ifdef HAVE_SCRIPT
 1397: 	      if (daemon->lease_change_command)
 1398: 		{
 1399: 		  struct dhcp_netid *n;
 1400: 		  
 1401: 		  if (mess->giaddr.s_addr)
 1402: 		    lease->giaddr = mess->giaddr;
 1403: 		  
 1404: 		  free(lease->extradata);
 1405: 		  lease->extradata = NULL;
 1406: 		  lease->extradata_size = lease->extradata_len = 0;
 1407: 		  
 1408: 		  add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
 1409: 		  add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
 1410: 		  add_extradata_opt(lease, oui);
 1411: 		  add_extradata_opt(lease, serial);
 1412: 		  add_extradata_opt(lease, class);
 1413: 
 1414: 		  if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
 1415: 		    {
 1416: 		      add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
 1417: 		      add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
 1418: 		      add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
 1419: 		    }
 1420: 		  else
 1421: 		    {
 1422: 		      add_extradata_opt(lease, NULL);
 1423: 		      add_extradata_opt(lease, NULL);
 1424: 		      add_extradata_opt(lease, NULL);
 1425: 		    }
 1426: 
 1427: 		  /* DNSMASQ_REQUESTED_OPTIONS */
 1428: 		  if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
 1429: 		    {
 1430: 		      int i, len = option_len(opt);
 1431: 		      unsigned char *rop = option_ptr(opt, 0);
 1432: 		      
 1433: 		      for (i = 0; i < len; i++)
 1434: 			lease_add_extradata(lease, (unsigned char *)daemon->namebuff,
 1435: 					    sprintf(daemon->namebuff, "%u", rop[i]), (i + 1) == len ? 0 : ',');
 1436: 		    }
 1437: 		  else
 1438: 		    lease_add_extradata(lease, NULL, 0, 0);
 1439: 		  
 1440: 		  add_extradata_opt(lease, option_find(mess, sz, OPTION_MUD_URL_V4, 1));
 1441: 		  
 1442: 		  /* space-concat tag set */
 1443: 		  if (!tagif_netid)
 1444: 		    add_extradata_opt(lease, NULL);
 1445: 		  else
 1446: 		    for (n = tagif_netid; n; n = n->next)
 1447: 		      {
 1448: 			struct dhcp_netid *n1;
 1449: 			/* kill dupes */
 1450: 			for (n1 = n->next; n1; n1 = n1->next)
 1451: 			  if (strcmp(n->net, n1->net) == 0)
 1452: 			    break;
 1453: 			if (!n1)
 1454: 			  lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0); 
 1455: 		      }
 1456: 		  
 1457: 		  if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
 1458: 		    {
 1459: 		      int len = option_len(opt);
 1460: 		      unsigned char *ucp = option_ptr(opt, 0);
 1461: 		      /* If the user-class option started as counted strings, the first byte will be zero. */
 1462: 		      if (len != 0 && ucp[0] == 0)
 1463: 			ucp++, len--;
 1464: 		      lease_add_extradata(lease, ucp, len, -1);
 1465: 		    }
 1466: 		}
 1467: #endif
 1468: 	    }
 1469: 	  
 1470: 	  if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
 1471: 	    {
 1472: 	      domain = get_domain(mess->yiaddr);
 1473: 	      hostname = client_hostname;
 1474: 	      hostname_auth = 1;
 1475: 	    }
 1476: 	  
 1477: 	  time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
 1478: 	  lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
 1479: 	  
 1480: 	  /* if all the netids in the ignore_name list are present, ignore client-supplied name */
 1481: 	  if (!hostname_auth)
 1482: 	    {
 1483: 	      for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
 1484: 		if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
 1485: 		  break;
 1486: 	      if (id_list)
 1487: 		hostname = NULL;
 1488: 	    }
 1489: 	  
 1490: 	  /* Last ditch, if configured, generate hostname from mac address */
 1491: 	  if (!hostname && emac_len != 0)
 1492: 	    {
 1493: 	      for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
 1494: 		if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
 1495: 		  break;
 1496: 	      if (id_list)
 1497: 		{
 1498: 		  int i;
 1499: 
 1500: 		  hostname = daemon->dhcp_buff;
 1501: 		  /* buffer is 256 bytes, 3 bytes per octet */
 1502: 		  for (i = 0; (i < emac_len) && (i < 80); i++)
 1503: 		    hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
 1504: 		  hostname = daemon->dhcp_buff;
 1505: 		}
 1506: 	    }
 1507: 
 1508: 	  if (hostname)
 1509: 	    lease_set_hostname(lease, hostname, hostname_auth, get_domain(lease->addr), domain);
 1510: 	  
 1511: 	  lease_set_expires(lease, time, now);
 1512: 	  lease_set_interface(lease, int_index, now);
 1513: 
 1514: 	  if (override.s_addr != 0)
 1515: 	    lease->override = override;
 1516: 	  else
 1517: 	    override = lease->override;
 1518: 
 1519: 	  daemon->metrics[METRIC_DHCPACK]++;
 1520: 	  log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);  
 1521: 
 1522: 	  clear_packet(mess, end);
 1523: 	  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
 1524: 	  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
 1525: 	  option_put(mess, end, OPTION_LEASE_TIME, 4, time);
 1526: 	  if (rapid_commit)
 1527: 	     option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
 1528: 	   do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr), 
 1529: 		     netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
 1530: 	}
 1531: 
 1532:       return dhcp_packet_size(mess, agent_id, real_end); 
 1533:       
 1534:     case DHCPINFORM:
 1535:       if (ignore || have_config(config, CONFIG_DISABLE))
 1536: 	message = _("ignored");
 1537:       
 1538:       daemon->metrics[METRIC_DHCPINFORM]++;
 1539:       log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
 1540:      
 1541:       if (message || mess->ciaddr.s_addr == 0)
 1542: 	return 0;
 1543: 
 1544:       /* For DHCPINFORM only, cope without a valid context */
 1545:       context = narrow_context(context, mess->ciaddr, tagif_netid);
 1546:       
 1547:       /* Find a least based on IP address if we didn't
 1548: 	 get one from MAC address/client-d */
 1549:       if (!lease &&
 1550: 	  (lease = lease_find_by_addr(mess->ciaddr)) && 
 1551: 	  lease->hostname)
 1552: 	hostname = lease->hostname;
 1553:       
 1554:       if (!hostname)
 1555: 	hostname = host_from_dns(mess->ciaddr);
 1556:       
 1557:       if (context && context->netid.net)
 1558: 	{
 1559: 	  context->netid.next = netid;
 1560: 	  tagif_netid = run_tag_if(&context->netid);
 1561: 	}
 1562: 
 1563:       log_tags(tagif_netid, ntohl(mess->xid));
 1564:       
 1565:       daemon->metrics[METRIC_DHCPACK]++;
 1566:       log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
 1567:       
 1568:       if (lease)
 1569: 	{
 1570: 	  lease_set_interface(lease, int_index, now);
 1571: 	  if (override.s_addr != 0)
 1572: 	    lease->override = override;
 1573: 	  else
 1574: 	    override = lease->override;
 1575: 	}
 1576: 
 1577:       clear_packet(mess, end);
 1578:       option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
 1579:       option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
 1580:      
 1581:       /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but 
 1582: 	 we supply a utility which makes DHCPINFORM requests to get this information.
 1583: 	 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
 1584: 	 which won't be true for ordinary clients, but will be true for the 
 1585: 	 dhcp_lease_time utility. */
 1586:       if (lease && in_list(req_options, OPTION_LEASE_TIME))
 1587: 	{
 1588: 	  if (lease->expires == 0)
 1589: 	    time = 0xffffffff;
 1590: 	  else
 1591: 	    time = (unsigned int)difftime(lease->expires, now);
 1592: 	  option_put(mess, end, OPTION_LEASE_TIME, 4, time);
 1593: 	}
 1594: 
 1595:       do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
 1596: 		 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0, pxevendor);
 1597:       
 1598:       *is_inform = 1; /* handle reply differently */
 1599:       return dhcp_packet_size(mess, agent_id, real_end); 
 1600:     }
 1601:   
 1602:   return 0;
 1603: }
 1604: 
 1605: /* find a good value to use as MAC address for logging and address-allocation hashing.
 1606:    This is normally just the chaddr field from the DHCP packet,
 1607:    but eg Firewire will have hlen == 0 and use the client-id instead. 
 1608:    This could be anything, but will normally be EUI64 for Firewire.
 1609:    We assume that if the first byte of the client-id equals the htype byte
 1610:    then the client-id is using the usual encoding and use the rest of the 
 1611:    client-id: if not we can use the whole client-id. This should give
 1612:    sane MAC address logs. */
 1613: unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, 
 1614: 				      int clid_len, unsigned char *clid, int *len_out)
 1615: {
 1616:   if (hwlen == 0 && clid && clid_len > 3)
 1617:     {
 1618:       if (clid[0]  == hwtype)
 1619: 	{
 1620: 	  *len_out = clid_len - 1 ;
 1621: 	  return clid + 1;
 1622: 	}
 1623: 
 1624: #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
 1625:       if (clid[0] ==  ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
 1626: 	{
 1627: 	  *len_out = clid_len - 1 ;
 1628: 	  return clid + 1;
 1629: 	}
 1630: #endif
 1631:       
 1632:       *len_out = clid_len;
 1633:       return clid;
 1634:     }
 1635:   
 1636:   *len_out = hwlen;
 1637:   return hwaddr;
 1638: }
 1639: 
 1640: static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
 1641: {
 1642:   unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
 1643:   
 1644:   if (opt)
 1645:     { 
 1646:       unsigned int req_time = option_uint(opt, 0, 4);
 1647:       if (req_time < 120 )
 1648: 	req_time = 120; /* sanity */
 1649:       if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
 1650: 	time = req_time;
 1651:     }
 1652: 
 1653:   return time;
 1654: }
 1655: 
 1656: static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
 1657: {
 1658:   if (override.s_addr != 0)
 1659:     return override;
 1660:   else if (context && context->local.s_addr != 0)
 1661:     return context->local;
 1662:   else
 1663:     return fallback;
 1664: }
 1665: 
 1666: static int sanitise(unsigned char *opt, char *buf)
 1667: {
 1668:   char *p;
 1669:   int i;
 1670:   
 1671:   *buf = 0;
 1672:   
 1673:   if (!opt)
 1674:     return 0;
 1675: 
 1676:   p = option_ptr(opt, 0);
 1677: 
 1678:   for (i = option_len(opt); i > 0; i--)
 1679:     {
 1680:       char c = *p++;
 1681:       if (isprint((unsigned char)c))
 1682: 	*buf++ = c;
 1683:     }
 1684:   *buf = 0; /* add terminator */
 1685:   
 1686:   return 1;
 1687: }
 1688: 
 1689: #ifdef HAVE_SCRIPT
 1690: static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
 1691: {
 1692:   if (!opt)
 1693:     lease_add_extradata(lease, NULL, 0, 0);
 1694:   else
 1695:     lease_add_extradata(lease, option_ptr(opt, 0), option_len(opt), 0); 
 1696: }
 1697: #endif
 1698: 
 1699: static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
 1700: 		       int mac_len, char *interface, char *string, char *err, u32 xid)
 1701: {
 1702:   if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
 1703:     return;
 1704:   
 1705:   daemon->addrbuff[0] = 0;
 1706:   if (addr)
 1707:     inet_ntop(AF_INET, addr, daemon->addrbuff, ADDRSTRLEN);
 1708:   
 1709:   print_mac(daemon->namebuff, ext_mac, mac_len);
 1710:   
 1711:   if (option_bool(OPT_LOG_OPTS))
 1712:     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
 1713: 	      ntohl(xid), 
 1714: 	      type,
 1715: 	      interface, 
 1716: 	      daemon->addrbuff,
 1717: 	      addr ? " " : "",
 1718: 	      daemon->namebuff,
 1719: 	      string ? string : "",
 1720: 	      err ? err : "");
 1721:   else
 1722:     my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
 1723: 	      type,
 1724: 	      interface, 
 1725: 	      daemon->addrbuff,
 1726: 	      addr ? " " : "",
 1727: 	      daemon->namebuff,
 1728: 	      string ? string : "",
 1729: 	      err ? err : "");
 1730:   
 1731: #ifdef HAVE_UBUS
 1732:   if (!strcmp(type, "DHCPACK"))
 1733:     ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
 1734:   else if (!strcmp(type, "DHCPRELEASE"))
 1735:     ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
 1736: #endif
 1737: }
 1738: 
 1739: static void log_options(unsigned char *start, u32 xid)
 1740: {
 1741:   while (*start != OPTION_END)
 1742:     {
 1743:       char *optname = option_string(AF_INET, start[0], option_ptr(start, 0), option_len(start), daemon->namebuff, MAXDNAME);
 1744:       
 1745:       my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d %s  %s", 
 1746: 		ntohl(xid), option_len(start), start[0], optname, daemon->namebuff);
 1747:       start += start[1] + 2;
 1748:     }
 1749: }
 1750: 
 1751: static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
 1752: {
 1753:   while (1) 
 1754:     {
 1755:       if (p >= end)
 1756: 	return NULL;
 1757:       else if (*p == OPTION_END)
 1758: 	return opt == OPTION_END ? p : NULL;
 1759:       else if (*p == OPTION_PAD)
 1760: 	p++;
 1761:       else 
 1762: 	{ 
 1763: 	  int opt_len;
 1764: 	  if (p > end - 2)
 1765: 	    return NULL; /* malformed packet */
 1766: 	  opt_len = option_len(p);
 1767: 	  if (p > end - (2 + opt_len))
 1768: 	    return NULL; /* malformed packet */
 1769: 	  if (*p == opt && opt_len >= minsize)
 1770: 	    return p;
 1771: 	  p += opt_len + 2;
 1772: 	}
 1773:     }
 1774: }
 1775:  
 1776: static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
 1777: {
 1778:   unsigned char *ret, *overload;
 1779:   
 1780:   /* skip over DHCP cookie; */
 1781:   if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
 1782:     return ret;
 1783: 
 1784:   /* look for overload option. */
 1785:   if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
 1786:     return NULL;
 1787:   
 1788:   /* Can we look in filename area ? */
 1789:   if ((overload[2] & 1) &&
 1790:       (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
 1791:     return ret;
 1792: 
 1793:   /* finally try sname area */
 1794:   if ((overload[2] & 2) &&
 1795:       (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
 1796:     return ret;
 1797: 
 1798:   return NULL;
 1799: }
 1800: 
 1801: static struct in_addr option_addr(unsigned char *opt)
 1802: {
 1803:    /* this worries about unaligned data in the option. */
 1804:   /* struct in_addr is network byte order */
 1805:   struct in_addr ret;
 1806: 
 1807:   memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
 1808: 
 1809:   return ret;
 1810: }
 1811: 
 1812: static unsigned int option_uint(unsigned char *opt, int offset, int size)
 1813: {
 1814:   /* this worries about unaligned data and byte order */
 1815:   unsigned int ret = 0;
 1816:   int i;
 1817:   unsigned char *p = option_ptr(opt, offset);
 1818:   
 1819:   for (i = 0; i < size; i++)
 1820:     ret = (ret << 8) | *p++;
 1821: 
 1822:   return ret;
 1823: }
 1824: 
 1825: static unsigned char *dhcp_skip_opts(unsigned char *start)
 1826: {
 1827:   while (*start != 0)
 1828:     start += start[1] + 2;
 1829:   return start;
 1830: }
 1831: 
 1832: /* only for use when building packet: doesn't check for bad data. */ 
 1833: static unsigned char *find_overload(struct dhcp_packet *mess)
 1834: {
 1835:   unsigned char *p = &mess->options[0] + sizeof(u32);
 1836:   
 1837:   while (*p != 0)
 1838:     {
 1839:       if (*p == OPTION_OVERLOAD)
 1840: 	return p;
 1841:       p += p[1] + 2;
 1842:     }
 1843:   return NULL;
 1844: }
 1845: 
 1846: static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end)
 1847: {
 1848:   unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
 1849:   unsigned char *overload;
 1850:   size_t ret;
 1851:   
 1852:   /* move agent_id back down to the end of the packet */
 1853:   if (agent_id)
 1854:     {
 1855:       memmove(p, agent_id, real_end - agent_id);
 1856:       p += real_end - agent_id;
 1857:       memset(p, 0, real_end - p); /* in case of overlap */
 1858:     }
 1859:   
 1860:   /* add END options to the regions. */
 1861:   overload = find_overload(mess);
 1862:   
 1863:   if (overload && (option_uint(overload, 0, 1) & 1))
 1864:     {
 1865:       *dhcp_skip_opts(mess->file) = OPTION_END;
 1866:       if (option_bool(OPT_LOG_OPTS))
 1867: 	log_options(mess->file, mess->xid);
 1868:     }
 1869:   else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
 1870:     my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
 1871:   
 1872:   if (overload && (option_uint(overload, 0, 1) & 2))
 1873:     {
 1874:       *dhcp_skip_opts(mess->sname) = OPTION_END;
 1875:       if (option_bool(OPT_LOG_OPTS))
 1876: 	log_options(mess->sname, mess->xid);
 1877:     }
 1878:   else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
 1879:     my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
 1880: 
 1881: 
 1882:   *p++ = OPTION_END;
 1883:   
 1884:   if (option_bool(OPT_LOG_OPTS))
 1885:     {
 1886:       if (mess->siaddr.s_addr != 0)
 1887: 	{
 1888: 	  inet_ntop(AF_INET, &mess->siaddr, daemon->addrbuff, ADDRSTRLEN);
 1889: 	  my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), daemon->addrbuff);
 1890: 	}
 1891:       
 1892:       if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
 1893: 	my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
 1894:       
 1895:       log_options(&mess->options[0] + sizeof(u32), mess->xid);
 1896:     } 
 1897:   
 1898:   ret = (size_t)(p - (unsigned char *)mess);
 1899:   
 1900:   if (ret < MIN_PACKETSZ)
 1901:     ret = MIN_PACKETSZ;
 1902:   
 1903:   return ret;
 1904: }
 1905: 
 1906: static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
 1907: {
 1908:   unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
 1909:   
 1910:   if (p + len + 3 >= end)
 1911:     /* not enough space in options area, try and use overload, if poss */
 1912:     {
 1913:       unsigned char *overload;
 1914:       
 1915:       if (!(overload = find_overload(mess)) &&
 1916: 	  (mess->file[0] == 0 || mess->sname[0] == 0))
 1917: 	{
 1918: 	  /* attempt to overload fname and sname areas, we've reserved space for the
 1919: 	     overflow option previuously. */
 1920: 	  overload = p;
 1921: 	  *(p++) = OPTION_OVERLOAD;
 1922: 	  *(p++) = 1;
 1923: 	}
 1924:       
 1925:       p = NULL;
 1926:       
 1927:       /* using filename field ? */
 1928:       if (overload)
 1929: 	{
 1930: 	  if (mess->file[0] == 0)
 1931: 	    overload[2] |= 1;
 1932: 	  
 1933: 	  if (overload[2] & 1)
 1934: 	    {
 1935: 	      p = dhcp_skip_opts(mess->file);
 1936: 	      if (p + len + 3 >= mess->file + sizeof(mess->file))
 1937: 		p = NULL;
 1938: 	    }
 1939: 	  
 1940: 	  if (!p)
 1941: 	    {
 1942: 	      /* try to bring sname into play (it may be already) */
 1943: 	      if (mess->sname[0] == 0)
 1944: 		overload[2] |= 2;
 1945: 	      
 1946: 	      if (overload[2] & 2)
 1947: 		{
 1948: 		  p = dhcp_skip_opts(mess->sname);
 1949: 		  if (p + len + 3 >= mess->sname + sizeof(mess->sname))
 1950: 		    p = NULL;
 1951: 		}
 1952: 	    }
 1953: 	}
 1954:       
 1955:       if (!p)
 1956: 	my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
 1957:     }
 1958:  
 1959:   if (p)
 1960:     {
 1961:       *(p++) = opt;
 1962:       *(p++) = len;
 1963:     }
 1964: 
 1965:   return p;
 1966: }
 1967: 	      
 1968: static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
 1969: {
 1970:   int i;
 1971:   unsigned char *p = free_space(mess, end, opt, len);
 1972:   
 1973:   if (p) 
 1974:     for (i = 0; i < len; i++)
 1975:       *(p++) = val >> (8 * (len - (i + 1)));
 1976: }
 1977: 
 1978: static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt, 
 1979: 			      const char *string, int null_term)
 1980: {
 1981:   unsigned char *p;
 1982:   size_t len = strlen(string);
 1983: 
 1984:   if (null_term && len != 255)
 1985:     len++;
 1986: 
 1987:   if ((p = free_space(mess, end, opt, len)))
 1988:     memcpy(p, string, len);
 1989: }
 1990: 
 1991: /* return length, note this only does the data part */
 1992: static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
 1993: {
 1994:   int len = opt->len;
 1995:   
 1996:   if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
 1997:     len++;
 1998: 
 1999:   if (p && len != 0)
 2000:     {
 2001:       if (context && (opt->flags & DHOPT_ADDR))
 2002: 	{
 2003: 	  int j;
 2004: 	  struct in_addr *a = (struct in_addr *)opt->val;
 2005: 	  for (j = 0; j < opt->len; j+=INADDRSZ, a++)
 2006: 	    {
 2007: 	      /* zero means "self" (but not in vendorclass options.) */
 2008: 	      if (a->s_addr == 0)
 2009: 		memcpy(p, &context->local, INADDRSZ);
 2010: 	      else
 2011: 		memcpy(p, a, INADDRSZ);
 2012: 	      p += INADDRSZ;
 2013: 	    }
 2014: 	}
 2015:       else
 2016: 	/* empty string may be extended to "\0" by null_term */
 2017: 	memcpy(p, opt->val ? opt->val : (unsigned char *)"", len);
 2018:     }  
 2019:   return len;
 2020: }
 2021: 
 2022: static int in_list(unsigned char *list, int opt)
 2023: {
 2024:   int i;
 2025: 
 2026:    /* If no requested options, send everything, not nothing. */
 2027:   if (!list)
 2028:     return 1;
 2029:   
 2030:   for (i = 0; list[i] != OPTION_END; i++)
 2031:     if (opt == list[i])
 2032:       return 1;
 2033: 
 2034:   return 0;
 2035: }
 2036: 
 2037: static struct dhcp_opt *option_find2(int opt)
 2038: {
 2039:   struct dhcp_opt *opts;
 2040:   
 2041:   for (opts = daemon->dhcp_opts; opts; opts = opts->next)
 2042:     if (opts->opt == opt && (opts->flags & DHOPT_TAGOK))
 2043:       return opts;
 2044:   
 2045:   return NULL;
 2046: }
 2047: 
 2048: /* mark vendor-encapsulated options which match the client-supplied  or
 2049:    config-supplied vendor class */
 2050: static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
 2051: {
 2052:   for (; dopt; dopt = dopt->next)
 2053:     {
 2054:       dopt->flags &= ~DHOPT_VENDOR_MATCH;
 2055:       if (opt && (dopt->flags & DHOPT_VENDOR))
 2056: 	{
 2057: 	  const struct dhcp_pxe_vendor *pv;
 2058: 	  struct dhcp_pxe_vendor dummy_vendor = {
 2059: 	    .data = (char *)dopt->u.vendor_class,
 2060: 	    .next = NULL,
 2061: 	  };
 2062: 	  if (dopt->flags & DHOPT_VENDOR_PXE)
 2063: 	    pv = daemon->dhcp_pxe_vendors;
 2064: 	  else
 2065: 	    pv = &dummy_vendor;
 2066: 	  for (; pv; pv = pv->next)
 2067: 	    {
 2068: 	      int i, len = 0, matched = 0;
 2069: 	      if (pv->data)
 2070: 	        len = strlen(pv->data);
 2071: 	      for (i = 0; i <= (option_len(opt) - len); i++)
 2072: 	        if (len == 0 || memcmp(pv->data, option_ptr(opt, i), len) == 0)
 2073: 	          {
 2074: 		    matched = 1;
 2075: 	            break;
 2076: 	          }
 2077: 	      if (matched)
 2078: 		{
 2079: 	          dopt->flags |= DHOPT_VENDOR_MATCH;
 2080: 		  break;
 2081: 		}
 2082: 	    }
 2083: 	}
 2084:     }
 2085: }
 2086: 
 2087: static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,  
 2088: 			 struct dhcp_packet *mess, unsigned char *end, int null_term)
 2089: {
 2090:   int len, enc_len, ret = 0;
 2091:   struct dhcp_opt *start;
 2092:   unsigned char *p;
 2093:     
 2094:   /* find size in advance */
 2095:   for (enc_len = 0, start = opt; opt; opt = opt->next)
 2096:     if (opt->flags & flag)
 2097:       {
 2098: 	int new = do_opt(opt, NULL, NULL, null_term) + 2;
 2099: 	ret  = 1;
 2100: 	if (enc_len + new <= 255)
 2101: 	  enc_len += new;
 2102: 	else
 2103: 	  {
 2104: 	    p = free_space(mess, end, encap, enc_len);
 2105: 	    for (; start && start != opt; start = start->next)
 2106: 	      if (p && (start->flags & flag))
 2107: 		{
 2108: 		  len = do_opt(start, p + 2, NULL, null_term);
 2109: 		  *(p++) = start->opt;
 2110: 		  *(p++) = len;
 2111: 		  p += len;
 2112: 		}
 2113: 	    enc_len = new;
 2114: 	    start = opt;
 2115: 	  }
 2116:       }
 2117:   
 2118:   if (enc_len != 0 &&
 2119:       (p = free_space(mess, end, encap, enc_len + 1)))
 2120:     {
 2121:       for (; start; start = start->next)
 2122: 	if (start->flags & flag)
 2123: 	  {
 2124: 	    len = do_opt(start, p + 2, NULL, null_term);
 2125: 	    *(p++) = start->opt;
 2126: 	    *(p++) = len;
 2127: 	    p += len;
 2128: 	  }
 2129:       *p = OPTION_END;
 2130:     }
 2131: 
 2132:   return ret;
 2133: }
 2134: 
 2135: static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor)
 2136: {
 2137:   unsigned char *p;
 2138: 
 2139:   if (!pxevendor)
 2140:     pxevendor="PXEClient";
 2141:   option_put_string(mess, end, OPTION_VENDOR_ID, pxevendor, 0);
 2142:   if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
 2143:     memcpy(p, uuid, 17);
 2144: }
 2145: 
 2146: static int prune_vendor_opts(struct dhcp_netid *netid)
 2147: {
 2148:   int force = 0;
 2149:   struct dhcp_opt *opt;
 2150: 
 2151:   /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
 2152:   for (opt = daemon->dhcp_opts; opt; opt = opt->next)
 2153:     if (opt->flags & DHOPT_VENDOR_MATCH)
 2154:       {
 2155: 	if (!match_netid(opt->netid, netid, 1))
 2156: 	  opt->flags &= ~DHOPT_VENDOR_MATCH;
 2157: 	else if (opt->flags & DHOPT_FORCE)
 2158: 	  force = 1;
 2159:       }
 2160:   return force;
 2161: }
 2162: 
 2163: 
 2164: /* Many UEFI PXE implementations have badly broken menu code.
 2165:    If there's exactly one relevant menu item, we abandon the menu system,
 2166:    and jamb the data direct into the DHCP file, siaddr and sname fields.
 2167:    Note that in this case, we have to assume that layer zero would be requested
 2168:    by the client PXE stack. */
 2169: static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
 2170: {
 2171:   struct pxe_service *service, *found;
 2172: 
 2173:   /* Only workaround UEFI archs. */
 2174:   if (pxe_arch < 6)
 2175:     return 0;
 2176:   
 2177:   for (found = NULL, service = daemon->pxe_services; service; service = service->next)
 2178:     if (pxe_arch == service->CSA && service->basename && match_netid(service->netid, netid, 1))
 2179:       {
 2180: 	if (found)
 2181: 	  return 0; /* More than one relevant menu item */
 2182: 	  
 2183: 	found = service;
 2184:       }
 2185: 
 2186:   if (!found)
 2187:     return 0; /* No relevant menu items. */
 2188:   
 2189:   if (!pxe)
 2190:      return 1;
 2191:   
 2192:   if (found->sname)
 2193:     {
 2194:       mess->siaddr = a_record_from_hosts(found->sname, now);
 2195:       snprintf((char *)mess->sname, sizeof(mess->sname), "%s", found->sname);
 2196:     }
 2197:   else 
 2198:     {
 2199:       if (found->server.s_addr != 0)
 2200: 	mess->siaddr = found->server; 
 2201:       else
 2202: 	mess->siaddr = local;
 2203:   
 2204:       inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
 2205:     }
 2206:   
 2207:   if (found->basename)
 2208:     snprintf((char *)mess->file, sizeof(mess->file), 
 2209: 	     strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
 2210:   
 2211:   return 1;
 2212: }
 2213: 
 2214: static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
 2215: {
 2216: #define NUM_OPTS 4  
 2217: 
 2218:   unsigned  char *p, *q;
 2219:   struct pxe_service *service;
 2220:   static struct dhcp_opt *o, *ret;
 2221:   int i, j = NUM_OPTS - 1;
 2222:   struct in_addr boot_server;
 2223:   
 2224:   /* We pass back references to these, hence they are declared static */
 2225:   static unsigned char discovery_control;
 2226:   static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' }; 
 2227:   static struct dhcp_opt *fake_opts = NULL;
 2228:   
 2229:   /* Disable multicast, since we don't support it, and broadcast
 2230:      unless we need it */
 2231:   discovery_control = 3;
 2232:   
 2233:   ret = daemon->dhcp_opts;
 2234:   
 2235:   if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
 2236:     return ret;
 2237: 
 2238:   for (i = 0; i < NUM_OPTS; i++)
 2239:     {
 2240:       fake_opts[i].flags = DHOPT_VENDOR_MATCH;
 2241:       fake_opts[i].netid = NULL;
 2242:       fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
 2243:     }
 2244:   
 2245:   /* create the data for the PXE_MENU and PXE_SERVERS options. */
 2246:   p = (unsigned char *)daemon->dhcp_buff;
 2247:   q = (unsigned char *)daemon->dhcp_buff3;
 2248: 
 2249:   for (i = 0, service = daemon->pxe_services; service; service = service->next)
 2250:     if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
 2251:       {
 2252: 	size_t len = strlen(service->menu);
 2253: 	/* opt 43 max size is 255. encapsulated option has type and length
 2254: 	   bytes, so its max size is 253. */
 2255: 	if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
 2256: 	  {
 2257: 	    *(p++) = service->type >> 8;
 2258: 	    *(p++) = service->type;
 2259: 	    *(p++) = len;
 2260: 	    memcpy(p, service->menu, len);
 2261: 	    p += len;
 2262: 	    i++;
 2263: 	  }
 2264: 	else
 2265: 	  {
 2266: 	  toobig:
 2267: 	    my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
 2268: 	    return daemon->dhcp_opts;
 2269: 	  }
 2270: 	
 2271: 	boot_server = service->basename ? local : 
 2272: 	  (service->sname ? a_record_from_hosts(service->sname, now) : service->server);
 2273: 	
 2274: 	if (boot_server.s_addr != 0)
 2275: 	  {
 2276: 	    if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
 2277: 	      goto toobig;
 2278: 	    
 2279: 	    /* Boot service with known address - give it */
 2280: 	    *(q++) = service->type >> 8;
 2281: 	    *(q++) = service->type;
 2282: 	    *(q++) = 1;
 2283: 	    /* dest misaligned */
 2284: 	    memcpy(q, &boot_server.s_addr, INADDRSZ);
 2285: 	    q += INADDRSZ;
 2286: 	  }
 2287: 	else if (service->type != 0)
 2288: 	  /* We don't know the server for a service type, so we'll
 2289: 	     allow the client to broadcast for it */
 2290: 	  discovery_control = 2;
 2291:       }
 2292: 
 2293:   /* if no prompt, wait forever if there's a choice */
 2294:   fake_prompt[0] = (i > 1) ? 255 : 0;
 2295:   
 2296:   if (i == 0)
 2297:     discovery_control = 8; /* no menu - just use use mess->filename */
 2298:   else
 2299:     {
 2300:       ret = &fake_opts[j--];
 2301:       ret->len = p - (unsigned char *)daemon->dhcp_buff;
 2302:       ret->val = (unsigned char *)daemon->dhcp_buff;
 2303:       ret->opt = SUBOPT_PXE_MENU;
 2304: 
 2305:       if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
 2306: 	{
 2307: 	  ret = &fake_opts[j--]; 
 2308: 	  ret->len = q - (unsigned char *)daemon->dhcp_buff3;
 2309: 	  ret->val = (unsigned char *)daemon->dhcp_buff3;
 2310: 	  ret->opt = SUBOPT_PXE_SERVERS;
 2311: 	}
 2312:     }
 2313: 
 2314:   for (o = daemon->dhcp_opts; o; o = o->next)
 2315:     if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
 2316:       break;
 2317:   
 2318:   if (!o)
 2319:     {
 2320:       ret = &fake_opts[j--]; 
 2321:       ret->len = sizeof(fake_prompt);
 2322:       ret->val = fake_prompt;
 2323:       ret->opt = SUBOPT_PXE_MENU_PROMPT;
 2324:     }
 2325:   
 2326:   ret = &fake_opts[j--]; 
 2327:   ret->len = 1;
 2328:   ret->opt = SUBOPT_PXE_DISCOVERY;
 2329:   ret->val= &discovery_control;
 2330:  
 2331:   return ret;
 2332: }
 2333:   
 2334: static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
 2335: {
 2336:   memset(mess->sname, 0, sizeof(mess->sname));
 2337:   memset(mess->file, 0, sizeof(mess->file));
 2338:   memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
 2339:   mess->siaddr.s_addr = 0;
 2340: }
 2341: 
 2342: struct dhcp_boot *find_boot(struct dhcp_netid *netid)
 2343: {
 2344:   struct dhcp_boot *boot;
 2345: 
 2346:   /* decide which dhcp-boot option we're using */
 2347:   for (boot = daemon->boot_config; boot; boot = boot->next)
 2348:     if (match_netid(boot->netid, netid, 0))
 2349:       break;
 2350:   if (!boot)
 2351:     /* No match, look for one without a netid */
 2352:     for (boot = daemon->boot_config; boot; boot = boot->next)
 2353:       if (match_netid(boot->netid, netid, 1))
 2354: 	break;
 2355: 
 2356:   return boot;
 2357: }
 2358: 
 2359: static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor)
 2360: {
 2361:   const unsigned char *opt = NULL;
 2362:   ssize_t conf_len = 0;
 2363:   const struct dhcp_pxe_vendor *conf = daemon->dhcp_pxe_vendors;
 2364:   opt = option_find(mess, sz, OPTION_VENDOR_ID, 0);
 2365:   if (!opt) 
 2366:     return 0;
 2367:   for (; conf; conf = conf->next)
 2368:     {
 2369:       conf_len = strlen(conf->data);
 2370:       if (option_len(opt) < conf_len)
 2371:         continue;
 2372:       if (strncmp(option_ptr(opt, 0), conf->data, conf_len) == 0)
 2373:         {
 2374:           if (pxe_vendor)
 2375:             *pxe_vendor = conf->data;
 2376:           return 1;
 2377:         }
 2378:     }
 2379:   return 0;
 2380: }
 2381: 
 2382: static void do_options(struct dhcp_context *context,
 2383: 		       struct dhcp_packet *mess,
 2384: 		       unsigned char *end, 
 2385: 		       unsigned char *req_options,
 2386: 		       char *hostname, 
 2387: 		       char *domain,
 2388: 		       struct dhcp_netid *netid,
 2389: 		       struct in_addr subnet_addr,
 2390: 		       unsigned char fqdn_flags,
 2391: 		       int null_term, int pxe_arch,
 2392: 		       unsigned char *uuid,
 2393: 		       int vendor_class_len,
 2394: 		       time_t now,
 2395: 		       unsigned int lease_time,
 2396: 		       unsigned short fuzz,
 2397: 		       const char *pxevendor)
 2398: {
 2399:   struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
 2400:   struct dhcp_boot *boot;
 2401:   unsigned char *p;
 2402:   int i, len, force_encap = 0;
 2403:   unsigned char f0 = 0, s0 = 0;
 2404:   int done_file = 0, done_server = 0;
 2405:   int done_vendor_class = 0;
 2406:   struct dhcp_netid *tagif;
 2407:   struct dhcp_netid_list *id_list;
 2408: 
 2409:   /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
 2410:   if (context)
 2411:     context->netid.next = NULL;
 2412:   tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
 2413: 	
 2414:   /* logging */
 2415:   if (option_bool(OPT_LOG_OPTS) && req_options)
 2416:     {
 2417:       char *q = daemon->namebuff;
 2418:       for (i = 0; req_options[i] != OPTION_END; i++)
 2419: 	{
 2420: 	  char *s = option_string(AF_INET, req_options[i], NULL, 0, NULL, 0);
 2421: 	  q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
 2422: 			"%d%s%s%s", 
 2423: 			req_options[i],
 2424: 			strlen(s) != 0 ? ":" : "",
 2425: 			s, 
 2426: 			req_options[i+1] == OPTION_END ? "" : ", ");
 2427: 	  if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
 2428: 	    {
 2429: 	      q = daemon->namebuff;
 2430: 	      my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
 2431: 	    }
 2432: 	}
 2433:     }
 2434:       
 2435:   for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
 2436:     if ((!id_list->list) || match_netid(id_list->list, netid, 0))
 2437:       break;
 2438:   if (id_list)
 2439:     mess->flags |= htons(0x8000); /* force broadcast */
 2440:   
 2441:   if (context)
 2442:     mess->siaddr = context->local;
 2443:   
 2444:   /* See if we can send the boot stuff as options.
 2445:      To do this we need a requested option list, BOOTP
 2446:      and very old DHCP clients won't have this, we also 
 2447:      provide a manual option to disable it.
 2448:      Some PXE ROMs have bugs (surprise!) and need zero-terminated 
 2449:      names, so we always send those.  */
 2450:   if ((boot = find_boot(tagif)))
 2451:     {
 2452:       if (boot->sname)
 2453: 	{	  
 2454: 	  if (!option_bool(OPT_NO_OVERRIDE) &&
 2455: 	      req_options && 
 2456: 	      in_list(req_options, OPTION_SNAME))
 2457: 	    option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
 2458: 	  else
 2459: 	    safe_strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname));
 2460: 	}
 2461:       
 2462:       if (boot->file)
 2463: 	{
 2464: 	  if (!option_bool(OPT_NO_OVERRIDE) &&
 2465: 	      req_options && 
 2466: 	      in_list(req_options, OPTION_FILENAME))
 2467: 	    option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
 2468: 	  else
 2469: 	    safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
 2470: 	}
 2471:       
 2472:       if (boot->next_server.s_addr) 
 2473: 	mess->siaddr = boot->next_server;
 2474:       else if (boot->tftp_sname)
 2475: 	mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
 2476:     }
 2477:   else
 2478:     /* Use the values of the relevant options if no dhcp-boot given and
 2479:        they're not explicitly asked for as options. OPTION_END is used
 2480:        as an internal way to specify siaddr without using dhcp-boot, for use in
 2481:        dhcp-optsfile. */
 2482:     {
 2483:       if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
 2484: 	  (opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
 2485: 	{
 2486: 	  safe_strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file));
 2487: 	  done_file = 1;
 2488: 	}
 2489:       
 2490:       if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
 2491: 	  (opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
 2492: 	{
 2493: 	  safe_strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname));
 2494: 	  done_server = 1;
 2495: 	}
 2496:       
 2497:       if ((opt = option_find2(OPTION_END)))
 2498: 	mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;	
 2499:     }
 2500:         
 2501:   /* We don't want to do option-overload for BOOTP, so make the file and sname
 2502:      fields look like they are in use, even when they aren't. This gets restored
 2503:      at the end of this function. */
 2504: 
 2505:   if (!req_options || option_bool(OPT_NO_OVERRIDE))
 2506:     {
 2507:       f0 = mess->file[0];
 2508:       mess->file[0] = 1;
 2509:       s0 = mess->sname[0];
 2510:       mess->sname[0] = 1;
 2511:     }
 2512:       
 2513:   /* At this point, if mess->sname or mess->file are zeroed, they are available
 2514:      for option overload, reserve space for the overload option. */
 2515:   if (mess->file[0] == 0 || mess->sname[0] == 0)
 2516:     end -= 3;
 2517: 
 2518:   /* rfc3011 says this doesn't need to be in the requested options list. */
 2519:   if (subnet_addr.s_addr)
 2520:     option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
 2521:    
 2522:   if (lease_time != 0xffffffff)
 2523:     { 
 2524:       unsigned int t1val = lease_time/2; 
 2525:       unsigned int t2val = (lease_time*7)/8;
 2526:       unsigned int hval;
 2527:       
 2528:       /* If set by user, sanity check, so not longer than lease. */
 2529:       if ((opt = option_find2(OPTION_T1)))
 2530: 	{
 2531: 	  hval = ntohl(*((unsigned int *)opt->val));
 2532: 	  if (hval < lease_time && hval > 2)
 2533: 	    t1val = hval;
 2534: 	}
 2535: 
 2536:        if ((opt = option_find2(OPTION_T2)))
 2537: 	{
 2538: 	  hval = ntohl(*((unsigned int *)opt->val));
 2539: 	  if (hval < lease_time && hval > 2)
 2540: 	    t2val = hval;
 2541: 	}
 2542:        	  
 2543:        /* ensure T1 is still < T2 */
 2544:        if (t2val <= t1val)
 2545: 	 t1val = t2val - 1; 
 2546: 
 2547:        while (fuzz > (t1val/8))
 2548: 	 fuzz = fuzz/2;
 2549: 	 
 2550:        t1val -= fuzz;
 2551:        t2val -= fuzz;
 2552:        
 2553:        option_put(mess, end, OPTION_T1, 4, t1val);
 2554:        option_put(mess, end, OPTION_T2, 4, t2val);
 2555:     }
 2556: 
 2557:   /* replies to DHCPINFORM may not have a valid context */
 2558:   if (context)
 2559:     {
 2560:       if (!option_find2(OPTION_NETMASK))
 2561: 	option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
 2562:   
 2563:       /* May not have a "guessed" broadcast address if we got no packets via a relay
 2564: 	 from this net yet (ie just unicast renewals after a restart */
 2565:       if (context->broadcast.s_addr &&
 2566: 	  !option_find2(OPTION_BROADCAST))
 2567: 	option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
 2568:       
 2569:       /* Same comments as broadcast apply, and also may not be able to get a sensible
 2570: 	 default when using subnet select.  User must configure by steam in that case. */
 2571:       if (context->router.s_addr &&
 2572: 	  in_list(req_options, OPTION_ROUTER) &&
 2573: 	  !option_find2(OPTION_ROUTER))
 2574: 	option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
 2575:       
 2576:       if (daemon->port == NAMESERVER_PORT &&
 2577: 	  in_list(req_options, OPTION_DNSSERVER) &&
 2578: 	  !option_find2(OPTION_DNSSERVER))
 2579: 	option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
 2580:     }
 2581: 
 2582:   if (domain && in_list(req_options, OPTION_DOMAINNAME) && 
 2583:       !option_find2(OPTION_DOMAINNAME))
 2584:     option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
 2585:  
 2586:   /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
 2587:   if (hostname)
 2588:     {
 2589:       if (in_list(req_options, OPTION_HOSTNAME) &&
 2590: 	  !option_find2(OPTION_HOSTNAME))
 2591: 	option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
 2592:       
 2593:       if (fqdn_flags != 0)
 2594: 	{
 2595: 	  len = strlen(hostname) + 3;
 2596: 	  
 2597: 	  if (fqdn_flags & 0x04)
 2598: 	    len += 2;
 2599: 	  else if (null_term)
 2600: 	    len++;
 2601: 
 2602: 	  if (domain)
 2603: 	    len += strlen(domain) + 1;
 2604: 	  else if (fqdn_flags & 0x04)
 2605: 	    len--;
 2606: 
 2607: 	  if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
 2608: 	    {
 2609: 	      *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */ 
 2610: 	      *(p++) = 255;
 2611: 	      *(p++) = 255;
 2612: 
 2613: 	      if (fqdn_flags & 0x04)
 2614: 		{
 2615: 		  p = do_rfc1035_name(p, hostname, NULL);
 2616: 		  if (domain)
 2617: 		    {
 2618: 		      p = do_rfc1035_name(p, domain, NULL);
 2619: 		      *p++ = 0;
 2620: 		    }
 2621: 		}
 2622: 	      else
 2623: 		{
 2624: 		  memcpy(p, hostname, strlen(hostname));
 2625: 		  p += strlen(hostname);
 2626: 		  if (domain)
 2627: 		    {
 2628: 		      *(p++) = '.';
 2629: 		      memcpy(p, domain, strlen(domain));
 2630: 		      p += strlen(domain);
 2631: 		    }
 2632: 		  if (null_term)
 2633: 		    *(p++) = 0;
 2634: 		}
 2635: 	    }
 2636: 	}
 2637:     }      
 2638: 
 2639:   for (opt = config_opts; opt; opt = opt->next)
 2640:     {
 2641:       int optno = opt->opt;
 2642: 
 2643:       /* netids match and not encapsulated? */
 2644:       if (!(opt->flags & DHOPT_TAGOK))
 2645: 	continue;
 2646:       
 2647:       /* was it asked for, or are we sending it anyway? */
 2648:       if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
 2649: 	continue;
 2650:       
 2651:       /* prohibit some used-internally options. T1 and T2 already handled. */
 2652:       if (optno == OPTION_CLIENT_FQDN ||
 2653: 	  optno == OPTION_MAXMESSAGE ||
 2654: 	  optno == OPTION_OVERLOAD ||
 2655: 	  optno == OPTION_PAD ||
 2656: 	  optno == OPTION_END ||
 2657: 	  optno == OPTION_T1 ||
 2658: 	  optno == OPTION_T2)
 2659: 	continue;
 2660: 
 2661:       if (optno == OPTION_SNAME && done_server)
 2662: 	continue;
 2663: 
 2664:       if (optno == OPTION_FILENAME && done_file)
 2665: 	continue;
 2666:       
 2667:       /* For the options we have default values on
 2668: 	 dhc-option=<optionno> means "don't include this option"
 2669: 	 not "include a zero-length option" */
 2670:       if (opt->len == 0 && 
 2671: 	  (optno == OPTION_NETMASK ||
 2672: 	   optno == OPTION_BROADCAST ||
 2673: 	   optno == OPTION_ROUTER ||
 2674: 	   optno == OPTION_DNSSERVER || 
 2675: 	   optno == OPTION_DOMAINNAME ||
 2676: 	   optno == OPTION_HOSTNAME))
 2677: 	continue;
 2678: 
 2679:       /* vendor-class comes from elsewhere for PXE */
 2680:       if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
 2681: 	continue;
 2682:       
 2683:       /* always force null-term for filename and servername - buggy PXE again. */
 2684:       len = do_opt(opt, NULL, context, 
 2685: 		   (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
 2686: 
 2687:       if ((p = free_space(mess, end, optno, len)))
 2688: 	{
 2689: 	  do_opt(opt, p, context, 
 2690: 		 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
 2691: 	  
 2692: 	  /* If we send a vendor-id, revisit which vendor-ops we consider 
 2693: 	     it appropriate to send. */
 2694: 	  if (optno == OPTION_VENDOR_ID)
 2695: 	    {
 2696: 	      match_vendor_opts(p - 2, config_opts);
 2697: 	      done_vendor_class = 1;
 2698: 	    }
 2699: 	}  
 2700:     }
 2701: 
 2702:   /* Now send options to be encapsulated in arbitrary options, 
 2703:      eg dhcp-option=encap:172,17,.......
 2704:      Also handle vendor-identifying vendor-encapsulated options,
 2705:      dhcp-option = vi-encap:13,17,.......
 2706:      The may be more that one "outer" to do, so group
 2707:      all the options which match each outer in turn. */
 2708:   for (opt = config_opts; opt; opt = opt->next)
 2709:     opt->flags &= ~DHOPT_ENCAP_DONE;
 2710:   
 2711:   for (opt = config_opts; opt; opt = opt->next)
 2712:     {
 2713:       int flags;
 2714:       
 2715:       if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
 2716: 	{
 2717: 	  int found = 0;
 2718: 	  struct dhcp_opt *o;
 2719: 
 2720: 	  if (opt->flags & DHOPT_ENCAP_DONE)
 2721: 	    continue;
 2722: 
 2723: 	  for (len = 0, o = config_opts; o; o = o->next)
 2724: 	    {
 2725: 	      int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
 2726: 
 2727: 	      o->flags &= ~DHOPT_ENCAP_MATCH;
 2728: 	      
 2729: 	      if (!(o->flags & flags) || opt->u.encap != o->u.encap)
 2730: 		continue;
 2731: 	      
 2732: 	      o->flags |= DHOPT_ENCAP_DONE;
 2733: 	      if (match_netid(o->netid, tagif, 1) &&
 2734: 		  ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
 2735: 		{
 2736: 		  o->flags |= DHOPT_ENCAP_MATCH;
 2737: 		  found = 1;
 2738: 		  len += do_opt(o, NULL, NULL, 0) + 2;
 2739: 		}
 2740: 	    } 
 2741: 	  
 2742: 	  if (found)
 2743: 	    { 
 2744: 	      if (flags & DHOPT_ENCAPSULATE)
 2745: 		do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
 2746: 	      else if (len > 250)
 2747: 		my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
 2748: 	      else if ((p = free_space(mess, end,  OPTION_VENDOR_IDENT_OPT, len + 5)))
 2749: 		{
 2750: 		  int swap_ent = htonl(opt->u.encap);
 2751: 		  memcpy(p, &swap_ent, 4);
 2752: 		  p += 4;
 2753: 		  *(p++) = len;
 2754: 		  for (o = config_opts; o; o = o->next)
 2755: 		    if (o->flags & DHOPT_ENCAP_MATCH)
 2756: 		      {
 2757: 			len = do_opt(o, p + 2, NULL, 0);
 2758: 			*(p++) = o->opt;
 2759: 			*(p++) = len;
 2760: 			p += len;
 2761: 		      }     
 2762: 		}
 2763: 	    }
 2764: 	}
 2765:     }      
 2766: 
 2767:   force_encap = prune_vendor_opts(tagif);
 2768:   
 2769:   if (context && pxe_arch != -1)
 2770:     {
 2771:       pxe_misc(mess, end, uuid, pxevendor);
 2772:       if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
 2773: 	config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
 2774:     }
 2775: 
 2776:   if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
 2777:       do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) && 
 2778:       pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
 2779:       (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
 2780:     /* If we send vendor encapsulated options, and haven't already sent option 60,
 2781:        echo back the value we got from the client. */
 2782:     memcpy(p, daemon->dhcp_buff3, vendor_class_len);	    
 2783:    
 2784:    /* restore BOOTP anti-overload hack */
 2785:   if (!req_options || option_bool(OPT_NO_OVERRIDE))
 2786:     {
 2787:       mess->file[0] = f0;
 2788:       mess->sname[0] = s0;
 2789:     }
 2790: }
 2791: 
 2792: static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid)
 2793: {
 2794:   struct delay_config *delay_conf;
 2795:   
 2796:   /* Decide which delay_config option we're using */
 2797:   for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
 2798:     if (match_netid(delay_conf->netid, netid, 0))
 2799:       break;
 2800:   
 2801:   if (!delay_conf)
 2802:     /* No match, look for one without a netid */
 2803:     for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
 2804:       if (match_netid(delay_conf->netid, netid, 1))
 2805:         break;
 2806: 
 2807:   if (delay_conf)
 2808:     {
 2809:       if (!option_bool(OPT_QUIET_DHCP))
 2810: 	my_syslog(MS_DHCP | LOG_INFO, _("%u reply delay: %d"), ntohl(xid), delay_conf->delay);
 2811:       delay_dhcp(recvtime, delay_conf->delay, -1, 0, 0);
 2812:     }
 2813: }
 2814: 
 2815: #endif /* HAVE_DHCP */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>