aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-11-28 20:35:27 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:24 -0500
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 2a15eb51fd6b..51c65ac18c57 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,
31 enum sip_header_pos pos); 31 enum sip_header_pos pos);
32extern int ct_sip_lnlen(const char *line, const char *limit); 32extern int ct_sip_lnlen(const char *line, const char *limit);
33extern const char *ct_sip_search(const char *needle, const char *haystack, 33extern const char *ct_sip_search(const char *needle, const char *haystack,
34 size_t needle_len, size_t haystack_len); 34 size_t needle_len, size_t haystack_len,
35 int case_sensitive);
35#endif /* __KERNEL__ */ 36#endif /* __KERNEL__ */
36#endif /* __IP_CONNTRACK_SIP_H__ */ 37#endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index cc3176581667..a9c0d1d3e56f 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 {
64 size_t lnlen; 64 size_t lnlen;
65 size_t snlen; 65 size_t snlen;
66 size_t ln_strlen; 66 size_t ln_strlen;
67 int case_sensitive;
67 int (*match_len)(const char *, const char *, int *); 68 int (*match_len)(const char *, const char *, int *);
68}; 69};
69 70
@@ -105,6 +106,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
105 .match_len = skp_digits_len 106 .match_len = skp_digits_len
106 }, 107 },
107 [POS_MEDIA] = { /* SDP media info */ 108 [POS_MEDIA] = { /* SDP media info */
109 .case_sensitive = 1,
108 .lname = "\nm=", 110 .lname = "\nm=",
109 .lnlen = sizeof("\nm=") - 1, 111 .lnlen = sizeof("\nm=") - 1,
110 .sname = "\rm=", 112 .sname = "\rm=",
@@ -114,6 +116,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
114 .match_len = digits_len 116 .match_len = digits_len
115 }, 117 },
116 [POS_OWNER] = { /* SDP owner address*/ 118 [POS_OWNER] = { /* SDP owner address*/
119 .case_sensitive = 1,
117 .lname = "\no=", 120 .lname = "\no=",
118 .lnlen = sizeof("\no=") - 1, 121 .lnlen = sizeof("\no=") - 1,
119 .sname = "\ro=", 122 .sname = "\ro=",
@@ -123,6 +126,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
123 .match_len = epaddr_len 126 .match_len = epaddr_len
124 }, 127 },
125 [POS_CONNECTION] = { /* SDP connection info */ 128 [POS_CONNECTION] = { /* SDP connection info */
129 .case_sensitive = 1,
126 .lname = "\nc=", 130 .lname = "\nc=",
127 .lnlen = sizeof("\nc=") - 1, 131 .lnlen = sizeof("\nc=") - 1,
128 .sname = "\rc=", 132 .sname = "\rc=",
@@ -132,6 +136,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = {
132 .match_len = epaddr_len 136 .match_len = epaddr_len
133 }, 137 },
134 [POS_SDP_HEADER] = { /* SDP version header */ 138 [POS_SDP_HEADER] = { /* SDP version header */
139 .case_sensitive = 1,
135 .lname = "\nv=", 140 .lname = "\nv=",
136 .lnlen = sizeof("\nv=") - 1, 141 .lnlen = sizeof("\nv=") - 1,
137 .sname = "\rv=", 142 .sname = "\rv=",
@@ -161,13 +166,19 @@ EXPORT_SYMBOL_GPL(ct_sip_lnlen);
161 166
162/* Linear string search, case sensitive. */ 167/* Linear string search, case sensitive. */
163const char *ct_sip_search(const char *needle, const char *haystack, 168const char *ct_sip_search(const char *needle, const char *haystack,
164 size_t needle_len, size_t haystack_len) 169 size_t needle_len, size_t haystack_len,
170 int case_sensitive)
165{ 171{
166 const char *limit = haystack + (haystack_len - needle_len); 172 const char *limit = haystack + (haystack_len - needle_len);
167 173
168 while (haystack <= limit) { 174 while (haystack <= limit) {
169 if (memcmp(haystack, needle, needle_len) == 0) 175 if (case_sensitive) {
170 return haystack; 176 if (strncmp(haystack, needle, needle_len) == 0)
177 return haystack;
178 } else {
179 if (strnicmp(haystack, needle, needle_len) == 0)
180 return haystack;
181 }
171 haystack++; 182 haystack++;
172 } 183 }
173 return NULL; 184 return NULL;
@@ -280,7 +291,8 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
280 continue; 291 continue;
281 } 292 }
282 aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen, 293 aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
283 ct_sip_lnlen(dptr, limit)); 294 ct_sip_lnlen(dptr, limit),
295 hnfo->case_sensitive);
284 if (!aux) { 296 if (!aux) {
285 DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, 297 DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
286 hnfo->lname); 298 hnfo->lname);
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 47097aac63d8..e16604c4339d 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,
87 buffer, bufflen, POS_VIA)) 87 buffer, bufflen, POS_VIA))
88 return 0; 88 return 0;
89 89
90 /* This search should ignore case, but later.. */
91 aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1, 90 aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
92 (*pskb)->len - dataoff); 91 (*pskb)->len - dataoff, 0);
93 if (!aux) 92 if (!aux)
94 return 0; 93 return 0;
95 94
96 if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"), 95 if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
97 ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff))) 96 ct_sip_lnlen(aux,
97 *dptr + (*pskb)->len - dataoff),
98 1))
98 return 1; 99 return 1;
99 100
100 return mangle_sip_packet(pskb, ctinfo, ct, dptr, 101 return mangle_sip_packet(pskb, ctinfo, ct, dptr,