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

version 1.1.1.1, 2013/07/29 19:37:40 version 1.1.1.5, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley/* dnsmasq is Copyright (c) 2000-2022 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 18 Line 18
   
 #ifdef HAVE_SCRIPT  #ifdef HAVE_SCRIPT
   
/* This file has code to fork a helper process which recieves data via a pipe /* This file has code to fork a helper process which receives data via a pipe 
    shared with the main process and which is responsible for calling a script when     shared with the main process and which is responsible for calling a script when
    DHCP leases change.     DHCP leases change.
   
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
     struct in6_addr addr6;
   #ifdef HAVE_DHCP6
     int vendorclass_count;
     unsigned int iaid;
   #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 74  int create_helper(int event_fd, int err_fd, uid_t uid, Line 81  int create_helper(int event_fd, int err_fd, uid_t uid,
   pid_t pid;    pid_t pid;
   int i, pipefd[2];    int i, pipefd[2];
   struct sigaction sigact;    struct sigaction sigact;
  unsigned char *alloc_buff = NULL;
   
   /* create the pipe through which the main program sends us commands,    /* create the pipe through which the main program sends us commands,
      then fork our process. */       then fork our process. */
   if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)    if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
Line 89  int create_helper(int event_fd, int err_fd, uid_t uid, Line 97  int create_helper(int event_fd, int err_fd, uid_t uid,
       return pipefd[1];        return pipefd[1];
     }      }
   
  /* ignore SIGTERM, so that we can clean up when the main process gets hit  /* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
      and SIGALRM so that we can use sleep() */       and SIGALRM so that we can use sleep() */
   sigact.sa_handler = SIG_IGN;    sigact.sa_handler = SIG_IGN;
   sigact.sa_flags = 0;    sigact.sa_flags = 0;
   sigemptyset(&sigact.sa_mask);    sigemptyset(&sigact.sa_mask);
   sigaction(SIGTERM, &sigact, NULL);    sigaction(SIGTERM, &sigact, NULL);
   sigaction(SIGALRM, &sigact, NULL);    sigaction(SIGALRM, &sigact, NULL);
     sigaction(SIGINT, &sigact, NULL);
   
   if (!option_bool(OPT_DEBUG) && uid != 0)    if (!option_bool(OPT_DEBUG) && uid != 0)
     {      {
Line 122  int create_helper(int event_fd, int err_fd, uid_t uid, Line 131  int create_helper(int event_fd, int err_fd, uid_t uid,
      Don't close err_fd, in case the lua-init fails.       Don't close err_fd, in case the lua-init fails.
      Note that we have to do this before lua init       Note that we have to do this before lua init
      so we don't close any lua fds. */       so we don't close any lua fds. */
  for (max_fd--; max_fd >= 0; max_fd--)  close_fds(max_fd, pipefd[0], event_fd, err_fd);
    if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO &&  
        max_fd != STDIN_FILENO && max_fd != pipefd[0] &&  
        max_fd != event_fd && max_fd != err_fd) 
      close(max_fd); 
       
 #ifdef HAVE_LUASCRIPT  #ifdef HAVE_LUASCRIPT
   if (daemon->luascript)    if (daemon->luascript)
Line 179  int create_helper(int event_fd, int err_fd, uid_t uid, Line 184  int create_helper(int event_fd, int err_fd, uid_t uid,
       struct script_data data;        struct script_data data;
       char *p, *action_str, *hostname = NULL, *domain = NULL;        char *p, *action_str, *hostname = NULL, *domain = NULL;
       unsigned char *buf = (unsigned char *)daemon->namebuff;        unsigned char *buf = (unsigned char *)daemon->namebuff;
      unsigned char *end, *extradata, *alloc_buff = NULL;      unsigned char *end, *extradata;
       int is6, err = 0;        int is6, err = 0;
         int pipeout[2];
   
      free(alloc_buff);      /* Free rarely-allocated memory from previous iteration. */
       if (alloc_buff)
         {
           free(alloc_buff);
           alloc_buff = NULL;
         }
               
       /* we read zero bytes when pipe closed: this is our signal to exit */         /* we read zero bytes when pipe closed: this is our signal to exit */ 
       if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))        if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))
Line 211  int create_helper(int event_fd, int err_fd, uid_t uid, Line 222  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)
        continue;        {
          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 if (data.action == ACTION_RELAY_SNOOP)
          {
            is6 = 1;
            action_str = "relay-snoop";
          }
        else
          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 262  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 275  int create_helper(int event_fd, int err_fd, uid_t uid, Line 291  int create_helper(int event_fd, int err_fd, uid_t uid,
           char *dot;            char *dot;
           hostname = (char *)buf;            hostname = (char *)buf;
           hostname[data.hostname_len - 1] = 0;            hostname[data.hostname_len - 1] = 0;
          if (data.action != ACTION_TFTP)          if (data.action != ACTION_TFTP && data.action != ACTION_RELAY_SNOOP)
             {              {
               if (!legal_hostname(hostname))                if (!legal_hostname(hostname))
                 hostname = NULL;                  hostname = NULL;
Line 291  int create_helper(int event_fd, int err_fd, uid_t uid, Line 307  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  
       else        else
        inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN);        inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
#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 332  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_RELAY_SNOOP)
               {
                 lua_getglobal(lua, "snoop"); 
                 if (lua_type(lua, -1) != LUA_TFUNCTION)
                   lua_pop(lua, 1); /* tftp 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, hostname);
                     lua_setfield(lua, -2, "prefix"); 
                     lua_pushstring(lua, data.interface);
                     lua_setfield(lua, -2, "client_interface");
                     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 379  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 371  int create_helper(int event_fd, int err_fd, uid_t uid, Line 421  int create_helper(int event_fd, int err_fd, uid_t uid,
                               
               end = extradata + data.ed_len;                end = extradata + data.ed_len;
               buf = extradata;                buf = extradata;
   
                 lua_pushnumber(lua, data.ed_len == 0 ? 1 : 0);
                 lua_setfield(lua, -2, "data_missing");
                               
               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 394  int create_helper(int event_fd, int err_fd, uid_t uid, Line 451  int create_helper(int event_fd, int err_fd, uid_t uid,
                   buf = grab_extradata_lua(buf, end, "subscriber_id");                    buf = grab_extradata_lua(buf, end, "subscriber_id");
                   buf = grab_extradata_lua(buf, end, "remote_id");                    buf = grab_extradata_lua(buf, end, "remote_id");
                 }                  }
              
               buf = grab_extradata_lua(buf, end, "requested_options");
               buf = grab_extradata_lua(buf, end, "mud_url");
               buf = grab_extradata_lua(buf, end, "tags");                buf = grab_extradata_lua(buf, end, "tags");
                               
               if (is6)                if (is6)
                 buf = grab_extradata_lua(buf, end, "relay_address");                  buf = grab_extradata_lua(buf, end, "relay_address");
               else if (data.giaddr.s_addr != 0)                else if (data.giaddr.s_addr != 0)
                 {                  {
                  lua_pushstring(lua, inet_ntoa(data.giaddr));                  inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
                   lua_pushstring(lua, daemon->dhcp_buff2);
                   lua_setfield(lua, -2, "relay_address");                    lua_setfield(lua, -2, "relay_address");
                 }                  }
                               
Line 423  int create_helper(int event_fd, int err_fd, uid_t uid, Line 483  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 441  int create_helper(int event_fd, int err_fd, uid_t uid, Line 501  int create_helper(int event_fd, int err_fd, uid_t uid,
       if (!daemon->lease_change_command)        if (!daemon->lease_change_command)
         continue;          continue;
   
         /* Pipe to capture stdout and stderr from script */
         if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
           continue;
         
       /* possible fork errors are all temporary resource problems */        /* possible fork errors are all temporary resource problems */
       while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))        while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
         sleep(2);          sleep(2);
   
       if (pid == -1)        if (pid == -1)
        continue;        {
           if (!option_bool(OPT_DEBUG))
             {
               close(pipeout[0]);
               close(pipeout[1]);
             }
           continue;
         }
               
       /* wait for child to complete */        /* wait for child to complete */
       if (pid != 0)        if (pid != 0)
         {          {
             if (!option_bool(OPT_DEBUG))
               {
                 FILE *fp;
             
                 close(pipeout[1]);
                 
                 /* Read lines sent to stdout/err by the script and pass them back to be logged */
                 if (!(fp = fdopen(pipeout[0], "r")))
                   close(pipeout[0]);
                 else
                   {
                     while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
                       {
                         /* do not include new lines, log will append them */
                         size_t len = strlen(daemon->packet);
                         if (len > 0)
                           {
                             --len;
                             if (daemon->packet[len] == '\n')
                               daemon->packet[len] = 0;
                           }
                         send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
                       }
                     fclose(fp);
                   }
               }
             
           /* reap our children's children, if necessary */            /* reap our children's children, if necessary */
           while (1)            while (1)
             {              {
Line 473  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,
                       
           continue;            continue;
         }          }
   
         if (!option_bool(OPT_DEBUG))
           {
             /* map stdout/stderr of script to pipeout */
             close(pipeout[0]);
             dup2(pipeout[1], STDOUT_FILENO);
             dup2(pipeout[1], STDERR_FILENO);
             close(pipeout[1]);
           }
               
      if (data.action != ACTION_TFTP)      if (data.action != ACTION_TFTP && data.action != ACTION_ARP && data.action != ACTION_RELAY_SNOOP)
         {          {
          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 600  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;
   
             if (data.ed_len == 0)
               my_setenv("DNSMASQ_DATA_MISSING", "1", &err);
                       
           if (!is6)            if (!is6)
             buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);              buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
 #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 531  int create_helper(int event_fd, int err_fd, uid_t uid, Line 637  int create_helper(int event_fd, int err_fd, uid_t uid,
               buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);                buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);
             }              }
                       
             buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
             buf = grab_extradata(buf, end, "DNSMASQ_MUD_URL", &err);
           buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);            buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
                  
           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);             {
               const char *giaddr = NULL;
               if (data.giaddr.s_addr != 0)
                   giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
               my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &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 657  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);
       close(pipefd[0]);        close(pipefd[0]);
   
         if (data.action == ACTION_RELAY_SNOOP)
           strcpy(daemon->packet, data.interface);
         
       p =  strrchr(daemon->lease_change_command, '/');        p =  strrchr(daemon->lease_change_command, '/');
       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 692  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 780  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 800  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 723  void queue_script(int action, struct dhcp_lease *lease Line 845  void queue_script(int action, struct dhcp_lease *lease
   bytes_in_buf = p - (unsigned char *)buf;    bytes_in_buf = p - (unsigned char *)buf;
 }  }
   
   #ifdef HAVE_DHCP6
   void queue_relay_snoop(struct in6_addr *client, int if_index, struct in6_addr *prefix, int prefix_len)
   {
     /* no script */
     if (daemon->helperfd == -1)
       return;
     
     inet_ntop(AF_INET6, prefix, daemon->addrbuff, ADDRSTRLEN);
   
     /* 5 for /nnn and zero on the end of the prefix. */
     buff_alloc(sizeof(struct script_data) + ADDRSTRLEN + 5);
     memset(buf, 0, sizeof(struct script_data));
   
     buf->action = ACTION_RELAY_SNOOP;
     buf->addr6 = *client;
     buf->hostname_len = sprintf((char *)(buf+1), "%s/%u", daemon->addrbuff, prefix_len) + 1;
     
     indextoname(daemon->dhcp6fd, if_index, buf->interface);
   
     bytes_in_buf = sizeof(struct script_data) + buf->hostname_len;
   }
   #endif
   
 #ifdef HAVE_TFTP  #ifdef HAVE_TFTP
 /* This nastily re-uses DHCP-fields for TFTP stuff */  /* This nastily re-uses DHCP-fields for TFTP stuff */
 void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)  void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
Line 739  void queue_tftp(off_t file_len, char *filename, union  Line 884  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  
   else    else
    memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ);    buf->addr6 = peer->in6.sin6_addr;
#endif 
   
   memcpy((unsigned char *)(buf+1), filename, filename_len);    memcpy((unsigned char *)(buf+1), filename, filename_len);
       
Line 754  void queue_tftp(off_t file_len, char *filename, union  Line 897  void queue_tftp(off_t file_len, char *filename, union 
 }  }
 #endif  #endif
   
   void queue_arp(int action, unsigned char *mac, int maclen, int family, union 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->addr4;
     else
       buf->addr6 = addr->addr6;
     
     memcpy(buf->hwaddr, mac, maclen);
     
     bytes_in_buf = sizeof(struct script_data);
   }
   
 int helper_buf_empty(void)  int helper_buf_empty(void)
 {  {
   return bytes_in_buf == 0;    return bytes_in_buf == 0;
Line 780  void helper_write(void) Line 945  void helper_write(void)
     }      }
 }  }
   
#endif#endif /* HAVE_SCRIPT */
 
 
 

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


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