Diff for /embedaddon/miniupnpd/pf/obsdrdr.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-2012 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 55 Line 55
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
   
   #include "../macros.h"
 #include "../config.h"  #include "../config.h"
 #include "obsdrdr.h"  #include "obsdrdr.h"
 #include "../upnpglobalvars.h"  #include "../upnpglobalvars.h"
   
/* anchor name *//* list too keep timestamps for port mappings having a lease duration */
static const char anchor_name[] = "miniupnpd";struct timestamp_entry {
         struct timestamp_entry * next;
         unsigned int timestamp;
         unsigned short eport;
         short protocol;
 };
   
   static struct timestamp_entry * timestamp_list = NULL;
   
   static unsigned int
   get_timestamp(unsigned short eport, int proto)
   {
           struct timestamp_entry * e;
           e = timestamp_list;
           while(e) {
                   if(e->eport == eport && e->protocol == (short)proto)
                           return e->timestamp;
                   e = e->next;
           }
           return 0;
   }
   
   static void
   remove_timestamp_entry(unsigned short eport, int proto)
   {
           struct timestamp_entry * e;
           struct timestamp_entry * * p;
           p = &timestamp_list;
           e = *p;
           while(e) {
                   if(e->eport == eport && e->protocol == (short)proto) {
                           /* remove the entry */
                           *p = e->next;
                           free(e);
                           return;
                   }
                   p = &(e->next);
                   e = *p;
           }
   }
   
 /* /dev/pf when opened */  /* /dev/pf when opened */
static int dev = -1;int dev = -1;
   
 /* shutdown_redirect() :  /* shutdown_redirect() :
  * close the /dev/pf device */   * close the /dev/pf device */
Line 138  error: Line 178  error:
 /* add_redirect_rule2() :  /* add_redirect_rule2() :
  * create a rdr rule */   * create a rdr rule */
 int  int
