Diff for /embedaddon/miniupnpd/miniupnpd.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/05/29 12:55:57 version 1.1.1.3, 2013/07/22 00:32:35
Line 1 Line 1
 /* $Id$ */  /* $Id$ */
 /* MiniUPnP project  /* MiniUPnP project
  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/   * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
 * (c) 2006-2011 Thomas Bernard * (c) 2006-2013 Thomas Bernard
  * This software is subject to the conditions detailed   * This software is subject to the conditions detailed
  * in the LICENCE file provided within the distribution */   * in the LICENCE file provided within the distribution */
   
Line 12 Line 12
 /* apt-get install libnetfilter-queue-dev */  /* apt-get install libnetfilter-queue-dev */
 #include <netinet/ip.h>  #include <netinet/ip.h>
 #include <netinet/udp.h>  #include <netinet/udp.h>
//#include <linux/netfilter_ipv4.h>  /* Defines verdicts (NF_ACCEPT, etc) */#if 0
 #include <linux/netfilter_ipv4.h>  /* Defines verdicts (NF_ACCEPT, etc) */
 #endif
 #include <linux/netfilter.h>  #include <linux/netfilter.h>
 #include <libnetfilter_queue/libnetfilter_queue.h>  #include <libnetfilter_queue/libnetfilter_queue.h>
 #include <linux/netfilter/nfnetlink_queue.h>  #include <linux/netfilter/nfnetlink_queue.h>
Line 47 Line 49
 #include <sys/un.h>  #include <sys/un.h>
 #endif  #endif
   
   #include "macros.h"
 #include "upnpglobalvars.h"  #include "upnpglobalvars.h"
 #include "upnphttp.h"  #include "upnphttp.h"
 #include "upnpdescgen.h"  #include "upnpdescgen.h"
Line 56 Line 59
 #include "options.h"  #include "options.h"
 #include "minissdp.h"  #include "minissdp.h"
 #include "upnpredirect.h"  #include "upnpredirect.h"
   #include "upnppinhole.h"
 #include "miniupnpdtypes.h"  #include "miniupnpdtypes.h"
 #include "daemonize.h"  #include "daemonize.h"
 #include "upnpevents.h"  #include "upnpevents.h"
Line 67 Line 71
 #ifdef USE_IFACEWATCHER  #ifdef USE_IFACEWATCHER
 #include "ifacewatcher.h"  #include "ifacewatcher.h"
 #endif  #endif
   #ifdef ENABLE_6FC_SERVICE
   #ifdef USE_NETFILTER
   void init_iptpinhole(void);
   #endif
   #endif
   
 #ifndef DEFAULT_CONFIG  #ifndef DEFAULT_CONFIG
 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"  #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
Line 91  int get_udp_dst_port (char *payload); Line 100  int get_udp_dst_port (char *payload);
 #endif  #endif
   
 /* variables used by signals */  /* variables used by signals */
static volatile int quitting = 0;static volatile sig_atomic_t quitting = 0;
volatile int should_send_public_address_change_notif = 0;volatile sig_atomic_t should_send_public_address_change_notif = 0;
   
 /* OpenAndConfHTTPSocket() :  /* OpenAndConfHTTPSocket() :
  * setup the socket used to handle incoming HTTP connections. */   * setup the socket used to handle incoming HTTP connections. */
Line 133  OpenAndConfHTTPSocket(unsigned short port) Line 142  OpenAndConfHTTPSocket(unsigned short port)
         }          }
 #endif  #endif
   
           if(!set_non_blocking(s))
           {
                   syslog(LOG_WARNING, "set_non_blocking(http): %m");
           }
   
 #ifdef ENABLE_IPV6  #ifdef ENABLE_IPV6
         memset(&listenname, 0, sizeof(struct sockaddr_in6));          memset(&listenname, 0, sizeof(struct sockaddr_in6));
         listenname.sin6_family = AF_INET6;          listenname.sin6_family = AF_INET6;
Line 193  OpenAndConfNFqueue(){ Line 207  OpenAndConfNFqueue(){
   
         inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));          inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));
   
        //Get a queue connection handle from the module        /* Get a queue connection handle from the module */
         if (!(nfqHandle = nfq_open())) {          if (!(nfqHandle = nfq_open())) {
                 syslog(LOG_ERR, "Error in nfq_open(): %m");                  syslog(LOG_ERR, "Error in nfq_open(): %m");
                 return -1;                  return -1;
         }          }
   
        //Unbind the handler from processing any IP packets        /* Unbind the handler from processing any IP packets
        //      Not totally sure why this is done, or if it's necessary...           Not totally sure why this is done, or if it's necessary... */
         if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {          if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {
                 syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");                  syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");
                 return -1;                  return -1;
         }          }
   
        //Bind this handler to process IP packets...        /* Bind this handler to process IP packets... */
         if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {          if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
                 syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");                  syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
                 return -1;                  return -1;
         }          }
   
        //      Install a callback on queue -Q        /*      Install a callback on queue -Q */
         if (!(myQueue = nfq_create_queue(nfqHandle,  nfqueue, &nfqueue_cb, NULL))) {          if (!(myQueue = nfq_create_queue(nfqHandle,  nfqueue, &nfqueue_cb, NULL))) {
                 syslog(LOG_ERR, "Error in nfq_create_queue(): %m");                  syslog(LOG_ERR, "Error in nfq_create_queue(): %m");
                 return -1;                  return -1;
         }          }
   
        //      Turn on packet copy mode        /*      Turn on packet copy mode */
         if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {          if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
                 syslog(LOG_ERR, "Error setting packet copy mode (): %m");                  syslog(LOG_ERR, "Error setting packet copy mode (): %m");
                 return -1;                  return -1;
Line 256  static int nfqueue_cb( Line 270  static int nfqueue_cb(
                 int dport = get_udp_dst_port(pkt);                  int dport = get_udp_dst_port(pkt);
   
                 int x = sizeof (struct ip) + sizeof (struct udphdr);                  int x = sizeof (struct ip) + sizeof (struct udphdr);
        
                /* packets we are interested in are UDP multicast to 239.255.255.250:1900                       /* packets we are interested in are UDP multicast to 239.255.255.250:1900
                  * and start with a data string M-SEARCH                   * and start with a data string M-SEARCH
                  */                   */
                if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)                 if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)
                         && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {                          && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
                
                         /* get the index that the packet came in on */                          /* get the index that the packet came in on */
                         u_int32_t idx = nfq_get_indev(nfa);                          u_int32_t idx = nfq_get_indev(nfa);
                         int i = 0;                          int i = 0;
Line 272  static int nfqueue_cb( Line 286  static int nfqueue_cb(
                                         struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));                                          struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
   
                                         char *dd = pkt + x;                                          char *dd = pkt + x;
                                        
                                         struct sockaddr_in sendername;                                          struct sockaddr_in sendername;
                                         sendername.sin_family = AF_INET;                                          sendername.sin_family = AF_INET;
                                         sendername.sin_port = udp->source;                                          sendername.sin_port = udp->source;
Line 284  static int nfqueue_cb( Line 298  static int nfqueue_cb(
                                 }                                  }
                         }                          }
                 }                  }
                
                 nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);                  nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
   
         } else {          } else {
                 syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");                  syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
                return 1; // from nfqueue source: 0 = ok, >0 = soft error, <0 hard error                return 1;
                 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
         }          }
   
         return 0;          return 0;
