Blame view

net/dccp/ipv6.c 30.5 KB
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1
2
  /*
   *	DCCP over IPv6
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
3
   *	Linux INET6 implementation
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
4
5
6
7
8
9
10
11
12
13
   *
   *	Based on net/dccp6/ipv6.c
   *
   *	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
   *
   *	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.
   */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
14
15
  #include <linux/module.h>
  #include <linux/random.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/slab.h>
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
17
18
19
20
21
  #include <linux/xfrm.h>
  
  #include <net/addrconf.h>
  #include <net/inet_common.h>
  #include <net/inet_hashtables.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
22
  #include <net/inet_sock.h>
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
23
24
25
26
27
28
  #include <net/inet6_connection_sock.h>
  #include <net/inet6_hashtables.h>
  #include <net/ip6_route.h>
  #include <net/ipv6.h>
  #include <net/protocol.h>
  #include <net/transp_v6.h>
aa0e4e4ae   David S. Miller   [DCCP]: ipv6.c ne...
29
  #include <net/ip6_checksum.h>
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
30
  #include <net/xfrm.h>
6e5714eaf   David S. Miller   net: Compute prot...
31
  #include <net/secure_seq.h>
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
32
33
34
  
  #include "dccp.h"
  #include "ipv6.h"
4b79f0af4   Ian McDonald   [DCCP]: Fix defau...
35
  #include "feat.h"
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
36

13f51d82a   Pavel Emelyanov   [DCCP]: Fix comme...
37
  /* The per-net dccp.v6_ctl_sk is used for sending RSTs and ACKs */
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
38

3b401a81c   Stephen Hemminger   inet: inet_connec...
39
40
  static const struct inet_connection_sock_af_ops dccp_ipv6_mapped;
  static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
41

3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
42
43
44
45
  static void dccp_v6_hash(struct sock *sk)
  {
  	if (sk->sk_state != DCCP_CLOSED) {
  		if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
46
  			inet_hash(sk);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
47
48
49
  			return;
  		}
  		local_bh_disable();
9327f7053   Eric Dumazet   tcp: Fix a connec...
50
  		__inet6_hash(sk, NULL);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
51
52
53
  		local_bh_enable();
  	}
  }
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
54
  /* add pseudo-header to DCCP checksum stored in skb->csum */
868c86bcb   Al Viro   [NET]: annotate c...
55
  static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
b71d1d426   Eric Dumazet   inet: constify ip...
56
57
  				      const struct in6_addr *saddr,
  				      const struct in6_addr *daddr)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
58
  {
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
59
60
  	return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
  }
bb2962461   Herbert Xu   inet: Remove unus...
61
  static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
62
63
64
65
66
67
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct dccp_hdr *dh = dccp_hdr(skb);
  
  	dccp_csum_outgoing(skb);
  	dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
68
  }
6e5714eaf   David S. Miller   net: Compute prot...
69
  static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
d7f7365f5   Gerrit Renker   [DCCPv6]: Choose ...
70
  {
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
71
72
  	return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
  					     ipv6_hdr(skb)->saddr.s6_addr32,
d7f7365f5   Gerrit Renker   [DCCPv6]: Choose ...
73
74
  					     dccp_hdr(skb)->dccph_dport,
  					     dccp_hdr(skb)->dccph_sport     );
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
75
  }
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
76
  static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
d5fdd6bab   Brian Haley   ipv6: Use correct...
77
  			u8 type, u8 code, int offset, __be32 info)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
78
  {
b71d1d426   Eric Dumazet   inet: constify ip...
79
  	const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
80
  	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
e0bcfb0c6   Wei Yongjun   dccp: Add check f...
81
  	struct dccp_sock *dp;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
82
83
84
85
  	struct ipv6_pinfo *np;
  	struct sock *sk;
  	int err;
  	__u64 seq;
ca12a1a44   Pavel Emelyanov   inet: prepare net...
86
  	struct net *net = dev_net(skb->dev);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
87

860239c56   Wei Yongjun   dccp: Add check f...
88
89
  	if (skb->len < offset + sizeof(*dh) ||
  	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
e41b5368e   Denis V. Lunev   ipv6: added net a...
90
91
  		ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
  				   ICMP6_MIB_INERRORS);
860239c56   Wei Yongjun   dccp: Add check f...
92
93
  		return;
  	}
ca12a1a44   Pavel Emelyanov   inet: prepare net...
94
  	sk = inet6_lookup(net, &dccp_hashinfo,
671a1c740   Pavel Emelyanov   [NETNS][DCCPV6]: ...
95
  			&hdr->daddr, dh->dccph_dport,
d86e0dac2   Pavel Emelyanov   [NETNS]: Tcp-v6 s...
96
  			&hdr->saddr, dh->dccph_sport, inet6_iif(skb));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
97
98
  
  	if (sk == NULL) {
e41b5368e   Denis V. Lunev   ipv6: added net a...
99
100
  		ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
  				   ICMP6_MIB_INERRORS);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
101
102
103
104
  		return;
  	}
  
  	if (sk->sk_state == DCCP_TIME_WAIT) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
105
  		inet_twsk_put(inet_twsk(sk));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
106
107
108
109
110
  		return;
  	}
  
  	bh_lock_sock(sk);
  	if (sock_owned_by_user(sk))
de0744af1   Pavel Emelyanov   mib: add net to N...
111
  		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
112
113
114
  
  	if (sk->sk_state == DCCP_CLOSED)
  		goto out;
e0bcfb0c6   Wei Yongjun   dccp: Add check f...
115
116
117
118
119
120
121
  	dp = dccp_sk(sk);
  	seq = dccp_hdr_seq(dh);
  	if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
  	    !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
  		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
  		goto out;
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
122
  	np = inet6_sk(sk);
ec18d9a26   David S. Miller   ipv6: Add redirec...
123
124
  	if (type == NDISC_REDIRECT) {
  		struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
1ed5c48f2   David S. Miller   net: Remove check...
125
  		if (dst)
6700c2709   David S. Miller   net: Pass optiona...
126
  			dst->ops->redirect(dst, sk, skb);
f25e4f35d   Duan Jiong   net:dccp: do not ...
127
  		goto out;
ec18d9a26   David S. Miller   ipv6: Add redirec...
128
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
129
  	if (type == ICMPV6_PKT_TOOBIG) {
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
130
131
132
133
134
135
  		struct dst_entry *dst = NULL;
  
  		if (sock_owned_by_user(sk))
  			goto out;
  		if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED))
  			goto out;
