Blame view

net/netfilter/nf_conntrack_h323_main.c 50.9 KB
f361c4dc5   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
2
3
4
5
  /*
   * H.323 connection tracking helper
   *
   * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
f229f6ce4   Patrick McHardy   netfilter: add my...
6
   * Copyright (c) 2006-2012 Patrick McHardy <kaber@trash.net>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
7
   *
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
8
   * Based on the 'brute force' H.323 connection tracking module by
fe03d4745   Jozsef Kadlecsik   Update my email a...
9
   * Jozsef Kadlecsik <kadlec@netfilter.org>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
10
11
12
13
14
15
16
17
18
19
   *
   * 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
  #include <linux/udp.h>
  #include <linux/tcp.h>
  #include <linux/skbuff.h>
  #include <net/route.h>
  #include <net/ip6_route.h>
3f87c08c6   Pablo Neira Ayuso   netfilter: move r...
26
  #include <linux/netfilter_ipv6.h>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
27
28
29
30
31
32
33
  
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
  #include <net/netfilter/nf_conntrack_tuple.h>
  #include <net/netfilter/nf_conntrack_expect.h>
  #include <net/netfilter/nf_conntrack_ecache.h>
  #include <net/netfilter/nf_conntrack_helper.h>
5d0aa2ccd   Patrick McHardy   netfilter: nf_con...
34
  #include <net/netfilter/nf_conntrack_zones.h>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
35
  #include <linux/netfilter/nf_conntrack_h323.h>
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
36
37
38
39
40
41
42
43
  /* Parameters */
  static unsigned int default_rrq_ttl __read_mostly = 300;
  module_param(default_rrq_ttl, uint, 0600);
  MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
  
  static int gkrouted_only __read_mostly = 1;
  module_param(gkrouted_only, int, 0600);
  MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
eb9399220   Rusty Russell   module_param: mak...
44
  static bool callforward_filter __read_mostly = true;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
45
46
  module_param(callforward_filter, bool, 0600);
  MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
47
  				     "if both endpoints are on different sides "
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
48
49
50
  				     "(determined by routing information)");
  
  /* Hooks for NAT */
