diff options
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/x_tables.c | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index d7817af..750b928 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -52,6 +52,12 @@ enum { MATCH, }; +static const char *xt_prefix[NPROTO] = { + [AF_INET] = "ip", + [AF_INET6] = "ip6", + [NF_ARP] = "arp", +}; + /* Registration hooks for targets. */ int xt_register_target(int af, struct xt_target *target) @@ -158,18 +164,12 @@ struct xt_target *xt_find_target(int af, const char *name, u8 revision) } EXPORT_SYMBOL(xt_find_target); -static const char *xt_prefix[NPROTO] = { - [AF_INET] = "ipt_%s", - [AF_INET6] = "ip6t_%s", - [NF_ARP] = "arpt_%s", -}; - struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) { struct xt_target *target; target = try_then_request_module(xt_find_target(af, name, revision), - xt_prefix[af], name); + "%st_%s", xt_prefix[af], name); if (IS_ERR(target) || !target) return NULL; return target; @@ -237,6 +237,64 @@ int xt_find_revision(int 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) +{ + if (XT_ALIGN(match->matchsize) != size) { + printk("%s_tables: %s match: invalid size %Zu != %u\n", + xt_prefix[family], match->name, + XT_ALIGN(match->matchsize), size); + return -EINVAL; + } + if (match->table && strcmp(match->table, table)) { + printk("%s_tables: %s match: only valid in %s table, not %s\n", + xt_prefix[family], match->name, match->table, table); + return -EINVAL; + } + if (match->hooks && (hook_mask & ~match->hooks) != 0) { + printk("%s_tables: %s match: bad hook_mask %u\n", + xt_prefix[family], match->name, hook_mask); + return -EINVAL; + } + if (match->proto && (match->proto != proto || inv_proto)) { + printk("%s_tables: %s match: only valid for protocol %u\n", + xt_prefix[family], match->name, match->proto); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_GPL(xt_check_match); + +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) +{ + if (XT_ALIGN(target->targetsize) != size) { + printk("%s_tables: %s target: invalid size %Zu != %u\n", + xt_prefix[family], target->name, + XT_ALIGN(target->targetsize), size); + return -EINVAL; + } + if (target->table && strcmp(target->table, table)) { + printk("%s_tables: %s target: only valid in %s table, not %s\n", + xt_prefix[family], target->name, target->table, table); + return -EINVAL; + } + if (target->hooks && (hook_mask & ~target->hooks) != 0) { + printk("%s_tables: %s target: bad hook_mask %u\n", + xt_prefix[family], target->name, hook_mask); + return -EINVAL; + } + if (target->proto && (target->proto != proto || inv_proto)) { + printk("%s_tables: %s target: only valid for protocol %u\n", + xt_prefix[family], target->name, target->proto); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_GPL(xt_check_target); + struct xt_table_info *xt_alloc_table_info(unsigned int size) { struct xt_table_info *newinfo; |