Line 369  write_ctlsockets_list(int fd, struct ctlelem * e) Line 384  write_ctlsockets_list(int fd, struct ctlelem * e)
         }          }
 }  }
   
   #ifndef DISABLE_CONFIG_FILE
 static void  static void
 write_option_list(int fd)  write_option_list(int fd)
 {  {
         char buffer[256];          char buffer[256];
         int len;          int len;
        int i;        unsigned int i;
         write(fd, "Options :\n", 10);          write(fd, "Options :\n", 10);
         for(i=0; i<num_options; i++)          for(i=0; i<num_options; i++)
         {          {
Line 384  write_option_list(int fd) Line 400  write_option_list(int fd)
                 write(fd, buffer, len);                  write(fd, buffer, len);
         }          }
 }  }
   #endif
   
 static void  static void
 write_command_line(int fd, int argc, char * * argv)  write_command_line(int fd, int argc, char * * argv)
Line 403  write_command_line(int fd, int argc, char * * argv) Line 420  write_command_line(int fd, int argc, char * * argv)
   
 #endif  #endif
   
/* Handler for the SIGTERM signal (kill) /* Handler for the SIGTERM signal (kill)
  * SIGINT is also handled */   * SIGINT is also handled */
 static void  static void
 sigterm(int sig)  sigterm(int sig)
 {  {
        /*int save_errno = errno;*/        UNUSED(sig);
        signal(sig, SIG_IGN);   /* Ignore this signal while we are quitting */        /*int save_errno = errno; */
         /*signal(sig, SIG_IGN);*/        /* Ignore this signal while we are quitting */
         /* Note : isn't it useless ? */
   
   #if 0
           /* calling syslog() is forbidden in signal handler according to
            * signal(3) */
         syslog(LOG_NOTICE, "received signal %d, good-bye", sig);          syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
   #endif
   
         quitting = 1;          quitting = 1;
         /*errno = save_errno;*/          /*errno = save_errno;*/
Line 421  sigterm(int sig) Line 444  sigterm(int sig)
 static void  static void
 sigusr1(int sig)  sigusr1(int sig)
 {  {
           UNUSED(sig);
   #if 0
           /* calling syslog() is forbidden in signal handler according to
            * signal(3) */
         syslog(LOG_INFO, "received signal %d, public ip address change", sig);          syslog(LOG_INFO, "received signal %d, public ip address change", sig);
   #endif
   
         should_send_public_address_change_notif = 1;          should_send_public_address_change_notif = 1;
 }  }
Line 506  struct runtime_vars { Line 534  struct runtime_vars {
   
 /* parselanaddr()  /* parselanaddr()
  * parse address with mask   * parse address with mask
 * ex: 192.168.1.1/24 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
  * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the   * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
  * external interface associated with the lan subnet follows.   * external interface associated with the lan subnet follows.
  * ex : 192.168.1.1/24 81.21.41.11   * ex : 192.168.1.1/24 81.21.41.11
  *   *
 * return value :  * Can also use the interface name (ie eth0)
  *
  * return value :
  *    0 : ok   *    0 : ok
  *   -1 : error */   *   -1 : error */
 static int  static int
 parselanaddr(struct lan_addr_s * lan_addr, const char * str)  parselanaddr(struct lan_addr_s * lan_addr, const char * str)
 {  {
         const char * p;          const char * p;
         int nbits = 24; /* by default, networks are /24 */  
         int n;          int n;
           char tmp[16];
   
           memset(lan_addr, 0, sizeof(struct lan_addr_s));
         p = str;          p = str;
         while(*p && *p != '/' && !isspace(*p))          while(*p && *p != '/' && !isspace(*p))
                 p++;                  p++;
         n = p - str;          n = p - str;
        if(*p == '/')        if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
         {          {
                nbits = atoi(++p);                /* not starting with a digit : suppose it is an interface name */
                while(*p && !isspace(*p))                memcpy(lan_addr->ifname, str, n);
                        p++;                lan_addr->ifname[n] = '\0';
                 if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str)) < 0)
                         goto parselan_error;
         }          }
        if(n>15)        else
         {          {
                fprintf(stderr, "Error parsing address/mask : %s\n", str);                if(n>15)
                return -1;                        goto parselan_error;
                 memcpy(lan_addr->str, str, n);
                 lan_addr->str[n] = '\0';
         }          }
         memcpy(lan_addr->str, str, n);  
         lan_addr->str[n] = '\0';  
         if(!inet_aton(lan_addr->str, &lan_addr->addr))          if(!inet_aton(lan_addr->str, &lan_addr->addr))
                   goto parselan_error;
           if(*p == '/')
         {          {
                fprintf(stderr, "Error parsing address/mask : %s\n", str);                const char * q = ++p;
                return -1;                while(*p && isdigit(*p))
                         p++;
                 if(*p=='.')
                 {
                         while(*p && (*p=='.' || isdigit(*p)))
                                 p++;
                         n = p - q;
                         if(n>15)
                                 goto parselan_error;
                         memcpy(tmp, q, n);
                         tmp[n] = '\0';
                         if(!inet_aton(tmp, &lan_addr->mask))
                                 goto parselan_error;
                 }
                 else
                 {
                         int nbits = atoi(q);
                         if(nbits > 32 || nbits < 0)
                                 goto parselan_error;
                         lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
                 }
         }          }
        lan_addr->mask.s_addr = htonl(nbits ? (0xffffffff << (32 - nbits)) : 0);        else
         {
                 /* by default, networks are /24 */
                 lan_addr->mask.s_addr = htonl(0xffffff00u);
         }
 #ifdef MULTIPLE_EXTERNAL_IP  #ifdef MULTIPLE_EXTERNAL_IP
         /* skip spaces */          /* skip spaces */
         while(*p && isspace(*p))          while(*p && isspace(*p))
Line 562  parselanaddr(struct lan_addr_s * lan_addr, const char  Line 622  parselanaddr(struct lan_addr_s * lan_addr, const char 
                 }                  }
         }          }
 #endif  #endif
   #ifdef ENABLE_IPV6
           if(lan_addr->ifname[0] != '\0')
           {
                   lan_addr->index = if_nametoindex(lan_addr->ifname);
                   if(lan_addr->index == 0)
                           fprintf(stderr, "Cannot get index for network interface %s",
                                   lan_addr->ifname);
           }
   #endif
         return 0;          return 0;
   parselan_error:
           fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
                   str);
           return -1;
 }  }
   
 /* init phase :  /* init phase :
Line 580  init(int argc, char * * argv, struct runtime_vars * v) Line 653  init(int argc, char * * argv, struct runtime_vars * v)
         int i;          int i;
         int pid;          int pid;
         int debug_flag = 0;          int debug_flag = 0;
         int options_flag = 0;  
         int openlog_option;          int openlog_option;
         struct sigaction sa;          struct sigaction sa;
         /*const char * logfilename = 0;*/          /*const char * logfilename = 0;*/
         const char * presurl = 0;          const char * presurl = 0;
   #ifndef DISABLE_CONFIG_FILE
           int options_flag = 0;
         const char * optionsfile = DEFAULT_CONFIG;          const char * optionsfile = DEFAULT_CONFIG;
   #endif /* DISABLE_CONFIG_FILE */
         struct lan_addr_s * lan_addr;          struct lan_addr_s * lan_addr;
         struct lan_addr_s * lan_addr2;          struct lan_addr_s * lan_addr2;
   
