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

version 1.1, 2012/02/21 23:16:02 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-2010 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 63 Line 67
 #include "natpmp.h"  #include "natpmp.h"
 #endif  #endif
 #include "commonrdr.h"  #include "commonrdr.h"
   #include "upnputils.h"
   #ifdef USE_IFACEWATCHER
   #include "ifacewatcher.h"
   #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 81  static struct nfq_handle *nfqHandle; Line 94  static struct nfq_handle *nfqHandle;
 static struct sockaddr_in ssdp;  static struct sockaddr_in ssdp;
   
 /* prototypes */  /* prototypes */
 void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port);  
 static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;  static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;
 int identify_ip_protocol (char *payload);  int identify_ip_protocol (char *payload);
 int get_udp_dst_port (char *payload);  int get_udp_dst_port (char *payload);
 #endif  #endif
   
   /* variables used by signals */
   static volatile sig_atomic_t quitting = 0;
   volatile sig_atomic_t should_send_public_address_change_notif = 0;
   
 static int sudp = -1;  
   
 /* MAX_LAN_ADDR : maximum number of interfaces  
  * to listen to SSDP traffic */  
 /*#define MAX_LAN_ADDR (4)*/  
   
 static volatile int quitting = 0;  
 static volatile int 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. */
 static int  static int
