Blame view

net/netfilter/nf_conntrack_proto_udplite.c 6.81 KB
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
1
2
3
4
5
6
7
8
9
10
11
12
  /* (C) 1999-2001 Paul `Rusty' Russell
   * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   * (C) 2007 Patrick McHardy <kaber@trash.net>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  #include <linux/types.h>
  #include <linux/timer.h>
  #include <linux/module.h>
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
13
14
15
16
17
18
19
20
21
22
23
24
  #include <linux/udp.h>
  #include <linux/seq_file.h>
  #include <linux/skbuff.h>
  #include <linux/ipv6.h>
  #include <net/ip6_checksum.h>
  #include <net/checksum.h>
  
  #include <linux/netfilter.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_ipv6.h>
  #include <net/netfilter/nf_conntrack_l4proto.h>
  #include <net/netfilter/nf_conntrack_ecache.h>
f01ffbd6e   Patrick McHardy   [NETFILTER]: nf_l...
25
  #include <net/netfilter/nf_log.h>
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
26
27
28
  
  static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
  static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
29
30
31
  static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
  				 unsigned int dataoff,
  				 struct nf_conntrack_tuple *tuple)
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
32
  {
da3f13c95   Jan Engelhardt   [NETFILTER]: nf_{...
33
34
  	const struct udphdr *hp;
  	struct udphdr _hdr;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
35
36
37
  
  	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  	if (hp == NULL)
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
38
  		return false;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
39
40
41
  
  	tuple->src.u.udp.port = hp->source;
  	tuple->dst.u.udp.port = hp->dest;
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
42
  	return true;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
43
  }
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
44
45
  static bool udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
  				 const struct nf_conntrack_tuple *orig)
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
46
47
48
  {
  	tuple->src.u.udp.port = orig->dst.u.udp.port;
  	tuple->dst.u.udp.port = orig->src.u.udp.port;
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
49
  	return true;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
50
51
52
53
54
55
56
57
58
59
  }
  
  /* Print out the per-protocol part of the tuple. */
  static int udplite_print_tuple(struct seq_file *s,
  			       const struct nf_conntrack_tuple *tuple)
  {
  	return seq_printf(s, "sport=%hu dport=%hu ",
  			  ntohs(tuple->src.u.udp.port),
  			  ntohs(tuple->dst.u.udp.port));
  }
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
60
  /* Returns verdict for packet, and may modify conntracktype */
c88130bcd   Patrick McHardy   [NETFILTER]: nf_c...
61
  static int udplite_packet(struct nf_conn *ct,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
62
63
64
  			  const struct sk_buff *skb,
  			  unsigned int dataoff,
  			  enum ip_conntrack_info ctinfo,
76108cea0   Jan Engelhardt   netfilter: Use un...
65
  			  u_int8_t pf,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
66
67
68
69
  			  unsigned int hooknum)
  {
  	/* If we've seen traffic both ways, this is some kind of UDP
  	   stream.  Extend timeout. */
c88130bcd   Patrick McHardy   [NETFILTER]: nf_c...
70
71
  	if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
  		nf_ct_refresh_acct(ct, ctinfo, skb,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
72
73
  				   nf_ct_udplite_timeout_stream);
  		/* Also, more likely to be important, and not a probe */
c88130bcd   Patrick McHardy   [NETFILTER]: nf_c...
74
  		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
858b31330   Patrick McHardy   netfilter: nf_con...
75
  			nf_conntrack_event_cache(IPCT_ASSURED, ct);
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
76
  	} else
c88130bcd   Patrick McHardy   [NETFILTER]: nf_c...
77
  		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout);
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
78
79
80
81
82
  
  	return NF_ACCEPT;
  }
  
  /* Called when a new connection for this protocol found. */
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
83
84
  static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
  			unsigned int dataoff)
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
85
  {
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
86
  	return true;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
87
  }
8fea97ec1   Patrick McHardy   netfilter: nf_con...
88
  static int udplite_error(struct net *net, struct nf_conn *tmpl,
74c51a149   Alexey Dobriyan   netfilter: netns ...
89
90
  			 struct sk_buff *skb,
  			 unsigned int dataoff,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
91
  			 enum ip_conntrack_info *ctinfo,
76108cea0   Jan Engelhardt   netfilter: Use un...
92
  			 u_int8_t pf,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
93
94
95
  			 unsigned int hooknum)
  {
  	unsigned int udplen = skb->len - dataoff;
da3f13c95   Jan Engelhardt   [NETFILTER]: nf_{...
96
97
  	const struct udphdr *hdr;
  	struct udphdr _hdr;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
98
99
100
101
102
  	unsigned int cscov;
  
  	/* Header is too small? */
  	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  	if (hdr == NULL) {
c2a2c7e0c   Alexey Dobriyan   netfilter: netns ...
103
  		if (LOG_INVALID(net, IPPROTO_UDPLITE))
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
104
105
106
107
108
109
110
111
112
  			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  				      "nf_ct_udplite: short packet ");
  		return -NF_ACCEPT;
  	}
  
  	cscov = ntohs(hdr->len);
  	if (cscov == 0)
  		cscov = udplen;
  	else if (cscov < sizeof(*hdr) || cscov > udplen) {
c2a2c7e0c   Alexey Dobriyan   netfilter: netns ...
113
  		if (LOG_INVALID(net, IPPROTO_UDPLITE))
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
114
115
116
117
118
119
120
  			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  				"nf_ct_udplite: invalid checksum coverage ");
  		return -NF_ACCEPT;
  	}
  
  	/* UDPLITE mandates checksums */
  	if (!hdr->check) {
c2a2c7e0c   Alexey Dobriyan   netfilter: netns ...
121
  		if (LOG_INVALID(net, IPPROTO_UDPLITE))
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
122
123
124
125
126
127
  			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  				      "nf_ct_udplite: checksum missing ");
  		return -NF_ACCEPT;
  	}
  
  	/* Checksum invalid? Ignore. */
