Blame view

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

a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
591
592
593
594
595
596
597
598
599
  	RCU_INIT_POINTER(set_h245_addr_hook, set_h245_addr);
  	RCU_INIT_POINTER(set_h225_addr_hook, set_h225_addr);
  	RCU_INIT_POINTER(set_sig_addr_hook, set_sig_addr);
  	RCU_INIT_POINTER(set_ras_addr_hook, set_ras_addr);
  	RCU_INIT_POINTER(nat_rtp_rtcp_hook, nat_rtp_rtcp);
  	RCU_INIT_POINTER(nat_t120_hook, nat_t120);
  	RCU_INIT_POINTER(nat_h245_hook, nat_h245);
  	RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
  	RCU_INIT_POINTER(nat_q931_hook, nat_q931);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
600
601
602
603
604
605
  	return 0;
  }
  
  /****************************************************************************/
  static void __exit fini(void)
  {
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
606
607
608
609
610
611
612
613
614
  	RCU_INIT_POINTER(set_h245_addr_hook, NULL);
  	RCU_INIT_POINTER(set_h225_addr_hook, NULL);
  	RCU_INIT_POINTER(set_sig_addr_hook, NULL);
  	RCU_INIT_POINTER(set_ras_addr_hook, NULL);
  	RCU_INIT_POINTER(nat_rtp_rtcp_hook, NULL);
  	RCU_INIT_POINTER(nat_t120_hook, NULL);
  	RCU_INIT_POINTER(nat_h245_hook, NULL);
  	RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
  	RCU_INIT_POINTER(nat_q931_hook, NULL);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
615
616
617
618
619
620
621
622
623
624
625
  	synchronize_rcu();
  }
  
  /****************************************************************************/
  module_init(init);
  module_exit(fini);
  
  MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
  MODULE_DESCRIPTION("H.323 NAT helper");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("ip_nat_h323");