]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv4/netfilter/nf_nat_sip.c
netfilter: nf_conntrack_sip: pass data offset to NAT functions
[net-next-2.6.git] / net / ipv4 / netfilter / nf_nat_sip.c
index 07d61a57613c6a0a21685874b497559c2a005619..2454ea5abb79c88ca43b7363a26b66a8a0f093c2 100644 (file)
@@ -29,7 +29,7 @@ MODULE_DESCRIPTION("SIP NAT helper");
 MODULE_ALIAS("ip_nat_sip");
 
 
-static unsigned int mangle_packet(struct sk_buff *skb,
+static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff,
                                  const char **dptr, unsigned int *datalen,
                                  unsigned int matchoff, unsigned int matchlen,
                                  const char *buffer, unsigned int buflen)
@@ -42,12 +42,12 @@ static unsigned int mangle_packet(struct sk_buff *skb,
                return 0;
 
        /* Reload data pointer and adjust datalen value */
-       *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
+       *dptr = skb->data + dataoff;
        *datalen += buflen - matchlen;
        return 1;
 }
 
-static int map_addr(struct sk_buff *skb,
+static int map_addr(struct sk_buff *skb, unsigned int dataoff,
                    const char **dptr, unsigned int *datalen,
                    unsigned int matchoff, unsigned int matchlen,
                    union nf_inet_addr *addr, __be16 port)
@@ -76,11 +76,11 @@ static int map_addr(struct sk_buff *skb,
 
        buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport));
 
-       return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
+       return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
                             buffer, buflen);
 }
 
-static int map_sip_addr(struct sk_buff *skb,
+static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff,
                        const char **dptr, unsigned int *datalen,
                        enum sip_header_types type)
 {
@@ -93,16 +93,17 @@ static int map_sip_addr(struct sk_buff *skb,
        if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
                                    &matchoff, &matchlen, &addr, &port) <= 0)
                return 1;
-       return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port);
+       return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
+                       &addr, port);
 }
 
-static unsigned int ip_nat_sip(struct sk_buff *skb,
+static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
                               const char **dptr, unsigned int *datalen)
 {
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-       unsigned int dataoff, matchoff, matchlen;
+       unsigned int coff, matchoff, matchlen;
        union nf_inet_addr addr;
        __be16 port;
        int request, in_header;
@@ -112,7 +113,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
                if (ct_sip_parse_request(ct, *dptr, *datalen,
                                         &matchoff, &matchlen,
                                         &addr, &port) > 0 &&
-                   !map_addr(skb, dptr, datalen, matchoff, matchlen,
+                   !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
                              &addr, port))
                        return NF_DROP;
                request = 1;
@@ -138,7 +139,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
                                goto next;
                }
 
-               if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
+               if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
                              &addr, port))
                        return NF_DROP;
 
@@ -153,8 +154,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
                    addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
                        buflen = sprintf(buffer, "%pI4",
                                        &ct->tuplehash[!dir].tuple.dst.u3.ip);
-                       if (!mangle_packet(skb, dptr, datalen, poff, plen,
-                                          buffer, buflen))
+                       if (!mangle_packet(skb, dataoff, dptr, datalen,
+                                          poff, plen, buffer, buflen))
                                return NF_DROP;
                }
 
@@ -167,8 +168,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
                    addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
                        buflen = sprintf(buffer, "%pI4",
                                        &ct->tuplehash[!dir].tuple.src.u3.ip);
-                       if (!mangle_packet(skb, dptr, datalen, poff, plen,
-                                          buffer, buflen))
+                       if (!mangle_packet(skb, dataoff, dptr, datalen,
+                                          poff, plen, buffer, buflen))
                                return NF_DROP;
                }
 
@@ -181,27 +182,27 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
                    htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
                        __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
                        buflen = sprintf(buffer, "%u", ntohs(p));
-                       if (!mangle_packet(skb, dptr, datalen, poff, plen,
-                                          buffer, buflen))
+                       if (!mangle_packet(skb, dataoff, dptr, datalen,
+                                          poff, plen, buffer, buflen))
                                return NF_DROP;
                }
        }
 
 next:
        /* Translate Contact headers */
-       dataoff = 0;
+       coff = 0;
        in_header = 0;
-       while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen,
+       while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
                                       SIP_HDR_CONTACT, &in_header,
                                       &matchoff, &matchlen,
                                       &addr, &port) > 0) {
-               if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
+               if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
                              &addr, port))
                        return NF_DROP;
        }
 
-       if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) ||
-           !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO))
+       if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) ||
+           !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
                return NF_DROP;
        return NF_ACCEPT;
 }
@@ -232,7 +233,7 @@ static void ip_nat_sip_expected(struct nf_conn *ct,
        }
 }
 
