aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/netfilter/nf_conntrack_sip.h25
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c121
-rw-r--r--net/netfilter/nf_conntrack_sip.c142
3 files changed, 219 insertions, 69 deletions
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index 6ddf95f51fb5..eca3ad3f28dc 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -93,11 +93,26 @@ extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
93 struct nf_conntrack_expect *exp, 93 struct nf_conntrack_expect *exp,
94 unsigned int matchoff, 94 unsigned int matchoff,
95 unsigned int matchlen); 95 unsigned int matchlen);
96extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, 96extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
97 const char **dptr, 97 const char **dptr,
98 unsigned int *datalen, 98 unsigned int dataoff,
99 struct nf_conntrack_expect *rtp_exp, 99 unsigned int *datalen,
100 struct nf_conntrack_expect *rtcp_exp); 100 enum sdp_header_types type,
101 enum sdp_header_types term,
102 const union nf_inet_addr *addr);
103extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
104 const char **dptr,
105 unsigned int dataoff,
106 unsigned int *datalen,
107 const union nf_inet_addr *addr);
108extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
109 const char **dptr,
110 unsigned int *datalen,
111 struct nf_conntrack_expect *rtp_exp,
112 struct nf_conntrack_expect *rtcp_exp,
113 unsigned int mediaoff,
114 unsigned int medialen,
115 union nf_inet_addr *rtp_addr);
101 116
102extern int ct_sip_parse_request(const struct nf_conn *ct, 117extern int ct_sip_parse_request(const struct nf_conn *ct,
103 const char *dptr, unsigned int datalen, 118 const char *dptr, unsigned int datalen,
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
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 217262e23403..f929add324f3 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -60,13 +60,34 @@ unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
60 unsigned int matchlen) __read_mostly; 60 unsigned int matchlen) __read_mostly;
61EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); 61EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
62 62
63unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, 63unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
64 const char **dptr, 64 const char **dptr,
65 unsigned int *datalen, 65 unsigned int dataoff,
66 struct nf_conntrack_expect *rtp_exp, 66 unsigned int *datalen,
67 struct nf_conntrack_expect *rtcp_exp) 67 enum sdp_header_types type,
68 __read_mostly; 68 enum sdp_header_types term,
69EXPORT_SYMBOL_GPL(nf_nat_sdp_hook); 69 const union nf_inet_addr *addr)
70 __read_mostly;
71EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook);
72
73unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
74 const char **dptr,
75 unsigned int dataoff,
76 unsigned int *datalen,
77 const union nf_inet_addr *addr)
78 __read_mostly;
79EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook);
80
81unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
82 const char **dptr,
83 unsigned int *datalen,
84 struct nf_conntrack_expect *rtp_exp,
85 struct nf_conntrack_expect *rtcp_exp,
86 unsigned int mediaoff,
87 unsigned int medialen,
88 union nf_inet_addr *rtp_addr)
89 __read_mostly;
90EXPORT_SYMBOL_GPL(nf_nat_sdp_media_hook);
70 91
71static int string_len(const struct nf_conn *ct, const char *dptr, 92static int string_len(const struct nf_conn *ct, const char *dptr,
72 const char *limit, int *shift) 93 const char *limit, int *shift)
@@ -613,6 +634,26 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
613} 634}
614EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header); 635EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header);
615 636
637static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,
638 unsigned int dataoff, unsigned int datalen,
639 enum sdp_header_types type,
640 enum sdp_header_types term,
641 unsigned int *matchoff, unsigned int *matchlen,
642 union nf_inet_addr *addr)
643{
644 int ret;
645
646 ret = ct_sip_get_sdp_header(ct, dptr, dataoff, datalen, type, term,
647 matchoff, matchlen);
648 if (ret <= 0)
649 return ret;
650
651 if (!parse_addr(ct, dptr + *matchoff, NULL, addr,
652 dptr + *matchoff + *matchlen))
653 return -1;
654 return 1;
655}
656
616static int refresh_signalling_expectation(struct nf_conn *ct, 657static int refresh_signalling_expectation(struct nf_conn *ct,
617 union nf_inet_addr *addr, 658 union nf_inet_addr *addr,
618 __be16 port, 659 __be16 port,
@@ -663,7 +704,8 @@ static void flush_expectations(struct nf_conn *ct, bool media)
663 704
664static int set_expected_rtp_rtcp(struct sk_buff *skb, 705static int set_expected_rtp_rtcp(struct sk_buff *skb,
665 const char **dptr, unsigned int *datalen, 706 const char **dptr, unsigned int *datalen,
666 union nf_inet_addr *daddr, __be16 port) 707 union nf_inet_addr *daddr, __be16 port,
708 unsigned int mediaoff, unsigned int medialen)
667{ 709{
668 struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp; 710 struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp;
669 enum ip_conntrack_info ctinfo; 711 enum ip_conntrack_info ctinfo;
@@ -675,7 +717,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
675 int skip_expect = 0, ret = NF_DROP; 717 int skip_expect = 0, ret = NF_DROP;
676 u_int16_t base_port; 718 u_int16_t base_port;
677 __be16 rtp_port, rtcp_port; 719 __be16 rtp_port, rtcp_port;
678 typeof(nf_nat_sdp_hook) nf_nat_sdp; 720 typeof(nf_nat_sdp_media_hook) nf_nat_sdp_media;
679 721
680 saddr = NULL; 722 saddr = NULL;
681 if (sip_direct_media) { 723 if (sip_direct_media) {
@@ -724,9 +766,10 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
724 nf_ct_expect_init(rtcp_exp, SIP_EXPECT_AUDIO, family, saddr, daddr, 766 nf_ct_expect_init(rtcp_exp, SIP_EXPECT_AUDIO, family, saddr, daddr,
725 IPPROTO_UDP, NULL, &rtcp_port); 767 IPPROTO_UDP, NULL, &rtcp_port);
726 768
727 nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); 769 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
728 if (nf_nat_sdp && ct->status & IPS_NAT_MASK) 770 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK)
729 ret = nf_nat_sdp(skb, dptr, datalen, rtp_exp, rtcp_exp); 771 ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp,
772 mediaoff, medialen, daddr);
730 else { 773 else {
731 if (nf_ct_expect_related(rtp_exp) == 0) { 774 if (nf_ct_expect_related(rtp_exp) == 0) {
732 if (nf_ct_expect_related(rtcp_exp) != 0) 775 if (nf_ct_expect_related(rtcp_exp) != 0)
@@ -750,33 +793,78 @@ static int process_sdp(struct sk_buff *skb,
750 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 793 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
751 int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; 794 int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
752 unsigned int matchoff, matchlen; 795 unsigned int matchoff, matchlen;
753 union nf_inet_addr addr; 796 unsigned int mediaoff, medialen;
797 unsigned int sdpoff;
798 unsigned int caddr_len, maddr_len;
799 union nf_inet_addr caddr, maddr, rtp_addr;
754 unsigned int port; 800 unsigned int port;
755 enum sdp_header_types type; 801 enum sdp_header_types c_hdr;
802 int ret;
803 typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr;
804 typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session;
756 805
757 /* Get address and port from SDP packet. */ 806 c_hdr = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
758 type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 : 807 SDP_HDR_CONNECTION_IP6;
759 SDP_HDR_CONNECTION_IP6;
760 808
809 /* Find beginning of session description */
761 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, 810 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
762 type, SDP_HDR_UNSPEC, 811 SDP_HDR_VERSION, SDP_HDR_UNSPEC,
763 &matchoff, &matchlen) <= 0) 812 &matchoff, &matchlen) <= 0)
764 return NF_ACCEPT; 813 return NF_ACCEPT;
765 814 sdpoff = matchoff;
766 /* We'll drop only if there are parse problems. */ 815
767 if (!parse_addr(ct, *dptr + matchoff, NULL, &addr, *dptr + *datalen)) 816 /* The connection information is contained in the session description
768 return NF_DROP; 817 * and/or once per media description. The first media description marks
769 818 * the end of the session description. */
770 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, 819 caddr_len = 0;
820 if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen,
821 c_hdr, SDP_HDR_MEDIA,
822 &matchoff, &matchlen, &caddr) > 0)
823 caddr_len = matchlen;
824
825 if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen,
771 SDP_HDR_MEDIA, SDP_HDR_UNSPEC, 826 SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
772 &matchoff, &matchlen) <= 0) 827 &mediaoff, &medialen) <= 0)
773 return NF_ACCEPT; 828 return NF_ACCEPT;
774 829
775 port = simple_strtoul(*dptr + matchoff, NULL, 10); 830 port = simple_strtoul(*dptr + mediaoff, NULL, 10);
776 if (port < 1024 || port > 65535) 831 if (port < 1024 || port > 65535)
777 return NF_DROP; 832 return NF_DROP;
778 833
779 return set_expected_rtp_rtcp(skb, dptr, datalen, &addr, htons(port)); 834 /* The media description overrides the session description. */
835 maddr_len = 0;
836 if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen,
837 c_hdr, SDP_HDR_MEDIA,
838 &matchoff, &matchlen, &maddr) > 0) {
839 maddr_len = matchlen;
840 memcpy(&rtp_addr, &maddr, sizeof(rtp_addr));
841 } else if (caddr_len)
842 memcpy(&rtp_addr, &caddr, sizeof(rtp_addr));
843 else
844 return NF_DROP;
845
846 ret = set_expected_rtp_rtcp(skb, dptr, datalen, &rtp_addr, htons(port),
847 mediaoff, medialen);
848 if (ret != NF_ACCEPT)
849 return ret;
850
851 /* Update media connection address if present */
852 if (maddr_len) {
853 nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook);
854 if (nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
855 ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen,
856 c_hdr, SDP_HDR_MEDIA, &rtp_addr);
857 if (ret != NF_ACCEPT)
858 return ret;
859 }
860 }
861
862 /* Update session connection and owner addresses */
863 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
864 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
865 ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr);
866
867 return ret;
780} 868}
781static int process_invite_response(struct sk_buff *skb, 869static int process_invite_response(struct sk_buff *skb,
782 const char **dptr, unsigned int *datalen, 870 const char **dptr, unsigned int *datalen,