Line 104  OpenAndConfHTTPSocket(unsigned short port) Line 110  OpenAndConfHTTPSocket(unsigned short port)
 {  {
         int s;          int s;
         int i = 1;          int i = 1;
   #ifdef ENABLE_IPV6
           struct sockaddr_in6 listenname;
   #else
         struct sockaddr_in listenname;          struct sockaddr_in listenname;
   #endif
           socklen_t listenname_len;
   
        if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)        if( (s = socket(
 #ifdef ENABLE_IPV6
                         PF_INET6,
 #else
                         PF_INET,
 #endif
                         SOCK_STREAM, 0)) < 0)
         {          {
                 syslog(LOG_ERR, "socket(http): %m");                  syslog(LOG_ERR, "socket(http): %m");
                 return -1;                  return -1;
Line 116  OpenAndConfHTTPSocket(unsigned short port) Line 133  OpenAndConfHTTPSocket(unsigned short port)
         {          {
                 syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");                  syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
         }          }
   #if 0
           /* enable this to force IPV6 only for IPV6 socket.
            * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
           if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0)
           {
                   syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m");
           }
   #endif
   
        memset(&listenname, 0, sizeof(struct sockaddr_in));        if(!set_non_blocking(s))
         {
                 syslog(LOG_WARNING, "set_non_blocking(http): %m");
         }
 
 #ifdef ENABLE_IPV6
         memset(&listenname, 0, sizeof(struct sockaddr_in6));
         listenname.sin6_family = AF_INET6;
         listenname.sin6_port = htons(port);
         listenname.sin6_addr = in6addr_any;
         listenname_len =  sizeof(struct sockaddr_in6);
 #else
         listenname.sin_family = AF_INET;          listenname.sin_family = AF_INET;
         listenname.sin_port = htons(port);          listenname.sin_port = htons(port);
         listenname.sin_addr.s_addr = htonl(INADDR_ANY);          listenname.sin_addr.s_addr = htonl(INADDR_ANY);
           listenname_len =  sizeof(struct sockaddr_in);
   #endif
   
        if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)        if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
         {          {
                 syslog(LOG_ERR, "bind(http): %m");                  syslog(LOG_ERR, "bind(http): %m");
                 close(s);                  close(s);
                 return -1;                  return -1;
         }          }
   
        if(listen(s, 6) < 0)        if(listen(s, 5) < 0)
         {          {
                 syslog(LOG_ERR, "listen(http): %m");                  syslog(LOG_ERR, "listen(http): %m");
                 close(s);                  close(s);
Line 169  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 232  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 248  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;
                                         sendername.sin_addr.s_addr = iph->ip_src.s_addr;                                          sendername.sin_addr.s_addr = iph->ip_src.s_addr;
   
                                         /* printf("pkt found %s\n",dd);*/                                          /* printf("pkt found %s\n",dd);*/
                                        ProcessSSDPData (sudp, dd, sendername, size - x, (unsigned short) 5555);                                        ProcessSSDPData (sudp, dd, size - x,
                                                          &sendername, (unsigned short) 5555);
                                 }                                  }
                         }                          }
                 }                  }
                
                 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 344  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 359  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 378  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 396  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 472  set_startup_time(int sysuptime) Line 525  set_startup_time(int sysuptime)
 struct runtime_vars {  struct runtime_vars {
         /* LAN IP addresses for SSDP traffic and HTTP */          /* LAN IP addresses for SSDP traffic and HTTP */
         /* moved to global vars */          /* moved to global vars */
         /*int n_lan_addr;*/  
         /*struct lan_addr_s lan_addr[MAX_LAN_ADDR];*/  
         int port;       /* HTTP Port */          int port;       /* HTTP Port */
         int notify_interval;    /* seconds between SSDP announces */          int notify_interval;    /* seconds between SSDP announces */
         /* unused rules cleaning related variables : */          /* unused rules cleaning related variables : */
Line 483  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 539  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 557  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_addr2;
   
         /* only print usage if -h is used */          /* only print usage if -h is used */
         for(i=1; i<argc; i++)          for(i=1; i<argc; i++)
Line 570  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 580  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 */
   
        /*v->n_lan_addr = 0;*/        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 600  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 611  init(int argc, char * * argv, struct runtime_vars * v) Line 713  init(int argc, char * * argv, struct runtime_vars * v)
                                 use_ext_ip_addr = ary_options[i].value;                                  use_ext_ip_addr = ary_options[i].value;
                                 break;                                  break;
                         case UPNPLISTENING_IP:                          case UPNPLISTENING_IP:
                                if(n_lan_addr < MAX_LAN_ADDR)/* if(v->n_lan_addr < MAX_LAN_ADDR)*/                                lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
                                 if (lan_addr == NULL)
                                 {                                  {
                                        /*if(parselanaddr(&v->lan_addr[v->n_lan_addr],*/                                        fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
                                        if(parselanaddr(&lan_addr[n_lan_addr],                                        break;
                                                     ary_options[i].value) == 0) 
                                                n_lan_addr++; /*v->n_lan_addr++; */ 
                                 }                                  }
                                else                                if(parselanaddr(lan_addr, ary_options[i].value) != 0)
                                 {                                  {
                                        fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",                                        fprintf(stderr, "can't parse \"%s\" as valid lan address\n", ary_options[i].value);
                                            MAX_LAN_ADDR, ary_options[i].value);                                        free(lan_addr);
                                         break;
                                 }                                  }
                                   LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
                                 break;                                  break;
                         case UPNPPORT:                          case UPNPPORT:
                                 v->port = atoi(ary_options[i].value);                                  v->port = atoi(ary_options[i].value);
Line 636  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 651  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 662  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 674  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 719  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 741  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 774  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 854  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)
                         {                          {
                                 int address_already_there = 0;  
                                 int j;  
                                 i++;                                  i++;
                                for(j=0; j<n_lan_addr; j++)                                lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
                                 if (lan_addr == NULL)
                                 {                                  {
                                        struct lan_addr_s tmpaddr;                                        fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
                                        parselanaddr(&tmpaddr, argv[i]);                                        break;
                                        if(0 == strcmp(lan_addr[j].str, tmpaddr.str)) 
                                                address_already_there = 1; 
                                 }                                  }
                                if(address_already_there)                                if(parselanaddr(lan_addr, argv[i]) != 0)
                                 {
                                         fprintf(stderr, "can't parse \"%s\" as valid lan address\n", argv[i]);
                                         free(lan_addr);
                                         break;                                          break;
                                if(n_lan_addr < MAX_LAN_ADDR)                                }
                                 /* 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(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)                                        if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
                                                n_lan_addr++;                                                break;
                                 }                                  }
                                else                                if (lan_addr2 == NULL)
                                         LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
                         }
                         else
                                 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, "Too many listening ips (max: %d), ignoring %s\n",                                        fprintf(stderr, "memory allocation error for listen address storage\n");
                                            MAX_LAN_ADDR, argv[i]);                                        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                          else
                                   fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
   #endif
                           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]);                                  fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                         break;                          break;
                 case 'f':                  case 'f':
Line 889  init(int argc, char * * argv, struct runtime_vars * v) Line 1074  init(int argc, char * * argv, struct runtime_vars * v)
                         fprintf(stderr, "Unknown option: %s\n", argv[i]);                          fprintf(stderr, "Unknown option: %s\n", argv[i]);
                 }                  }
         }          }
        if(!ext_if_name || (n_lan_addr==0))        if(!ext_if_name || !lan_addrs.lh_first)
         {          {
                 /* bad configuration */                  /* bad configuration */
                 goto print_usage;                  goto print_usage;
Line 929  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 942  init(int argc, char * * argv, struct runtime_vars * v) Line 1127  init(int argc, char * * argv, struct runtime_vars * v)
         else          else
         {          {
                 snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,                  snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
                         "http://%s/", lan_addr[0].str);                         "http://%s/", lan_addrs.lh_first->str);
                         /*"http://%s:%d/", lan_addr[0].str, 80);*/                         /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
         }          }
   
         /* set signal handler */          /* set signal handler */
         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 976  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 988  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 1023  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 1037  int Line 1249  int
 main(int argc, char * * argv)  main(int argc, char * * argv)
 {  {
         int i;          int i;
        int shttpl = -1;        int shttpl = -1;        /* socket for HTTP */
         int sudp = -1;          /* IP v4 socket for receiving SSDP */
 #ifdef ENABLE_IPV6
         int sudpv6 = -1;        /* IP v6 socket for receiving SSDP */
 #endif
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
        int snatpmp[MAX_LAN_ADDR];        int * snatpmp = NULL;
 #endif
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
         int nfqh = -1;          int nfqh = -1;
 #endif  #endif
   #ifdef USE_IFACEWATCHER
           int sifacewatcher = -1;
 #endif  #endif
        int snotify[MAX_LAN_ADDR];
         int * snotify = NULL;
         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 1064  main(int argc, char * * argv) Line 1283  main(int argc, char * * argv)
         /* variables used for the unused-rule cleanup process */          /* variables used for the unused-rule cleanup process */
         struct rule_state * rule_list = 0;          struct rule_state * rule_list = 0;
         struct timeval checktime = {0, 0};          struct timeval checktime = {0, 0};
        syslog(LOG_INFO, "SNet version started");        struct lan_addr_s * lan_addr;
#ifdef ENABLE_6FC_SERVICE
        unsigned int next_pinhole_ts;
        memset(snotify, 0, sizeof(snotify)); 
#ifdef ENABLE_NATPMP 
        for(i = 0; i < MAX_LAN_ADDR; i++) 
                snatpmp[i] = -1; 
 #endif  #endif
   
         if(init(argc, argv, &v) != 0)          if(init(argc, argv, &v) != 0)
                 return 1;                  return 1;
           /* count lan addrs */
           addr_count = 0;
           for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
                   addr_count++;
           if(addr_count > 0) {
   #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
           if(addr_count > 0) {
                   snatpmp = malloc(addr_count * sizeof(int));
                   for(i = 0; i < addr_count; i++)
                           snatpmp[i] = -1;
           }
   #endif
   
         LIST_INIT(&upnphttphead);          LIST_INIT(&upnphttphead);
 #ifdef USE_MINIUPNPDCTL  #ifdef USE_MINIUPNPDCTL
Line 1089  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 1109  main(int argc, char * * argv) Line 1353  main(int argc, char * * argv)
                         v.port = ntohs(sockinfo.sin_port);                          v.port = ntohs(sockinfo.sin_port);
                 }                  }
                 syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);                  syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
   #ifdef ENABLE_IPV6
                   if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
                           syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
                                  ipv6_addr_for_http_with_brackets);
                   } else {
                           memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
                           syslog(LOG_WARNING, "no HTTP IPv6 address");
                   }
   #endif
   
                 /* open socket for SSDP connections */                  /* open socket for SSDP connections */
                sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);                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_addr[0].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;
                         }                          }
                 }                  }
   #ifdef ENABLE_IPV6
                   sudpv6 = OpenAndConfSSDPReceiveSocket(1);
                   if(sudpv6 < 0)
                   {
                           syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
                   }
   #endif
   
                 /* open socket for sending notifications */                  /* open socket for sending notifications */
                 if(OpenAndConfSSDPNotifySockets(snotify) < 0)                  if(OpenAndConfSSDPNotifySockets(snotify) < 0)
