Added the new version for dummynet.
[ipfw.git] / dummynet / ip_fw2.c
index 4e46566..21d1b41 100644 (file)
@@ -70,11 +70,6 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_fw2.c,v 1.175.2.13 2008/10/30 16:29:04 bz
 #include <net/pf_mtag.h>
 #include <net/vnet.h>
 
-#ifdef linux
-#define INP_LOCK_ASSERT                /* define before missing.h otherwise ? */
-#include "missing.h"
-#endif
-
 #define        IPFW_INTERNAL   /* Access to protected data structures in ip_fw.h. */
 
 #include <netinet/in.h>
@@ -104,10 +99,6 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_fw2.c,v 1.175.2.13 2008/10/30 16:29:04 bz
 
 #include <machine/in_cksum.h>  /* XXX for in_cksum */
 
-#ifdef IPFW_HASHTABLES
-#include "hashtable.h"
-#endif
-
 #ifdef MAC
 #include <security/mac/mac_framework.h>
 #endif
@@ -183,18 +174,14 @@ SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose,
 SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
     CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
     "Set upper limit of matches of ipfw rules logged");
-static unsigned int dummy_default_rule = IPFW_DEFAULT_RULE;
+unsigned int dummy_default_rule = IPFW_DEFAULT_RULE;
 SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
     &dummy_default_rule, IPFW_DEFAULT_RULE,
     "The default/max possible rule number.");
-static unsigned int dummy_tables_max = IPFW_TABLES_MAX;
+unsigned int dummy_tables_max = IPFW_TABLES_MAX;
 SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
     &dummy_tables_max, IPFW_TABLES_MAX,
     "The maximum number of tables.");
-static unsigned int skipto_entries = 256;
-SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, skipto_entries,
-    CTLFLAG_RW, &skipto_entries, 0,
-    "Number of entries in the skipto cache");
 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
     &default_to_accept, 0,
     "Make the default rule accept all packets.");
@@ -1886,61 +1873,6 @@ send_reject(struct ip_fw_args *args, int code, int ip_len, struct ip *ip)
        args->m = NULL;
 }
 
-static void
-set_skipto_table(struct ip_fw_chain *ch)
-{
-       int i, n, sh;
-       struct ip_fw *f, **t, **oldt;
-
-       for (sh = 15; sh > 0; sh--)
-               if (skipto_entries > 1<<sh)
-                       break;
-       sh++;
-       skipto_entries = 1<< (16 - sh) ;
-       /* XXX unsafe and too long */
-       t = malloc(skipto_entries * sizeof(*t), M_IPFW_TBL, M_WAITOK | M_ZERO);
-       if (t == NULL)
-               return;
-       IPFW_RLOCK(ch);
-       /* Store pointers in the table. In the loop i is the next
-        * free slot, n is the slot where the current rule goes.
-        */
-       for (i = 0, f = ch->rules; f; f = f->next) {
-               n = f->rulenum >> sh ;
-               while (i <= n)
-                       t[i++] = f;
-       }
-       V_layer3_chain.skipto_shift = sh;
-       V_layer3_chain.skipto_size = skipto_entries;
-       oldt = V_layer3_chain.skipto_ptrs;
-       V_layer3_chain.skipto_ptrs = t;
-       IPFW_RUNLOCK(ch);
-       if (oldt) {
-               IPFW_WLOCK(ch);
-               IPFW_WUNLOCK(ch);
-               /* now can free oldt */
-               free(oldt, M_IPFW_TBL);
-       }
-}
-#if 0
-/*
- * Map a rule number to a rule pointer, using the skipto table.
- * First lookup the slot, then follow the chain until we find a
- * non-null entry with rulenum >= num. Return default_rule on error.
- */
-static struct ip_fw *
-rule2ptr(struct ip_fw_chain *ch, int num)
-{
-       struct ip_fw *r = NULL;
-       int ix = (num & 0xffff) >> ch->skipto_shift;
-
-       while (ix < ch->skipto_size && (r = ch->skipto_ptrs[ix]) == NULL)
-               ix++;
-       while (r && num < r->rulenum)
-               r = r->next;
-       return (r ? r : ch->default_rule);
-}
-#endif
 /**
  *
  * Given an ip_fw *, lookup_next_rule will return a pointer
@@ -1957,10 +1889,11 @@ rule2ptr(struct ip_fw_chain *ch, int num)
  */
 
 static struct ip_fw *