35ad9b9cf   David S. Miller   ipv6: Add helper ...
136
137
138
139
140
  		dst = inet6_csk_update_pmtu(sk, ntohl(info));
  		if (!dst)
  			goto out;
  
  		if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst))
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
141
  			dccp_sync_mss(sk, dst_mtu(dst));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
142
143
144
145
  		goto out;
  	}
  
  	icmpv6_err_convert(type, code, &err);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
146
147
148
149
150
151
152
153
154
155
  	/* Might be for an request_sock */
  	switch (sk->sk_state) {
  		struct request_sock *req, **prev;
  	case DCCP_LISTEN:
  		if (sock_owned_by_user(sk))
  			goto out;
  
  		req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
  					   &hdr->daddr, &hdr->saddr,
  					   inet6_iif(skb));
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
156
  		if (req == NULL)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
157
  			goto out;
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
158
159
160
  		/*
  		 * ICMPs are not backlogged, hence we cannot get an established
  		 * socket here.
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
161
  		 */
547b792ca   Ilpo Järvinen   net: convert BUG_...
162
  		WARN_ON(req->sk != NULL);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
163

f541fb7e2   Samuel Jero   dccp: fix bug in ...
164
165
  		if (!between48(seq, dccp_rsk(req)->dreq_iss,
  				    dccp_rsk(req)->dreq_gss)) {
de0744af1   Pavel Emelyanov   mib: add net to N...
166
  			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
167
168
169
170
171
172
173
174
  			goto out;
  		}
  
  		inet_csk_reqsk_queue_drop(sk, req, prev);
  		goto out;
  
  	case DCCP_REQUESTING:
  	case DCCP_RESPOND:  /* Cannot happen.
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
175
  			       It can, it SYNs are crossed. --ANK */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
176
177
178
179
180
181
182
183
  		if (!sock_owned_by_user(sk)) {
  			DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
  			sk->sk_err = err;
  			/*
  			 * Wake people up to see the error
  			 * (see connect in sock.c)
  			 */
  			sk->sk_error_report(sk);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  			dccp_done(sk);
  		} else
  			sk->sk_err_soft = err;
  		goto out;
  	}
  
  	if (!sock_owned_by_user(sk) && np->recverr) {
  		sk->sk_err = err;
  		sk->sk_error_report(sk);
  	} else
  		sk->sk_err_soft = err;
  
  out:
  	bh_unlock_sock(sk);
  	sock_put(sk);
  }
1a2c6181c   Christoph Paasch   tcp: Remove TCPCT
200
  static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
