Diff for /embedaddon/miniupnpd/upnpredirect.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 23:16:02 version 1.1.1.2, 2012/05/29 12:55:57
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-2009 Thomas Bernard  * (c) 2006-2011 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 59  proto_atoi(const char * protocol) Line 59  proto_atoi(const char * protocol)
 }  }
   
 #ifdef ENABLE_LEASEFILE  #ifdef ENABLE_LEASEFILE
static int lease_file_add( unsigned short eport, const char * iaddr, unsigned short iport, int proto, const char * desc)static int
 lease_file_add(unsigned short eport,
                const char * iaddr,
                unsigned short iport,
                int proto,
                const char * desc,
                unsigned int timestamp)
 {  {
         FILE * fd;          FILE * fd;
   
Line 71  static int lease_file_add( unsigned short eport, const Line 77  static int lease_file_add( unsigned short eport, const
                 return -1;                  return -1;
         }          }
   
        fprintf( fd, "%s:%hu:%s:%hu:%s\n",        fprintf(fd, "%s:%hu:%s:%hu:%u:%s\n",
                 ((proto==IPPROTO_TCP)?"TCP":"UDP"), eport, iaddr, iport, desc);                ((proto==IPPROTO_TCP)?"TCP":"UDP"), eport, iaddr, iport,
                 timestamp, desc);
         fclose(fd);          fclose(fd);
                   
         return 0;          return 0;
 }  }
   
static int lease_file_remove( unsigned short eport, int proto)static int
 lease_file_remove(unsigned short eport, int proto)
 {  {
         FILE* fd, *fdt;          FILE* fd, *fdt;
         int tmp;          int tmp;
Line 116  static int lease_file_remove( unsigned short eport, in Line 124  static int lease_file_remove( unsigned short eport, in
         fdt = fdopen(tmp, "a");          fdt = fdopen(tmp, "a");
   
         buf[sizeof(buf)-1] = 0;          buf[sizeof(buf)-1] = 0;
        while( fgets( buf, sizeof(buf)-1, fd) != NULL) {        while( fgets(buf, sizeof(buf)-1, fd) != NULL) {
                 buf_size = strlen(buf);                  buf_size = strlen(buf);
   
                if (buf_size < str_size || strncmp( str, buf, str_size)!=0) {                if (buf_size < str_size || strncmp(str, buf, str_size)!=0) {
                         fwrite(buf, buf_size, 1, fdt);                          fwrite(buf, buf_size, 1, fdt);
                 }                  }
         }          }
         fclose(fdt);          fclose(fdt);
         fclose(fd);          fclose(fd);
                   
        if (rename( tmpfilename, lease_file) < 0) {        if (rename(tmpfilename, lease_file) < 0) {
                 syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file);                  syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file);
                remove( tmpfilename);                remove(tmpfilename);
         }          }
                   
         return 0;          return 0;
Line 146  int reload_from_lease_file() Line 154  int reload_from_lease_file()
         char * proto;          char * proto;
         char * iaddr;          char * iaddr;
         char * desc;          char * desc;
           char * rhost;
           unsigned int leaseduration;
           unsigned int timestamp;
           time_t current_time;
         char line[128];          char line[128];
         int r;          int r;
   
Line 159  int reload_from_lease_file() Line 171  int reload_from_lease_file()
                 syslog(LOG_WARNING, "could not unlink file %s : %m", lease_file);                  syslog(LOG_WARNING, "could not unlink file %s : %m", lease_file);
         }          }
   
           current_time = time(NULL);
         while(fgets(line, sizeof(line), fd)) {          while(fgets(line, sizeof(line), fd)) {
                 syslog(LOG_DEBUG, "parsing lease file line '%s'", line);                  syslog(LOG_DEBUG, "parsing lease file line '%s'", line);
                 proto = line;                  proto = line;
Line 181  int reload_from_lease_file() Line 194  int reload_from_lease_file()
                         continue;                          continue;
                 }                  }
                 *(p++) = '\0';                  *(p++) = '\0';
                   timestamp = (unsigned int)atoi(p);
                   p = strchr(p, ':');
                   if(!p) {
                           syslog(LOG_ERR, "unrecognized data in lease file");
                           continue;
                   }
                   *(p++) = '\0';
                 desc = strchr(p, ':');                  desc = strchr(p, ':');
                 if(!desc) {                  if(!desc) {
                         syslog(LOG_ERR, "unrecognized data in lease file");                          syslog(LOG_ERR, "unrecognized data in lease file");
Line 197  int reload_from_lease_file() Line 217  int reload_from_lease_file()
                 while(isspace(*p) && (p > desc))                  while(isspace(*p) && (p > desc))
                         *(p--) = '\0';                          *(p--) = '\0';
   
                r = upnp_redirect(eport, iaddr, iport, proto, desc);                if(timestamp > 0) {
                         if(timestamp <= current_time) {
                                 syslog(LOG_NOTICE, "already expired lease in lease file");
                                 continue;
                         } else {
                                 leaseduration = current_time - timestamp;
                         }
                 } else {
                         leaseduration = 0;      /* default value */
                 }
                 rhost = NULL;
                 r = upnp_redirect(rhost, eport, iaddr, iport, proto, desc, leaseduration);
                 if(r == -1) {                  if(r == -1) {
                         syslog(LOG_ERR, "Failed to redirect %hu -> %s:%hu protocol %s",                          syslog(LOG_ERR, "Failed to redirect %hu -> %s:%hu protocol %s",
                                eport, iaddr, iport, proto);                                 eport, iaddr, iport, proto);
                 } else if(r == -2) {                  } else if(r == -2) {
                         /* Add the redirection again to the lease file */                          /* Add the redirection again to the lease file */
                        lease_file_add(eport, iaddr, iport, proto_atoi(proto), desc);                        lease_file_add(eport, iaddr, iport, proto_atoi(proto),
                                        desc, timestamp);
                 }                  }
         }          }
         fclose(fd);          fclose(fd);
