[NETFILTER]: sip conntrack: do case insensitive SIP header search
Patrick McHardy [Wed, 29 Nov 2006 01:35:27 +0000 (02:35 +0100)]
SIP headers are generally case-insensitive, only SDP headers are
case sensitive.

Signed-off-by: Patrick McHardy <kaber@trash.net>

include/linux/netfilter_ipv4/ip_conntrack_sip.h
net/ipv4/netfilter/ip_conntrack_sip.c
net/ipv4/netfilter/ip_nat_sip.c

index 2a15eb5..51c65ac 100644 (file)
@@ -31,6 +31,7 @@ extern int ct_sip_get_info(const char *dptr, size_t dlen,
                           enum sip_header_pos pos);
 extern int ct_sip_lnlen(const char *line, const char *limit);
 extern const char *ct_sip_search(const char *needle, const char *haystack,
-                                 size_t needle_len, size_t haystack_len);
+                                size_t needle_len, size_t haystack_len,
+                                int case_sensitive);
 #endif /* __KERNEL__ */
 #endif /* __IP_CONNTRACK_SIP_H__ */
index cc31765..a9c0d1d 100644 (file)
@@ -64,6 +64,7 @@ struct sip_header_nfo {
        size_t          lnlen;
        size_t          snlen;
        size_t          ln_strlen;
+       int             case_sensitive;
        int             (*match_len)(const char *, const char *, int *);
 };
 
@@ -105,6 +106,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
                .match_len      = skp_digits_len
        },
        [POS_MEDIA] = {         /* SDP media info */
+               .case_sensitive = 1,
                .lname          = "\nm=",
                .lnlen          = sizeof("\nm=") - 1,
                .sname          = "\rm=",
@@ -114,6 +116,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
                .match_len      = digits_len
        },
        [POS_OWNER] = {         /* SDP owner address*/
+               .case_sensitive = 1,
                .lname          = "\no=",
                .lnlen          = sizeof("\no=") - 1,
                .sname          = "\ro=",
@@ -123,6 +126,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
                .match_len      = epaddr_len
        },
        [POS_CONNECTION] = {    /* SDP connection info */
+               .case_sensitive = 1,
                .lname          = "\nc=",
                .lnlen          = sizeof("\nc=") - 1,
                .sname          = "\rc=",
@@ -132,6 +136,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
                .match_len      = epaddr_len
        },
        [POS_SDP_HEADER] = {    /* SDP version header */
+               .case_sensitive = 1,
                .lname          = "\nv=",
                .lnlen          = sizeof("\nv=") - 1,
                .sname          = "\rv=",
@@ -161,13 +166,19 @@ EXPORT_SYMBOL_GPL(ct_sip_lnlen);
 
 /* Linear string search, case sensitive. */
 const char *ct_sip_search(const char *needle, const char *haystack,
-                          size_t needle_len, size_t haystack_len)
+                         size_t needle_len, size_t haystack_len,
+                         int case_sensitive)
 {
        const char *limit = haystack + (haystack_len - needle_len);
 
        while (haystack <= limit) {
-               if (memcmp(haystack, needle, needle_len) == 0)
-                       return haystack;
+               if (case_sensitive) {
+                       if (strncmp(haystack, needle, needle_len) == 0)
+                               return haystack;
+               } else {
+                       if (strnicmp(haystack, needle, needle_len) == 0)
+                               return haystack;
+               }
                haystack++;
        }
        return NULL;
@@ -280,7 +291,8 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
                        continue;
                }
                aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
-                                   ct_sip_lnlen(dptr, limit));
+                                   ct_sip_lnlen(dptr, limit),
+                                   hnfo->case_sensitive);
                if (!aux) {
                        DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
                               hnfo->lname);
index 47097aa..e16604c 100644 (file)
@@ -87,14 +87,15 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb,
                                       buffer, bufflen, POS_VIA))
                        return 0;
 
-               /* This search should ignore case, but later.. */
                aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
-                                   (*pskb)->len - dataoff);
+                                   (*pskb)->len - dataoff, 0);
                if (!aux)
                        return 0;
 
                if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
-                   ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
+                                  ct_sip_lnlen(aux,
+                                               *dptr + (*pskb)->len - dataoff),
+                                  1))
                        return 1;
 
                return mangle_sip_packet(pskb, ctinfo, ct, dptr,