Blame view

net/dccp/ipv4.c 28.3 KB
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
1
2
3
4
5
6
7
8
9
10
11
  /*
   *  net/dccp/ipv4.c
   *
   *  An implementation of the DCCP protocol
   *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
12
13
  #include <linux/dccp.h>
  #include <linux/icmp.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
14
  #include <linux/slab.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
15
16
17
18
19
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/random.h>
  
  #include <net/icmp.h>
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
20
  #include <net/inet_common.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
21
  #include <net/inet_hashtables.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
22
  #include <net/inet_sock.h>
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
23
  #include <net/protocol.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
24
  #include <net/sock.h>
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
25
  #include <net/timewait_sock.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
26
27
  #include <net/tcp_states.h>
  #include <net/xfrm.h>
6e5714eaf   David S. Miller   net: Compute prot...
28
  #include <net/secure_seq.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
29

ae31c3399   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
30
  #include "ackvec.h"
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
31
32
  #include "ccid.h"
  #include "dccp.h"
afe00251d   Andrea Bittau   [DCCP]: Initial f...
33
  #include "feat.h"
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
34

724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
35
  /*
13f51d82a   Pavel Emelyanov   [DCCP]: Fix comme...
36
   * The per-net dccp.v4_ctl_sk socket is used for responding to
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
37
38
39
   * the Out-of-the-blue (OOTB) packets. A control sock will be created
   * for this socket at the initialization time.
   */
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
40

f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
41
  int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
42
  {
2d7192d6c   David S. Miller   ipv4: Sanitize an...
43
  	const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
44
45
  	struct inet_sock *inet = inet_sk(sk);
  	struct dccp_sock *dp = dccp_sk(sk);
dca8b089c   David S. Miller   ipv4: Rearrange h...
46
  	__be16 orig_sport, orig_dport;
bada8adc4   Al Viro   [IPV4]: ip_route_...
47
  	__be32 daddr, nexthop;
2c42758cf   David S. Miller   dccp: Use cork fl...
48
  	struct flowi4 *fl4;
2d7192d6c   David S. Miller   ipv4: Sanitize an...
49
  	struct rtable *rt;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
50
  	int err;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
51
  	struct ip_options_rcu *inet_opt;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
52
53
54
55
56
57
58
59
60
61
  
  	dp->dccps_role = DCCP_ROLE_CLIENT;
  
  	if (addr_len < sizeof(struct sockaddr_in))
  		return -EINVAL;
  
  	if (usin->sin_family != AF_INET)
  		return -EAFNOSUPPORT;
  
  	nexthop = daddr = usin->sin_addr.s_addr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
62
63
64
65
  
  	inet_opt = rcu_dereference_protected(inet->inet_opt,
  					     sock_owned_by_user(sk));
  	if (inet_opt != NULL && inet_opt->opt.srr) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
66
67
  		if (daddr == 0)
  			return -EINVAL;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
68
  		nexthop = inet_opt->opt.faddr;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
69
  	}
dca8b089c   David S. Miller   ipv4: Rearrange h...
70
71
  	orig_sport = inet->inet_sport;
  	orig_dport = usin->sin_port;
2c42758cf   David S. Miller   dccp: Use cork fl...
72
73
  	fl4 = &inet->cork.fl.u.ip4;
  	rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
b23dd4fe4   David S. Miller   ipv4: Make output...
74
75
76
77
78
  			      RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
  			      IPPROTO_DCCP,
  			      orig_sport, orig_dport, sk, true);
  	if (IS_ERR(rt))
  		return PTR_ERR(rt);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
79
80
81
82
83
  
  	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
  		ip_rt_put(rt);
  		return -ENETUNREACH;
  	}
f6d8bd051   Eric Dumazet   inet: add RCU pro...
84
  	if (inet_opt == NULL || !inet_opt->opt.srr)
2c42758cf   David S. Miller   dccp: Use cork fl...
85
  		daddr = fl4->daddr;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
86

c720c7e83   Eric Dumazet   inet: rename some...
87
  	if (inet->inet_saddr == 0)
2c42758cf   David S. Miller   dccp: Use cork fl...
88
  		inet->inet_saddr = fl4->saddr;
c720c7e83   Eric Dumazet   inet: rename some...
89
  	inet->inet_rcv_saddr = inet->inet_saddr;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
90

c720c7e83   Eric Dumazet   inet: rename some...
91
92
  	inet->inet_dport = usin->sin_port;
  	inet->inet_daddr = daddr;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
93

d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
94
  	inet_csk(sk)->icsk_ext_hdr_len = 0;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
95
96
  	if (inet_opt)
  		inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
97
98
99
100
101
102
103
  	/*
  	 * Socket identity is still unknown (sport may be zero).
  	 * However we set state to DCCP_REQUESTING and not releasing socket
  	 * lock select source port, enter ourselves into the hash tables and
  	 * complete initialization after this.
  	 */
  	dccp_set_state(sk, DCCP_REQUESTING);
a7f5e7f16   Arnaldo Carvalho de Melo   [INET]: Generalis...
104
  	err = inet_hash_connect(&dccp_death_row, sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
105
106
  	if (err != 0)
  		goto failure;
2c42758cf   David S. Miller   dccp: Use cork fl...
107
  	rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
b23dd4fe4   David S. Miller   ipv4: Make output...
108
109
  			       inet->inet_sport, inet->inet_dport, sk);
  	if (IS_ERR(rt)) {
525c6465d   RongQing.Li   dccp: fix error p...
110
  		err = PTR_ERR(rt);
b23dd4fe4   David S. Miller   ipv4: Make output...
111
  		rt = NULL;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
112
  		goto failure;
b23dd4fe4   David S. Miller   ipv4: Make output...
113
  	}
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
114
  	/* OK, now commit destination to socket.  */
d8d1f30b9   Changli Gao   net-next: remove ...
115
  	sk_setup_caps(sk, &rt->dst);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
116

c720c7e83   Eric Dumazet   inet: rename some...
117
118
119
120
121
  	dp->dccps_iss = secure_dccp_sequence_number(inet->inet_saddr,
  						    inet->inet_daddr,
  						    inet->inet_sport,
  						    inet->inet_dport);
  	inet->inet_id = dp->dccps_iss ^ jiffies;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
