File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / rfc2131.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (10 years, 11 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_66p0, v2_66, HEAD
dnsmasq

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

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