[NETFILTER]: nf_conntrack_sip: move SDP parsing to seperate function
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
624f8b7bba
commit
7d3dd043b6
@@ -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,
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user