netfilter: xtables: add struct xt_mtchk_param::net
[safe/jmp/linux-2.6] / net / ipv4 / netfilter / nf_nat_snmp_basic.c
index 07f2a49..0b9c7ce 100644 (file)
@@ -50,6 +50,7 @@
 #include <net/udp.h>
 
 #include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_nat_helper.h>
 
@@ -219,7 +220,7 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
                if (ch < 0x80)
                        *len = ch;
                else {
-                       cnt = (unsigned char) (ch & 0x7F);
+                       cnt = ch & 0x7F;
                        *len = 0;
 
                        while (cnt > 0) {
@@ -231,6 +232,11 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
                        }
                }
        }
+
+       /* don't trust len bigger than ctx buffer */
+       if (*len > ctx->end - ctx->pointer)
+               return 0;
+
        return 1;
 }
 
@@ -249,6 +255,10 @@ static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
        if (!asn1_length_decode(ctx, &def, &len))
                return 0;
 
+       /* primitive shall be definite, indefinite shall be constructed */
+       if (*con == ASN1_PRI && !def)
+               return 0;
+
        if (def)
                *eoc = ctx->pointer + len;
        else
@@ -260,7 +270,7 @@ static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
 {
        unsigned char ch;
 
-       if (eoc == 0) {
+       if (eoc == NULL) {
                if (!asn1_octet_decode(ctx, &ch))
                        return 0;
 
@@ -429,10 +439,15 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
                                     unsigned int *len)
 {
        unsigned long subid;
-       unsigned int  size;
        unsigned long *optr;
+       size_t size;
 
        size = eoc - ctx->pointer + 1;
+
+       /* first subid actually encodes first two subids */
+       if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
+               return 0;
+
        *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
        if (*oid == NULL) {
                if (net_ratelimit())
@@ -617,8 +632,7 @@ struct snmp_cnv
        int syntax;
 };
 
-static struct snmp_cnv snmp_conv [] =
-{
+static const struct snmp_cnv snmp_conv[] = {
        {ASN1_UNI, ASN1_NUL, SNMP_NULL},
        {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
        {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
@@ -643,7 +657,7 @@ static unsigned char snmp_tag_cls2syntax(unsigned int tag,
                                         unsigned int cls,
                                         unsigned short *syntax)
 {
-       struct snmp_cnv *cnv;
+       const struct snmp_cnv *cnv;
 
        cnv = snmp_conv;
 
@@ -728,6 +742,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
                        *obj = kmalloc(sizeof(struct snmp_object) + len,
                                       GFP_ATOMIC);
                        if (*obj == NULL) {
+                               kfree(p);
                                kfree(id);
                                if (net_ratelimit())
                                        printk("OOM in bsalg (%d)\n", __LINE__);
@@ -903,7 +918,7 @@ static inline void mangle_address(unsigned char *begin,
                u_int32_t old;
 
                if (debug)
-                       memcpy(&old, (unsigned char *)addr, sizeof(old));
+                       memcpy(&old, addr, sizeof(old));
 
                *addr = map->to;
 
@@ -915,8 +930,8 @@ static inline void mangle_address(unsigned char *begin,
                }
 
                if (debug)
-                       printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
-                              "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
+                       printk(KERN_DEBUG "bsalg: mapped %pI4 to %pI4\n",
+                              &old, addr);
        }
 }
 
@@ -998,7 +1013,7 @@ err_id_free:
  *
  *****************************************************************************/
 
-static void hex_dump(unsigned char *buf, size_t len)
+static void hex_dump(const unsigned char *buf, size_t len)
 {
        size_t i;
 
@@ -1023,7 +1038,7 @@ static int snmp_parse_mangle(unsigned char *msg,
        unsigned int cls, con, tag, vers, pdutype;
        struct asn1_ctx ctx;
        struct asn1_octstr comm;
-       struct snmp_object **obj;
+       struct snmp_object *obj;
 
        if (debug > 1)
                hex_dump(msg, len);
@@ -1079,7 +1094,7 @@ static int snmp_parse_mangle(unsigned char *msg,
        if (cls != ASN1_CTX || con != ASN1_CON)
                return 0;
        if (debug > 1) {
-               unsigned char *pdus[] = {
+               static const unsigned char *const pdus[] = {
                        [SNMP_PDU_GET] = "get",
                        [SNMP_PDU_NEXT] = "get-next",
                        [SNMP_PDU_RESPONSE] = "response",
@@ -1133,43 +1148,34 @@ static int snmp_parse_mangle(unsigned char *msg,
        if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
                return 0;
 
-       obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
-       if (obj == NULL) {
-               if (net_ratelimit())
-                       printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
-               return 0;
-       }
-
        while (!asn1_eoc_decode(&ctx, eoc)) {
                unsigned int i;
 
-               if (!snmp_object_decode(&ctx, obj)) {
-                       if (*obj) {
-                               kfree((*obj)->id);
-                               kfree(*obj);
+               if (!snmp_object_decode(&ctx, &obj)) {
+                       if (obj) {
+                               kfree(obj->id);
+                               kfree(obj);
                        }
-                       kfree(obj);
                        return 0;
                }
 
                if (debug > 1) {
                        printk(KERN_DEBUG "bsalg: object: ");
-                       for (i = 0; i < (*obj)->id_len; i++) {
+                       for (i = 0; i < obj->id_len; i++) {
                                if (i > 0)
                                        printk(".");
-                               printk("%lu", (*obj)->id[i]);
+                               printk("%lu", obj->id[i]);
                        }
-                       printk(": type=%u\n", (*obj)->type);
+                       printk(": type=%u\n", obj->type);
 
                }
 
-               if ((*obj)->type == SNMP_IPADDR)
+               if (obj->type == SNMP_IPADDR)
                        mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
 
-               kfree((*obj)->id);
-               kfree(*obj);
+               kfree(obj->id);
+               kfree(obj);
        }
-       kfree(obj);
 
        if (!asn1_eoc_decode(&ctx, eoc))
                return 0;
@@ -1231,8 +1237,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 {
        int dir = CTINFO2DIR(ctinfo);
        unsigned int ret;
-       struct iphdr *iph = ip_hdr(skb);
-       struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+       const struct iphdr *iph = ip_hdr(skb);
+       const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
 
        /* SNMP replies and originating SNMP traps get mangled */
        if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
@@ -1252,9 +1258,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
         */
        if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
                 if (net_ratelimit())
-                        printk(KERN_WARNING "SNMP: dropping malformed packet "
-                               "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
-                               NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+                        printk(KERN_WARNING "SNMP: dropping malformed packet src=%pI4 dst=%pI4\n",
+                               &iph->saddr, &iph->daddr);
                 return NF_DROP;
        }
 
@@ -1267,25 +1272,28 @@ static int help(struct sk_buff *skb, unsigned int protoff,
        return ret;
 }
 
+static const struct nf_conntrack_expect_policy snmp_exp_policy = {
+       .max_expected   = 0,
+       .timeout        = 180,
+};
+
 static struct nf_conntrack_helper snmp_helper __read_mostly = {
-       .max_expected           = 0,
-       .timeout                = 180,
        .me                     = THIS_MODULE,
        .help                   = help,
+       .expect_policy          = &snmp_exp_policy,
        .name                   = "snmp",
        .tuple.src.l3num        = AF_INET,
-       .tuple.src.u.udp.port   = __constant_htons(SNMP_PORT),
+       .tuple.src.u.udp.port   = cpu_to_be16(SNMP_PORT),
        .tuple.dst.protonum     = IPPROTO_UDP,
 };
 
 static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
-       .max_expected           = 0,
-       .timeout                = 180,
        .me                     = THIS_MODULE,
        .help                   = help,
+       .expect_policy          = &snmp_exp_policy,
        .name                   = "snmp_trap",
        .tuple.src.l3num        = AF_INET,
-       .tuple.src.u.udp.port   = __constant_htons(SNMP_TRAP_PORT),
+       .tuple.src.u.udp.port   = cpu_to_be16(SNMP_TRAP_PORT),
        .tuple.dst.protonum     = IPPROTO_UDP,
 };