[NETFILTER]: nf_conntrack_sip: kill request URI "header" definitions
authorPatrick McHardy <kaber@trash.net>
Wed, 26 Mar 2008 03:18:40 +0000 (20:18 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 26 Mar 2008 03:18:40 +0000 (20:18 -0700)
The request URI is not a header and needs to be treated differently than
real SIP headers. Add a seperate function for parsing it and get rid of
the POS_REQ_URI/POS_REG_REQ_URI definitions.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netfilter/nf_conntrack_sip.h
net/ipv4/netfilter/nf_nat_sip.c
net/netfilter/nf_conntrack_sip.c

index 9131cbc9b9dea9a4bbcd21b814a617990f25b4aa..480b26f40ce405e1531fd7892645697aab16cee1 100644 (file)
@@ -6,8 +6,6 @@
 #define SIP_TIMEOUT    3600
 
 enum sip_header_pos {
-       POS_REG_REQ_URI,
-       POS_REQ_URI,
        POS_FROM,
        POS_TO,
        POS_VIA,
@@ -59,6 +57,9 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
                                       unsigned int *datalen,
                                       struct nf_conntrack_expect *exp);
 
+extern int ct_sip_parse_request(const struct nf_conn *ct,
+                               const char *dptr, unsigned int datalen,
+                               unsigned int *matchoff, unsigned int *matchlen);
 extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
                            size_t dlen, unsigned int *matchoff,
                            unsigned int *matchlen, enum sip_header_pos pos);
index aa8a4f492baf659cc0a800fe1f0f35f4a0a9ace8..60151b5901a5888f23e6a375fc57622e447fe306 100644 (file)
@@ -78,20 +78,17 @@ static unsigned int mangle_packet(struct sk_buff *skb,
        return 1;
 }
 
-static int map_sip_addr(struct sk_buff *skb,
-                       const char **dptr, unsigned int *datalen,
-                       enum sip_header_pos pos, struct addr_map *map)
+static int map_addr(struct sk_buff *skb,
+                   const char **dptr, unsigned int *datalen,
+                   unsigned int matchoff, unsigned int matchlen,
+                   struct addr_map *map)
 {
        enum ip_conntrack_info ctinfo;
-       struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+       struct nf_conn *ct __maybe_unused = nf_ct_get(skb, &ctinfo);
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-       unsigned int matchlen, matchoff, addrlen;
+       unsigned int addrlen;
        char *addr;
 
-       if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
-                           pos) <= 0)
-               return 1;
-
        if ((matchlen == map->addr[dir].srciplen ||
             matchlen == map->addr[dir].srclen) &&
            strncmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
@@ -109,13 +106,27 @@ static int map_sip_addr(struct sk_buff *skb,
                             addr, addrlen);
 }
 
+static int map_sip_addr(struct sk_buff *skb,
+                       const char **dptr, unsigned int *datalen,
+                       enum sip_header_pos pos, struct addr_map *map)
+{
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+       unsigned int matchlen, matchoff;
+
+       if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
+                           pos) <= 0)
+               return 1;
+       return map_addr(skb, dptr, datalen, matchoff, matchlen, map);
+}
+
 static unsigned int ip_nat_sip(struct sk_buff *skb,
                               const char **dptr, unsigned int *datalen)
 {
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
-       enum sip_header_pos pos;
        struct addr_map map;
+       unsigned int matchoff, matchlen;
 
        if (*datalen < strlen("SIP/2.0"))
                return NF_ACCEPT;
@@ -124,18 +135,9 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 
        /* Basic rules: requests and responses. */
        if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
-               /* 10.2: Constructing the REGISTER Request:
-                *
-                * The "userinfo" and "@" components of the SIP URI MUST NOT
-                * be present.
-                */
-               if (*datalen >= strlen("REGISTER") &&
-                   strnicmp(*dptr, "REGISTER", strlen("REGISTER")) == 0)
-                       pos = POS_REG_REQ_URI;
-               else
-                       pos = POS_REQ_URI;
-
-               if (!map_sip_addr(skb, dptr, datalen, pos, &map))
+               if (ct_sip_parse_request(ct, *dptr, *datalen,
+                                        &matchoff, &matchlen) > 0 &&
+                   !map_addr(skb, dptr, datalen, matchoff, matchlen, &map))
                        return NF_DROP;
        }
 
index 801fcb3c749f1d0c6ab5a73c7172fc7b43f9f9eb..bb4396155681c7567a3342abf8d4782e59886ab3 100644 (file)
@@ -65,20 +65,6 @@ struct sip_header_nfo {
 };
 
 static const struct sip_header_nfo ct_sip_hdrs[] = {
-       [POS_REG_REQ_URI] = {   /* SIP REGISTER request URI */
-               .lname          = "sip:",
-               .lnlen          = sizeof("sip:") - 1,
-               .ln_str         = ":",
-               .ln_strlen      = sizeof(":") - 1,
-               .match_len      = epaddr_len,
-       },
-       [POS_REQ_URI] = {       /* SIP request URI */
-               .lname          = "sip:",
-               .lnlen          = sizeof("sip:") - 1,
-               .ln_str         = "@",
-               .ln_strlen      = sizeof("@") - 1,
-               .match_len      = epaddr_len,
-       },
        [POS_FROM] = {          /* SIP From header */
                .lname          = "From:",
                .lnlen          = sizeof("From:") - 1,
@@ -164,6 +150,18 @@ const char *ct_sip_search(const char *needle, const char *haystack,
 }
 EXPORT_SYMBOL_GPL(ct_sip_search);
 
+static int string_len(const struct nf_conn *ct, const char *dptr,
+                     const char *limit, int *shift)
+{
+       int len = 0;
+
+       while (dptr < limit && isalpha(*dptr)) {
+               dptr++;
+               len++;
+       }
+       return len;
+}
+
 static int digits_len(const struct nf_conn *ct, const char *dptr,
                      const char *limit, int *shift)
 {
@@ -258,6 +256,44 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
        return epaddr_len(ct, dptr, limit, shift);
 }
 
+/* Parse a SIP request line of the form:
+ *
+ * Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ *
+ * and return the offset and length of the address contained in the Request-URI.
+ */
+int ct_sip_parse_request(const struct nf_conn *ct,
+                        const char *dptr, unsigned int datalen,
+                        unsigned int *matchoff, unsigned int *matchlen)
+{
+       const char *start = dptr, *limit = dptr + datalen;
+       unsigned int mlen;
+       int shift = 0;
+
+       /* Skip method and following whitespace */
+       mlen = string_len(ct, dptr, limit, NULL);
+       if (!mlen)
+               return 0;
+       dptr += mlen;
+       if (++dptr >= limit)
+               return 0;
+
+       /* Find SIP URI */
+       limit -= strlen("sip:");
+       for (; dptr < limit; dptr++) {
+               if (*dptr == '\r' || *dptr == '\n')
+                       return -1;
+               if (strnicmp(dptr, "sip:", strlen("sip:")) == 0)
+                       break;
+       }
+       *matchlen = skp_epaddr_len(ct, dptr, limit, &shift);
+       if (!*matchlen)
+               return 0;
+       *matchoff = dptr - start + shift;
+       return 1;
+}
+EXPORT_SYMBOL_GPL(ct_sip_parse_request);
+
 /* Returns 0 if not found, -1 error parsing. */
 int ct_sip_get_info(const struct nf_conn *ct,
                    const char *dptr, size_t dlen,