051966c0c   Patrick McHardy   netfilter: nf_nat...
51
  int (*set_h245_addr_hook) (struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
52
53
  			   unsigned char **data, int dataoff,
  			   H245_TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
54
  			   union nf_inet_addr *addr, __be16 port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
55
  			   __read_mostly;
051966c0c   Patrick McHardy   netfilter: nf_nat...
56
  int (*set_h225_addr_hook) (struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
57
58
  			   unsigned char **data, int dataoff,
  			   TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
59
  			   union nf_inet_addr *addr, __be16 port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
60
  			   __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
61
  int (*set_sig_addr_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
62
63
  			  struct nf_conn *ct,
  			  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
64
  			  unsigned int protoff, unsigned char **data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
65
  			  TransportAddress *taddr, int count) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
66
  int (*set_ras_addr_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
67
68
  			  struct nf_conn *ct,
  			  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
69
  			  unsigned int protoff, unsigned char **data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
70
  			  TransportAddress *taddr, int count) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
71
  int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
72
73
  			  struct nf_conn *ct,
  			  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
74
  			  unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
75
76
77
78
79
  			  unsigned char **data, int dataoff,
  			  H245_TransportAddress *taddr,
  			  __be16 port, __be16 rtp_port,
  			  struct nf_conntrack_expect *rtp_exp,
  			  struct nf_conntrack_expect *rtcp_exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
80
  int (*nat_t120_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
81
82
  		      struct nf_conn *ct,
  		      enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
83
  		      unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
84
85
86
  		      unsigned char **data, int dataoff,
  		      H245_TransportAddress *taddr, __be16 port,
  		      struct nf_conntrack_expect *exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
87
  int (*nat_h245_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
88
89
  		      struct nf_conn *ct,
  		      enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
90
  		      unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
91
92
93
  		      unsigned char **data, int dataoff,
  		      TransportAddress *taddr, __be16 port,
  		      struct nf_conntrack_expect *exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
94
  int (*nat_callforwarding_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
95
96
  				struct nf_conn *ct,
  				enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
97
  				unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
98
99
100
  				unsigned char **data, int dataoff,
  				TransportAddress *taddr, __be16 port,
  				struct nf_conntrack_expect *exp) __read_mostly;
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
101
  int (*nat_q931_hook) (struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
102
103
  		      struct nf_conn *ct,
  		      enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
104
  		      unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
105
106
107
108
109
110
111
112
113
114
  		      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...
115
  static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
116
117
118
  			 struct nf_conn *ct, enum ip_conntrack_info ctinfo,
  			 unsigned char **data, int *datalen, int *dataoff)
  {
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
119
  	struct nf_ct_h323_master *info = nfct_help_data(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
120
  	int dir = CTINFO2DIR(ctinfo);
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
121
122
  	const struct tcphdr *th;
  	struct tcphdr _tcph;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
123
124
125
126
127
128
129
  	int tcpdatalen;
  	int tcpdataoff;
  	unsigned char *tpkt;
  	int tpktlen;
  	int tpktoff;
  
  	/* Get TCP header */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
130
  	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
131
132
133
134
135
136
137
  	if (th == NULL)
  		return 0;
  
  	/* Get TCP data offset */
  	tcpdataoff = protoff + th->doff * 4;
  
  	/* Get TCP data length */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
138
  	tcpdatalen = skb->len - tcpdataoff;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
139
140
141
142
143
  	if (tcpdatalen <= 0)	/* No TCP data */
  		goto clear_out;
  
  	if (*data == NULL) {	/* first TPKT */
  		/* Get first TPKT pointer */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
144
  		tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
145
146
147
148
149
150
151
  					  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...
152
153
154
155
  				pr_debug("nf_ct_h323: previous packet "
  					 "indicated separate TPKT data of %hu "
  					 "bytes
  ", info->tpkt_len[dir]);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
156
157
158
159
160
161
162
163
164
165
  				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...
166
167
  				pr_debug("nf_ct_h323: fragmented TPKT
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  				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...
194
195
196
197
  			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...
198
199
200
  			info->tpkt_len[dir] = tpktlen - 4;
  			return 0;
  		}
e772c349a   Patrick McHardy   netfilter: nf_ct_...
201
202
  		pr_debug("nf_ct_h323: incomplete TPKT (fragmented?)
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  		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...
220
  static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
221
  			 H245_TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
222
  			 union nf_inet_addr *addr, __be16 *port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
223
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
224
  	const unsigned char *p;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
225
226
227
228
229
230
231
  	int len;
  
  	if (taddr->choice != eH245_TransportAddress_unicastAddress)
  		return 0;
  
  	switch (taddr->unicastAddress.choice) {
  	case eUnicastAddress_iPAddress:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
232
  		if (nf_ct_l3num(ct) != AF_INET)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
233
234
235
236
237
  			return 0;
  		p = data + taddr->unicastAddress.iPAddress.network;
  		len = 4;
  		break;
  	case eUnicastAddress_iP6Address:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
238
  		if (nf_ct_l3num(ct) != AF_INET6)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
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
  			   enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
255
  			   unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
256
257
258
259
260
261
262
  			   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...
263
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
264
265
266
267
268
269
270
271
272
273
274
  	struct nf_conntrack_expect *rtp_exp;
  	struct nf_conntrack_expect *rtcp_exp;
  	typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
  
  	/* Read RTP or RTCP address */
  	if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
  	    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
  	    port == 0)
  		return 0;
  
  	/* RTP port is even */
d109e9af6   Pablo Neira Ayuso   netfilter: nf_ct_...
275
276
  	rtp_port = port & ~htons(1);
  	rtcp_port = port | htons(1);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
277
278
  
  	/* 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
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  		   (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
300
  		   nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
301
302
  		   ct->status & IPS_NAT_MASK) {
  		/* NAT needed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
303
  		ret = nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
304
305
  				   taddr, port, rtp_port, rtp_exp, rtcp_exp);
  	} else {		/* Conntrack only */
3c00fb0bf   xiao ruizhu   netfilter: nf_con...
306
307
  		if (nf_ct_expect_related(rtp_exp, 0) == 0) {
  			if (nf_ct_expect_related(rtcp_exp, 0) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
308
  				pr_debug("nf_ct_h323: expect RTP ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
309
  				nf_ct_dump_tuple(&rtp_exp->tuple);
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
310
  				pr_debug("nf_ct_h323: expect RTCP ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
311
  				nf_ct_dump_tuple(&rtcp_exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
312
  			} else {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
313
  				nf_ct_unexpect_related(rtp_exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
314
315
316
317
318
  				ret = -1;
  			}
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
319
320
  	nf_ct_expect_put(rtp_exp);
  	nf_ct_expect_put(rtcp_exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
321
322
323
  
  	return ret;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
324
  static int expect_t120(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
325
326
  		       struct nf_conn *ct,
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
327
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
328
329
330
331
332
333
  		       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
  	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple channels */
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
  		   &ct->tuplehash[!dir].tuple.dst.u3,
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  	    (nat_t120 = rcu_dereference(nat_t120_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
357
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
358
359
  	    ct->status & IPS_NAT_MASK) {
  		/* NAT needed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
360
  		ret = nat_t120(skb, ct, ctinfo, protoff, data, dataoff, taddr,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
361
362
  			       port, exp);
  	} else {		/* Conntrack only */
3c00fb0bf   xiao ruizhu   netfilter: nf_con...
363
  		if (nf_ct_expect_related(exp, 0) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
364
  			pr_debug("nf_ct_h323: expect T.120 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
365
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
366
367
368
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
369
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
370
371
372
  
  	return ret;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
373
  static int process_h245_channel(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
374
375
  				struct nf_conn *ct,
  				enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
376
  				unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
377
378
379
380
381
382
383
  				unsigned char **data, int dataoff,
  				H2250LogicalChannelParameters *channel)
  {
  	int ret;
  
  	if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
  		/* RTP */
051966c0c   Patrick McHardy   netfilter: nf_nat...
384
  		ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, 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 */
051966c0c   Patrick McHardy   netfilter: nf_nat...
393
  		ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
394
395
396
397
398
399
400
  				      &channel->mediaControlChannel);
  		if (ret < 0)
  			return -1;
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
401
  static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
402
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
403
  		       unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
404
405
406
407
  		       unsigned char **data, int dataoff,
  		       OpenLogicalChannel *olc)
  {
  	int ret;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
408
409
  	pr_debug("nf_ct_h323: OpenLogicalChannel
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
410
411
412
413
  
  	if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
  	    eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
  	{
051966c0c   Patrick McHardy   netfilter: nf_nat...
414
415
  		ret = process_h245_channel(skb, ct, ctinfo,
  					   protoff, 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 =
051966c0c   Patrick McHardy   netfilter: nf_nat...
433
434
  		    process_h245_channel(skb, ct, ctinfo,
  					 protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
  					 &olc->
  					 reverseLogicalChannelParameters.
  					 multiplexParameters.
  					 h2250LogicalChannelParameters);
  		if (ret < 0)
  			return -1;
  	}
  
  	if ((olc->options & eOpenLogicalChannel_separateStack) &&
  	    olc->forwardLogicalChannelParameters.dataType.choice ==
  	    eDataType_data &&
  	    olc->forwardLogicalChannelParameters.dataType.data.application.
  	    choice == eDataApplicationCapability_application_t120 &&
  	    olc->forwardLogicalChannelParameters.dataType.data.application.
  	    t120.choice == eDataProtocolCapability_separateLANStack &&
  	    olc->separateStack.networkAddress.choice ==
  	    eNetworkAccessParameters_networkAddress_localAreaAddress) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
452
  		ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
453
454
455
456
457
458
459
460
  				  &olc->separateStack.networkAddress.
  				  localAreaAddress);
  		if (ret < 0)
  			return -1;
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
461
  static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
462
  			enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
463
  			unsigned int protoff, unsigned char **data, int dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
464
465
466
467
  			OpenLogicalChannelAck *olca)
  {
  	H2250LogicalChannelAckParameters *ack;
  	int ret;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
468
469
  	pr_debug("nf_ct_h323: OpenLogicalChannelAck
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
470
471
472
473
474
475
476
477
478
  
  	if ((olca->options &
  	     eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
  	    (olca->reverseLogicalChannelParameters.options &
  	     eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
  	    && (olca->reverseLogicalChannelParameters.multiplexParameters.
  		choice ==
  		eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
  	{
051966c0c   Patrick McHardy   netfilter: nf_nat...
479
480
  		ret = process_h245_channel(skb, ct, ctinfo,
  					   protoff, 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 */
051966c0c   Patrick McHardy   netfilter: nf_nat...
499
500
  			ret = expect_rtp_rtcp(skb, ct, ctinfo,
  					      protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
501
502
503
504
505
506
507
508
  					      &ack->mediaChannel);
  			if (ret < 0)
  				return -1;
  		}
  
  		if (ack->options &
  		    eH2250LogicalChannelAckParameters_mediaControlChannel) {
  			/* RTCP */
051966c0c   Patrick McHardy   netfilter: nf_nat...
509
510
  			ret = expect_rtp_rtcp(skb, ct, ctinfo,
  					      protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
511
512
513
514
515
  					      &ack->mediaControlChannel);
  			if (ret < 0)
  				return -1;
  		}
  	}
f8f1c08ea   Jing Min Zhao   [NETFILTER]: nf_c...
516
517
518
  	if ((olca->options & eOpenLogicalChannelAck_separateStack) &&
  		olca->separateStack.networkAddress.choice ==
  		eNetworkAccessParameters_networkAddress_localAreaAddress) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
519
  		ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff,
f8f1c08ea   Jing Min Zhao   [NETFILTER]: nf_c...
520
521
522
523
524
  				  &olca->separateStack.networkAddress.
  				  localAreaAddress);
  		if (ret < 0)
  			return -1;
  	}
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
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
  			enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
529
  			unsigned int protoff, unsigned char **data, int dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
530
531
532
533
534
535
  			MultimediaSystemControlMessage *mscm)
  {
  	switch (mscm->choice) {
  	case eMultimediaSystemControlMessage_request:
  		if (mscm->request.choice ==
  		    eRequestMessage_openLogicalChannel) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
536
537
  			return process_olc(skb, ct, ctinfo,
  					   protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
538
539
  					   &mscm->request.openLogicalChannel);
  		}
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
540
541
542
  		pr_debug("nf_ct_h323: H.245 Request %d
  ",
  			 mscm->request.choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
543
544
545
546
  		break;
  	case eMultimediaSystemControlMessage_response:
  		if (mscm->response.choice ==
  		    eResponseMessage_openLogicalChannelAck) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
547
548
  			return process_olca(skb, ct, ctinfo,
  					    protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
549
550
551
  					    &mscm->response.
  					    openLogicalChannelAck);
  		}
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
552
553
554
  		pr_debug("nf_ct_h323: H.245 Response %d
  ",
  			 mscm->response.choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
555
556
  		break;
  	default:
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
557
558
  		pr_debug("nf_ct_h323: H.245 signal %d
  ", mscm->choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
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 */
051966c0c   Patrick McHardy   netfilter: nf_nat...
601
602
  		if (process_h245(skb, ct, ctinfo, protoff,
  				 &data, dataoff, &mscm) < 0)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
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);
b20ab9cc6   Pablo Neira Ayuso   netfilter: nf_ct_...
611
  	nf_ct_helper_log(skb, ct, "cannot process H.245 message");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
612
613
  	return NF_DROP;
  }
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
614
615
616
617
  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...
618
619
620
  static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
  	.name			= "H.245",
  	.me			= THIS_MODULE,
a56b8f815   Patrick McHardy   netfilter: nf_con...
621
  	.tuple.src.l3num	= AF_UNSPEC,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
622
  	.tuple.dst.protonum	= IPPROTO_UDP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
623
624
  	.help			= h245_help,
  	.expect_policy		= &h245_exp_policy,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
625
  };
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
626
627
  int get_h225_addr(struct nf_conn *ct, unsigned char *data,
  		  TransportAddress *taddr,
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
628
  		  union nf_inet_addr *addr, __be16 *port)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
629
  {
905e3e8ec   Jan Engelhardt   [NETFILTER]: nf_c...
630
  	const unsigned char *p;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
631
632
633
634
  	int len;
  
  	switch (taddr->choice) {
  	case eTransportAddress_ipAddress:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
635
  		if (nf_ct_l3num(ct) != AF_INET)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
636
637
638
639
640
  			return 0;
  		p = data + taddr->ipAddress.ip;
  		len = 4;
  		break;
  	case eTransportAddress_ip6Address:
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
641
  		if (nf_ct_l3num(ct) != AF_INET6)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
642
  			return 0;
bb807245e   Jing Min Zhao   [NETFILTER]: nf_c...
643
  		p = data + taddr->ip6Address.ip;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
644
645
646
647
648
649
650
651
652
653
654
655
  		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...
656
  static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
657
  		       enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
658
  		       unsigned int protoff, unsigned char **data, int dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
659
660
661
662
663
  		       TransportAddress *taddr)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
664
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
665
666
667
668
669
670
671
672
673
674
  	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...
675
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
676
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
677
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
678
679
680
  			  &ct->tuplehash[!dir].tuple.src.u3,
  			  &ct->tuplehash[!dir].tuple.dst.u3,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
681
682
683
684
685
686
  	exp->helper = &nf_conntrack_helper_h245;
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
  		   &ct->tuplehash[!dir].tuple.dst.u3,
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  	    (nat_h245 = rcu_dereference(nat_h245_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
687
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
688
689
  	    ct->status & IPS_NAT_MASK) {
  		/* NAT needed */
051966c0c   Patrick McHardy   netfilter: nf_nat...
690
  		ret = nat_h245(skb, ct, ctinfo, protoff, data, dataoff, taddr,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
691
692
  			       port, exp);
  	} else {		/* Conntrack only */
3c00fb0bf   xiao ruizhu   netfilter: nf_con...
693
  		if (nf_ct_expect_related(exp, 0) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
694
  			pr_debug("nf_ct_q931: expect H.245 ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
695
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
696
697
698
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
699
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
700
701
702
703
704
  
  	return ret;
  }
  
  /* If the calling party is on the same side of the forward-to party,
ca9b01473   Varsha Rao   netfilter: nf_con...
705
706
   * we don't need to track the second call
   */
2c7b5d5da   Vasily Averin   netfilter: nf_con...
707
708
  static int callforward_do_filter(struct net *net,
  				 const union nf_inet_addr *src,
76108cea0   Jan Engelhardt   netfilter: Use un...
709
710
  				 const union nf_inet_addr *dst,
  				 u_int8_t family)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
711
  {
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
712
  	int ret = 0;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
713
714
  	switch (family) {
  	case AF_INET: {
5a49d0e04   David S. Miller   netfilter: Use fl...
715
  		struct flowi4 fl1, fl2;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
716
  		struct rtable *rt1, *rt2;
5a49d0e04   David S. Miller   netfilter: Use fl...
717
718
719
720
721
  		memset(&fl1, 0, sizeof(fl1));
  		fl1.daddr = src->ip;
  
  		memset(&fl2, 0, sizeof(fl2));
  		fl2.daddr = dst->ip;
3f87c08c6   Pablo Neira Ayuso   netfilter: move r...
722
723
724
725
  		if (!nf_ip_route(net, (struct dst_entry **)&rt1,
  				 flowi4_to_flowi(&fl1), false)) {
  			if (!nf_ip_route(net, (struct dst_entry **)&rt2,
  					 flowi4_to_flowi(&fl2), false)) {
bbb5823cf   Julian Anastasov   netfilter: nf_con...
726
727
  				if (rt_nexthop(rt1, fl1.daddr) ==
  				    rt_nexthop(rt2, fl2.daddr) &&
d8d1f30b9   Changli Gao   net-next: remove ...
728
  				    rt1->dst.dev  == rt2->dst.dev)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
729
  					ret = 1;
d8d1f30b9   Changli Gao   net-next: remove ...
730
  				dst_release(&rt2->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
731
  			}
d8d1f30b9   Changli Gao   net-next: remove ...
732
  			dst_release(&rt1->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
733
734
735
  		}
  		break;
  	}
b33c448c4   Subash Abhinov Kasiviswanathan   netfilter: nf_con...
736
  #if IS_ENABLED(CONFIG_IPV6)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
737
738
  	case AF_INET6: {
  		struct rt6_info *rt1, *rt2;
3f87c08c6   Pablo Neira Ayuso   netfilter: move r...
739
  		struct flowi6 fl1, fl2;
5a49d0e04   David S. Miller   netfilter: Use fl...
740
  		memset(&fl1, 0, sizeof(fl1));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
741
  		fl1.daddr = src->in6;
5a49d0e04   David S. Miller   netfilter: Use fl...
742
743
  
  		memset(&fl2, 0, sizeof(fl2));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
744
  		fl2.daddr = dst->in6;
b33c448c4   Subash Abhinov Kasiviswanathan   netfilter: nf_con...
745
  		if (!nf_ip6_route(net, (struct dst_entry **)&rt1,
3f87c08c6   Pablo Neira Ayuso   netfilter: move r...
746
  				  flowi6_to_flowi(&fl1), false)) {
b33c448c4   Subash Abhinov Kasiviswanathan   netfilter: nf_con...
747
  			if (!nf_ip6_route(net, (struct dst_entry **)&rt2,
3f87c08c6   Pablo Neira Ayuso   netfilter: move r...
748
  					  flowi6_to_flowi(&fl2), false)) {
2647a9b07   Martin KaFai Lau   ipv6: Remove exte...
749
750
  				if (ipv6_addr_equal(rt6_nexthop(rt1, &fl1.daddr),
  						    rt6_nexthop(rt2, &fl2.daddr)) &&
d8d1f30b9   Changli Gao   net-next: remove ...
751
  				    rt1->dst.dev == rt2->dst.dev)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
752
  					ret = 1;
d8d1f30b9   Changli Gao   net-next: remove ...
753
  				dst_release(&rt2->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
754
  			}
d8d1f30b9   Changli Gao   net-next: remove ...
755
  			dst_release(&rt1->dst);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
756
757
758
759
760
761
762
763
  		}
  		break;
  	}
  #endif
  	}
  	return ret;
  
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
764
  static int expect_callforwarding(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
765
766
  				 struct nf_conn *ct,
  				 enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
767
  				 unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
768
769
770
771
772
773
  				 unsigned char **data, int dataoff,
  				 TransportAddress *taddr)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret = 0;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
774
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
775
  	struct nf_conntrack_expect *exp;
2c7b5d5da   Vasily Averin   netfilter: nf_con...
776
  	struct net *net = nf_ct_net(ct);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
777
778
779
780
781
782
783
  	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,
ca9b01473   Varsha Rao   netfilter: nf_con...
784
785
  	 * we don't need to track the second call
  	 */
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
786
  	if (callforward_filter &&
2c7b5d5da   Vasily Averin   netfilter: nf_con...
787
  	    callforward_do_filter(net, &addr, &ct->tuplehash[!dir].tuple.src.u3,
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
788
  				  nf_ct_l3num(ct))) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
789
790
  		pr_debug("nf_ct_q931: Call Forwarding not tracked
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
791
792
793
794
  		return 0;
  	}
  
  	/* Create expect for the second call leg */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
795
  	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
796
  		return -1;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
797
  	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
798
799
  			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
  			  IPPROTO_TCP, NULL, &port);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
800
801
802
803
804
805
  	exp->helper = nf_conntrack_helper_q931;
  
  	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
  		   &ct->tuplehash[!dir].tuple.dst.u3,
  		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
  	    (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
806
  	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
807
808
  	    ct->status & IPS_NAT_MASK) {
  		/* Need NAT */
051966c0c   Patrick McHardy   netfilter: nf_nat...
809
810
  		ret = nat_callforwarding(skb, ct, ctinfo,
  					 protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
811
812
  					 taddr, port, exp);
  	} else {		/* Conntrack only */
3c00fb0bf   xiao ruizhu   netfilter: nf_con...
813
  		if (nf_ct_expect_related(exp, 0) == 0) {
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
814
  			pr_debug("nf_ct_q931: expect Call Forwarding ");
3c9fba656   Jan Engelhardt   [NETFILTER]: nf_c...
815
  			nf_ct_dump_tuple(&exp->tuple);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
816
817
818
  		} else
  			ret = -1;
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
819
  	nf_ct_expect_put(exp);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
820
821
822
  
  	return ret;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
823
  static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
824
  			 enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
825
  			 unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
826
827
828
829
830
831
832
  			 unsigned char **data, int dataoff,
  			 Setup_UUIE *setup)
  {
  	int dir = CTINFO2DIR(ctinfo);
  	int ret;
  	int i;
  	__be16 port;
643a2c15a   Jan Engelhardt   [NETFILTER]: Intr...
833
  	union nf_inet_addr addr;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
834
  	typeof(set_h225_addr_hook) set_h225_addr;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
835
836
  	pr_debug("nf_ct_q931: Setup
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
837
838
  
  	if (setup->options & eSetup_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
839
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
840
841
842
843
844
845
846
  				  &setup->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	set_h225_addr = rcu_dereference(set_h225_addr_hook);
  	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
847
848
  	    (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
849
  	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
850
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
851
  	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
5b095d989   Harvey Harrison   net: replace %p6 ...
852
853
  		pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu
  ",
38ff4fa49   Harvey Harrison   netfilter: replac...
854
  			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3,
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
855
  			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
051966c0c   Patrick McHardy   netfilter: nf_nat...
856
  		ret = set_h225_addr(skb, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
857
858
859
860
861
862
863
864
  				    &setup->destCallSignalAddress,
  				    &ct->tuplehash[!dir].tuple.src.u3,
  				    ct->tuplehash[!dir].tuple.src.u.tcp.port);
  		if (ret < 0)
  			return -1;
  	}
  
  	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
811927ccf   Patrick McHardy   netfilter: nf_con...
865
866
  	    (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
  	    ct->status & IPS_NAT_MASK &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
867
  	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
868
  			  &addr, &port) &&
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
869
  	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
5b095d989   Harvey Harrison   net: replace %p6 ...
870
871
  		pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu
  ",
38ff4fa49   Harvey Harrison   netfilter: replac...
872
  			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3,
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
873
  			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
051966c0c   Patrick McHardy   netfilter: nf_nat...
874
  		ret = set_h225_addr(skb, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
875
876
877
878
879
880
881
882
883
  				    &setup->sourceCallSignalAddress,
  				    &ct->tuplehash[!dir].tuple.dst.u3,
  				    ct->tuplehash[!dir].tuple.dst.u.tcp.port);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (setup->options & eSetup_UUIE_fastStart) {
  		for (i = 0; i < setup->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
884
885
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
886
887
888
889
890
891
892
893
  					  &setup->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
894
  static int process_callproceeding(struct sk_buff *skb,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
895
896
  				  struct nf_conn *ct,
  				  enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
897
  				  unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
898
899
900
901
902
  				  unsigned char **data, int dataoff,
  				  CallProceeding_UUIE *callproc)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
903
904
  	pr_debug("nf_ct_q931: CallProceeding
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
905
906
  
  	if (callproc->options & eCallProceeding_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
907
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
908
909
910
911
912
913
914
  				  &callproc->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (callproc->options & eCallProceeding_UUIE_fastStart) {
  		for (i = 0; i < callproc->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
915
916
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
917
918
919
920
921
922
923
924
  					  &callproc->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
925
  static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
926
  			   enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
927
  			   unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
928
929
930
931
932
  			   unsigned char **data, int dataoff,
  			   Connect_UUIE *connect)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
933
934
  	pr_debug("nf_ct_q931: Connect
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
935
936
  
  	if (connect->options & eConnect_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
937
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
938
939
940
941
942
943
944
  				  &connect->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (connect->options & eConnect_UUIE_fastStart) {
  		for (i = 0; i < connect->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
945
946
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
947
948
949
950
951
952
953
954
  					  &connect->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
955
  static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
956
  			    enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
957
  			    unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
958
959
960
961
962
  			    unsigned char **data, int dataoff,
  			    Alerting_UUIE *alert)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
963
964
  	pr_debug("nf_ct_q931: Alerting
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
965
966
  
  	if (alert->options & eAlerting_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
967
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
968
969
970
971
972
973
974
  				  &alert->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (alert->options & eAlerting_UUIE_fastStart) {
  		for (i = 0; i < alert->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
975
976
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
977
978
979
980
981
982
983
984
  					  &alert->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
985
  static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
986
  			    enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
987
  			    unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
988
989
990
991
992
  			    unsigned char **data, int dataoff,
  			    Facility_UUIE *facility)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
993
994
  	pr_debug("nf_ct_q931: Facility
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
995
996
997
  
  	if (facility->reason.choice == eFacilityReason_callForwarded) {
  		if (facility->options & eFacility_UUIE_alternativeAddress)
051966c0c   Patrick McHardy   netfilter: nf_nat...
998
999
  			return expect_callforwarding(skb, ct, ctinfo,
  						     protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1000
1001
1002
1003
1004
1005
  						     &facility->
  						     alternativeAddress);
  		return 0;
  	}
  
  	if (facility->options & eFacility_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1006
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1007
1008
1009
1010
1011
1012
1013
  				  &facility->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (facility->options & eFacility_UUIE_fastStart) {
  		for (i = 0; i < facility->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1014
1015
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1016
1017
1018
1019
1020
1021
1022
1023
  					  &facility->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1024
  static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1025
  			    enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1026
  			    unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1027
1028
1029
1030
1031
  			    unsigned char **data, int dataoff,
  			    Progress_UUIE *progress)
  {
  	int ret;
  	int i;
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1032
1033
  	pr_debug("nf_ct_q931: Progress
  ");
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1034
1035
  
  	if (progress->options & eProgress_UUIE_h245Address) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1036
  		ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1037
1038
1039
1040
1041
1042
1043
  				  &progress->h245Address);
  		if (ret < 0)
  			return -1;
  	}
  
  	if (progress->options & eProgress_UUIE_fastStart) {
  		for (i = 0; i < progress->fastStart.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1044
1045
  			ret = process_olc(skb, ct, ctinfo,
  					  protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1046
1047
1048
1049
1050
1051
1052
1053
  					  &progress->fastStart.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1054
  static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1055
  			enum ip_conntrack_info ctinfo,
051966c0c   Patrick McHardy   netfilter: nf_nat...
1056
1057
  			unsigned int protoff, unsigned char **data, int dataoff,
  			Q931 *q931)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1058
1059
1060
1061
1062
1063
1064
  {
  	H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
  	int i;
  	int ret = 0;
  
  	switch (pdu->h323_message_body.choice) {
  	case eH323_UU_PDU_h323_message_body_setup:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1065
  		ret = process_setup(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1066
1067
1068
  				    &pdu->h323_message_body.setup);
  		break;
  	case eH323_UU_PDU_h323_message_body_callProceeding:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1069
1070
  		ret = process_callproceeding(skb, ct, ctinfo,
  					     protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1071
1072
1073
1074
  					     &pdu->h323_message_body.
  					     callProceeding);
  		break;
  	case eH323_UU_PDU_h323_message_body_connect:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1075
  		ret = process_connect(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1076
1077
1078
  				      &pdu->h323_message_body.connect);
  		break;
  	case eH323_UU_PDU_h323_message_body_alerting:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1079
  		ret = process_alerting(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1080
1081
  				       &pdu->h323_message_body.alerting);
  		break;
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1082
  	case eH323_UU_PDU_h323_message_body_facility:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1083
  		ret = process_facility(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1084
1085
1086
  				       &pdu->h323_message_body.facility);
  		break;
  	case eH323_UU_PDU_h323_message_body_progress:
051966c0c   Patrick McHardy   netfilter: nf_nat...
1087
  		ret = process_progress(skb, ct, ctinfo, protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1088
1089
1090
  				       &pdu->h323_message_body.progress);
  		break;
  	default:
0d53778e8   Patrick McHardy   [NETFILTER]: Conv...
1091
1092
1093
  		pr_debug("nf_ct_q931: Q.931 signal %d
  ",
  			 pdu->h323_message_body.choice);
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1094
1095
1096
1097
1098
1099
1100
1101
  		break;
  	}
  
  	if (ret < 0)
  		return -1;
  
  	if (pdu->options & eH323_UU_PDU_h245Control) {
  		for (i = 0; i < pdu->h245Control.count; i++) {
051966c0c   Patrick McHardy   netfilter: nf_nat...
1102
1103
  			ret = process_h245(skb, ct, ctinfo,
  					   protoff, data, dataoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1104
1105
1106
1107
1108
1109
1110
1111
  					   &pdu->h245Control.item[i]);
  			if (ret < 0)
  				return -1;
  		}
  	}
  
  	return 0;
  }
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
1112
  static int q931_help(struct sk_buff *skb, unsigned int protoff,
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1113
1114
1115
1116
1117
1118
1119
1120
1121
  		     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...
1122
  	if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY)
f587de0e2   Patrick McHardy   [NETFILTER]: nf_c...
1123
  		return NF_ACCEPT;
fb0488337   Eric Dumazet   netfilter: add mo...
1124

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

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