cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nf_nat_sip.c (21280B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* SIP extension for NAT alteration.
      3 *
      4 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
      5 * based on RR's ip_nat_ftp.c and other modules.
      6 * (C) 2007 United Security Providers
      7 * (C) 2007, 2008, 2011, 2012 Patrick McHardy <kaber@trash.net>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/skbuff.h>
     12#include <linux/inet.h>
     13#include <linux/udp.h>
     14#include <linux/tcp.h>
     15
     16#include <net/netfilter/nf_nat.h>
     17#include <net/netfilter/nf_nat_helper.h>
     18#include <net/netfilter/nf_conntrack_core.h>
     19#include <net/netfilter/nf_conntrack_helper.h>
     20#include <net/netfilter/nf_conntrack_expect.h>
     21#include <net/netfilter/nf_conntrack_seqadj.h>
     22#include <linux/netfilter/nf_conntrack_sip.h>
     23
     24#define NAT_HELPER_NAME "sip"
     25
     26MODULE_LICENSE("GPL");
     27MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
     28MODULE_DESCRIPTION("SIP NAT helper");
     29MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
     30
     31static struct nf_conntrack_nat_helper nat_helper_sip =
     32	NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
     33
     34static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff,
     35				  unsigned int dataoff,
     36				  const char **dptr, unsigned int *datalen,
     37				  unsigned int matchoff, unsigned int matchlen,
     38				  const char *buffer, unsigned int buflen)
     39{
     40	enum ip_conntrack_info ctinfo;
     41	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
     42	struct tcphdr *th;
     43	unsigned int baseoff;
     44
     45	if (nf_ct_protonum(ct) == IPPROTO_TCP) {
     46		th = (struct tcphdr *)(skb->data + protoff);
     47		baseoff = protoff + th->doff * 4;
     48		matchoff += dataoff - baseoff;
     49
     50		if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
     51						protoff, matchoff, matchlen,
     52						buffer, buflen, false))
     53			return 0;
     54	} else {
     55		baseoff = protoff + sizeof(struct udphdr);
     56		matchoff += dataoff - baseoff;
     57
     58		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
     59					      protoff, matchoff, matchlen,
     60					      buffer, buflen))
     61			return 0;
     62	}
     63
     64	/* Reload data pointer and adjust datalen value */
     65	*dptr = skb->data + dataoff;
     66	*datalen += buflen - matchlen;
     67	return 1;
     68}
     69
     70static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer,
     71			    const union nf_inet_addr *addr, bool delim)
     72{
     73	if (nf_ct_l3num(ct) == NFPROTO_IPV4)
     74		return sprintf(buffer, "%pI4", &addr->ip);
     75	else {
     76		if (delim)
     77			return sprintf(buffer, "[%pI6c]", &addr->ip6);
     78		else
     79			return sprintf(buffer, "%pI6c", &addr->ip6);
     80	}
     81}
     82
     83static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer,
     84				 const union nf_inet_addr *addr, u16 port)
     85{
     86	if (nf_ct_l3num(ct) == NFPROTO_IPV4)
     87		return sprintf(buffer, "%pI4:%u", &addr->ip, port);
     88	else
     89		return sprintf(buffer, "[%pI6c]:%u", &addr->ip6, port);
     90}
     91
     92static int map_addr(struct sk_buff *skb, unsigned int protoff,
     93		    unsigned int dataoff,
     94		    const char **dptr, unsigned int *datalen,
     95		    unsigned int matchoff, unsigned int matchlen,
     96		    union nf_inet_addr *addr, __be16 port)
     97{
     98	enum ip_conntrack_info ctinfo;
     99	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    100	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
    101	struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
    102	char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
    103	unsigned int buflen;
    104	union nf_inet_addr newaddr;
    105	__be16 newport;
    106
    107	if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) &&
    108	    ct->tuplehash[dir].tuple.src.u.udp.port == port) {
    109		newaddr = ct->tuplehash[!dir].tuple.dst.u3;
    110		newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
    111	} else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) &&
    112		   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
    113		newaddr = ct->tuplehash[!dir].tuple.src.u3;
    114		newport = ct_sip_info->forced_dport ? :
    115			  ct->tuplehash[!dir].tuple.src.u.udp.port;
    116	} else
    117		return 1;
    118
    119	if (nf_inet_addr_cmp(&newaddr, addr) && newport == port)
    120		return 1;
    121
    122	buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, ntohs(newport));
    123	return mangle_packet(skb, protoff, dataoff, dptr, datalen,
    124			     matchoff, matchlen, buffer, buflen);
    125}
    126
    127static int map_sip_addr(struct sk_buff *skb, unsigned int protoff,
    128			unsigned int dataoff,
    129			const char **dptr, unsigned int *datalen,
    130			enum sip_header_types type)
    131{
    132	enum ip_conntrack_info ctinfo;
    133	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    134	unsigned int matchlen, matchoff;
    135	union nf_inet_addr addr;
    136	__be16 port;
    137
    138	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
    139				    &matchoff, &matchlen, &addr, &port) <= 0)
    140		return 1;
    141	return map_addr(skb, protoff, dataoff, dptr, datalen,
    142			matchoff, matchlen, &addr, port);
    143}
    144
    145static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
    146			       unsigned int dataoff,
    147			       const char **dptr, unsigned int *datalen)
    148{
    149	enum ip_conntrack_info ctinfo;
    150	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    151	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
    152	struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
    153	unsigned int coff, matchoff, matchlen;
    154	enum sip_header_types hdr;
    155	union nf_inet_addr addr;
    156	__be16 port;
    157	int request, in_header;
    158
    159	/* Basic rules: requests and responses. */
    160	if (strncasecmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
    161		if (ct_sip_parse_request(ct, *dptr, *datalen,
    162					 &matchoff, &matchlen,
    163					 &addr, &port) > 0 &&
    164		    !map_addr(skb, protoff, dataoff, dptr, datalen,
    165			      matchoff, matchlen, &addr, port)) {
    166			nf_ct_helper_log(skb, ct, "cannot mangle SIP message");
    167			return NF_DROP;
    168		}
    169		request = 1;
    170	} else
    171		request = 0;
    172
    173	if (nf_ct_protonum(ct) == IPPROTO_TCP)
    174		hdr = SIP_HDR_VIA_TCP;
    175	else
    176		hdr = SIP_HDR_VIA_UDP;
    177
    178	/* Translate topmost Via header and parameters */
    179	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
    180				    hdr, NULL, &matchoff, &matchlen,
    181				    &addr, &port) > 0) {
    182		unsigned int olen, matchend, poff, plen, buflen, n;
    183		char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
    184
    185		/* We're only interested in headers related to this
    186		 * connection */
    187		if (request) {
    188			if (!nf_inet_addr_cmp(&addr,
    189					&ct->tuplehash[dir].tuple.src.u3) ||
    190			    port != ct->tuplehash[dir].tuple.src.u.udp.port)
    191				goto next;
    192		} else {
    193			if (!nf_inet_addr_cmp(&addr,
    194					&ct->tuplehash[dir].tuple.dst.u3) ||
    195			    port != ct->tuplehash[dir].tuple.dst.u.udp.port)
    196				goto next;
    197		}
    198
    199		olen = *datalen;
    200		if (!map_addr(skb, protoff, dataoff, dptr, datalen,
    201			      matchoff, matchlen, &addr, port)) {
    202			nf_ct_helper_log(skb, ct, "cannot mangle Via header");
    203			return NF_DROP;
    204		}
    205
    206		matchend = matchoff + matchlen + *datalen - olen;
    207
    208		/* The maddr= parameter (RFC 2361) specifies where to send
    209		 * the reply. */
    210		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
    211					       "maddr=", &poff, &plen,
    212					       &addr, true) > 0 &&
    213		    nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) &&
    214		    !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) {
    215			buflen = sip_sprintf_addr(ct, buffer,
    216					&ct->tuplehash[!dir].tuple.dst.u3,
    217					true);
    218			if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
    219					   poff, plen, buffer, buflen)) {
    220				nf_ct_helper_log(skb, ct, "cannot mangle maddr");
    221				return NF_DROP;
    222			}
    223		}
    224
    225		/* The received= parameter (RFC 2361) contains the address
    226		 * from which the server received the request. */
    227		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
    228					       "received=", &poff, &plen,
    229					       &addr, false) > 0 &&
    230		    nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) &&
    231		    !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) {
    232			buflen = sip_sprintf_addr(ct, buffer,
    233					&ct->tuplehash[!dir].tuple.src.u3,
    234					false);
    235			if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
    236					   poff, plen, buffer, buflen)) {
    237				nf_ct_helper_log(skb, ct, "cannot mangle received");
    238				return NF_DROP;
    239			}
    240		}
    241
    242		/* The rport= parameter (RFC 3581) contains the port number
    243		 * from which the server received the request. */
    244		if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
    245						 "rport=", &poff, &plen,
    246						 &n) > 0 &&
    247		    htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
    248		    htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
    249			__be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
    250			buflen = sprintf(buffer, "%u", ntohs(p));
    251			if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
    252					   poff, plen, buffer, buflen)) {
    253				nf_ct_helper_log(skb, ct, "cannot mangle rport");
    254				return NF_DROP;
    255			}
    256		}
    257	}
    258
    259next:
    260	/* Translate Contact headers */
    261	coff = 0;
    262	in_header = 0;
    263	while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
    264				       SIP_HDR_CONTACT, &in_header,
    265				       &matchoff, &matchlen,
    266				       &addr, &port) > 0) {
    267		if (!map_addr(skb, protoff, dataoff, dptr, datalen,
    268			      matchoff, matchlen,
    269			      &addr, port)) {
    270			nf_ct_helper_log(skb, ct, "cannot mangle contact");
    271			return NF_DROP;
    272		}
    273	}
    274
    275	if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) ||
    276	    !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) {
    277		nf_ct_helper_log(skb, ct, "cannot mangle SIP from/to");
    278		return NF_DROP;
    279	}
    280
    281	/* Mangle destination port for Cisco phones, then fix up checksums */
    282	if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
    283		struct udphdr *uh;
    284
    285		if (skb_ensure_writable(skb, skb->len)) {
    286			nf_ct_helper_log(skb, ct, "cannot mangle packet");
    287			return NF_DROP;
    288		}
    289
    290		uh = (void *)skb->data + protoff;
    291		uh->dest = ct_sip_info->forced_dport;
    292
    293		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff,
    294					      0, 0, NULL, 0)) {
    295			nf_ct_helper_log(skb, ct, "cannot mangle packet");
    296			return NF_DROP;
    297		}
    298	}
    299
    300	return NF_ACCEPT;
    301}
    302
    303static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
    304				  s16 off)
    305{
    306	enum ip_conntrack_info ctinfo;
    307	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    308	const struct tcphdr *th;
    309
    310	if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0)
    311		return;
    312
    313	th = (struct tcphdr *)(skb->data + protoff);
    314	nf_ct_seqadj_set(ct, ctinfo, th->seq, off);
    315}
    316
    317/* Handles expected signalling connections and media streams */
    318static void nf_nat_sip_expected(struct nf_conn *ct,
    319				struct nf_conntrack_expect *exp)
    320{
    321	struct nf_conn_help *help = nfct_help(ct->master);
    322	struct nf_conntrack_expect *pair_exp;
    323	int range_set_for_snat = 0;
    324	struct nf_nat_range2 range;
    325
    326	/* This must be a fresh one. */
    327	BUG_ON(ct->status & IPS_NAT_DONE_MASK);
    328
    329	/* For DST manip, map port here to where it's expected. */
    330	range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
    331	range.min_proto = range.max_proto = exp->saved_proto;
    332	range.min_addr = range.max_addr = exp->saved_addr;
    333	nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
    334
    335	/* Do media streams SRC manip according with the parameters
    336	 * found in the paired expectation.
    337	 */
    338	if (exp->class != SIP_EXPECT_SIGNALLING) {
    339		spin_lock_bh(&nf_conntrack_expect_lock);
    340		hlist_for_each_entry(pair_exp, &help->expectations, lnode) {
    341			if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) &&
    342			    pair_exp->tuple.dst.protonum == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum &&
    343			    nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &pair_exp->saved_addr) &&
    344			    ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == pair_exp->saved_proto.all) {
    345				range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
    346				range.min_proto.all = range.max_proto.all = pair_exp->tuple.dst.u.all;
    347				range.min_addr = range.max_addr = pair_exp->tuple.dst.u3;
    348				range_set_for_snat = 1;
    349				break;
    350			}
    351		}
    352		spin_unlock_bh(&nf_conntrack_expect_lock);
    353	}
    354
    355	/* When no paired expectation has been found, change src to
    356	 * where master sends to, but only if the connection actually came
    357	 * from the same source.
    358	 */
    359	if (!range_set_for_snat &&
    360	    nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
    361			     &ct->master->tuplehash[exp->dir].tuple.src.u3)) {
    362		range.flags = NF_NAT_RANGE_MAP_IPS;
    363		range.min_addr = range.max_addr
    364			= ct->master->tuplehash[!exp->dir].tuple.dst.u3;
    365		range_set_for_snat = 1;
    366	}
    367
    368	/* Perform SRC manip. */
    369	if (range_set_for_snat)
    370		nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
    371}
    372
    373static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
    374				      unsigned int dataoff,
    375				      const char **dptr, unsigned int *datalen,
    376				      struct nf_conntrack_expect *exp,
    377				      unsigned int matchoff,
    378				      unsigned int matchlen)
    379{
    380	enum ip_conntrack_info ctinfo;
    381	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    382	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
    383	struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
    384	union nf_inet_addr newaddr;
    385	u_int16_t port;
    386	__be16 srcport;
    387	char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
    388	unsigned int buflen;
    389
    390	/* Connection will come from reply */
    391	if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
    392			     &ct->tuplehash[!dir].tuple.dst.u3))
    393		newaddr = exp->tuple.dst.u3;
    394	else
    395		newaddr = ct->tuplehash[!dir].tuple.dst.u3;
    396
    397	/* If the signalling port matches the connection's source port in the
    398	 * original direction, try to use the destination port in the opposite
    399	 * direction. */
    400	srcport = ct_sip_info->forced_dport ? :
    401		  ct->tuplehash[dir].tuple.src.u.udp.port;
    402	if (exp->tuple.dst.u.udp.port == srcport)
    403		port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
    404	else
    405		port = ntohs(exp->tuple.dst.u.udp.port);
    406
    407	exp->saved_addr = exp->tuple.dst.u3;
    408	exp->tuple.dst.u3 = newaddr;
    409	exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
    410	exp->dir = !dir;
    411	exp->expectfn = nf_nat_sip_expected;
    412
    413	for (; port != 0; port++) {
    414		int ret;
    415
    416		exp->tuple.dst.u.udp.port = htons(port);
    417		ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER);
    418		if (ret == 0)
    419			break;
    420		else if (ret != -EBUSY) {
    421			port = 0;
    422			break;
    423		}
    424	}
    425
    426	if (port == 0) {
    427		nf_ct_helper_log(skb, ct, "all ports in use for SIP");
    428		return NF_DROP;
    429	}
    430
    431	if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) ||
    432	    exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
    433		buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port);
    434		if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
    435				   matchoff, matchlen, buffer, buflen)) {
    436			nf_ct_helper_log(skb, ct, "cannot mangle packet");
    437			goto err;
    438		}
    439	}
    440	return NF_ACCEPT;
    441
    442err:
    443	nf_ct_unexpect_related(exp);
    444	return NF_DROP;
    445}
    446
    447static int mangle_content_len(struct sk_buff *skb, unsigned int protoff,
    448			      unsigned int dataoff,
    449			      const char **dptr, unsigned int *datalen)
    450{
    451	enum ip_conntrack_info ctinfo;
    452	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    453	unsigned int matchoff, matchlen;
    454	char buffer[sizeof("65536")];
    455	int buflen, c_len;
    456
    457	/* Get actual SDP length */
    458	if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
    459				  SDP_HDR_VERSION, SDP_HDR_UNSPEC,
    460				  &matchoff, &matchlen) <= 0)
    461		return 0;
    462	c_len = *datalen - matchoff + strlen("v=");
    463
    464	/* Now, update SDP length */
    465	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
    466			      &matchoff, &matchlen) <= 0)
    467		return 0;
    468
    469	buflen = sprintf(buffer, "%u", c_len);
    470	return mangle_packet(skb, protoff, dataoff, dptr, datalen,
    471			     matchoff, matchlen, buffer, buflen);
    472}
    473
    474static int mangle_sdp_packet(struct sk_buff *skb, unsigned int protoff,
    475			     unsigned int dataoff,
    476			     const char **dptr, unsigned int *datalen,
    477			     unsigned int sdpoff,
    478			     enum sdp_header_types type,
    479			     enum sdp_header_types term,
    480			     char *buffer, int buflen)
    481{
    482	enum ip_conntrack_info ctinfo;
    483	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    484	unsigned int matchlen, matchoff;
    485
    486	if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
    487				  &matchoff, &matchlen) <= 0)
    488		return -ENOENT;
    489	return mangle_packet(skb, protoff, dataoff, dptr, datalen,
    490			     matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL;
    491}
    492
    493static unsigned int nf_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff,
    494				    unsigned int dataoff,
    495				    const char **dptr, unsigned int *datalen,
    496				    unsigned int sdpoff,
    497				    enum sdp_header_types type,
    498				    enum sdp_header_types term,
    499				    const union nf_inet_addr *addr)
    500{
    501	enum ip_conntrack_info ctinfo;
    502	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    503	char buffer[INET6_ADDRSTRLEN];
    504	unsigned int buflen;
    505
    506	buflen = sip_sprintf_addr(ct, buffer, addr, false);
    507	if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen,
    508			      sdpoff, type, term, buffer, buflen))
    509		return 0;
    510
    511	return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
    512}
    513
    514static unsigned int nf_nat_sdp_port(struct sk_buff *skb, unsigned int protoff,
    515				    unsigned int dataoff,
    516				    const char **dptr, unsigned int *datalen,
    517				    unsigned int matchoff,
    518				    unsigned int matchlen,
    519				    u_int16_t port)
    520{
    521	char buffer[sizeof("nnnnn")];
    522	unsigned int buflen;
    523
    524	buflen = sprintf(buffer, "%u", port);
    525	if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
    526			   matchoff, matchlen, buffer, buflen))
    527		return 0;
    528
    529	return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
    530}
    531
    532static unsigned int nf_nat_sdp_session(struct sk_buff *skb, unsigned int protoff,
    533				       unsigned int dataoff,
    534				       const char **dptr, unsigned int *datalen,
    535				       unsigned int sdpoff,
    536				       const union nf_inet_addr *addr)
    537{
    538	enum ip_conntrack_info ctinfo;
    539	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    540	char buffer[INET6_ADDRSTRLEN];
    541	unsigned int buflen;
    542
    543	/* Mangle session description owner and contact addresses */
    544	buflen = sip_sprintf_addr(ct, buffer, addr, false);
    545	if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
    546			      SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen))
    547		return 0;
    548
    549	switch (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
    550				  SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
    551				  buffer, buflen)) {
    552	case 0:
    553	/*
    554	 * RFC 2327:
    555	 *
    556	 * Session description
    557	 *
    558	 * c=* (connection information - not required if included in all media)
    559	 */
    560	case -ENOENT:
    561		break;
    562	default:
    563		return 0;
    564	}
    565
    566	return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
    567}
    568
    569/* So, this packet has hit the connection tracking matching code.
    570   Mangle it, and change the expectation to match the new version. */
    571static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
    572				     unsigned int dataoff,
    573				     const char **dptr, unsigned int *datalen,
    574				     struct nf_conntrack_expect *rtp_exp,
    575				     struct nf_conntrack_expect *rtcp_exp,
    576				     unsigned int mediaoff,
    577				     unsigned int medialen,
    578				     union nf_inet_addr *rtp_addr)
    579{
    580	enum ip_conntrack_info ctinfo;
    581	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
    582	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
    583	u_int16_t port;
    584
    585	/* Connection will come from reply */
    586	if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
    587			     &ct->tuplehash[!dir].tuple.dst.u3))
    588		*rtp_addr = rtp_exp->tuple.dst.u3;
    589	else
    590		*rtp_addr = ct->tuplehash[!dir].tuple.dst.u3;
    591
    592	rtp_exp->saved_addr = rtp_exp->tuple.dst.u3;
    593	rtp_exp->tuple.dst.u3 = *rtp_addr;
    594	rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
    595	rtp_exp->dir = !dir;
    596	rtp_exp->expectfn = nf_nat_sip_expected;
    597
    598	rtcp_exp->saved_addr = rtcp_exp->tuple.dst.u3;
    599	rtcp_exp->tuple.dst.u3 = *rtp_addr;
    600	rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
    601	rtcp_exp->dir = !dir;
    602	rtcp_exp->expectfn = nf_nat_sip_expected;
    603
    604	/* Try to get same pair of ports: if not, try to change them. */
    605	for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
    606	     port != 0; port += 2) {
    607		int ret;
    608
    609		rtp_exp->tuple.dst.u.udp.port = htons(port);
    610		ret = nf_ct_expect_related(rtp_exp,
    611					   NF_CT_EXP_F_SKIP_MASTER);
    612		if (ret == -EBUSY)
    613			continue;
    614		else if (ret < 0) {
    615			port = 0;
    616			break;
    617		}
    618		rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
    619		ret = nf_ct_expect_related(rtcp_exp,
    620					   NF_CT_EXP_F_SKIP_MASTER);
    621		if (ret == 0)
    622			break;
    623		else if (ret == -EBUSY) {
    624			nf_ct_unexpect_related(rtp_exp);
    625			continue;
    626		} else if (ret < 0) {
    627			nf_ct_unexpect_related(rtp_exp);
    628			port = 0;
    629			break;
    630		}
    631	}
    632
    633	if (port == 0) {
    634		nf_ct_helper_log(skb, ct, "all ports in use for SDP media");
    635		goto err1;
    636	}
    637
    638	/* Update media port. */
    639	if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
    640	    !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen,
    641			     mediaoff, medialen, port)) {
    642		nf_ct_helper_log(skb, ct, "cannot mangle SDP message");
    643		goto err2;
    644	}
    645
    646	return NF_ACCEPT;
    647
    648err2:
    649	nf_ct_unexpect_related(rtp_exp);
    650	nf_ct_unexpect_related(rtcp_exp);
    651err1:
    652	return NF_DROP;
    653}
    654
    655static struct nf_ct_helper_expectfn sip_nat = {
    656	.name		= "sip",
    657	.expectfn	= nf_nat_sip_expected,
    658};
    659
    660static void __exit nf_nat_sip_fini(void)
    661{
    662	nf_nat_helper_unregister(&nat_helper_sip);
    663	RCU_INIT_POINTER(nf_nat_sip_hooks, NULL);
    664	nf_ct_helper_expectfn_unregister(&sip_nat);
    665	synchronize_rcu();
    666}
    667
    668static const struct nf_nat_sip_hooks sip_hooks = {
    669	.msg		= nf_nat_sip,
    670	.seq_adjust	= nf_nat_sip_seq_adjust,
    671	.expect		= nf_nat_sip_expect,
    672	.sdp_addr	= nf_nat_sdp_addr,
    673	.sdp_port	= nf_nat_sdp_port,
    674	.sdp_session	= nf_nat_sdp_session,
    675	.sdp_media	= nf_nat_sdp_media,
    676};
    677
    678static int __init nf_nat_sip_init(void)
    679{
    680	BUG_ON(nf_nat_sip_hooks != NULL);
    681	nf_nat_helper_register(&nat_helper_sip);
    682	RCU_INIT_POINTER(nf_nat_sip_hooks, &sip_hooks);
    683	nf_ct_helper_expectfn_register(&sip_nat);
    684	return 0;
    685}
    686
    687module_init(nf_nat_sip_init);
    688module_exit(nf_nat_sip_fini);