aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c121
-rw-r--r--net/netfilter/nf_conntrack_sip.c142
2 files changed, 199 insertions, 64 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
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,