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 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/ip.h>
16 #include <net/ip.h>
17 #include <linux/udp.h>
18 #include <linux/tcp.h>
19 
20 #include <net/netfilter/nf_nat.h>
21 #include <net/netfilter/nf_nat_helper.h>
22 #include <net/netfilter/nf_nat_rule.h>
23 #include <net/netfilter/nf_conntrack_helper.h>
24 #include <net/netfilter/nf_conntrack_expect.h>
25 #include <linux/netfilter/nf_conntrack_sip.h>
26 
27 MODULE_LICENSE("GPL");
28 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
29 MODULE_DESCRIPTION("SIP NAT helper");
30 MODULE_ALIAS("ip_nat_sip");
31 
32 
mangle_packet(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int matchoff,unsigned int matchlen,const char * buffer,unsigned int buflen)33 static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff,
34 				  const char **dptr, unsigned int *datalen,
35 				  unsigned int matchoff, unsigned int matchlen,
36 				  const char *buffer, unsigned int buflen)
37 {
38 	enum ip_conntrack_info ctinfo;
39 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
40 	struct tcphdr *th;
41 	unsigned int baseoff;
42 
43 	if (nf_ct_protonum(ct) == IPPROTO_TCP) {
44 		th = (struct tcphdr *)(skb->data + ip_hdrlen(skb));
45 		baseoff = ip_hdrlen(skb) + th->doff * 4;
46 		matchoff += dataoff - baseoff;
47 
48 		if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
49 						matchoff, matchlen,
50 						buffer, buflen, false))
51 			return 0;
52 	} else {
53 		baseoff = ip_hdrlen(skb) + sizeof(struct udphdr);
54 		matchoff += dataoff - baseoff;
55 
56 		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
57 					      matchoff, matchlen,
58 					      buffer, buflen))
59 			return 0;
60 	}
61 
62 	/* Reload data pointer and adjust datalen value */
63 	*dptr = skb->data + dataoff;
64 	*datalen += buflen - matchlen;
65 	return 1;
66 }
67 
map_addr(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int matchoff,unsigned int matchlen,union nf_inet_addr * addr,__be16 port)68 static int map_addr(struct sk_buff *skb, unsigned int dataoff,
69 		    const char **dptr, unsigned int *datalen,
70 		    unsigned int matchoff, unsigned int matchlen,
71 		    union nf_inet_addr *addr, __be16 port)
72 {
73 	enum ip_conntrack_info ctinfo;
74 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
75 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
76 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
77 	unsigned int buflen;
78 	__be32 newaddr;
79 	__be16 newport;
80 
81 	if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
82 	    ct->tuplehash[dir].tuple.src.u.udp.port == port) {
83 		newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
84 		newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
85 	} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
86 		   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
87 		newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
88 		newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
89 	} else
90 		return 1;
91 
92 	if (newaddr == addr->ip && newport == port)
93 		return 1;
94 
95 	buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport));
96 
97 	return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
98 			     buffer, buflen);
99 }
100 
map_sip_addr(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen,enum sip_header_types type)101 static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff,
102 			const char **dptr, unsigned int *datalen,
103 			enum sip_header_types type)
104 {
105 	enum ip_conntrack_info ctinfo;
106 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
107 	unsigned int matchlen, matchoff;
108 	union nf_inet_addr addr;
109 	__be16 port;
110 
111 	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
112 				    &matchoff, &matchlen, &addr, &port) <= 0)
113 		return 1;
114 	return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
115 			&addr, port);
116 }
117 
ip_nat_sip(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen)118 static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
119 			       const char **dptr, unsigned int *datalen)
120 {
121 	enum ip_conntrack_info ctinfo;
122 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
123 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
124 	unsigned int coff, matchoff, matchlen;
125 	enum sip_header_types hdr;
126 	union nf_inet_addr addr;
127 	__be16 port;
128 	int request, in_header;
129 
130 	/* Basic rules: requests and responses. */
131 	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
132 		if (ct_sip_parse_request(ct, *dptr, *datalen,
133 					 &matchoff, &matchlen,
134 					 &addr, &port) > 0 &&
135 		    !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
136 			      &addr, port))
137 			return NF_DROP;
138 		request = 1;
139 	} else
140 		request = 0;
141 
142 	if (nf_ct_protonum(ct) == IPPROTO_TCP)
143 		hdr = SIP_HDR_VIA_TCP;
144 	else
145 		hdr = SIP_HDR_VIA_UDP;
146 
147 	/* Translate topmost Via header and parameters */
148 	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
149 				    hdr, NULL, &matchoff, &matchlen,
150 				    &addr, &port) > 0) {
151 		unsigned int matchend, poff, plen, buflen, n;
152 		char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
153 
154 		/* We're only interested in headers related to this
155 		 * connection */
156 		if (request) {
157 			if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip ||
158 			    port != ct->tuplehash[dir].tuple.src.u.udp.port)
159 				goto next;
160 		} else {
161 			if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip ||
162 			    port != ct->tuplehash[dir].tuple.dst.u.udp.port)
163 				goto next;
164 		}
165 
166 		if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
167 			      &addr, port))
168 			return NF_DROP;
169 
170 		matchend = matchoff + matchlen;
171 
172 		/* The maddr= parameter (RFC 2361) specifies where to send
173 		 * the reply. */
174 		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
175 					       "maddr=", &poff, &plen,
176 					       &addr) > 0 &&
177 		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
178 		    addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
179 			buflen = sprintf(buffer, "%pI4",
180 					&ct->tuplehash[!dir].tuple.dst.u3.ip);
181 			if (!mangle_packet(skb, dataoff, dptr, datalen,
182 					   poff, plen, buffer, buflen))
183 				return NF_DROP;
184 		}
185 
186 		/* The received= parameter (RFC 2361) contains the address
187 		 * from which the server received the request. */
188 		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
189 					       "received=", &poff, &plen,
190 					       &addr) > 0 &&
191 		    addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
192 		    addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
193 			buflen = sprintf(buffer, "%pI4",
194 					&ct->tuplehash[!dir].tuple.src.u3.ip);
195 			if (!mangle_packet(skb, dataoff, dptr, datalen,
196 					   poff, plen, buffer, buflen))
197 				return NF_DROP;
198 		}
199 
200 		/* The rport= parameter (RFC 3581) contains the port number
201 		 * from which the server received the request. */
202 		if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
203 						 "rport=", &poff, &plen,
204 						 &n) > 0 &&
205 		    htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
206 		    htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
207 			__be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
208 			buflen = sprintf(buffer, "%u", ntohs(p));
209 			if (!mangle_packet(skb, dataoff, dptr, datalen,
210 					   poff, plen, buffer, buflen))
211 				return NF_DROP;
212 		}
213 	}
214 
215 next:
216 	/* Translate Contact headers */
217 	coff = 0;
218 	in_header = 0;
219 	while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
220 				       SIP_HDR_CONTACT, &in_header,
221 				       &matchoff, &matchlen,
222 				       &addr, &port) > 0) {
223 		if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
224 			      &addr, port))
225 			return NF_DROP;
226 	}
227 
228 	if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) ||
229 	    !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
230 		return NF_DROP;
231 
232 	return NF_ACCEPT;
233 }
234 
ip_nat_sip_seq_adjust(struct sk_buff * skb,s16 off)235 static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off)
236 {
237 	enum ip_conntrack_info ctinfo;
238 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
239 	const struct tcphdr *th;
240 
241 	if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0)
242 		return;
243 
244 	th = (struct tcphdr *)(skb->data + ip_hdrlen(skb));
245 	nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off);
246 }
247 
248 /* Handles expected signalling connections and media streams */
ip_nat_sip_expected(struct nf_conn * ct,struct nf_conntrack_expect * exp)249 static void ip_nat_sip_expected(struct nf_conn *ct,
250 				struct nf_conntrack_expect *exp)
251 {
252 	struct nf_nat_ipv4_range range;
253 
254 	/* This must be a fresh one. */
255 	BUG_ON(ct->status & IPS_NAT_DONE_MASK);
256 
257 	/* For DST manip, map port here to where it's expected. */
258 	range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
259 	range.min = range.max = exp->saved_proto;
260 	range.min_ip = range.max_ip = exp->saved_ip;
261 	nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
262 
263 	/* Change src to where master sends to, but only if the connection
264 	 * actually came from the same source. */
265 	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip ==
266 	    ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
267 		range.flags = NF_NAT_RANGE_MAP_IPS;
268 		range.min_ip = range.max_ip
269 			= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
270 		nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
271 	}
272 }
273 
ip_nat_sip_expect(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen,struct nf_conntrack_expect * exp,unsigned int matchoff,unsigned int matchlen)274 static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff,
275 				      const char **dptr, unsigned int *datalen,
276 				      struct nf_conntrack_expect *exp,
277 				      unsigned int matchoff,
278 				      unsigned int matchlen)
279 {
280 	enum ip_conntrack_info ctinfo;
281 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
282 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
283 	__be32 newip;
284 	u_int16_t port;
285 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
286 	unsigned buflen;
287 
288 	/* Connection will come from reply */
289 	if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip)
290 		newip = exp->tuple.dst.u3.ip;
291 	else
292 		newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
293 
294 	/* If the signalling port matches the connection's source port in the
295 	 * original direction, try to use the destination port in the opposite
296 	 * direction. */
297 	if (exp->tuple.dst.u.udp.port ==
298 	    ct->tuplehash[dir].tuple.src.u.udp.port)
299 		port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
300 	else
301 		port = ntohs(exp->tuple.dst.u.udp.port);
302 
303 	exp->saved_ip = exp->tuple.dst.u3.ip;
304 	exp->tuple.dst.u3.ip = newip;
305 	exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
306 	exp->dir = !dir;
307 	exp->expectfn = ip_nat_sip_expected;
308 
309 	for (; port != 0; port++) {
310 		int ret;
311 
312 		exp->tuple.dst.u.udp.port = htons(port);
313 		ret = nf_ct_expect_related(exp);
314 		if (ret == 0)
315 			break;
316 		else if (ret != -EBUSY) {
317 			port = 0;
318 			break;
319 		}
320 	}
321 
322 	if (port == 0)
323 		return NF_DROP;
324 
325 	if (exp->tuple.dst.u3.ip != exp->saved_ip ||
326 	    exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
327 		buflen = sprintf(buffer, "%pI4:%u", &newip, port);
328 		if (!mangle_packet(skb, dataoff, dptr, datalen,
329 				   matchoff, matchlen, buffer, buflen))
330 			goto err;
331 	}
332 	return NF_ACCEPT;
333 
334 err:
335 	nf_ct_unexpect_related(exp);
336 	return NF_DROP;
337 }
338 
mangle_content_len(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen)339 static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff,
340 			      const char **dptr, unsigned int *datalen)
341 {
342 	enum ip_conntrack_info ctinfo;
343 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
344 	unsigned int matchoff, matchlen;
345 	char buffer[sizeof("65536")];
346 	int buflen, c_len;
347 
348 	/* Get actual SDP length */
349 	if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
350 				  SDP_HDR_VERSION, SDP_HDR_UNSPEC,
351 				  &matchoff, &matchlen) <= 0)
352 		return 0;
353 	c_len = *datalen - matchoff + strlen("v=");
354 
355 	/* Now, update SDP length */
356 	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
357 			      &matchoff, &matchlen) <= 0)
358 		return 0;
359 
360 	buflen = sprintf(buffer, "%u", c_len);
361 	return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
362 			     buffer, buflen);
363 }
364 
mangle_sdp_packet(struct sk_buff * skb,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)365 static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff,
366 			     const char **dptr, unsigned int *datalen,
367 			     unsigned int sdpoff,
368 			     enum sdp_header_types type,
369 			     enum sdp_header_types term,
370 			     char *buffer, int buflen)
371 {
372 	enum ip_conntrack_info ctinfo;
373 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
374 	unsigned int matchlen, matchoff;
375 
376 	if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
377 				  &matchoff, &matchlen) <= 0)
378 		return -ENOENT;
379 	return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
380 			     buffer, buflen) ? 0 : -EINVAL;
381 }
382 
ip_nat_sdp_addr(struct sk_buff * skb,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)383 static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff,
384 				    const char **dptr, unsigned int *datalen,
385 				    unsigned int sdpoff,
386 				    enum sdp_header_types type,
387 				    enum sdp_header_types term,
388 				    const union nf_inet_addr *addr)
389 {
390 	char buffer[sizeof("nnn.nnn.nnn.nnn")];
391 	unsigned int buflen;
392 
393 	buflen = sprintf(buffer, "%pI4", &addr->ip);
394 	if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term,
395 			      buffer, buflen))
396 		return 0;
397 
398 	return mangle_content_len(skb, dataoff, dptr, datalen);
399 }
400 
ip_nat_sdp_port(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int matchoff,unsigned int matchlen,u_int16_t port)401 static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff,
402 				    const char **dptr, unsigned int *datalen,
403 				    unsigned int matchoff,
404 				    unsigned int matchlen,
405 				    u_int16_t port)
406 {
407 	char buffer[sizeof("nnnnn")];
408 	unsigned int buflen;
409 
410 	buflen = sprintf(buffer, "%u", port);
411 	if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
412 			   buffer, buflen))
413 		return 0;
414 
415 	return mangle_content_len(skb, dataoff, dptr, datalen);
416 }
417 
ip_nat_sdp_session(struct sk_buff * skb,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int sdpoff,const union nf_inet_addr * addr)418 static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff,
419 				       const char **dptr, unsigned int *datalen,
420 				       unsigned int sdpoff,
421 				       const union nf_inet_addr *addr)
422 {
423 	char buffer[sizeof("nnn.nnn.nnn.nnn")];
424 	unsigned int buflen;
425 
426 	/* Mangle session description owner and contact addresses */
427 	buflen = sprintf(buffer, "%pI4", &addr->ip);
428 	if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
429 			       SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
430 			       buffer, buflen))
431 		return 0;
432 
433 	switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
434 				  SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
435 				  buffer, buflen)) {
436 	case 0:
437 	/*
438 	 * RFC 2327:
439 	 *
440 	 * Session description
441 	 *
442 	 * c=* (connection information - not required if included in all media)
443 	 */
444 	case -ENOENT:
445 		break;
446 	default:
447 		return 0;
448 	}
449 
450 	return mangle_content_len(skb, dataoff, dptr, datalen);
451 }
452 
453 /* So, this packet has hit the connection tracking matching code.
454    Mangle it, and change the expectation to match the new version. */
ip_nat_sdp_media(struct sk_buff * skb,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)455 static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff,
456 				     const char **dptr, unsigned int *datalen,
457 				     struct nf_conntrack_expect *rtp_exp,
458 				     struct nf_conntrack_expect *rtcp_exp,
459 				     unsigned int mediaoff,
460 				     unsigned int medialen,
461 				     union nf_inet_addr *rtp_addr)
462 {
463 	enum ip_conntrack_info ctinfo;
464 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
465 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
466 	u_int16_t port;
467 
468 	/* Connection will come from reply */
469 	if (ct->tuplehash[dir].tuple.src.u3.ip ==
470 	    ct->tuplehash[!dir].tuple.dst.u3.ip)
471 		rtp_addr->ip = rtp_exp->tuple.dst.u3.ip;
472 	else
473 		rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
474 
475 	rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip;
476 	rtp_exp->tuple.dst.u3.ip = rtp_addr->ip;
477 	rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
478 	rtp_exp->dir = !dir;
479 	rtp_exp->expectfn = ip_nat_sip_expected;
480 
481 	rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip;
482 	rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip;
483 	rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
484 	rtcp_exp->dir = !dir;
485 	rtcp_exp->expectfn = ip_nat_sip_expected;
486 
487 	/* Try to get same pair of ports: if not, try to change them. */
488 	for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
489 	     port != 0; port += 2) {
490 		int ret;
491 
492 		rtp_exp->tuple.dst.u.udp.port = htons(port);
493 		ret = nf_ct_expect_related(rtp_exp);
494 		if (ret == -EBUSY)
495 			continue;
496 		else if (ret < 0) {
497 			port = 0;
498 			break;
499 		}
500 		rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
501 		ret = nf_ct_expect_related(rtcp_exp);
502 		if (ret == 0)
503 			break;
504 		else if (ret != -EBUSY) {
505 			nf_ct_unexpect_related(rtp_exp);
506 			port = 0;
507 			break;
508 		}
509 	}
510 
511 	if (port == 0)
512 		goto err1;
513 
514 	/* Update media port. */
515 	if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
516 	    !ip_nat_sdp_port(skb, dataoff, dptr, datalen,
517 			     mediaoff, medialen, port))
518 		goto err2;
519 
520 	return NF_ACCEPT;
521 
522 err2:
523 	nf_ct_unexpect_related(rtp_exp);
524 	nf_ct_unexpect_related(rtcp_exp);
525 err1:
526 	return NF_DROP;
527 }
528 
nf_nat_sip_fini(void)529 static void __exit nf_nat_sip_fini(void)
530 {
531 	RCU_INIT_POINTER(nf_nat_sip_hook, NULL);
532 	RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, NULL);
533 	RCU_INIT_POINTER(nf_nat_sip_expect_hook, NULL);
534 	RCU_INIT_POINTER(nf_nat_sdp_addr_hook, NULL);
535 	RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL);
536 	RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL);
537 	RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL);
538 	synchronize_rcu();
539 }
540 
nf_nat_sip_init(void)541 static int __init nf_nat_sip_init(void)
542 {
543 	BUG_ON(nf_nat_sip_hook != NULL);
544 	BUG_ON(nf_nat_sip_seq_adjust_hook != NULL);
545 	BUG_ON(nf_nat_sip_expect_hook != NULL);
546 	BUG_ON(nf_nat_sdp_addr_hook != NULL);
547 	BUG_ON(nf_nat_sdp_port_hook != NULL);
548 	BUG_ON(nf_nat_sdp_session_hook != NULL);
549 	BUG_ON(nf_nat_sdp_media_hook != NULL);
550 	RCU_INIT_POINTER(nf_nat_sip_hook, ip_nat_sip);
551 	RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust);
552 	RCU_INIT_POINTER(nf_nat_sip_expect_hook, ip_nat_sip_expect);
553 	RCU_INIT_POINTER(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
554 	RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port);
555 	RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session);
556 	RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media);
557 	return 0;
558 }
559 
560 module_init(nf_nat_sip_init);
561 module_exit(nf_nat_sip_fini);
562