Line 221  int reload_from_lease_file() Line 253  int reload_from_lease_file()
  *          -3 permission check failed   *          -3 permission check failed
  */   */
 int  int
upnp_redirect(unsigned short eport, upnp_redirect(const char * rhost, unsigned short eport, 
               const char * iaddr, unsigned short iport,                const char * iaddr, unsigned short iport,
              const char * protocol, const char * desc)              const char * protocol, const char * desc,
               unsigned int leaseduration)
 {  {
         int proto, r;          int proto, r;
         char iaddr_old[32];          char iaddr_old[32];
         unsigned short iport_old;          unsigned short iport_old;
         struct in_addr address;          struct in_addr address;
           unsigned int timestamp;
   
         proto = proto_atoi(protocol);          proto = proto_atoi(protocol);
         if(inet_aton(iaddr, &address) < 0) {          if(inet_aton(iaddr, &address) < 0) {
                 syslog(LOG_ERR, "inet_aton(%s) : %m", iaddr);                  syslog(LOG_ERR, "inet_aton(%s) : %m", iaddr);
Line 242  upnp_redirect(unsigned short eport,  Line 277  upnp_redirect(unsigned short eport, 
                 return -3;                  return -3;
         }          }
         r = get_redirect_rule(ext_if_name, eport, proto,          r = get_redirect_rule(ext_if_name, eport, proto,
                              iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0, 0, 0);                              iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0,
                               0, 0,
                               &timestamp, 0, 0);
         if(r == 0) {          if(r == 0) {
                 /* if existing redirect rule matches redirect request return success                  /* if existing redirect rule matches redirect request return success
                  * xbox 360 does not keep track of the port it redirects and will                   * xbox 360 does not keep track of the port it redirects and will
                  * redirect another port when receiving ConflictInMappingEntry */                   * redirect another port when receiving ConflictInMappingEntry */
                if(strcmp(iaddr,iaddr_old)==0 && iport==iport_old) {                if(strcmp(iaddr, iaddr_old)==0 && iport==iport_old) {
                         syslog(LOG_INFO, "ignoring redirect request as it matches existing redirect");                          syslog(LOG_INFO, "ignoring redirect request as it matches existing redirect");
                 } else {                  } else {
   
Line 256  upnp_redirect(unsigned short eport,  Line 293  upnp_redirect(unsigned short eport, 
                         return -2;                          return -2;
                 }                  }
         } else {          } else {
                   timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
                 syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",                  syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
                         eport, iaddr, iport, protocol, desc);                                             eport, iaddr, iport, protocol, desc);                   
                return upnp_redirect_internal(eport, iaddr, iport, proto, desc);                return upnp_redirect_internal(rhost, eport, iaddr, iport, proto,
                                               desc, timestamp);
         }          }
   
         return 0;          return 0;
 }  }
   
 int  int
upnp_redirect_internal(unsigned short eport,upnp_redirect_internal(const char * rhost, unsigned short eport,
                        const char * iaddr, unsigned short iport,                         const char * iaddr, unsigned short iport,
                       int proto, const char * desc)                       int proto, const char * desc,
                        unsigned int timestamp)
 {  {
         /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",          /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
                 eport, iaddr, iport, protocol, desc);                   */                  eport, iaddr, iport, protocol, desc);                   */
        if(add_redirect_rule2(ext_if_name, eport, iaddr, iport, proto, desc) < 0) {        if(add_redirect_rule2(ext_if_name, rhost, eport, iaddr, iport, proto,
                               desc, timestamp) < 0) {
                 return -1;                  return -1;
         }          }
   
 #ifdef ENABLE_LEASEFILE  #ifdef ENABLE_LEASEFILE
        lease_file_add( eport, iaddr, iport, proto, desc);        lease_file_add( eport, iaddr, iport, proto, desc, timestamp);
 #endif  #endif
 /*      syslog(LOG_INFO, "creating pass rule to %s:%hu protocol %s for: %s",  /*      syslog(LOG_INFO, "creating pass rule to %s:%hu protocol %s for: %s",
                 iaddr, iport, protocol, desc);*/                  iaddr, iport, protocol, desc);*/
        if(add_filter_rule2(ext_if_name, iaddr, eport, iport, proto, desc) < 0) {        if(add_filter_rule2(ext_if_name, rhost, iaddr, eport, iport, proto, desc) < 0) {
                 /* clean up the redirect rule */                  /* clean up the redirect rule */
 #if !defined(__linux__)  #if !defined(__linux__)
                 delete_redirect_rule(ext_if_name, eport, proto);                  delete_redirect_rule(ext_if_name, eport, proto);
 #endif  #endif
                 return -1;                  return -1;
         }          }
           if(timestamp > 0) {
                   if(!nextruletoclean_timestamp || (timestamp < nextruletoclean_timestamp))
                           nextruletoclean_timestamp = timestamp;
           }
 #ifdef ENABLE_EVENTS  #ifdef ENABLE_EVENTS
           /* the number of port mappings changed, we must
            * inform the subscribers */
         upnp_event_var_change_notify(EWanIPC);          upnp_event_var_change_notify(EWanIPC);
 #endif  #endif
         return 0;          return 0;
Line 295  upnp_redirect_internal(unsigned short eport, Line 342  upnp_redirect_internal(unsigned short eport,
   
   
   
   /* Firewall independant code which call the FW dependant code. */
 int  int
 upnp_get_redirection_infos(unsigned short eport, const char * protocol,  upnp_get_redirection_infos(unsigned short eport, const char * protocol,
                            unsigned short * iport,                             unsigned short * iport,
                            char * iaddr, int iaddrlen,                             char * iaddr, int iaddrlen,
                           char * desc, int desclen)                           char * desc, int desclen,
                            char * rhost, int rhostlen,
                            unsigned int * leaseduration)
 {  {
           int r;
           unsigned int timestamp;
           time_t current_time;
   
         if(desc && (desclen > 0))          if(desc && (desclen > 0))
                 desc[0] = '\0';                  desc[0] = '\0';
        return get_redirect_rule(ext_if_name, eport, proto_atoi(protocol),        if(rhost && (rhostlen > 0))
                                 iaddr, iaddrlen, iport, desc, desclen, 0, 0);                rhost[0] = '\0';
         r = get_redirect_rule(ext_if_name, eport, proto_atoi(protocol),
                               iaddr, iaddrlen, iport, desc, desclen,
                               rhost, rhostlen, &timestamp,
                               0, 0);
         if(r == 0 && timestamp > 0 && timestamp > (current_time = time(NULL))) {
                 *leaseduration = timestamp - current_time;
         } else {
                 *leaseduration = 0;
         }
         return r;
 }  }
   
 int  int
Line 312  upnp_get_redirection_infos_by_index(int index, Line 376  upnp_get_redirection_infos_by_index(int index,
                                     unsigned short * eport, char * protocol,                                      unsigned short * eport, char * protocol,
                                     unsigned short * iport,                                       unsigned short * iport, 
                                     char * iaddr, int iaddrlen,                                      char * iaddr, int iaddrlen,
                                    char * desc, int desclen)                                    char * desc, int desclen,
                                     char * rhost, int rhostlen,
                                     unsigned int * leaseduration)
 {  {
         /*char ifname[IFNAMSIZ];*/          /*char ifname[IFNAMSIZ];*/
         int proto = 0;          int proto = 0;
           unsigned int timestamp;
           time_t current_time;
   
         if(desc && (desclen > 0))          if(desc && (desclen > 0))
                 desc[0] = '\0';                  desc[0] = '\0';
           if(rhost && (rhost > 0))
                   rhost[0] = '\0';
         if(get_redirect_rule_by_index(index, 0/*ifname*/, eport, iaddr, iaddrlen,          if(get_redirect_rule_by_index(index, 0/*ifname*/, eport, iaddr, iaddrlen,
                                      iport, &proto, desc, desclen, 0, 0) < 0)                                      iport, &proto, desc, desclen,
                                       rhost, rhostlen, &timestamp,
                                       0, 0) < 0)
                 return -1;                  return -1;
         else          else
         {          {
                   current_time = time(NULL);
                   *leaseduration = (timestamp > current_time)
                                    ? (timestamp - current_time)
                                    : 0;
                 if(proto == IPPROTO_TCP)                  if(proto == IPPROTO_TCP)
                         memcpy(protocol, "TCP", 4);                          memcpy(protocol, "TCP", 4);
                 else                  else
Line 332  upnp_get_redirection_infos_by_index(int index, Line 408  upnp_get_redirection_infos_by_index(int index,
         }          }
 }  }
   
   /* called from natpmp.c too */
 int  int
 _upnp_delete_redir(unsigned short eport, int proto)  _upnp_delete_redir(unsigned short eport, int proto)
 {  {
Line 360  upnp_delete_redirection(unsigned short eport, const ch Line 437  upnp_delete_redirection(unsigned short eport, const ch
 }  }
   
 /* upnp_get_portmapping_number_of_entries()  /* upnp_get_portmapping_number_of_entries()
 * TODO: improve this code */ * TODO: improve this code. */
 int  int
 upnp_get_portmapping_number_of_entries()  upnp_get_portmapping_number_of_entries()
 {  {
         int n = 0, r = 0;          int n = 0, r = 0;
         unsigned short eport, iport;          unsigned short eport, iport;
        char protocol[4], iaddr[32], desc[64];        char protocol[4], iaddr[32], desc[64], rhost[32];
         unsigned int leaseduration;
         do {          do {
                 protocol[0] = '\0'; iaddr[0] = '\0'; desc[0] = '\0';                  protocol[0] = '\0'; iaddr[0] = '\0'; desc[0] = '\0';
                 r = upnp_get_redirection_infos_by_index(n, &eport, protocol, &iport,                  r = upnp_get_redirection_infos_by_index(n, &eport, protocol, &iport,
                                                         iaddr, sizeof(iaddr),                                                          iaddr, sizeof(iaddr),
                                                        desc, sizeof(desc) );                                                        desc, sizeof(desc),
                                                         rhost, sizeof(rhost),
                                                         &leaseduration);
                 n++;                  n++;
         } while(r==0);          } while(r==0);
         return (n-1);          return (n-1);
 }  }
   
/* functions used to remove unused rules *//* functions used to remove unused rules
  * As a side effect, delete expired rules (based on LeaseDuration) */
 struct rule_state *  struct rule_state *
 get_upnp_rules_state_list(int max_rules_number_target)  get_upnp_rules_state_list(int max_rules_number_target)
 {  {
         /*char ifname[IFNAMSIZ];*/          /*char ifname[IFNAMSIZ];*/
         int proto;          int proto;
         unsigned short iport;          unsigned short iport;
           unsigned int timestamp;
         struct rule_state * tmp;          struct rule_state * tmp;
         struct rule_state * list = 0;          struct rule_state * list = 0;
           struct rule_state * * p;
         int i = 0;          int i = 0;
           time_t current_time;
   
         /*ifname[0] = '\0';*/          /*ifname[0] = '\0';*/
         tmp = malloc(sizeof(struct rule_state));          tmp = malloc(sizeof(struct rule_state));
         if(!tmp)          if(!tmp)
                 return 0;                  return 0;
           current_time = time(NULL);
           nextruletoclean_timestamp = 0;
         while(get_redirect_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0,          while(get_redirect_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0,
                                      &iport, &proto, 0, 0,                                      &iport, &proto, 0, 0, 0,0, &timestamp,
                                                                   &tmp->packets, &tmp->bytes) >= 0)                                                                    &tmp->packets, &tmp->bytes) >= 0)
         {          {
                   tmp->to_remove = 0;
                   if(timestamp > 0) {
                           /* need to remove this port mapping ? */
                           if(timestamp <= current_time)
                                   tmp->to_remove = 1;
                           else if((nextruletoclean_timestamp <= current_time)
                                  || (timestamp < nextruletoclean_timestamp))
                                   nextruletoclean_timestamp = timestamp;
                   }
                 tmp->proto = (short)proto;                  tmp->proto = (short)proto;
                 /* add tmp to list */                  /* add tmp to list */
                 tmp->next = list;                  tmp->next = list;
Line 406  get_upnp_rules_state_list(int max_rules_number_target) Line 502  get_upnp_rules_state_list(int max_rules_number_target)
                         break;                          break;
         }          }
         free(tmp);          free(tmp);
           /* remove the redirections that need to be removed */
           for(p = &list, tmp = list; tmp; tmp = *p)
           {
                   if(tmp->to_remove)
                   {
                           syslog(LOG_NOTICE, "remove port mapping %hu %s because it has expired",
                                  tmp->eport, (tmp->proto==IPPROTO_TCP)?"TCP":"UDP");
                           _upnp_delete_redir(tmp->eport, tmp->proto);
                           *p = tmp->next;
                           free(tmp);
                           i--;
                   } else {
                           p = &(tmp->next);
                   }
           }
         /* return empty list if not enough redirections */          /* return empty list if not enough redirections */
         if(i<=max_rules_number_target)          if(i<=max_rules_number_target)
                 while(list)                  while(list)
Line 426  remove_unused_rules(struct rule_state * list) Line 537  remove_unused_rules(struct rule_state * list)
         struct rule_state * tmp;          struct rule_state * tmp;
         u_int64_t packets;          u_int64_t packets;
         u_int64_t bytes;          u_int64_t bytes;
           unsigned int timestamp;
         int n = 0;          int n = 0;
   
         while(list)          while(list)
         {          {
                 /* remove the rule if no traffic has used it */                  /* remove the rule if no traffic has used it */
                 if(get_redirect_rule(ifname, list->eport, list->proto,                  if(get_redirect_rule(ifname, list->eport, list->proto,
                                 0, 0, &iport, 0, 0, &packets, &bytes) >= 0)                                 0, 0, &iport, 0, 0, 0, 0, &timestamp,
                                      &packets, &bytes) >= 0)
                 {                  {
                         if(packets == list->packets && bytes == list->bytes)                          if(packets == list->packets && bytes == list->bytes)
                         {                          {
Line 447  remove_unused_rules(struct rule_state * list) Line 561  remove_unused_rules(struct rule_state * list)
                 syslog(LOG_NOTICE, "removed %d unused rules", n);                  syslog(LOG_NOTICE, "removed %d unused rules", n);
 }  }
   
   /* upnp_get_portmappings_in_range()
    * return a list of all "external" ports for which a port
    * mapping exists */
   unsigned short *
   upnp_get_portmappings_in_range(unsigned short startport,
                                  unsigned short endport,
                                  const char * protocol,
                                  unsigned int * number)
   {
           int proto;
           proto = proto_atoi(protocol);
           if(!number)
                   return NULL;
           return get_portmappings_in_range(startport, endport, proto, number);
   }
   
   #ifdef ENABLE_6FC_SERVICE
   int
   upnp_check_outbound_pinhole(int proto, int * timeout)
   {
   #if 0
           int s, tmptimeout, tmptime_out;
           switch(proto)
           {
                   case IPPROTO_UDP:
                           s = retrieve_timeout("udp_timeout", timeout);
                           return s;
                           break;
                   case IPPROTO_UDPLITE:
                           s = retrieve_timeout("udp_timeout_stream", timeout);
                           return s;
                           break;
                   case IPPROTO_TCP:
                           s = retrieve_timeout("tcp_timeout_established", timeout);
                           return s;
                           break;
                   case 65535:
                           s = retrieve_timeout("udp_timeout", timeout);
                           s = retrieve_timeout("udp_timeout_stream", &tmptimeout);
                           s = retrieve_timeout("tcp_timeout_established", &tmptime_out);
                           if(tmptimeout<tmptime_out)
                           {
                                   if(tmptimeout<*timeout)
                                           *timeout = tmptimeout;
                           }
                           else
                           {
                                   if(tmptime_out<*timeout)
                                           *timeout = tmptimeout;
                           }
                           return s;
                           break;
                   default:
                           return -5;
                           break;
           }
   #endif
           return 0;
   }
   
   /* upnp_add_inboundpinhole()
    * returns: 0 on success
    *          -1 failed to add pinhole
    *          -2 already created
    *          -3 inbound pinhole disabled
    */
   int
   upnp_add_inboundpinhole(const char * raddr,
                           unsigned short rport,
                           const char * iaddr,
                           unsigned short iport,
                           const char * protocol,
                           const char * leaseTime,
                           int * uid)
   {
           int r, s, t, lt=0;
           char iaddr_old[40]="", proto[6]="", idfound[5]="", leaseTmp[12]; // IPv6 Modification
           snprintf(proto, sizeof(proto), "%.5d", atoi(protocol));
           unsigned short iport_old = 0;
           time_t current = time(NULL);
           /*struct in6_addr address; // IPv6 Modification
           if(inet_pton(AF_INET6, iaddr, &address) < 0) // IPv6 Modification
           {
                   syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
                   return 0;
           }*/
   
   #if 0
           r = get_rule_from_file(raddr, rport, iaddr_old, &iport_old, proto, 0, 0, idfound);
   #endif
           r = 0;
   
           lt = (int) current + atoi(leaseTime);
           snprintf(leaseTmp, sizeof(leaseTmp), "%d", lt);
           printf("LeaseTime: %d / %d -> %s\n", atoi(leaseTime), (int)current, leaseTmp);
   
           printf("\tCompare addr: %s // port: %d\n\t     to addr: %s // port: %d\n", iaddr, iport, iaddr_old, iport_old);
           if(r == 1 && strcmp(iaddr, iaddr_old)==0 && iport==iport_old)
           {
                   syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr, rport, iaddr_old, iport_old, protocol);
                   t = upnp_update_inboundpinhole(idfound, leaseTime);
                   *uid = atoi(idfound);
                   return t;
           }
           else
           {
                   syslog(LOG_INFO, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s and %s lease time.", raddr, rport, iaddr, iport, protocol, leaseTime);
                   s = upnp_add_inboundpinhole_internal(raddr, rport, iaddr, iport, protocol, uid);
   #if 0
                   if(rule_file_add(raddr, rport, iaddr, iport, protocol, leaseTmp, uid)<0)
                           return -8;
                   else
                   {
                           if(nextpinholetoclean_timestamp == 0 || (atoi(leaseTmp) <= nextpinholetoclean_timestamp))
                           {
                                   printf("Initializing the nextpinholetoclean variables. uid = %d\n", *uid);
                                   snprintf(nextpinholetoclean_uid, 5, "%.4d", *uid);
                                   nextpinholetoclean_timestamp = atoi(leaseTmp);
                           }
                           return s;
                   }
   #endif
           }
   return 0;
   }
   
   int
   upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport,
                          const char * iaddr, unsigned short iport,
                          const char * proto, int * uid)
   {
           int c = 9999;
           char cmd[256], cmd_raw[256], cuid[42];
   #if 0
           static const char cmdval_full_udptcp[] = "ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT";
           static const char cmdval_udptcp[] = "ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT";
           static const char cmdval_full_udplite[] = "ip6tables -I %s %d -p %s -i %s -s %s -d %s -j ACCEPT";
           static const char cmdval_udplite[] = "ip6tables -I %s %d -p %s -i %s -d %s -j ACCEPT";
           // raw table command
           static const char cmdval_full_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE";
           static const char cmdval_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE";
           static const char cmdval_full_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s -d %s -j TRACE";
           static const char cmdval_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -d %s -j TRACE";
   #endif
           //printf("%s\n", raddr);
           if(raddr!=NULL)
           {
   #ifdef IPPROTO_UDPLITE
                   if(atoi(proto) == IPPROTO_UDPLITE)
                   {
           /*              snprintf(cmd, sizeof(cmd), cmdval_full_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, iaddr);
                           snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udplite_raw, line_number, proto, ext_if_name, raddr, iaddr);*/
                   }
                   else
   #endif
                   {
           /*              snprintf(cmd, sizeof(cmd), cmdval_full_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);
                           snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udptcp_raw, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);*/
                   }
           }
           else
           {
   #ifdef IPPROTO_UDPLITE
                   if(atoi(proto) == IPPROTO_UDPLITE)
                   {
                           /*snprintf(cmd, sizeof(cmd), cmdval_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, iaddr);
                           snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udplite_raw, line_number, proto, ext_if_name, iaddr);*/
                   }
                   else
   #endif
                   {
                           /*snprintf(cmd, sizeof(cmd), cmdval_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, rport, iaddr, iport);
                           snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udptcp_raw, line_number, proto, ext_if_name, rport, iaddr, iport);
   */
                   }
           }
   #ifdef DEBUG
           syslog(LOG_INFO, "Adding following ip6tables rule:");
           syslog(LOG_INFO, "  -> %s", cmd);
           syslog(LOG_INFO, "  -> %s", cmd_raw);
   #endif
           // TODO Add a better checking error.
           if(system(cmd) < 0 || system(cmd_raw) < 0)
           {
                   return 0;
           }
           srand(time(NULL));
           snprintf(cuid, sizeof(cuid), "%.4d", rand()%c);
           *uid = atoi(cuid);
           printf("\t_add_ uid: %s\n", cuid);
           return 1;
   }
   
   int
   upnp_get_pinhole_info(const char * raddr,
                         unsigned short rport,
                         char * iaddr,
                         unsigned short * iport,
                         char * proto,
                         const char * uid,
                         char * lt)
   {
           /* TODO : to be done
            * Call Firewall specific code to get IPv6 pinhole infos */
           return 0;
   }
   
   int
   upnp_update_inboundpinhole(const char * uid, const char * leasetime)
   {
           /* TODO : to be implemented */
   #if 0
           int r, n;
           syslog(LOG_INFO, "Updating pinhole for inbound traffic with ID: %s", uid);
           r = check_rule_from_file(uid, 0);
           if(r < 0)
                   return r;
           else
           {
                   n = rule_file_update(uid, leasetime);
                   upnp_update_expiredpinhole();
                   return n;
           }
   #else
           return -1;
   #endif
   }
   
   int
   upnp_delete_inboundpinhole(const char * uid)
   {
           /* TODO : to be implemented */
   #if 0
           /* this is a alpha implementation calling ip6tables via system(), 
            * it can be usefull as an example to code the netfilter version */
           int r, s, linenum=0;
           char cmd[256], cmd_raw[256];
           syslog(LOG_INFO, "Removing pinhole for inbound traffic with ID: %s", uid);
           r = check_rule_from_file(uid, &linenum);
           if(r > 0)
           {
                   s = rule_file_remove(uid, linenum);
                   if(s < 0)
                           return s;
                   else
                   {
                           snprintf(cmd, sizeof(cmd), "ip6tables -t filter -D %s %d", miniupnpd_forward_chain, linenum);
                           snprintf(cmd_raw, sizeof(cmd_raw), "ip6tables -t raw -D PREROUTING %d", linenum -1);
   #ifdef DEBUG
                           syslog(LOG_INFO, "Deleting ip6tables rule:");
                           syslog(LOG_INFO, "  -> %s", cmd);
                           syslog(LOG_INFO, "  -> %s", cmd_raw);
   #endif
                           // TODO Add a better checking error.
                           if(system(cmd) < 0 || system(cmd_raw) < 0)
                           {
                                   return 0;
                           }
                   }
           }
           upnp_update_expiredpinhole();
           return r;
   #else
   return -1;
   #endif
   }
   
   /*
    * Result:
    *       1: Found Result
    *      -4: No result
    *      -5: Result in another table
    *      -6: Result in another chain
    *      -7: Result in a chain not a rule
   */
   int
   upnp_check_pinhole_working(const char * uid,
                              char * eaddr,
                              char * iaddr,
                              unsigned short * eport,
                              unsigned short * iport,
                              char * protocol,
                              int * rulenum_used)
   {
           /* TODO : to be implemented */
   #if 0
           FILE * fd;
           time_t expire = time(NULL);
           char buf[1024], filename[] = "/var/log/kern.log", expire_time[32]="";
           int res = -4, str_len;
   
           str_len = strftime(expire_time, sizeof(expire_time), "%b %d %H:%M:%S", localtime(&expire));
   
           fd = fopen(filename, "r");
           if (fd==NULL)
           {
                   syslog(LOG_ERR, "Get_rule: could not open file: %s", filename);
                   return -1;
           }
   
           syslog(LOG_INFO, "Get_rule: Starting getting info in file %s for %s\n", filename, uid);
           buf[sizeof(buf)-1] = 0;
           while(fgets(buf, sizeof(buf)-1, fd) != NULL && res != 1)
           {
                   //printf("line: %s\n", buf);
                   char * r, * t, * c, * p;
                   // looking for something like filter:FORWARD:rule: or filter:MINIUPNPD:rule:
                   r = strstr(buf, ":rule:");
                   p = strstr(buf, ":policy:");
                   t = strstr(buf, "TRACE:"); // table pointeur
                   t += 7;
                   c = t + 7; // chain pointeur
                   if(r)
                   {
                           printf("\t** Found %.*s\n", 24 ,t);
                           char * src, * dst, * sport, * dport, * proto, * line;
                           char time[15]="", src_addr[40], dst_addr[40], proto_tmp[8];
                           int proto_int;
                           strncpy(time, buf, sizeof(time));
                           /*if(compare_time(time, expire_time)<0)
                           {
                                   printf("\t\tNot corresponding time\n");
                                   continue;
                           }*/
   
                           line = r + 6;
                           printf("\trule line = %d\n", atoi(line));
   
                           src = strstr(buf, "SRC=");
                           src += 4;
                           snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src);
   #if 0
                           del_char(src_addr);
                           add_char(src_addr);
   #endif
   
                           dst = strstr(buf, "DST=");
                           dst += 4;
                           snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst);
   #if 0
                           del_char(dst_addr);
                           add_char(dst_addr);
   #endif
   
                           proto = strstr(buf, "PROTO=");
                           proto += 6;
                           proto_int = atoi(protocol);
                           if(proto_int == IPPROTO_UDP)
                                   strcpy(proto_tmp, "UDP");
                           else if(proto_int == IPPROTO_TCP)
                                   strcpy(proto_tmp, "TCP");
   #ifdef IPPROTO_UDPLITE
                           else if(proto_int == IPPROTO_UDPLITE)
                                   strcpy(proto_tmp, "UDPLITE");
   #endif
                           else
                                   strcpy(proto_tmp, "UnsupportedProto");
   
           //              printf("\tCompare eaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
           //              printf("\tCompare iaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
                           // TODO Check time
                           // Check that the paquet found in trace correspond to the one we are looking for
                           if( /*(strcmp(eaddr, src_addr) == 0) &&*/ (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, strlen(proto_tmp))==0))
                           {
                                   sport = strstr(buf, "SPT=");
                                   sport += 4;
                                   dport = strstr(buf, "DPT=");
                                   dport += 4;
                                   printf("\tCompare eport: %hu\n\t     to   port: %d\n", *eport, atoi(sport));
                                   printf("\tCompare iport: %hu\n\t     to   port: %d\n", *iport, atoi(dport));
                                   if(/*eport != atoi(sport) &&*/ *iport != atoi(dport))
                                   {
                                           printf("\t\tPort not corresponding\n");
                                           continue;
                                   }
                                   printf("\ttable found: %.*s\n", 6, t);
                                   printf("\tchain found: %.*s\n", 9, c);
                                   // Check that the table correspond to the filter table
                                   if(strncmp(t, "filter", 6)==0)
                                   {
                                           // Check that the table correspond to the MINIUPNP table
                                           if(strncmp(c, "MINIUPNPD", 9)==0)
                                           {
                                                   *rulenum_used = atoi(line);
                                                   res = 1;
                                           }
                                           else
                                           {
                                                   res = -6;
                                                   continue;
                                           }
                                   }
                                   else
                                   {
                                           res = -5;
                                           continue;
                                   }
                           }
                           else
                           {
                                   printf("Packet information not corresponding\n");
                                   continue;
                           }
                   }
                   if(!r && p)
                   {
                           printf("\t** Policy case\n");
                           char * src, * dst, * sport, * dport, * proto, * line;
                           char time[15], src_addr[40], dst_addr[40], proto_tmp[8];
                           int proto_int;
                           strncpy(time, buf, sizeof(time));
                           /*if(compare_time(time, expire_time)<0)
                           {
                                   printf("\t\tNot corresponding time\n");
                                   continue;
                           }*/
   
                           line = p + 8;
                           printf("\trule line = %d\n", atoi(line));
   
                           src = strstr(buf, "SRC=");
                           src += 4;
                           snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src);
   #if 0
                           del_char(src_addr);
                           add_char(src_addr);
   #endif
   
                           dst = strstr(buf, "DST=");
                           dst += 4;
                           snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst);
   #if 0
                           del_char(dst_addr);
                           add_char(dst_addr);
   #endif
   
                           proto = strstr(buf, "PROTO=");
                           proto += 6;
                           proto_int = atoi(protocol);
                           if(proto_int == IPPROTO_UDP)
                                   strcpy(proto_tmp, "UDP");
                           else if(proto_int == IPPROTO_TCP)
                                   strcpy(proto_tmp, "TCP");
   #ifdef IPPROTO_UDPLITE
                           else if(proto_int == IPPROTO_UDPLITE)
                                   strcpy(proto_tmp, "UDPLITE");
   #endif
                           else
                                   strcpy(proto_tmp, "UnsupportedProto");
   
           //              printf("\tCompare eaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
           //              printf("\tCompare iaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
                           // Check that the paquet found in trace correspond to the one we are looking for
                           if( (strcmp(eaddr, src_addr) == 0) && (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, 5)==0))
                           {
                                   sport = strstr(buf, "SPT=");
                                   sport += 4;
                                   dport = strstr(buf, "DPT=");
                                   dport += 4;
                                   printf("\tCompare eport: %hu\n\t     to   port: %d\n", *eport, atoi(sport));
                                   printf("\tCompare iport: %hu\n\t     to   port: %d\n", *iport, atoi(dport));
                                   if(*eport != atoi(sport) && *iport != atoi(dport))
                                   {
                                           printf("\t\tPort not corresponding\n");
                                           continue;
                                   }
                                   else
                                   {
                                           printf("Find a corresponding policy trace in the chain: %.*s\n", 10, c);
                                           res = -7;
                                           continue;
                                   }
                           }
                           else
                                   continue;
                   }
           }
           fclose(fd);
           return res;
   #else
           return -4;
   #endif
   }
   
   int
   upnp_get_pinhole_packets(const char * uid, int * packets)
   {
           /* TODO : to be implemented */
   #if 0
           int line=0, r;
           char cmd[256];
           r = check_rule_from_file(uid, &line);
           if(r < 0)
                   return r;
           else
           {
                   snprintf(cmd, sizeof(cmd), "ip6tables -L MINIUPNPD %d -v", line);
                   return retrieve_packets(cmd, &line, packets);
           }
   #else
           return 0;
   #endif
   }
   
   int
   upnp_update_expiredpinhole(void)
   {
   #if 0
           int r;
           char uid[5], leaseTime[12];
   
           r = get_rule_from_leasetime(uid, leaseTime);
           if(r<0)
                   return r;
           else
           {
                   strcpy(nextpinholetoclean_uid, uid);
                   nextpinholetoclean_timestamp = atoi(leaseTime);
                   return 1;
           }
   #endif
           return 0;
   }
   
   int
   upnp_clean_expiredpinhole()
   {
   #if 0
           upnp_delete_inboundpinhole(nextpinholetoclean_uid);
   
           return upnp_update_expiredpinhole();
   #endif
           return 0;
   }
   #endif
   
 /* stuff for miniupnpdctl */  /* stuff for miniupnpdctl */
 #ifdef USE_MINIUPNPDCTL  #ifdef USE_MINIUPNPDCTL
 void  void
 write_ruleset_details(int s)  write_ruleset_details(int s)
 {  {
         char ifname[IFNAMSIZ];  
         int proto = 0;          int proto = 0;
         unsigned short eport, iport;          unsigned short eport, iport;
         char desc[64];          char desc[64];
         char iaddr[32];          char iaddr[32];
           char rhost[32];
           unsigned int timestamp;
         u_int64_t packets;          u_int64_t packets;
         u_int64_t bytes;          u_int64_t bytes;
         int i = 0;          int i = 0;
         char buffer[256];          char buffer[256];
         int n;          int n;
        ifname[0] = '\0';
         write(s, "Ruleset :\n", 10);          write(s, "Ruleset :\n", 10);
        while(get_redirect_rule_by_index(i, ifname, &eport, iaddr, sizeof(iaddr),        while(get_redirect_rule_by_index(i, 0/*ifname*/, &eport, iaddr, sizeof(iaddr),
                                          &iport, &proto, desc, sizeof(desc),                                           &iport, &proto, desc, sizeof(desc),
                                            rhost, sizeof(rhost),
                                            &timestamp,
                                          &packets, &bytes) >= 0)                                           &packets, &bytes) >= 0)
         {          {
                n = snprintf(buffer, sizeof(buffer), "%2d %s %s %hu->%s:%hu "                n = snprintf(buffer, sizeof(buffer),
                                                     "'%s' %" PRIu64 " %" PRIu64 "\n",                             "%2d %s %s:%hu->%s:%hu "
                                                     /*"'%s' %llu %llu\n",*/                             "'%s' %u %" PRIu64 " %" PRIu64 "\n",
                             i, ifname, proto==IPPROTO_TCP?"TCP":"UDP",                             /*"'%s' %llu %llu\n",*/
                             eport, iaddr, iport, desc, packets, bytes);                             i, proto==IPPROTO_TCP?"TCP":"UDP", rhost,
                              eport, iaddr, iport, desc, timestamp, packets, bytes);
                 write(s, buffer, n);                  write(s, buffer, n);
                 i++;                  i++;
         }          }

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


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