122
123
124
125
126
127
128
129
  
  	err = dccp_connect(sk);
  	rt = NULL;
  	if (err != 0)
  		goto failure;
  out:
  	return err;
  failure:
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
130
131
132
  	/*
  	 * This unhashes the socket and releases the local port, if necessary.
  	 */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
133
134
135
  	dccp_set_state(sk, DCCP_CLOSED);
  	ip_rt_put(rt);
  	sk->sk_route_caps = 0;
c720c7e83   Eric Dumazet   inet: rename some...
136
  	inet->inet_dport = 0;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
137
138
  	goto out;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
139
  EXPORT_SYMBOL_GPL(dccp_v4_connect);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  /*
   * This routine does path mtu discovery as defined in RFC1191.
   */
  static inline void dccp_do_pmtu_discovery(struct sock *sk,
  					  const struct iphdr *iph,
  					  u32 mtu)
  {
  	struct dst_entry *dst;
  	const struct inet_sock *inet = inet_sk(sk);
  	const struct dccp_sock *dp = dccp_sk(sk);
  
  	/* We are not interested in DCCP_LISTEN and request_socks (RESPONSEs
  	 * send out by Linux are always < 576bytes so they should go through
  	 * unfragmented).
  	 */
  	if (sk->sk_state == DCCP_LISTEN)
  		return;
  
  	/* We don't check in the destentry if pmtu discovery is forbidden
  	 * on this route. We just assume that no packet_to_big packets
  	 * are send back when pmtu discovery is not active.
c9eaf1734   YOSHIFUJI Hideaki   [NET] DCCP: Fix w...
161
  	 * There is a small race when the user changes this flag in the
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  	 * route, but I think that's acceptable.
  	 */
  	if ((dst = __sk_dst_check(sk, 0)) == NULL)
  		return;
  
  	dst->ops->update_pmtu(dst, mtu);
  
  	/* Something is about to be wrong... Remember soft error
  	 * for the case, if this connection will not able to recover.
  	 */
  	if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
  		sk->sk_err_soft = EMSGSIZE;
  
  	mtu = dst_mtu(dst);
  
  	if (inet->pmtudisc != IP_PMTUDISC_DONT &&
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
178
  	    inet_csk(sk)->icsk_pmtu_cookie > mtu) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
179
180
181
  		dccp_sync_mss(sk, mtu);
  
  		/*
0e64e94e4   Gerrit Renker   [DCCP]: Update do...
182
  		 * From RFC 4340, sec. 14.1:
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
183
  		 *
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
184
185
186
  		 *	DCCP-Sync packets are the best choice for upward
  		 *	probing, since DCCP-Sync probes do not risk application
  		 *	data loss.
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
187
  		 */
e92ae93a8   Arnaldo Carvalho de Melo   [DCCP]: Send SYNC...
188
  		dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
189
190
  	} /* else let the usual retransmit timer handle it */
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
191
192
193
194
195
196
197
198
199
200
201
202
  /*
   * This routine is called by the ICMP module when it gets some sort of error
   * condition. If err < 0 then the socket should be closed and the error
   * returned to the user. If err > 0 it's just the icmp type << 8 | icmp code.
   * After adjustment header points to the first 8 bytes of the tcp header. We
   * need to find the appropriate port.
   *
   * The locking strategy used here is very "optimistic". When someone else
   * accesses the socket the ICMP is just dropped and for some paths there is no
   * check at all. A more general error queue to queue errors for later handling
   * is probably better.
   */
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
203
  static void dccp_v4_err(struct sk_buff *skb, u32 info)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
204
205
  {
  	const struct iphdr *iph = (struct iphdr *)skb->data;
18e1d8360   Wei Yongjun   dccp: Fix incorre...
206
207
  	const u8 offset = iph->ihl << 2;
  	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
208
209
  	struct dccp_sock *dp;
  	struct inet_sock *inet;
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
210
211
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
212
213
214
  	struct sock *sk;
  	__u64 seq;
  	int err;
fd54d716b   Pavel Emelyanov   inet: toss struct...
215
  	struct net *net = dev_net(skb->dev);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
216

18e1d8360   Wei Yongjun   dccp: Fix incorre...
217
218
  	if (skb->len < offset + sizeof(*dh) ||
  	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
dcfc23cac   Pavel Emelyanov   mib: add struct n...
219
  		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
220
221
  		return;
  	}
fd54d716b   Pavel Emelyanov   inet: toss struct...
222
  	sk = inet_lookup(net, &dccp_hashinfo,
b9901a84c   Pavel Emelyanov   [NETNS][DCCPV4]: ...
223
224
  			iph->daddr, dh->dccph_dport,
  			iph->saddr, dh->dccph_sport, inet_iif(skb));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
225
  	if (sk == NULL) {
dcfc23cac   Pavel Emelyanov   mib: add struct n...
226
  		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
227
228
229
230
  		return;
  	}
  
  	if (sk->sk_state == DCCP_TIME_WAIT) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
231
  		inet_twsk_put(inet_twsk(sk));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
232
233
234
235
236
237
238
239
  		return;
  	}
  
  	bh_lock_sock(sk);
  	/* If too many ICMPs get dropped on busy
  	 * servers this needs to be solved differently.
  	 */
  	if (sock_owned_by_user(sk))
de0744af1   Pavel Emelyanov   mib: add net to N...
240
  		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
241
242
243
244
245
  
  	if (sk->sk_state == DCCP_CLOSED)
  		goto out;
  
  	dp = dccp_sk(sk);
fde20105f   Gerrit Renker   [DCCP]: Retrieve ...
246
  	seq = dccp_hdr_seq(dh);
1238d0873   Gerrit Renker   [DCCP]: One more ...
247
  	if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
d68f0866f   Wei Yongjun   dccp: Fix sequenc...
248
  	    !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
