]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/ipv4/netfilter/ip_tables.c
netfilter: xtables: move extension arguments into compound structure (1/6)
[mirror_ubuntu-bionic-kernel.git] / net / ipv4 / netfilter / ip_tables.c
index 600737f122d2eee84f269f3abffe2b02880d454b..99fdb59454fdd3524a421733c58be4d5ca074915 100644 (file)
@@ -53,7 +53,7 @@ MODULE_DESCRIPTION("IPv4 packet filter");
 do {                                                           \
        if (!(x))                                               \
                printk("IP_NF_ASSERT: %s:%s:%u\n",              \
-                      __FUNCTION__, __FILE__, __LINE__);       \
+                      __func__, __FILE__, __LINE__);   \
 } while(0)
 #else
 #define IP_NF_ASSERT(x)
@@ -186,16 +186,14 @@ ipt_error(struct sk_buff *skb,
 
 /* Performance critical - called for every packet */
 static inline bool
-do_match(struct ipt_entry_match *m,
-             const struct sk_buff *skb,
-             const struct net_device *in,
-             const struct net_device *out,
-             int offset,
-             bool *hotdrop)
+do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
+        struct xt_match_param *par)
 {
+       par->match     = m->u.kernel.match;
+       par->matchinfo = m->data;
+
        /* Stop iteration if it doesn't match */
-       if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
-                                     offset, ip_hdrlen(skb), hotdrop))
+       if (!m->u.kernel.match->match(skb, par))
                return true;
        else
                return false;
