Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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

parent 624f8b7b
Loading
Loading
Loading
Loading
+43 −41
Original line number Diff line number Diff line
@@ -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) {

		/* 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) {
	    strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0)
		return NF_ACCEPT;

			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;