Commit 7d3dd043 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: nf_conntrack_sip: move SDP parsing to seperate function

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 624f8b7b
...@@ -565,19 +565,49 @@ static int set_expected_rtp(struct sk_buff *skb, ...@@ -565,19 +565,49 @@ static int set_expected_rtp(struct sk_buff *skb,
return ret; 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, static int sip_help(struct sk_buff *skb,
unsigned int protoff, unsigned int protoff,
struct nf_conn *ct, struct nf_conn *ct,
enum ip_conntrack_info ctinfo) 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; unsigned int dataoff, datalen;
const char *dptr; 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; typeof(nf_nat_sip_hook) nf_nat_sip;
/* No Data ? */ /* No Data ? */
...@@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb, ...@@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb,
dptr = skb->data + dataoff; dptr = skb->data + dataoff;
else { else {
pr_debug("Copy of skbuff not supported yet.\n"); pr_debug("Copy of skbuff not supported yet.\n");
goto out; return NF_ACCEPT;
} }
nf_nat_sip = rcu_dereference(nf_nat_sip_hook); nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
if (nf_nat_sip && ct->status & IPS_NAT_MASK) { if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
if (!nf_nat_sip(skb, &dptr, &datalen)) { if (!nf_nat_sip(skb, &dptr, &datalen))
ret = NF_DROP; return NF_DROP;
goto out;
}
} }
datalen = skb->len - dataoff; datalen = skb->len - dataoff;
if (datalen < strlen("SIP/2.0 200")) if (datalen < strlen("SIP/2.0 200"))
goto out; return NF_ACCEPT;
/* RTP info only in some SDP pkts */ /* RTP info only in some SDP pkts */
if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 && if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 &&
strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 && strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 &&
strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 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 183", strlen("SIP/2.0 183")) != 0 &&
strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) { strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0)
goto out; return NF_ACCEPT;
}
/* 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) {
/* We'll drop only if there are parse problems. */ return process_sdp(skb, &dptr, &datalen);
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;
} }
static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment