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