Diff for /embedaddon/dnsmasq/src/rfc2131.c between versions 1.1 and 1.1.1.2

version 1.1, 2013/07/29 19:37:40 version 1.1.1.2, 2014/06/15 16:31:38
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
Line 34  static void option_put_string(struct dhcp_packet *mess Line 34  static void option_put_string(struct dhcp_packet *mess
 static struct in_addr option_addr(unsigned char *opt);  static struct in_addr option_addr(unsigned char *opt);
 static unsigned int option_uint(unsigned char *opt, int i, int size);  static unsigned int option_uint(unsigned char *opt, int i, int size);
 static void log_packet(char *type, void *addr, unsigned char *ext_mac,   static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
                       int mac_len, char *interface, char *string, u32 xid);                       int mac_len, char *interface, char *string, char *err, u32 xid);
 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);  static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);  static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);  static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
 static void clear_packet(struct dhcp_packet *mess, unsigned char *end);  static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
   static int in_list(unsigned char *list, int opt);
 static void do_options(struct dhcp_context *context,  static void do_options(struct dhcp_context *context,
                        struct dhcp_packet *mess,                         struct dhcp_packet *mess,
                        unsigned char *real_end,                          unsigned char *real_end, 
Line 91  size_t dhcp_reply(struct dhcp_context *context, char * Line 92  size_t dhcp_reply(struct dhcp_context *context, char *
   struct dhcp_netid known_id, iface_id, cpewan_id;    struct dhcp_netid known_id, iface_id, cpewan_id;
   struct dhcp_opt *o;    struct dhcp_opt *o;
   unsigned char pxe_uuid[17];    unsigned char pxe_uuid[17];
  unsigned char *oui = NULL, *serial = NULL, *class = NULL;  unsigned char *oui = NULL, *serial = NULL;
 #ifdef HAVE_SCRIPT
   unsigned char *class = NULL;
 #endif
   
   subnet_addr.s_addr = override.s_addr = 0;    subnet_addr.s_addr = override.s_addr = 0;
   
Line 155  size_t dhcp_reply(struct dhcp_context *context, char * Line 159  size_t dhcp_reply(struct dhcp_context *context, char *
                   unsigned char *y = option_ptr(opt, offset + elen + 5);                    unsigned char *y = option_ptr(opt, offset + elen + 5);
                   oui = option_find1(x, y, 1, 1);                    oui = option_find1(x, y, 1, 1);
                   serial = option_find1(x, y, 2, 1);                    serial = option_find1(x, y, 2, 1);
                  class = option_find1(x, y, 3, 1);#ifdef HAVE_SCRIPT
                                    class = option_find1(x, y, 3, 1);               
 #endif
                   /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing                     /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing 
                      the gateway id back. Note that the device class is optional */                       the gateway id back. Note that the device class is optional */
                   if (oui && serial)                    if (oui && serial)
Line 354  size_t dhcp_reply(struct dhcp_context *context, char * Line 359  size_t dhcp_reply(struct dhcp_context *context, char *
                       ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));                        ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
         }          }
     }      }
     
     /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
        Otherwise assume the option is an array, and look for a matching element. 
        If no data given, existance of the option is enough. This code handles 
        rfc3925 V-I classes too. */
     for (o = daemon->dhcp_match; o; o = o->next)
       {
         unsigned int len, elen, match = 0;
         size_t offset, o2;
   
         if (o->flags & DHOPT_RFC3925)
           {
             if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
               continue;
             
             for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
               {
                 len = option_uint(opt, offset + 4 , 1);
                 /* Need to take care that bad data can't run us off the end of the packet */
                 if ((offset + len + 5 <= (option_len(opt))) &&
                     (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
                   for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
                     { 
                       elen = option_uint(opt, o2, 1);
                       if ((o2 + elen + 1 <= option_len(opt)) &&
                           (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
                         break;
                     }
                 if (match) 
                   break;
               }     
           }
         else
           {
             if (!(opt = option_find(mess, sz, o->opt, 1)))
               continue;
             
             match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
           } 
   
         if (match)
           {
             o->netid->next = netid;
             netid = o->netid;
           }
       }
           
     /* user-class options are, according to RFC3004, supposed to contain
        a set of counted strings. Here we check that this is so (by seeing
        if the counts are consistent with the overall option length) and if
        so zero the counts so that we don't get spurious matches between 
        the vendor string and the counts. If the lengths don't add up, we
        assume that the option is a single string and non RFC3004 compliant 
        and just do the substring match. dhclient provides these broken options.
        The code, later, which sends user-class data to the lease-change script
        relies on the transformation done here.
     */
   
     if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
       {
         unsigned char *ucp = option_ptr(opt, 0);
         int tmp, j;
         for (j = 0; j < option_len(opt); j += ucp[j] + 1);
         if (j == option_len(opt))
           for (j = 0; j < option_len(opt); j = tmp)
             {
               tmp = j + ucp[j] + 1;
               ucp[j] = 0;
             }
       }
       
     for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
       {
         int mopt;
         
         if (vendor->match_type == MATCH_VENDOR)
           mopt = OPTION_VENDOR_ID;
         else if (vendor->match_type == MATCH_USER)
           mopt = OPTION_USER_CLASS; 
         else
           continue;
   
         if ((opt = option_find(mess, sz, mopt, 1)))
           {
             int i;
             for (i = 0; i <= (option_len(opt) - vendor->len); i++)
               if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
                 {
                   vendor->netid.next = netid;
                   netid = &vendor->netid;
                   break;
                 }
           }
       }
   
     /* mark vendor-encapsulated options which match the client-supplied vendor class,
        save client-supplied vendor class */
     if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
       {
         memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
         vendor_class_len = option_len(opt);
       }
     match_vendor_opts(opt, daemon->dhcp_opts);
     
     if (option_bool(OPT_LOG_OPTS))
       {
         if (sanitise(opt, daemon->namebuff))
           my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
         if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
           my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
       }
   
   mess->op = BOOTREPLY;    mess->op = BOOTREPLY;
       
   config = find_config(daemon->dhcp_conf, context, clid, clid_len,     config = find_config(daemon->dhcp_conf, context, clid, clid_len, 
Line 493  size_t dhcp_reply(struct dhcp_context *context, char * Line 609  size_t dhcp_reply(struct dhcp_context *context, char *
               lease_set_interface(lease, int_index, now);                lease_set_interface(lease, int_index, now);
                               
               clear_packet(mess, end);                clear_packet(mess, end);
               match_vendor_opts(NULL, daemon->dhcp_opts); /* clear flags */  
               do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),                 do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), 
                         netid, subnet_addr, 0, 0, -1, NULL, 0, now);                         netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
             }              }
         }          }
               
      log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);      log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
               
       return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);        return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
     }      }
               
  if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))  if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 3)))
     {      {
       /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */        /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
       int len = option_len(opt);        int len = option_len(opt);
Line 534  size_t dhcp_reply(struct dhcp_context *context, char * Line 649  size_t dhcp_reply(struct dhcp_context *context, char *
         }          }
               
       if (fqdn_flags & 0x04)        if (fqdn_flags & 0x04)
        while (*op != 0 && ((op + (*op) + 1) - pp) < len)        while (*op != 0 && ((op + (*op)) - pp) < len)
           {            {
             memcpy(pq, op+1, *op);              memcpy(pq, op+1, *op);
             pq += *op;              pq += *op;
Line 622  size_t dhcp_reply(struct dhcp_context *context, char * Line 737  size_t dhcp_reply(struct dhcp_context *context, char *
         }          }
     }      }
       
   /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.  
      Otherwise assume the option is an array, and look for a matching element.   
      If no data given, existance of the option is enough. This code handles   
      rfc3925 V-I classes too. */  
   for (o = daemon->dhcp_match; o; o = o->next)  
     {  
       unsigned int len, elen, match = 0;  
       size_t offset, o2;  
   
       if (o->flags & DHOPT_RFC3925)  
         {  
           if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))  
             continue;  
             
           for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)  
             {  
               len = option_uint(opt, offset + 4 , 1);  
               /* Need to take care that bad data can't run us off the end of the packet */  
               if ((offset + len + 5 <= (option_len(opt))) &&  
                   (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))  
                 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)  
                   {   
                     elen = option_uint(opt, o2, 1);  
                     if ((o2 + elen + 1 <= option_len(opt)) &&  
                         (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))  
                       break;  
                   }  
               if (match)   
                 break;  
             }       
         }  
       else  
         {  
           if (!(opt = option_find(mess, sz, o->opt, 1)))  
             continue;  
             
           match = match_bytes(o, option_ptr(opt, 0), option_len(opt));  
         }   
   
       if (match)  
         {  
           o->netid->next = netid;  
           netid = o->netid;  
         }  
     }  
           
   /* user-class options are, according to RFC3004, supposed to contain  
      a set of counted strings. Here we check that this is so (by seeing  
      if the counts are consistent with the overall option length) and if  
      so zero the counts so that we don't get spurious matches between   
      the vendor string and the counts. If the lengths don't add up, we  
      assume that the option is a single string and non RFC3004 compliant   
      and just do the substring match. dhclient provides these broken options.  
      The code, later, which sends user-class data to the lease-change script  
      relies on the transformation done here.  
   */  
   
   if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))  
     {  
       unsigned char *ucp = option_ptr(opt, 0);  
       int tmp, j;  
       for (j = 0; j < option_len(opt); j += ucp[j] + 1);  
       if (j == option_len(opt))  
         for (j = 0; j < option_len(opt); j = tmp)  
           {  
             tmp = j + ucp[j] + 1;  
             ucp[j] = 0;  
           }  
     }  
       
   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)  
     {  
       int mopt;  
         
       if (vendor->match_type == MATCH_VENDOR)  
         mopt = OPTION_VENDOR_ID;  
       else if (vendor->match_type == MATCH_USER)  
         mopt = OPTION_USER_CLASS;   
       else  
         continue;  
   
       if ((opt = option_find(mess, sz, mopt, 1)))  
         {  
           int i;  
           for (i = 0; i <= (option_len(opt) - vendor->len); i++)  
             if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)  
               {  
                 vendor->netid.next = netid;  
                 netid = &vendor->netid;  
                 break;  
               }  
         }  
     }  
   
   /* mark vendor-encapsulated options which match the client-supplied vendor class,  
      save client-supplied vendor class */  
   if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))  
     {  
       memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));  
       vendor_class_len = option_len(opt);  
     }  
   match_vendor_opts(opt, daemon->dhcp_opts);  
     
   if (option_bool(OPT_LOG_OPTS))  
     {  
       if (sanitise(opt, daemon->namebuff))  
         my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);  
       if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))  
         my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);  
     }  
   
   tagif_netid = run_tag_if(netid);    tagif_netid = run_tag_if(netid);
  
   /* if all the netids in the ignore list are present, ignore this client */    /* if all the netids in the ignore list are present, ignore this client */
   for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)    for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
     if (match_netid(id_list->list, tagif_netid, 0))      if (match_netid(id_list->list, tagif_netid, 0))
