aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nf_conntrack_sip.c84
1 files changed, 43 insertions, 41 deletions
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index f20fa2d94c0a..96bedb52bd4b 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -565,19 +565,49 @@ static int set_expected_rtp(struct sk_buff *skb,
565 return ret; 565 return ret;
566} 566}
567 567
568static int process_sdp(struct sk_buff *skb,
569 const char **dptr, unsigned int *datalen)
570{
571 enum ip_conntrack_info ctinfo;
572 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
573 int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
574 unsigned int matchoff, matchlen;
575 union nf_inet_addr addr;
576 unsigned int port;
577 enum sdp_header_types type;
578
579 /* Get address and port from SDP packet. */
580 type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
581 SDP_HDR_CONNECTION_IP6;
582
583 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
584 type, SDP_HDR_UNSPEC,
585 &matchoff, &matchlen) <= 0)
586 return NF_ACCEPT;
587
588 /* We'll drop only if there are parse problems. */
589 if (!parse_addr(ct, *dptr + matchoff, NULL, &addr, *dptr + *datalen))
590 return NF_DROP;
591
592 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
593 SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
594 &matchoff, &matchlen) <= 0)
595 return NF_ACCEPT;
596
597 port = simple_strtoul(*dptr + matchoff, NULL, 10);
598 if (port < 1024 || port > 65535)
599 return NF_DROP;
600
601 return set_expected_rtp(skb, dptr, datalen, &addr, htons(port));
602}
603
568static int sip_help(struct sk_buff *skb, 604static int sip_help(struct sk_buff *skb,
569 unsigned int protoff, 605 unsigned int protoff,
570 struct nf_conn *ct, 606 struct nf_conn *ct,
571 enum ip_conntrack_info ctinfo) 607 enum ip_conntrack_info ctinfo)
572{ 608{
573 int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
574 union nf_inet_addr addr;
575 unsigned int dataoff, datalen; 609 unsigned int dataoff, datalen;
576 const char *dptr; 610 const char *dptr;
577 int ret = NF_ACCEPT;
578 unsigned int matchoff, matchlen;
579 u_int16_t port;
580 enum sdp_header_types type;
581 typeof(nf_nat_sip_hook) nf_nat_sip; 611 typeof(nf_nat_sip_hook) nf_nat_sip;
582 612
583 /* No Data ? */ 613 /* No Data ? */
@@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb,
591 dptr = skb->data + dataoff; 621 dptr = skb->data + dataoff;
592 else { 622 else {
593 pr_debug("Copy of skbuff not supported yet.\n"); 623 pr_debug("Copy of skbuff not supported yet.\n");
594 goto out; 624 return NF_ACCEPT;
595 } 625 }
596 626
597 nf_nat_sip = rcu_dereference(nf_nat_sip_hook); 627 nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
598 if (nf_nat_sip && ct->status & IPS_NAT_MASK) { 628 if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
599 if (!nf_nat_sip(skb, &dptr, &datalen)) { 629 if (!nf_nat_sip(skb, &dptr, &datalen))
600 ret = NF_DROP; 630 return NF_DROP;
601 goto out;
602 }
603 } 631 }
604 632
605 datalen = skb->len - dataoff; 633 datalen = skb->len - dataoff;
606 if (datalen < strlen("SIP/2.0 200")) 634 if (datalen < strlen("SIP/2.0 200"))
607 goto out; 635 return NF_ACCEPT;
608 636
609 /* RTP info only in some SDP pkts */ 637 /* RTP info only in some SDP pkts */
610 if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 && 638 if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 &&
611 strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 && 639 strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 &&
612 strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 && 640 strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 &&
613 strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 && 641 strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 &&
614 strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) { 642 strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0)
615 goto out; 643 return NF_ACCEPT;
616 }
617 /* Get address and port from SDP packet. */
618 type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
619 SDP_HDR_CONNECTION_IP6;
620 if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, type, SDP_HDR_UNSPEC,
621 &matchoff, &matchlen) > 0) {
622 644
623 /* We'll drop only if there are parse problems. */ 645 return process_sdp(skb, &dptr, &datalen);
624 if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
625 dptr + datalen)) {
626 ret = NF_DROP;
627 goto out;
628 }
629 if (ct_sip_get_sdp_header(ct, dptr, 0, datalen,
630 SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
631 &matchoff, &matchlen) > 0) {
632
633 port = simple_strtoul(dptr + matchoff, NULL, 10);
634 if (port < 1024) {
635 ret = NF_DROP;
636 goto out;
637 }
638 ret = set_expected_rtp(skb, &dptr, &datalen,
639 &addr, htons(port));
640 }
641 }
642out:
643 return ret;
644} 646}
645 647
646static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; 648static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;