Line 1128  main(int argc, char * * argv) Line 1388  main(int argc, char * * argv)
                                 "messages. EXITING");                                  "messages. EXITING");
                         return 1;                          return 1;
                 }                  }
   
   #ifdef USE_IFACEWATCHER
                   /* open socket for kernel notifications about new network interfaces */
                   if (sudp >= 0)
                   {
                           sifacewatcher = OpenAndConfInterfaceWatchSocket();
                           if (sifacewatcher < 0)
                           {
                                   syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
                           }
                   }
   #endif
         }          }
   
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
Line 1141  main(int argc, char * * argv) Line 1413  main(int argc, char * * argv)
                         syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",                          syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
                                NATPMP_PORT);                                 NATPMP_PORT);
                 }                  }
   #if 0
                 ScanNATPMPforExpiration();                  ScanNATPMPforExpiration();
   #endif
         }          }
 #endif  #endif
   
Line 1161  main(int argc, char * * argv) Line 1435  main(int argc, char * * argv)
                 }                  }
         }          }
 #endif  #endif
   
         /* main loop */          /* main loop */
         while(!quitting)          while(!quitting)
         {          {
Line 1168  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 */
                 if(should_send_public_address_change_notif)
                 {
                         syslog(LOG_DEBUG, "should send external iface address change notification(s)");
 #ifdef ENABLE_NATPMP
                         if(GETFLAG(ENABLENATPMPMASK))
                                 SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
 #endif
 #ifdef ENABLE_EVENTS
                         if(GETFLAG(ENABLEUPNPMASK))
                         {
                                 upnp_event_var_change_notify(EWanIPC);
                         }
 #endif
                         should_send_public_address_change_notif = 0;
                 }
                 /* Check if we need to send SSDP NOTIFY messages and do it if                  /* Check if we need to send SSDP NOTIFY messages and do it if
                  * needed */                   * needed */
                 if(gettimeofday(&timeofday, 0) < 0)                  if(gettimeofday(&timeofday, 0) < 0)
Line 1221  main(int argc, char * * argv) Line 1512  main(int argc, char * * argv)
                         }                          }
                         memcpy(&checktime, &timeofday, sizeof(struct timeval));                          memcpy(&checktime, &timeofday, sizeof(struct timeval));
                 }                  }
                   /* Remove expired port mappings, based on UPnP IGD LeaseDuration
                    * or NAT-PMP lifetime) */
                   if(nextruletoclean_timestamp
                     && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
                   {
                           syslog(LOG_DEBUG, "cleaning expired Port Mappings");
                           get_upnp_rules_state_list(0);
                   }
                   if(nextruletoclean_timestamp
                     && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
                   {
                           timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
                           timeout.tv_usec = 0;
                           syslog(LOG_DEBUG, "setting timeout to %u sec",
                                  (unsigned)timeout.tv_sec);
                   }
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
   #if 0
                 /* Remove expired NAT-PMP mappings */                  /* Remove expired NAT-PMP mappings */
                while( nextnatpmptoclean_timestamp && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))                while(nextnatpmptoclean_timestamp
                      && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))
                 {                  {
                         /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/                          /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
                         if(CleanExpiredNATPMP() < 0) {                          if(CleanExpiredNATPMP() < 0) {
Line 1231  main(int argc, char * * argv) Line 1540  main(int argc, char * * argv)
                                 break;                                  break;
                         }                          }
                 }                  }
                if(nextnatpmptoclean_timestamp && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))                if(nextnatpmptoclean_timestamp
                   && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))
                 {                  {
                        /*syslog(LOG_DEBUG, "setting timeout to %d sec", nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/                        /*syslog(LOG_DEBUG, "setting timeout to %d sec",
#ifdef ENABLE_NFQUEUE                               nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
                if (nfqh >= 0)                         timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;
                {                        timeout.tv_usec = 0;
                        FD_SET(nfqh, &readset); 
                        max_fd = MAX( max_fd, nfqh); 
                 }                  }
 #endif  #endif
#endif
                        timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;#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;                          timeout.tv_usec = 0;
                 }                  }
 #endif  #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);
   #ifdef USE_IFACEWATCHER
                           if (sifacewatcher >= 0)
                           {
                                   FD_SET(sifacewatcher, &readset);
                                   max_fd = MAX(max_fd, sifacewatcher);
                           }
   #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);
                 }                  }
   #ifdef ENABLE_IPV6
                   if (sudpv6 >= 0)
                   {
                           FD_SET(sudpv6, &readset);
                           max_fd = MAX( max_fd, sudpv6);
                   }
   #endif
   
   #ifdef ENABLE_NFQUEUE
                   if (nfqh >= 0)
                   {
                           FD_SET(nfqh, &readset);
                           max_fd = MAX( max_fd, nfqh);
                   }
   #endif
   
                 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 1280  main(int argc, char * * argv) Line 1621  main(int argc, char * * argv)
                 }                  }
 #endif  #endif
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
                for(i=0; i<n_lan_addr; i++) {                for(i=0; i<addr_count; i++) {
                         if(snatpmp[i] >= 0) {                          if(snatpmp[i] >= 0) {
                                 FD_SET(snatpmp[i], &readset);                                  FD_SET(snatpmp[i], &readset);
                                 max_fd = MAX( max_fd, snatpmp[i]);                                  max_fd = MAX( max_fd, snatpmp[i]);
Line 1292  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 1303  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 1332  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 1363  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 1377  main(int argc, char * * argv) Line 1723  main(int argc, char * * argv)
 #endif  #endif
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
                 /* process NAT-PMP packets */                  /* process NAT-PMP packets */
                for(i=0; i<n_lan_addr; i++)                for(i=0; i<addr_count; i++)
                 {                  {
                         if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))                          if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
                         {                          {
Line 1391  main(int argc, char * * argv) Line 1737  main(int argc, char * * argv)
                         /*syslog(LOG_INFO, "Received UDP Packet");*/                          /*syslog(LOG_INFO, "Received UDP Packet");*/
                         ProcessSSDPRequest(sudp, (unsigned short)v.port);                          ProcessSSDPRequest(sudp, (unsigned short)v.port);
                 }                  }
   #ifdef ENABLE_IPV6
                   if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
                   {
                           syslog(LOG_INFO, "Received UDP Packet (IPv6)");
                           ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
                   }
   #endif
   #ifdef USE_IFACEWATCHER
                   /* process kernel notifications */
                   if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
                           ProcessInterfaceWatchNotify(sifacewatcher);
   #endif
   
                 /* process active HTTP connections */                  /* process active HTTP connections */
                 /* 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 1406  main(int argc, char * * argv) Line 1768  main(int argc, char * * argv)
                 {                  {
                         int shttp;                          int shttp;
                         socklen_t clientnamelen;                          socklen_t clientnamelen;
   #ifdef ENABLE_IPV6
                           struct sockaddr_storage clientname;
                           clientnamelen = sizeof(struct sockaddr_storage);
   #else
                         struct sockaddr_in clientname;                          struct sockaddr_in clientname;
                         clientnamelen = sizeof(struct sockaddr_in);                          clientnamelen = sizeof(struct sockaddr_in);
   #endif
                         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
                         {                          {
                                 struct upnphttp * tmp = 0;                                  struct upnphttp * tmp = 0;
                                syslog(LOG_INFO, "HTTP connection from %s:%d",                                char addr_str[64];
                                        inet_ntoa(clientname.sin_addr),
                                        ntohs(clientname.sin_port) );                                sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
                                /*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {                                syslog(LOG_INFO, "HTTP connection from %s", addr_str);
                                        syslog(LOG_ERR, "fcntl F_SETFL, O_NONBLOCK");                                if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
                                }*/                                {
                                         /* The peer is not a LAN ! */
                                         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)
                                         {
 #ifdef ENABLE_IPV6
                                                 if(clientname.ss_family == AF_INET)
                                                 {
                                                         tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
                                                 }
                                                 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,
                                                                        &addr->sin6_addr.s6_addr[12],
                                                                        4);
                                                         }
                                                         else
                                                         {
                                                                 tmp->ipv6 = 1;
                                                                 memcpy(&tmp->clientaddr_v6,
                                                                        &addr->sin6_addr,
                                                                        sizeof(struct in6_addr));
                                                         }
                                                 }
 #else
                                                 tmp->clientaddr = clientname.sin_addr;
 #endif
                                                 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
                                         }
                                         else
                                         {
                                                 syslog(LOG_ERR, "New_upnphttp() failed");
                                                 close(shttp);
                                         }
                                 }
                         }
                 }
 #ifdef ENABLE_NFQUEUE  #ifdef ENABLE_NFQUEUE
                 /* process NFQ packets */                  /* process NFQ packets */
                 if(nfqh >= 0 && FD_ISSET(nfqh, &readset))                  if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
