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

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

[NETFILTER]: nf_conntrack_sip: kill request URI "header" definitions



The request URI is not a header and needs to be treated differently than
real SIP headers. Add a seperate function for parsing it and get rid of
the POS_REQ_URI/POS_REG_REQ_URI definitions.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3e9b4600
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -6,8 +6,6 @@
#define SIP_TIMEOUT	3600
#define SIP_TIMEOUT	3600


enum sip_header_pos {
enum sip_header_pos {
	POS_REG_REQ_URI,
	POS_REQ_URI,
	POS_FROM,
	POS_FROM,
	POS_TO,
	POS_TO,
	POS_VIA,
	POS_VIA,
@@ -59,6 +57,9 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
				       unsigned int *datalen,
				       unsigned int *datalen,
				       struct nf_conntrack_expect *exp);
				       struct nf_conntrack_expect *exp);


extern int ct_sip_parse_request(const struct nf_conn *ct,
				const char *dptr, unsigned int datalen,
				unsigned int *matchoff, unsigned int *matchlen);
extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
                           size_t dlen, unsigned int *matchoff,
                           size_t dlen, unsigned int *matchoff,
                           unsigned int *matchlen, enum sip_header_pos pos);
                           unsigned int *matchlen, enum sip_header_pos pos);
+24 −22
Original line number Original line Diff line number Diff line
@@ -78,20 +78,17 @@ static unsigned int mangle_packet(struct sk_buff *skb,
	return 1;
	return 1;
}
}


static int map_sip_addr(struct sk_buff *skb,
static int map_addr(struct sk_buff *skb,
		    const char **dptr, unsigned int *datalen,
		    const char **dptr, unsigned int *datalen,
			enum sip_header_pos pos, struct addr_map *map)
		    unsigned int matchoff, unsigned int matchlen,
		    struct addr_map *map)
{
{
	enum ip_conntrack_info ctinfo;
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
	struct nf_conn *ct __maybe_unused = nf_ct_get(skb, &ctinfo);
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	unsigned int matchlen, matchoff, addrlen;
	unsigned int addrlen;
	char *addr;
	char *addr;


	if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
			    pos) <= 0)
		return 1;

	if ((matchlen == map->addr[dir].srciplen ||
	if ((matchlen == map->addr[dir].srciplen ||
	     matchlen == map->addr[dir].srclen) &&
	     matchlen == map->addr[dir].srclen) &&
	    strncmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
	    strncmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
@@ -109,13 +106,27 @@ static int map_sip_addr(struct sk_buff *skb,
			     addr, addrlen);
			     addr, addrlen);
}
}


static int map_sip_addr(struct sk_buff *skb,
			const char **dptr, unsigned int *datalen,
			enum sip_header_pos pos, struct addr_map *map)
{
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
	unsigned int matchlen, matchoff;

	if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
			    pos) <= 0)
		return 1;
	return map_addr(skb, dptr, datalen, matchoff, matchlen, map);
}

static unsigned int ip_nat_sip(struct sk_buff *skb,
static unsigned int ip_nat_sip(struct sk_buff *skb,
			       const char **dptr, unsigned int *datalen)
			       const char **dptr, unsigned int *datalen)
{
{
	enum ip_conntrack_info ctinfo;
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
	enum sip_header_pos pos;
	struct addr_map map;
	struct addr_map map;
	unsigned int matchoff, matchlen;


	if (*datalen < strlen("SIP/2.0"))
	if (*datalen < strlen("SIP/2.0"))
		return NF_ACCEPT;
		return NF_ACCEPT;
@@ -124,18 +135,9 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,


	/* Basic rules: requests and responses. */
	/* Basic rules: requests and responses. */
	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
		/* 10.2: Constructing the REGISTER Request:
		if (ct_sip_parse_request(ct, *dptr, *datalen,
		 *
					 &matchoff, &matchlen) > 0 &&
		 * The "userinfo" and "@" components of the SIP URI MUST NOT
		    !map_addr(skb, dptr, datalen, matchoff, matchlen, &map))
		 * be present.
		 */
		if (*datalen >= strlen("REGISTER") &&
		    strnicmp(*dptr, "REGISTER", strlen("REGISTER")) == 0)
			pos = POS_REG_REQ_URI;
		else
			pos = POS_REQ_URI;

		if (!map_sip_addr(skb, dptr, datalen, pos, &map))
			return NF_DROP;
			return NF_DROP;
	}
	}


