]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/netfilter/x_tables.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[mv-sheeva.git] / net / netfilter / x_tables.c
index cf2f3e90cef946c2d1f45d7411e859652eecdba0..89837a4eef7621e6678049fee3c096bf67de8acf 100644 (file)
@@ -30,7 +30,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
+MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
 
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
@@ -58,10 +58,12 @@ static struct xt_af *xt;
 #define duprintf(format, args...)
 #endif
 
-static const char *const xt_prefix[NPROTO] = {
-       [AF_INET]       = "ip",
-       [AF_INET6]      = "ip6",
-       [NF_ARP]        = "arp",
+static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
+       [NFPROTO_UNSPEC] = "x",
+       [NFPROTO_IPV4]   = "ip",
+       [NFPROTO_ARP]    = "arp",
+       [NFPROTO_BRIDGE] = "eb",
+       [NFPROTO_IPV6]   = "ip6",
 };
 
 /* Registration hooks for targets. */
@@ -207,6 +209,11 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
                }
        }
        mutex_unlock(&xt[af].mutex);
+
+       if (af != NFPROTO_UNSPEC)
+               /* Try searching again in the family-independent list */
+               return xt_find_match(NFPROTO_UNSPEC, name, revision);
+
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL(xt_find_match);
@@ -232,6 +239,11 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
                }
        }
        mutex_unlock(&xt[af].mutex);
+
+       if (af != NFPROTO_UNSPEC)
+               /* Try searching again in the family-independent list */
+               return xt_find_target(NFPROTO_UNSPEC, name, revision);
+
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL(xt_find_target);
@@ -309,31 +321,41 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
 }
 EXPORT_SYMBOL_GPL(xt_find_revision);
 
-int xt_check_match(const struct xt_match *match, unsigned short family,
-                  unsigned int size, const char *table, unsigned int hook_mask,
-                  unsigned short proto, int inv_proto)
+int xt_check_match(struct xt_mtchk_param *par,
+                  unsigned int size, u_int8_t proto, bool inv_proto)
 {
-       if (XT_ALIGN(match->matchsize) != size) {
+       if (XT_ALIGN(par->match->matchsize) != size &&
+           par->match->matchsize != -1) {
+               /*
+                * ebt_among is exempt from centralized matchsize checking
+                * because it uses a dynamic-size data set.
+                */
                printk("%s_tables: %s match: invalid size %Zu != %u\n",
-                      xt_prefix[family], match->name,
-                      XT_ALIGN(match->matchsize), size);
+                      xt_prefix[par->family], par->match->name,
+                      XT_ALIGN(par->match->matchsize), size);
                return -EINVAL;
        }
-       if (match->table && strcmp(match->table, table)) {
+       if (par->match->table != NULL &&
+           strcmp(par->match->table, par->table) != 0) {
                printk("%s_tables: %s match: only valid in %s table, not %s\n",
-                      xt_prefix[family], match->name, match->table, table);
+                      xt_prefix[par->family], par->match->name,
+                      par->match->table, par->table);
                return -EINVAL;
        }
-       if (match->hooks && (hook_mask & ~match->hooks) != 0) {
-               printk("%s_tables: %s match: bad hook_mask %u/%u\n",
-                      xt_prefix[family], match->name, hook_mask, match->hooks);
+       if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
+               printk("%s_tables: %s match: bad hook_mask %#x/%#x\n",
+                      xt_prefix[par->family], par->match->name,
+                      par->hook_mask, par->match->hooks);
                return -EINVAL;
        }
-       if (match->proto && (match->proto != proto || inv_proto)) {
+       if (par->match->proto && (par->match->proto != proto || inv_proto)) {
                printk("%s_tables: %s match: only valid for protocol %u\n",
-                      xt_prefix[family], match->name, match->proto);
+                      xt_prefix[par->family], par->match->name,
+                      par->match->proto);
                return -EINVAL;
        }
+       if (par->match->checkentry != NULL && !par->match->checkentry(par))
+               return -EINVAL;
        return 0;
 }
 EXPORT_SYMBOL_GPL(xt_check_match);
@@ -450,32 +472,36 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
 EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
 #endif /* CONFIG_COMPAT */
 
-int xt_check_target(const struct xt_target *target, unsigned short family,
-                   unsigned int size, const char *table, unsigned int hook_mask,
-                   unsigned short proto, int inv_proto)
+int xt_check_target(struct xt_tgchk_param *par,
+                   unsigned int size, u_int8_t proto, bool inv_proto)
 {
-       if (XT_ALIGN(target->targetsize) != size) {
+       if (XT_ALIGN(par->target->targetsize) != size) {
                printk("%s_tables: %s target: invalid size %Zu != %u\n",
-                      xt_prefix[family], target->name,
-                      XT_ALIGN(target->targetsize), size);
+                      xt_prefix[par->family], par->target->name,
+                      XT_ALIGN(par->target->targetsize), size);
                return -EINVAL;
        }
-       if (target->table && strcmp(target->table, table)) {
+       if (par->target->table != NULL &&
+           strcmp(par->target->table, par->table) != 0) {
                printk("%s_tables: %s target: only valid in %s table, not %s\n",
-                      xt_prefix[family], target->name, target->table, table);
+                      xt_prefix[par->family], par->target->name,
+                      par->target->table, par->table);
                return -EINVAL;
        }
-       if (target->hooks && (hook_mask & ~target->hooks) != 0) {
-               printk("%s_tables: %s target: bad hook_mask %u/%u\n",
-                      xt_prefix[family], target->name, hook_mask,
-                      target->hooks);
+       if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
+               printk("%s_tables: %s target: bad hook_mask %#x/%#x\n",
+                      xt_prefix[par->family], par->target->name,
+                      par->hook_mask, par->target->hooks);
                return -EINVAL;
        }
-       if (target->proto && (target->proto != proto || inv_proto)) {
+       if (par->target->proto && (par->target->proto != proto || inv_proto)) {
                printk("%s_tables: %s target: only valid for protocol %u\n",
-                      xt_prefix[family], target->name, target->proto);
+                      xt_prefix[par->family], par->target->name,
+                      par->target->proto);
                return -EINVAL;
        }
+       if (par->target->checkentry != NULL && !par->target->checkentry(par))
+               return -EINVAL;
        return 0;
 }
 EXPORT_SYMBOL_GPL(xt_check_target);
@@ -932,7 +958,7 @@ int xt_proto_init(struct net *net, u_int8_t af)
        struct proc_dir_entry *proc;
 #endif
 
-       if (af >= NPROTO)
+       if (af >= ARRAY_SIZE(xt_prefix))
                return -EINVAL;
 
 
@@ -1001,7 +1027,7 @@ static int __net_init xt_net_init(struct net *net)
 {
        int i;
 
-       for (i = 0; i < NPROTO; i++)
+       for (i = 0; i < NFPROTO_NUMPROTO; i++)
                INIT_LIST_HEAD(&net->xt.tables[i]);
        return 0;
 }
@@ -1014,11 +1040,11 @@ static int __init xt_init(void)
 {
        int i, rv;
 
-       xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
+       xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL);
        if (!xt)
                return -ENOMEM;
 
-       for (i = 0; i < NPROTO; i++) {
+       for (i = 0; i < NFPROTO_NUMPROTO; i++) {
                mutex_init(&xt[i].mutex);
 #ifdef CONFIG_COMPAT
                mutex_init(&xt[i].compat_mutex);