diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/nf_nat_sip.c | 101 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_sip.c | 82 |
2 files changed, 95 insertions, 88 deletions
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"); | |||
29 | MODULE_ALIAS("ip_nat_sip"); | 29 | MODULE_ALIAS("ip_nat_sip"); |
30 | 30 | ||
31 | 31 | ||
32 | static unsigned int mangle_packet(struct sk_buff *skb, | 32 | static 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 | ||
50 | static int map_addr(struct sk_buff *skb, | 50 | static 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 | ||
83 | static int map_sip_addr(struct sk_buff *skb, | 83 | static 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 | ||
99 | static unsigned int ip_nat_sip(struct sk_buff *skb, | 100 | static 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 | ||
190 | next: | 191 | next: |
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 | ||
235 | static unsigned int ip_nat_sip_expect(struct sk_buff *skb, | 236 | static 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 | ||
293 | static int mangle_content_len(struct sk_buff *skb, | 294 | static 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 | ||
319 | static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr, | 320 | static 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 | ||
336 | static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, | 338 | static 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 | ||
354 | static unsigned int ip_nat_sdp_port(struct sk_buff *skb, | 356 | static 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 | ||
372 | static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, | 373 | static 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. */ |
409 | static unsigned int ip_nat_sdp_media(struct sk_buff *skb, | 410 | static 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); | |||
50 | MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " | 50 | MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " |
51 | "endpoints only (default 1)"); | 51 | "endpoints only (default 1)"); |
52 | 52 | ||
53 | unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, | 53 | unsigned 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; |
56 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); | 56 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); |
57 | 57 | ||
58 | unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, | 58 | unsigned 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; |
64 | EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); | 65 | EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); |
65 | 66 | ||
66 | unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, | 67 | unsigned 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; |
74 | EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); | 75 | EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); |
75 | 76 | ||
76 | unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, | 77 | unsigned 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, | |||
82 | EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); | 83 | EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); |
83 | 84 | ||
84 | unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, | 85 | unsigned 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; |
90 | EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); | 92 | EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); |
91 | 93 | ||
92 | unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, | 94 | unsigned 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 | ||
732 | static int set_expected_rtp_rtcp(struct sk_buff *skb, | 734 | static 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 | ||
870 | static int process_sdp(struct sk_buff *skb, | 873 | static 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 | } |
971 | static int process_invite_response(struct sk_buff *skb, | 976 | static 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 | ||
987 | static int process_update_response(struct sk_buff *skb, | 992 | static 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 | ||
1003 | static int process_prack_response(struct sk_buff *skb, | 1008 | static 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 | ||
1019 | static int process_bye_request(struct sk_buff *skb, | 1024 | static 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 | */ |
1034 | static int process_register_request(struct sk_buff *skb, | 1039 | static 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 | ||
1120 | static int process_register_response(struct sk_buff *skb, | 1125 | static 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 | ||
1196 | static int process_sip_response(struct sk_buff *skb, | 1201 | static 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 | ||
1232 | static int process_sip_request(struct sk_buff *skb, | 1238 | static 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 | ||