201
202
203
204
  {
  	struct inet6_request_sock *ireq6 = inet6_rsk(req);
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct sk_buff *skb;
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
205
  	struct in6_addr *final_p, final;
4c9483b2f   David S. Miller   ipv6: Convert to ...
206
  	struct flowi6 fl6;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
207
  	int err = -1;
fd80eb942   Denis V. Lunev   [INET]: Remove st...
208
  	struct dst_entry *dst;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
209

4c9483b2f   David S. Miller   ipv6: Convert to ...
210
211
  	memset(&fl6, 0, sizeof(fl6));
  	fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
212
213
  	fl6.daddr = ireq6->rmt_addr;
  	fl6.saddr = ireq6->loc_addr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
214
215
  	fl6.flowlabel = 0;
  	fl6.flowi6_oif = ireq6->iif;
1958b856c   David S. Miller   net: Put fl6_* ma...
216
217
  	fl6.fl6_dport = inet_rsk(req)->rmt_port;
  	fl6.fl6_sport = inet_rsk(req)->loc_port;
4c9483b2f   David S. Miller   ipv6: Convert to ...
218
  	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
219

3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
220

0979e465c   RongQing.Li   dccp: remove unne...
221
  	final_p = fl6_update_dst(&fl6, np->opt, &final);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
222

4c9483b2f   David S. Miller   ipv6: Convert to ...
223
  	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
68d0c6d34   David S. Miller   ipv6: Consolidate...
224
225
226
  	if (IS_ERR(dst)) {
  		err = PTR_ERR(dst);
  		dst = NULL;
fd80eb942   Denis V. Lunev   [INET]: Remove st...
227
  		goto done;
68d0c6d34   David S. Miller   ipv6: Consolidate...
228
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
229
230
231
232
  
  	skb = dccp_make_response(sk, dst, req);
  	if (skb != NULL) {
  		struct dccp_hdr *dh = dccp_hdr(skb);
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
233

6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
234
235
236
  		dh->dccph_checksum = dccp_v6_csum_finish(skb,
  							 &ireq6->loc_addr,
  							 &ireq6->rmt_addr);
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
237
  		fl6.daddr = ireq6->rmt_addr;
0979e465c   RongQing.Li   dccp: remove unne...
238
  		err = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
239
  		err = net_xmit_eval(err);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
240
241
242
  	}
  
  done:
0cbd78250   David S. Miller   [DCCP] ipv6: dccp...
243
  	dst_release(dst);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
244
245
246
247
248
  	return err;
  }
  
  static void dccp_v6_reqsk_destructor(struct request_sock *req)
  {
d99a7bd21   Gerrit Renker   dccp: Cleanup rou...
249
  	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
250
251
252
  	if (inet6_rsk(req)->pktopts != NULL)
  		kfree_skb(inet6_rsk(req)->pktopts);
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
253
  static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
254
  {
b71d1d426   Eric Dumazet   inet: constify ip...
255
  	const struct ipv6hdr *rxip6h;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
256
  	struct sk_buff *skb;
4c9483b2f   David S. Miller   ipv6: Convert to ...
257
  	struct flowi6 fl6;
adf30907d   Eric Dumazet   net: skb->dst acc...
258
  	struct net *net = dev_net(skb_dst(rxskb)->dev);
334527d35   Pavel Emelyanov   [NETNS][DCCPV6]: ...
259
  	struct sock *ctl_sk = net->dccp.v6_ctl_sk;
adf30907d   Eric Dumazet   net: skb->dst acc...
260
  	struct dst_entry *dst;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
261

e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
262
  	if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
263
264
265
  		return;
  
  	if (!ipv6_unicast_destination(rxskb))
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
266
  		return;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
267

020477419   Pavel Emelyanov   [NETNS][DCCPV6]: ...
268
  	skb = dccp_ctl_make_reset(ctl_sk, rxskb);
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
269
  	if (skb == NULL)
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
270
  		return;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
271

0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
272
  	rxip6h = ipv6_hdr(rxskb);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
273
274
  	dccp_hdr(skb)->dccph_checksum = dccp_v6_csum_finish(skb, &rxip6h->saddr,
  							    &rxip6h->daddr);
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
275

4c9483b2f   David S. Miller   ipv6: Convert to ...
276
  	memset(&fl6, 0, sizeof(fl6));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
277
278
  	fl6.daddr = rxip6h->saddr;
  	fl6.saddr = rxip6h->daddr;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
279

4c9483b2f   David S. Miller   ipv6: Convert to ...
280
281
  	fl6.flowi6_proto = IPPROTO_DCCP;
  	fl6.flowi6_oif = inet6_iif(rxskb);
1958b856c   David S. Miller   net: Put fl6_* ma...
282
283
  	fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
  	fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
4c9483b2f   David S. Miller   ipv6: Convert to ...
284
  	security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
285
286
  
  	/* sk = NULL, but it is safe for now. RST socket required. */
4c9483b2f   David S. Miller   ipv6: Convert to ...
287
  	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
68d0c6d34   David S. Miller   ipv6: Consolidate...
288
289
  	if (!IS_ERR(dst)) {
  		skb_dst_set(skb, dst);
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
290
  		ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
68d0c6d34   David S. Miller   ipv6: Consolidate...
291
292
293
  		DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
  		DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
  		return;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
294
295
296
297
  	}
  
  	kfree_skb(skb);
  }
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
298
299
300
301
302
303
304
  static struct request_sock_ops dccp6_request_sock_ops = {
  	.family		= AF_INET6,
  	.obj_size	= sizeof(struct dccp6_request_sock),
  	.rtx_syn_ack	= dccp_v6_send_response,
  	.send_ack	= dccp_reqsk_send_ack,
  	.destructor	= dccp_v6_reqsk_destructor,
  	.send_reset	= dccp_v6_ctl_send_reset,
c72e11833   Eric Dumazet   inet: makes syn_a...
305
  	.syn_ack_timeout = dccp_syn_ack_timeout,
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
306
  };
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
307
308
309
  static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
  {
  	const struct dccp_hdr *dh = dccp_hdr(skb);
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
310
  	const struct ipv6hdr *iph = ipv6_hdr(skb);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
311
312
313
314
315
316
317
318
319
320
  	struct sock *nsk;
  	struct request_sock **prev;
  	/* Find possible connection requests. */
  	struct request_sock *req = inet6_csk_search_req(sk, &prev,
  							dh->dccph_sport,
  							&iph->saddr,
  							&iph->daddr,
  							inet6_iif(skb));
  	if (req != NULL)
  		return dccp_check_req(sk, skb, req, prev);
671a1c740   Pavel Emelyanov   [NETNS][DCCPV6]: ...
321
  	nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
322
323
324
  					 &iph->saddr, dh->dccph_sport,
  					 &iph->daddr, ntohs(dh->dccph_dport),
  					 inet6_iif(skb));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
325
326
327
328
329
  	if (nsk != NULL) {
  		if (nsk->sk_state != DCCP_TIME_WAIT) {
  			bh_lock_sock(nsk);
  			return nsk;
  		}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
330
  		inet_twsk_put(inet_twsk(nsk));
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
331
332
333
334
335
336
337
338
  		return NULL;
  	}
  
  	return sk;
  }
  
  static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
  {
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
339
340
341
342
  	struct request_sock *req;
  	struct dccp_request_sock *dreq;
  	struct inet6_request_sock *ireq6;
  	struct ipv6_pinfo *np = inet6_sk(sk);
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
343
  	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
344
  	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
345
346
347
348
349
  
  	if (skb->protocol == htons(ETH_P_IP))
  		return dccp_v4_conn_request(sk, skb);
  
  	if (!ipv6_unicast_destination(skb))
4a5409a5a   Gerrit Renker   [DCCP]: Twice the...
350
  		return 0;	/* discard, don't send a reset here */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
351
352
  
  	if (dccp_bad_service_code(sk, service)) {
4a5409a5a   Gerrit Renker   [DCCP]: Twice the...
353
  		dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
354
  		goto drop;
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
355
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
356
  	/*
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
357
  	 * There are no SYN attacks on IPv6, yet...
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
358
  	 */
4a5409a5a   Gerrit Renker   [DCCP]: Twice the...
359
  	dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
360
  	if (inet_csk_reqsk_queue_is_full(sk))
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
361
  		goto drop;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
362
363
364
  
  	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
  		goto drop;
82709531a   Gerrit Renker   [DCCP]: Fix Oops ...
365
  	req = inet6_reqsk_alloc(&dccp6_request_sock_ops);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
366
367
  	if (req == NULL)
  		goto drop;
ac75773c2   Gerrit Renker   dccp: Per-socket ...
368
369
  	if (dccp_reqsk_init(req, dccp_sk(sk), skb))
  		goto drop_and_free;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
370

8b8194124   Gerrit Renker   [DCCP]: Allow to ...
371
372
373
  	dreq = dccp_rsk(req);
  	if (dccp_parse_options(sk, dreq, skb))
  		goto drop_and_free;
4237c75c0   Venkat Yekkirala   [MLSXFRM]: Auto-l...
374
375
  	if (security_inet_conn_request(sk, skb, req))
  		goto drop_and_free;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
376
  	ireq6 = inet6_rsk(req);
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
377
378
  	ireq6->rmt_addr = ipv6_hdr(skb)->saddr;
  	ireq6->loc_addr = ipv6_hdr(skb)->daddr;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
379
380
381
382
383
384
385
386
387
388
389
390
391
  
  	if (ipv6_opt_accepted(sk, skb) ||
  	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
  	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
  		atomic_inc(&skb->users);
  		ireq6->pktopts = skb;
  	}
  	ireq6->iif = sk->sk_bound_dev_if;
  
  	/* So that link locals have meaning */
  	if (!sk->sk_bound_dev_if &&
  	    ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
  		ireq6->iif = inet6_iif(skb);
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
392
  	/*
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
393
394
  	 * Step 3: Process LISTEN state
  	 *
d83ca5acc   Gerrit Renker   [DCCP]: Update co...
395
  	 *   Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
396
  	 *
f541fb7e2   Samuel Jero   dccp: fix bug in ...
397
  	 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
398
  	 */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
399
  	dreq->dreq_isr	   = dcb->dccpd_seq;
f541fb7e2   Samuel Jero   dccp: fix bug in ...
400
  	dreq->dreq_gsr     = dreq->dreq_isr;
865e9022d   Gerrit Renker   [DCCP]: Remove re...
401
  	dreq->dreq_iss	   = dccp_v6_init_sequence(skb);
f541fb7e2   Samuel Jero   dccp: fix bug in ...
402
  	dreq->dreq_gss     = dreq->dreq_iss;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
403
  	dreq->dreq_service = service;
1a2c6181c   Christoph Paasch   tcp: Remove TCPCT
404
  	if (dccp_v6_send_response(sk, req))
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
405
406
407
408
409
410
411
412
413
  		goto drop_and_free;
  
  	inet6_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);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
414
415
416
417
418
419
420
421
422
423
424
  	return -1;
  }
  
  static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
  					      struct sk_buff *skb,
  					      struct request_sock *req,
  					      struct dst_entry *dst)
  {
  	struct inet6_request_sock *ireq6 = inet6_rsk(req);
  	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
  	struct inet_sock *newinet;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
425
426
  	struct dccp6_sock *newdp6;
  	struct sock *newsk;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
427
428
429
430
431
  
  	if (skb->protocol == htons(ETH_P_IP)) {
  		/*
  		 *	v6 mapped
  		 */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
432
  		newsk = dccp_v4_request_recv_sock(sk, skb, req, dst);
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
433
  		if (newsk == NULL)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
434
435
436
  			return NULL;
  
  		newdp6 = (struct dccp6_sock *)newsk;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
437
438
439
440
441
  		newinet = inet_sk(newsk);
  		newinet->pinet6 = &newdp6->inet6;
  		newnp = inet6_sk(newsk);
  
  		memcpy(newnp, np, sizeof(struct ipv6_pinfo));
c720c7e83   Eric Dumazet   inet: rename some...
442
  		ipv6_addr_set_v4mapped(newinet->inet_daddr, &newnp->daddr);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
443

c720c7e83   Eric Dumazet   inet: rename some...
444
  		ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
445

4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
446
  		newnp->rcv_saddr = newnp->saddr;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
447
448
449
450
451
452
  
  		inet_csk(newsk)->icsk_af_ops = &dccp_ipv6_mapped;
  		newsk->sk_backlog_rcv = dccp_v4_do_rcv;
  		newnp->pktoptions  = NULL;
  		newnp->opt	   = NULL;
  		newnp->mcast_oif   = inet6_iif(skb);
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
453
  		newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
454
455
456
457
458
459
460
461
462
463
464
  
  		/*
  		 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
  		 * here, dccp_create_openreq_child now does this for us, see the comment in
  		 * that function for the gory details. -acme
  		 */
  
  		/* It is tricky place. Until this moment IPv4 tcp
  		   worked with IPv6 icsk.icsk_af_ops.
  		   Sync it now.
  		 */
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
465
  		dccp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
466
467
468
  
  		return newsk;
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
469
470
471
  
  	if (sk_acceptq_is_full(sk))
  		goto out_overflow;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
472
  	if (dst == NULL) {
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
473
  		struct in6_addr *final_p, final;
4c9483b2f   David S. Miller   ipv6: Convert to ...
474
475
476
477
  		struct flowi6 fl6;
  
  		memset(&fl6, 0, sizeof(fl6));
  		fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
478
  		fl6.daddr = ireq6->rmt_addr;
0979e465c   RongQing.Li   dccp: remove unne...
479
  		final_p = fl6_update_dst(&fl6, np->opt, &final);
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
480
  		fl6.saddr = ireq6->loc_addr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
481
  		fl6.flowi6_oif = sk->sk_bound_dev_if;
1958b856c   David S. Miller   net: Put fl6_* ma...
482
483
  		fl6.fl6_dport = inet_rsk(req)->rmt_port;
  		fl6.fl6_sport = inet_rsk(req)->loc_port;
4c9483b2f   David S. Miller   ipv6: Convert to ...
484
485
486
  		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
  
  		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
68d0c6d34   David S. Miller   ipv6: Consolidate...
487
  		if (IS_ERR(dst))
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
488
  			goto out;
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
489
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
490
491
492
  
  	newsk = dccp_create_openreq_child(sk, req, skb);
  	if (newsk == NULL)
093d28232   Balazs Scheidler   tproxy: fix hash ...
493
  		goto out_nonewsk;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
494
495
496
497
498
499
  
  	/*
  	 * No need to charge this sock to the relevant IPv6 refcnt debug socks
  	 * count here, dccp_create_openreq_child now does this for us, see the
  	 * comment in that function for the gory details. -acme
  	 */
8e1ef0a95   YOSHIFUJI Hideaki   [IPV6]: Cache sou...
500
  	__ip6_dst_store(newsk, dst, NULL, NULL);
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
501
502
  	newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
  						      NETIF_F_TSO);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
503
504
505
  	newdp6 = (struct dccp6_sock *)newsk;
  	newinet = inet_sk(newsk);
  	newinet->pinet6 = &newdp6->inet6;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
506
507
508
  	newnp = inet6_sk(newsk);
  
  	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
509
510
511
  	newnp->daddr = ireq6->rmt_addr;
  	newnp->saddr = ireq6->loc_addr;
  	newnp->rcv_saddr = ireq6->loc_addr;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
512
  	newsk->sk_bound_dev_if = ireq6->iif;
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
513
  	/* Now IPv6 options...
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
514
515
516
  
  	   First: no IPv4 options.
  	 */
f6d8bd051   Eric Dumazet   inet: add RCU pro...
517
  	newinet->inet_opt = NULL;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
518
519
520
521
522
523
524
525
  
  	/* Clone RX bits */
  	newnp->rxopt.all = np->rxopt.all;
  
  	/* Clone pktoptions received with SYN */
  	newnp->pktoptions = NULL;
  	if (ireq6->pktopts != NULL) {
  		newnp->pktoptions = skb_clone(ireq6->pktopts, GFP_ATOMIC);
7604adc2f   Eric Dumazet   ipv6: dccp: dont ...
526
  		consume_skb(ireq6->pktopts);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
527
528
529
530
531
532
  		ireq6->pktopts = NULL;
  		if (newnp->pktoptions)
  			skb_set_owner_r(newnp->pktoptions, newsk);
  	}
  	newnp->opt	  = NULL;
  	newnp->mcast_oif  = inet6_iif(skb);
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
533
  	newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
534

45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
535
536
537
538
539
  	/*
  	 * Clone native IPv6 options from listening socket (if any)
  	 *
  	 * Yes, keeping reference count would be much more clever, but we make
  	 * one more one thing there: reattach optmem to newsk.
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
540
  	 */
0979e465c   RongQing.Li   dccp: remove unne...
541
542
  	if (np->opt != NULL)
  		newnp->opt = ipv6_dup_options(newsk, np->opt);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
543

d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
544
  	inet_csk(newsk)->icsk_ext_hdr_len = 0;
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
545
  	if (newnp->opt != NULL)
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
546
547
  		inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
  						     newnp->opt->opt_flen);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
548
549
  
  	dccp_sync_mss(newsk, dst_mtu(dst));
c720c7e83   Eric Dumazet   inet: rename some...
550
551
  	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
  	newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
552

093d28232   Balazs Scheidler   tproxy: fix hash ...
553
  	if (__inet_inherit_port(sk, newsk) < 0) {
e337e24d6   Christoph Paasch   inet: Fix kmemlea...
554
555
  		inet_csk_prepare_forced_close(newsk);
  		dccp_done(newsk);
093d28232   Balazs Scheidler   tproxy: fix hash ...
556
557
  		goto out;
  	}
9327f7053   Eric Dumazet   tcp: Fix a connec...
558
  	__inet6_hash(newsk, NULL);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
559
560
561
562
  
  	return newsk;
  
  out_overflow:
de0744af1   Pavel Emelyanov   mib: add net to N...
563
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
093d28232   Balazs Scheidler   tproxy: fix hash ...
564
565
  out_nonewsk:
  	dst_release(dst);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
566
  out:
de0744af1   Pavel Emelyanov   mib: add net to N...
567
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  	return NULL;
  }
  
  /* The socket must have it's spinlock held when we get
   * here.
   *
   * We have a potential double-lock case here, so even when
   * doing backlog processing we use the BH locking scheme.
   * This is because we cannot sleep with the original spinlock
   * held.
   */
  static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct sk_buff *opt_skb = NULL;
  
  	/* Imagine: socket is IPv6. IPv4 packet arrives,
  	   goes to IPv4 receive handler and backlogged.
  	   From backlog it always goes here. Kerboom...
  	   Fortunately, dccp_rcv_established and rcv_established
  	   handle them correctly, but it is not case with
  	   dccp_v6_hnd_req and dccp_v6_ctl_send_reset().   --ANK
  	 */
  
  	if (skb->protocol == htons(ETH_P_IP))
  		return dccp_v4_do_rcv(sk, skb);
fda9ef5d6   Dmitry Mishin   [NET]: Fix sk->sk...
594
  	if (sk_filter(sk, skb))
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
595
596
597
  		goto discard;
  
  	/*
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
598
599
  	 * socket locking is here for SMP purposes as backlog rcv is currently
  	 * called with bh processing disabled.
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
600
601
602
603
604
605
606
607
608
609
610
611
612
  	 */
  
  	/* Do Stevens' IPV6_PKTOPTIONS.
  
  	   Yes, guys, it is the only place in our code, where we
  	   may make it not affecting IPv4.
  	   The rest of code is protocol independent,
  	   and I do not like idea to uglify IPv4.
  
  	   Actually, all the idea behind IPV6_PKTOPTIONS
  	   looks not very well thought. For now we latch
  	   options, received in the last packet, enqueued
  	   by tcp. Feel free to propose better solution.
c9eaf1734   YOSHIFUJI Hideaki   [NET] DCCP: Fix w...
613
  					       --ANK (980728)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
614
615
  	 */
  	if (np->rxopt.all)
89e7e5777   Gerrit Renker   [DCCPv6]: Add a F...
616
617
618
619
  	/*
  	 * FIXME: Add handling of IPV6_PKTOPTIONS skb. See the comments below
  	 *        (wrt ipv6_pktopions) and net/ipv6/tcp_ipv6.c for an example.
  	 */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
620
621
622
623
624
  		opt_skb = skb_clone(skb, GFP_ATOMIC);
  
  	if (sk->sk_state == DCCP_OPEN) { /* Fast path */
  		if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
  			goto reset;
fd169f15a   David S. Miller   [DCCP] ipv6: Fix ...
625
  		if (opt_skb) {
89e7e5777   Gerrit Renker   [DCCPv6]: Add a F...
626
  			/* XXX This is where we would goto ipv6_pktoptions. */
fd169f15a   David S. Miller   [DCCP] ipv6: Fix ...
627
628
  			__kfree_skb(opt_skb);
  		}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
629
630
  		return 0;
  	}
d83ca5acc   Gerrit Renker   [DCCP]: Update co...
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
  	/*
  	 *  Step 3: Process LISTEN state
  	 *     If S.state == LISTEN,
  	 *	 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
  	 *
  	 * NOTE: the check for the packet types is done in
  	 *	 dccp_rcv_state_process
  	 */
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
655
  	if (sk->sk_state == DCCP_LISTEN) {
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
656
  		struct sock *nsk = dccp_v6_hnd_req(sk, skb);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
657

45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
658
659
  		if (nsk == NULL)
  			goto discard;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
660
661
662
663
664
  		/*
  		 * Queue it on the new socket if the new socket is active,
  		 * otherwise we just shortcircuit this and continue with
  		 * the new socket..
  		 */
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
665
  		if (nsk != sk) {
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
666
667
  			if (dccp_child_process(sk, nsk, skb))
  				goto reset;
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
668
  			if (opt_skb != NULL)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
669
670
671
672
673
674
675
  				__kfree_skb(opt_skb);
  			return 0;
  		}
  	}
  
  	if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
  		goto reset;
fd169f15a   David S. Miller   [DCCP] ipv6: Fix ...
676
  	if (opt_skb) {
89e7e5777   Gerrit Renker   [DCCPv6]: Add a F...
677
  		/* XXX This is where we would goto ipv6_pktoptions. */
fd169f15a   David S. Miller   [DCCP] ipv6: Fix ...
678
679
  		__kfree_skb(opt_skb);
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
680
681
682
  	return 0;
  
  reset:
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
683
  	dccp_v6_ctl_send_reset(sk, skb);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
684
  discard:
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
685
  	if (opt_skb != NULL)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
686
687
688
689
  		__kfree_skb(opt_skb);
  	kfree_skb(skb);
  	return 0;
  }
e5bbef20e   Herbert Xu   [IPV6]: Replace s...
690
  static int dccp_v6_rcv(struct sk_buff *skb)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
691
692
  {
  	const struct dccp_hdr *dh;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
693
  	struct sock *sk;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
694
  	int min_cov;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
695

6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
696
  	/* Step 1: Check header basics */
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
697
698
699
  
  	if (dccp_invalid_packet(skb))
  		goto discard_it;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
700
  	/* Step 1: If header checksum is incorrect, drop packet and return. */
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
701
702
  	if (dccp_v6_csum_finish(skb, &ipv6_hdr(skb)->saddr,
  				     &ipv6_hdr(skb)->daddr)) {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
703
704
  		DCCP_WARN("dropped packet with invalid checksum
  ");
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
705
706
  		goto discard_it;
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
707
  	dh = dccp_hdr(skb);
fde20105f   Gerrit Renker   [DCCP]: Retrieve ...
708
  	DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(dh);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
709
710
711
712
713
714
715
716
  	DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
  
  	if (dccp_packet_without_ack(skb))
  		DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
  	else
  		DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
  
  	/* Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
717
  	 *	Look up flow ID in table and get corresponding socket */
9a1f27c48   Arnaldo Carvalho de Melo   inet_hashtables: ...
718
719
  	sk = __inet6_lookup_skb(&dccp_hashinfo, skb,
  			        dh->dccph_sport, dh->dccph_dport);
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
720
  	/*
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
721
  	 * Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
722
  	 *	If no socket ...
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
723
  	 */
d23c7107b   Gerrit Renker   [DCCP]: Simplify ...
724
725
726
727
  	if (sk == NULL) {
  		dccp_pr_debug("failed to look up flow ID in table and "
  			      "get corresponding socket
  ");
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
728
  		goto no_dccp_socket;
d23c7107b   Gerrit Renker   [DCCP]: Simplify ...
729
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
730

45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
731
  	/*
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
732
  	 * Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
733
  	 *	... or S.state == TIMEWAIT,
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
734
735
736
  	 *		Generate Reset(No Connection) unless P.type == Reset
  	 *		Drop packet and return
  	 */
d23c7107b   Gerrit Renker   [DCCP]: Simplify ...
737
738
739
740
741
742
  	if (sk->sk_state == DCCP_TIME_WAIT) {
  		dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait
  ");
  		inet_twsk_put(inet_twsk(sk));
  		goto no_dccp_socket;
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
743

6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
744
745
  	/*
  	 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
746
747
  	 *	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...
748
749
750
751
752
753
754
755
756
  	 */
  	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: send Data Dropped option (see also dccp_v4_rcv) */
  		goto discard_and_relse;
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
757
758
  	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
  		goto discard_and_relse;
58a5a7b95   Arnaldo Carvalho de Melo   [NET]: Conditiona...
759
  	return sk_receive_skb(sk, skb, 1) ? -1 : 0;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
760
761
762
763
764
765
  
  no_dccp_socket:
  	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
  		goto discard_it;
  	/*
  	 * Step 2:
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
766
  	 *	If no socket ...
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
767
768
769
770
771
772
  	 *		Generate Reset(No Connection) unless P.type == Reset
  	 *		Drop packet and return
  	 */
  	if (dh->dccph_type != DCCP_PKT_RESET) {
  		DCCP_SKB_CB(skb)->dccpd_reset_code =
  					DCCP_RESET_CODE_NO_CONNECTION;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
773
  		dccp_v6_ctl_send_reset(sk, skb);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
774
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
775

d23c7107b   Gerrit Renker   [DCCP]: Simplify ...
776
  discard_it:
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
777
778
779
780
781
782
  	kfree_skb(skb);
  	return 0;
  
  discard_and_relse:
  	sock_put(sk);
  	goto discard_it;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
783
  }
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
784
785
786
787
788
789
790
791
  static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
  			   int addr_len)
  {
  	struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
  	struct inet_connection_sock *icsk = inet_csk(sk);
  	struct inet_sock *inet = inet_sk(sk);
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct dccp_sock *dp = dccp_sk(sk);
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
792
  	struct in6_addr *saddr = NULL, *final_p, final;
4c9483b2f   David S. Miller   ipv6: Convert to ...
793
  	struct flowi6 fl6;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
794
795
796
797
798
799
800
801
802
803
804
  	struct dst_entry *dst;
  	int addr_type;
  	int err;
  
  	dp->dccps_role = DCCP_ROLE_CLIENT;
  
  	if (addr_len < SIN6_LEN_RFC2133)
  		return -EINVAL;
  
  	if (usin->sin6_family != AF_INET6)
  		return -EAFNOSUPPORT;
4c9483b2f   David S. Miller   ipv6: Convert to ...
805
  	memset(&fl6, 0, sizeof(fl6));
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
806
807
  
  	if (np->sndflow) {
4c9483b2f   David S. Miller   ipv6: Convert to ...
808
809
810
  		fl6.flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
  		IP6_ECN_flow_init(fl6.flowlabel);
  		if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
811
  			struct ip6_flowlabel *flowlabel;
4c9483b2f   David S. Miller   ipv6: Convert to ...
812
  			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
813
814
  			if (flowlabel == NULL)
  				return -EINVAL;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
815
  			usin->sin6_addr = flowlabel->dst;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
  			fl6_sock_release(flowlabel);
  		}
  	}
  	/*
  	 * connect() to INADDR_ANY means loopback (BSD'ism).
  	 */
  	if (ipv6_addr_any(&usin->sin6_addr))
  		usin->sin6_addr.s6_addr[15] = 1;
  
  	addr_type = ipv6_addr_type(&usin->sin6_addr);
  
  	if (addr_type & IPV6_ADDR_MULTICAST)
  		return -ENETUNREACH;
  
  	if (addr_type & IPV6_ADDR_LINKLOCAL) {
  		if (addr_len >= sizeof(struct sockaddr_in6) &&
  		    usin->sin6_scope_id) {
  			/* If interface is set while binding, indices
  			 * must coincide.
  			 */
  			if (sk->sk_bound_dev_if &&
  			    sk->sk_bound_dev_if != usin->sin6_scope_id)
  				return -EINVAL;
  
  			sk->sk_bound_dev_if = usin->sin6_scope_id;
  		}
  
  		/* Connect to link-local address requires an interface */
  		if (!sk->sk_bound_dev_if)
  			return -EINVAL;
  	}
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
847
  	np->daddr = usin->sin6_addr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
848
  	np->flow_label = fl6.flowlabel;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
  
  	/*
  	 * DCCP over IPv4
  	 */
  	if (addr_type == IPV6_ADDR_MAPPED) {
  		u32 exthdrlen = icsk->icsk_ext_hdr_len;
  		struct sockaddr_in sin;
  
  		SOCK_DEBUG(sk, "connect: ipv4 mapped
  ");
  
  		if (__ipv6_only_sock(sk))
  			return -ENETUNREACH;
  
  		sin.sin_family = AF_INET;
  		sin.sin_port = usin->sin6_port;
  		sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
  
  		icsk->icsk_af_ops = &dccp_ipv6_mapped;
  		sk->sk_backlog_rcv = dccp_v4_do_rcv;
  
  		err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
  		if (err) {
  			icsk->icsk_ext_hdr_len = exthdrlen;
  			icsk->icsk_af_ops = &dccp_ipv6_af_ops;
  			sk->sk_backlog_rcv = dccp_v6_do_rcv;
  			goto failure;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
876
  		}
c720c7e83   Eric Dumazet   inet: rename some...
877
878
  		ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
  		ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, &np->rcv_saddr);
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
879
880
881
882
883
884
  
  		return err;
  	}
  
  	if (!ipv6_addr_any(&np->rcv_saddr))
  		saddr = &np->rcv_saddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
885
  	fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
886
887
  	fl6.daddr = np->daddr;
  	fl6.saddr = saddr ? *saddr : np->saddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
888
  	fl6.flowi6_oif = sk->sk_bound_dev_if;
1958b856c   David S. Miller   net: Put fl6_* ma...
889
890
  	fl6.fl6_dport = usin->sin6_port;
  	fl6.fl6_sport = inet->inet_sport;
4c9483b2f   David S. Miller   ipv6: Convert to ...
891
  	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
892

4c9483b2f   David S. Miller   ipv6: Convert to ...
893
  	final_p = fl6_update_dst(&fl6, np->opt, &final);
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
894

4c9483b2f   David S. Miller   ipv6: Convert to ...
895
  	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
68d0c6d34   David S. Miller   ipv6: Consolidate...
896
897
  	if (IS_ERR(dst)) {
  		err = PTR_ERR(dst);
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
898
  		goto failure;
14e50e57a   David S. Miller   [XFRM]: Allow pac...
899
  	}
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
900
901
  
  	if (saddr == NULL) {
4c9483b2f   David S. Miller   ipv6: Convert to ...
902
  		saddr = &fl6.saddr;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
903
  		np->rcv_saddr = *saddr;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
904
905
906
  	}
  
  	/* set the source address */
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
907
  	np->saddr = *saddr;
c720c7e83   Eric Dumazet   inet: rename some...
908
  	inet->inet_rcv_saddr = LOOPBACK4_IPV6;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
909
910
911
912
913
914
915
  
  	__ip6_dst_store(sk, dst, NULL, NULL);
  
  	icsk->icsk_ext_hdr_len = 0;
  	if (np->opt != NULL)
  		icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
  					  np->opt->opt_nflen);
c720c7e83   Eric Dumazet   inet: rename some...
916
  	inet->inet_dport = usin->sin6_port;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
917
918
919
920
921
  
  	dccp_set_state(sk, DCCP_REQUESTING);
  	err = inet6_hash_connect(&dccp_death_row, sk);
  	if (err)
  		goto late_failure;
d7f7365f5   Gerrit Renker   [DCCPv6]: Choose ...
922
923
924
  
  	dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32,
  						      np->daddr.s6_addr32,
c720c7e83   Eric Dumazet   inet: rename some...
925
926
  						      inet->inet_sport,
  						      inet->inet_dport);
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
927
928
929
930
931
932
933
934
935
936
  	err = dccp_connect(sk);
  	if (err)
  		goto late_failure;
  
  	return 0;
  
  late_failure:
  	dccp_set_state(sk, DCCP_CLOSED);
  	__sk_dst_reset(sk);
  failure:
c720c7e83   Eric Dumazet   inet: rename some...
937
  	inet->inet_dport = 0;
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
938
939
940
  	sk->sk_route_caps = 0;
  	return err;
  }
3b401a81c   Stephen Hemminger   inet: inet_connec...
941
  static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
942
943
944
945
946
947
948
949
950
951
  	.queue_xmit	   = inet6_csk_xmit,
  	.send_check	   = dccp_v6_send_check,
  	.rebuild_header	   = inet6_sk_rebuild_header,
  	.conn_request	   = dccp_v6_conn_request,
  	.syn_recv_sock	   = dccp_v6_request_recv_sock,
  	.net_header_len	   = sizeof(struct ipv6hdr),
  	.setsockopt	   = ipv6_setsockopt,
  	.getsockopt	   = ipv6_getsockopt,
  	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
  	.sockaddr_len	   = sizeof(struct sockaddr_in6),
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
952
  	.bind_conflict	   = inet6_csk_bind_conflict,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
953
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
954
955
  	.compat_setsockopt = compat_ipv6_setsockopt,
  	.compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
956
  #endif
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
957
958
959
960
961
  };
  
  /*
   *	DCCP over IPv4 via INET6 API
   */
3b401a81c   Stephen Hemminger   inet: inet_connec...
962
  static const struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
963
964
965
966
967
968
969
970
971
972
  	.queue_xmit	   = ip_queue_xmit,
  	.send_check	   = dccp_v4_send_check,
  	.rebuild_header	   = inet_sk_rebuild_header,
  	.conn_request	   = dccp_v6_conn_request,
  	.syn_recv_sock	   = dccp_v6_request_recv_sock,
  	.net_header_len	   = sizeof(struct iphdr),
  	.setsockopt	   = ipv6_setsockopt,
  	.getsockopt	   = ipv6_getsockopt,
  	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
  	.sockaddr_len	   = sizeof(struct sockaddr_in6),
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
973
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
974
975
  	.compat_setsockopt = compat_ipv6_setsockopt,
  	.compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
976
  #endif
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
977
978
979
980
981
982
983
  };
  
  /* NOTE: A lot of things set to zero explicitly by call to
   *       sk_alloc() so need not be done here.
   */
  static int dccp_v6_init_sock(struct sock *sk)
  {
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
984
985
  	static __u8 dccp_v6_ctl_sock_initialized;
  	int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
986

724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
987
988
989
  	if (err == 0) {
  		if (unlikely(!dccp_v6_ctl_sock_initialized))
  			dccp_v6_ctl_sock_initialized = 1;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
990
  		inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
991
  	}
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
992
993
994
  
  	return err;
  }
7d06b2e05   Brian Haley   net: change proto...
995
  static void dccp_v6_destroy_sock(struct sock *sk)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
996
  {
3e0fadc51   Arnaldo Carvalho de Melo   [DCCP]: Move dccp...
997
  	dccp_destroy_sock(sk);
7d06b2e05   Brian Haley   net: change proto...
998
  	inet6_destroy_sock(sk);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
999
  }
73c9e02c2   Gerrit Renker   [DCCPv6]: remove ...
1000
1001
1002
  static struct timewait_sock_ops dccp6_timewait_sock_ops = {
  	.twsk_obj_size	= sizeof(struct dccp6_timewait_sock),
  };
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1003
  static struct proto dccp_v6_prot = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  	.name		   = "DCCPv6",
  	.owner		   = THIS_MODULE,
  	.close		   = dccp_close,
  	.connect	   = dccp_v6_connect,
  	.disconnect	   = dccp_disconnect,
  	.ioctl		   = dccp_ioctl,
  	.init		   = dccp_v6_init_sock,
  	.setsockopt	   = dccp_setsockopt,
  	.getsockopt	   = dccp_getsockopt,
  	.sendmsg	   = dccp_sendmsg,
  	.recvmsg	   = dccp_recvmsg,
  	.backlog_rcv	   = dccp_v6_do_rcv,
  	.hash		   = dccp_v6_hash,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1017
  	.unhash		   = inet_unhash,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1018
  	.accept		   = inet_csk_accept,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1019
  	.get_port	   = inet_csk_get_port,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1020
1021
1022
1023
1024
  	.shutdown	   = dccp_shutdown,
  	.destroy	   = dccp_v6_destroy_sock,
  	.orphan_count	   = &dccp_orphan_count,
  	.max_header	   = MAX_DCCP_HEADER,
  	.obj_size	   = sizeof(struct dccp6_sock),
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1025
  	.slab_flags	   = SLAB_DESTROY_BY_RCU,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1026
1027
  	.rsk_prot	   = &dccp6_request_sock_ops,
  	.twsk_prot	   = &dccp6_timewait_sock_ops,
39d8cda76   Pavel Emelyanov   [SOCK]: Add udp_h...
1028
  	.h.hashinfo	   = &dccp_hashinfo,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1029
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1030
1031
  	.compat_setsockopt = compat_dccp_setsockopt,
  	.compat_getsockopt = compat_dccp_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1032
  #endif
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1033
  };