-static unsigned int ip_nat_sip_expect(struct sk_buff *skb,
+static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff,
                                      const char **dptr, unsigned int *datalen,
                                      struct nf_conntrack_expect *exp,
                                      unsigned int matchoff,
@@ -279,8 +280,8 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb,
        if (exp->tuple.dst.u3.ip != exp->saved_ip ||
            exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
                buflen = sprintf(buffer, "%pI4:%u", &newip, port);
-               if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
-                                  buffer, buflen))
+               if (!mangle_packet(skb, dataoff, dptr, datalen,
+                                  matchoff, matchlen, buffer, buflen))
                        goto err;
        }
        return NF_ACCEPT;
@@ -290,7 +291,7 @@ err:
        return NF_DROP;
 }
 
-static int mangle_content_len(struct sk_buff *skb,
+static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff,
                              const char **dptr, unsigned int *datalen)
 {
        enum ip_conntrack_info ctinfo;
@@ -312,12 +313,13 @@ static int mangle_content_len(struct sk_buff *skb,
                return 0;
 
        buflen = sprintf(buffer, "%u", c_len);
-       return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
+       return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
                             buffer, buflen);
 }
 
-static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
-                            unsigned int dataoff, unsigned int *datalen,
+static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff,
+                            const char **dptr, unsigned int *datalen,
+                            unsigned int sdpoff,
                             enum sdp_header_types type,
                             enum sdp_header_types term,
                             char *buffer, int buflen)
@@ -326,16 +328,16 @@ static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        unsigned int matchlen, matchoff;
 
-       if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
+       if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
                                  &matchoff, &matchlen) <= 0)
                return -ENOENT;
-       return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
+       return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
                             buffer, buflen) ? 0 : -EINVAL;
 }
 
-static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
-                                   unsigned int dataoff,
-                                   unsigned int *datalen,
+static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff,
+                                   const char **dptr, unsigned int *datalen,
+                                   unsigned int sdpoff,
                                    enum sdp_header_types type,
                                    enum sdp_header_types term,
                                    const union nf_inet_addr *addr)
@@ -344,16 +346,15 @@ static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
        unsigned int buflen;
 
        buflen = sprintf(buffer, "%pI4", &addr->ip);
-       if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
+       if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term,
                              buffer, buflen))
                return 0;
 
-       return mangle_content_len(skb, dptr, datalen);
+       return mangle_content_len(skb, dataoff, dptr, datalen);
 }
 
-static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
-                                   const char **dptr,
-                                   unsigned int *datalen,
+static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff,
+                                   const char **dptr, unsigned int *datalen,
                                    unsigned int matchoff,
                                    unsigned int matchlen,
                                    u_int16_t port)
@@ -362,16 +363,16 @@ static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
        unsigned int buflen;
 
        buflen = sprintf(buffer, "%u", port);
-       if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
+       if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
                           buffer, buflen))
                return 0;
 
-       return mangle_content_len(skb, dptr, datalen);
+       return mangle_content_len(skb, dataoff, dptr, datalen);
 }
 
-static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
-                                      unsigned int dataoff,
-                                      unsigned int *datalen,
+static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff,
+                                      const char **dptr, unsigned int *datalen,
+                                      unsigned int sdpoff,
                                       const union nf_inet_addr *addr)
 {
        char buffer[sizeof("nnn.nnn.nnn.nnn")];
@@ -379,12 +380,12 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
 
        /* Mangle session description owner and contact addresses */
        buflen = sprintf(buffer, "%pI4", &addr->ip);
-       if (mangle_sdp_packet(skb, dptr, dataoff, datalen,
+       if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
                               SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
                               buffer, buflen))
                return 0;
 
-       switch (mangle_sdp_packet(skb, dptr, dataoff, datalen,
+       switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
                                  SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
                                  buffer, buflen)) {
        case 0:
@@ -401,14 +402,13 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
                return 0;
        }
 
-       return mangle_content_len(skb, dptr, datalen);
+       return mangle_content_len(skb, dataoff, dptr, datalen);
 }
 
 /* So, this packet has hit the connection tracking matching code.
    Mangle it, and change the expectation to match the new version. */
-static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
-                                    const char **dptr,
-                                    unsigned int *datalen,
+static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff,
+                                    const char **dptr, unsigned int *datalen,
                                     struct nf_conntrack_expect *rtp_exp,
                                     struct nf_conntrack_expect *rtcp_exp,
                                     unsigned int mediaoff,
@@ -456,7 +456,8 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
 
        /* Update media port. */
        if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
-           !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port))
+           !ip_nat_sdp_port(skb, dataoff, dptr, datalen,
+                            mediaoff, medialen, port))
                goto err2;
 
        return NF_ACCEPT;