de0744af1   Pavel Emelyanov   mib: add net to N...
249
  		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  		goto out;
  	}
  
  	switch (type) {
  	case ICMP_SOURCE_QUENCH:
  		/* Just silently ignore these. */
  		goto out;
  	case ICMP_PARAMETERPROB:
  		err = EPROTO;
  		break;
  	case ICMP_DEST_UNREACH:
  		if (code > NR_ICMP_UNREACH)
  			goto out;
  
  		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
  			if (!sock_owned_by_user(sk))
  				dccp_do_pmtu_discovery(sk, iph, info);
  			goto out;
  		}
  
  		err = icmp_err_convert[code].errno;
  		break;
  	case ICMP_TIME_EXCEEDED:
  		err = EHOSTUNREACH;
  		break;
  	default:
  		goto out;
  	}
  
  	switch (sk->sk_state) {
  		struct request_sock *req , **prev;
  	case DCCP_LISTEN:
  		if (sock_owned_by_user(sk))
  			goto out;
  		req = inet_csk_search_req(sk, &prev, dh->dccph_dport,
  					  iph->daddr, iph->saddr);
  		if (!req)
  			goto out;
  
  		/*
  		 * ICMPs are not backlogged, hence we cannot get an established
  		 * socket here.
  		 */
547b792ca   Ilpo Järvinen   net: convert BUG_...
293
  		WARN_ON(req->sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
294
295
  
  		if (seq != dccp_rsk(req)->dreq_iss) {
de0744af1   Pavel Emelyanov   mib: add net to N...
296
  			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  			goto out;
  		}
  		/*
  		 * Still in RESPOND, just remove it silently.
  		 * There is no good way to pass the error to the newly
  		 * created socket, and POSIX does not want network
  		 * errors returned from accept().
  		 */
  		inet_csk_reqsk_queue_drop(sk, req, prev);
  		goto out;
  
  	case DCCP_REQUESTING:
  	case DCCP_RESPOND:
  		if (!sock_owned_by_user(sk)) {
  			DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
  			sk->sk_err = err;
  
  			sk->sk_error_report(sk);
  
  			dccp_done(sk);
  		} else
  			sk->sk_err_soft = err;
  		goto out;
  	}
  
  	/* If we've already connected we will keep trying
  	 * until we time out, or the user gives up.
  	 *
  	 * rfc1122 4.2.3.9 allows to consider as hard errors
  	 * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
  	 * but it is obsoleted by pmtu discovery).
  	 *
  	 * Note, that in modern internet, where routing is unreliable
  	 * and in each dark corner broken firewalls sit, sending random
  	 * errors ordered by their masters even this two messages finally lose
  	 * their original sense (even Linux sends invalid PORT_UNREACHs)
  	 *
  	 * Now we are in compliance with RFCs.
  	 *							--ANK (980905)
  	 */
  
  	inet = inet_sk(sk);
  	if (!sock_owned_by_user(sk) && inet->recverr) {
  		sk->sk_err = err;
  		sk->sk_error_report(sk);
  	} else /* Only an error on timeout */
  		sk->sk_err_soft = err;
  out:
  	bh_unlock_sock(sk);
  	sock_put(sk);
  }
2bda28531   Al Viro   [NET]: Annotate c...
348
  static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb,
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
349
350
351
352
  				      __be32 src, __be32 dst)
  {
  	return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum);
  }
