Blame view

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

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

3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1129
1130
  	pr_debug("nf_ct_q931: skblen = %u
  ", skb->len);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1131
1132
1133
1134
  
  	spin_lock_bh(&nf_h323_lock);
  
  	/* Process each TPKT */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1135
  	while (get_tpkt_data(skb, protoff, ct, ctinfo,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1136
  			     &data, &datalen, &dataoff)) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1137
  		pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1138
  		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1139
1140
1141
1142
  
  		/* Decode Q.931 signal */
  		ret = DecodeQ931(data, datalen, &q931);
  		if (ret < 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1143
1144
1145
1146
  			pr_debug("nf_ct_q931: decoding error: %s
  ",
  				 ret == H323_ERROR_BOUND ?
  				 "out of bound" : "out of range");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1147
1148
1149
1150
1151
  			/* We don't drop when decoding error */
  			break;
  		}
  
  		/* Process Q.931 signal */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1152
  		if (process_q931(skb, ct, ctinfo, &data, dataoff, &q931) < 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1153
1154
1155
1156
1157
1158
1159
1160
1161
  			goto drop;
  	}
  
  	spin_unlock_bh(&nf_h323_lock);
  	return NF_ACCEPT;
  
        drop:
  	spin_unlock_bh(&nf_h323_lock);
  	if (net_ratelimit())
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
1162
1163
  		pr_info("nf_ct_q931: packet dropped
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1164
1165
1166
1167
  	return NF_DROP;
  }
  
  /****************************************************************************/
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1168
1169
1170
1171
1172
  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...
1173
1174
1175
1176
  static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
  	{
  		.name			= "Q.931",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1177
  		.tuple.src.l3num	= AF_INET,
09640e636   Harvey Harrison   net: replace uses...
1178
  		.tuple.src.u.tcp.port	= cpu_to_be16(Q931_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1179
  		.tuple.dst.protonum	= IPPROTO_TCP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1180
1181
  		.help			= q931_help,
  		.expect_policy		= &q931_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1182
1183
1184
1185
  	},
  	{
  		.name			= "Q.931",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1186
  		.tuple.src.l3num	= AF_INET6,
09640e636   Harvey Harrison   net: replace uses...
1187
  		.tuple.src.u.tcp.port	= cpu_to_be16(Q931_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1188
  		.tuple.dst.protonum	= IPPROTO_TCP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1189
1190
  		.help			= q931_help,
  		.expect_policy		= &q931_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1191
1192
1193
1194
  	},
  };
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1195
  static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1196
1197
  				   int *datalen)
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
1198
1199
  	const struct udphdr *uh;
  	struct udphdr _uh;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1200
  	int dataoff;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1201
  	uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1202
1203
1204
  	if (uh == NULL)
  		return NULL;
  	dataoff = protoff + sizeof(_uh);
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1205
  	if (dataoff >= skb->len)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1206
  		return NULL;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1207
1208
  	*datalen = skb->len - dataoff;
  	return skb_header_pointer(skb, dataoff, *datalen, h323_buffer);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1209
1210
1211
1212
  }
  
  /****************************************************************************/
  static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1213
  					       union nf_inet_addr *addr,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1214
1215
  					       __be16 port)
  {
84541cc13   Alexey Dobriyan   netfilter: netns ...
1216
  	struct net *net = nf_ct_net(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1217
1218
1219
1220
1221
1222
1223
1224
  	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...
1225
  	exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
  	if (exp && exp->master == ct)
  		return exp;
  	return NULL;
  }
  
  /****************************************************************************/
  static int set_expect_timeout(struct nf_conntrack_expect *exp,
  			      unsigned timeout)
  {
  	if (!exp || !del_timer(&exp->timeout))
  		return 0;
  
  	exp->timeout.expires = jiffies + timeout * HZ;
  	add_timer(&exp->timeout);
  
  	return 1;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1245
  static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1246
1247
1248
1249
1250
1251
1252
1253
1254
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data,
  		       TransportAddress *taddr, int count)
  {
  	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	int i;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1255
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1256
1257
1258
1259
1260
1261
1262
  	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 ...
1263
  			   sizeof(addr)) == 0 && port != 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1264
1265
1266
1267
1268
1269
1270
  			break;
  	}
  
  	if (i >= count)		/* Not found */
  		return 0;
  
  	/* Create expect for Q.931 */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1271
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1272
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1273
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1274
1275
1276
1277
  			  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...