Line 595  init(int argc, char * * argv, struct runtime_vars * v) Line 670  init(int argc, char * * argv, struct runtime_vars * v)
                 if(0 == strcmp(argv[i], "-h"))                  if(0 == strcmp(argv[i], "-h"))
                         goto print_usage;                          goto print_usage;
         }          }
   #ifndef DISABLE_CONFIG_FILE
         /* first check if "-f" option is used */          /* first check if "-f" option is used */
         for(i=2; i<argc; i++)          for(i=2; i<argc; i++)
         {          {
Line 605  init(int argc, char * * argv, struct runtime_vars * v) Line 681  init(int argc, char * * argv, struct runtime_vars * v)
                         break;                          break;
                 }                  }
         }          }
   #endif /* DISABLE_CONFIG_FILE */
   
         /* set initial values */          /* set initial values */
        SETFLAG(ENABLEUPNPMASK);        SETFLAG(ENABLEUPNPMASK);        /* UPnP is enabled by default */
   
         LIST_INIT(&lan_addrs);          LIST_INIT(&lan_addrs);
         v->port = -1;          v->port = -1;
         v->notify_interval = 30;        /* seconds between SSDP announces */          v->notify_interval = 30;        /* seconds between SSDP announces */
         v->clean_ruleset_threshold = 20;          v->clean_ruleset_threshold = 20;
         v->clean_ruleset_interval = 0;  /* interval between ruleset check. 0=disabled */          v->clean_ruleset_interval = 0;  /* interval between ruleset check. 0=disabled */
#ifndef DISABLE_CONFIG_FILE
         /* read options file first since          /* read options file first since
          * command line arguments have final say */           * command line arguments have final say */
         if(readoptionsfile(optionsfile) < 0)          if(readoptionsfile(optionsfile) < 0)
Line 625  init(int argc, char * * argv, struct runtime_vars * v) Line 702  init(int argc, char * * argv, struct runtime_vars * v)
         }          }
         else          else
         {          {
                for(i=0; i<num_options; i++)                for(i=0; i<(int)num_options; i++)
                 {                  {
                         switch(ary_options[i].id)                          switch(ary_options[i].id)
                         {                          {
Line 662  init(int argc, char * * argv, struct runtime_vars * v) Line 739  init(int argc, char * * argv, struct runtime_vars * v)
                         case UPNPPRESENTATIONURL:                          case UPNPPRESENTATIONURL:
                                 presurl = ary_options[i].value;                                  presurl = ary_options[i].value;
                                 break;                                  break;
                           case UPNPFRIENDLY_NAME:
                                   strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN);
                                   friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
                                   break;
 #ifdef USE_NETFILTER  #ifdef USE_NETFILTER
                         case UPNPFORWARDCHAIN:                          case UPNPFORWARDCHAIN:
                                 miniupnpd_forward_chain = ary_options[i].value;                                  miniupnpd_forward_chain = ary_options[i].value;
Line 677  init(int argc, char * * argv, struct runtime_vars * v) Line 758  init(int argc, char * * argv, struct runtime_vars * v)
                                 if(strcmp(ary_options[i].value, "yes") == 0)                                  if(strcmp(ary_options[i].value, "yes") == 0)
                                         SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/                                          SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
                                 break;                                  break;
   #if defined(USE_PF) || defined(USE_IPF)
                         case UPNPPACKET_LOG:                          case UPNPPACKET_LOG:
                                 if(strcmp(ary_options[i].value, "yes") == 0)                                  if(strcmp(ary_options[i].value, "yes") == 0)
                                         SETFLAG(LOGPACKETSMASK);        /*logpackets = 1;*/                                          SETFLAG(LOGPACKETSMASK);        /*logpackets = 1;*/
                                 break;                                  break;
   #endif
                         case UPNPUUID:                          case UPNPUUID:
                                 strncpy(uuidvalue+5, ary_options[i].value,                                  strncpy(uuidvalue+5, ary_options[i].value,
                                         strlen(uuidvalue+5) + 1);                                          strlen(uuidvalue+5) + 1);
Line 688  init(int argc, char * * argv, struct runtime_vars * v) Line 771  init(int argc, char * * argv, struct runtime_vars * v)
                         case UPNPSERIAL:                          case UPNPSERIAL:
                                 strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);                                  strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
                                 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';                                  serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
                                break;                                                          break;
                         case UPNPMODEL_NUMBER:                          case UPNPMODEL_NUMBER:
                                 strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);                                  strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
                                 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';                                  modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
Line 700  init(int argc, char * * argv, struct runtime_vars * v) Line 783  init(int argc, char * * argv, struct runtime_vars * v)
                                 v->clean_ruleset_interval = atoi(ary_options[i].value);                                  v->clean_ruleset_interval = atoi(ary_options[i].value);
                                 break;                                  break;
 #ifdef USE_PF  #ifdef USE_PF
                           case UPNPANCHOR:
                                   anchor_name = ary_options[i].value;
                                   break;
                         case UPNPQUEUE:                          case UPNPQUEUE:
                                 queue = ary_options[i].value;                                  queue = ary_options[i].value;
                                 break;                                  break;
Line 745  init(int argc, char * * argv, struct runtime_vars * v) Line 831  init(int argc, char * * argv, struct runtime_vars * v)
                         }                          }
                 }                  }
         }          }
   #endif /* DISABLE_CONFIG_FILE */
   
         /* command line arguments processing */          /* command line arguments processing */
         for(i=1; i<argc; i++)          for(i=1; i<argc; i++)