41135cc83   Alexey Dobriyan   net: constify str...
1034
  static const struct inet6_protocol dccp_v6_protocol = {
45329e71e   Arnaldo Carvalho de Melo   [DCCP] ipv6: clea...
1035
1036
1037
  	.handler	= dccp_v6_rcv,
  	.err_handler	= dccp_v6_err,
  	.flags		= INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1038
  };
5708e868d   Alexey Dobriyan   net: constify rem...
1039
  static const struct proto_ops inet6_dccp_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
  	.family		   = PF_INET6,
  	.owner		   = THIS_MODULE,
  	.release	   = inet6_release,
  	.bind		   = inet6_bind,
  	.connect	   = inet_stream_connect,
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = inet_accept,
  	.getname	   = inet6_getname,
  	.poll		   = dccp_poll,
  	.ioctl		   = inet6_ioctl,
  	.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...
1058
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1059
1060
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1061
  #endif
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1062
1063
1064
1065
1066
1067
1068
  };
  
  static struct inet_protosw dccp_v6_protosw = {
  	.type		= SOCK_DCCP,
  	.protocol	= IPPROTO_DCCP,
  	.prot		= &dccp_v6_prot,
  	.ops		= &inet6_dccp_ops,
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1069
  	.flags		= INET_PROTOSW_ICSK,
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1070
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
1071
  static int __net_init dccp_v6_init_net(struct net *net)
8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1072
  {
d14a0ebda   Gerrit Renker   net-2.6 [Bug-Fix]...
1073
1074
  	if (dccp_hashinfo.bhash == NULL)
  		return -ESOCKTNOSUPPORT;
334527d35   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1075

d14a0ebda   Gerrit Renker   net-2.6 [Bug-Fix]...
1076
1077
  	return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
  				    SOCK_DCCP, IPPROTO_DCCP, net);
8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1078
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
1079
  static void __net_exit dccp_v6_exit_net(struct net *net)
8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1080
  {
334527d35   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1081
  	inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1082
1083
1084
1085
1086
1087
  }
  
  static struct pernet_operations dccp_v6_ops = {
  	.init   = dccp_v6_init_net,
  	.exit   = dccp_v6_exit_net,
  };
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  static int __init dccp_v6_init(void)
  {
  	int err = proto_register(&dccp_v6_prot, 1);
  
  	if (err != 0)
  		goto out;
  
  	err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
  	if (err != 0)
  		goto out_unregister_proto;
  
  	inet6_register_protosw(&dccp_v6_protosw);
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
1100

8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1101
1102
1103
  	err = register_pernet_subsys(&dccp_v6_ops);
  	if (err != 0)
  		goto out_destroy_ctl_sock;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1104
1105
  out:
  	return err;
8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1106
1107
  
  out_destroy_ctl_sock:
724788735   Arnaldo Carvalho de Melo   [DCCP] ipv6: Add ...
1108
1109
  	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
  	inet6_unregister_protosw(&dccp_v6_protosw);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1110
1111
1112
1113
1114
1115
1116
  out_unregister_proto:
  	proto_unregister(&dccp_v6_prot);
  	goto out;
  }
  
  static void __exit dccp_v6_exit(void)
  {
8231bd270   Pavel Emelyanov   [NETNS][DCCPV6]: ...
1117
  	unregister_pernet_subsys(&dccp_v6_ops);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
  	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
  	inet6_unregister_protosw(&dccp_v6_protosw);
  	proto_unregister(&dccp_v6_prot);
  }
  
  module_init(dccp_v6_init);
  module_exit(dccp_v6_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_INET6-proto-0-type-SOCK_DCCP
   */
7131c6c73   Jean Delvare   [INET]: Use MODUL...
1131
1132
  MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6);
  MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6);
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
1133
1134
1135
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
  MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");