Diff for /embedaddon/dnsmasq/src/helper.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2013/07/29 19:37:40 version 1.1.1.3, 2016/11/02 09:57:01
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley/* dnsmasq is Copyright (c) 2000-2016 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 61  struct script_data Line 61  struct script_data
 #else  #else
   time_t expires;    time_t expires;
 #endif  #endif
   #ifdef HAVE_TFTP
     off_t file_len;
   #endif
   #ifdef HAVE_IPV6
     struct in6_addr addr6;
   #endif
   #ifdef HAVE_DHCP6
     int iaid, vendorclass_count;
   #endif
   unsigned char hwaddr[DHCP_CHADDR_MAX];    unsigned char hwaddr[DHCP_CHADDR_MAX];
   char interface[IF_NAMESIZE];    char interface[IF_NAMESIZE];
   
 };  };
   
 static struct script_data *buf = NULL;  static struct script_data *buf = NULL;
Line 211  int create_helper(int event_fd, int err_fd, uid_t uid, Line 219  int create_helper(int event_fd, int err_fd, uid_t uid,
           action_str = "tftp";            action_str = "tftp";
           is6 = (data.flags != AF_INET);            is6 = (data.flags != AF_INET);
         }          }
      else      else if (data.action == ACTION_ARP)
         {
           action_str = "arp-add";
           is6 = (data.flags != AF_INET);
         }
        else if (data.action == ACTION_ARP_DEL)
         {
           action_str = "arp-del";
           is6 = (data.flags != AF_INET);
           data.action = ACTION_ARP;
         }
        else 
         continue;          continue;
   
                   
      if (!is6)      /* stringify MAC into dhcp_buff */
       p = daemon->dhcp_buff;
       if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0) 
         p += sprintf(p, "%.2x-", data.hwaddr_type);
       for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++)
         {          {
          /* stringify MAC into dhcp_buff */          p += sprintf(p, "%.2x", data.hwaddr[i]);
          p = daemon->dhcp_buff;          if (i != data.hwaddr_len - 1)
          if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0)             p += sprintf(p, ":");
            p += sprintf(p, "%.2x-", data.hwaddr_type); 
          for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++) 
            { 
              p += sprintf(p, "%.2x", data.hwaddr[i]); 
              if (i != data.hwaddr_len - 1) 
                p += sprintf(p, ":"); 
            } 
         }          }
             
       /* supplied data may just exceed normal buffer (unlikely) */        /* supplied data may just exceed normal buffer (unlikely) */
       if ((data.hostname_len + data.ed_len + data.clid_len) > MAXDNAME &&         if ((data.hostname_len + data.ed_len + data.clid_len) > MAXDNAME && 
           !(alloc_buff = buf = malloc(data.hostname_len + data.ed_len + data.clid_len)))            !(alloc_buff = buf = malloc(data.hostname_len + data.ed_len + data.clid_len)))
