Blame view

net/netfilter/nf_conntrack_h323_main.c 54.1 KB
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1
2
3
4
  /*
   * H.323 connection tracking helper
   *
   * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
f229f6ce4   Patrick McHardy   netfilter: add my...
5
   * Copyright (c) 2006-2012 Patrick McHardy <kaber@trash.net>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   *
   * This source code is licensed under General Public License version 2.
   *
   * Based on the 'brute force' H.323 connection tracking module by
   * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
   *
   * For more information, please see http://nath323.sourceforge.net/
   */
  
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/ctype.h>
  #include <linux/inet.h>
  #include <linux/in.h>
  #include <linux/ip.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
22
23
24
25
26
27
28
29
30
31
32
33
  #include <linux/udp.h>
  #include <linux/tcp.h>
  #include <linux/skbuff.h>
  #include <net/route.h>
  #include <net/ip6_route.h>
  
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
  #include <net/netfilter/nf_conntrack_tuple.h>
  #include <net/netfilter/nf_conntrack_expect.h>
  #include <net/netfilter/nf_conntrack_ecache.h>
  #include <net/netfilter/nf_conntrack_helper.h>
5d0aa2ccd   Patrick McHardy   netfilter: nf_con...
34
  #include <net/netfilter/nf_conntrack_zones.h>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
35
  #include <linux/netfilter/nf_conntrack_h323.h>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
36
37
38
39
40
41
42
43
  /* Parameters */
  static unsigned int default_rrq_ttl __read_mostly = 300;
  module_param(default_rrq_ttl, uint, 0600);
  MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
  
  static int gkrouted_only __read_mostly = 1;
  module_param(gkrouted_only, int, 0600);
  MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
eb9399220   Rusty Russell   module_param: mak...
44
  static bool callforward_filter __read_mostly = true;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
45
46
  module_param(callforward_filter, bool, 0600);
  MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
47
  				     "if both endpoints are on different sides "
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
48
49
50
  				     "(determined by routing information)");
  
  /* Hooks for NAT */