Line 1430  main(int argc, char * * argv) Line 1847  main(int argc, char * * argv)
                         ProcessNFQUEUE(nfqh);                          ProcessNFQUEUE(nfqh);
                 }                  }
 #endif  #endif
                                 /* Create a new upnphttp object and add it to  
                                  * the active upnphttp object list */  
                                 tmp = New_upnphttp(shttp);  
                                 if(tmp)  
                                 {  
                                         tmp->clientaddr = clientname.sin_addr;  
                                         LIST_INSERT_HEAD(&upnphttphead, tmp, entries);  
                                 }  
                                 else  
                                 {  
                                         syslog(LOG_ERR, "New_upnphttp() failed");  
                                         close(shttp);  
                                 }  
                         }  
                 }  
                 /* delete finished HTTP connections */                  /* delete finished HTTP connections */
                 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 1457  main(int argc, char * * argv) Line 1859  main(int argc, char * * argv)
                         e = next;                          e = next;
                 }                  }
   
                 /* send public address change notifications */  
                 if(should_send_public_address_change_notif)  
                 {  
 #ifdef ENABLE_NATPMP  
                         if(GETFLAG(ENABLENATPMPMASK))  
                                 SendNATPMPPublicAddressChangeNotification(snatpmp/*snotify*/, n_lan_addr);  
 #endif  
 #ifdef ENABLE_EVENTS  
                         if(GETFLAG(ENABLEUPNPMASK))  
                         {  
                                 upnp_event_var_change_notify(EWanIPC);  
                         }  
 #endif  
                         should_send_public_address_change_notif = 0;  
                 }  
         }       /* end of main loop */          }       /* end of main loop */
   
 shutdown:  shutdown:
