summaryrefslogtreecommitdiffstats
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,
return ret;
}
+static int process_sdp(struct sk_buff *skb,
+ const char **dptr, unsigned int *datalen)
+{
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ unsigned int matchoff, matchlen;
+ union nf_inet_addr addr;
+ unsigned int port;
+ enum sdp_header_types type;
+
+ /* Get address and port from SDP packet. */
+ type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
+ SDP_HDR_CONNECTION_IP6;
+
+ if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
+ type, SDP_HDR_UNSPEC,
+ &matchoff, &matchlen) <= 0)
+ return NF_ACCEPT;
+
+ /* We'll drop only if there are parse problems. */
+ if (!parse_addr(ct, *dptr + matchoff, NULL, &addr, *dptr + *datalen))
+ return NF_DROP;
+
+ if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
+ SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
+ &matchoff, &matchlen) <= 0)
+ return NF_ACCEPT;
+
+ port = simple_strtoul(*dptr + matchoff, NULL, 10);
+ if (port < 1024 || port > 65535)
+ return NF_DROP;
+
+ return set_expected_rtp(skb, dptr, datalen, &addr, htons(port));
+}
+
static int sip_help(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
{
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
- union nf_inet_addr addr;
unsigned int dataoff, datalen;
const char *dptr;
- int ret = NF_ACCEPT;
- unsigned int matchoff, matchlen;
- u_int16_t port;
- enum sdp_header_types type;
typeof(nf_nat_sip_hook) nf_nat_sip;
/* No Data ? */
@@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb,
dptr = skb->data + dataoff;
else {
pr_debug("Copy of skbuff not supported yet.\n");
- goto out;
+ return NF_ACCEPT;
}
nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
- if (!nf_nat_sip(skb, &dptr, &datalen)) {
- ret = NF_DROP;
- goto out;
- }
+ if (!nf_nat_sip(skb, &dptr, &datalen))
+ return NF_DROP;
}
datalen = skb->len - dataoff;
if (datalen < strlen("SIP/2.0 200"))
- goto out;
+ return NF_ACCEPT;
/* RTP info only in some SDP pkts */
if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 &&
strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 &&
strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 &&
strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 &&
- strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) {
- goto out;
- }
- /* Get address and port from SDP packet. */
- type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
- SDP_HDR_CONNECTION_IP6;
- if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, type, SDP_HDR_UNSPEC,
- &matchoff, &matchlen) > 0) {
+ strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0)
+ return NF_ACCEPT;
- /* We'll drop only if there are parse problems. */
- if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
- dptr + datalen)) {
- ret = NF_DROP;
- goto out;
- }
- if (ct_sip_get_sdp_header(ct, dptr, 0, datalen,
- SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
- &matchoff, &matchlen) > 0) {
-
- port = simple_strtoul(dptr + matchoff, NULL, 10);
- if (port < 1024) {
- ret = NF_DROP;
- goto out;
- }
- ret = set_expected_rtp(skb, &dptr, &datalen,
- &addr, htons(port));
- }
- }
-out:
- return ret;
+ return process_sdp(skb, &dptr, &datalen);
}
static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;