Line 767  init(int argc, char * * argv, struct runtime_vars * v) Line 854  init(int argc, char * * argv, struct runtime_vars * v)
                         else                          else
                                 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);                                  fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                         break;                          break;
                   case 'r':
                           if(i+1 < argc)
                                   v->clean_ruleset_interval = atoi(argv[++i]);
                           else
                                   fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                           break;
                 case 'u':                  case 'u':
                         if(i+1 < argc)                          if(i+1 < argc)
                                 strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1);                                  strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1);
                         else                          else
                                 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);                                  fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                         break;                          break;
                   case 'z':
                           if(i+1 < argc)
                                   strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
                           else
                                   fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                           friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
                           break;
                 case 's':                  case 's':
                         if(i+1 < argc)                          if(i+1 < argc)
                                 strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);                                  strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
Line 800  init(int argc, char * * argv, struct runtime_vars * v) Line 900  init(int argc, char * * argv, struct runtime_vars * v)
                 /*case 'l':                  /*case 'l':
                         logfilename = argv[++i];                          logfilename = argv[++i];
                         break;*/                          break;*/
   #if defined(USE_PF) || defined(USE_IPF)
                 case 'L':                  case 'L':
                         /*logpackets = 1;*/                          /*logpackets = 1;*/
                         SETFLAG(LOGPACKETSMASK);                          SETFLAG(LOGPACKETSMASK);
                         break;                          break;
   #endif
                 case 'S':                  case 'S':
                         SETFLAG(SECUREMODEMASK);                          SETFLAG(SECUREMODEMASK);
                         break;                          break;
Line 880  init(int argc, char * * argv, struct runtime_vars * v) Line 982  init(int argc, char * * argv, struct runtime_vars * v)
                                 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);                                  fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
                         break;                          break;
                 case 'a':                  case 'a':
   #ifndef MULTIPLE_EXTERNAL_IP
                         if(i+1 < argc)                          if(i+1 < argc)
                         {                          {
                                 i++;                                  i++;
Line 906  init(int argc, char * * argv, struct runtime_vars * v) Line 1009  init(int argc, char * * argv, struct runtime_vars * v)
                         }                          }
                         else                          else
                                 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);                                  fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
   #else
                           if(i+2 < argc)
                           {
                                   char *val=calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 1), sizeof(char));
                                   if (val == NULL)
                                   {
                                           fprintf(stderr, "memory allocation error for listen address storage\n");
                                           break;
                                   }
                                   sprintf(val, "%s %s", argv[i+1], argv[i+2]);
   
                                   lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
                                   if (lan_addr == NULL)
                                   {
                                           fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
                                           free(val);
                                           break;
                                   }
                                   if(parselanaddr(lan_addr, val) != 0)
                                   {
                                           fprintf(stderr, "can't parse \"%s\" as valid lan address\n", val);
                                           free(lan_addr);
                                           free(val);
                                           break;
                                   }
                                   /* check if we already have this address */
                                   for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
                                   {
                                           if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
                                                   break;
                                   }
                                   if (lan_addr2 == NULL)
                                           LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
   
                                   free(val);
                                   i+=2;
                           }
                           else
                                   fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
   #endif
                         break;                          break;
                   case 'A':
                           if(i+1 < argc) {
                                   void * tmp;
                                   tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1));
                                   if(tmp == NULL) {
                                           fprintf(stderr, "memory allocation error for permission\n");
                                   } else {
                                           upnppermlist = tmp;
                                           if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) {
                                                   num_upnpperm++;
                                           } else {
                                                   fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]);
                                           }
                                   }
                           } else
                                   fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                           break;
                 case 'f':                  case 'f':
                         i++;    /* discarding, the config file is already read */                          i++;    /* discarding, the config file is already read */
                         break;                          break;
Line 954  init(int argc, char * * argv, struct runtime_vars * v) Line 1114  init(int argc, char * * argv, struct runtime_vars * v)
         {          {
                 syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");                  syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");
                 return 1;                  return 1;
        }               }
   
         set_startup_time(GETFLAG(SYSUPTIMEMASK));          set_startup_time(GETFLAG(SYSUPTIMEMASK));
   