Line 827  size_t dhcp_reply(struct dhcp_context *context, char * Line 831  size_t dhcp_reply(struct dhcp_context *context, char *
           opt71.next = daemon->dhcp_opts;            opt71.next = daemon->dhcp_opts;
           do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);            do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
                       
          log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);          log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
           log_tags(tagif_netid, ntohl(mess->xid));            log_tags(tagif_netid, ntohl(mess->xid));
           return dhcp_packet_size(mess, agent_id, real_end);                  return dhcp_packet_size(mess, agent_id, real_end);      
         }          }
Line 848  size_t dhcp_reply(struct dhcp_context *context, char * Line 852  size_t dhcp_reply(struct dhcp_context *context, char *
                               
               if (tmp)                if (tmp)
                 {                  {
                  struct dhcp_boot *boot = find_boot(tagif_netid);                  struct dhcp_boot *boot;
                                  
                   if (tmp->netid.net)
                     {
                       tmp->netid.next = netid;
                       tagif_netid = run_tag_if(&tmp->netid);
                     }
                   
                   boot = find_boot(tagif_netid);
                   
                   mess->yiaddr.s_addr = 0;                    mess->yiaddr.s_addr = 0;
                   if  (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)                    if  (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
                     {                      {
Line 879  size_t dhcp_reply(struct dhcp_context *context, char * Line 891  size_t dhcp_reply(struct dhcp_context *context, char *
                   prune_vendor_opts(tagif_netid);                    prune_vendor_opts(tagif_netid);
                   do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);                    do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
                                       
                  log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid);                  log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
                   log_tags(tagif_netid, ntohl(mess->xid));                    log_tags(tagif_netid, ntohl(mess->xid));
                   return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);                             return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);         
                 }                  }
Line 911  size_t dhcp_reply(struct dhcp_context *context, char * Line 923  size_t dhcp_reply(struct dhcp_context *context, char *
       if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))        if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
         return 0;          return 0;
               
      log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid);      log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
               
       if (lease && lease->addr.s_addr == option_addr(opt).s_addr)        if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
         lease_prune(lease, now);          lease_prune(lease, now);
Line 943  size_t dhcp_reply(struct dhcp_context *context, char * Line 955  size_t dhcp_reply(struct dhcp_context *context, char *
       else        else
         message = _("unknown lease");          message = _("unknown lease");
   
      log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);      log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
                   
       return 0;        return 0;
               
     case DHCPDISCOVER:      case DHCPDISCOVER:
       if (ignore || have_config(config, CONFIG_DISABLE))        if (ignore || have_config(config, CONFIG_DISABLE))
         {          {
             if (option_bool(OPT_QUIET_DHCP))
               return 0;
           message = _("ignored");            message = _("ignored");
           opt = NULL;            opt = NULL;
         }          }
Line 1007  size_t dhcp_reply(struct dhcp_context *context, char * Line 1021  size_t dhcp_reply(struct dhcp_context *context, char *
             message = _("no address available");                    message = _("no address available");      
         }          }
               
      log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid);       log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid); 
   
       if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))        if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
         return 0;          return 0;
