xref: /openbmc/linux/net/ipv4/netfilter/nf_nat_h323.c (revision c92c2717)
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 	nated_port = nf_nat_exp_find_port(exp, nated_port);
295 	if (nated_port == 0) {	/* No port available */
296 		net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
297 		return 0;
298 	}
299 
300 	/* Modify signal */
301 	if (set_h245_addr(skb, protoff, data, dataoff, taddr,
302 			  &ct->tuplehash[!dir].tuple.dst.u3,
303 			  htons(nated_port)) < 0) {
304 		nf_ct_unexpect_related(exp);
305 		return -1;
306 	}
307 
308 	pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n",
309 		 &exp->tuple.src.u3.ip,
310 		 ntohs(exp->tuple.src.u.tcp.port),
311 		 &exp->tuple.dst.u3.ip,
312 		 ntohs(exp->tuple.dst.u.tcp.port));
313 
314 	return 0;
315 }
316 
317 /****************************************************************************/
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)318 static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
319 		    enum ip_conntrack_info ctinfo,
320 		    unsigned int protoff, unsigned char **data, int dataoff,
321 		    TransportAddress *taddr, __be16 port,
322 		    struct nf_conntrack_expect *exp)
323 {
324 	struct nf_ct_h323_master *info = nfct_help_data(ct);
325 	int dir = CTINFO2DIR(ctinfo);
326 	u_int16_t nated_port = ntohs(port);
327 
328 	/* Set expectations for NAT */
329 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
330 	exp->expectfn = nf_nat_follow_master;
331 	exp->dir = !dir;
332 
333 	/* Check existing expects */
334 	if (info->sig_port[dir] == port)
335 		nated_port = ntohs(info->sig_port[!dir]);
336 
337 	nated_port = nf_nat_exp_find_port(exp, nated_port);
338 	if (nated_port == 0) {	/* No port available */
339 		net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
340 		return 0;
341 	}
342 
343 	/* Modify signal */
344 	if (set_h225_addr(skb, protoff, data, dataoff, taddr,
345 			  &ct->tuplehash[!dir].tuple.dst.u3,
346 			  htons(nated_port))) {
347 		nf_ct_unexpect_related(exp);
348 		return -1;
349 	}
350 
351 	/* Save ports */
352 	info->sig_port[dir] = port;
353 	info->sig_port[!dir] = htons(nated_port);
354 
355 	pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
356 		 &exp->tuple.src.u3.ip,
357 		 ntohs(exp->tuple.src.u.tcp.port),
358 		 &exp->tuple.dst.u3.ip,
359 		 ntohs(exp->tuple.dst.u.tcp.port));
360 
361 	return 0;
362 }
363 
364 /****************************************************************************
365  * This conntrack expect function replaces nf_conntrack_q931_expect()
366  * which was set by nf_conntrack_h323.c.
367  ****************************************************************************/
ip_nat_q931_expect(struct nf_conn * new,struct nf_conntrack_expect * this)368 static void ip_nat_q931_expect(struct nf_conn *new,
369 			       struct nf_conntrack_expect *this)
370 {
371 	struct nf_nat_range2 range;
372 
373 	if (this->tuple.src.u3.ip != 0) {	/* Only accept calls from GK */
374 		nf_nat_follow_master(new, this);
375 		return;
376 	}
377 
378 	/* This must be a fresh one. */
379 	BUG_ON(new->status & IPS_NAT_DONE_MASK);
380 
381 	/* Change src to where master sends to */
382 	range.flags = NF_NAT_RANGE_MAP_IPS;
383 	range.min_addr = range.max_addr =
384 	    new->tuplehash[!this->dir].tuple.src.u3;
385 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
386 
387 	/* For DST manip, map port here to where it's expected. */
388 	range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
389 	range.min_proto = range.max_proto = this->saved_proto;
390 	range.min_addr = range.max_addr =
391 	    new->master->tuplehash[!this->dir].tuple.src.u3;
392 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
393 }
394 
395 /****************************************************************************/
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)396 static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
397 		    enum ip_conntrack_info ctinfo,
398 		    unsigned int protoff, unsigned char **data,
399 		    TransportAddress *taddr, int idx,
400 		    __be16 port, struct nf_conntrack_expect *exp)
401 {
402 	struct nf_ct_h323_master *info = nfct_help_data(ct);
403 	int dir = CTINFO2DIR(ctinfo);
404 	u_int16_t nated_port = ntohs(port);
405 	union nf_inet_addr addr;
406 
407 	/* Set expectations for NAT */
408 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
409 	exp->expectfn = ip_nat_q931_expect;
410 	exp->dir = !dir;
411 
412 	/* Check existing expects */
413 	if (info->sig_port[dir] == port)
414 		nated_port = ntohs(info->sig_port[!dir]);
415 
416 	nated_port = nf_nat_exp_find_port(exp, nated_port);
417 	if (nated_port == 0) {	/* No port available */
418 		net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
419 		return 0;
420 	}
421 
422 	/* Modify signal */
423 	if (set_h225_addr(skb, protoff, data, 0, &taddr[idx],
424 			  &ct->tuplehash[!dir].tuple.dst.u3,
425 			  htons(nated_port))) {
426 		nf_ct_unexpect_related(exp);
427 		return -1;
428 	}
429 
430 	/* Save ports */
431 	info->sig_port[dir] = port;
432 	info->sig_port[!dir] = htons(nated_port);
433 
434 	/* Fix for Gnomemeeting */
435 	if (idx > 0 &&
436 	    get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
437 	    (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
438 		if (set_h225_addr(skb, protoff, data, 0, &taddr[0],
439 				  &ct->tuplehash[!dir].tuple.dst.u3,
440 				  info->sig_port[!dir])) {
441 			nf_ct_unexpect_related(exp);
442 			return -1;
443 		}
444 	}
445 
446 	/* Success */
447 	pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n",
448 		 &exp->tuple.src.u3.ip,
449 		 ntohs(exp->tuple.src.u.tcp.port),
450 		 &exp->tuple.dst.u3.ip,
451 		 ntohs(exp->tuple.dst.u.tcp.port));
452 
453 	return 0;
454 }
455 
456 /****************************************************************************/
ip_nat_callforwarding_expect(struct nf_conn * new,struct nf_conntrack_expect * this)457 static void ip_nat_callforwarding_expect(struct nf_conn *new,
458 					 struct nf_conntrack_expect *this)
459 {
460 	struct nf_nat_range2 range;
461 
462 	/* This must be a fresh one. */
463 	BUG_ON(new->status & IPS_NAT_DONE_MASK);
464 
465 	/* Change src to where master sends to */
466 	range.flags = NF_NAT_RANGE_MAP_IPS;
467 	range.min_addr = range.max_addr =
468 	    new->tuplehash[!this->dir].tuple.src.u3;
469 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
470 
471 	/* For DST manip, map port here to where it's expected. */
472 	range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
473 	range.min_proto = range.max_proto = this->saved_proto;
474 	range.min_addr = range.max_addr = this->saved_addr;
475 	nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
476 }
477 
478 /****************************************************************************/
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)479 static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
480 			      enum ip_conntrack_info ctinfo,
481 			      unsigned int protoff,
482 			      unsigned char **data, int dataoff,
483 			      TransportAddress *taddr, __be16 port,
484 			      struct nf_conntrack_expect *exp)
485 {
486 	int dir = CTINFO2DIR(ctinfo);
487 	u_int16_t nated_port;
488 
489 	/* Set expectations for NAT */
490 	exp->saved_addr = exp->tuple.dst.u3;
491 	exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
492 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
493 	exp->expectfn = ip_nat_callforwarding_expect;
494 	exp->dir = !dir;
495 
496 	nated_port = nf_nat_exp_find_port(exp, ntohs(port));
497 	if (nated_port == 0) {	/* No port available */
498 		net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
499 		return 0;
500 	}
501 
502 	/* Modify signal */
503 	if (set_h225_addr(skb, protoff, data, dataoff, taddr,
504 			  &ct->tuplehash[!dir].tuple.dst.u3,
505 			  htons(nated_port))) {
506 		nf_ct_unexpect_related(exp);
507 		return -1;
508 	}
509 
510 	/* Success */
511 	pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n",
512 		 &exp->tuple.src.u3.ip,
513 		 ntohs(exp->tuple.src.u.tcp.port),
514 		 &exp->tuple.dst.u3.ip,
515 		 ntohs(exp->tuple.dst.u.tcp.port));
516 
517 	return 0;
518 }
519 
520 static struct nf_ct_helper_expectfn q931_nat = {
521 	.name		= "Q.931",
522 	.expectfn	= ip_nat_q931_expect,
523 };
524 
525 static struct nf_ct_helper_expectfn callforwarding_nat = {
526 	.name		= "callforwarding",
527 	.expectfn	= ip_nat_callforwarding_expect,
528 };
529 
530 static const struct nfct_h323_nat_hooks nathooks = {
531 	.set_h245_addr = set_h245_addr,
532 	.set_h225_addr = set_h225_addr,
533 	.set_sig_addr = set_sig_addr,
534 	.set_ras_addr = set_ras_addr,
535 	.nat_rtp_rtcp = nat_rtp_rtcp,
536 	.nat_t120 = nat_t120,
537 	.nat_h245 = nat_h245,
538 	.nat_callforwarding = nat_callforwarding,
539 	.nat_q931 = nat_q931,
540 };
541 
542 /****************************************************************************/
nf_nat_h323_init(void)543 static int __init nf_nat_h323_init(void)
544 {
545 	RCU_INIT_POINTER(nfct_h323_nat_hook, &nathooks);
546 	nf_ct_helper_expectfn_register(&q931_nat);
547 	nf_ct_helper_expectfn_register(&callforwarding_nat);
548 	return 0;
549 }
550 
551 /****************************************************************************/
nf_nat_h323_fini(void)552 static void __exit nf_nat_h323_fini(void)
553 {
554 	RCU_INIT_POINTER(nfct_h323_nat_hook, NULL);
555 	nf_ct_helper_expectfn_unregister(&q931_nat);
556 	nf_ct_helper_expectfn_unregister(&callforwarding_nat);
557 	synchronize_rcu();
558 }
559 
560 /****************************************************************************/
561 module_init(nf_nat_h323_init);
562 module_exit(nf_nat_h323_fini);
563 
564 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
565 MODULE_DESCRIPTION("H.323 NAT helper");
566 MODULE_LICENSE("GPL");
567 MODULE_ALIAS_NF_NAT_HELPER("h323");
568