051966c0c   Patrick McHardy   netfilter: nf_nat...
51
  int (*set_h245_addr_hook) (struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
52
53
  			   unsigned char **data, int dataoff,
  			   H245_TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
54
  			   union nf_inet_addr *addr, __be16 port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
55
  			   __read_mostly;
051966c0c   Patrick McHardy   netfilter: nf_nat...
56
  int (*set_h225_addr_hook) (struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
57
58
  			   unsigned char **data, int dataoff,
  			   TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
59
  			   union nf_inet_addr *addr, __be16 port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
60
  			   __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
61
  int (*set_sig_addr_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
62
63
  			  struct nf_conn *ct,
  			  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
64
  			  unsigned int protoff, unsigned char **data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
65
  			  TransportAddress *taddr, int count) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
66
  int (*set_ras_addr_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
67
68
  			  struct nf_conn *ct,
  			  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
69
  			  unsigned int protoff, unsigned char **data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
70
  			  TransportAddress *taddr, int count) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
71
  int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
72
73
  			  struct nf_conn *ct,
  			  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
74
  			  unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
75
76
77
78
79
  			  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) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
80
  int (*nat_t120_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
81
82
  		      struct nf_conn *ct,
  		      enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
83
  		      unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
84
85
86
  		      unsigned char **data, int dataoff,
  		      H245_TransportAddress *taddr, __be16 port,
  		      struct nf_conntrack_expect *exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
87
  int (*nat_h245_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
88
89
  		      struct nf_conn *ct,
  		      enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
90
  		      unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
91
92
93
  		      unsigned char **data, int dataoff,
  		      TransportAddress *taddr, __be16 port,
  		      struct nf_conntrack_expect *exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
94
  int (*nat_callforwarding_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
95
96
  				struct nf_conn *ct,
  				enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
97
  				unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
98
99
100
  				unsigned char **data, int dataoff,
  				TransportAddress *taddr, __be16 port,
  				struct nf_conntrack_expect *exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
101
  int (*nat_q931_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
102
103
  		      struct nf_conn *ct,
  		      enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
104
  		      unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
105
106
107
108
109
110
111
112
113
114
115
116
  		      unsigned char **data, TransportAddress *taddr, int idx,
  		      __be16 port, struct nf_conntrack_expect *exp)
  		      __read_mostly;
  
  static DEFINE_SPINLOCK(nf_h323_lock);
  static char *h323_buffer;
  
  static struct nf_conntrack_helper nf_conntrack_helper_h245;
  static struct nf_conntrack_helper nf_conntrack_helper_q931[];
  static struct nf_conntrack_helper nf_conntrack_helper_ras[];
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
117
  static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
118
119
120
  			 struct nf_conn *ct, enum ip_conntrack_info ctinfo,
  			 unsigned char **data, int *datalen, int *dataoff)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
121
  	struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
122
  	int dir = CTINFO2DIR(ctinfo);
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
123
124
  	const struct tcphdr *th;
  	struct tcphdr _tcph;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
125
126
127
128
129
130
131
  	int tcpdatalen;
  	int tcpdataoff;
  	unsigned char *tpkt;
  	int tpktlen;
  	int tpktoff;
  
  	/* Get TCP header */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
132
  	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
133
134
135
136
137
138
139
  	if (th == NULL)
  		return 0;
  
  	/* Get TCP data offset */
  	tcpdataoff = protoff + th->doff * 4;
  
  	/* Get TCP data length */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
140
  	tcpdatalen = skb->len - tcpdataoff;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
141
142
143
144
145
  	if (tcpdatalen <= 0)	/* No TCP data */
  		goto clear_out;
  
  	if (*data == NULL) {	/* first TPKT */
  		/* Get first TPKT pointer */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
146
  		tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
147
148
149
150
151
152
153
  					  h323_buffer);
  		BUG_ON(tpkt == NULL);
  
  		/* Validate TPKT identifier */
  		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
  			/* Netmeeting sends TPKT header and data separately */
  			if (info->tpkt_len[dir] > 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
154
155
156
157
  				pr_debug("nf_ct_h323: previous packet "
  					 "indicated separate TPKT data of %hu "
  					 "bytes
  ", info->tpkt_len[dir]);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
158
159
160
161
162
163
164
165
166
167
  				if (info->tpkt_len[dir] <= tcpdatalen) {
  					/* Yes, there was a TPKT header
  					 * received */
  					*data = tpkt;
  					*datalen = info->tpkt_len[dir];
  					*dataoff = 0;
  					goto out;
  				}
  
  				/* Fragmented TPKT */
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
168
169
  				pr_debug("nf_ct_h323: fragmented TPKT
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  				goto clear_out;
  			}
  
  			/* It is not even a TPKT */
  			return 0;
  		}
  		tpktoff = 0;
  	} else {		/* Next TPKT */
  		tpktoff = *dataoff + *datalen;
  		tcpdatalen -= tpktoff;
  		if (tcpdatalen <= 4)	/* No more TPKT */
  			goto clear_out;
  		tpkt = *data + *datalen;
  
  		/* Validate TPKT identifier */
  		if (tpkt[0] != 0x03 || tpkt[1] != 0)
  			goto clear_out;
  	}
  
  	/* Validate TPKT length */
  	tpktlen = tpkt[2] * 256 + tpkt[3];
  	if (tpktlen < 4)
  		goto clear_out;
  	if (tpktlen > tcpdatalen) {
  		if (tcpdatalen == 4) {	/* Separate TPKT header */
  			/* Netmeeting sends TPKT header and data separately */
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
196
197
198
199
  			pr_debug("nf_ct_h323: separate TPKT header indicates "
  				 "there will be TPKT data of %hu bytes
  ",
  				 tpktlen - 4);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
200
201
202
  			info->tpkt_len[dir] = tpktlen - 4;
  			return 0;
  		}
e772c349a   Patrick McHardy   netfilter: nf_ct_...
203
204
  		pr_debug("nf_ct_h323: incomplete TPKT (fragmented?)
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  		goto clear_out;
  	}
  
  	/* This is the encapsulated data */
  	*data = tpkt + 4;
  	*datalen = tpktlen - 4;
  	*dataoff = tpktoff + 4;
  
        out:
  	/* Clear TPKT length */
  	info->tpkt_len[dir] = 0;
  	return 1;
  
        clear_out:
  	info->tpkt_len[dir] = 0;
  	return 0;
  }
  
  /****************************************************************************/
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
224
  static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
225
  			 H245_TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
226
  			 union nf_inet_addr *addr, __be16 *port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
227
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
228
  	const unsigned char *p;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
229
230
231
232
233
234
235
  	int len;
  
  	if (taddr->choice != eH245_TransportAddress_unicastAddress)
  		return 0;
  
  	switch (taddr->unicastAddress.choice) {
  	case eUnicastAddress_iPAddress:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
236
  		if (nf_ct_l3num(ct) != AF_INET)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
237
238
239
240
241
  			return 0;
  		p = data + taddr->unicastAddress.iPAddress.network;
  		len = 4;
  		break;
  	case eUnicastAddress_iP6Address:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
242
  		if (nf_ct_l3num(ct) != AF_INET6)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  			return 0;
  		p = data + taddr->unicastAddress.iP6Address.network;
  		len = 16;
  		break;
  	default:
  		return 0;
  	}
  
  	memcpy(addr, p, len);
  	memset((void *)addr + len, 0, sizeof(*addr) - len);
  	memcpy(port, p + len, sizeof(__be16));
  
  	return 1;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
259
  static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
260
  			   enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
261
  			   unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
262
263
264
265
266
267
268
  			   unsigned char **data, int dataoff,
  			   H245_TransportAddress *taddr)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
  	__be16 rtp_port, rtcp_port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
269
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
270
271
272
273
274
275
276
277
278
279
280
  	struct nf_conntrack_expect *rtp_exp;
  	struct nf_conntrack_expect *rtcp_exp;
  	typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
  
  	/* Read RTP or RTCP address */
  	if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
  	    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
  	    port == 0)
  		return 0;
  
  	/* RTP port is even */
d109e9af6   Pablo Neira Ayuso   netfilter: nf_ct_...
281
282
  	rtp_port = port & ~htons(1);
  	rtcp_port = port | htons(1);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
283
284
  
  	/* Create expect for RTP */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
285
  	if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
286
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
287
  	nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
288
289
290
  			  &ct->tuplehash[!dir].tuple.src.u3,
  			  &ct->tuplehash[!dir].tuple.dst.u3,
  			  IPPROTO_UDP, NULL, &rtp_port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
291
292
  
  	/* Create expect for RTCP */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
293
294
  	if ((rtcp_exp = nf_ct_expect_alloc(ct)) == NULL) {
  		nf_ct_expect_put(rtp_exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
295
296
  		return -1;
  	}
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
297
  	nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
298
299
300
  			  &ct->tuplehash[!dir].tuple.src.u3,
  			  &ct->tuplehash[!dir].tuple.dst.u3,
  			  IPPROTO_UDP, NULL, &rtcp_port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
301
302
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
303
  		   &ct->tuplehash[!dir].tuple.dst.u3,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
304
305
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  		   (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
306
  		   nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
307
308
  		   ct->status & IPS_NAT_MASK) {
  		/* NAT needed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
309
  		ret = nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
310
311
  				   taddr, port, rtp_port, rtp_exp, rtcp_exp);
  	} else {		/* Conntrack only */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
312
313
  		if (nf_ct_expect_related(rtp_exp) == 0) {
  			if (nf_ct_expect_related(rtcp_exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
314
  				pr_debug("nf_ct_h323: expect RTP ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
315
  				nf_ct_dump_tuple(&rtp_exp->tuple);
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
316
  				pr_debug("nf_ct_h323: expect RTCP ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
317
  				nf_ct_dump_tuple(&rtcp_exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
318
  			} else {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
319
  				nf_ct_unexpect_related(rtp_exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
320
321
322
323
324
  				ret = -1;
  			}
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
325
326
  	nf_ct_expect_put(rtp_exp);
  	nf_ct_expect_put(rtcp_exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
327
328
329
330
331
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
332
  static int expect_t120(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
333
334
  		       struct nf_conn *ct,
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
335
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
336
337
338
339
340
341
  		       unsigned char **data, int dataoff,
  		       H245_TransportAddress *taddr)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
342
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
343
344
345
346
347
348
349
350
351
352
  	struct nf_conntrack_expect *exp;
  	typeof(nat_t120_hook) nat_t120;
  
  	/* Read T.120 address */
  	if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
  	    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
  	    port == 0)
  		return 0;
  
  	/* Create expect for T.120 connections */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
353
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
354
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
355
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
356
357
358
  			  &ct->tuplehash[!dir].tuple.src.u3,
  			  &ct->tuplehash[!dir].tuple.dst.u3,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
359
360
361
362
363
364
  	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple channels */
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
  		   &ct->tuplehash[!dir].tuple.dst.u3,
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  	    (nat_t120 = rcu_dereference(nat_t120_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
365
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
366
367
  	    ct->status & IPS_NAT_MASK) {
  		/* NAT needed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
368
  		ret = nat_t120(skb, ct, ctinfo, protoff, data, dataoff, taddr,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
369
370
  			       port, exp);
  	} else {		/* Conntrack only */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
371
  		if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
372
  			pr_debug("nf_ct_h323: expect T.120 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
373
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
374
375
376
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
377
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
378
379
380
381
382
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
383
  static int process_h245_channel(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
384
385
  				struct nf_conn *ct,
  				enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
386
  				unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
387
388
389
390
391
392
393
  				unsigned char **data, int dataoff,
  				H2250LogicalChannelParameters *channel)
  {
  	int ret;
  
  	if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
  		/* RTP */
051966c0c   Patrick McHardy   netfilter: nf_nat...
394
  		ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
395
396
397
398
399
400
401
402
  				      &channel->mediaChannel);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (channel->
  	    options & eH2250LogicalChannelParameters_mediaControlChannel) {
  		/* RTCP */
051966c0c   Patrick McHardy   netfilter: nf_nat...
403
  		ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
404
405
406
407
408
409
410
411
412
  				      &channel->mediaControlChannel);
  		if (ret < 0)
  			return -1;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
413
  static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
414
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
415
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
416
417
418
419
  		       unsigned char **data, int dataoff,
  		       OpenLogicalChannel *olc)
  {
  	int ret;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
420
421
  	pr_debug("nf_ct_h323: OpenLogicalChannel
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
422
423
424
425
  
  	if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
  	    eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
  	{
051966c0c   Patrick McHardy   netfilter: nf_nat...
426
427
  		ret = process_h245_channel(skb, ct, ctinfo,
  					   protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  					   &olc->
  					   forwardLogicalChannelParameters.
  					   multiplexParameters.
  					   h2250LogicalChannelParameters);
  		if (ret < 0)
  			return -1;
  	}
  
  	if ((olc->options &
  	     eOpenLogicalChannel_reverseLogicalChannelParameters) &&
  	    (olc->reverseLogicalChannelParameters.options &
  	     eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
  	    && (olc->reverseLogicalChannelParameters.multiplexParameters.
  		choice ==
  		eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
  	{
  		ret =
051966c0c   Patrick McHardy   netfilter: nf_nat...
445
446
  		    process_h245_channel(skb, ct, ctinfo,
  					 protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  					 &olc->
  					 reverseLogicalChannelParameters.
  					 multiplexParameters.
  					 h2250LogicalChannelParameters);
  		if (ret < 0)
  			return -1;
  	}
  
  	if ((olc->options & eOpenLogicalChannel_separateStack) &&
  	    olc->forwardLogicalChannelParameters.dataType.choice ==
  	    eDataType_data &&
  	    olc->forwardLogicalChannelParameters.dataType.data.application.
  	    choice == eDataApplicationCapability_application_t120 &&
  	    olc->forwardLogicalChannelParameters.dataType.data.application.
  	    t120.choice == eDataProtocolCapability_separateLANStack &&
  	    olc->separateStack.networkAddress.choice ==
  	    eNetworkAccessParameters_networkAddress_localAreaAddress) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
464
  		ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
465
466
467
468
469
470
471
472
473
474
  				  &olc->separateStack.networkAddress.
  				  localAreaAddress);
  		if (ret < 0)
  			return -1;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
475
  static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
476
  			enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
477
  			unsigned int protoff, unsigned char **data, int dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
478
479
480
481
  			OpenLogicalChannelAck *olca)
  {
  	H2250LogicalChannelAckParameters *ack;
  	int ret;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
482
483
  	pr_debug("nf_ct_h323: OpenLogicalChannelAck
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
484
485
486
487
488
489
490
491
492
  
  	if ((olca->options &
  	     eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
  	    (olca->reverseLogicalChannelParameters.options &
  	     eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
  	    && (olca->reverseLogicalChannelParameters.multiplexParameters.
  		choice ==
  		eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
  	{
051966c0c   Patrick McHardy   netfilter: nf_nat...
493
494
  		ret = process_h245_channel(skb, ct, ctinfo,
  					   protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  					   &olca->
  					   reverseLogicalChannelParameters.
  					   multiplexParameters.
  					   h2250LogicalChannelParameters);
  		if (ret < 0)
  			return -1;
  	}
  
  	if ((olca->options &
  	     eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
  	    (olca->forwardMultiplexAckParameters.choice ==
  	     eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
  	{
  		ack = &olca->forwardMultiplexAckParameters.
  		    h2250LogicalChannelAckParameters;
  		if (ack->options &
  		    eH2250LogicalChannelAckParameters_mediaChannel) {
  			/* RTP */
051966c0c   Patrick McHardy   netfilter: nf_nat...
513
514
  			ret = expect_rtp_rtcp(skb, ct, ctinfo,
  					      protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
515
516
517
518
519
520
521
522
  					      &ack->mediaChannel);
  			if (ret < 0)
  				return -1;
  		}
  
  		if (ack->options &
  		    eH2250LogicalChannelAckParameters_mediaControlChannel) {
  			/* RTCP */
051966c0c   Patrick McHardy   netfilter: nf_nat...
523
524
  			ret = expect_rtp_rtcp(skb, ct, ctinfo,
  					      protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
525
526
527
528
529
  					      &ack->mediaControlChannel);
  			if (ret < 0)
  				return -1;
  		}
  	}
f8f1c08ea   Jing Min Zhao   [NETFILTER]: nf_c...
530
531
532
  	if ((olca->options & eOpenLogicalChannelAck_separateStack) &&
  		olca->separateStack.networkAddress.choice ==
  		eNetworkAccessParameters_networkAddress_localAreaAddress) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
533
  		ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff,
f8f1c08ea   Jing Min Zhao   [NETFILTER]: nf_c...
534
535
536
537
538
  				  &olca->separateStack.networkAddress.
  				  localAreaAddress);
  		if (ret < 0)
  			return -1;
  	}
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
539
540
541
542
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
543
  static int process_h245(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
544
  			enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
545
  			unsigned int protoff, unsigned char **data, int dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
546
547
548
549
550
551
  			MultimediaSystemControlMessage *mscm)
  {
  	switch (mscm->choice) {
  	case eMultimediaSystemControlMessage_request:
  		if (mscm->request.choice ==
  		    eRequestMessage_openLogicalChannel) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
552
553
  			return process_olc(skb, ct, ctinfo,
  					   protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
554
555
  					   &mscm->request.openLogicalChannel);
  		}
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
556
557
558
  		pr_debug("nf_ct_h323: H.245 Request %d
  ",
  			 mscm->request.choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
559
560
561
562
  		break;
  	case eMultimediaSystemControlMessage_response:
  		if (mscm->response.choice ==
  		    eResponseMessage_openLogicalChannelAck) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
563
564
  			return process_olca(skb, ct, ctinfo,
  					    protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
565
566
567
  					    &mscm->response.
  					    openLogicalChannelAck);
  		}
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
568
569
570
  		pr_debug("nf_ct_h323: H.245 Response %d
  ",
  			 mscm->response.choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
571
572
  		break;
  	default:
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
573
574
  		pr_debug("nf_ct_h323: H.245 signal %d
  ", mscm->choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
575
576
577
578
579
580
581
  		break;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
582
  static int h245_help(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
583
584
585
586
587
588
589
590
591
  		     struct nf_conn *ct, enum ip_conntrack_info ctinfo)
  {
  	static MultimediaSystemControlMessage mscm;
  	unsigned char *data = NULL;
  	int datalen;
  	int dataoff;
  	int ret;
  
  	/* Until there's been traffic both ways, don't look in packets. */
fb0488337   Eric Dumazet   netfilter: add mo...
592
  	if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
593
  		return NF_ACCEPT;
fb0488337   Eric Dumazet   netfilter: add mo...
594

3db05fea5   Herbert Xu   [NETFILTER]: Repl...
595
596
  	pr_debug("nf_ct_h245: skblen = %u
  ", skb->len);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
597
598
599
600
  
  	spin_lock_bh(&nf_h323_lock);
  
  	/* Process each TPKT */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
601
  	while (get_tpkt_data(skb, protoff, ct, ctinfo,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
602
  			     &data, &datalen, &dataoff)) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
603
  		pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
604
  		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
605
606
607
608
609
  
  		/* Decode H.245 signal */
  		ret = DecodeMultimediaSystemControlMessage(data, datalen,
  							   &mscm);
  		if (ret < 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
610
611
612
613
  			pr_debug("nf_ct_h245: decoding error: %s
  ",
  				 ret == H323_ERROR_BOUND ?
  				 "out of bound" : "out of range");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
614
615
616
617
618
  			/* We don't drop when decoding error */
  			break;
  		}
  
  		/* Process H.245 signal */
051966c0c   Patrick McHardy   netfilter: nf_nat...
619
620
  		if (process_h245(skb, ct, ctinfo, protoff,
  				 &data, dataoff, &mscm) < 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
621
622
623
624
625
626
627
628
  			goto drop;
  	}
  
  	spin_unlock_bh(&nf_h323_lock);
  	return NF_ACCEPT;
  
        drop:
  	spin_unlock_bh(&nf_h323_lock);
b20ab9cc6   Pablo Neira Ayuso   netfilter: nf_ct_...
629
  	nf_ct_helper_log(skb, ct, "cannot process H.245 message");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
630
631
632
633
  	return NF_DROP;
  }
  
  /****************************************************************************/
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
634
635
636
637
  static const struct nf_conntrack_expect_policy h245_exp_policy = {
  	.max_expected	= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
  	.timeout	= 240,
  };
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
638
639
640
  static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
  	.name			= "H.245",
  	.me			= THIS_MODULE,
a56b8f815   Patrick McHardy   netfilter: nf_con...
641
  	.tuple.src.l3num	= AF_UNSPEC,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
642
  	.tuple.dst.protonum	= IPPROTO_UDP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
643
644
  	.help			= h245_help,
  	.expect_policy		= &h245_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
645
646
647
648
649
  };
  
  /****************************************************************************/
  int get_h225_addr(struct nf_conn *ct, unsigned char *data,
  		  TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
650
  		  union nf_inet_addr *addr, __be16 *port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
651
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
652
  	const unsigned char *p;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
653
654
655
656
  	int len;
  
  	switch (taddr->choice) {
  	case eTransportAddress_ipAddress:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
657
  		if (nf_ct_l3num(ct) != AF_INET)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
658
659
660
661
662
  			return 0;
  		p = data + taddr->ipAddress.ip;
  		len = 4;
  		break;
  	case eTransportAddress_ip6Address:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
663
  		if (nf_ct_l3num(ct) != AF_INET6)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
664
  			return 0;
bb807245e   Jing Min Zhao   [NETFILTER]: nf_c...
665
  		p = data + taddr->ip6Address.ip;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  		len = 16;
  		break;
  	default:
  		return 0;
  	}
  
  	memcpy(addr, p, len);
  	memset((void *)addr + len, 0, sizeof(*addr) - len);
  	memcpy(port, p + len, sizeof(__be16));
  
  	return 1;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
680
  static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
681
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
682
  		       unsigned int protoff, unsigned char **data, int dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
683
684
685
686
687
  		       TransportAddress *taddr)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
688
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
689
690
691
692
693
694
695
696
697
698
  	struct nf_conntrack_expect *exp;
  	typeof(nat_h245_hook) nat_h245;
  
  	/* Read h245Address */
  	if (!get_h225_addr(ct, *data, taddr, &addr, &port) ||
  	    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
  	    port == 0)
  		return 0;
  
  	/* Create expect for h245 connection */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
699
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
700
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
701
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
702
703
704
  			  &ct->tuplehash[!dir].tuple.src.u3,
  			  &ct->tuplehash[!dir].tuple.dst.u3,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
705
706
707
708
709
710
  	exp->helper = &nf_conntrack_helper_h245;
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
  		   &ct->tuplehash[!dir].tuple.dst.u3,
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  	    (nat_h245 = rcu_dereference(nat_h245_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
711
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
712
713
  	    ct->status & IPS_NAT_MASK) {
  		/* NAT needed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
714
  		ret = nat_h245(skb, ct, ctinfo, protoff, data, dataoff, taddr,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
715
716
  			       port, exp);
  	} else {		/* Conntrack only */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
717
  		if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
718
  			pr_debug("nf_ct_q931: expect H.245 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
719
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
720
721
722
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
723
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
724
725
726
727
728
729
  
  	return ret;
  }
  
  /* If the calling party is on the same side of the forward-to party,
   * we don't need to track the second call */
2c7b5d5da   Vasily Averin   netfilter: nf_con...
730
731
  static int callforward_do_filter(struct net *net,
  				 const union nf_inet_addr *src,
76108cea0   Jan Engelhardt   netfilter: Use un...
732
733
  				 const union nf_inet_addr *dst,
  				 u_int8_t family)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
734
  {
1e796fda0   Patrick McHardy   [NETFILTER]: cons...
735
  	const struct nf_afinfo *afinfo;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
736
  	int ret = 0;
e2361cb90   Aaron Conole   netfilter: Remove...
737
  	/* rcu_read_lock()ed by nf_hook_thresh */
1841a4c7a   Patrick McHardy   [NETFILTER]: nf_c...
738
739
740
  	afinfo = nf_get_afinfo(family);
  	if (!afinfo)
  		return 0;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
741
742
  	switch (family) {
  	case AF_INET: {
5a49d0e04   David S. Miller   netfilter: Use fl...
743
  		struct flowi4 fl1, fl2;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
744
  		struct rtable *rt1, *rt2;
5a49d0e04   David S. Miller   netfilter: Use fl...
745
746
747
748
749
  		memset(&fl1, 0, sizeof(fl1));
  		fl1.daddr = src->ip;
  
  		memset(&fl2, 0, sizeof(fl2));
  		fl2.daddr = dst->ip;
2c7b5d5da   Vasily Averin   netfilter: nf_con...
750
  		if (!afinfo->route(net, (struct dst_entry **)&rt1,
0fae2e774   Florian Westphal   netfilter: af_inf...
751
  				   flowi4_to_flowi(&fl1), false)) {
2c7b5d5da   Vasily Averin   netfilter: nf_con...
752
  			if (!afinfo->route(net, (struct dst_entry **)&rt2,
0fae2e774   Florian Westphal   netfilter: af_inf...
753
  					   flowi4_to_flowi(&fl2), false)) {
bbb5823cf   Julian Anastasov   netfilter: nf_con...
754
755
  				if (rt_nexthop(rt1, fl1.daddr) ==
  				    rt_nexthop(rt2, fl2.daddr) &&
d8d1f30b9   Changli Gao   net-next: remove ...
756
  				    rt1->dst.dev  == rt2->dst.dev)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
757
  					ret = 1;
d8d1f30b9   Changli Gao   net-next: remove ...
758
  				dst_release(&rt2->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
759
  			}
d8d1f30b9   Changli Gao   net-next: remove ...
760
  			dst_release(&rt1->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
761
762
763
  		}
  		break;
  	}
c0cd11566   Igor Maravić   net:netfilter: us...
764
  #if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
765
  	case AF_INET6: {
5a49d0e04   David S. Miller   netfilter: Use fl...
766
  		struct flowi6 fl1, fl2;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
767
  		struct rt6_info *rt1, *rt2;
5a49d0e04   David S. Miller   netfilter: Use fl...
768
  		memset(&fl1, 0, sizeof(fl1));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
769
  		fl1.daddr = src->in6;
5a49d0e04   David S. Miller   netfilter: Use fl...
770
771
  
  		memset(&fl2, 0, sizeof(fl2));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
772
  		fl2.daddr = dst->in6;
2c7b5d5da   Vasily Averin   netfilter: nf_con...
773
  		if (!afinfo->route(net, (struct dst_entry **)&rt1,
0fae2e774   Florian Westphal   netfilter: af_inf...
774
  				   flowi6_to_flowi(&fl1), false)) {
2c7b5d5da   Vasily Averin   netfilter: nf_con...
775
  			if (!afinfo->route(net, (struct dst_entry **)&rt2,
0fae2e774   Florian Westphal   netfilter: af_inf...
776
  					   flowi6_to_flowi(&fl2), false)) {
2647a9b07   Martin KaFai Lau   ipv6: Remove exte...
777
778
  				if (ipv6_addr_equal(rt6_nexthop(rt1, &fl1.daddr),
  						    rt6_nexthop(rt2, &fl2.daddr)) &&
d8d1f30b9   Changli Gao   net-next: remove ...
779
  				    rt1->dst.dev == rt2->dst.dev)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
780
  					ret = 1;
d8d1f30b9   Changli Gao   net-next: remove ...
781
  				dst_release(&rt2->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
782
  			}
d8d1f30b9   Changli Gao   net-next: remove ...
783
  			dst_release(&rt1->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
784
785
786
787
788
789
790
791
792
793
  		}
  		break;
  	}
  #endif
  	}
  	return ret;
  
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
794
  static int expect_callforwarding(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
795
796
  				 struct nf_conn *ct,
  				 enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
797
  				 unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
798
799
800
801
802
803
  				 unsigned char **data, int dataoff,
  				 TransportAddress *taddr)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
804
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
805
  	struct nf_conntrack_expect *exp;
2c7b5d5da   Vasily Averin   netfilter: nf_con...
806
  	struct net *net = nf_ct_net(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
807
808
809
810
811
812
813
814
815
  	typeof(nat_callforwarding_hook) nat_callforwarding;
  
  	/* Read alternativeAddress */
  	if (!get_h225_addr(ct, *data, taddr, &addr, &port) || port == 0)
  		return 0;
  
  	/* If the calling party is on the same side of the forward-to party,
  	 * we don't need to track the second call */
  	if (callforward_filter &&
2c7b5d5da   Vasily Averin   netfilter: nf_con...
816
  	    callforward_do_filter(net, &addr, &ct->tuplehash[!dir].tuple.src.u3,
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
817
  				  nf_ct_l3num(ct))) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
818
819
  		pr_debug("nf_ct_q931: Call Forwarding not tracked
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
820
821
822
823
  		return 0;
  	}
  
  	/* Create expect for the second call leg */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
824
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
825
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
826
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
827
828
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
829
830
831
832
833
834
  	exp->helper = nf_conntrack_helper_q931;
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
  		   &ct->tuplehash[!dir].tuple.dst.u3,
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  	    (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
835
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
836
837
  	    ct->status & IPS_NAT_MASK) {
  		/* Need NAT */
051966c0c   Patrick McHardy   netfilter: nf_nat...
838
839
  		ret = nat_callforwarding(skb, ct, ctinfo,
  					 protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
840
841
  					 taddr, port, exp);
  	} else {		/* Conntrack only */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
842
  		if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
843
  			pr_debug("nf_ct_q931: expect Call Forwarding ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
844
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
845
846
847
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
848
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
849
850
851
852
853
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
854
  static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
855
  			 enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
856
  			 unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
857
858
859
860
861
862
863
  			 unsigned char **data, int dataoff,
  			 Setup_UUIE *setup)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret;
  	int i;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
864
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
865
  	typeof(set_h225_addr_hook) set_h225_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
866
867
  	pr_debug("nf_ct_q931: Setup
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
868
869
  
  	if (setup->options & eSetup_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
870
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
871
872
873
874
875
876
877
  				  &setup->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	set_h225_addr = rcu_dereference(set_h225_addr_hook);
  	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
878
879
  	    (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
880
  	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
881
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
882
  	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
5b095d989   Harvey Harrison   net: replace %p6 ...
883
884
  		pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu
  ",
38ff4fa49   Harvey Harrison   netfilter: replac...
885
  			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3,
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
886
  			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
051966c0c   Patrick McHardy   netfilter: nf_nat...
887
  		ret = set_h225_addr(skb, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
888
889
890
891
892
893
894
895
  				    &setup->destCallSignalAddress,
  				    &ct->tuplehash[!dir].tuple.src.u3,
  				    ct->tuplehash[!dir].tuple.src.u.tcp.port);
  		if (ret < 0)
  			return -1;
  	}
  
  	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
896
897
  	    (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
898
  	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
899
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
900
  	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
5b095d989   Harvey Harrison   net: replace %p6 ...
901
902
  		pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu
  ",
38ff4fa49   Harvey Harrison   netfilter: replac...
903
  			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3,
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
904
  			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
051966c0c   Patrick McHardy   netfilter: nf_nat...
905
  		ret = set_h225_addr(skb, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
906
907
908
909
910
911
912
913
914
  				    &setup->sourceCallSignalAddress,
  				    &ct->tuplehash[!dir].tuple.dst.u3,
  				    ct->tuplehash[!dir].tuple.dst.u.tcp.port);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (setup->options & eSetup_UUIE_fastStart) {
  		for (i = 0; i < setup->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
915
916
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
917
918
919
920
921
922
923
924
925
926
  					  &setup->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
927
  static int process_callproceeding(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
928
929
  				  struct nf_conn *ct,
  				  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
930
  				  unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
931
932
933
934
935
  				  unsigned char **data, int dataoff,
  				  CallProceeding_UUIE *callproc)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
936
937
  	pr_debug("nf_ct_q931: CallProceeding
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
938
939
  
  	if (callproc->options & eCallProceeding_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
940
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
941
942
943
944
945
946
947
  				  &callproc->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (callproc->options & eCallProceeding_UUIE_fastStart) {
  		for (i = 0; i < callproc->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
948
949
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
950
951
952
953
954
955
956
957
958
959
  					  &callproc->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
960
  static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
961
  			   enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
962
  			   unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
963
964
965
966
967
  			   unsigned char **data, int dataoff,
  			   Connect_UUIE *connect)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
968
969
  	pr_debug("nf_ct_q931: Connect
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
970
971
  
  	if (connect->options & eConnect_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
972
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
973
974
975
976
977
978
979
  				  &connect->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (connect->options & eConnect_UUIE_fastStart) {
  		for (i = 0; i < connect->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
980
981
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
982
983
984
985
986
987
988
989
990
991
  					  &connect->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
992
  static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
993
  			    enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
994
  			    unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
995
996
997
998
999
  			    unsigned char **data, int dataoff,
  			    Alerting_UUIE *alert)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1000
1001
  	pr_debug("nf_ct_q931: Alerting
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1002
1003
  
  	if (alert->options & eAlerting_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1004
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1005
1006
1007
1008
1009
1010
1011
  				  &alert->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (alert->options & eAlerting_UUIE_fastStart) {
  		for (i = 0; i < alert->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1012
1013
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  					  &alert->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1024
  static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1025
  			    enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1026
  			    unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1027
1028
1029
1030
1031
  			    unsigned char **data, int dataoff,
  			    Facility_UUIE *facility)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1032
1033
  	pr_debug("nf_ct_q931: Facility
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1034
1035
1036
  
  	if (facility->reason.choice == eFacilityReason_callForwarded) {
  		if (facility->options & eFacility_UUIE_alternativeAddress)
051966c0c   Patrick McHardy   netfilter: nf_nat...
1037
1038
  			return expect_callforwarding(skb, ct, ctinfo,
  						     protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1039
1040
1041
1042
1043
1044
  						     &facility->
  						     alternativeAddress);
  		return 0;
  	}
  
  	if (facility->options & eFacility_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1045
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1046
1047
1048
1049
1050
1051
1052
  				  &facility->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (facility->options & eFacility_UUIE_fastStart) {
  		for (i = 0; i < facility->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1053
1054
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
  					  &facility->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1065
  static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1066
  			    enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1067
  			    unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1068
1069
1070
1071
1072
  			    unsigned char **data, int dataoff,
  			    Progress_UUIE *progress)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1073
1074
  	pr_debug("nf_ct_q931: Progress
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1075
1076
  
  	if (progress->options & eProgress_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1077
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1078
1079
1080
1081
1082
1083
1084
  				  &progress->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (progress->options & eProgress_UUIE_fastStart) {
  		for (i = 0; i < progress->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1085
1086
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  					  &progress->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1097
  static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1098
  			enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1099
1100
  			unsigned int protoff, unsigned char **data, int dataoff,
  			Q931 *q931)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1101
1102
1103
1104
1105
1106
1107
  {
  	H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
  	int i;
  	int ret = 0;
  
  	switch (pdu->h323_message_body.choice) {
  	case eH323_UU_PDU_h323_message_body_setup:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1108
  		ret = process_setup(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1109
1110
1111
  				    &pdu->h323_message_body.setup);
  		break;
  	case eH323_UU_PDU_h323_message_body_callProceeding:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1112
1113
  		ret = process_callproceeding(skb, ct, ctinfo,
  					     protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1114
1115
1116
1117
  					     &pdu->h323_message_body.
  					     callProceeding);
  		break;
  	case eH323_UU_PDU_h323_message_body_connect:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1118
  		ret = process_connect(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1119
1120
1121
  				      &pdu->h323_message_body.connect);
  		break;
  	case eH323_UU_PDU_h323_message_body_alerting:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1122
  		ret = process_alerting(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1123
1124
  				       &pdu->h323_message_body.alerting);
  		break;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1125
  	case eH323_UU_PDU_h323_message_body_facility:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1126
  		ret = process_facility(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1127
1128
1129
  				       &pdu->h323_message_body.facility);
  		break;
  	case eH323_UU_PDU_h323_message_body_progress:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1130
  		ret = process_progress(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1131
1132
1133
  				       &pdu->h323_message_body.progress);
  		break;
  	default:
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1134
1135
1136
  		pr_debug("nf_ct_q931: Q.931 signal %d
  ",
  			 pdu->h323_message_body.choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1137
1138
1139
1140
1141
1142
1143
1144
  		break;
  	}
  
  	if (ret < 0)
  		return -1;
  
  	if (pdu->options & eH323_UU_PDU_h245Control) {
  		for (i = 0; i < pdu->h245Control.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1145
1146
  			ret = process_h245(skb, ct, ctinfo,
  					   protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  					   &pdu->h245Control.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1157
  static int q931_help(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1158
1159
1160
1161
1162
1163
1164
1165
1166
  		     struct nf_conn *ct, enum ip_conntrack_info ctinfo)
  {
  	static Q931 q931;
  	unsigned char *data = NULL;
  	int datalen;
  	int dataoff;
  	int ret;
  
  	/* Until there's been traffic both ways, don't look in packets. */
fb0488337   Eric Dumazet   netfilter: add mo...
1167
  	if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1168
  		return NF_ACCEPT;
fb0488337   Eric Dumazet   netfilter: add mo...
1169

3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1170
1171
  	pr_debug("nf_ct_q931: skblen = %u
  ", skb->len);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1172
1173
1174
1175
  
  	spin_lock_bh(&nf_h323_lock);
  
  	/* Process each TPKT */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1176
  	while (get_tpkt_data(skb, protoff, ct, ctinfo,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1177
  			     &data, &datalen, &dataoff)) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1178
  		pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1179
  		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1180
1181
1182
1183
  
  		/* Decode Q.931 signal */
  		ret = DecodeQ931(data, datalen, &q931);
  		if (ret < 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1184
1185
1186
1187
  			pr_debug("nf_ct_q931: decoding error: %s
  ",
  				 ret == H323_ERROR_BOUND ?
  				 "out of bound" : "out of range");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1188
1189
1190
1191
1192
  			/* We don't drop when decoding error */
  			break;
  		}
  
  		/* Process Q.931 signal */
051966c0c   Patrick McHardy   netfilter: nf_nat...
1193
1194
  		if (process_q931(skb, ct, ctinfo, protoff,
  				 &data, dataoff, &q931) < 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1195
1196
1197
1198
1199
1200
1201
1202
  			goto drop;
  	}
  
  	spin_unlock_bh(&nf_h323_lock);
  	return NF_ACCEPT;
  
        drop:
  	spin_unlock_bh(&nf_h323_lock);
b20ab9cc6   Pablo Neira Ayuso   netfilter: nf_ct_...
1203
  	nf_ct_helper_log(skb, ct, "cannot process Q.931 message");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1204
1205
1206
1207
  	return NF_DROP;
  }
  
  /****************************************************************************/
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1208
1209
1210
1211
1212
  static const struct nf_conntrack_expect_policy q931_exp_policy = {
  	/* T.120 and H.245 */
  	.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 4,
  	.timeout		= 240,
  };
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1213
1214
1215
1216
  static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
  	{
  		.name			= "Q.931",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1217
  		.tuple.src.l3num	= AF_INET,
09640e636   Harvey Harrison   net: replace uses...
1218
  		.tuple.src.u.tcp.port	= cpu_to_be16(Q931_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1219
  		.tuple.dst.protonum	= IPPROTO_TCP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1220
1221
  		.help			= q931_help,
  		.expect_policy		= &q931_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1222
1223
1224
1225
  	},
  	{
  		.name			= "Q.931",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1226
  		.tuple.src.l3num	= AF_INET6,
09640e636   Harvey Harrison   net: replace uses...
1227
  		.tuple.src.u.tcp.port	= cpu_to_be16(Q931_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1228
  		.tuple.dst.protonum	= IPPROTO_TCP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1229
1230
  		.help			= q931_help,
  		.expect_policy		= &q931_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1231
1232
1233
1234
  	},
  };
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1235
  static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1236
1237
  				   int *datalen)
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
1238
1239
  	const struct udphdr *uh;
  	struct udphdr _uh;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1240
  	int dataoff;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1241
  	uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1242
1243
1244
  	if (uh == NULL)
  		return NULL;
  	dataoff = protoff + sizeof(_uh);
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1245
  	if (dataoff >= skb->len)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1246
  		return NULL;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1247
1248
  	*datalen = skb->len - dataoff;
  	return skb_header_pointer(skb, dataoff, *datalen, h323_buffer);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1249
1250
1251
1252
  }
  
  /****************************************************************************/
  static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1253
  					       union nf_inet_addr *addr,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1254
1255
  					       __be16 port)
  {
84541cc13   Alexey Dobriyan   netfilter: netns ...
1256
  	struct net *net = nf_ct_net(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1257
1258
1259
1260
1261
1262
1263
1264
  	struct nf_conntrack_expect *exp;
  	struct nf_conntrack_tuple tuple;
  
  	memset(&tuple.src.u3, 0, sizeof(tuple.src.u3));
  	tuple.src.u.tcp.port = 0;
  	memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3));
  	tuple.dst.u.tcp.port = port;
  	tuple.dst.protonum = IPPROTO_TCP;
5d0aa2ccd   Patrick McHardy   netfilter: nf_con...
1265
  	exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1266
1267
1268
1269
1270
1271
  	if (exp && exp->master == ct)
  		return exp;
  	return NULL;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1272
  static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1273
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1274
  		       unsigned int protoff, unsigned char **data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1275
1276
  		       TransportAddress *taddr, int count)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1277
  	struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1278
1279
1280
1281
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	int i;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1282
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1283
1284
1285
1286
1287
1288
1289
  	struct nf_conntrack_expect *exp;
  	typeof(nat_q931_hook) nat_q931;
  
  	/* Look for the first related address */
  	for (i = 0; i < count; i++) {
  		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
  		    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1290
  			   sizeof(addr)) == 0 && port != 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1291
1292
1293
1294
1295
1296
1297
  			break;
  	}
  
  	if (i >= count)		/* Not found */
  		return 0;
  
  	/* Create expect for Q.931 */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1298
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1299
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1300
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1301
1302
1303
1304
  			  gkrouted_only ? /* only accept calls from GK? */
  				&ct->tuplehash[!dir].tuple.src.u3 : NULL,
  			  &ct->tuplehash[!dir].tuple.dst.u3,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1305
1306
1307
1308
  	exp->helper = nf_conntrack_helper_q931;
  	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
  
  	nat_q931 = rcu_dereference(nat_q931_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1309
1310
  	if (nat_q931 && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {	/* Need NAT */
051966c0c   Patrick McHardy   netfilter: nf_nat...
1311
1312
  		ret = nat_q931(skb, ct, ctinfo, protoff, data,
  			       taddr, i, port, exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1313
  	} else {		/* Conntrack only */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1314
  		if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1315
  			pr_debug("nf_ct_ras: expect Q.931 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1316
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1317
1318
1319
1320
1321
1322
  
  			/* Save port for looking up expect in processing RCF */
  			info->sig_port[dir] = port;
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1323
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1324
1325
1326
1327
1328
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1329
  static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1330
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1331
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1332
1333
1334
  		       unsigned char **data, GatekeeperRequest *grq)
  {
  	typeof(set_ras_addr_hook) set_ras_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1335
1336
  	pr_debug("nf_ct_ras: GRQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1337
1338
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1339
1340
  	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK)	/* NATed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
1341
  		return set_ras_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1342
1343
1344
1345
1346
  				    &grq->rasAddress, 1);
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1347
  static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1348
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1349
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1350
1351
1352
1353
1354
  		       unsigned char **data, GatekeeperConfirm *gcf)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1355
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1356
  	struct nf_conntrack_expect *exp;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1357
1358
  	pr_debug("nf_ct_ras: GCF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
  
  	if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
  		return 0;
  
  	/* Registration port is the same as discovery port */
  	if (!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
  	    port == ct->tuplehash[dir].tuple.src.u.udp.port)
  		return 0;
  
  	/* Avoid RAS expectation loops. A GCF is never expected. */
  	if (test_bit(IPS_EXPECTED_BIT, &ct->status))
  		return 0;
  
  	/* Need new expect */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1373
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1374
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1375
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1376
1377
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_UDP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1378
  	exp->helper = nf_conntrack_helper_ras;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1379
  	if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1380
  		pr_debug("nf_ct_ras: expect RAS ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1381
  		nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1382
1383
  	} else
  		ret = -1;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1384
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1385
1386
1387
1388
1389
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1390
  static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1391
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1392
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1393
1394
  		       unsigned char **data, RegistrationRequest *rrq)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1395
  	struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1396
1397
  	int ret;
  	typeof(set_ras_addr_hook) set_ras_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1398
1399
  	pr_debug("nf_ct_ras: RRQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1400

051966c0c   Patrick McHardy   netfilter: nf_nat...
1401
  	ret = expect_q931(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1402
1403
1404
1405
1406
1407
  			  rrq->callSignalAddress.item,
  			  rrq->callSignalAddress.count);
  	if (ret < 0)
  		return -1;
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1408
1409
  	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1410
  		ret = set_ras_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1411
1412
1413
1414
1415
1416
1417
  				   rrq->rasAddress.item,
  				   rrq->rasAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (rrq->options & eRegistrationRequest_timeToLive) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1418
1419
  		pr_debug("nf_ct_ras: RRQ TTL = %u seconds
  ", rrq->timeToLive);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1420
1421
1422
1423
1424
1425
1426
1427
  		info->timeout = rrq->timeToLive;
  	} else
  		info->timeout = default_rrq_ttl;
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1428
  static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1429
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1430
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1431
1432
  		       unsigned char **data, RegistrationConfirm *rcf)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1433
  	struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1434
1435
1436
1437
  	int dir = CTINFO2DIR(ctinfo);
  	int ret;
  	struct nf_conntrack_expect *exp;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1438
1439
  	pr_debug("nf_ct_ras: RCF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1440
1441
  
  	set_sig_addr = rcu_dereference(set_sig_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1442
1443
  	if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1444
  		ret = set_sig_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1445
1446
1447
1448
1449
1450
1451
  					rcf->callSignalAddress.item,
  					rcf->callSignalAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (rcf->options & eRegistrationConfirm_timeToLive) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1452
1453
  		pr_debug("nf_ct_ras: RCF TTL = %u seconds
  ", rcf->timeToLive);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1454
1455
1456
1457
  		info->timeout = rcf->timeToLive;
  	}
  
  	if (info->timeout > 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1458
1459
1460
  		pr_debug("nf_ct_ras: set RAS connection timeout to "
  			 "%u seconds
  ", info->timeout);
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1461
  		nf_ct_refresh(ct, skb, info->timeout * HZ);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1462
1463
  
  		/* Set expect timeout */
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1464
  		spin_lock_bh(&nf_conntrack_expect_lock);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1465
1466
1467
  		exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
  				  info->sig_port[!dir]);
  		if (exp) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1468
1469
1470
  			pr_debug("nf_ct_ras: set Q.931 expect "
  				 "timeout to %u seconds for",
  				 info->timeout);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1471
  			nf_ct_dump_tuple(&exp->tuple);
707e6835f   Liping Zhang   netfilter: nf_ct_...
1472
1473
  			mod_timer_pending(&exp->timeout,
  					  jiffies + info->timeout * HZ);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1474
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1475
  		spin_unlock_bh(&nf_conntrack_expect_lock);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1476
1477
1478
1479
1480
1481
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1482
  static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1483
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1484
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1485
1486
  		       unsigned char **data, UnregistrationRequest *urq)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1487
  	struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1488
1489
1490
  	int dir = CTINFO2DIR(ctinfo);
  	int ret;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1491
1492
  	pr_debug("nf_ct_ras: URQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1493
1494
  
  	set_sig_addr = rcu_dereference(set_sig_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1495
1496
  	if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1497
  		ret = set_sig_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
  				   urq->callSignalAddress.item,
  				   urq->callSignalAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	/* Clear old expect */
  	nf_ct_remove_expectations(ct);
  	info->sig_port[dir] = 0;
  	info->sig_port[!dir] = 0;
  
  	/* Give it 30 seconds for UCF or URJ */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1510
  	nf_ct_refresh(ct, skb, 30 * HZ);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1511
1512
1513
1514
1515
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1516
  static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1517
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1518
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1519
1520
  		       unsigned char **data, AdmissionRequest *arq)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1521
  	const struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1522
1523
  	int dir = CTINFO2DIR(ctinfo);
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1524
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1525
  	typeof(set_h225_addr_hook) set_h225_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1526
1527
  	pr_debug("nf_ct_ras: ARQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1528
1529
1530
1531
  
  	set_h225_addr = rcu_dereference(set_h225_addr_hook);
  	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
  	    get_h225_addr(ct, *data, &arq->destCallSignalAddress,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1532
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1533
1534
  	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
  	    port == info->sig_port[dir] &&
811927ccf   Patrick McHardy   netfilter: nf_con...
1535
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1536
1537
  	    set_h225_addr && ct->status & IPS_NAT_MASK) {
  		/* Answering ARQ */
051966c0c   Patrick McHardy   netfilter: nf_nat...
1538
  		return set_h225_addr(skb, protoff, data, 0,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1539
1540
1541
1542
1543
1544
1545
  				     &arq->destCallSignalAddress,
  				     &ct->tuplehash[!dir].tuple.dst.u3,
  				     info->sig_port[!dir]);
  	}
  
  	if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
  	    get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1546
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1547
  	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
1548
1549
  	    set_h225_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1550
  		/* Calling ARQ */
051966c0c   Patrick McHardy   netfilter: nf_nat...
1551
  		return set_h225_addr(skb, protoff, data, 0,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1552
1553
1554
1555
1556
1557
1558
1559
1560
  				     &arq->srcCallSignalAddress,
  				     &ct->tuplehash[!dir].tuple.dst.u3,
  				     port);
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1561
  static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1562
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1563
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1564
1565
1566
1567
1568
  		       unsigned char **data, AdmissionConfirm *acf)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1569
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1570
1571
  	struct nf_conntrack_expect *exp;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1572
1573
  	pr_debug("nf_ct_ras: ACF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1574
1575
1576
1577
1578
1579
1580
1581
  
  	if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
  			   &addr, &port))
  		return 0;
  
  	if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) {
  		/* Answering ACF */
  		set_sig_addr = rcu_dereference(set_sig_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1582
1583
  		if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  		    ct->status & IPS_NAT_MASK)
051966c0c   Patrick McHardy   netfilter: nf_nat...
1584
  			return set_sig_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1585
1586
1587
1588
1589
  					    &acf->destCallSignalAddress, 1);
  		return 0;
  	}
  
  	/* Need new expect */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1590
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1591
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1592
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1593
1594
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1595
1596
  	exp->flags = NF_CT_EXPECT_PERMANENT;
  	exp->helper = nf_conntrack_helper_q931;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1597
  	if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1598
  		pr_debug("nf_ct_ras: expect Q.931 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1599
  		nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1600
1601
  	} else
  		ret = -1;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1602
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1603
1604
1605
1606
1607
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1608
  static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1609
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1610
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1611
1612
1613
  		       unsigned char **data, LocationRequest *lrq)
  {
  	typeof(set_ras_addr_hook) set_ras_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1614
1615
  	pr_debug("nf_ct_ras: LRQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1616
1617
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1618
1619
  	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK)
051966c0c   Patrick McHardy   netfilter: nf_nat...
1620
  		return set_ras_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1621
1622
1623
1624
1625
  				    &lrq->replyAddress, 1);
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1626
  static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1627
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1628
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1629
1630
1631
1632
1633
  		       unsigned char **data, LocationConfirm *lcf)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1634
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1635
  	struct nf_conntrack_expect *exp;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1636
1637
  	pr_debug("nf_ct_ras: LCF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1638
1639
1640
1641
1642
1643
  
  	if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
  			   &addr, &port))
  		return 0;
  
  	/* Need new expect for call signal */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1644
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1645
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1646
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1647
1648
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1649
1650
  	exp->flags = NF_CT_EXPECT_PERMANENT;
  	exp->helper = nf_conntrack_helper_q931;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1651
  	if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1652
  		pr_debug("nf_ct_ras: expect Q.931 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1653
  		nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1654
1655
  	} else
  		ret = -1;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1656
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1657
1658
1659
1660
1661
1662
1663
  
  	/* Ignore rasAddress */
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1664
  static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1665
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1666
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1667
1668
1669
1670
1671
  		       unsigned char **data, InfoRequestResponse *irr)
  {
  	int ret;
  	typeof(set_ras_addr_hook) set_ras_addr;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1672
1673
  	pr_debug("nf_ct_ras: IRR
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1674
1675
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1676
1677
  	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1678
  		ret = set_ras_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1679
1680
1681
1682
1683
1684
  				   &irr->rasAddress, 1);
  		if (ret < 0)
  			return -1;
  	}
  
  	set_sig_addr = rcu_dereference(set_sig_addr_hook);
811927ccf   Patrick McHardy   netfilter: nf_con...
1685
1686
  	if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1687
  		ret = set_sig_addr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  					irr->callSignalAddress.item,
  					irr->callSignalAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1698
  static int process_ras(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1699
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1700
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1701
1702
1703
1704
  		       unsigned char **data, RasMessage *ras)
  {
  	switch (ras->choice) {
  	case eRasMessage_gatekeeperRequest:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1705
  		return process_grq(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1706
1707
  				   &ras->gatekeeperRequest);
  	case eRasMessage_gatekeeperConfirm:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1708
  		return process_gcf(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1709
1710
  				   &ras->gatekeeperConfirm);
  	case eRasMessage_registrationRequest:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1711
  		return process_rrq(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1712
1713
  				   &ras->registrationRequest);
  	case eRasMessage_registrationConfirm:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1714
  		return process_rcf(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1715
1716
  				   &ras->registrationConfirm);
  	case eRasMessage_unregistrationRequest:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1717
  		return process_urq(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1718
1719
  				   &ras->unregistrationRequest);
  	case eRasMessage_admissionRequest:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1720
  		return process_arq(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1721
1722
  				   &ras->admissionRequest);
  	case eRasMessage_admissionConfirm:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1723
  		return process_acf(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1724
1725
  				   &ras->admissionConfirm);
  	case eRasMessage_locationRequest:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1726
  		return process_lrq(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1727
1728
  				   &ras->locationRequest);
  	case eRasMessage_locationConfirm:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1729
  		return process_lcf(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1730
1731
  				   &ras->locationConfirm);
  	case eRasMessage_infoRequestResponse:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1732
  		return process_irr(skb, ct, ctinfo, protoff, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1733
1734
  				   &ras->infoRequestResponse);
  	default:
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1735
1736
  		pr_debug("nf_ct_ras: RAS message %d
  ", ras->choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1737
1738
1739
1740
1741
1742
1743
  		break;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1744
  static int ras_help(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1745
1746
1747
1748
1749
1750
  		    struct nf_conn *ct, enum ip_conntrack_info ctinfo)
  {
  	static RasMessage ras;
  	unsigned char *data;
  	int datalen = 0;
  	int ret;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1751
1752
  	pr_debug("nf_ct_ras: skblen = %u
  ", skb->len);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1753
1754
1755
1756
  
  	spin_lock_bh(&nf_h323_lock);
  
  	/* Get UDP data */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1757
  	data = get_udp_data(skb, protoff, &datalen);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1758
1759
  	if (data == NULL)
  		goto accept;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1760
  	pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1761
  	nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1762
1763
1764
1765
  
  	/* Decode RAS message */
  	ret = DecodeRasMessage(data, datalen, &ras);
  	if (ret < 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1766
1767
1768
1769
  		pr_debug("nf_ct_ras: decoding error: %s
  ",
  			 ret == H323_ERROR_BOUND ?
  			 "out of bound" : "out of range");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1770
1771
1772
1773
  		goto accept;
  	}
  
  	/* Process RAS message */
051966c0c   Patrick McHardy   netfilter: nf_nat...
1774
  	if (process_ras(skb, ct, ctinfo, protoff, &data, &ras) < 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1775
1776
1777
1778
1779
1780
1781
1782
  		goto drop;
  
        accept:
  	spin_unlock_bh(&nf_h323_lock);
  	return NF_ACCEPT;
  
        drop:
  	spin_unlock_bh(&nf_h323_lock);
b20ab9cc6   Pablo Neira Ayuso   netfilter: nf_ct_...
1783
  	nf_ct_helper_log(skb, ct, "cannot process RAS message");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1784
1785
1786
1787
  	return NF_DROP;
  }
  
  /****************************************************************************/
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1788
1789
1790
1791
  static const struct nf_conntrack_expect_policy ras_exp_policy = {
  	.max_expected		= 32,
  	.timeout		= 240,
  };
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1792
1793
1794
1795
  static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
  	{
  		.name			= "RAS",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1796
  		.tuple.src.l3num	= AF_INET,
09640e636   Harvey Harrison   net: replace uses...
1797
  		.tuple.src.u.udp.port	= cpu_to_be16(RAS_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1798
  		.tuple.dst.protonum	= IPPROTO_UDP,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1799
  		.help			= ras_help,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1800
  		.expect_policy		= &ras_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1801
1802
1803
1804
  	},
  	{
  		.name			= "RAS",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1805
  		.tuple.src.l3num	= AF_INET6,
09640e636   Harvey Harrison   net: replace uses...
1806
  		.tuple.src.u.udp.port	= cpu_to_be16(RAS_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1807
  		.tuple.dst.protonum	= IPPROTO_UDP,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1808
  		.help			= ras_help,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1809
  		.expect_policy		= &ras_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1810
1811
  	},
  };
d53e3fc39   Liping Zhang   netfilter: use nf...
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
  static int __init h323_helper_init(void)
  {
  	int ret;
  
  	ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245);
  	if (ret < 0)
  		return ret;
  	ret = nf_conntrack_helpers_register(nf_conntrack_helper_q931,
  					ARRAY_SIZE(nf_conntrack_helper_q931));
  	if (ret < 0)
  		goto err1;
  	ret = nf_conntrack_helpers_register(nf_conntrack_helper_ras,
  					ARRAY_SIZE(nf_conntrack_helper_ras));
  	if (ret < 0)
  		goto err2;
  
  	return 0;
  err2:
  	nf_conntrack_helpers_unregister(nf_conntrack_helper_q931,
  					ARRAY_SIZE(nf_conntrack_helper_q931));
  err1:
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
  	return ret;
  }
  
  static void __exit h323_helper_exit(void)
  {
  	nf_conntrack_helpers_unregister(nf_conntrack_helper_ras,
  					ARRAY_SIZE(nf_conntrack_helper_ras));
  	nf_conntrack_helpers_unregister(nf_conntrack_helper_q931,
  					ARRAY_SIZE(nf_conntrack_helper_q931));
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
  }
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1845
1846
1847
  /****************************************************************************/
  static void __exit nf_conntrack_h323_fini(void)
  {
d53e3fc39   Liping Zhang   netfilter: use nf...
1848
  	h323_helper_exit();
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1849
  	kfree(h323_buffer);
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1850
1851
  	pr_debug("nf_ct_h323: fini
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1852
1853
1854
1855
1856
1857
  }
  
  /****************************************************************************/
  static int __init nf_conntrack_h323_init(void)
  {
  	int ret;
dcf67740f   Florian Westphal   netfilter: helper...
1858
  	NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_h323_master));
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1859
1860
1861
  	h323_buffer = kmalloc(65536, GFP_KERNEL);
  	if (!h323_buffer)
  		return -ENOMEM;
d53e3fc39   Liping Zhang   netfilter: use nf...
1862
  	ret = h323_helper_init();
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1863
1864
  	if (ret < 0)
  		goto err1;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1865
1866
  	pr_debug("nf_ct_h323: init success
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1867
  	return 0;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1868
  err1:
8a548868d   Patrick McHardy   netfilter: nf_con...
1869
  	kfree(h323_buffer);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
  	return ret;
  }
  
  /****************************************************************************/
  module_init(nf_conntrack_h323_init);
  module_exit(nf_conntrack_h323_fini);
  
  EXPORT_SYMBOL_GPL(get_h225_addr);
  EXPORT_SYMBOL_GPL(set_h245_addr_hook);
  EXPORT_SYMBOL_GPL(set_h225_addr_hook);
  EXPORT_SYMBOL_GPL(set_sig_addr_hook);
  EXPORT_SYMBOL_GPL(set_ras_addr_hook);
  EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
  EXPORT_SYMBOL_GPL(nat_t120_hook);
  EXPORT_SYMBOL_GPL(nat_h245_hook);
  EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
  EXPORT_SYMBOL_GPL(nat_q931_hook);
  
  MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
  MODULE_DESCRIPTION("H.323 connection tracking helper");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("ip_conntrack_h323");
be3eed2e9   Pablo Neira Ayuso   netfilter: nf_ct_...
1892
1893
1894
  MODULE_ALIAS_NFCT_HELPER("RAS");
  MODULE_ALIAS_NFCT_HELPER("Q.931");
  MODULE_ALIAS_NFCT_HELPER("H.245");