1278
1279
1280
1281
1282
  	exp->helper = nf_conntrack_helper_q931;
  	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
  
  	nat_q931 = rcu_dereference(nat_q931_hook);
  	if (nat_q931 && ct->status & IPS_NAT_MASK) {	/* Need NAT */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1283
  		ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1284
  	} else {		/* Conntrack only */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1285
  		if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1286
  			pr_debug("nf_ct_ras: expect Q.931 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1287
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1288
1289
1290
1291
1292
1293
  
  			/* Save port for looking up expect in processing RCF */
  			info->sig_port[dir] = port;
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1294
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1295
1296
1297
1298
1299
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1300
  static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1301
1302
1303
1304
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, GatekeeperRequest *grq)
  {
  	typeof(set_ras_addr_hook) set_ras_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1305
1306
  	pr_debug("nf_ct_ras: GRQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1307
1308
1309
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
  	if (set_ras_addr && ct->status & IPS_NAT_MASK)	/* NATed */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1310
  		return set_ras_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1311
1312
1313
1314
1315
  				    &grq->rasAddress, 1);
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1316
  static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1317
1318
1319
1320
1321
1322
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, GatekeeperConfirm *gcf)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1323
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1324
  	struct nf_conntrack_expect *exp;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1325
1326
  	pr_debug("nf_ct_ras: GCF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  
  	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...
1341
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1342
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1343
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1344
1345
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_UDP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1346
  	exp->helper = nf_conntrack_helper_ras;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1347
  	if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1348
  		pr_debug("nf_ct_ras: expect RAS ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1349
  		nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1350
1351
  	} else
  		ret = -1;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1352
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1353
1354
1355
1356
1357
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1358
  static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1359
1360
1361
1362
1363
1364
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, RegistrationRequest *rrq)
  {
  	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  	int ret;
  	typeof(set_ras_addr_hook) set_ras_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1365
1366
  	pr_debug("nf_ct_ras: RRQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1367

3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1368
  	ret = expect_q931(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1369
1370
1371
1372
1373
1374
1375
  			  rrq->callSignalAddress.item,
  			  rrq->callSignalAddress.count);
  	if (ret < 0)
  		return -1;
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
  	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1376
  		ret = set_ras_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1377
1378
1379
1380
1381
1382
1383
  				   rrq->rasAddress.item,
  				   rrq->rasAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (rrq->options & eRegistrationRequest_timeToLive) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1384
1385
  		pr_debug("nf_ct_ras: RRQ TTL = %u seconds
  ", rrq->timeToLive);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1386
1387
1388
1389
1390
1391
1392
1393
  		info->timeout = rrq->timeToLive;
  	} else
  		info->timeout = default_rrq_ttl;
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1394
  static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1395
1396
1397
1398
1399
1400
1401
1402
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, RegistrationConfirm *rcf)
  {
  	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  	int dir = CTINFO2DIR(ctinfo);
  	int ret;
  	struct nf_conntrack_expect *exp;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1403
1404
  	pr_debug("nf_ct_ras: RCF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1405
1406
1407
  
  	set_sig_addr = rcu_dereference(set_sig_addr_hook);
  	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1408
  		ret = set_sig_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1409
1410
1411
1412
1413
1414
1415
  					rcf->callSignalAddress.item,
  					rcf->callSignalAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (rcf->options & eRegistrationConfirm_timeToLive) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1416
1417
  		pr_debug("nf_ct_ras: RCF TTL = %u seconds
  ", rcf->timeToLive);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1418
1419
1420
1421
  		info->timeout = rcf->timeToLive;
  	}
  
  	if (info->timeout > 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1422
1423
1424
  		pr_debug("nf_ct_ras: set RAS connection timeout to "
  			 "%u seconds
  ", info->timeout);
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1425
  		nf_ct_refresh(ct, skb, info->timeout * HZ);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1426
1427
  
  		/* Set expect timeout */
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
1428
  		spin_lock_bh(&nf_conntrack_lock);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1429
1430
1431
  		exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
  				  info->sig_port[!dir]);
  		if (exp) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1432
1433
1434
  			pr_debug("nf_ct_ras: set Q.931 expect "
  				 "timeout to %u seconds for",
  				 info->timeout);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1435
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1436
1437
  			set_expect_timeout(exp, info->timeout);
  		}
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
1438
  		spin_unlock_bh(&nf_conntrack_lock);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1439
1440
1441
1442
1443
1444
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1445
  static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1446
1447
1448
1449
1450
1451
1452
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, UnregistrationRequest *urq)
  {
  	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  	int dir = CTINFO2DIR(ctinfo);
  	int ret;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1453
1454
  	pr_debug("nf_ct_ras: URQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1455
1456
1457
  
  	set_sig_addr = rcu_dereference(set_sig_addr_hook);
  	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1458
  		ret = set_sig_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
  				   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...
1471
  	nf_ct_refresh(ct, skb, 30 * HZ);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1472
1473
1474
1475
1476
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1477
  static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1478
1479
1480
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, AdmissionRequest *arq)
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
1481
  	const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1482
1483
  	int dir = CTINFO2DIR(ctinfo);
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1484
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1485
  	typeof(set_h225_addr_hook) set_h225_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1486
1487
  	pr_debug("nf_ct_ras: ARQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1488
1489
1490
1491
  
  	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 ...
1492
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1493
1494
1495
1496
  	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
  	    port == info->sig_port[dir] &&
  	    set_h225_addr && ct->status & IPS_NAT_MASK) {
  		/* Answering ARQ */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1497
  		return set_h225_addr(skb, data, 0,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1498
1499
1500
1501
1502
1503
1504
  				     &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 ...
1505
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1506
1507
1508
  	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
  	    set_h225_addr && ct->status & IPS_NAT_MASK) {
  		/* Calling ARQ */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1509
  		return set_h225_addr(skb, data, 0,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1510
1511
1512
1513
1514
1515
1516
1517
1518
  				     &arq->srcCallSignalAddress,
  				     &ct->tuplehash[!dir].tuple.dst.u3,
  				     port);
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1519
  static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1520
1521
1522
1523
1524
1525
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, AdmissionConfirm *acf)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1526
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1527
1528
  	struct nf_conntrack_expect *exp;
  	typeof(set_sig_addr_hook) set_sig_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1529
1530
  	pr_debug("nf_ct_ras: ACF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1531
1532
1533
1534
1535
1536
1537
1538
1539
  
  	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);
  		if (set_sig_addr && ct->status & IPS_NAT_MASK)
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1540
  			return set_sig_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1541
1542
1543
1544
1545
  					    &acf->destCallSignalAddress, 1);
  		return 0;
  	}
  
  	/* Need new expect */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1546
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1547
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1548
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1549
1550
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1551
1552
  	exp->flags = NF_CT_EXPECT_PERMANENT;
  	exp->helper = nf_conntrack_helper_q931;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1553
  	if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1554
  		pr_debug("nf_ct_ras: expect Q.931 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1555
  		nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1556
1557
  	} else
  		ret = -1;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1558
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1559
1560
1561
1562
1563
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1564
  static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1565
1566
1567
1568
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, LocationRequest *lrq)
  {
  	typeof(set_ras_addr_hook) set_ras_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1569
1570
  	pr_debug("nf_ct_ras: LRQ
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1571
1572
1573
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
  	if (set_ras_addr && ct->status & IPS_NAT_MASK)
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1574
  		return set_ras_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1575
1576
1577
1578
1579
  				    &lrq->replyAddress, 1);
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1580
  static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1581
1582
1583
1584
1585
1586
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, LocationConfirm *lcf)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
1587
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1588
  	struct nf_conntrack_expect *exp;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1589
1590
  	pr_debug("nf_ct_ras: LCF
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1591
1592
1593
1594
1595
1596
  
  	if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
  			   &addr, &port))
  		return 0;
  
  	/* Need new expect for call signal */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1597
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1598
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
1599
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1600
1601
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1602
1603
  	exp->flags = NF_CT_EXPECT_PERMANENT;
  	exp->helper = nf_conntrack_helper_q931;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1604
  	if (nf_ct_expect_related(exp) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1605
  		pr_debug("nf_ct_ras: expect Q.931 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1606
  		nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1607
1608
  	} else
  		ret = -1;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
1609
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1610
1611
1612
1613
1614
1615
1616
  
  	/* Ignore rasAddress */
  
  	return ret;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1617
  static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1618
1619
1620
1621
1622
1623
  		       enum ip_conntrack_info ctinfo,
  		       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...
1624
1625
  	pr_debug("nf_ct_ras: IRR
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1626
1627
1628
  
  	set_ras_addr = rcu_dereference(set_ras_addr_hook);
  	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1629
  		ret = set_ras_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1630
1631
1632
1633
1634
1635
1636
  				   &irr->rasAddress, 1);
  		if (ret < 0)
  			return -1;
  	}
  
  	set_sig_addr = rcu_dereference(set_sig_addr_hook);
  	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1637
  		ret = set_sig_addr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
  					irr->callSignalAddress.item,
  					irr->callSignalAddress.count);
  		if (ret < 0)
  			return -1;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1648
  static int process_ras(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1649
1650
1651
1652
1653
  		       enum ip_conntrack_info ctinfo,
  		       unsigned char **data, RasMessage *ras)
  {
  	switch (ras->choice) {
  	case eRasMessage_gatekeeperRequest:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1654
  		return process_grq(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1655
1656
  				   &ras->gatekeeperRequest);
  	case eRasMessage_gatekeeperConfirm:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1657
  		return process_gcf(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1658
1659
  				   &ras->gatekeeperConfirm);
  	case eRasMessage_registrationRequest:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1660
  		return process_rrq(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1661
1662
  				   &ras->registrationRequest);
  	case eRasMessage_registrationConfirm:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1663
  		return process_rcf(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1664
1665
  				   &ras->registrationConfirm);
  	case eRasMessage_unregistrationRequest:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1666
  		return process_urq(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1667
1668
  				   &ras->unregistrationRequest);
  	case eRasMessage_admissionRequest:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1669
  		return process_arq(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1670
1671
  				   &ras->admissionRequest);
  	case eRasMessage_admissionConfirm:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1672
  		return process_acf(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1673
1674
  				   &ras->admissionConfirm);
  	case eRasMessage_locationRequest:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1675
  		return process_lrq(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1676
1677
  				   &ras->locationRequest);
  	case eRasMessage_locationConfirm:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1678
  		return process_lcf(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1679
1680
  				   &ras->locationConfirm);
  	case eRasMessage_infoRequestResponse:
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1681
  		return process_irr(skb, ct, ctinfo, data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1682
1683
  				   &ras->infoRequestResponse);
  	default:
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1684
1685
  		pr_debug("nf_ct_ras: RAS message %d
  ", ras->choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1686
1687
1688
1689
1690
1691
1692
  		break;
  	}
  
  	return 0;
  }
  
  /****************************************************************************/
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1693
  static int ras_help(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1694
1695
1696
1697
1698
1699
  		    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...
1700
1701
  	pr_debug("nf_ct_ras: skblen = %u
  ", skb->len);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1702
1703
1704
1705
  
  	spin_lock_bh(&nf_h323_lock);
  
  	/* Get UDP data */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1706
  	data = get_udp_data(skb, protoff, &datalen);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1707
1708
  	if (data == NULL)
  		goto accept;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1709
  	pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
1710
  	nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1711
1712
1713
1714
  
  	/* Decode RAS message */
  	ret = DecodeRasMessage(data, datalen, &ras);
  	if (ret < 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1715
1716
1717
1718
  		pr_debug("nf_ct_ras: decoding error: %s
  ",
  			 ret == H323_ERROR_BOUND ?
  			 "out of bound" : "out of range");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1719
1720
1721
1722
  		goto accept;
  	}
  
  	/* Process RAS message */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1723
  	if (process_ras(skb, ct, ctinfo, &data, &ras) < 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1724
1725
1726
1727
1728
1729
1730
1731
1732
  		goto drop;
  
        accept:
  	spin_unlock_bh(&nf_h323_lock);
  	return NF_ACCEPT;
  
        drop:
  	spin_unlock_bh(&nf_h323_lock);
  	if (net_ratelimit())
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
1733
1734
  		pr_info("nf_ct_ras: packet dropped
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1735
1736
1737
1738
  	return NF_DROP;
  }
  
  /****************************************************************************/
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1739
1740
1741
1742
  static const struct nf_conntrack_expect_policy ras_exp_policy = {
  	.max_expected		= 32,
  	.timeout		= 240,
  };
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1743
1744
1745
1746
  static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
  	{
  		.name			= "RAS",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1747
  		.tuple.src.l3num	= AF_INET,
09640e636   Harvey Harrison   net: replace uses...
1748
  		.tuple.src.u.udp.port	= cpu_to_be16(RAS_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1749
  		.tuple.dst.protonum	= IPPROTO_UDP,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1750
  		.help			= ras_help,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1751
  		.expect_policy		= &ras_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1752
1753
1754
1755
  	},
  	{
  		.name			= "RAS",
  		.me			= THIS_MODULE,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1756
  		.tuple.src.l3num	= AF_INET6,
09640e636   Harvey Harrison   net: replace uses...
1757
  		.tuple.src.u.udp.port	= cpu_to_be16(RAS_PORT),
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1758
  		.tuple.dst.protonum	= IPPROTO_UDP,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1759
  		.help			= ras_help,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
1760
  		.expect_policy		= &ras_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
  	},
  };
  
  /****************************************************************************/
  static void __exit nf_conntrack_h323_fini(void)
  {
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[1]);
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
a56b8f815   Patrick McHardy   netfilter: nf_con...
1771
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1772
  	kfree(h323_buffer);
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1773
1774
  	pr_debug("nf_ct_h323: fini
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
  }
  
  /****************************************************************************/
  static int __init nf_conntrack_h323_init(void)
  {
  	int ret;
  
  	h323_buffer = kmalloc(65536, GFP_KERNEL);
  	if (!h323_buffer)
  		return -ENOMEM;
a56b8f815   Patrick McHardy   netfilter: nf_con...
1785
  	ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1786
1787
  	if (ret < 0)
  		goto err1;
a56b8f815   Patrick McHardy   netfilter: nf_con...
1788
  	ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1789
1790
  	if (ret < 0)
  		goto err2;
a56b8f815   Patrick McHardy   netfilter: nf_con...
1791
  	ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1792
1793
  	if (ret < 0)
  		goto err3;
a56b8f815   Patrick McHardy   netfilter: nf_con...
1794
  	ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1795
1796
  	if (ret < 0)
  		goto err4;
a56b8f815   Patrick McHardy   netfilter: nf_con...
1797
1798
1799
  	ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
  	if (ret < 0)
  		goto err5;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1800
1801
  	pr_debug("nf_ct_h323: init success
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1802
  	return 0;
a56b8f815   Patrick McHardy   netfilter: nf_con...
1803
  err5:
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1804
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
a56b8f815   Patrick McHardy   netfilter: nf_con...
1805
  err4:
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1806
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
a56b8f815   Patrick McHardy   netfilter: nf_con...
1807
  err3:
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1808
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
a56b8f815   Patrick McHardy   netfilter: nf_con...
1809
1810
  err2:
  	nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1811
  err1:
8a548868d   Patrick McHardy   netfilter: nf_con...
1812
  	kfree(h323_buffer);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
  	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");
4dc06f963   Pablo Neira Ayuso   netfilter: nf_con...
1835
  MODULE_ALIAS_NFCT_HELPER("h323");