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