@@ -296,7 +294,7 @@ static void trace_packet(struct sk_buff *skb,
                         struct ipt_entry *e)
 {
        void *table_base;
-       struct ipt_entry *root;
+       const struct ipt_entry *root;
        char *hookname, *chainname, *comment;
        unsigned int rulenum = 0;
 
@@ -326,8 +324,7 @@ ipt_do_table(struct sk_buff *skb,
             struct xt_table *table)
 {
        static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
-       u_int16_t offset;
-       struct iphdr *ip;
+       const struct iphdr *ip;
        u_int16_t datalen;
        bool hotdrop = false;
        /* Initializing verdict to NF_DROP keeps gcc happy. */
@@ -336,6 +333,7 @@ ipt_do_table(struct sk_buff *skb,
        void *table_base;
        struct ipt_entry *e, *back;
        struct xt_table_info *private;
+       struct xt_match_param mtpar;
 
        /* Initialization */
        ip = ip_hdr(skb);
@@ -348,7 +346,11 @@ ipt_do_table(struct sk_buff *skb,
         * things we don't know, ie. tcp syn flag or ports).  If the
         * rule is also a fragment-specific rule, non-fragments won't
         * match it. */
-       offset = ntohs(ip->frag_off) & IP_OFFSET;
+       mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
+       mtpar.thoff   = ip_hdrlen(skb);
+       mtpar.hotdrop = &hotdrop;
+       mtpar.in      = in;
+       mtpar.out     = out;
 
        read_lock_bh(&table->lock);
        IP_NF_ASSERT(table->valid_hooks & (1 << hook));
@@ -362,12 +364,11 @@ ipt_do_table(struct sk_buff *skb,
        do {
                IP_NF_ASSERT(e);
                IP_NF_ASSERT(back);
-               if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
+               if (ip_packet_match(ip, indev, outdev,
+                   &e->ip, mtpar.fragoff)) {
                        struct ipt_entry_target *t;
 
-                       if (IPT_MATCH_ITERATE(e, do_match,
-                                             skb, in, out,
-                                             offset, &hotdrop) != 0)
+                       if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
                                goto no_match;
 
                        ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
@@ -616,17 +617,14 @@ check_match(struct ipt_entry_match *m, const char *name,
        match = m->u.kernel.match;
        ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
                             name, hookmask, ip->proto,
-                            ip->invflags & IPT_INV_PROTO);
-       if (!ret && m->u.kernel.match->checkentry
-           && !m->u.kernel.match->checkentry(name, ip, match, m->data,
-                                             hookmask)) {
+                            ip->invflags & IPT_INV_PROTO, ip, m->data);
+       if (ret < 0) {
                duprintf("ip_tables: check failed for `%s'.\n",
                         m->u.kernel.match->name);
-               ret = -EINVAL;
+               return ret;
        }
-       if (!ret)
-               (*i)++;
-       return ret;
+       ++*i;
+       return 0;
 }
 
 static int
@@ -668,15 +666,13 @@ static int check_target(struct ipt_entry *e, const char *name)
        target = t->u.kernel.target;
        ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
                              name, e->comefrom, e->ip.proto,
-                             e->ip.invflags & IPT_INV_PROTO);
-       if (!ret && t->u.kernel.target->checkentry
-           && !t->u.kernel.target->checkentry(name, e, target, t->data,
-                                              e->comefrom)) {
+                             e->ip.invflags & IPT_INV_PROTO, e, t->data);
+       if (ret < 0) {
                duprintf("ip_tables: check failed for `%s'.\n",
                         t->u.kernel.target->name);
-               ret = -EINVAL;
+               return ret;
        }
-       return ret;
+       return 0;
 }
 
 static int
@@ -926,7 +922,7 @@ static struct xt_counters * alloc_counters(struct xt_table *table)
 {
        unsigned int countersize;
        struct xt_counters *counters;
-       struct xt_table_info *private = table->private;
+       const struct xt_table_info *private = table->private;
 
        /* We need atomic snapshot of counters: rest doesn't change
           (other than comefrom, which userspace doesn't care
@@ -953,9 +949,9 @@ copy_entries_to_user(unsigned int total_size,
        unsigned int off, num;
        struct ipt_entry *e;
        struct xt_counters *counters;
-       struct xt_table_info *private = table->private;
+       const struct xt_table_info *private = table->private;
        int ret = 0;
-       void *loc_cpu_entry;
+       const void *loc_cpu_entry;
 
        counters = alloc_counters(table);
        if (IS_ERR(counters))
@@ -975,8 +971,8 @@ copy_entries_to_user(unsigned int total_size,
        /* ... then go back and fix counters and names */
        for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
                unsigned int i;
-               struct ipt_entry_match *m;
-               struct ipt_entry_target *t;
+               const struct ipt_entry_match *m;
+               const struct ipt_entry_target *t;
 
                e = (struct ipt_entry *)(loc_cpu_entry + off);
                if (copy_to_user(userptr + off
@@ -1116,7 +1112,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
                                    "iptable_%s", name);
        if (t && !IS_ERR(t)) {
                struct ipt_getinfo info;
-               struct xt_table_info *private = t->private;
+               const struct xt_table_info *private = t->private;
 
 #ifdef CONFIG_COMPAT
                if (compat) {
@@ -1172,7 +1168,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
 
        t = xt_find_table_lock(net, AF_INET, get.name);
        if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
+               const struct xt_table_info *private = t->private;
                duprintf("t->private->number = %u\n", private->number);
                if (get.size == private->size)
                        ret = copy_entries_to_user(private->size,
@@ -1180,7 +1176,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
                else {
                        duprintf("get_entries: I've got %u not %u!\n",
                                 private->size, get.size);
-                       ret = -EINVAL;
+                       ret = -EAGAIN;
                }
                module_put(t->me);
                xt_table_unlock(t);
@@ -1337,11 +1333,11 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat
        struct xt_counters_info tmp;
        struct xt_counters *paddc;
        unsigned int num_counters;
-       char *name;
+       const char *name;
        int size;
        void *ptmp;
        struct xt_table *t;
-       struct xt_table_info *private;
+       const struct xt_table_info *private;
        int ret = 0;
        void *loc_cpu_entry;
 #ifdef CONFIG_COMPAT
@@ -1852,11 +1848,11 @@ compat_do_ipt_set_ctl(struct sock *sk,  int cmd, void __user *user,
 
        switch (cmd) {
        case IPT_SO_SET_REPLACE:
-               ret = compat_do_replace(sk->sk_net, user, len);
+               ret = compat_do_replace(sock_net(sk), user, len);
                break;
 
        case IPT_SO_SET_ADD_COUNTERS:
-               ret = do_add_counters(sk->sk_net, user, len, 1);
+               ret = do_add_counters(sock_net(sk), user, len, 1);
                break;
 
        default:
@@ -1878,11 +1874,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
                            void __user *userptr)
 {
        struct xt_counters *counters;
-       struct xt_table_info *private = table->private;
+       const struct xt_table_info *private = table->private;
        void __user *pos;
        unsigned int size;
        int ret = 0;
-       void *loc_cpu_entry;
+       const void *loc_cpu_entry;
        unsigned int i = 0;
 
        counters = alloc_counters(table);
@@ -1929,7 +1925,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
        xt_compat_lock(AF_INET);
        t = xt_find_table_lock(net, AF_INET, get.name);
        if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
+               const struct xt_table_info *private = t->private;
                struct xt_table_info info;
                duprintf("t->private->number = %u\n", private->number);
                ret = compat_table_info(private, &info);
@@ -1939,7 +1935,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
                } else if (!ret) {
                        duprintf("compat_get_entries: I've got %u not %u!\n",
                                 private->size, get.size);
-                       ret = -EINVAL;
+                       ret = -EAGAIN;
                }
                xt_compat_flush_offsets(AF_INET);
                module_put(t->me);
@@ -1963,10 +1959,10 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 
        switch (cmd) {
        case IPT_SO_GET_INFO:
-               ret = get_info(sk->sk_net, user, len, 1);
+               ret = get_info(sock_net(sk), user, len, 1);
                break;
        case IPT_SO_GET_ENTRIES:
-               ret = compat_get_entries(sk->sk_net, user, len);
+               ret = compat_get_entries(sock_net(sk), user, len);
                break;
        default:
                ret = do_ipt_get_ctl(sk, cmd, user, len);
@@ -1985,11 +1981,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
        switch (cmd) {
        case IPT_SO_SET_REPLACE:
-               ret = do_replace(sk->sk_net, user, len);
+               ret = do_replace(sock_net(sk), user, len);
                break;
 
        case IPT_SO_SET_ADD_COUNTERS:
-               ret = do_add_counters(sk->sk_net, user, len, 0);
+               ret = do_add_counters(sock_net(sk), user, len, 0);
                break;
 
        default:
@@ -2010,11 +2006,11 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 
        switch (cmd) {
        case IPT_SO_GET_INFO:
-               ret = get_info(sk->sk_net, user, len, 0);
+               ret = get_info(sock_net(sk), user, len, 0);
                break;
 
        case IPT_SO_GET_ENTRIES:
-               ret = get_entries(sk->sk_net, user, len);
+               ret = get_entries(sock_net(sk), user, len);
                break;
 
        case IPT_SO_GET_REVISION_MATCH:
@@ -2121,29 +2117,23 @@ icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
 }
 
 static bool
-icmp_match(const struct sk_buff *skb,
-          const struct net_device *in,
-          const struct net_device *out,
-          const struct xt_match *match,
-          const void *matchinfo,
-          int offset,
-          unsigned int protoff,
-          bool *hotdrop)
+icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
 {
-       struct icmphdr _icmph, *ic;
-       const struct ipt_icmp *icmpinfo = matchinfo;
+       const struct icmphdr *ic;
+       struct icmphdr _icmph;
+       const struct ipt_icmp *icmpinfo = par->matchinfo;
 
        /* Must not be a fragment. */
-       if (offset)
+       if (par->fragoff != 0)
                return false;
 
-       ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
+       ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
        if (ic == NULL) {
                /* We've been asked to examine this packet, and we
                 * can't.  Hence, no choice but to drop.
                 */
                duprintf("Dropping evil ICMP tinygram.\n");
-               *hotdrop = true;
+               *par->hotdrop = true;
                return false;
        }