File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / rfc2131.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:56:46 2021 UTC (3 years, 3 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_84, HEAD
dnsmasq 2.84

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

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