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