c04d05529   Alexey Dobriyan   netfilter: netns ...
128
  	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
d63a65073   Patrick McHardy   [NETFILTER]: Add ...
129
130
  	    nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
  	    			pf)) {
c2a2c7e0c   Alexey Dobriyan   netfilter: netns ...
131
  		if (LOG_INVALID(net, IPPROTO_UDPLITE))
d63a65073   Patrick McHardy   [NETFILTER]: Add ...
132
133
134
  			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  				      "nf_ct_udplite: bad UDPLite checksum ");
  		return -NF_ACCEPT;
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
135
136
137
138
139
140
141
142
143
144
  	}
  
  	return NF_ACCEPT;
  }
  
  #ifdef CONFIG_SYSCTL
  static unsigned int udplite_sysctl_table_users;
  static struct ctl_table_header *udplite_sysctl_header;
  static struct ctl_table udplite_sysctl_table[] = {
  	{
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
145
146
147
148
  		.procname	= "nf_conntrack_udplite_timeout",
  		.data		= &nf_ct_udplite_timeout,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
6d9f239a1   Alexey Dobriyan   net: '&' redux
149
  		.proc_handler	= proc_dointvec_jiffies,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
150
151
  	},
  	{
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
152
153
154
155
  		.procname	= "nf_conntrack_udplite_timeout_stream",
  		.data		= &nf_ct_udplite_timeout_stream,
  		.maxlen		= sizeof(unsigned int),
  		.mode		= 0644,
6d9f239a1   Alexey Dobriyan   net: '&' redux
156
  		.proc_handler	= proc_dointvec_jiffies,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
157
  	},
f8572d8f2   Eric W. Biederman   sysctl net: Remov...
158
  	{ }
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
159
160
161
162
163
164
165
166
167
168
169
  };
  #endif /* CONFIG_SYSCTL */
  
  static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
  {
  	.l3proto		= PF_INET,
  	.l4proto		= IPPROTO_UDPLITE,
  	.name			= "udplite",
  	.pkt_to_tuple		= udplite_pkt_to_tuple,
  	.invert_tuple		= udplite_invert_tuple,
  	.print_tuple		= udplite_print_tuple,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
170
171
172
173
  	.packet			= udplite_packet,
  	.new			= udplite_new,
  	.error			= udplite_error,
  #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
174
  	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr,
a400c30ed   Holger Eitzenberger   netfilter: nf_con...
175
  	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
176
  	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
177
  	.nla_policy		= nf_ct_port_nla_policy,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  #endif
  #ifdef CONFIG_SYSCTL
  	.ctl_table_users	= &udplite_sysctl_table_users,
  	.ctl_table_header	= &udplite_sysctl_header,
  	.ctl_table		= udplite_sysctl_table,
  #endif
  };
  
  static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
  {
  	.l3proto		= PF_INET6,
  	.l4proto		= IPPROTO_UDPLITE,
  	.name			= "udplite",
  	.pkt_to_tuple		= udplite_pkt_to_tuple,
  	.invert_tuple		= udplite_invert_tuple,
  	.print_tuple		= udplite_print_tuple,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
194
195
196
197
  	.packet			= udplite_packet,
  	.new			= udplite_new,
  	.error			= udplite_error,
  #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
198
  	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr,
5ff482940   Patrick McHardy   netfilter: nf_ct_...
199
  	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
200
  	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
201
  	.nla_policy		= nf_ct_port_nla_policy,
59eecdfb1   Patrick McHardy   [NETFILTER]: nf_c...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  #endif
  #ifdef CONFIG_SYSCTL
  	.ctl_table_users	= &udplite_sysctl_table_users,
  	.ctl_table_header	= &udplite_sysctl_header,
  	.ctl_table		= udplite_sysctl_table,
  #endif
  };
  
  static int __init nf_conntrack_proto_udplite_init(void)
  {
  	int err;
  
  	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
  	if (err < 0)
  		goto err1;
  	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
  	if (err < 0)
  		goto err2;
  	return 0;
  err2:
  	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
  err1:
  	return err;
  }
  
  static void __exit nf_conntrack_proto_udplite_exit(void)
  {
  	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
  	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
  }
  
  module_init(nf_conntrack_proto_udplite_init);
  module_exit(nf_conntrack_proto_udplite_exit);
  
  MODULE_LICENSE("GPL");