+50 −14
Original line number Original line Diff line number Diff line
@@ -65,20 +65,6 @@ struct sip_header_nfo {
};
};


static const struct sip_header_nfo ct_sip_hdrs[] = {
static const struct sip_header_nfo ct_sip_hdrs[] = {
	[POS_REG_REQ_URI] = { 	/* SIP REGISTER request URI */
		.lname		= "sip:",
		.lnlen		= sizeof("sip:") - 1,
		.ln_str		= ":",
		.ln_strlen	= sizeof(":") - 1,
		.match_len	= epaddr_len,
	},
	[POS_REQ_URI] = { 	/* SIP request URI */
		.lname		= "sip:",
		.lnlen		= sizeof("sip:") - 1,
		.ln_str		= "@",
		.ln_strlen	= sizeof("@") - 1,
		.match_len	= epaddr_len,
	},
	[POS_FROM] = {		/* SIP From header */
	[POS_FROM] = {		/* SIP From header */
		.lname		= "From:",
		.lname		= "From:",
		.lnlen		= sizeof("From:") - 1,
		.lnlen		= sizeof("From:") - 1,
@@ -164,6 +150,18 @@ const char *ct_sip_search(const char *needle, const char *haystack,
}
}
EXPORT_SYMBOL_GPL(ct_sip_search);
EXPORT_SYMBOL_GPL(ct_sip_search);


static int string_len(const struct nf_conn *ct, const char *dptr,
		      const char *limit, int *shift)
{
	int len = 0;

	while (dptr < limit && isalpha(*dptr)) {
		dptr++;
		len++;
	}
	return len;
}

static int digits_len(const struct nf_conn *ct, const char *dptr,
static int digits_len(const struct nf_conn *ct, const char *dptr,
		      const char *limit, int *shift)
		      const char *limit, int *shift)
{
{
@@ -258,6 +256,44 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
	return epaddr_len(ct, dptr, limit, shift);
	return epaddr_len(ct, dptr, limit, shift);
}
}


/* Parse a SIP request line of the form:
 *
 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
 *
 * and return the offset and length of the address contained in the Request-URI.
 */
int ct_sip_parse_request(const struct nf_conn *ct,
			 const char *dptr, unsigned int datalen,
			 unsigned int *matchoff, unsigned int *matchlen)
{
	const char *start = dptr, *limit = dptr + datalen;
	unsigned int mlen;
	int shift = 0;

	/* Skip method and following whitespace */
	mlen = string_len(ct, dptr, limit, NULL);
	if (!mlen)
		return 0;
	dptr += mlen;
	if (++dptr >= limit)
		return 0;

	/* Find SIP URI */
	limit -= strlen("sip:");
	for (; dptr < limit; dptr++) {
		if (*dptr == '\r' || *dptr == '\n')
			return -1;
		if (strnicmp(dptr, "sip:", strlen("sip:")) == 0)
			break;
	}
	*matchlen = skp_epaddr_len(ct, dptr, limit, &shift);
	if (!*matchlen)
		return 0;
	*matchoff = dptr - start + shift;
	return 1;
}
EXPORT_SYMBOL_GPL(ct_sip_parse_request);

/* Returns 0 if not found, -1 error parsing. */
/* Returns 0 if not found, -1 error parsing. */
int ct_sip_get_info(const struct nf_conn *ct,
int ct_sip_get_info(const struct nf_conn *ct,
		    const char *dptr, size_t dlen,
		    const char *dptr, size_t dlen,