Line 1020  size_t dhcp_reply(struct dhcp_context *context, char * Line 1034  size_t dhcp_reply(struct dhcp_context *context, char *
   
       log_tags(tagif_netid, ntohl(mess->xid));        log_tags(tagif_netid, ntohl(mess->xid));
               
      log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);      log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
               
       time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));        time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
       clear_packet(mess, end);        clear_packet(mess, end);
Line 1072  size_t dhcp_reply(struct dhcp_context *context, char * Line 1086  size_t dhcp_reply(struct dhcp_context *context, char *
                          Have to set override to make sure we echo back the correct server-id */                           Have to set override to make sure we echo back the correct server-id */
                       struct irec *intr;                        struct irec *intr;
                                               
                      enumerate_interfaces();                      enumerate_interfaces(0);
   
                       for (intr = daemon->interfaces; intr; intr = intr->next)                        for (intr = daemon->interfaces; intr; intr = intr->next)
                         if (intr->addr.sa.sa_family == AF_INET &&                          if (intr->addr.sa.sa_family == AF_INET &&
Line 1136  size_t dhcp_reply(struct dhcp_context *context, char * Line 1150  size_t dhcp_reply(struct dhcp_context *context, char *
           mess->yiaddr = mess->ciaddr;            mess->yiaddr = mess->ciaddr;
         }          }
               
      log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);      log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
     
       if (!message)        if (!message)
         {          {
Line 1208  size_t dhcp_reply(struct dhcp_context *context, char * Line 1222  size_t dhcp_reply(struct dhcp_context *context, char *
   
       if (message)        if (message)
         {          {
          log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid);          log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
                       
           mess->yiaddr.s_addr = 0;            mess->yiaddr.s_addr = 0;
           clear_packet(mess, end);            clear_packet(mess, end);
Line 1347  size_t dhcp_reply(struct dhcp_context *context, char * Line 1361  size_t dhcp_reply(struct dhcp_context *context, char *
           else            else
             override = lease->override;              override = lease->override;
   
          log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid);            log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);  
                       
           clear_packet(mess, end);            clear_packet(mess, end);
           option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);            option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
Line 1370  size_t dhcp_reply(struct dhcp_context *context, char * Line 1384  size_t dhcp_reply(struct dhcp_context *context, char *
       if (ignore || have_config(config, CONFIG_DISABLE))        if (ignore || have_config(config, CONFIG_DISABLE))
         message = _("ignored");          message = _("ignored");
               
      log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);      log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
             
       if (message || mess->ciaddr.s_addr == 0)        if (message || mess->ciaddr.s_addr == 0)
         return 0;          return 0;
Line 1385  size_t dhcp_reply(struct dhcp_context *context, char * Line 1399  size_t dhcp_reply(struct dhcp_context *context, char *
           lease->hostname)            lease->hostname)
         hostname = lease->hostname;          hostname = lease->hostname;
               
      if (!hostname && (hostname = host_from_dns(mess->ciaddr)))      if (!hostname)
        domain = get_domain(mess->ciaddr);        hostname = host_from_dns(mess->ciaddr);
               
       if (context && context->netid.net)        if (context && context->netid.net)
         {          {
Line 1396  size_t dhcp_reply(struct dhcp_context *context, char * Line 1410  size_t dhcp_reply(struct dhcp_context *context, char *
   
       log_tags(tagif_netid, ntohl(mess->xid));        log_tags(tagif_netid, ntohl(mess->xid));
               
      log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);      log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
               
       if (lease)        if (lease)
         {          {
Line 1410  size_t dhcp_reply(struct dhcp_context *context, char * Line 1424  size_t dhcp_reply(struct dhcp_context *context, char *
       clear_packet(mess, end);        clear_packet(mess, end);
       option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);        option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
       option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));        option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
           
       /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but 
          we supply a utility which makes DHCPINFORM requests to get this information.
          Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
          which won't be true for ordinary clients, but will be true for the 
          dhcp_lease_time utility. */
       if (lease && in_list(req_options, OPTION_LEASE_TIME))
         {
           if (lease->expires == 0)
             time = 0xffffffff;
           else
             time = (unsigned int)difftime(lease->expires, now);
           option_put(mess, end, OPTION_LEASE_TIME, 4, time);
         }
 
       do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),        do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
                  netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);                   netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
               
Line 1516  static void add_extradata_opt(struct dhcp_lease *lease Line 1544  static void add_extradata_opt(struct dhcp_lease *lease
 #endif  #endif
   
 static void log_packet(char *type, void *addr, unsigned char *ext_mac,   static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
                       int mac_len, char *interface, char *string, u32 xid)                       int mac_len, char *interface, char *string, char *err, u32 xid)
 {  {
   struct in_addr a;    struct in_addr a;
     
     if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
       return;
     
   /* addr may be misaligned */    /* addr may be misaligned */
   if (addr)    if (addr)
     memcpy(&a, addr, sizeof(a));      memcpy(&a, addr, sizeof(a));
Line 1527  static void log_packet(char *type, void *addr, unsigne Line 1558  static void log_packet(char *type, void *addr, unsigne
   print_mac(daemon->namebuff, ext_mac, mac_len);    print_mac(daemon->namebuff, ext_mac, mac_len);
       
   if(option_bool(OPT_LOG_OPTS))    if(option_bool(OPT_LOG_OPTS))
     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s",     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
                ntohl(xid),                  ntohl(xid), 
                type,                 type,
                interface,                  interface, 
                addr ? inet_ntoa(a) : "",                 addr ? inet_ntoa(a) : "",
                addr ? " " : "",                 addr ? " " : "",
                daemon->namebuff,                 daemon->namebuff,
               string ? string : "");               string ? string : "",
                err ? err : "");
   else    else
    my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s",    my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
               type,                type,
               interface,                 interface, 
               addr ? inet_ntoa(a) : "",                addr ? inet_ntoa(a) : "",
               addr ? " " : "",                addr ? " " : "",
               daemon->namebuff,                daemon->namebuff,
              string ? string : "");              string ? string : "",
               err ? err : "");
 }  }
   
 static void log_options(unsigned char *start, u32 xid)  static void log_options(unsigned char *start, u32 xid)
Line 1819  static int do_opt(struct dhcp_opt *opt, unsigned char  Line 1852  static int do_opt(struct dhcp_opt *opt, unsigned char 
             }              }
         }          }
       else        else
        memcpy(p, opt->val, len);        /* empty string may be extended to "\0" by null_term */
         memcpy(p, opt->val ? opt->val : (unsigned char *)"", len);
     }        }  
   return len;    return len;
 }  }
Line 2275  static void do_options(struct dhcp_context *context, Line 2309  static void do_options(struct dhcp_context *context,
   
           if (domain)            if (domain)
             len += strlen(domain) + 1;              len += strlen(domain) + 1;
                    else if (fqdn_flags & 0x04)
             len--;
 
           if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))            if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
             {              {
               *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */                 *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */ 
Line 2286  static void do_options(struct dhcp_context *context, Line 2322  static void do_options(struct dhcp_context *context,
                 {                  {
                   p = do_rfc1035_name(p, hostname);                    p = do_rfc1035_name(p, hostname);
                   if (domain)                    if (domain)
                    p = do_rfc1035_name(p, domain);                    {
                  *p++ = 0;                      p = do_rfc1035_name(p, domain);
                       *p++ = 0;
                     }
                 }                  }
               else                else
                 {                  {

Removed from v.1.1  
changed lines
  Added in v.1.1.1.2


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