Line 975  init(int argc, char * * argv, struct runtime_vars * v) Line 1135  init(int argc, char * * argv, struct runtime_vars * v)
         memset(&sa, 0, sizeof(struct sigaction));          memset(&sa, 0, sizeof(struct sigaction));
         sa.sa_handler = sigterm;          sa.sa_handler = sigterm;
   
        if (sigaction(SIGTERM, &sa, NULL))        if(sigaction(SIGTERM, &sa, NULL) < 0)
         {          {
                 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");                  syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
                 return 1;                  return 1;
         }          }
        if (sigaction(SIGINT, &sa, NULL))        if(sigaction(SIGINT, &sa, NULL) < 0)
         {          {
                 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");                  syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
                 return 1;                  return 1;
         }          }
        sa.sa_handler = SIG_IGN;
        if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {        if(sigaction(SIGPIPE, &sa, NULL) < 0)
         {
                 syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");                  syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
         }          }
   
         sa.sa_handler = sigusr1;          sa.sa_handler = sigusr1;
        if (sigaction(SIGUSR1, &sa, NULL))        if(sigaction(SIGUSR1, &sa, NULL) < 0)
         {          {
                 syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");                  syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
         }          }
Line 1001  init(int argc, char * * argv, struct runtime_vars * v) Line 1161  init(int argc, char * * argv, struct runtime_vars * v)
                 syslog(LOG_ERR, "Failed to init redirection engine. EXITING");                  syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
                 return 1;                  return 1;
         }          }
   #ifdef ENABLE_6FC_SERVICE
   #ifdef USE_NETFILTER
           init_iptpinhole();
   #endif
   #endif
   
        writepidfile(pidfilename, pid);        if(writepidfile(pidfilename, pid) < 0)
                 pidfilename = NULL;
   
 #ifdef ENABLE_LEASEFILE  #ifdef ENABLE_LEASEFILE
         /*remove(lease_file);*/          /*remove(lease_file);*/
Line 1013  init(int argc, char * * argv, struct runtime_vars * v) Line 1179  init(int argc, char * * argv, struct runtime_vars * v)
         return 0;          return 0;
 print_usage:  print_usage:
         fprintf(stderr, "Usage:\n\t"          fprintf(stderr, "Usage:\n\t"
                "%s [-f config_file] [-i ext_ifname] [-o ext_ip]\n"                "%s "
#ifndef ENABLE_NATPMP#ifndef DISABLE_CONFIG_FILE
                        "\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S]\n"                        "[-f config_file] "
 #endif
                         "[-i ext_ifname] [-o ext_ip]\n"
 #ifndef MULTIPLE_EXTERNAL_IP
                         "\t\t[-a listening_ip]"
 #else  #else
                        "\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S] [-N]\n"                        "\t\t[-a listening_ip ext_ip]"
 #endif  #endif
                           " [-p port] [-d]"
   #if defined(USE_PF) || defined(USE_IPF)
                           " [-L]"
   #endif
                           " [-U] [-S]"
   #ifdef ENABLE_NATPMP
                           " [-N]"
   #endif
                           "\n"
                         /*"[-l logfile] " not functionnal */                          /*"[-l logfile] " not functionnal */
                         "\t\t[-u uuid] [-s serial] [-m model_number] \n"                          "\t\t[-u uuid] [-s serial] [-m model_number] \n"
                        "\t\t[-t notify_interval] [-P pid_filename]\n"                        "\t\t[-t notify_interval] [-P pid_filename] [-z fiendly_name]\n"
                        "\t\t[-B down up] [-w url]\n"                        "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
 #ifdef USE_PF  #ifdef USE_PF
                         "\t\t[-q queue] [-T tag]\n"                          "\t\t[-q queue] [-T tag]\n"
 #endif  #endif
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
                         "\t\t[-Q queue] [-n name]\n"                          "\t\t[-Q queue] [-n name]\n"
 #endif  #endif
                           "\t\t[-A \"permission rule\"]\n"
                 "\nNotes:\n\tThere can be one or several listening_ips.\n"                  "\nNotes:\n\tThere can be one or several listening_ips.\n"
                 "\tNotify interval is in seconds. Default is 30 seconds.\n"                  "\tNotify interval is in seconds. Default is 30 seconds.\n"
                         "\tDefault pid file is '%s'.\n"                          "\tDefault pid file is '%s'.\n"
                         "\tDefault config file is '%s'.\n"                          "\tDefault config file is '%s'.\n"
                         "\tWith -d miniupnpd will run as a standard program.\n"                          "\tWith -d miniupnpd will run as a standard program.\n"
   #if defined(USE_PF) || defined(USE_IPF)
                         "\t-L sets packet log in pf and ipf on.\n"                          "\t-L sets packet log in pf and ipf on.\n"
   #endif
                         "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"                          "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
                         "\t-U causes miniupnpd to report system uptime instead "                          "\t-U causes miniupnpd to report system uptime instead "
                         "of daemon uptime.\n"                          "of daemon uptime.\n"
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
                        "\t-N enable NAT-PMP functionnality.\n"                        "\t-N enable NAT-PMP functionality.\n"
 #endif  #endif
                         "\t-B sets bitrates reported by daemon in bits per second.\n"                          "\t-B sets bitrates reported by daemon in bits per second.\n"
                         "\t-w sets the presentation url. Default is http address on port 80\n"                          "\t-w sets the presentation url. Default is http address on port 80\n"
Line 1048  print_usage: Line 1230  print_usage:
                         "\t-T sets the tag name in pf.\n"                          "\t-T sets the tag name in pf.\n"
 #endif  #endif
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
                        "\t-Q sets the queue number that is used by NFQUEUE.\n"                        "\t-Q sets the queue number that is used by NFQUEUE.\n"
                        "\t-n sets the name of the interface(s) that packets will arrive on.\n"                        "\t-n sets the name of the interface(s) that packets will arrive on.\n"
 #endif  #endif
                           "\t-A use following syntax for permission rules :\n"
                           "\t  (allow|deny) (external port range) ip/mask (internal port range)\n"
                           "\texamples :\n"
                           "\t  \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
                           "\t  \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
                         "\t-h prints this help and quits.\n"                          "\t-h prints this help and quits.\n"
                 "", argv[0], pidfilename, DEFAULT_CONFIG);                  "", argv[0], pidfilename, DEFAULT_CONFIG);
         return 1;          return 1;
Line 1068  main(int argc, char * * argv) Line 1255  main(int argc, char * * argv)
         int sudpv6 = -1;        /* IP v6 socket for receiving SSDP */          int sudpv6 = -1;        /* IP v6 socket for receiving SSDP */
 #endif  #endif
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
        int * snatpmp;        int * snatpmp = NULL;
 #endif  #endif
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
         int nfqh = -1;          int nfqh = -1;
