Diff for /embedaddon/dnsmasq/src/helper.c between versions 1.1.1.2 and 1.1.1.4

version 1.1.1.2, 2014/06/15 16:31:38 version 1.1.1.4, 2021/03/17 00:56:46
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley/* dnsmasq is Copyright (c) 2000-2021 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 64  struct script_data Line 64  struct script_data
 #ifdef HAVE_TFTP  #ifdef HAVE_TFTP
   off_t file_len;    off_t file_len;
 #endif  #endif
 #ifdef HAVE_IPV6  
   struct in6_addr addr6;    struct in6_addr addr6;
 #endif  
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
  int iaid, vendorclass_count;  int vendorclass_count;
   unsigned int iaid;
 #endif  #endif
   unsigned char hwaddr[DHCP_CHADDR_MAX];    unsigned char hwaddr[DHCP_CHADDR_MAX];
   char interface[IF_NAMESIZE];    char interface[IF_NAMESIZE];
Line 82  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 97  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 130  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 187  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 219  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)
         {
           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;
   
                   
Line 289  int create_helper(int event_fd, int err_fd, uid_t uid, Line 303  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.addr6, daemon->addrbuff, ADDRSTRLEN);          inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
 #endif  
   
 #ifdef HAVE_TFTP  #ifdef HAVE_TFTP
       /* file length */        /* file length */
Line 321  int create_helper(int event_fd, int err_fd, uid_t uid, Line 333  int create_helper(int event_fd, int err_fd, uid_t uid,
                   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 445  int create_helper(int event_fd, int err_fd, uid_t uid, Line 473  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 477  int create_helper(int event_fd, int err_fd, uid_t uid, Line 543  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)
         {          {
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
           my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);            my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
Line 529  int create_helper(int event_fd, int err_fd, uid_t uid, Line 604  int create_helper(int event_fd, int err_fd, uid_t uid,
               buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);                buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);
               buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);                buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);
               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_TAGS", &err);            buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
Line 550  int create_helper(int event_fd, int err_fd, uid_t uid, Line 626  int create_helper(int event_fd, int err_fd, uid_t uid,
           my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err);            my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err);
           if (data.action == ACTION_OLD_HOSTNAME)            if (data.action == ACTION_OLD_HOSTNAME)
             hostname = NULL;              hostname = NULL;
             
             my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
         }          }
   
       my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &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)
Line 563  int create_helper(int event_fd, int err_fd, uid_t uid, Line 639  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, is6 ? daemon->packet : daemon->dhcp_buff,                 (is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff, 
                 daemon->addrbuff, hostname, (char*)NULL);                  daemon->addrbuff, hostname, (char*)NULL);
           err = errno;            err = errno;
         }          }
Line 749  void queue_tftp(off_t file_len, char *filename, union  Line 825  void queue_tftp(off_t file_len, char *filename, union 
   
   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
     buf->addr6 = peer->in6.sin6_addr;      buf->addr6 = peer->in6.sin6_addr;
 #endif  
   
   memcpy((unsigned char *)(buf+1), filename, filename_len);    memcpy((unsigned char *)(buf+1), filename, filename_len);
       
   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, 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)
 {  {

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


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