bb2962461   Herbert Xu   inet: Remove unus...
353
  void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb)
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
354
355
356
  {
  	const struct inet_sock *inet = inet_sk(sk);
  	struct dccp_hdr *dh = dccp_hdr(skb);
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
357
  	dccp_csum_outgoing(skb);
c720c7e83   Eric Dumazet   inet: rename some...
358
359
360
  	dh->dccph_checksum = dccp_v4_csum_finish(skb,
  						 inet->inet_saddr,
  						 inet->inet_daddr);
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
361
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
362
  EXPORT_SYMBOL_GPL(dccp_v4_send_check);
865e9022d   Gerrit Renker   [DCCP]: Remove re...
363
  static inline u64 dccp_v4_init_sequence(const struct sk_buff *skb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
364
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
365
366
  	return secure_dccp_sequence_number(ip_hdr(skb)->daddr,
  					   ip_hdr(skb)->saddr,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
367
368
369
  					   dccp_hdr(skb)->dccph_dport,
  					   dccp_hdr(skb)->dccph_sport);
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
370
371
372
373
374
375
376
377
378
379
380
381
  /*
   * The three way handshake has completed - we got a valid ACK or DATAACK -
   * now create the new socket.
   *
   * This is the equivalent of TCP's tcp_v4_syn_recv_sock
   */
  struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
  				       struct request_sock *req,
  				       struct dst_entry *dst)
  {
  	struct inet_request_sock *ireq;
  	struct inet_sock *newinet;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
382
383
384
385
  	struct sock *newsk;
  
  	if (sk_acceptq_is_full(sk))
  		goto exit_overflow;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
386
387
  	newsk = dccp_create_openreq_child(sk, req, skb);
  	if (newsk == NULL)
093d28232   Balazs Scheidler   tproxy: fix hash ...
388
  		goto exit_nonewsk;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
389

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
390
391
  	newinet		   = inet_sk(newsk);
  	ireq		   = inet_rsk(req);
c720c7e83   Eric Dumazet   inet: rename some...
392
393
394
  	newinet->inet_daddr	= ireq->rmt_addr;
  	newinet->inet_rcv_saddr = ireq->loc_addr;
  	newinet->inet_saddr	= ireq->loc_addr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
395
  	newinet->inet_opt	= ireq->opt;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
396
397
  	ireq->opt	   = NULL;
  	newinet->mc_index  = inet_iif(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
398
  	newinet->mc_ttl	   = ip_hdr(skb)->ttl;
c720c7e83   Eric Dumazet   inet: rename some...
399
  	newinet->inet_id   = jiffies;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
400

0e7344199   David S. Miller   ipv4: Use inet_cs...
401
402
403
404
  	if (dst == NULL && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
  		goto put_and_exit;
  
  	sk_setup_caps(newsk, dst);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
405
  	dccp_sync_mss(newsk, dst_mtu(dst));
0e7344199   David S. Miller   ipv4: Use inet_cs...
406
407
  	if (__inet_inherit_port(sk, newsk) < 0)
  		goto put_and_exit;
9327f7053   Eric Dumazet   tcp: Fix a connec...
408
  	__inet_hash_nolisten(newsk, NULL);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
409
410
411
412
  
  	return newsk;
  
  exit_overflow:
de0744af1   Pavel Emelyanov   mib: add net to N...
413
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
093d28232   Balazs Scheidler   tproxy: fix hash ...
414
415
  exit_nonewsk:
  	dst_release(dst);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
416
  exit:
de0744af1   Pavel Emelyanov   mib: add net to N...
417
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
418
  	return NULL;
0e7344199   David S. Miller   ipv4: Use inet_cs...
419
  put_and_exit:
918eb3996   Eric Dumazet   net: add missing ...
420
  	bh_unlock_sock(newsk);
0e7344199   David S. Miller   ipv4: Use inet_cs...
421
422
  	sock_put(newsk);
  	goto exit;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
423
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
424
  EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
425
426
427
  static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
  {
  	const struct dccp_hdr *dh = dccp_hdr(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
428
  	const struct iphdr *iph = ip_hdr(skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
429
430
431
432
433
434
435
436
  	struct sock *nsk;
  	struct request_sock **prev;
  	/* Find possible connection requests. */
  	struct request_sock *req = inet_csk_search_req(sk, &prev,
  						       dh->dccph_sport,
  						       iph->saddr, iph->daddr);
  	if (req != NULL)
  		return dccp_check_req(sk, skb, req, prev);
b9901a84c   Pavel Emelyanov   [NETNS][DCCPV4]: ...
437
  	nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo,
8f491069b   Herbert Xu   [IPV4]: Use netwo...
438
439
440
  				      iph->saddr, dh->dccph_sport,
  				      iph->daddr, dh->dccph_dport,
  				      inet_iif(skb));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
441
442
443
444
445
  	if (nsk != NULL) {
  		if (nsk->sk_state != DCCP_TIME_WAIT) {
  			bh_lock_sock(nsk);
  			return nsk;
  		}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
446
  		inet_twsk_put(inet_twsk(nsk));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
447
448
449
450
451
  		return NULL;
  	}
  
  	return sk;
  }
f54873982   Pavel Emelyanov   [NETNS][DCCPV4]: ...
452
  static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
453
454
455
  					   struct sk_buff *skb)
  {
  	struct rtable *rt;
898f73585   David S. Miller   dccp: Evaluate ip...
456
  	const struct iphdr *iph = ip_hdr(skb);
9d6ec9380   David S. Miller   ipv4: Use flowi4 ...
457
458
  	struct flowi4 fl4 = {
  		.flowi4_oif = skb_rtable(skb)->rt_iif,
898f73585   David S. Miller   dccp: Evaluate ip...
459
460
  		.daddr = iph->saddr,
  		.saddr = iph->daddr,
9d6ec9380   David S. Miller   ipv4: Use flowi4 ...
461
462
  		.flowi4_tos = RT_CONN_FLAGS(sk),
  		.flowi4_proto = sk->sk_protocol,
9cce96df5   David S. Miller   net: Put fl4_* ma...
463
464
  		.fl4_sport = dccp_hdr(skb)->dccph_dport,
  		.fl4_dport = dccp_hdr(skb)->dccph_sport,
1d28f42c1   David S. Miller   net: Put flowi_* ...
465
  	};
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
466

9d6ec9380   David S. Miller   ipv4: Use flowi4 ...
467
468
  	security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
  	rt = ip_route_output_flow(net, &fl4, sk);
b23dd4fe4   David S. Miller   ipv4: Make output...
469
  	if (IS_ERR(rt)) {
7c73a6faf   Pavel Emelyanov   mib: add net to I...
470
  		IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
471
472
  		return NULL;
  	}
d8d1f30b9   Changli Gao   net-next: remove ...
473
  	return &rt->dst;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
474
  }
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
475
476
  static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
  				 struct request_values *rv_unused)
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
477
478
479
  {
  	int err = -1;
  	struct sk_buff *skb;
fd80eb942   Denis V. Lunev   [INET]: Remove st...
480
  	struct dst_entry *dst;
6bd023f3d   David S. Miller   ipv4: Make caller...
481
  	struct flowi4 fl4;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
482

6bd023f3d   David S. Miller   ipv4: Make caller...
483
  	dst = inet_csk_route_req(sk, &fl4, req);
fd80eb942   Denis V. Lunev   [INET]: Remove st...
484
  	if (dst == NULL)
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
485
486
487
488
489
490
  		goto out;
  
  	skb = dccp_make_response(sk, dst, req);
  	if (skb != NULL) {
  		const struct inet_request_sock *ireq = inet_rsk(req);
  		struct dccp_hdr *dh = dccp_hdr(skb);
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
491
492
  		dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr,
  							      ireq->rmt_addr);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
493
494
495
  		err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
  					    ireq->rmt_addr,
  					    ireq->opt);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
496
  		err = net_xmit_eval(err);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
497
498
499
500
501
502
  	}
  
  out:
  	dst_release(dst);
  	return err;
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
503
  static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
504
505
  {
  	int err;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
506
  	const struct iphdr *rxiph;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
507
508
  	struct sk_buff *skb;
  	struct dst_entry *dst;
adf30907d   Eric Dumazet   net: skb->dst acc...
509
  	struct net *net = dev_net(skb_dst(rxskb)->dev);
b76c4b27f   Pavel Emelyanov   [NETNS][DCCPV4]: ...
510
  	struct sock *ctl_sk = net->dccp.v4_ctl_sk;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
511
512
  
  	/* Never send a reset in response to a reset. */
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
513
  	if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
514
  		return;
511c3f92a   Eric Dumazet   net: skb->rtable ...
515
  	if (skb_rtable(rxskb)->rt_type != RTN_LOCAL)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
516
  		return;
f54873982   Pavel Emelyanov   [NETNS][DCCPV4]: ...
517
  	dst = dccp_v4_route_skb(net, ctl_sk, rxskb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
518
519
  	if (dst == NULL)
  		return;
7b1cffa8c   Pavel Emelyanov   [NETNS][DCCPV4]: ...
520
  	skb = dccp_ctl_make_reset(ctl_sk, rxskb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
521
522
  	if (skb == NULL)
  		goto out;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
523
  	rxiph = ip_hdr(rxskb);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
524
525
  	dccp_hdr(skb)->dccph_checksum = dccp_v4_csum_finish(skb, rxiph->saddr,
  								 rxiph->daddr);
adf30907d   Eric Dumazet   net: skb->dst acc...
526
  	skb_dst_set(skb, dst_clone(dst));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
527

7b1cffa8c   Pavel Emelyanov   [NETNS][DCCPV4]: ...
528
529
  	bh_lock_sock(ctl_sk);
  	err = ip_build_and_send_pkt(skb, ctl_sk,
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
530
  				    rxiph->daddr, rxiph->saddr, NULL);
7b1cffa8c   Pavel Emelyanov   [NETNS][DCCPV4]: ...
531
  	bh_unlock_sock(ctl_sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
532

b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
533
  	if (net_xmit_eval(err) == 0) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
534
535
536
537
538
539
  		DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
  		DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
  	}
  out:
  	 dst_release(dst);
  }
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
540
541
  static void dccp_v4_reqsk_destructor(struct request_sock *req)
  {
d99a7bd21   Gerrit Renker   dccp: Cleanup rou...
542
  	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
  	kfree(inet_rsk(req)->opt);
  }
  
  static struct request_sock_ops dccp_request_sock_ops __read_mostly = {
  	.family		= PF_INET,
  	.obj_size	= sizeof(struct dccp_request_sock),
  	.rtx_syn_ack	= dccp_v4_send_response,
  	.send_ack	= dccp_reqsk_send_ack,
  	.destructor	= dccp_v4_reqsk_destructor,
  	.send_reset	= dccp_v4_ctl_send_reset,
  };
  
  int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
  {
  	struct inet_request_sock *ireq;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
558
559
  	struct request_sock *req;
  	struct dccp_request_sock *dreq;
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
560
  	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
561
  	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
562
563
  
  	/* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
511c3f92a   Eric Dumazet   net: skb->rtable ...
564
  	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
4a5409a5a   Gerrit Renker   [DCCP]: Twice the...
565
  		return 0;	/* discard, don't send a reset here */
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
566
567
  
  	if (dccp_bad_service_code(sk, service)) {
4a5409a5a   Gerrit Renker   [DCCP]: Twice the...
568
  		dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
569
  		goto drop;
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
570
  	}
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
571
572
573
574
575
  	/*
  	 * TW buckets are converted to open requests without
  	 * limitations, they conserve resources and peer is
  	 * evidently real one.
  	 */
4a5409a5a   Gerrit Renker   [DCCP]: Twice the...
576
  	dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
577
578
579
580
581
582
583
584
585
586
587
  	if (inet_csk_reqsk_queue_is_full(sk))
  		goto drop;
  
  	/*
  	 * Accept backlog is full. If we have already queued enough
  	 * of warm entries in syn queue, drop request. It is better than
  	 * clogging syn queue with openreqs with exponentially increasing
  	 * timeout.
  	 */
  	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
  		goto drop;
ce4a7d0d4   Arnaldo Carvalho de Melo   inet{6}_request_s...
588
  	req = inet_reqsk_alloc(&dccp_request_sock_ops);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
589
590
  	if (req == NULL)
  		goto drop;
ac75773c2   Gerrit Renker   dccp: Per-socket ...
591
592
  	if (dccp_reqsk_init(req, dccp_sk(sk), skb))
  		goto drop_and_free;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
593

8b8194124   Gerrit Renker   [DCCP]: Allow to ...
594
595
596
  	dreq = dccp_rsk(req);
  	if (dccp_parse_options(sk, dreq, skb))
  		goto drop_and_free;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
597
598
599
600
  	if (security_inet_conn_request(sk, skb, req))
  		goto drop_and_free;
  
  	ireq = inet_rsk(req);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
601
602
  	ireq->loc_addr = ip_hdr(skb)->daddr;
  	ireq->rmt_addr = ip_hdr(skb)->saddr;
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
603

8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
604
  	/*
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
605
606
607
608
609
610
611
  	 * Step 3: Process LISTEN state
  	 *
  	 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
  	 *
  	 * In fact we defer setting S.GSR, S.SWL, S.SWH to
  	 * dccp_create_openreq_child.
  	 */
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
612
  	dreq->dreq_isr	   = dcb->dccpd_seq;
865e9022d   Gerrit Renker   [DCCP]: Remove re...
613
  	dreq->dreq_iss	   = dccp_v4_init_sequence(skb);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
614
  	dreq->dreq_service = service;
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
615
  	if (dccp_v4_send_response(sk, req, NULL))
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
616
617
618
619
620
621
622
623
624
  		goto drop_and_free;
  
  	inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
  	return 0;
  
  drop_and_free:
  	reqsk_free(req);
  drop:
  	DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
3d2fe62b8   Gerrit Renker   [DCCPv4]: remove ...
625
626
627
628
  	return -1;
  }
  
  EXPORT_SYMBOL_GPL(dccp_v4_conn_request);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
629
630
631
632
633
634
635
636
637
638
639
640
  int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
  {
  	struct dccp_hdr *dh = dccp_hdr(skb);
  
  	if (sk->sk_state == DCCP_OPEN) { /* Fast path */
  		if (dccp_rcv_established(sk, skb, dh, skb->len))
  			goto reset;
  		return 0;
  	}
  
  	/*
  	 *  Step 3: Process LISTEN state
d83ca5acc   Gerrit Renker   [DCCP]: Update co...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  	 *	 If P.type == Request or P contains a valid Init Cookie option,
  	 *	      (* Must scan the packet's options to check for Init
  	 *		 Cookies.  Only Init Cookies are processed here,
  	 *		 however; other options are processed in Step 8.  This
  	 *		 scan need only be performed if the endpoint uses Init
  	 *		 Cookies *)
  	 *	      (* Generate a new socket and switch to that socket *)
  	 *	      Set S := new socket for this port pair
  	 *	      S.state = RESPOND
  	 *	      Choose S.ISS (initial seqno) or set from Init Cookies
  	 *	      Initialize S.GAR := S.ISS
  	 *	      Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
  	 *	      Continue with S.state == RESPOND
  	 *	      (* A Response packet will be generated in Step 11 *)
  	 *	 Otherwise,
  	 *	      Generate Reset(No Connection) unless P.type == Reset
  	 *	      Drop packet and return
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
658
  	 *
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
659
660
  	 * NOTE: the check for the packet types is done in
  	 *	 dccp_rcv_state_process
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  	 */
  	if (sk->sk_state == DCCP_LISTEN) {
  		struct sock *nsk = dccp_v4_hnd_req(sk, skb);
  
  		if (nsk == NULL)
  			goto discard;
  
  		if (nsk != sk) {
  			if (dccp_child_process(sk, nsk, skb))
  				goto reset;
  			return 0;
  		}
  	}
  
  	if (dccp_rcv_state_process(sk, skb, dh, skb->len))
  		goto reset;
  	return 0;
  
  reset:
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
680
  	dccp_v4_ctl_send_reset(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
681
682
683
684
  discard:
  	kfree_skb(skb);
  	return 0;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
685
  EXPORT_SYMBOL_GPL(dccp_v4_do_rcv);
09dbc3895   Gerrit Renker   [DCCP]: Miscellan...
686
687
688
689
690
  /**
   *	dccp_invalid_packet  -  check for malformed packets
   *	Implements RFC 4340, 8.5:  Step 1: Check header basics
   *	Packets that fail these checks are ignored and do not receive Resets.
   */
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
691
  int dccp_invalid_packet(struct sk_buff *skb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
692
693
  {
  	const struct dccp_hdr *dh;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
694
  	unsigned int cscov;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
695
696
697
  
  	if (skb->pkt_type != PACKET_HOST)
  		return 1;
09dbc3895   Gerrit Renker   [DCCP]: Miscellan...
698
  	/* If the packet is shorter than 12 bytes, drop packet and return */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
699
  	if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
700
701
  		DCCP_WARN("pskb_may_pull failed
  ");
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
702
703
704
705
  		return 1;
  	}
  
  	dh = dccp_hdr(skb);
09dbc3895   Gerrit Renker   [DCCP]: Miscellan...
706
  	/* If P.type is not understood, drop packet and return */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
707
  	if (dh->dccph_type >= DCCP_PKT_INVALID) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
708
709
  		DCCP_WARN("invalid packet type
  ");
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
710
711
712
713
  		return 1;
  	}
  
  	/*
09dbc3895   Gerrit Renker   [DCCP]: Miscellan...
714
  	 * If P.Data Offset is too small for packet type, drop packet and return
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
715
716
  	 */
  	if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
717
718
  		DCCP_WARN("P.Data Offset(%u) too small
  ", dh->dccph_doff);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
719
720
  		return 1;
  	}
09dbc3895   Gerrit Renker   [DCCP]: Miscellan...
721
722
723
  	/*
  	 * If P.Data Offset is too too large for packet, drop packet and return
  	 */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
724
  	if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
725
726
  		DCCP_WARN("P.Data Offset(%u) too large
  ", dh->dccph_doff);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
727
728
  		return 1;
  	}
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
729
730
731
732
  	/*
  	 * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
  	 * has short sequence numbers), drop packet and return
  	 */
6079a463c   Wei Yongjun   dccp: Fix to hand...
733
734
  	if ((dh->dccph_type < DCCP_PKT_DATA    ||
  	    dh->dccph_type > DCCP_PKT_DATAACK) && dh->dccph_x == 0)  {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
735
736
737
  		DCCP_WARN("P.type (%s) not Data || [Data]Ack, while P.X == 0
  ",
  			  dccp_packet_name(dh->dccph_type));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
738
739
  		return 1;
  	}
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
740
741
742
743
744
745
  	/*
  	 * If P.CsCov is too large for the packet size, drop packet and return.
  	 * This must come _before_ checksumming (not as RFC 4340 suggests).
  	 */
  	cscov = dccp_csum_coverage(skb);
  	if (cscov > skb->len) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
746
747
748
  		DCCP_WARN("P.CsCov %u exceeds packet length %d
  ",
  			  dh->dccph_cscov, skb->len);
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
749
750
751
752
753
754
  		return 1;
  	}
  
  	/* If header checksum is incorrect, drop packet and return.
  	 * (This step is completed in the AF-dependent functions.) */
  	skb->csum = skb_checksum(skb, 0, cscov, 0);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
755
756
  	return 0;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
757
  EXPORT_SYMBOL_GPL(dccp_invalid_packet);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
758
  /* this is called when real data arrives */
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
759
  static int dccp_v4_rcv(struct sk_buff *skb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
760
761
  {
  	const struct dccp_hdr *dh;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
762
  	const struct iphdr *iph;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
763
  	struct sock *sk;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
764
  	int min_cov;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
765

6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
766
  	/* Step 1: Check header basics */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
767
768
769
  
  	if (dccp_invalid_packet(skb))
  		goto discard_it;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
770
  	iph = ip_hdr(skb);
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
771
  	/* Step 1: If header checksum is incorrect, drop packet and return */
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
772
  	if (dccp_v4_csum_finish(skb, iph->saddr, iph->daddr)) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
773
774
  		DCCP_WARN("dropped packet with invalid checksum
  ");
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
775
776
  		goto discard_it;
  	}
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
777
  	dh = dccp_hdr(skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
778

fde20105f   Gerrit Renker   [DCCP]: Retrieve ...
779
  	DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(dh);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
780
  	DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
21454aaad   Harvey Harrison   net: replace NIPQ...
781
  	dccp_pr_debug("%8.8s src=%pI4@%-5d dst=%pI4@%-5d seq=%llu",
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
782
  		      dccp_packet_name(dh->dccph_type),
21454aaad   Harvey Harrison   net: replace NIPQ...
783
784
  		      &iph->saddr, ntohs(dh->dccph_sport),
  		      &iph->daddr, ntohs(dh->dccph_dport),
f6ccf5541   David S. Miller   [DCCP]: Fix u64 p...
785
  		      (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
786
787
788
789
790
791
792
  
  	if (dccp_packet_without_ack(skb)) {
  		DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
  		dccp_pr_debug_cat("
  ");
  	} else {
  		DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
d23c7107b   Gerrit Renker   [DCCP]: Simplify ...
793
794
  		dccp_pr_debug_cat(", ack=%llu
  ", (unsigned long long)
f6ccf5541   David S. Miller   [DCCP]: Fix u64 p...
795
  				  DCCP_SKB_CB(skb)->dccpd_ack_seq);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
796
797
798
  	}
  
  	/* Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
799
  	 *	Look up flow ID in table and get corresponding socket */
9a1f27c48   Arnaldo Carvalho de Melo   inet_hashtables: ...
800
801
  	sk = __inet_lookup_skb(&dccp_hashinfo, skb,
  			       dh->dccph_sport, dh->dccph_dport);
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
802
  	/*
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
803
  	 * Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
804
  	 *	If no socket ...
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
805
806
807
808
809
810
811
  	 */
  	if (sk == NULL) {
  		dccp_pr_debug("failed to look up flow ID in table and "
  			      "get corresponding socket
  ");
  		goto no_dccp_socket;
  	}
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
812
  	/*
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
813
  	 * Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
814
  	 *	... or S.state == TIMEWAIT,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
815
816
817
  	 *		Generate Reset(No Connection) unless P.type == Reset
  	 *		Drop packet and return
  	 */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
818
  	if (sk->sk_state == DCCP_TIME_WAIT) {
d23c7107b   Gerrit Renker   [DCCP]: Simplify ...
819
820
821
822
  		dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait
  ");
  		inet_twsk_put(inet_twsk(sk));
  		goto no_dccp_socket;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
823
  	}
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
824
825
  	/*
  	 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
826
827
  	 *	o if MinCsCov = 0, only packets with CsCov = 0 are accepted
  	 *	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
828
829
830
831
832
833
834
835
836
837
838
  	 */
  	min_cov = dccp_sk(sk)->dccps_pcrlen;
  	if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov))  {
  		dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d
  ",
  			      dh->dccph_cscov, min_cov);
  		/* FIXME: "Such packets SHOULD be reported using Data Dropped
  		 *         options (Section 11.7) with Drop Code 0, Protocol
  		 *         Constraints."                                     */
  		goto discard_and_relse;
  	}
25995ff57   Arnaldo Carvalho de Melo   [SOCK]: Introduce...
839
  	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
840
  		goto discard_and_relse;
eb9c7ebe6   Patrick McHardy   [NETFILTER]: Hand...
841
  	nf_reset(skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
842

58a5a7b95   Arnaldo Carvalho de Melo   [NET]: Conditiona...
843
  	return sk_receive_skb(sk, skb, 1);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
844
845
846
847
848
849
  
  no_dccp_socket:
  	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  		goto discard_it;
  	/*
  	 * Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
850
  	 *	If no socket ...
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
851
852
853
854
  	 *		Generate Reset(No Connection) unless P.type == Reset
  	 *		Drop packet and return
  	 */
  	if (dh->dccph_type != DCCP_PKT_RESET) {
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
855
856
  		DCCP_SKB_CB(skb)->dccpd_reset_code =
  					DCCP_RESET_CODE_NO_CONNECTION;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
857
  		dccp_v4_ctl_send_reset(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
858
859
860
  	}
  
  discard_it:
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
861
862
863
864
865
866
867
  	kfree_skb(skb);
  	return 0;
  
  discard_and_relse:
  	sock_put(sk);
  	goto discard_it;
  }
3b401a81c   Stephen Hemminger   inet: inet_connec...
868
  static const struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
869
870
871
872
873
874
875
876
877
878
  	.queue_xmit	   = ip_queue_xmit,
  	.send_check	   = dccp_v4_send_check,
  	.rebuild_header	   = inet_sk_rebuild_header,
  	.conn_request	   = dccp_v4_conn_request,
  	.syn_recv_sock	   = dccp_v4_request_recv_sock,
  	.net_header_len	   = sizeof(struct iphdr),
  	.setsockopt	   = ip_setsockopt,
  	.getsockopt	   = ip_getsockopt,
  	.addr2sockaddr	   = inet_csk_addr2sockaddr,
  	.sockaddr_len	   = sizeof(struct sockaddr_in),
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
879
  	.bind_conflict	   = inet_csk_bind_conflict,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
880
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
881
882
  	.compat_setsockopt = compat_ip_setsockopt,
  	.compat_getsockopt = compat_ip_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
883
  #endif
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
884
  };
3e0fadc51   Arnaldo Carvalho de Melo   [DCCP]: Move dccp...
885
  static int dccp_v4_init_sock(struct sock *sk)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
886
  {
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
887
888
  	static __u8 dccp_v4_ctl_sock_initialized;
  	int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
889

724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
890
891
892
  	if (err == 0) {
  		if (unlikely(!dccp_v4_ctl_sock_initialized))
  			dccp_v4_ctl_sock_initialized = 1;
3e0fadc51   Arnaldo Carvalho de Melo   [DCCP]: Move dccp...
893
  		inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
894
  	}
3e0fadc51   Arnaldo Carvalho de Melo   [DCCP]: Move dccp...
895
  	return err;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
896
  }
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
897
898
899
  static struct timewait_sock_ops dccp_timewait_sock_ops = {
  	.twsk_obj_size	= sizeof(struct inet_timewait_sock),
  };
5e0817f84   Adrian Bunk   [DCCP] ipv4: make...
900
  static struct proto dccp_v4_prot = {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
901
902
903
904
905
906
907
908
909
910
911
912
  	.name			= "DCCP",
  	.owner			= THIS_MODULE,
  	.close			= dccp_close,
  	.connect		= dccp_v4_connect,
  	.disconnect		= dccp_disconnect,
  	.ioctl			= dccp_ioctl,
  	.init			= dccp_v4_init_sock,
  	.setsockopt		= dccp_setsockopt,
  	.getsockopt		= dccp_getsockopt,
  	.sendmsg		= dccp_sendmsg,
  	.recvmsg		= dccp_recvmsg,
  	.backlog_rcv		= dccp_v4_do_rcv,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
913
914
  	.hash			= inet_hash,
  	.unhash			= inet_unhash,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
915
  	.accept			= inet_csk_accept,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
916
  	.get_port		= inet_csk_get_port,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
917
  	.shutdown		= dccp_shutdown,
3e0fadc51   Arnaldo Carvalho de Melo   [DCCP]: Move dccp...
918
  	.destroy		= dccp_destroy_sock,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
919
920
921
  	.orphan_count		= &dccp_orphan_count,
  	.max_header		= MAX_DCCP_HEADER,
  	.obj_size		= sizeof(struct dccp_sock),
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
922
  	.slab_flags		= SLAB_DESTROY_BY_RCU,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
923
  	.rsk_prot		= &dccp_request_sock_ops,
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
924
  	.twsk_prot		= &dccp_timewait_sock_ops,
39d8cda76   Pavel Emelyanov   [SOCK]: Add udp_h...
925
  	.h.hashinfo		= &dccp_hashinfo,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
926
927
928
929
  #ifdef CONFIG_COMPAT
  	.compat_setsockopt	= compat_dccp_setsockopt,
  	.compat_getsockopt	= compat_dccp_getsockopt,
  #endif
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
930
  };
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
931

32613090a   Alexey Dobriyan   net: constify str...
932
  static const struct net_protocol dccp_v4_protocol = {
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
933
934
935
  	.handler	= dccp_v4_rcv,
  	.err_handler	= dccp_v4_err,
  	.no_policy	= 1,
fc5f8580d   Pavel Emelyanov   [NETNS][DCCPV4]: ...
936
  	.netns_ok	= 1,
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
937
938
939
  };
  
  static const struct proto_ops inet_dccp_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
940
941
942
943
944
945
946
947
  	.family		   = PF_INET,
  	.owner		   = THIS_MODULE,
  	.release	   = inet_release,
  	.bind		   = inet_bind,
  	.connect	   = inet_stream_connect,
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = inet_accept,
  	.getname	   = inet_getname,
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
948
  	/* FIXME: work on tcp_poll to rename it to inet_csk_poll */
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
949
950
  	.poll		   = dccp_poll,
  	.ioctl		   = inet_ioctl,
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
951
  	/* FIXME: work on inet_listen to rename it to sock_common_listen */
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
952
953
954
955
956
957
958
959
  	.listen		   = inet_dccp_listen,
  	.shutdown	   = inet_shutdown,
  	.setsockopt	   = sock_common_setsockopt,
  	.getsockopt	   = sock_common_getsockopt,
  	.sendmsg	   = inet_sendmsg,
  	.recvmsg	   = sock_common_recvmsg,
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = sock_no_sendpage,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
960
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
961
962
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
963
  #endif
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
964
965
966
967
968
969
970
  };
  
  static struct inet_protosw dccp_v4_protosw = {
  	.type		= SOCK_DCCP,
  	.protocol	= IPPROTO_DCCP,
  	.prot		= &dccp_v4_prot,
  	.ops		= &inet_dccp_ops,
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
971
972
973
  	.no_check	= 0,
  	.flags		= INET_PROTOSW_ICSK,
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
974
  static int __net_init dccp_v4_init_net(struct net *net)
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
975
  {
d14a0ebda   Gerrit Renker   net-2.6 [Bug-Fix]...
976
977
  	if (dccp_hashinfo.bhash == NULL)
  		return -ESOCKTNOSUPPORT;
b76c4b27f   Pavel Emelyanov   [NETNS][DCCPV4]: ...
978

d14a0ebda   Gerrit Renker   net-2.6 [Bug-Fix]...
979
980
  	return inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET,
  				    SOCK_DCCP, IPPROTO_DCCP, net);
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
981
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
982
  static void __net_exit dccp_v4_exit_net(struct net *net)
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
983
  {
b76c4b27f   Pavel Emelyanov   [NETNS][DCCPV4]: ...
984
  	inet_ctl_sock_destroy(net->dccp.v4_ctl_sk);
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
985
986
987
988
989
990
  }
  
  static struct pernet_operations dccp_v4_ops = {
  	.init	= dccp_v4_init_net,
  	.exit	= dccp_v4_exit_net,
  };
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
991
992
993
994
995
996
997
998
999
1000
1001
1002
  static int __init dccp_v4_init(void)
  {
  	int err = proto_register(&dccp_v4_prot, 1);
  
  	if (err != 0)
  		goto out;
  
  	err = inet_add_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
  	if (err != 0)
  		goto out_proto_unregister;
  
  	inet_register_protosw(&dccp_v4_protosw);
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
1003
1004
1005
  	err = register_pernet_subsys(&dccp_v4_ops);
  	if (err)
  		goto out_destroy_ctl_sock;
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
1006
1007
  out:
  	return err;
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
1008
  out_destroy_ctl_sock:
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
1009
1010
1011
1012
1013
1014
1015
1016
1017
  	inet_unregister_protosw(&dccp_v4_protosw);
  	inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
  out_proto_unregister:
  	proto_unregister(&dccp_v4_prot);
  	goto out;
  }
  
  static void __exit dccp_v4_exit(void)
  {
72a2d6138   Pavel Emelyanov   [NETNS][DCCPV4]: ...
1018
  	unregister_pernet_subsys(&dccp_v4_ops);
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
  	inet_unregister_protosw(&dccp_v4_protosw);
  	inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
  	proto_unregister(&dccp_v4_prot);
  }
  
  module_init(dccp_v4_init);
  module_exit(dccp_v4_exit);
  
  /*
   * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
   * values directly, Also cover the case where the protocol is not specified,
   * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
   */
7131c6c73   Jean Delvare   [INET]: Use MODUL...
1032
1033
  MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6);
  MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6);
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
1034
1035
1036
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
  MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");