-lookup_next_rule(struct ip_fw_chain *ch, struct ip_fw *me, uint32_t tablearg)
+lookup_next_rule(struct ip_fw *me, u_int32_t tablearg)
 {
        struct ip_fw *rule = NULL;
        ipfw_insn *cmd;
+       u_int16_t       rulenum;
 
        /* look for action, in case it is a skipto */
        cmd = ACTION_PTR(me);
@@ -1970,19 +1903,21 @@ lookup_next_rule(struct ip_fw_chain *ch, struct ip_fw *me, uint32_t tablearg)
                cmd += F_LEN(cmd);
        if (cmd->opcode == O_TAG)
                cmd += F_LEN(cmd);
-       if (cmd->opcode != O_SKIPTO ) {
-               rule = me->next;
-       } else {
-               tablearg = tablearg ? tablearg : cmd->arg1;
+       if (cmd->opcode == O_SKIPTO ) {
+               if (tablearg != 0) {
+                       rulenum = (u_int16_t)tablearg;
+               } else {
+                       rulenum = cmd->arg1;
+               }
                for (rule = me->next; rule ; rule = rule->next) {
-                       if (rule->rulenum >= tablearg) {
+                       if (rule->rulenum >= rulenum) {
                                break;
                        }
                }
-
-//             rule = rule2ptr(ch, tablearg ? tablearg : cmd->arg1);
        }
-       me->next_rule = rule; /* XXX perhaps unnecessary ? */
+       if (rule == NULL)               /* failure or not a skipto */
+               rule = me->next;
+       me->next_rule = rule;
        return rule;
 }
 
@@ -1994,11 +1929,6 @@ add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
        struct table_entry *ent;
        struct radix_node *rn;
 
-#ifdef IPFW_HASHTABLES
-       if (tbl >= 2*IPFW_TABLES_MAX)
-               return EINVAL;
-       return EINVAL; // XXX to be completed
-#endif
        if (tbl >= IPFW_TABLES_MAX)
                return (EINVAL);
        rnh = ch->tables[tbl];
@@ -2037,11 +1967,6 @@ del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
        struct table_entry *ent;
        struct sockaddr_in sa, mask;
 
-#ifdef IPFW_HASHTABLES
-       if (tbl >= 2*IPFW_TABLES_MAX)
-               return EINVAL;
-       return EINVAL; // XXX to be completed
-#endif
        if (tbl >= IPFW_TABLES_MAX)
                return (EINVAL);
        rnh = ch->tables[tbl];
@@ -2085,11 +2010,6 @@ flush_table(struct ip_fw_chain *ch, uint16_t tbl)
 
        IPFW_WLOCK_ASSERT(ch);
 
-#ifdef IPFW_HASHTABLES
-       if (tbl >= 2*IPFW_TABLES_MAX)
-               return EINVAL;
-       return EINVAL; // XXX to be completed
-#endif
        if (tbl >= IPFW_TABLES_MAX)
                return (EINVAL);
        rnh = ch->tables[tbl];
@@ -2107,10 +2027,6 @@ flush_tables(struct ip_fw_chain *ch)
 
        for (tbl = 0; tbl < IPFW_TABLES_MAX; tbl++)
                flush_table(ch, tbl);
-#ifdef IPFW_HASHTABLES
-       for (tbl = 0; tbl < IPFW_TABLES_MAX; tbl++)
-               ch->hashtab[tbl] = ipfw_ht_destroy(ch->hashtab[tbl]);
-#endif
 }
 
 static int
@@ -2127,10 +2043,6 @@ init_tables(struct ip_fw_chain *ch)
                        return (ENOMEM);
                }
        }
-#ifdef IPFW_HASHTABLES
-        for (i = 0; i < IPFW_TABLES_MAX; i++)
-               ch->hashtab[i] = ipfw_ht_destroy(ch->hashtab[i]);
-#endif
        return (0);
 }
 