Line 239  int create_helper(int event_fd, int err_fd, uid_t uid, Line 255  int create_helper(int event_fd, int err_fd, uid_t uid,
         continue;          continue;
   
       /* CLID into packet */        /* CLID into packet */
      if (!is6)      for (p = daemon->packet, i = 0; i < data.clid_len; i++)
        for (p = daemon->packet, i = 0; i < data.clid_len; i++)        {
          {          p += sprintf(p, "%.2x", buf[i]);
            p += sprintf(p, "%.2x", buf[i]);          if (i != data.clid_len - 1) 
            if (i != data.clid_len - 1)  
               p += sprintf(p, ":");                p += sprintf(p, ":");
          }        }
 
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
      else      if (is6)
         {          {
           /* or IAID and server DUID for IPv6 */            /* or IAID and server DUID for IPv6 */
          sprintf(daemon->dhcp_buff3, "%s%u", data.flags & LEASE_TA ? "T" : "", data.hwaddr_type);                sprintf(daemon->dhcp_buff3, "%s%u", data.flags & LEASE_TA ? "T" : "", data.iaid);      
          for (p = daemon->packet, i = 0; i < daemon->duid_len; i++)          for (p = daemon->dhcp_packet.iov_base, i = 0; i < daemon->duid_len; i++)
             {              {
               p += sprintf(p, "%.2x", daemon->duid[i]);                p += sprintf(p, "%.2x", daemon->duid[i]);
               if (i != daemon->duid_len - 1)                 if (i != daemon->duid_len - 1) 
                 p += sprintf(p, ":");                  p += sprintf(p, ":");
             }              }
   
           /* duid not MAC for IPv6 */  
           for (p = daemon->dhcp_buff, i = 0; i < data.clid_len; i++)  
             {  
               p += sprintf(p, "%.2x", buf[i]);  
               if (i != data.clid_len - 1)   
                 p += sprintf(p, ":");  
             }   
         }          }
 #endif  #endif
   
Line 291  int create_helper(int event_fd, int err_fd, uid_t uid, Line 300  int create_helper(int event_fd, int err_fd, uid_t uid,
           
       if (!is6)        if (!is6)
         inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);          inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);
#ifdef HAVE_DHCP6#ifdef HAVE_IPV6
       else        else
        inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN);        inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
 #endif  #endif
   
   #ifdef HAVE_TFTP
       /* file length */        /* file length */
       if (data.action == ACTION_TFTP)        if (data.action == ACTION_TFTP)
        sprintf(daemon->dhcp_buff, "%u", data.hwaddr_len);        sprintf(is6 ? daemon->packet : daemon->dhcp_buff, "%lu", (unsigned long)data.file_len);
      #endif
 
 #ifdef HAVE_LUASCRIPT  #ifdef HAVE_LUASCRIPT
       if (daemon->luascript)        if (daemon->luascript)
         {          {
Line 316  int create_helper(int event_fd, int err_fd, uid_t uid, Line 327  int create_helper(int event_fd, int err_fd, uid_t uid,
                   lua_setfield(lua, -2, "destination_address");                    lua_setfield(lua, -2, "destination_address");
                   lua_pushstring(lua, hostname);                    lua_pushstring(lua, hostname);
                   lua_setfield(lua, -2, "file_name");                     lua_setfield(lua, -2, "file_name"); 
                  lua_pushstring(lua, daemon->dhcp_buff);                  lua_pushstring(lua, is6 ? daemon->packet : daemon->dhcp_buff);
                   lua_setfield(lua, -2, "file_size");                    lua_setfield(lua, -2, "file_size");
                   lua_call(lua, 2, 0);  /* pass 2 values, expect 0 */                    lua_call(lua, 2, 0);  /* pass 2 values, expect 0 */
                 }                  }
             }              }
             else if (data.action == ACTION_ARP)
               {
                 lua_getglobal(lua, "arp"); 
                 if (lua_type(lua, -1) != LUA_TFUNCTION)
                   lua_pop(lua, 1); /* arp function optional */
                 else
                   {
                     lua_pushstring(lua, action_str); /* arg1 - action */
                     lua_newtable(lua);               /* arg2 - data table */
                     lua_pushstring(lua, daemon->addrbuff);
                     lua_setfield(lua, -2, "client_address");
                     lua_pushstring(lua, daemon->dhcp_buff);
                     lua_setfield(lua, -2, "mac_address");
                     lua_call(lua, 2, 0);  /* pass 2 values, expect 0 */
                   }
               }
           else            else
             {              {
               lua_getglobal(lua, "lease");     /* function to call */                lua_getglobal(lua, "lease");     /* function to call */
Line 329  int create_helper(int event_fd, int err_fd, uid_t uid, Line 356  int create_helper(int event_fd, int err_fd, uid_t uid,
                               
               if (is6)                if (is6)
                 {                  {
                   lua_pushstring(lua, daemon->dhcp_buff);  
                   lua_setfield(lua, -2, "client_duid");  
                   lua_pushstring(lua, daemon->packet);                    lua_pushstring(lua, daemon->packet);
                     lua_setfield(lua, -2, "client_duid");
                     lua_pushstring(lua, daemon->dhcp_packet.iov_base);
                   lua_setfield(lua, -2, "server_duid");                    lua_setfield(lua, -2, "server_duid");
                   lua_pushstring(lua, daemon->dhcp_buff3);                    lua_pushstring(lua, daemon->dhcp_buff3);
                   lua_setfield(lua, -2, "iaid");                    lua_setfield(lua, -2, "iaid");
Line 375  int create_helper(int event_fd, int err_fd, uid_t uid, Line 402  int create_helper(int event_fd, int err_fd, uid_t uid,
               if (!is6)                if (!is6)
                 buf = grab_extradata_lua(buf, end, "vendor_class");                  buf = grab_extradata_lua(buf, end, "vendor_class");
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
              else              else  if (data.vendorclass_count != 0)
                for (i = 0; i < data.hwaddr_len; i++)                {
                  {                  sprintf(daemon->dhcp_buff2, "vendor_class_id");
                    sprintf(daemon->dhcp_buff2, "vendor_class%i", i);                  buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
                    buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);                  for (i = 0; i < data.vendorclass_count - 1; i++)
                  }                    {
                       sprintf(daemon->dhcp_buff2, "vendor_class%i", i);
                       buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
                     }
                 }
 #endif  #endif
                               
               buf = grab_extradata_lua(buf, end, "supplied_hostname");                buf = grab_extradata_lua(buf, end, "supplied_hostname");
Line 423  int create_helper(int event_fd, int err_fd, uid_t uid, Line 454  int create_helper(int event_fd, int err_fd, uid_t uid,
                   lua_setfield(lua, -2, "old_hostname");                    lua_setfield(lua, -2, "old_hostname");
                 }                  }
                               
              if (!is6)              if (!is6 || data.hwaddr_len != 0)
                 {                  {
                   lua_pushstring(lua, daemon->dhcp_buff);                    lua_pushstring(lua, daemon->dhcp_buff);
                   lua_setfield(lua, -2, "mac_address");                    lua_setfield(lua, -2, "mac_address");
Line 474  int create_helper(int event_fd, int err_fd, uid_t uid, Line 505  int create_helper(int event_fd, int err_fd, uid_t uid,
           continue;            continue;
         }          }
               
      if (data.action != ACTION_TFTP)      if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
         {          {
          if (is6)#ifdef HAVE_DHCP6
            {          my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
              my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err);          my_setenv("DNSMASQ_SERVER_DUID", is6 ? daemon->dhcp_packet.iov_base : NULL, &err); 
              my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err);          my_setenv("DNSMASQ_MAC", is6 && data.hwaddr_len != 0 ? daemon->dhcp_buff : NULL, &err);
            }#endif
                       
          if (!is6 && data.clid_len != 0)          my_setenv("DNSMASQ_CLIENT_ID", !is6 && data.clid_len != 0 ? daemon->packet : NULL, &err);
            my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err);          my_setenv("DNSMASQ_INTERFACE", strlen(data.interface) != 0 ? data.interface : NULL, &err);
                       
           if (strlen(data.interface) != 0)  
             my_setenv("DNSMASQ_INTERFACE", data.interface, &err);  
             
 #ifdef HAVE_BROKEN_RTC  #ifdef HAVE_BROKEN_RTC
           sprintf(daemon->dhcp_buff2, "%u", data.length);            sprintf(daemon->dhcp_buff2, "%u", data.length);
           my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err);            my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err);
Line 496  int create_helper(int event_fd, int err_fd, uid_t uid, Line 524  int create_helper(int event_fd, int err_fd, uid_t uid,
           my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err);             my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); 
 #endif  #endif
                       
          if (domain)          my_setenv("DNSMASQ_DOMAIN", domain, &err);
            my_setenv("DNSMASQ_DOMAIN", domain, &err); 
                       
           end = extradata + data.ed_len;            end = extradata + data.ed_len;
           buf = extradata;            buf = extradata;
Line 507  int create_helper(int event_fd, int err_fd, uid_t uid, Line 534  int create_helper(int event_fd, int err_fd, uid_t uid,
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
           else            else
             {              {
              if (data.hwaddr_len != 0)              if (data.vendorclass_count != 0)
                 {                  {
                   buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err);                    buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err);
                  for (i = 0; i < data.hwaddr_len - 1; i++)                  for (i = 0; i < data.vendorclass_count - 1; i++)
                     {                      {
                       sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i);                        sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i);
                       buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);                        buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
Line 535  int create_helper(int event_fd, int err_fd, uid_t uid, Line 562  int create_helper(int event_fd, int err_fd, uid_t uid,
   
           if (is6)            if (is6)
             buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);              buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
          else if (data.giaddr.s_addr != 0)          else 
            my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);             my_setenv("DNSMASQ_RELAY_ADDRESS", data.giaddr.s_addr != 0 ? inet_ntoa(data.giaddr) : NULL, &err); 
                       
           for (i = 0; buf; i++)            for (i = 0; buf; i++)
             {              {
Line 544  int create_helper(int event_fd, int err_fd, uid_t uid, Line 571  int create_helper(int event_fd, int err_fd, uid_t uid,
               buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);                buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
             }              }
                       
          if (data.action != ACTION_DEL && data.remaining_time != 0)          sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
            {          my_setenv("DNSMASQ_TIME_REMAINING", data.action != ACTION_DEL && data.remaining_time != 0 ? daemon->dhcp_buff2 : NULL, &err);
              sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); 
              my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); 
            } 
                       
          if (data.action == ACTION_OLD_HOSTNAME && hostname)          my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err);
            {          if (data.action == ACTION_OLD_HOSTNAME)
              my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);            hostname = NULL;
              hostname = NULL;          
            }          my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
        }    }
 
      if (option_bool(OPT_LOG_OPTS)) 
        my_setenv("DNSMASQ_LOG_DHCP", "1", &err); 
          
       /* we need to have the event_fd around if exec fails */        /* we need to have the event_fd around if exec fails */
       if ((i = fcntl(event_fd, F_GETFD)) != -1)        if ((i = fcntl(event_fd, F_GETFD)) != -1)
         fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);          fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
Line 569  int create_helper(int event_fd, int err_fd, uid_t uid, Line 589  int create_helper(int event_fd, int err_fd, uid_t uid,
       if (err == 0)        if (err == 0)
         {          {
           execl(daemon->lease_change_command,             execl(daemon->lease_change_command, 
                p ? p+1 : daemon->lease_change_command,                p ? p+1 : daemon->lease_change_command, action_str, 
                action_str, daemon->dhcp_buff, daemon->addrbuff, hostname, (char*)NULL);                (is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff, 
                 daemon->addrbuff, hostname, (char*)NULL);
           err = errno;            err = errno;
         }          }
       /* failed, send event so the main process logs the problem */        /* failed, send event so the main process logs the problem */
Line 581  int create_helper(int event_fd, int err_fd, uid_t uid, Line 602  int create_helper(int event_fd, int err_fd, uid_t uid,
   
 static void my_setenv(const char *name, const char *value, int *error)  static void my_setenv(const char *name, const char *value, int *error)
 {  {
  if (*error == 0 && setenv(name, value, 1) != 0)  if (*error == 0)
    *error = errno;    {
       if (!value)
         unsetenv(name);
       else if (setenv(name, value, 1) != 0)
         *error = errno;
     }
 }  }
     
 static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end,  char *env, int *err)  static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end,  char *env, int *err)
 {  {
  unsigned char *next;  unsigned char *next = NULL;
   char *val = NULL;
   
  if (!buf || (buf == end))  if (buf && (buf != end))
    return NULL; 
 
  for (next = buf; *next != 0; next++) 
    if (next == end) 
      return NULL; 
   
  if (next != buf) 
     {      {
      char *p;      for (next = buf; ; next++)
      /* No "=" in value */        if (next == end)
      if ((p = strchr((char *)buf, '=')))          {
        *p = 0;            next = NULL;
      my_setenv(env, (char *)buf, err);            break;
    }          }
         else if (*next == 0)
           break;
   
  return next + 1;      if (next && (next != buf))
         {
           char *p;
           /* No "=" in value */
           if ((p = strchr((char *)buf, '=')))
             *p = 0;
           val = (char *)buf;
         }
     }
   
   my_setenv(env, val, err);
    
   return next ? next + 1 : NULL;
 }  }
   
 #ifdef HAVE_LUASCRIPT  #ifdef HAVE_LUASCRIPT
Line 656  void queue_script(int action, struct dhcp_lease *lease Line 690  void queue_script(int action, struct dhcp_lease *lease
   unsigned int hostname_len = 0, clid_len = 0, ed_len = 0;    unsigned int hostname_len = 0, clid_len = 0, ed_len = 0;
   int fd = daemon->dhcpfd;    int fd = daemon->dhcpfd;
 #ifdef HAVE_DHCP6   #ifdef HAVE_DHCP6 
   int is6 = !!(lease->flags & (LEASE_TA | LEASE_NA));  
   
   if (!daemon->dhcp)    if (!daemon->dhcp)
     fd = daemon->dhcp6fd;      fd = daemon->dhcp6fd;
 #endif  #endif
Line 678  void queue_script(int action, struct dhcp_lease *lease Line 710  void queue_script(int action, struct dhcp_lease *lease
   buf->action = action;    buf->action = action;
   buf->flags = lease->flags;    buf->flags = lease->flags;
 #ifdef HAVE_DHCP6   #ifdef HAVE_DHCP6 
  if (is6)  buf->vendorclass_count = lease->vendorclass_count;
    buf->hwaddr_len = lease->vendorclass_count;  buf->addr6 = lease->addr6;
  else  buf->iaid = lease->iaid;
 #endif  #endif
    buf->hwaddr_len = lease->hwaddr_len;  buf->hwaddr_len = lease->hwaddr_len;
   buf->hwaddr_type = lease->hwaddr_type;    buf->hwaddr_type = lease->hwaddr_type;
   buf->clid_len = clid_len;    buf->clid_len = clid_len;
   buf->ed_len = ed_len;    buf->ed_len = ed_len;
Line 739  void queue_tftp(off_t file_len, char *filename, union  Line 771  void queue_tftp(off_t file_len, char *filename, union 
   
   buf->action = ACTION_TFTP;    buf->action = ACTION_TFTP;
   buf->hostname_len = filename_len;    buf->hostname_len = filename_len;
  buf->hwaddr_len = file_len;  buf->file_len = file_len;
   
   if ((buf->flags = peer->sa.sa_family) == AF_INET)    if ((buf->flags = peer->sa.sa_family) == AF_INET)
     buf->addr = peer->in.sin_addr;      buf->addr = peer->in.sin_addr;
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   else    else
    memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ);    buf->addr6 = peer->in6.sin6_addr;
 #endif  #endif
   
   memcpy((unsigned char *)(buf+1), filename, filename_len);    memcpy((unsigned char *)(buf+1), filename, filename_len);
Line 753  void queue_tftp(off_t file_len, char *filename, union  Line 785  void queue_tftp(off_t file_len, char *filename, union 
   bytes_in_buf = sizeof(struct script_data) +  filename_len;    bytes_in_buf = sizeof(struct script_data) +  filename_len;
 }  }
 #endif  #endif
   
   void queue_arp(int action, unsigned char *mac, int maclen, int family, struct all_addr *addr)
   {
     /* no script */
     if (daemon->helperfd == -1)
       return;
     
     buff_alloc(sizeof(struct script_data));
     memset(buf, 0, sizeof(struct script_data));
   
     buf->action = action;
     buf->hwaddr_len = maclen;
     buf->hwaddr_type =  ARPHRD_ETHER; 
     if ((buf->flags = family) == AF_INET)
       buf->addr = addr->addr.addr4;
   #ifdef HAVE_IPV6
     else
       buf->addr6 = addr->addr.addr6;
   #endif
     
     memcpy(buf->hwaddr, mac, maclen);
     
     bytes_in_buf = sizeof(struct script_data);
   }
   
 int helper_buf_empty(void)  int helper_buf_empty(void)
 {  {

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


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