add_redirect_rule2(const char * ifname, unsigned short eport,add_redirect_rule2(const char * ifname,
                    const char * rhost, unsigned short eport,
                    const char * iaddr, unsigned short iport, int proto,                     const char * iaddr, unsigned short iport, int proto,
                                   const char * desc)                   const char * desc, unsigned int timestamp)
 {  {
         int r;          int r;
         struct pfioc_rule pcr;          struct pfioc_rule pcr;
Line 171  add_redirect_rule2(const char * ifname, unsigned short Line 212  add_redirect_rule2(const char * ifname, unsigned short
         if(1)          if(1)
         {          {
                 pcr.rule.direction = PF_IN;                  pcr.rule.direction = PF_IN;
                //pcr.rule.src.addr.type = PF_ADDR_NONE;                /*pcr.rule.src.addr.type = PF_ADDR_NONE;*/
                 pcr.rule.src.addr.type = PF_ADDR_ADDRMASK;                  pcr.rule.src.addr.type = PF_ADDR_ADDRMASK;
                 pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK;                  pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK;
                 pcr.rule.nat.addr.type = PF_ADDR_NONE;                  pcr.rule.nat.addr.type = PF_ADDR_NONE;
                 pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK;                  pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK;
 #endif  #endif
                
                 pcr.rule.dst.port_op = PF_OP_EQ;                  pcr.rule.dst.port_op = PF_OP_EQ;
                 pcr.rule.dst.port[0] = htons(eport);                  pcr.rule.dst.port[0] = htons(eport);
                 pcr.rule.dst.port[1] = htons(eport);                  pcr.rule.dst.port[1] = htons(eport);
Line 205  add_redirect_rule2(const char * ifname, unsigned short Line 246  add_redirect_rule2(const char * ifname, unsigned short
 #ifdef PFRULE_HAS_RTABLEID  #ifdef PFRULE_HAS_RTABLEID
                 pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */                  pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */
 #endif  #endif
   #ifdef PFRULE_HAS_ONRDOMAIN
                   pcr.rule.onrdomain = -1;        /* first appeared in OpenBSD 5.0 */
   #endif
                 pcr.rule.quick = 1;                  pcr.rule.quick = 1;
                 pcr.rule.keep_state = PF_STATE_NORMAL;                  pcr.rule.keep_state = PF_STATE_NORMAL;
                 if(tag)                  if(tag)
                         strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);                          strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
                 strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);                  strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
                   if(rhost && rhost[0] != '\0' && rhost[0] != '*')
                   {
                           inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr);
                           pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
                   }
 #ifndef PF_NEWSTYLE  #ifndef PF_NEWSTYLE
                 pcr.rule.rpool.proxy_port[0] = iport;                  pcr.rule.rpool.proxy_port[0] = iport;
                 pcr.rule.rpool.proxy_port[1] = iport;                  pcr.rule.rpool.proxy_port[1] = iport;
Line 255  add_redirect_rule2(const char * ifname, unsigned short Line 304  add_redirect_rule2(const char * ifname, unsigned short
                 free(a);                  free(a);
 #endif  #endif
         }          }
           if(r == 0 && timestamp > 0)
           {
                   struct timestamp_entry * tmp;
                   tmp = malloc(sizeof(struct timestamp_entry));
                   if(tmp)
                   {
                           tmp->next = timestamp_list;
                           tmp->timestamp = timestamp;
                           tmp->eport = eport;
                           tmp->protocol = (short)proto;
                           timestamp_list = tmp;
                   }
           }
         return r;          return r;
 }  }
   
 /* thanks to Seth Mos for this function */  /* thanks to Seth Mos for this function */
 int  int
add_filter_rule2(const char * ifname, const char * iaddr,add_filter_rule2(const char * ifname,
                  const char * rhost, const char * iaddr,
                  unsigned short eport, unsigned short iport,                   unsigned short eport, unsigned short iport,
                                  int proto, const char * desc)                                   int proto, const char * desc)
 {  {
 #ifndef PF_ENABLE_FILTER_RULES  #ifndef PF_ENABLE_FILTER_RULES
           UNUSED(ifname);
           UNUSED(rhost); UNUSED(iaddr);
           UNUSED(eport); UNUSED(iport);
           UNUSED(proto); UNUSED(desc);
         return 0;          return 0;
 #else  #else
         int r;          int r;
Line 296  add_filter_rule2(const char * ifname, const char * iad Line 363  add_filter_rule2(const char * ifname, const char * iad
         if(1)          if(1)
         {          {
 #endif  #endif
                
                 pcr.rule.dst.port_op = PF_OP_EQ;                  pcr.rule.dst.port_op = PF_OP_EQ;
                 pcr.rule.dst.port[0] = htons(eport);                  pcr.rule.dst.port[0] = htons(eport);
                 pcr.rule.direction = PF_IN;                  pcr.rule.direction = PF_IN;
Line 314  add_filter_rule2(const char * ifname, const char * iad Line 381  add_filter_rule2(const char * ifname, const char * iad
                 pcr.rule.flags = TH_SYN;                  pcr.rule.flags = TH_SYN;
                 pcr.rule.flagset = (TH_SYN|TH_ACK);                  pcr.rule.flagset = (TH_SYN|TH_ACK);
 #ifdef PFRULE_HAS_RTABLEID  #ifdef PFRULE_HAS_RTABLEID
                pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */                 pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */
 #endif  #endif
   #ifdef PFRULE_HAS_ONRDOMAIN
                   pcr.rule.onrdomain = -1;        /* first appeared in OpenBSD 5.0 */
   #endif
                 pcr.rule.keep_state = 1;                  pcr.rule.keep_state = 1;
                 strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);                  strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
                 if(queue)                  if(queue)
Line 323  add_filter_rule2(const char * ifname, const char * iad Line 393  add_filter_rule2(const char * ifname, const char * iad
                 if(tag)                  if(tag)
                         strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);                          strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
   
                   if(rhost && rhost[0] != '\0' && rhost[0] != '*')
                   {
                           inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr);
                           pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
                   }
 #ifndef PF_NEWSTYLE  #ifndef PF_NEWSTYLE
                 pcr.rule.rpool.proxy_port[0] = eport;                  pcr.rule.rpool.proxy_port[0] = eport;
                 a = calloc(1, sizeof(struct pf_pooladdr));                  a = calloc(1, sizeof(struct pf_pooladdr));
Line 332  add_filter_rule2(const char * ifname, const char * iad Line 407  add_filter_rule2(const char * ifname, const char * iad
                 TAILQ_INIT(&pcr.rule.rpool.list);                  TAILQ_INIT(&pcr.rule.rpool.list);
                 inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);                  inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
                 TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);                  TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
                
                 /* we have any - any port = # keep state label */                  /* we have any - any port = # keep state label */
                 /* we want any - iaddr port = # keep state label */                  /* we want any - iaddr port = # keep state label */
                 /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */                  /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */
Line 381  int Line 456  int
 get_redirect_rule(const char * ifname, unsigned short eport, int proto,  get_redirect_rule(const char * ifname, unsigned short eport, int proto,
                   char * iaddr, int iaddrlen, unsigned short * iport,                    char * iaddr, int iaddrlen, unsigned short * iport,
                   char * desc, int desclen,                    char * desc, int desclen,
                     char * rhost, int rhostlen,
                     unsigned int * timestamp,
                   u_int64_t * packets, u_int64_t * bytes)                    u_int64_t * packets, u_int64_t * bytes)
 {  {
         int i, n;          int i, n;
Line 388  get_redirect_rule(const char * ifname, unsigned short  Line 465  get_redirect_rule(const char * ifname, unsigned short 
 #ifndef PF_NEWSTYLE  #ifndef PF_NEWSTYLE
         struct pfioc_pooladdr pp;          struct pfioc_pooladdr pp;
 #endif  #endif
           UNUSED(ifname);
   
         if(dev<0) {          if(dev<0) {
                 syslog(LOG_ERR, "pf device is not open");                  syslog(LOG_ERR, "pf device is not open");
                 return -1;                  return -1;
Line 461  get_redirect_rule(const char * ifname, unsigned short  Line 540  get_redirect_rule(const char * ifname, unsigned short 
                         inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,                          inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,
                                   iaddr, iaddrlen);                                    iaddr, iaddrlen);
 #endif  #endif
                           if(rhost && rhostlen > 0)
                           {
                                   if (pr.rule.src.addr.v.a.addr.v4.s_addr == 0)
                                   {
                                           rhost[0] = '\0'; /* empty string */
                                   }
                                   else
                                   {
                                           inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr,
                                                     rhost, rhostlen);
                                   }
                           }
                           if(timestamp)
                                   *timestamp = get_timestamp(eport, proto);
                         return 0;                          return 0;
                 }                  }
         }          }
Line 473  delete_redirect_rule(const char * ifname, unsigned sho Line 566  delete_redirect_rule(const char * ifname, unsigned sho
 {  {
         int i, n;          int i, n;
         struct pfioc_rule pr;          struct pfioc_rule pr;
           UNUSED(ifname);
   
         if(dev<0) {          if(dev<0) {
                 syslog(LOG_ERR, "pf device is not open");                  syslog(LOG_ERR, "pf device is not open");
                 return -1;                  return -1;
Line 513  delete_redirect_rule(const char * ifname, unsigned sho Line 608  delete_redirect_rule(const char * ifname, unsigned sho
                                 syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");                                  syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
                                 goto error;                                  goto error;
                         }                          }
                           remove_timestamp_entry(eport, proto);
                         return 0;                          return 0;
                 }                  }
         }          }
Line 524  int Line 620  int
 delete_filter_rule(const char * ifname, unsigned short eport, int proto)  delete_filter_rule(const char * ifname, unsigned short eport, int proto)
 {  {
 #ifndef PF_ENABLE_FILTER_RULES  #ifndef PF_ENABLE_FILTER_RULES
           UNUSED(ifname); UNUSED(eport); UNUSED(proto);
         return 0;          return 0;
 #else  #else
         int i, n;          int i, n;
Line 578  get_redirect_rule_by_index(int index, Line 675  get_redirect_rule_by_index(int index,
                            char * ifname, unsigned short * eport,                             char * ifname, unsigned short * eport,
                            char * iaddr, int iaddrlen, unsigned short * iport,                             char * iaddr, int iaddrlen, unsigned short * iport,
                            int * proto, char * desc, int desclen,                             int * proto, char * desc, int desclen,
                              char * rhost, int rhostlen,
                              unsigned int * timestamp,
                            u_int64_t * packets, u_int64_t * bytes)                             u_int64_t * packets, u_int64_t * bytes)
 {  {
         int n;          int n;
Line 660  get_redirect_rule_by_index(int index, Line 759  get_redirect_rule_by_index(int index,
         inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,          inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,
                   iaddr, iaddrlen);                    iaddr, iaddrlen);
 #endif  #endif
           if(rhost && rhostlen > 0)
           {
                   if (pr.rule.src.addr.v.a.addr.v4.s_addr == 0)
                   {
                           rhost[0] = '\0'; /* empty string */
                   }
                   else
                   {
                           inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr,
                                     rhost, rhostlen);
                   }
           }
           if(timestamp)
                   *timestamp = get_timestamp(*eport, *proto);
         return 0;          return 0;
 error:  error:
         return -1;          return -1;
 }  }
   
   /* return an (malloc'ed) array of "external" port for which there is
    * a port mapping. number is the size of the array */
   unsigned short *
   get_portmappings_in_range(unsigned short startport, unsigned short endport,
                             int proto, unsigned int * number)
   {
           unsigned short * array;
           unsigned int capacity;
           int i, n;
           unsigned short eport;
           struct pfioc_rule pr;
   
           *number = 0;
           if(dev<0) {
                   syslog(LOG_ERR, "pf device is not open");
                   return NULL;
           }
           capacity = 128;
           array = calloc(capacity, sizeof(unsigned short));
           if(!array)
           {
                   syslog(LOG_ERR, "get_portmappings_in_range() : calloc error");
                   return NULL;
           }
           memset(&pr, 0, sizeof(pr));
           strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
   #ifndef PF_NEWSTYLE
           pr.rule.action = PF_RDR;
   #endif
           if(ioctl(dev, DIOCGETRULES, &pr) < 0)
           {
                   syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
                   free(array);
                   return NULL;
           }
           n = pr.nr;
           for(i=0; i<n; i++)
           {
                   pr.nr = i;
                   if(ioctl(dev, DIOCGETRULE, &pr) < 0)
                   {
                           syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
                           continue;
                   }
                   eport = ntohs(pr.rule.dst.port[0]);
                   if( (eport == ntohs(pr.rule.dst.port[1]))
                     && (pr.rule.proto == proto)
                     && (startport <= eport) && (eport <= endport) )
                   {
                           if(*number >= capacity)
                           {
                                   /* need to increase the capacity of the array */
                                   capacity += 128;
                                   array = realloc(array, sizeof(unsigned short)*capacity);
                                   if(!array)
                                   {
                                           syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity);
                                           *number = 0;
                                           return NULL;
                                   }
                           }
                           array[*number] = eport;
                           (*number)++;
                   }
           }
           return array;
   }
   
 /* this function is only for testing */  /* this function is only for testing */
 #if TEST  #if TEST
 void  void
Line 695  list_rules(void) Line 876  list_rules(void)
                 pr.nr = i;                  pr.nr = i;
                 if(ioctl(dev, DIOCGETRULE, &pr) < 0)                  if(ioctl(dev, DIOCGETRULE, &pr) < 0)
                         perror("DIOCGETRULE");                          perror("DIOCGETRULE");
                printf(" %s %d:%d -> %d:%d  proto %d keep_state=%d action=%d\n",                printf(" %s %s %d:%d -> %d:%d  proto %d keep_state=%d action=%d\n",
                         pr.rule.ifname,                          pr.rule.ifname,
                           inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, buf, 32),
                         (int)ntohs(pr.rule.dst.port[0]),                          (int)ntohs(pr.rule.dst.port[0]),
                         (int)ntohs(pr.rule.dst.port[1]),                          (int)ntohs(pr.rule.dst.port[1]),
 #ifndef PF_NEWSTYLE  #ifndef PF_NEWSTYLE

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


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