aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-11 06:23:53 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-11 06:23:53 -0500
commit3b6b9fab42fe98358d70735cf98d43fc18dc79c9 (patch)
tree98703e92c7259e35b7d6cd557bf0c1a6965f4e7c
parent54101f4f3bed87fa968b57f77f8ff3b09fd88bcf (diff)
netfilter: nf_conntrack_sip: pass data offset to NAT functions
When using TCP multiple SIP messages might be present in a single packet. A following patch will parse them by setting the dptr to the beginning of each message. The NAT helper needs to reload the dptr value after mangling the packet however, so it needs to know the offset of the message to the beginning of the packet. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter/nf_conntrack_sip.h14
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c101
-rw-r--r--net/netfilter/nf_conntrack_sip.c82
3 files changed, 105 insertions, 92 deletions
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index 23aa2ec6b7b7..2c6950b8bf7e 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -34,10 +34,10 @@ struct sdp_media_type {
34struct sip_handler { 34struct sip_handler {
35 const char *method; 35 const char *method;
36 unsigned int len; 36 unsigned int len;
37 int (*request)(struct sk_buff *skb, 37 int (*request)(struct sk_buff *skb, unsigned int dataoff,
38 const char **dptr, unsigned int *datalen, 38 const char **dptr, unsigned int *datalen,
39 unsigned int cseq); 39 unsigned int cseq);
40 int (*response)(struct sk_buff *skb, 40 int (*response)(struct sk_buff *skb, unsigned int dataoff,
41 const char **dptr, unsigned int *datalen, 41 const char **dptr, unsigned int *datalen,
42 unsigned int cseq, unsigned int code); 42 unsigned int cseq, unsigned int code);
43}; 43};
@@ -100,33 +100,39 @@ enum sdp_header_types {
100}; 100};
101 101
102extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, 102extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
103 unsigned int dataoff,
103 const char **dptr, 104 const char **dptr,
104 unsigned int *datalen); 105 unsigned int *datalen);
105extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, 106extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
107 unsigned int dataoff,
106 const char **dptr, 108 const char **dptr,
107 unsigned int *datalen, 109 unsigned int *datalen,
108 struct nf_conntrack_expect *exp, 110 struct nf_conntrack_expect *exp,
109 unsigned int matchoff, 111 unsigned int matchoff,
110 unsigned int matchlen); 112 unsigned int matchlen);
111extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, 113extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
112 const char **dptr,
113 unsigned int dataoff, 114 unsigned int dataoff,
115 const char **dptr,
114 unsigned int *datalen, 116 unsigned int *datalen,
117 unsigned int sdpoff,
115 enum sdp_header_types type, 118 enum sdp_header_types type,
116 enum sdp_header_types term, 119 enum sdp_header_types term,
117 const union nf_inet_addr *addr); 120 const union nf_inet_addr *addr);
118extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, 121extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
122 unsigned int dataoff,
119 const char **dptr, 123 const char **dptr,
120 unsigned int *datalen, 124 unsigned int *datalen,
121 unsigned int matchoff, 125 unsigned int matchoff,
122 unsigned int matchlen, 126 unsigned int matchlen,
123 u_int16_t port); 127 u_int16_t port);
124extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, 128extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
125 const char **dptr,
126 unsigned int dataoff, 129 unsigned int dataoff,
130 const char **dptr,
127 unsigned int *datalen, 131 unsigned int *datalen,
132 unsigned int sdpoff,
128 const union nf_inet_addr *addr); 133 const union nf_inet_addr *addr);
129extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, 134extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
135 unsigned int dataoff,
130 const char **dptr, 136 const char **dptr,
131 unsigned int *datalen, 137 unsigned int *datalen,
132 struct nf_conntrack_expect *rtp_exp, 138 struct nf_conntrack_expect *rtp_exp,
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 07d61a57613c..2454ea5abb79 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -29,7 +29,7 @@ MODULE_DESCRIPTION("SIP NAT helper");
29MODULE_ALIAS("ip_nat_sip"); 29MODULE_ALIAS("ip_nat_sip");
30 30
31 31
32static unsigned int mangle_packet(struct sk_buff *skb, 32static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff,
33 const char **dptr, unsigned int *datalen, 33 const char **dptr, unsigned int *datalen,
34 unsigned int matchoff, unsigned int matchlen, 34 unsigned int matchoff, unsigned int matchlen,
35 const char *buffer, unsigned int buflen) 35 const char *buffer, unsigned int buflen)
@@ -42,12 +42,12 @@ static unsigned int mangle_packet(struct sk_buff *skb,
42 return 0; 42 return 0;
43 43
44 /* Reload data pointer and adjust datalen value */ 44 /* Reload data pointer and adjust datalen value */
45 *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); 45 *dptr = skb->data + dataoff;
46 *datalen += buflen - matchlen; 46 *datalen += buflen - matchlen;
47 return 1; 47 return 1;
48} 48}
49 49
50static int map_addr(struct sk_buff *skb, 50static int map_addr(struct sk_buff *skb, unsigned int dataoff,
51 const char **dptr, unsigned int *datalen, 51 const char **dptr, unsigned int *datalen,
52 unsigned int matchoff, unsigned int matchlen, 52 unsigned int matchoff, unsigned int matchlen,
53 union nf_inet_addr *addr, __be16 port) 53 union nf_inet_addr *addr, __be16 port)
@@ -76,11 +76,11 @@ static int map_addr(struct sk_buff *skb,
76 76
77 buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport)); 77 buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport));
78 78
79 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 79 return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
80 buffer, buflen); 80 buffer, buflen);
81} 81}
82 82
83static int map_sip_addr(struct sk_buff *skb, 83static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff,
84 const char **dptr, unsigned int *datalen, 84 const char **dptr, unsigned int *datalen,
85 enum sip_header_types type) 85 enum sip_header_types type)
86{ 86{
@@ -93,16 +93,17 @@ static int map_sip_addr(struct sk_buff *skb,
93 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, 93 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
94 &matchoff, &matchlen, &addr, &port) <= 0) 94 &matchoff, &matchlen, &addr, &port) <= 0)
95 return 1; 95 return 1;
96 return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port); 96 return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
97 &addr, port);
97} 98}
98 99
99static unsigned int ip_nat_sip(struct sk_buff *skb, 100static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
100 const char **dptr, unsigned int *datalen) 101 const char **dptr, unsigned int *datalen)
101{ 102{
102 enum ip_conntrack_info ctinfo; 103 enum ip_conntrack_info ctinfo;
103 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 104 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
104 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 105 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
105 unsigned int dataoff, matchoff, matchlen; 106 unsigned int coff, matchoff, matchlen;
106 union nf_inet_addr addr; 107 union nf_inet_addr addr;
107 __be16 port; 108 __be16 port;
108 int request, in_header; 109 int request, in_header;
@@ -112,7 +113,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
112 if (ct_sip_parse_request(ct, *dptr, *datalen, 113 if (ct_sip_parse_request(ct, *dptr, *datalen,
113 &matchoff, &matchlen, 114 &matchoff, &matchlen,
114 &addr, &port) > 0 && 115 &addr, &port) > 0 &&
115 !map_addr(skb, dptr, datalen, matchoff, matchlen, 116 !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
116 &addr, port)) 117 &addr, port))
117 return NF_DROP; 118 return NF_DROP;
118 request = 1; 119 request = 1;
@@ -138,7 +139,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
138 goto next; 139 goto next;
139 } 140 }
140 141
141 if (!map_addr(skb, dptr, datalen, matchoff, matchlen, 142 if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
142 &addr, port)) 143 &addr, port))
143 return NF_DROP; 144 return NF_DROP;
144 145
@@ -153,8 +154,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
153 addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { 154 addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
154 buflen = sprintf(buffer, "%pI4", 155 buflen = sprintf(buffer, "%pI4",
155 &ct->tuplehash[!dir].tuple.dst.u3.ip); 156 &ct->tuplehash[!dir].tuple.dst.u3.ip);
156 if (!mangle_packet(skb, dptr, datalen, poff, plen, 157 if (!mangle_packet(skb, dataoff, dptr, datalen,
157 buffer, buflen)) 158 poff, plen, buffer, buflen))
158 return NF_DROP; 159 return NF_DROP;
159 } 160 }
160 161
@@ -167,8 +168,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
167 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { 168 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
168 buflen = sprintf(buffer, "%pI4", 169 buflen = sprintf(buffer, "%pI4",
169 &ct->tuplehash[!dir].tuple.src.u3.ip); 170 &ct->tuplehash[!dir].tuple.src.u3.ip);
170 if (!mangle_packet(skb, dptr, datalen, poff, plen, 171 if (!mangle_packet(skb, dataoff, dptr, datalen,
171 buffer, buflen)) 172 poff, plen, buffer, buflen))
172 return NF_DROP; 173 return NF_DROP;
173 } 174 }
174 175
@@ -181,27 +182,27 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
181 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { 182 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
182 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; 183 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
183 buflen = sprintf(buffer, "%u", ntohs(p)); 184 buflen = sprintf(buffer, "%u", ntohs(p));
184 if (!mangle_packet(skb, dptr, datalen, poff, plen, 185 if (!mangle_packet(skb, dataoff, dptr, datalen,
185 buffer, buflen)) 186 poff, plen, buffer, buflen))
186 return NF_DROP; 187 return NF_DROP;
187 } 188 }
188 } 189 }
189 190
190next: 191next:
191 /* Translate Contact headers */ 192 /* Translate Contact headers */
192 dataoff = 0; 193 coff = 0;
193 in_header = 0; 194 in_header = 0;
194 while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, 195 while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
195 SIP_HDR_CONTACT, &in_header, 196 SIP_HDR_CONTACT, &in_header,
196 &matchoff, &matchlen, 197 &matchoff, &matchlen,
197 &addr, &port) > 0) { 198 &addr, &port) > 0) {
198 if (!map_addr(skb, dptr, datalen, matchoff, matchlen, 199 if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
199 &addr, port)) 200 &addr, port))
200 return NF_DROP; 201 return NF_DROP;
201 } 202 }
202 203
203 if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) || 204 if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) ||
204 !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO)) 205 !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
205 return NF_DROP; 206 return NF_DROP;
206 return NF_ACCEPT; 207 return NF_ACCEPT;
207} 208}
@@ -232,7 +233,7 @@ static void ip_nat_sip_expected(struct nf_conn *ct,
232 } 233 }
233} 234}
234 235
235static unsigned int ip_nat_sip_expect(struct sk_buff *skb, 236static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff,
236 const char **dptr, unsigned int *datalen, 237 const char **dptr, unsigned int *datalen,
237 struct nf_conntrack_expect *exp, 238 struct nf_conntrack_expect *exp,
238 unsigned int matchoff, 239 unsigned int matchoff,
@@ -279,8 +280,8 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb,
279 if (exp->tuple.dst.u3.ip != exp->saved_ip || 280 if (exp->tuple.dst.u3.ip != exp->saved_ip ||
280 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { 281 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
281 buflen = sprintf(buffer, "%pI4:%u", &newip, port); 282 buflen = sprintf(buffer, "%pI4:%u", &newip, port);
282 if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, 283 if (!mangle_packet(skb, dataoff, dptr, datalen,
283 buffer, buflen)) 284 matchoff, matchlen, buffer, buflen))
284 goto err; 285 goto err;
285 } 286 }
286 return NF_ACCEPT; 287 return NF_ACCEPT;
@@ -290,7 +291,7 @@ err:
290 return NF_DROP; 291 return NF_DROP;
291} 292}
292 293
293static int mangle_content_len(struct sk_buff *skb, 294static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff,
294 const char **dptr, unsigned int *datalen) 295 const char **dptr, unsigned int *datalen)
295{ 296{
296 enum ip_conntrack_info ctinfo; 297 enum ip_conntrack_info ctinfo;
@@ -312,12 +313,13 @@ static int mangle_content_len(struct sk_buff *skb,
312 return 0; 313 return 0;
313 314
314 buflen = sprintf(buffer, "%u", c_len); 315 buflen = sprintf(buffer, "%u", c_len);
315 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 316 return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
316 buffer, buflen); 317 buffer, buflen);
317} 318}
318 319
319static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr, 320static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff,
320 unsigned int dataoff, unsigned int *datalen, 321 const char **dptr, unsigned int *datalen,
322 unsigned int sdpoff,
321 enum sdp_header_types type, 323 enum sdp_header_types type,
322 enum sdp_header_types term, 324 enum sdp_header_types term,
323 char *buffer, int buflen) 325 char *buffer, int buflen)
@@ -326,16 +328,16 @@ static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
326 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 328 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
327 unsigned int matchlen, matchoff; 329 unsigned int matchlen, matchoff;
328 330
329 if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term, 331 if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
330 &matchoff, &matchlen) <= 0) 332 &matchoff, &matchlen) <= 0)
331 return -ENOENT; 333 return -ENOENT;
332 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 334 return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
333 buffer, buflen) ? 0 : -EINVAL; 335 buffer, buflen) ? 0 : -EINVAL;
334} 336}
335 337
336static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, 338static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff,
337 unsigned int dataoff, 339 const char **dptr, unsigned int *datalen,
338 unsigned int *datalen, 340 unsigned int sdpoff,
339 enum sdp_header_types type, 341 enum sdp_header_types type,
340 enum sdp_header_types term, 342 enum sdp_header_types term,
341 const union nf_inet_addr *addr) 343 const union nf_inet_addr *addr)
@@ -344,16 +346,15 @@ static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
344 unsigned int buflen; 346 unsigned int buflen;
345 347
346 buflen = sprintf(buffer, "%pI4", &addr->ip); 348 buflen = sprintf(buffer, "%pI4", &addr->ip);
347 if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term, 349 if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term,
348 buffer, buflen)) 350 buffer, buflen))
349 return 0; 351 return 0;
350 352
351 return mangle_content_len(skb, dptr, datalen); 353 return mangle_content_len(skb, dataoff, dptr, datalen);
352} 354}
353 355
354static unsigned int ip_nat_sdp_port(struct sk_buff *skb, 356static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff,
355 const char **dptr, 357 const char **dptr, unsigned int *datalen,
356 unsigned int *datalen,
357 unsigned int matchoff, 358 unsigned int matchoff,
358 unsigned int matchlen, 359 unsigned int matchlen,
359 u_int16_t port) 360 u_int16_t port)
@@ -362,16 +363,16 @@ static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
362 unsigned int buflen; 363 unsigned int buflen;
363 364
364 buflen = sprintf(buffer, "%u", port); 365 buflen = sprintf(buffer, "%u", port);
365 if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, 366 if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
366 buffer, buflen)) 367 buffer, buflen))
367 return 0; 368 return 0;
368 369
369 return mangle_content_len(skb, dptr, datalen); 370 return mangle_content_len(skb, dataoff, dptr, datalen);
370} 371}
371 372
372static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, 373static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff,
373 unsigned int dataoff, 374 const char **dptr, unsigned int *datalen,
374 unsigned int *datalen, 375 unsigned int sdpoff,
375 const union nf_inet_addr *addr) 376 const union nf_inet_addr *addr)
376{ 377{
377 char buffer[sizeof("nnn.nnn.nnn.nnn")]; 378 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,
379 380
380 /* Mangle session description owner and contact addresses */ 381 /* Mangle session description owner and contact addresses */
381 buflen = sprintf(buffer, "%pI4", &addr->ip); 382 buflen = sprintf(buffer, "%pI4", &addr->ip);
382 if (mangle_sdp_packet(skb, dptr, dataoff, datalen, 383 if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
383 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, 384 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
384 buffer, buflen)) 385 buffer, buflen))
385 return 0; 386 return 0;
386 387
387 switch (mangle_sdp_packet(skb, dptr, dataoff, datalen, 388 switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
388 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, 389 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
389 buffer, buflen)) { 390 buffer, buflen)) {
390 case 0: 391 case 0:
@@ -401,14 +402,13 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
401 return 0; 402 return 0;
402 } 403 }
403 404
404 return mangle_content_len(skb, dptr, datalen); 405 return mangle_content_len(skb, dataoff, dptr, datalen);
405} 406}
406 407
407/* So, this packet has hit the connection tracking matching code. 408/* So, this packet has hit the connection tracking matching code.
408 Mangle it, and change the expectation to match the new version. */ 409 Mangle it, and change the expectation to match the new version. */
409static unsigned int ip_nat_sdp_media(struct sk_buff *skb, 410static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff,
410 const char **dptr, 411 const char **dptr, unsigned int *datalen,
411 unsigned int *datalen,
412 struct nf_conntrack_expect *rtp_exp, 412 struct nf_conntrack_expect *rtp_exp,
413 struct nf_conntrack_expect *rtcp_exp, 413 struct nf_conntrack_expect *rtcp_exp,
414 unsigned int mediaoff, 414 unsigned int mediaoff,
@@ -456,7 +456,8 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
456 456
457 /* Update media port. */ 457 /* Update media port. */
458 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && 458 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
459 !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port)) 459 !ip_nat_sdp_port(skb, dataoff, dptr, datalen,
460 mediaoff, medialen, port))
460 goto err2; 461 goto err2;
461 462
462 return NF_ACCEPT; 463 return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 0ca2f2b5c2fa..0ec37d6a2df7 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -50,12 +50,13 @@ module_param(sip_direct_media, int, 0600);
50MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " 50MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
51 "endpoints only (default 1)"); 51 "endpoints only (default 1)");
52 52
53unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, 53unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff,
54 const char **dptr, 54 const char **dptr,
55 unsigned int *datalen) __read_mostly; 55 unsigned int *datalen) __read_mostly;
56EXPORT_SYMBOL_GPL(nf_nat_sip_hook); 56EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
57 57
58unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, 58unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
59 unsigned int dataoff,
59 const char **dptr, 60 const char **dptr,
60 unsigned int *datalen, 61 unsigned int *datalen,
61 struct nf_conntrack_expect *exp, 62 struct nf_conntrack_expect *exp,
@@ -63,17 +64,17 @@ unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
63 unsigned int matchlen) __read_mostly; 64 unsigned int matchlen) __read_mostly;
64EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); 65EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
65 66
66unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, 67unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff,
67 const char **dptr, 68 const char **dptr,
68 unsigned int dataoff,
69 unsigned int *datalen, 69 unsigned int *datalen,
70 unsigned int sdpoff,
70 enum sdp_header_types type, 71 enum sdp_header_types type,
71 enum sdp_header_types term, 72 enum sdp_header_types term,
72 const union nf_inet_addr *addr) 73 const union nf_inet_addr *addr)
73 __read_mostly; 74 __read_mostly;
74EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); 75EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook);
75 76
76unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, 77unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff,
77 const char **dptr, 78 const char **dptr,
78 unsigned int *datalen, 79 unsigned int *datalen,
79 unsigned int matchoff, 80 unsigned int matchoff,
@@ -82,14 +83,15 @@ unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
82EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); 83EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook);
83 84
84unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, 85unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
85 const char **dptr,
86 unsigned int dataoff, 86 unsigned int dataoff,
87 const char **dptr,
87 unsigned int *datalen, 88 unsigned int *datalen,
89 unsigned int sdpoff,
88 const union nf_inet_addr *addr) 90 const union nf_inet_addr *addr)
89 __read_mostly; 91 __read_mostly;
90EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); 92EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook);
91 93
92unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, 94unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff,
93 const char **dptr, 95 const char **dptr,
94 unsigned int *datalen, 96 unsigned int *datalen,
95 struct nf_conntrack_expect *rtp_exp, 97 struct nf_conntrack_expect *rtp_exp,
@@ -729,7 +731,7 @@ static void flush_expectations(struct nf_conn *ct, bool media)
729 spin_unlock_bh(&nf_conntrack_lock); 731 spin_unlock_bh(&nf_conntrack_lock);
730} 732}
731 733
732static int set_expected_rtp_rtcp(struct sk_buff *skb, 734static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff,
733 const char **dptr, unsigned int *datalen, 735 const char **dptr, unsigned int *datalen,
734 union nf_inet_addr *daddr, __be16 port, 736 union nf_inet_addr *daddr, __be16 port,
735 enum sip_expectation_classes class, 737 enum sip_expectation_classes class,
@@ -806,7 +808,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
806 if (direct_rtp) { 808 if (direct_rtp) {
807 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); 809 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook);
808 if (nf_nat_sdp_port && 810 if (nf_nat_sdp_port &&
809 !nf_nat_sdp_port(skb, dptr, datalen, 811 !nf_nat_sdp_port(skb, dataoff, dptr, datalen,
810 mediaoff, medialen, ntohs(rtp_port))) 812 mediaoff, medialen, ntohs(rtp_port)))
811 goto err1; 813 goto err1;
812 } 814 }
@@ -828,7 +830,8 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
828 830
829 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); 831 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
830 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) 832 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
831 ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp, 833 ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen,
834 rtp_exp, rtcp_exp,
832 mediaoff, medialen, daddr); 835 mediaoff, medialen, daddr);
833 else { 836 else {
834 if (nf_ct_expect_related(rtp_exp) == 0) { 837 if (nf_ct_expect_related(rtp_exp) == 0) {
@@ -867,7 +870,7 @@ static const struct sdp_media_type *sdp_media_type(const char *dptr,
867 return NULL; 870 return NULL;
868} 871}
869 872
870static int process_sdp(struct sk_buff *skb, 873static int process_sdp(struct sk_buff *skb, unsigned int dataoff,
871 const char **dptr, unsigned int *datalen, 874 const char **dptr, unsigned int *datalen,
872 unsigned int cseq) 875 unsigned int cseq)
873{ 876{
@@ -942,7 +945,7 @@ static int process_sdp(struct sk_buff *skb,
942 else 945 else
943 return NF_DROP; 946 return NF_DROP;
944 947
945 ret = set_expected_rtp_rtcp(skb, dptr, datalen, 948 ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen,
946 &rtp_addr, htons(port), t->class, 949 &rtp_addr, htons(port), t->class,
947 mediaoff, medialen); 950 mediaoff, medialen);
948 if (ret != NF_ACCEPT) 951 if (ret != NF_ACCEPT)
@@ -950,8 +953,9 @@ static int process_sdp(struct sk_buff *skb,
950 953
951 /* Update media connection address if present */ 954 /* Update media connection address if present */
952 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { 955 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
953 ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen, 956 ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen,
954 c_hdr, SDP_HDR_MEDIA, &rtp_addr); 957 mediaoff, c_hdr, SDP_HDR_MEDIA,
958 &rtp_addr);
955 if (ret != NF_ACCEPT) 959 if (ret != NF_ACCEPT)
956 return ret; 960 return ret;
957 } 961 }
@@ -961,14 +965,15 @@ static int process_sdp(struct sk_buff *skb,
961 /* Update session connection and owner addresses */ 965 /* Update session connection and owner addresses */
962 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); 966 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
963 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) 967 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
964 ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr); 968 ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff,
969 &rtp_addr);
965 970
966 if (ret == NF_ACCEPT && i > 0) 971 if (ret == NF_ACCEPT && i > 0)
967 help->help.ct_sip_info.invite_cseq = cseq; 972 help->help.ct_sip_info.invite_cseq = cseq;
968 973
969 return ret; 974 return ret;
970} 975}
971static int process_invite_response(struct sk_buff *skb, 976static int process_invite_response(struct sk_buff *skb, unsigned int dataoff,
972 const char **dptr, unsigned int *datalen, 977 const char **dptr, unsigned int *datalen,
973 unsigned int cseq, unsigned int code) 978 unsigned int cseq, unsigned int code)
974{ 979{
@@ -978,13 +983,13 @@ static int process_invite_response(struct sk_buff *skb,
978 983
979 if ((code >= 100 && code <= 199) || 984 if ((code >= 100 && code <= 199) ||
980 (code >= 200 && code <= 299)) 985 (code >= 200 && code <= 299))
981 return process_sdp(skb, dptr, datalen, cseq); 986 return process_sdp(skb, dataoff, dptr, datalen, cseq);
982 else if (help->help.ct_sip_info.invite_cseq == cseq) 987 else if (help->help.ct_sip_info.invite_cseq == cseq)
983 flush_expectations(ct, true); 988 flush_expectations(ct, true);
984 return NF_ACCEPT; 989 return NF_ACCEPT;
985} 990}
986 991
987static int process_update_response(struct sk_buff *skb, 992static int process_update_response(struct sk_buff *skb, unsigned int dataoff,
988 const char **dptr, unsigned int *datalen, 993 const char **dptr, unsigned int *datalen,
989 unsigned int cseq, unsigned int code) 994 unsigned int cseq, unsigned int code)
990{ 995{
@@ -994,13 +999,13 @@ static int process_update_response(struct sk_buff *skb,
994 999
995 if ((code >= 100 && code <= 199) || 1000 if ((code >= 100 && code <= 199) ||
996 (code >= 200 && code <= 299)) 1001 (code >= 200 && code <= 299))
997 return process_sdp(skb, dptr, datalen, cseq); 1002 return process_sdp(skb, dataoff, dptr, datalen, cseq);
998 else if (help->help.ct_sip_info.invite_cseq == cseq) 1003 else if (help->help.ct_sip_info.invite_cseq == cseq)
999 flush_expectations(ct, true); 1004 flush_expectations(ct, true);
1000 return NF_ACCEPT; 1005 return NF_ACCEPT;
1001} 1006}
1002 1007
1003static int process_prack_response(struct sk_buff *skb, 1008static int process_prack_response(struct sk_buff *skb, unsigned int dataoff,
1004 const char **dptr, unsigned int *datalen, 1009 const char **dptr, unsigned int *datalen,
1005 unsigned int cseq, unsigned int code) 1010 unsigned int cseq, unsigned int code)
1006{ 1011{
@@ -1010,13 +1015,13 @@ static int process_prack_response(struct sk_buff *skb,
1010 1015
1011 if ((code >= 100 && code <= 199) || 1016 if ((code >= 100 && code <= 199) ||
1012 (code >= 200 && code <= 299)) 1017 (code >= 200 && code <= 299))
1013 return process_sdp(skb, dptr, datalen, cseq); 1018 return process_sdp(skb, dataoff, dptr, datalen, cseq);
1014 else if (help->help.ct_sip_info.invite_cseq == cseq) 1019 else if (help->help.ct_sip_info.invite_cseq == cseq)
1015 flush_expectations(ct, true); 1020 flush_expectations(ct, true);
1016 return NF_ACCEPT; 1021 return NF_ACCEPT;
1017} 1022}
1018 1023
1019static int process_bye_request(struct sk_buff *skb, 1024static int process_bye_request(struct sk_buff *skb, unsigned int dataoff,
1020 const char **dptr, unsigned int *datalen, 1025 const char **dptr, unsigned int *datalen,
1021 unsigned int cseq) 1026 unsigned int cseq)
1022{ 1027{
@@ -1031,7 +1036,7 @@ static int process_bye_request(struct sk_buff *skb,
1031 * signalling connections. The expectation is marked inactive and is activated 1036 * signalling connections. The expectation is marked inactive and is activated
1032 * when receiving a response indicating success from the registrar. 1037 * when receiving a response indicating success from the registrar.
1033 */ 1038 */
1034static int process_register_request(struct sk_buff *skb, 1039static int process_register_request(struct sk_buff *skb, unsigned int dataoff,
1035 const char **dptr, unsigned int *datalen, 1040 const char **dptr, unsigned int *datalen,
1036 unsigned int cseq) 1041 unsigned int cseq)
1037{ 1042{
@@ -1101,7 +1106,7 @@ static int process_register_request(struct sk_buff *skb,
1101 1106
1102 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); 1107 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
1103 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) 1108 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
1104 ret = nf_nat_sip_expect(skb, dptr, datalen, exp, 1109 ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp,
1105 matchoff, matchlen); 1110 matchoff, matchlen);
1106 else { 1111 else {
1107 if (nf_ct_expect_related(exp) != 0) 1112 if (nf_ct_expect_related(exp) != 0)
@@ -1117,7 +1122,7 @@ store_cseq:
1117 return ret; 1122 return ret;
1118} 1123}
1119 1124
1120static int process_register_response(struct sk_buff *skb, 1125static int process_register_response(struct sk_buff *skb, unsigned int dataoff,
1121 const char **dptr, unsigned int *datalen, 1126 const char **dptr, unsigned int *datalen,
1122 unsigned int cseq, unsigned int code) 1127 unsigned int cseq, unsigned int code)
1123{ 1128{
@@ -1127,7 +1132,7 @@ static int process_register_response(struct sk_buff *skb,
1127 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 1132 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
1128 union nf_inet_addr addr; 1133 union nf_inet_addr addr;
1129 __be16 port; 1134 __be16 port;
1130 unsigned int matchoff, matchlen, dataoff = 0; 1135 unsigned int matchoff, matchlen, coff = 0;
1131 unsigned int expires = 0; 1136 unsigned int expires = 0;
1132 int in_contact = 0, ret; 1137 int in_contact = 0, ret;
1133 1138
@@ -1154,7 +1159,7 @@ static int process_register_response(struct sk_buff *skb,
1154 while (1) { 1159 while (1) {
1155 unsigned int c_expires = expires; 1160 unsigned int c_expires = expires;
1156 1161
1157 ret = ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, 1162 ret = ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
1158 SIP_HDR_CONTACT, &in_contact, 1163 SIP_HDR_CONTACT, &in_contact,
1159 &matchoff, &matchlen, 1164 &matchoff, &matchlen,
1160 &addr, &port); 1165 &addr, &port);
@@ -1193,13 +1198,13 @@ static const struct sip_handler sip_handlers[] = {
1193 SIP_HANDLER("REGISTER", process_register_request, process_register_response), 1198 SIP_HANDLER("REGISTER", process_register_request, process_register_response),
1194}; 1199};
1195 1200
1196static int process_sip_response(struct sk_buff *skb, 1201static int process_sip_response(struct sk_buff *skb, unsigned int dataoff,
1197 const char **dptr, unsigned int *datalen) 1202 const char **dptr, unsigned int *datalen)
1198{ 1203{
1199 enum ip_conntrack_info ctinfo; 1204 enum ip_conntrack_info ctinfo;
1200 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1205 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1201 unsigned int matchoff, matchlen; 1206 unsigned int matchoff, matchlen, matchend;
1202 unsigned int code, cseq, dataoff, i; 1207 unsigned int code, cseq, i;
1203 1208
1204 if (*datalen < strlen("SIP/2.0 200")) 1209 if (*datalen < strlen("SIP/2.0 200"))
1205 return NF_ACCEPT; 1210 return NF_ACCEPT;
@@ -1213,7 +1218,7 @@ static int process_sip_response(struct sk_buff *skb,
1213 cseq = simple_strtoul(*dptr + matchoff, NULL, 10); 1218 cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
1214 if (!cseq) 1219 if (!cseq)
1215 return NF_DROP; 1220 return NF_DROP;
1216 dataoff = matchoff + matchlen + 1; 1221 matchend = matchoff + matchlen + 1;
1217 1222
1218 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1223 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
1219 const struct sip_handler *handler; 1224 const struct sip_handler *handler;
@@ -1221,15 +1226,16 @@ static int process_sip_response(struct sk_buff *skb,
1221 handler = &sip_handlers[i]; 1226 handler = &sip_handlers[i];
1222 if (handler->response == NULL) 1227 if (handler->response == NULL)
1223 continue; 1228 continue;
1224 if (*datalen < dataoff + handler->len || 1229 if (*datalen < matchend + handler->len ||
1225 strnicmp(*dptr + dataoff, handler->method, handler->len)) 1230 strnicmp(*dptr + matchend, handler->method, handler->len))
1226 continue; 1231 continue;
1227 return handler->response(skb, dptr, datalen, cseq, code); 1232 return handler->response(skb, dataoff, dptr, datalen,
1233 cseq, code);
1228 } 1234 }
1229 return NF_ACCEPT; 1235 return NF_ACCEPT;
1230} 1236}
1231 1237
1232static int process_sip_request(struct sk_buff *skb, 1238static int process_sip_request(struct sk_buff *skb, unsigned int dataoff,
1233 const char **dptr, unsigned int *datalen) 1239 const char **dptr, unsigned int *datalen)
1234{ 1240{
1235 enum ip_conntrack_info ctinfo; 1241 enum ip_conntrack_info ctinfo;
@@ -1254,7 +1260,7 @@ static int process_sip_request(struct sk_buff *skb,
1254 if (!cseq) 1260 if (!cseq)
1255 return NF_DROP; 1261 return NF_DROP;
1256 1262
1257 return handler->request(skb, dptr, datalen, cseq); 1263 return handler->request(skb, dataoff, dptr, datalen, cseq);
1258 } 1264 }
1259 return NF_ACCEPT; 1265 return NF_ACCEPT;
1260} 1266}
@@ -1288,13 +1294,13 @@ static int sip_help(struct sk_buff *skb,
1288 return NF_ACCEPT; 1294 return NF_ACCEPT;
1289 1295
1290 if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) 1296 if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
1291 ret = process_sip_request(skb, &dptr, &datalen); 1297 ret = process_sip_request(skb, dataoff, &dptr, &datalen);
1292 else 1298 else
1293 ret = process_sip_response(skb, &dptr, &datalen); 1299 ret = process_sip_response(skb, dataoff, &dptr, &datalen);
1294 1300
1295 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { 1301 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
1296 nf_nat_sip = rcu_dereference(nf_nat_sip_hook); 1302 nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
1297 if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen)) 1303 if (nf_nat_sip && !nf_nat_sip(skb, dataoff, &dptr, &datalen))
1298 ret = NF_DROP; 1304 ret = NF_DROP;
1299 } 1305 }
1300 1306