aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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 /net/ipv4
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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c101
1 files changed, 51 insertions, 50 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");
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;