1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * H.323 extension for NAT alteration.
4  *
5  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
6  * Copyright (c) 2006-2012 Patrick McHardy <kaber@trash.net>
7  *
8  * Based on the 'brute force' H.323 NAT module by
9  * Jozsef Kadlecsik <kadlec@netfilter.org>
10  */
11 
12 #include <linux/module.h>
13 #include <linux/tcp.h>
14 #include <net/tcp.h>
15 
16 #include <net/netfilter/nf_nat.h>
17 #include <net/netfilter/nf_nat_helper.h>
18 #include <net/netfilter/nf_conntrack_helper.h>
19 #include <net/netfilter/nf_conntrack_expect.h>
20 #include <linux/netfilter/nf_conntrack_h323.h>
21 
22 /****************************************************************************/
set_addr(struct sk_buff * skb,unsigned int protoff,unsigned char ** data,int dataoff,unsigned int addroff,__be32 ip,__be16 port)23 static int set_addr(struct sk_buff *skb, unsigned int protoff,
24 		    unsigned char **data, int dataoff,
25 		    unsigned int addroff, __be32 ip, __be16 port)
26 {
27 	enum ip_conntrack_info ctinfo;
28 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
29 	struct {
30 		__be32 ip;
31 		__be16 port;
32 	} __attribute__ ((__packed__)) buf;
33 	const struct tcphdr *th;
34 	struct tcphdr _tcph;
35 
36 	buf.ip = ip;
37 	buf.port = port;
38 	addroff += dataoff;
39 
40 	if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
41 		if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
42 					      protoff, addroff, sizeof(buf),
43 					      (char *) &buf, sizeof(buf))) {
44 			net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_tcp_packet error\n");
45 			return -1;
46 		}
47 
48 		/* Relocate data pointer */
49 		th = skb_header_pointer(skb, ip_hdrlen(skb),
50 					sizeof(_tcph), &_tcph);
51 		if (th == NULL)
52 			return -1;
53 		*data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;
54 	} else {
55 		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
56 					      protoff, addroff, sizeof(buf),
57 					      (char *) &buf, sizeof(buf))) {
58 			net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n");
59 			return -1;
60 		}
61 		/* nf_nat_mangle_udp_packet uses skb_ensure_writable() to copy
62 		 * or pull everything in a linear buffer, so we can safely
63 		 * use the skb pointers now */
64 		*data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
65 	}
66 
67 	return 0;
68 }
69 
70 /****************************************************************************/
set_h225_addr(struct sk_buff * skb,unsigned int protoff,unsigned char ** data,int dataoff,TransportAddress * taddr,union nf_inet_addr * addr,__be16 port)71 static int set_h225_addr(struct sk_buff *skb, unsigned int protoff,
72 			 unsigned char **data, int dataoff,
73 			 TransportAddress *taddr,
74 			 union nf_inet_addr *addr, __be16 port)
75 {
76 	return set_addr(skb, protoff, data, dataoff, taddr->ipAddress.ip,
77 			addr->ip, port);
78 }
79 
80 /****************************************************************************/
set_h245_addr(struct sk_buff * skb,unsigned protoff,unsigned char ** data,int dataoff,H245_TransportAddress * taddr,union nf_inet_addr * addr,__be16 port)81 static int set_h245_addr(struct sk_buff *skb, unsigned protoff,
82 			 unsigned char **data, int dataoff,
83 			 H245_TransportAddress *taddr,
84 			 union nf_inet_addr *addr, __be16 port)
85 {
86 	return set_addr(skb, protoff, data, dataoff,
87 			taddr->unicastAddress.iPAddress.network,
88 			addr->ip, port);
89 }
90 
91 /****************************************************************************/
set_sig_addr(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,TransportAddress * taddr,int count)92 static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
93 			enum ip_conntrack_info ctinfo,
94 			unsigned int protoff, unsigned char **data,
95 			TransportAddress *taddr, int count)
96 {
97 	const struct nf_ct_h323_master *info = nfct_help_data(ct);
98 	int dir = CTINFO2DIR(ctinfo);
99 	int i;
100 	__be16 port;
101 	union nf_inet_addr addr;
102 
103 	for (i = 0; i < count; i++) {
104 		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
105 			if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
106 			    port == info->sig_port[dir]) {
107 				/* GW->GK */
108 
109 				/* Fix for Gnomemeeting */
110 				if (i > 0 &&
111 				    get_h225_addr(ct, *data, &taddr[0],
112 						  &addr, &port) &&
113 				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
114 					i = 0;
115 
116 				pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
117 					 &addr.ip, port,
118 					 &ct->tuplehash[!dir].tuple.dst.u3.ip,
119 					 info->sig_port[!dir]);
120 				return set_h225_addr(skb, protoff, data, 0,
121 						     &taddr[i],
122 						     &ct->tuplehash[!dir].
123 						     tuple.dst.u3,
124 						     info->sig_port[!dir]);
125 			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
126 				   port == info->sig_port[dir]) {
127 				/* GK->GW */
128 				pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
129 					 &addr.ip, port,
130 					 &ct->tuplehash[!dir].tuple.src.u3.ip,
131 					 info->sig_port[!dir]);
132 				return set_h225_addr(skb, protoff, data, 0,
133 						     &taddr[i],
134 						     &ct->tuplehash[!dir].
135 						     tuple.src.u3,
136 						     info->sig_port[!dir]);
137 			}
138 		}
139 	}
140 
141 	return 0;
142 }
143 
144 /****************************************************************************/
set_ras_addr(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,TransportAddress * taddr,int count)145 static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
146 			enum ip_conntrack_info ctinfo,
147 			unsigned int protoff, unsigned char **data,
148 			TransportAddress *taddr, int count)
149 {
150 	int dir = CTINFO2DIR(ctinfo);
151 	int i;
152 	__be16 port;
153 	union nf_inet_addr addr;
154 
155 	for (i = 0; i < count; i++) {
156 		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
157 		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
158 		    port == ct->tuplehash[dir].tuple.src.u.udp.port) {
159 			pr_debug("nf_nat_ras: set rasAddress %pI4:%hu->%pI4:%hu\n",
160 				 &addr.ip, ntohs(port),
161 				 &ct->tuplehash[!dir].tuple.dst.u3.ip,
162 				 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
163 			return set_h225_addr(skb, protoff, data, 0, &taddr[i],
164 					     &ct->tuplehash[!dir].tuple.dst.u3,
165 					     ct->tuplehash[!dir].tuple.
166 								dst.u.udp.port);
167 		}
168 	}
169 
170 	return 0;
171 }
172 
173 /****************************************************************************/
nat_rtp_rtcp(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,int dataoff,H245_TransportAddress * taddr,__be16 port,__be16 rtp_port,struct nf_conntrack_expect * rtp_exp,struct nf_conntrack_expect * rtcp_exp)174 static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
175 			enum ip_conntrack_info ctinfo,
176 			unsigned int protoff, unsigned char **data, int dataoff,
177 			H245_TransportAddress *taddr,
178 			__be16 port, __be16 rtp_port,
179 			struct nf_conntrack_expect *rtp_exp,
180 			struct nf_conntrack_expect *rtcp_exp)
181 {
182 	struct nf_ct_h323_master *info = nfct_help_data(ct);
183 	int dir = CTINFO2DIR(ctinfo);
184 	int i;
185 	u_int16_t nated_port;
186 
187 	/* Set expectations for NAT */
188 	rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
189 	rtp_exp->expectfn = nf_nat_follow_master;
190 	rtp_exp->dir = !dir;
191 	rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
192 	rtcp_exp->expectfn = nf_nat_follow_master;
193 	rtcp_exp->dir = !dir;
194 
195 	/* Lookup existing expects */
196 	for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
197 		if (info->rtp_port[i][dir] == rtp_port) {
198 			/* Expected */
199 
200 			/* Use allocated ports first. This will refresh
201 			 * the expects */
202 			rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
203 			rtcp_exp->tuple.dst.u.udp.port =
204 			    htons(ntohs(info->rtp_port[i][dir]) + 1);
205 			break;
206 		} else if (info->rtp_port[i][dir] == 0) {
207 			/* Not expected */
208 			break;
209 		}
210 	}
211 
212 	/* Run out of expectations */
213 	if (i >= H323_RTP_CHANNEL_MAX) {
214 		net_notice_ratelimited("nf_nat_h323: out of expectations\n");
215 		return 0;
216 	}
217 
218 	/* Try to get a pair of ports. */
219 	for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
220 	     nated_port != 0; nated_port += 2) {
221 		int ret;
222 
223 		rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
224 		ret = nf_ct_expect_related(rtp_exp, 0);
225 		if (ret == 0) {
226 			rtcp_exp->tuple.dst.u.udp.port =
227 			    htons(nated_port + 1);
228 			ret = nf_ct_expect_related(rtcp_exp, 0);
229 			if (ret == 0)
230 				break;
231 			else if (ret == -EBUSY) {
232 				nf_ct_unexpect_related(rtp_exp);
233 				continue;
234 			} else if (ret < 0) {
235 				nf_ct_unexpect_related(rtp_exp);
236 				nated_port = 0;
237 				break;
238 			}
239 		} else if (ret != -EBUSY) {
240 			nated_port = 0;
241 			break;
242 		}
243 	}
244 
245 	if (nated_port == 0) {	/* No port available */
246 		net_notice_ratelimited("nf_nat_h323: out of RTP ports\n");
247 		return 0;
248 	}
249 
250 	/* Modify signal */
251 	if (set_h245_addr(skb, protoff, data, dataoff, taddr,
252 			  &ct->tuplehash[!dir].tuple.dst.u3,
253 			  htons((port & htons(1)) ? nated_port + 1 :
254 						    nated_port))) {
255 		nf_ct_unexpect_related(rtp_exp);
256 		nf_ct_unexpect_related(rtcp_exp);
257 		return -1;
258 	}
259 
260 	/* Save ports */
261 	info->rtp_port[i][dir] = rtp_port;
262 	info->rtp_port[i][!dir] = htons(nated_port);
263 
264 	/* Success */
265 	pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n",
266 		 &rtp_exp->tuple.src.u3.ip,
267 		 ntohs(rtp_exp->tuple.src.u.udp.port),
268 		 &rtp_exp->tuple.dst.u3.ip,
269 		 ntohs(rtp_exp->tuple.dst.u.udp.port));
270 	pr_debug("nf_nat_h323: expect RTCP %pI4:%hu->%pI4:%hu\n",
271 		 &rtcp_exp->tuple.src.u3.ip,
272 		 ntohs(rtcp_exp->tuple.src.u.udp.port),
273 		 &rtcp_exp->tuple.dst.u3.ip,
274 		 ntohs(rtcp_exp->tuple.dst.u.udp.port));
275 
276 	return 0;
277 }
278 
279 /****************************************************************************/
nat_t120(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,int dataoff,H245_TransportAddress * taddr,__be16 port,struct nf_conntrack_expect * exp)280 static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
281 		    enum ip_conntrack_info ctinfo,
282 		    unsigned int protoff, unsigned char **data, int dataoff,
283 		    H245_TransportAddress *taddr, __be16 port,
284 		    struct nf_conntrack_expect *exp)
285 {
286 	int dir = CTINFO2DIR(ctinfo);
287 	u_int16_t nated_port = ntohs(port);
288 
289 	/* Set expectations for NAT */
290 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
291 	exp->expectfn = nf_nat_follow_master;
292 	exp->dir = !dir;
293 
294 	/* Try to get same port: if not, try to change it. */
295 	for (; nated_port != 0; nated_port++) {
296 		int ret;
297 
298 		exp->tuple.dst.u.tcp.port = htons(nated_port);
299 		ret = nf_ct_expect_related(exp, 0);
300 		if (ret == 0)
301 			break;
302 		else if (ret != -EBUSY) {
303 			nated_port = 0;
304 			break;
305 		}
306 	}
307 
308 	if (nated_port == 0) {	/* No port available */
309 		net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
310 		return 0;
311 	}
312 
313 	/* Modify signal */
314 	if (set_h245_addr(skb, protoff, data, dataoff, taddr,
315 			  &ct->tuplehash[!dir].tuple.dst.u3,
316 			  htons(nated_port)) < 0) {
317 		nf_ct_unexpect_related(exp);
318 		return -1;
319 	}
320 
321 	pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n",
322 		 &exp->tuple.src.u3.ip,
323 		 ntohs(exp->tuple.src.u.tcp.port),
324 		 &exp->tuple.dst.u3.ip,
325 		 ntohs(exp->tuple.dst.u.tcp.port));
326 
327 	return 0;
328 }
329 
330 /****************************************************************************/
nat_h245(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,int dataoff,TransportAddress * taddr,__be16 port,struct nf_conntrack_expect * exp)331 static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
332 		    enum ip_conntrack_info ctinfo,
333 		    unsigned int protoff, unsigned char **data, int dataoff,
334 		    TransportAddress *taddr, __be16 port,
335 		    struct nf_conntrack_expect *exp)
336 {
337 	struct nf_ct_h323_master *info = nfct_help_data(ct);
338 	int dir = CTINFO2DIR(ctinfo);
339 	u_int16_t nated_port = ntohs(port);
340 
341 	/* Set expectations for NAT */
342 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
343 	exp->expectfn = nf_nat_follow_master;
344 	exp->dir = !dir;
345 
346 	/* Check existing expects */
347 	if (info->sig_port[dir] == port)
348 		nated_port = ntohs(info->sig_port[!dir]);
349 
350 	/* Try to get same port: if not, try to change it. */
351 	for (; nated_port != 0; nated_port++) {
352 		int ret;
353 
354 		exp->tuple.dst.u.tcp.port = htons(nated_port);
355 		ret = nf_ct_expect_related(exp, 0);
356 		if (ret == 0)
357 			break;
358 		else if (ret != -EBUSY) {
359 			nated_port = 0;
360 			break;
361 		}
362 	}
363 
364 	if (nated_port == 0) {	/* No port available */
365 		net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
366 		return 0;
367 	}
368 
369 	/* Modify signal */
370 	if (set_h225_addr(skb, protoff, data, dataoff, taddr,
371 			  &ct->tuplehash[!dir].tuple.dst.u3,
372 			  htons(nated_port))) {
373 		nf_ct_unexpect_related(exp);
374 		return -1;
375 	}
376 
377 	/* Save ports */
378 	info->sig_port[dir] = port;
379 	info->sig_port[!dir] = htons(nated_port);
380 
381 	pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
382 		 &exp->tuple.src.u3.ip,
383 		 ntohs(exp->tuple.src.u.tcp.port),
384 		 &exp->tuple.dst.u3.ip,
385 		 ntohs(exp->tuple.dst.u.tcp.port));
386 
387 	return 0;
388 }
389 
390 /****************************************************************************
391  * This conntrack expect function replaces nf_conntrack_q931_expect()
392  * which was set by nf_conntrack_h323.c.
393  ****************************************************************************/
ip_nat_q931_expect(struct nf_conn * new,struct nf_conntrack_expect * this)394 static void ip_nat_q931_expect(struct nf_conn *new,
395 			       struct nf_conntrack_expect *this)
396 {
397 	struct nf_nat_range2 range;
398 
399 	if (this->tuple.src.u3.ip != 0) {	/* Only accept calls from GK */
400 		nf_nat_follow_master(new, this);
401 		return;
402 	}
403 
404 	/* This must be a fresh one. */
405 	BUG_ON(new->status & IPS_NAT_DONE_MASK);
406 
407 	/* Change src to where master sends to */
408 	range.flags = NF_NAT_RANGE_MAP_IPS;
409 	range.min_addr = range.max_addr =
410 	    new->tuplehash[!this->dir].tuple.src.u3;
411 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
412 
413 	/* For DST manip, map port here to where it's expected. */
414 	range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
415 	range.min_proto = range.max_proto = this->saved_proto;
416 	range.min_addr = range.max_addr =
417 	    new->master->tuplehash[!this->dir].tuple.src.u3;
418 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
419 }
420 
421 /****************************************************************************/
nat_q931(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,TransportAddress * taddr,int idx,__be16 port,struct nf_conntrack_expect * exp)422 static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
423 		    enum ip_conntrack_info ctinfo,
424 		    unsigned int protoff, unsigned char **data,
425 		    TransportAddress *taddr, int idx,
426 		    __be16 port, struct nf_conntrack_expect *exp)
427 {
428 	struct nf_ct_h323_master *info = nfct_help_data(ct);
429 	int dir = CTINFO2DIR(ctinfo);
430 	u_int16_t nated_port = ntohs(port);
431 	union nf_inet_addr addr;
432 
433 	/* Set expectations for NAT */
434 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
435 	exp->expectfn = ip_nat_q931_expect;
436 	exp->dir = !dir;
437 
438 	/* Check existing expects */
439 	if (info->sig_port[dir] == port)
440 		nated_port = ntohs(info->sig_port[!dir]);
441 
442 	/* Try to get same port: if not, try to change it. */
443 	for (; nated_port != 0; nated_port++) {
444 		int ret;
445 
446 		exp->tuple.dst.u.tcp.port = htons(nated_port);
447 		ret = nf_ct_expect_related(exp, 0);
448 		if (ret == 0)
449 			break;
450 		else if (ret != -EBUSY) {
451 			nated_port = 0;
452 			break;
453 		}
454 	}
455 
456 	if (nated_port == 0) {	/* No port available */
457 		net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
458 		return 0;
459 	}
460 
461 	/* Modify signal */
462 	if (set_h225_addr(skb, protoff, data, 0, &taddr[idx],
463 			  &ct->tuplehash[!dir].tuple.dst.u3,
464 			  htons(nated_port))) {
465 		nf_ct_unexpect_related(exp);
466 		return -1;
467 	}
468 
469 	/* Save ports */
470 	info->sig_port[dir] = port;
471 	info->sig_port[!dir] = htons(nated_port);
472 
473 	/* Fix for Gnomemeeting */
474 	if (idx > 0 &&
475 	    get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
476 	    (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
477 		if (set_h225_addr(skb, protoff, data, 0, &taddr[0],
478 				  &ct->tuplehash[!dir].tuple.dst.u3,
479 				  info->sig_port[!dir])) {
480 			nf_ct_unexpect_related(exp);
481 			return -1;
482 		}
483 	}
484 
485 	/* Success */
486 	pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n",
487 		 &exp->tuple.src.u3.ip,
488 		 ntohs(exp->tuple.src.u.tcp.port),
489 		 &exp->tuple.dst.u3.ip,
490 		 ntohs(exp->tuple.dst.u.tcp.port));
491 
492 	return 0;
493 }
494 
495 /****************************************************************************/
ip_nat_callforwarding_expect(struct nf_conn * new,struct nf_conntrack_expect * this)496 static void ip_nat_callforwarding_expect(struct nf_conn *new,
497 					 struct nf_conntrack_expect *this)
498 {
499 	struct nf_nat_range2 range;
500 
501 	/* This must be a fresh one. */
502 	BUG_ON(new->status & IPS_NAT_DONE_MASK);
503 
504 	/* Change src to where master sends to */
505 	range.flags = NF_NAT_RANGE_MAP_IPS;
506 	range.min_addr = range.max_addr =
507 	    new->tuplehash[!this->dir].tuple.src.u3;
508 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
509 
510 	/* For DST manip, map port here to where it's expected. */
511 	range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
512 	range.min_proto = range.max_proto = this->saved_proto;
513 	range.min_addr = range.max_addr = this->saved_addr;
514 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
515 }
516 
517 /****************************************************************************/
nat_callforwarding(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int protoff,unsigned char ** data,int dataoff,TransportAddress * taddr,__be16 port,struct nf_conntrack_expect * exp)518 static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
519 			      enum ip_conntrack_info ctinfo,
520 			      unsigned int protoff,
521 			      unsigned char **data, int dataoff,
522 			      TransportAddress *taddr, __be16 port,
523 			      struct nf_conntrack_expect *exp)
524 {
525 	int dir = CTINFO2DIR(ctinfo);
526 	u_int16_t nated_port;
527 
528 	/* Set expectations for NAT */
529 	exp->saved_addr = exp->tuple.dst.u3;
530 	exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
531 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
532 	exp->expectfn = ip_nat_callforwarding_expect;
533 	exp->dir = !dir;
534 
535 	/* Try to get same port: if not, try to change it. */
536 	for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
537 		int ret;
538 
539 		exp->tuple.dst.u.tcp.port = htons(nated_port);
540 		ret = nf_ct_expect_related(exp, 0);
541 		if (ret == 0)
542 			break;
543 		else if (ret != -EBUSY) {
544 			nated_port = 0;
545 			break;
546 		}
547 	}
548 
549 	if (nated_port == 0) {	/* No port available */
550 		net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
551 		return 0;
552 	}
553 
554 	/* Modify signal */
555 	if (set_h225_addr(skb, protoff, data, dataoff, taddr,
556 			  &ct->tuplehash[!dir].tuple.dst.u3,
557 			  htons(nated_port))) {
558 		nf_ct_unexpect_related(exp);
559 		return -1;
560 	}
561 
562 	/* Success */
563 	pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n",
564 		 &exp->tuple.src.u3.ip,
565 		 ntohs(exp->tuple.src.u.tcp.port),
566 		 &exp->tuple.dst.u3.ip,
567 		 ntohs(exp->tuple.dst.u.tcp.port));
568 
569 	return 0;
570 }
571 
572 static struct nf_ct_helper_expectfn q931_nat = {
573 	.name		= "Q.931",
574 	.expectfn	= ip_nat_q931_expect,
575 };
576 
577 static struct nf_ct_helper_expectfn callforwarding_nat = {
578 	.name		= "callforwarding",
579 	.expectfn	= ip_nat_callforwarding_expect,
580 };
581 
582 /****************************************************************************/
init(void)583 static int __init init(void)
584 {
585 	BUG_ON(set_h245_addr_hook != NULL);
586 	BUG_ON(set_h225_addr_hook != NULL);
587 	BUG_ON(set_sig_addr_hook != NULL);
588 	BUG_ON(set_ras_addr_hook != NULL);
589 	BUG_ON(nat_rtp_rtcp_hook != NULL);
590 	BUG_ON(nat_t120_hook != NULL);
591 	BUG_ON(nat_h245_hook != NULL);
592 	BUG_ON(nat_callforwarding_hook != NULL);
593 	BUG_ON(nat_q931_hook != NULL);
594 
595 	RCU_INIT_POINTER(set_h245_addr_hook, set_h245_addr);
596 	RCU_INIT_POINTER(set_h225_addr_hook, set_h225_addr);
597 	RCU_INIT_POINTER(set_sig_addr_hook, set_sig_addr);
598 	RCU_INIT_POINTER(set_ras_addr_hook, set_ras_addr);
599 	RCU_INIT_POINTER(nat_rtp_rtcp_hook, nat_rtp_rtcp);
600 	RCU_INIT_POINTER(nat_t120_hook, nat_t120);
601 	RCU_INIT_POINTER(nat_h245_hook, nat_h245);
602 	RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
603 	RCU_INIT_POINTER(nat_q931_hook, nat_q931);
604 	nf_ct_helper_expectfn_register(&q931_nat);
605 	nf_ct_helper_expectfn_register(&callforwarding_nat);
606 	return 0;
607 }
608 
609 /****************************************************************************/
fini(void)610 static void __exit fini(void)
611 {
612 	RCU_INIT_POINTER(set_h245_addr_hook, NULL);
613 	RCU_INIT_POINTER(set_h225_addr_hook, NULL);
614 	RCU_INIT_POINTER(set_sig_addr_hook, NULL);
615 	RCU_INIT_POINTER(set_ras_addr_hook, NULL);
616 	RCU_INIT_POINTER(nat_rtp_rtcp_hook, NULL);
617 	RCU_INIT_POINTER(nat_t120_hook, NULL);
618 	RCU_INIT_POINTER(nat_h245_hook, NULL);
619 	RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
620 	RCU_INIT_POINTER(nat_q931_hook, NULL);
621 	nf_ct_helper_expectfn_unregister(&q931_nat);
622 	nf_ct_helper_expectfn_unregister(&callforwarding_nat);
623 	synchronize_rcu();
624 }
625 
626 /****************************************************************************/
627 module_init(init);
628 module_exit(fini);
629 
630 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
631 MODULE_DESCRIPTION("H.323 NAT helper");
632 MODULE_LICENSE("GPL");
633 MODULE_ALIAS_NF_NAT_HELPER("h323");
634