Line 1485  shutdown: Line 1872  shutdown:
   
         if (sudp >= 0) close(sudp);          if (sudp >= 0) close(sudp);
         if (shttpl >= 0) close(shttpl);          if (shttpl >= 0) close(shttpl);
   #ifdef ENABLE_IPV6
           if (sudpv6 >= 0) close(sudpv6);
   #endif
   #ifdef USE_IFACEWATCHER
           if(sifacewatcher >= 0) close(sifacewatcher);
   #endif
 #ifdef ENABLE_NATPMP  #ifdef ENABLE_NATPMP
        for(i=0; i<n_lan_addr; i++) {        for(i=0; i<addr_count; i++) {
                 if(snatpmp[i]>=0)                  if(snatpmp[i]>=0)
                 {                  {
                         close(snatpmp[i]);                          close(snatpmp[i]);
Line 1505  shutdown: Line 1898  shutdown:
                 }                  }
         }          }
 #endif  #endif
        
        /*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/ 
         if (GETFLAG(ENABLEUPNPMASK))          if (GETFLAG(ENABLEUPNPMASK))
         {          {
                if(SendSSDPGoodbye(snotify, n_lan_addr) < 0)#ifndef ENABLE_IPV6
                 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<n_lan_addr; i++)/* for(i=0; i<v.n_lan_addr; 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);
         }          }
   
        closelog();             /* delete lists */
         while(lan_addrs.lh_first != NULL)
         {
                 lan_addr = lan_addrs.lh_first;
                 LIST_REMOVE(lan_addrs.lh_first, list);
                 free(lan_addr);
         }
 
 #ifdef ENABLE_NATPMP
         free(snatpmp);
 #endif
         free(snotify);
         closelog();
 #ifndef DISABLE_CONFIG_FILE
         freeoptions();          freeoptions();
        #endif
 
         return 0;          return 0;
 }  }
   

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


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