@@ -2767,7 +2679,7 @@ do {                                                                      \
                        f = args->rule->next_rule;
 
                if (f == NULL)
-                       f = lookup_next_rule(chain, args->rule, 0);
+                       f = lookup_next_rule(args->rule, 0);
        } else {
                /*
                 * Find the starting rule. It can be either the first
@@ -2984,7 +2896,7 @@ do {                                                                      \
                                            a = dst_port;
                                        else if (v == 3)
                                            a = src_port;
-                                       else if (v >= 4 && v <= 6) {
+                                       else if (v == 4 || v == 5) {
                                            check_uidgid(
                                                    (ipfw_insn_u32 *)cmd,
                                                    proto, oif,
@@ -2994,16 +2906,12 @@ do {                                                                    \
 #ifdef linux
                                            if (v ==4 /* O_UID */)
                                                a = ucred_cache.uid;
-                                           else if (v == 5 /* O_GID */)
-                                               a = ucred_cache.gid;
-                                           else if (v == 6 /* O_JAIL */)
+                                           else if (v == 5 /* O_JAIL */)
                                                a = ucred_cache.xid;
 #else
                                            if (v ==4 /* O_UID */)
                                                a = (*uc)->cr_uid;
-                                           else if (v == 5 /* O_GID */)
-                                               ; // a = groupmember((gid_t)insn->d[0], *uc);
-                                           else if (v == 6 /* O_JAIL */)
+                                           else if (v == 5 /* O_JAIL */)
                                                a = (*uc)->cr_prison->pr_id;
 #endif
                                        } else
@@ -3590,10 +3498,10 @@ do {                                                                    \
                                }
                                /* handle skipto */
                                if (cmd->arg1 == IP_FW_TABLEARG) {
-                                       f = lookup_next_rule(chain, f, tablearg);
-                               } else {
+                                       f = lookup_next_rule(f, tablearg);
+                               } else { // XXX ?
                                        if (f->next_rule == NULL)
-                                               lookup_next_rule(chain, f, 0);
+                                               lookup_next_rule(f, 0);
                                        f = f->next_rule;
                                }
                                /*
@@ -3883,15 +3791,17 @@ add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule)
                goto done;
         }
 
+       /*
+        * If rulenum is 0, find highest numbered rule before the
+        * default rule, and add autoinc_step
+        */
        if (V_autoinc_step < 1)
                V_autoinc_step = 1;
        else if (V_autoinc_step > 1000)
                V_autoinc_step = 1000;
        if (rule->rulenum == 0) {
                /*
-                * If rulenum is 0, use highest numbered rule before
-                * the default, adding autoinc_step if room.
-                * Also set the number in the caller.
+                * locate the highest numbered rule before default
                 */
                for (f = chain->rules; f; f = f->next) {
                        if (f->rulenum == IPFW_DEFAULT_RULE)
@@ -3905,7 +3815,6 @@ add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule)
 
        /*
         * Now insert the new rule in the right place in the sorted list.
-        * XXX TODO also put in the skipto table.
         */
        for (prev = NULL, f = chain->rules; f; prev = f, f = f->next) {
                if (f->rulenum > rule->rulenum) { /* found the location */
@@ -3958,7 +3867,6 @@ remove_rule(struct ip_fw_chain *chain, struct ip_fw *rule,
                prev->next = n;
        V_static_count--;
        V_static_len -= l;
-       // XXX remove from the skipto table
 
        rule->next = chain->reap;
        chain->reap = rule;
@@ -5089,17 +4997,12 @@ ipfw_destroy(void)
        IPFW_WUNLOCK(&V_layer3_chain);
        if (reap != NULL)
                reap_rules(reap);
-       IPFW_DYN_LOCK_DESTROY();
        uma_zdestroy(ipfw_dyn_rule_zone);
+       IPFW_DYN_LOCK_DESTROY();
        if (V_ipfw_dyn_v != NULL)
                free(V_ipfw_dyn_v, M_IPFW);
        IPFW_LOCK_DESTROY(&V_layer3_chain);
 
-#ifdef INET6
-       /* Free IPv6 fw sysctl tree. */
-       sysctl_ctx_free(&ip6_fw_sysctl_ctx);
-#endif
-
        printf("IP firewall unloaded\n");
 }
 
@@ -5154,8 +5057,6 @@ vnet_ipfw_init(const void *unused)
        IPFW_LOCK_INIT(&V_layer3_chain);
        callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
 
-       set_skipto_table(&V_layer3_chain);
-
        bzero(&default_rule, sizeof default_rule);
        default_rule.act_ofs = 0;
        default_rule.rulenum = IPFW_DEFAULT_RULE;