Line 1077  main(int argc, char * * argv) Line 1264  main(int argc, char * * argv)
         int sifacewatcher = -1;          int sifacewatcher = -1;
 #endif  #endif
   
        int * snotify;        int * snotify = NULL;
         int addr_count;          int addr_count;
         LIST_HEAD(httplisthead, upnphttp) upnphttphead;          LIST_HEAD(httplisthead, upnphttp) upnphttphead;
         struct upnphttp * e = 0;          struct upnphttp * e = 0;
         struct upnphttp * next;          struct upnphttp * next;
         fd_set readset; /* for select() */          fd_set readset; /* for select() */
 #ifdef ENABLE_EVENTS  
         fd_set writeset;          fd_set writeset;
 #endif  
         struct timeval timeout, timeofday, lasttimeofday = {0, 0};          struct timeval timeout, timeofday, lasttimeofday = {0, 0};
         int max_fd = -1;          int max_fd = -1;
 #ifdef USE_MINIUPNPDCTL  #ifdef USE_MINIUPNPDCTL
Line 1099  main(int argc, char * * argv) Line 1284  main(int argc, char * * argv)
         struct rule_state * rule_list = 0;          struct rule_state * rule_list = 0;
         struct timeval checktime = {0, 0};          struct timeval checktime = {0, 0};
         struct lan_addr_s * lan_addr;          struct lan_addr_s * lan_addr;
        syslog(LOG_INFO, "SNet version started");#ifdef ENABLE_6FC_SERVICE
         unsigned int next_pinhole_ts;
 #endif
   
         if(init(argc, argv, &v) != 0)          if(init(argc, argv, &v) != 0)
                 return 1;                  return 1;
Line 1107  main(int argc, char * * argv) Line 1294  main(int argc, char * * argv)
         addr_count = 0;          addr_count = 0;
         for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)          for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
                 addr_count++;                  addr_count++;
        snotify = (int*) malloc(addr_count * sizeof(int));        if(addr_count > 0) {
        memset(snotify, 0, sizeof(snotify));#ifndef ENABLE_IPV6
                 snotify = calloc(addr_count, sizeof(int));
 #else
                 /* one for IPv4, one for IPv6 */
                 snotify = calloc(addr_count * 2, sizeof(int));
 #endif
         }
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
        snatpmp = (int*) malloc(addr_count * sizeof(int));        if(addr_count > 0) {
        for(i = 0; i < addr_count; i++)                snatpmp = malloc(addr_count * sizeof(int));
                snatpmp[i] = -1;                for(i = 0; i < addr_count; i++)
                         snatpmp[i] = -1;
         }
 #endif  #endif
   
         LIST_INIT(&upnphttphead);          LIST_INIT(&upnphttphead);
