aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-25 23:26:08 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-25 23:26:08 -0400
commit4ab9e64e5e3c0516577818804aaf13a630d67bc9 (patch)
tree70450c93e83f5038dc14da7614d669109e59a148 /net/ipv4
parenta9c1d35917c0c95c8f95a8e497fb91e301419693 (diff)
[NETFILTER]: nf_nat_sip: split up SDP mangling
The SDP connection addresses may be contained in the payload multiple times (in the session description and/or once per media description), currently only the session description is properly updated. Split up SDP mangling so the function setting up expectations only updates the media port, update connection addresses from media descriptions while parsing them and at the end update the session description when the final addresses are known. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c121
1 files changed, 84 insertions, 37 deletions
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index f73ab4883b75..4429069d9b42 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -316,45 +316,77 @@ static int mangle_content_len(struct sk_buff *skb,
316 buffer, buflen); 316 buffer, buflen);
317} 317}
318 318
319static unsigned mangle_sdp_packet(struct sk_buff *skb, 319static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
320 const char **dptr, unsigned int *datalen, 320 unsigned int dataoff, unsigned int *datalen,
321 enum sdp_header_types type, 321 enum sdp_header_types type,
322 enum sdp_header_types term,
322 char *buffer, int buflen) 323 char *buffer, int buflen)
323{ 324{
324 enum ip_conntrack_info ctinfo; 325 enum ip_conntrack_info ctinfo;
325 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 326 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
326 unsigned int matchlen, matchoff; 327 unsigned int matchlen, matchoff;
327 328
328 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, type, SDP_HDR_UNSPEC, 329 if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
329 &matchoff, &matchlen) <= 0) 330 &matchoff, &matchlen) <= 0)
330 return 0; 331 return 0;
331 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 332 return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
332 buffer, buflen); 333 buffer, buflen);
333} 334}
334 335
335static unsigned int mangle_sdp(struct sk_buff *skb, 336static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
336 enum ip_conntrack_info ctinfo, 337 unsigned int dataoff,
337 struct nf_conn *ct, 338 unsigned int *datalen,
338 __be32 newip, u_int16_t port, 339 enum sdp_header_types type,
339 const char **dptr, unsigned int *datalen) 340 enum sdp_header_types term,
341 const union nf_inet_addr *addr)
340{ 342{
341 char buffer[sizeof("nnn.nnn.nnn.nnn")]; 343 char buffer[sizeof("nnn.nnn.nnn.nnn")];
342 unsigned int bufflen; 344 unsigned int buflen;
343 345
344 /* Mangle owner and contact info. */ 346 buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
345 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); 347 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
346 if (!mangle_sdp_packet(skb, dptr, datalen, SDP_HDR_OWNER_IP4, 348 buffer, buflen))
347 buffer, bufflen))
348 return 0; 349 return 0;
349 350
350 if (!mangle_sdp_packet(skb, dptr, datalen, SDP_HDR_CONNECTION_IP4, 351 return mangle_content_len(skb, dptr, datalen);
351 buffer, bufflen)) 352}
353
354static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
355 const char **dptr,
356 unsigned int *datalen,
357 unsigned int matchoff,
358 unsigned int matchlen,
359 u_int16_t port)
360{
361 char buffer[sizeof("nnnnn")];
362 unsigned int buflen;
363
364 buflen = sprintf(buffer, "%u", port);
365 if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
366 buffer, buflen))
352 return 0; 367 return 0;
353 368
354 /* Mangle media port. */ 369 return mangle_content_len(skb, dptr, datalen);
355 bufflen = sprintf(buffer, "%u", port); 370}
356 if (!mangle_sdp_packet(skb, dptr, datalen, SDP_HDR_MEDIA, 371
357 buffer, bufflen)) 372static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
373 unsigned int dataoff,
374 unsigned int *datalen,
375 const union nf_inet_addr *addr)
376{
377 char buffer[sizeof("nnn.nnn.nnn.nnn")];
378 unsigned int buflen;
379
380 /* Mangle session description owner and contact addresses */
381 buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
382 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
383 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
384 buffer, buflen))
385 return 0;
386
387 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
388 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
389 buffer, buflen))
358 return 0; 390 return 0;
359 391
360 return mangle_content_len(skb, dptr, datalen); 392 return mangle_content_len(skb, dptr, datalen);
@@ -362,32 +394,35 @@ static unsigned int mangle_sdp(struct sk_buff *skb,
362 394
363/* So, this packet has hit the connection tracking matching code. 395/* So, this packet has hit the connection tracking matching code.
364 Mangle it, and change the expectation to match the new version. */ 396 Mangle it, and change the expectation to match the new version. */
365static unsigned int ip_nat_sdp(struct sk_buff *skb, 397static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
366 const char **dptr, unsigned int *datalen, 398 const char **dptr,
367 struct nf_conntrack_expect *rtp_exp, 399 unsigned int *datalen,
368 struct nf_conntrack_expect *rtcp_exp) 400 struct nf_conntrack_expect *rtp_exp,
401 struct nf_conntrack_expect *rtcp_exp,
402 unsigned int mediaoff,
403 unsigned int medialen,
404 union nf_inet_addr *rtp_addr)
369{ 405{
370 enum ip_conntrack_info ctinfo; 406 enum ip_conntrack_info ctinfo;
371 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 407 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
372 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 408 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
373 __be32 newip;
374 u_int16_t port; 409 u_int16_t port;
375 410
376 /* Connection will come from reply */ 411 /* Connection will come from reply */
377 if (ct->tuplehash[dir].tuple.src.u3.ip == 412 if (ct->tuplehash[dir].tuple.src.u3.ip ==
378 ct->tuplehash[!dir].tuple.dst.u3.ip) 413 ct->tuplehash[!dir].tuple.dst.u3.ip)
379 newip = rtp_exp->tuple.dst.u3.ip; 414 rtp_addr->ip = rtp_exp->tuple.dst.u3.ip;
380 else 415 else
381 newip = ct->tuplehash[!dir].tuple.dst.u3.ip; 416 rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
382 417
383 rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip; 418 rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip;
384 rtp_exp->tuple.dst.u3.ip = newip; 419 rtp_exp->tuple.dst.u3.ip = rtp_addr->ip;
385 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; 420 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
386 rtp_exp->dir = !dir; 421 rtp_exp->dir = !dir;
387 rtp_exp->expectfn = ip_nat_sip_expected; 422 rtp_exp->expectfn = ip_nat_sip_expected;
388 423
389 rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip; 424 rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip;
390 rtcp_exp->tuple.dst.u3.ip = newip; 425 rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip;
391 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; 426 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
392 rtcp_exp->dir = !dir; 427 rtcp_exp->dir = !dir;
393 rtcp_exp->expectfn = ip_nat_sip_expected; 428 rtcp_exp->expectfn = ip_nat_sip_expected;
@@ -405,21 +440,29 @@ static unsigned int ip_nat_sdp(struct sk_buff *skb,
405 } 440 }
406 441
407 if (port == 0) 442 if (port == 0)
408 return NF_DROP; 443 goto err1;
444
445 /* Update media port. */
446 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
447 !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port))
448 goto err2;
409 449
410 if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr, datalen)) {
411 nf_ct_unexpect_related(rtp_exp);
412 nf_ct_unexpect_related(rtcp_exp);
413 return NF_DROP;
414 }
415 return NF_ACCEPT; 450 return NF_ACCEPT;
451
452err2:
453 nf_ct_unexpect_related(rtp_exp);
454 nf_ct_unexpect_related(rtcp_exp);
455err1:
456 return NF_DROP;
416} 457}
417 458
418static void __exit nf_nat_sip_fini(void) 459static void __exit nf_nat_sip_fini(void)
419{ 460{
420 rcu_assign_pointer(nf_nat_sip_hook, NULL); 461 rcu_assign_pointer(nf_nat_sip_hook, NULL);
421 rcu_assign_pointer(nf_nat_sip_expect_hook, NULL); 462 rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
422 rcu_assign_pointer(nf_nat_sdp_hook, NULL); 463 rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
464 rcu_assign_pointer(nf_nat_sdp_session_hook, NULL);
465 rcu_assign_pointer(nf_nat_sdp_media_hook, NULL);
423 synchronize_rcu(); 466 synchronize_rcu();
424} 467}
425 468
@@ -427,10 +470,14 @@ static int __init nf_nat_sip_init(void)
427{ 470{
428 BUG_ON(nf_nat_sip_hook != NULL); 471 BUG_ON(nf_nat_sip_hook != NULL);
429 BUG_ON(nf_nat_sip_expect_hook != NULL); 472 BUG_ON(nf_nat_sip_expect_hook != NULL);
430 BUG_ON(nf_nat_sdp_hook != NULL); 473 BUG_ON(nf_nat_sdp_addr_hook != NULL);
474 BUG_ON(nf_nat_sdp_session_hook != NULL);
475 BUG_ON(nf_nat_sdp_media_hook != NULL);
431 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip); 476 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
432 rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect); 477 rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
433 rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp); 478 rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
479 rcu_assign_pointer(nf_nat_sdp_session_hook, ip_nat_sdp_session);
480 rcu_assign_pointer(nf_nat_sdp_media_hook, ip_nat_sdp_media);
434 return 0; 481 return 0;
435} 482}
436 483