aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-11-29 02:35:27 +0100
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-02 21:31:24 -0800
commit40883e8184947879f135605a05c0764c60656cc5 (patch)
treef45133bd4b1a33a9dd94ddad3f78ba442d1f2bea
parent9d5b8baa4e9ace9be113c6151aaeeb3c07a26fc8 (diff)
[NETFILTER]: sip conntrack: do case insensitive SIP header search
SIP headers are generally case-insensitive, only SDP headers are case sensitive. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_sip.h3
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c20
-rw-r--r--net/ipv4/netfilter/ip_nat_sip.c7
3 files changed, 22 insertions, 8 deletions
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
index 2a15eb51fd6..51c65ac18c5 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
@@ -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__ */
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index cc317658166..a9c0d1d3e56 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -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);
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 47097aac63d..e16604c4339 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -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,