Line 1129  main(int argc, char * * argv) Line 1324  main(int argc, char * * argv)
                 return 0;                  return 0;
         }          }
   
           syslog(LOG_INFO, "Starting%s%swith external interface %s",
   #ifdef ENABLE_NATPMP
                  GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
   #else
                  " ",
   #endif
                  GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
                  ext_if_name);
   
         if(GETFLAG(ENABLEUPNPMASK))          if(GETFLAG(ENABLEUPNPMASK))
         {          {
   
Line 1163  main(int argc, char * * argv) Line 1367  main(int argc, char * * argv)
                 sudp = OpenAndConfSSDPReceiveSocket(0);                  sudp = OpenAndConfSSDPReceiveSocket(0);
                 if(sudp < 0)                  if(sudp < 0)
                 {                  {
                        syslog(LOG_INFO, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");                        syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
                         if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {                          if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
                                 syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");                                  syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
                                 return 1;                                  return 1;
Line 1173  main(int argc, char * * argv) Line 1377  main(int argc, char * * argv)
                 sudpv6 = OpenAndConfSSDPReceiveSocket(1);                  sudpv6 = OpenAndConfSSDPReceiveSocket(1);
                 if(sudpv6 < 0)                  if(sudpv6 < 0)
                 {                  {
                        syslog(LOG_INFO, "Failed to open socket for receiving SSDP (IP v6).");                        syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
                 }                  }
 #endif  #endif
   
Line 1231  main(int argc, char * * argv) Line 1435  main(int argc, char * * argv)
                 }                  }
         }          }
 #endif  #endif
   
         /* main loop */          /* main loop */
         while(!quitting)          while(!quitting)
         {          {
Line 1238  main(int argc, char * * argv) Line 1443  main(int argc, char * * argv)
                 if((startup_time<60*60*24) && (time(NULL)>60*60*24))                  if((startup_time<60*60*24) && (time(NULL)>60*60*24))
                 {                  {
                         set_startup_time(GETFLAG(SYSUPTIMEMASK));                          set_startup_time(GETFLAG(SYSUPTIMEMASK));
                }                 }
                 /* send public address change notifications if needed */                  /* send public address change notifications if needed */
                 if(should_send_public_address_change_notif)                  if(should_send_public_address_change_notif)
                 {                  {
Line 1310  main(int argc, char * * argv) Line 1515  main(int argc, char * * argv)
                 /* Remove expired port mappings, based on UPnP IGD LeaseDuration                  /* Remove expired port mappings, based on UPnP IGD LeaseDuration
                  * or NAT-PMP lifetime) */                   * or NAT-PMP lifetime) */
                 if(nextruletoclean_timestamp                  if(nextruletoclean_timestamp
                  && (timeofday.tv_sec >= nextruletoclean_timestamp))                  && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
                 {                  {
                         syslog(LOG_DEBUG, "cleaning expired Port Mappings");                          syslog(LOG_DEBUG, "cleaning expired Port Mappings");
                         get_upnp_rules_state_list(0);                          get_upnp_rules_state_list(0);
                 }                  }
                 if(nextruletoclean_timestamp                  if(nextruletoclean_timestamp
                  && timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec))                  && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
                 {                  {
                         timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;                          timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
                         timeout.tv_usec = 0;                          timeout.tv_usec = 0;
Line 1345  main(int argc, char * * argv) Line 1550  main(int argc, char * * argv)
                 }                  }
 #endif  #endif
 #endif  #endif
   #ifdef ENABLE_6FC_SERVICE
                   /* Clean up expired IPv6 PinHoles */
                   next_pinhole_ts = 0;
                   upnp_clean_expired_pinholes(&next_pinhole_ts);
                   if(next_pinhole_ts &&
                      timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) {
                           timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec;
                           timeout.tv_usec = 0;
                   }
   #endif
   
                 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */                  /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
                 FD_ZERO(&readset);                  FD_ZERO(&readset);
                   FD_ZERO(&writeset);
   
                if (sudp >= 0)                 if (sudp >= 0)
                 {                  {
                         FD_SET(sudp, &readset);                          FD_SET(sudp, &readset);
                         max_fd = MAX( max_fd, sudp);                          max_fd = MAX( max_fd, sudp);
Line 1361  main(int argc, char * * argv) Line 1577  main(int argc, char * * argv)
                         }                          }
 #endif  #endif
                 }                  }
                if (shttpl >= 0)                 if (shttpl >= 0)
                 {                  {
                         FD_SET(shttpl, &readset);                          FD_SET(shttpl, &readset);
                         max_fd = MAX( max_fd, shttpl);                          max_fd = MAX( max_fd, shttpl);
Line 1375  main(int argc, char * * argv) Line 1591  main(int argc, char * * argv)
 #endif  #endif
   
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
                if (nfqh >= 0)                 if (nfqh >= 0)
                 {                  {
                         FD_SET(nfqh, &readset);                          FD_SET(nfqh, &readset);
                         max_fd = MAX( max_fd, nfqh);                          max_fd = MAX( max_fd, nfqh);
Line 1385  main(int argc, char * * argv) Line 1601  main(int argc, char * * argv)
                 i = 0;  /* active HTTP connections count */                  i = 0;  /* active HTTP connections count */
                 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)                  for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
                 {                  {
                        if((e->socket >= 0) && (e->state <= 2))                        if(e->socket >= 0)
                         {                          {
                                FD_SET(e->socket, &readset);                                if(e->state <= EWaitingForHttpContent)
                                max_fd = MAX( max_fd, e->socket);                                        FD_SET(e->socket, &readset);
                                 else if(e->state == ESendingAndClosing)
                                         FD_SET(e->socket, &writeset);
                                 else
                                         continue;
                                 max_fd = MAX(max_fd, e->socket);
                                 i++;                                  i++;
                         }                          }
                 }                  }
Line 1412  main(int argc, char * * argv) Line 1633  main(int argc, char * * argv)
                         FD_SET(sctl, &readset);                          FD_SET(sctl, &readset);
                         max_fd = MAX( max_fd, sctl);                          max_fd = MAX( max_fd, sctl);
                 }                  }
                
                 for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)                  for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
                 {                  {
                         if(ectl->socket >= 0) {                          if(ectl->socket >= 0) {
Line 1423  main(int argc, char * * argv) Line 1644  main(int argc, char * * argv)
 #endif  #endif
   
 #ifdef ENABLE_EVENTS  #ifdef ENABLE_EVENTS
                 FD_ZERO(&writeset);  
                 upnpevents_selectfds(&readset, &writeset, &max_fd);                  upnpevents_selectfds(&readset, &writeset, &max_fd);
 #endif  #endif
   
 #ifdef ENABLE_EVENTS  
                 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)                  if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
 #else  
                 if(select(max_fd+1, &readset, 0, 0, &timeout) < 0)  
 #endif  
                 {                  {
                         if(quitting) goto shutdown;                          if(quitting) goto shutdown;
                         if(errno == EINTR) continue; /* interrupted by a signal, start again */                          if(errno == EINTR) continue; /* interrupted by a signal, start again */
Line 1452  main(int argc, char * * argv) Line 1668  main(int argc, char * * argv)
                                 {                                  {
                                         /*write(ectl->socket, buf, l);*/                                          /*write(ectl->socket, buf, l);*/
                                         write_command_line(ectl->socket, argc, argv);                                          write_command_line(ectl->socket, argc, argv);
   #ifndef DISABLE_CONFIG_FILE
                                         write_option_list(ectl->socket);                                          write_option_list(ectl->socket);
   #endif
                                         write_permlist(ectl->socket, upnppermlist, num_upnpperm);                                          write_permlist(ectl->socket, upnppermlist, num_upnpperm);
                                         write_upnphttp_details(ectl->socket, upnphttphead.lh_first);                                          write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
                                         write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);                                          write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
Line 1483  main(int argc, char * * argv) Line 1701  main(int argc, char * * argv)
                         struct sockaddr_un clientname;                          struct sockaddr_un clientname;
                         struct ctlelem * tmp;                          struct ctlelem * tmp;
                         socklen_t clientnamelen = sizeof(struct sockaddr_un);                          socklen_t clientnamelen = sizeof(struct sockaddr_un);
                        //syslog(LOG_DEBUG, "sctl!");                        /*syslog(LOG_DEBUG, "sctl!");*/
                         s = accept(sctl, (struct sockaddr *)&clientname,                          s = accept(sctl, (struct sockaddr *)&clientname,
                                    &clientnamelen);                                     &clientnamelen);
                         syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);                          syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
                         tmp = malloc(sizeof(struct ctlelem));                          tmp = malloc(sizeof(struct ctlelem));
                        tmp->socket = s;                        if (tmp == NULL)
                        LIST_INSERT_HEAD(&ctllisthead, tmp, entries);                        {
                                 syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
                                 close(s);
                         }
                         else
                         {
                                 tmp->socket = s;
                                 LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
                         }
                 }                  }
 #endif  #endif
 #ifdef ENABLE_EVENTS  #ifdef ENABLE_EVENTS
Line 1528  main(int argc, char * * argv) Line 1754  main(int argc, char * * argv)
                 /* LIST_FOREACH macro is not available under linux */                  /* LIST_FOREACH macro is not available under linux */
                 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)                  for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
                 {                  {
                        if(  (e->socket >= 0) && (e->state <= 2)                        if(e->socket >= 0)
                                &&(FD_ISSET(e->socket, &readset)) ) 
                         {                          {
                                Process_upnphttp(e);                                if(FD_ISSET(e->socket, &readset) ||
                                    FD_ISSET(e->socket, &writeset))
                                 {
                                         Process_upnphttp(e);
                                 }
                         }                          }
                 }                  }
                 /* process incoming HTTP connections */                  /* process incoming HTTP connections */
Line 1549  main(int argc, char * * argv) Line 1778  main(int argc, char * * argv)
                         shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);                          shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
                         if(shttp<0)                          if(shttp<0)
                         {                          {
                                syslog(LOG_ERR, "accept(http): %m");                                /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
                                 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
                                         syslog(LOG_ERR, "accept(http): %m");
                         }                          }
                         else                          else
                         {                          {
Line 1558  main(int argc, char * * argv) Line 1789  main(int argc, char * * argv)
   
                                 sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));                                  sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
                                 syslog(LOG_INFO, "HTTP connection from %s", addr_str);                                  syslog(LOG_INFO, "HTTP connection from %s", addr_str);
                                /*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {                                if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
                                        syslog(LOG_ERR, "fcntl F_SETFL, O_NONBLOCK"); 
                                }*/ 
                                /* Create a new upnphttp object and add it to 
                                 * the active upnphttp object list */ 
                                tmp = New_upnphttp(shttp); 
                                if(tmp) 
                                 {                                  {
#ifdef ENABLE_IPV6                                        /* The peer is not a LAN ! */
                                        if(clientname.ss_family == AF_INET)                                        syslog(LOG_WARNING,
                                                "HTTP peer %s is not from a LAN, closing the connection",
                                                addr_str);
                                         close(shttp);
                                 }
                                 else
                                 {
                                         /* Create a new upnphttp object and add it to
                                          * the active upnphttp object list */
                                         tmp = New_upnphttp(shttp);
                                         if(tmp)
                                         {                                          {
                                                tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;#ifdef ENABLE_IPV6
                                        }                                                if(clientname.ss_family == AF_INET)
                                        else if(clientname.ss_family == AF_INET6) 
                                        { 
                                                struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; 
                                                if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) 
                                                 {                                                  {
                                                        memcpy(&tmp->clientaddr,                                                        tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
                                                               &addr->sin6_addr.s6_addr[12], 
                                                               4); 
                                                 }                                                  }
                                                else                                                else if(clientname.ss_family == AF_INET6)
                                                 {                                                  {
                                                        tmp->ipv6 = 1;                                                        struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
                                                        memcpy(&tmp->clientaddr_v6,                                                        if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
                                                               &addr->sin6_addr,                                                        {
                                                               sizeof(struct in6_addr));                                                                memcpy(&tmp->clientaddr,
                                                                        &addr->sin6_addr.s6_addr[12],
                                                                        4);
                                                         }
                                                         else
                                                         {
                                                                 tmp->ipv6 = 1;
                                                                 memcpy(&tmp->clientaddr_v6,
                                                                        &addr->sin6_addr,
                                                                        sizeof(struct in6_addr));
                                                         }
                                                 }                                                  }
                                         }  
 #else  #else
                                        tmp->clientaddr = clientname.sin_addr;                                                tmp->clientaddr = clientname.sin_addr;
 #endif  #endif
                                        LIST_INSERT_HEAD(&upnphttphead, tmp, entries);                                                LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
                                         }
                                         else
                                         {
                                                 syslog(LOG_ERR, "New_upnphttp() failed");
                                                 close(shttp);
                                         }
                                 }                                  }
                                 else  
                                 {  
                                         syslog(LOG_ERR, "New_upnphttp() failed");  
                                         close(shttp);  
                                 }  
                         }                          }
                 }                  }
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
Line 1612  main(int argc, char * * argv) Line 1851  main(int argc, char * * argv)
                 for(e = upnphttphead.lh_first; e != NULL; )                  for(e = upnphttphead.lh_first; e != NULL; )
                 {                  {
                         next = e->entries.le_next;                          next = e->entries.le_next;
                        if(e->state >= 100)                        if(e->state >= EToDelete)
                         {                          {
                                 LIST_REMOVE(e, entries);                                  LIST_REMOVE(e, entries);
                                 Delete_upnphttp(e);                                  Delete_upnphttp(e);
Line 1635  shutdown: Line 1874  shutdown:
         if (shttpl >= 0) close(shttpl);          if (shttpl >= 0) close(shttpl);
 #ifdef ENABLE_IPV6  #ifdef ENABLE_IPV6
         if (sudpv6 >= 0) close(sudpv6);          if (sudpv6 >= 0) close(sudpv6);
         //if (shttplv6 >= 0) close(shttplv6);  
 #endif  #endif
 #ifdef USE_IFACEWATCHER  #ifdef USE_IFACEWATCHER
         if(sifacewatcher >= 0) close(sifacewatcher);          if(sifacewatcher >= 0) close(sifacewatcher);
Line 1660  shutdown: Line 1898  shutdown:
                 }                  }
         }          }
 #endif  #endif
        
        /*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/ 
         if (GETFLAG(ENABLEUPNPMASK))          if (GETFLAG(ENABLEUPNPMASK))
         {          {
   #ifndef ENABLE_IPV6
                 if(SendSSDPGoodbye(snotify, addr_count) < 0)                  if(SendSSDPGoodbye(snotify, addr_count) < 0)
   #else
                   if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
   #endif
                 {                  {
                         syslog(LOG_ERR, "Failed to broadcast good-bye notifications");                          syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
                 }                  }
                for(i=0; i<addr_count; i++)#ifndef ENABLE_IPV6
                 for(i = 0; i < addr_count; i++)
 #else
                 for(i = 0; i < addr_count * 2; i++)
 #endif
                         close(snotify[i]);                          close(snotify[i]);
         }          }
   
        if(unlink(pidfilename) < 0)        if(pidfilename && (unlink(pidfilename) < 0))
         {          {
                 syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);                  syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
         }          }
Line 1689  shutdown: Line 1934  shutdown:
         free(snatpmp);          free(snatpmp);
 #endif  #endif
         free(snotify);          free(snotify);
        closelog();             closelog();
 #ifndef DISABLE_CONFIG_FILE
         freeoptions();          freeoptions();
        #endif
 
         return 0;          return 0;
 }  }
   

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


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