xref: /OK3568_Linux_fs/kernel/net/dccp/ipv6.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *	DCCP over IPv6
4*4882a593Smuzhiyun  *	Linux INET6 implementation
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *	Based on net/dccp6/ipv6.c
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/random.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/xfrm.h>
15*4882a593Smuzhiyun #include <linux/string.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <net/addrconf.h>
18*4882a593Smuzhiyun #include <net/inet_common.h>
19*4882a593Smuzhiyun #include <net/inet_hashtables.h>
20*4882a593Smuzhiyun #include <net/inet_sock.h>
21*4882a593Smuzhiyun #include <net/inet6_connection_sock.h>
22*4882a593Smuzhiyun #include <net/inet6_hashtables.h>
23*4882a593Smuzhiyun #include <net/ip6_route.h>
24*4882a593Smuzhiyun #include <net/ipv6.h>
25*4882a593Smuzhiyun #include <net/protocol.h>
26*4882a593Smuzhiyun #include <net/transp_v6.h>
27*4882a593Smuzhiyun #include <net/ip6_checksum.h>
28*4882a593Smuzhiyun #include <net/xfrm.h>
29*4882a593Smuzhiyun #include <net/secure_seq.h>
30*4882a593Smuzhiyun #include <net/sock.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "dccp.h"
33*4882a593Smuzhiyun #include "ipv6.h"
34*4882a593Smuzhiyun #include "feat.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /* The per-net dccp.v6_ctl_sk is used for sending RSTs and ACKs */
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static const struct inet_connection_sock_af_ops dccp_ipv6_mapped;
39*4882a593Smuzhiyun static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /* add pseudo-header to DCCP checksum stored in skb->csum */
dccp_v6_csum_finish(struct sk_buff * skb,const struct in6_addr * saddr,const struct in6_addr * daddr)42*4882a593Smuzhiyun static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
43*4882a593Smuzhiyun 				      const struct in6_addr *saddr,
44*4882a593Smuzhiyun 				      const struct in6_addr *daddr)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
dccp_v6_send_check(struct sock * sk,struct sk_buff * skb)49*4882a593Smuzhiyun static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct ipv6_pinfo *np = inet6_sk(sk);
52*4882a593Smuzhiyun 	struct dccp_hdr *dh = dccp_hdr(skb);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	dccp_csum_outgoing(skb);
55*4882a593Smuzhiyun 	dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &sk->sk_v6_daddr);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
dccp_v6_init_sequence(struct sk_buff * skb)58*4882a593Smuzhiyun static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
61*4882a593Smuzhiyun 					     ipv6_hdr(skb)->saddr.s6_addr32,
62*4882a593Smuzhiyun 					     dccp_hdr(skb)->dccph_dport,
63*4882a593Smuzhiyun 					     dccp_hdr(skb)->dccph_sport     );
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
dccp_v6_err(struct sk_buff * skb,struct inet6_skb_parm * opt,u8 type,u8 code,int offset,__be32 info)67*4882a593Smuzhiyun static int dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
68*4882a593Smuzhiyun 			u8 type, u8 code, int offset, __be32 info)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
71*4882a593Smuzhiyun 	const struct dccp_hdr *dh;
72*4882a593Smuzhiyun 	struct dccp_sock *dp;
73*4882a593Smuzhiyun 	struct ipv6_pinfo *np;
74*4882a593Smuzhiyun 	struct sock *sk;
75*4882a593Smuzhiyun 	int err;
76*4882a593Smuzhiyun 	__u64 seq;
77*4882a593Smuzhiyun 	struct net *net = dev_net(skb->dev);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	/* Only need dccph_dport & dccph_sport which are the first
80*4882a593Smuzhiyun 	 * 4 bytes in dccp header.
81*4882a593Smuzhiyun 	 * Our caller (icmpv6_notify()) already pulled 8 bytes for us.
82*4882a593Smuzhiyun 	 */
83*4882a593Smuzhiyun 	BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8);
84*4882a593Smuzhiyun 	BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8);
85*4882a593Smuzhiyun 	dh = (struct dccp_hdr *)(skb->data + offset);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	sk = __inet6_lookup_established(net, &dccp_hashinfo,
88*4882a593Smuzhiyun 					&hdr->daddr, dh->dccph_dport,
89*4882a593Smuzhiyun 					&hdr->saddr, ntohs(dh->dccph_sport),
90*4882a593Smuzhiyun 					inet6_iif(skb), 0);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	if (!sk) {
93*4882a593Smuzhiyun 		__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
94*4882a593Smuzhiyun 				  ICMP6_MIB_INERRORS);
95*4882a593Smuzhiyun 		return -ENOENT;
96*4882a593Smuzhiyun 	}
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	if (sk->sk_state == DCCP_TIME_WAIT) {
99*4882a593Smuzhiyun 		inet_twsk_put(inet_twsk(sk));
100*4882a593Smuzhiyun 		return 0;
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 	seq = dccp_hdr_seq(dh);
103*4882a593Smuzhiyun 	if (sk->sk_state == DCCP_NEW_SYN_RECV) {
104*4882a593Smuzhiyun 		dccp_req_err(sk, seq);
105*4882a593Smuzhiyun 		return 0;
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	bh_lock_sock(sk);
109*4882a593Smuzhiyun 	if (sock_owned_by_user(sk))
110*4882a593Smuzhiyun 		__NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	if (sk->sk_state == DCCP_CLOSED)
113*4882a593Smuzhiyun 		goto out;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	dp = dccp_sk(sk);
116*4882a593Smuzhiyun 	if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
117*4882a593Smuzhiyun 	    !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
118*4882a593Smuzhiyun 		__NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
119*4882a593Smuzhiyun 		goto out;
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	np = inet6_sk(sk);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if (type == NDISC_REDIRECT) {
125*4882a593Smuzhiyun 		if (!sock_owned_by_user(sk)) {
126*4882a593Smuzhiyun 			struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 			if (dst)
129*4882a593Smuzhiyun 				dst->ops->redirect(dst, sk, skb);
130*4882a593Smuzhiyun 		}
131*4882a593Smuzhiyun 		goto out;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	if (type == ICMPV6_PKT_TOOBIG) {
135*4882a593Smuzhiyun 		struct dst_entry *dst = NULL;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 		if (!ip6_sk_accept_pmtu(sk))
138*4882a593Smuzhiyun 			goto out;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		if (sock_owned_by_user(sk))
141*4882a593Smuzhiyun 			goto out;
142*4882a593Smuzhiyun 		if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED))
143*4882a593Smuzhiyun 			goto out;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 		dst = inet6_csk_update_pmtu(sk, ntohl(info));
146*4882a593Smuzhiyun 		if (!dst)
147*4882a593Smuzhiyun 			goto out;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 		if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst))
150*4882a593Smuzhiyun 			dccp_sync_mss(sk, dst_mtu(dst));
151*4882a593Smuzhiyun 		goto out;
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	icmpv6_err_convert(type, code, &err);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	/* Might be for an request_sock */
157*4882a593Smuzhiyun 	switch (sk->sk_state) {
158*4882a593Smuzhiyun 	case DCCP_REQUESTING:
159*4882a593Smuzhiyun 	case DCCP_RESPOND:  /* Cannot happen.
160*4882a593Smuzhiyun 			       It can, it SYNs are crossed. --ANK */
161*4882a593Smuzhiyun 		if (!sock_owned_by_user(sk)) {
162*4882a593Smuzhiyun 			__DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS);
163*4882a593Smuzhiyun 			sk->sk_err = err;
164*4882a593Smuzhiyun 			/*
165*4882a593Smuzhiyun 			 * Wake people up to see the error
166*4882a593Smuzhiyun 			 * (see connect in sock.c)
167*4882a593Smuzhiyun 			 */
168*4882a593Smuzhiyun 			sk->sk_error_report(sk);
169*4882a593Smuzhiyun 			dccp_done(sk);
170*4882a593Smuzhiyun 		} else
171*4882a593Smuzhiyun 			sk->sk_err_soft = err;
172*4882a593Smuzhiyun 		goto out;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (!sock_owned_by_user(sk) && np->recverr) {
176*4882a593Smuzhiyun 		sk->sk_err = err;
177*4882a593Smuzhiyun 		sk->sk_error_report(sk);
178*4882a593Smuzhiyun 	} else
179*4882a593Smuzhiyun 		sk->sk_err_soft = err;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun out:
182*4882a593Smuzhiyun 	bh_unlock_sock(sk);
183*4882a593Smuzhiyun 	sock_put(sk);
184*4882a593Smuzhiyun 	return 0;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 
dccp_v6_send_response(const struct sock * sk,struct request_sock * req)188*4882a593Smuzhiyun static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct inet_request_sock *ireq = inet_rsk(req);
191*4882a593Smuzhiyun 	struct ipv6_pinfo *np = inet6_sk(sk);
192*4882a593Smuzhiyun 	struct sk_buff *skb;
193*4882a593Smuzhiyun 	struct in6_addr *final_p, final;
194*4882a593Smuzhiyun 	struct flowi6 fl6;
195*4882a593Smuzhiyun 	int err = -1;
196*4882a593Smuzhiyun 	struct dst_entry *dst;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	memset(&fl6, 0, sizeof(fl6));
199*4882a593Smuzhiyun 	fl6.flowi6_proto = IPPROTO_DCCP;
200*4882a593Smuzhiyun 	fl6.daddr = ireq->ir_v6_rmt_addr;
201*4882a593Smuzhiyun 	fl6.saddr = ireq->ir_v6_loc_addr;
202*4882a593Smuzhiyun 	fl6.flowlabel = 0;
203*4882a593Smuzhiyun 	fl6.flowi6_oif = ireq->ir_iif;
204*4882a593Smuzhiyun 	fl6.fl6_dport = ireq->ir_rmt_port;
205*4882a593Smuzhiyun 	fl6.fl6_sport = htons(ireq->ir_num);
206*4882a593Smuzhiyun 	security_req_classify_flow(req, flowi6_to_flowi_common(&fl6));
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	rcu_read_lock();
210*4882a593Smuzhiyun 	final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final);
211*4882a593Smuzhiyun 	rcu_read_unlock();
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
214*4882a593Smuzhiyun 	if (IS_ERR(dst)) {
215*4882a593Smuzhiyun 		err = PTR_ERR(dst);
216*4882a593Smuzhiyun 		dst = NULL;
217*4882a593Smuzhiyun 		goto done;
218*4882a593Smuzhiyun 	}
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	skb = dccp_make_response(sk, dst, req);
221*4882a593Smuzhiyun 	if (skb != NULL) {
222*4882a593Smuzhiyun 		struct dccp_hdr *dh = dccp_hdr(skb);
223*4882a593Smuzhiyun 		struct ipv6_txoptions *opt;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 		dh->dccph_checksum = dccp_v6_csum_finish(skb,
226*4882a593Smuzhiyun 							 &ireq->ir_v6_loc_addr,
227*4882a593Smuzhiyun 							 &ireq->ir_v6_rmt_addr);
228*4882a593Smuzhiyun 		fl6.daddr = ireq->ir_v6_rmt_addr;
229*4882a593Smuzhiyun 		rcu_read_lock();
230*4882a593Smuzhiyun 		opt = ireq->ipv6_opt;
231*4882a593Smuzhiyun 		if (!opt)
232*4882a593Smuzhiyun 			opt = rcu_dereference(np->opt);
233*4882a593Smuzhiyun 		err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass,
234*4882a593Smuzhiyun 			       sk->sk_priority);
235*4882a593Smuzhiyun 		rcu_read_unlock();
236*4882a593Smuzhiyun 		err = net_xmit_eval(err);
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun done:
240*4882a593Smuzhiyun 	dst_release(dst);
241*4882a593Smuzhiyun 	return err;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun 
dccp_v6_reqsk_destructor(struct request_sock * req)244*4882a593Smuzhiyun static void dccp_v6_reqsk_destructor(struct request_sock *req)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
247*4882a593Smuzhiyun 	kfree(inet_rsk(req)->ipv6_opt);
248*4882a593Smuzhiyun 	kfree_skb(inet_rsk(req)->pktopts);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
dccp_v6_ctl_send_reset(const struct sock * sk,struct sk_buff * rxskb)251*4882a593Smuzhiyun static void dccp_v6_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	const struct ipv6hdr *rxip6h;
254*4882a593Smuzhiyun 	struct sk_buff *skb;
255*4882a593Smuzhiyun 	struct flowi6 fl6;
256*4882a593Smuzhiyun 	struct net *net = dev_net(skb_dst(rxskb)->dev);
257*4882a593Smuzhiyun 	struct sock *ctl_sk = net->dccp.v6_ctl_sk;
258*4882a593Smuzhiyun 	struct dst_entry *dst;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
261*4882a593Smuzhiyun 		return;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	if (!ipv6_unicast_destination(rxskb))
264*4882a593Smuzhiyun 		return;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	skb = dccp_ctl_make_reset(ctl_sk, rxskb);
267*4882a593Smuzhiyun 	if (skb == NULL)
268*4882a593Smuzhiyun 		return;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	rxip6h = ipv6_hdr(rxskb);
271*4882a593Smuzhiyun 	dccp_hdr(skb)->dccph_checksum = dccp_v6_csum_finish(skb, &rxip6h->saddr,
272*4882a593Smuzhiyun 							    &rxip6h->daddr);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	memset(&fl6, 0, sizeof(fl6));
275*4882a593Smuzhiyun 	fl6.daddr = rxip6h->saddr;
276*4882a593Smuzhiyun 	fl6.saddr = rxip6h->daddr;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	fl6.flowi6_proto = IPPROTO_DCCP;
279*4882a593Smuzhiyun 	fl6.flowi6_oif = inet6_iif(rxskb);
280*4882a593Smuzhiyun 	fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
281*4882a593Smuzhiyun 	fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
282*4882a593Smuzhiyun 	security_skb_classify_flow(rxskb, flowi6_to_flowi_common(&fl6));
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	/* sk = NULL, but it is safe for now. RST socket required. */
285*4882a593Smuzhiyun 	dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
286*4882a593Smuzhiyun 	if (!IS_ERR(dst)) {
287*4882a593Smuzhiyun 		skb_dst_set(skb, dst);
288*4882a593Smuzhiyun 		ip6_xmit(ctl_sk, skb, &fl6, 0, NULL, 0, 0);
289*4882a593Smuzhiyun 		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
290*4882a593Smuzhiyun 		DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
291*4882a593Smuzhiyun 		return;
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	kfree_skb(skb);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun static struct request_sock_ops dccp6_request_sock_ops = {
298*4882a593Smuzhiyun 	.family		= AF_INET6,
299*4882a593Smuzhiyun 	.obj_size	= sizeof(struct dccp6_request_sock),
300*4882a593Smuzhiyun 	.rtx_syn_ack	= dccp_v6_send_response,
301*4882a593Smuzhiyun 	.send_ack	= dccp_reqsk_send_ack,
302*4882a593Smuzhiyun 	.destructor	= dccp_v6_reqsk_destructor,
303*4882a593Smuzhiyun 	.send_reset	= dccp_v6_ctl_send_reset,
304*4882a593Smuzhiyun 	.syn_ack_timeout = dccp_syn_ack_timeout,
305*4882a593Smuzhiyun };
306*4882a593Smuzhiyun 
dccp_v6_conn_request(struct sock * sk,struct sk_buff * skb)307*4882a593Smuzhiyun static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	struct request_sock *req;
310*4882a593Smuzhiyun 	struct dccp_request_sock *dreq;
311*4882a593Smuzhiyun 	struct inet_request_sock *ireq;
312*4882a593Smuzhiyun 	struct ipv6_pinfo *np = inet6_sk(sk);
313*4882a593Smuzhiyun 	const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
314*4882a593Smuzhiyun 	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	if (skb->protocol == htons(ETH_P_IP))
317*4882a593Smuzhiyun 		return dccp_v4_conn_request(sk, skb);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (!ipv6_unicast_destination(skb))
320*4882a593Smuzhiyun 		return 0;	/* discard, don't send a reset here */
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) {
323*4882a593Smuzhiyun 		__IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS);
324*4882a593Smuzhiyun 		return 0;
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	if (dccp_bad_service_code(sk, service)) {
328*4882a593Smuzhiyun 		dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
329*4882a593Smuzhiyun 		goto drop;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 	/*
332*4882a593Smuzhiyun 	 * There are no SYN attacks on IPv6, yet...
333*4882a593Smuzhiyun 	 */
334*4882a593Smuzhiyun 	dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
335*4882a593Smuzhiyun 	if (inet_csk_reqsk_queue_is_full(sk))
336*4882a593Smuzhiyun 		goto drop;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (sk_acceptq_is_full(sk))
339*4882a593Smuzhiyun 		goto drop;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	req = inet_reqsk_alloc(&dccp6_request_sock_ops, sk, true);
342*4882a593Smuzhiyun 	if (req == NULL)
343*4882a593Smuzhiyun 		goto drop;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	if (dccp_reqsk_init(req, dccp_sk(sk), skb))
346*4882a593Smuzhiyun 		goto drop_and_free;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	dreq = dccp_rsk(req);
349*4882a593Smuzhiyun 	if (dccp_parse_options(sk, dreq, skb))
350*4882a593Smuzhiyun 		goto drop_and_free;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	if (security_inet_conn_request(sk, skb, req))
353*4882a593Smuzhiyun 		goto drop_and_free;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	ireq = inet_rsk(req);
356*4882a593Smuzhiyun 	ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
357*4882a593Smuzhiyun 	ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
358*4882a593Smuzhiyun 	ireq->ireq_family = AF_INET6;
359*4882a593Smuzhiyun 	ireq->ir_mark = inet_request_mark(sk, skb);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) ||
362*4882a593Smuzhiyun 	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
363*4882a593Smuzhiyun 	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
364*4882a593Smuzhiyun 		refcount_inc(&skb->users);
365*4882a593Smuzhiyun 		ireq->pktopts = skb;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 	ireq->ir_iif = sk->sk_bound_dev_if;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	/* So that link locals have meaning */
370*4882a593Smuzhiyun 	if (!sk->sk_bound_dev_if &&
371*4882a593Smuzhiyun 	    ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
372*4882a593Smuzhiyun 		ireq->ir_iif = inet6_iif(skb);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	/*
375*4882a593Smuzhiyun 	 * Step 3: Process LISTEN state
376*4882a593Smuzhiyun 	 *
377*4882a593Smuzhiyun 	 *   Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
378*4882a593Smuzhiyun 	 *
379*4882a593Smuzhiyun 	 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
380*4882a593Smuzhiyun 	 */
381*4882a593Smuzhiyun 	dreq->dreq_isr	   = dcb->dccpd_seq;
382*4882a593Smuzhiyun 	dreq->dreq_gsr     = dreq->dreq_isr;
383*4882a593Smuzhiyun 	dreq->dreq_iss	   = dccp_v6_init_sequence(skb);
384*4882a593Smuzhiyun 	dreq->dreq_gss     = dreq->dreq_iss;
385*4882a593Smuzhiyun 	dreq->dreq_service = service;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	if (dccp_v6_send_response(sk, req))
388*4882a593Smuzhiyun 		goto drop_and_free;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
391*4882a593Smuzhiyun 	reqsk_put(req);
392*4882a593Smuzhiyun 	return 0;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun drop_and_free:
395*4882a593Smuzhiyun 	reqsk_free(req);
396*4882a593Smuzhiyun drop:
397*4882a593Smuzhiyun 	__DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS);
398*4882a593Smuzhiyun 	return -1;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
dccp_v6_request_recv_sock(const struct sock * sk,struct sk_buff * skb,struct request_sock * req,struct dst_entry * dst,struct request_sock * req_unhash,bool * own_req)401*4882a593Smuzhiyun static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
402*4882a593Smuzhiyun 					      struct sk_buff *skb,
403*4882a593Smuzhiyun 					      struct request_sock *req,
404*4882a593Smuzhiyun 					      struct dst_entry *dst,
405*4882a593Smuzhiyun 					      struct request_sock *req_unhash,
406*4882a593Smuzhiyun 					      bool *own_req)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	struct inet_request_sock *ireq = inet_rsk(req);
409*4882a593Smuzhiyun 	struct ipv6_pinfo *newnp;
410*4882a593Smuzhiyun 	const struct ipv6_pinfo *np = inet6_sk(sk);
411*4882a593Smuzhiyun 	struct ipv6_txoptions *opt;
412*4882a593Smuzhiyun 	struct inet_sock *newinet;
413*4882a593Smuzhiyun 	struct dccp6_sock *newdp6;
414*4882a593Smuzhiyun 	struct sock *newsk;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	if (skb->protocol == htons(ETH_P_IP)) {
417*4882a593Smuzhiyun 		/*
418*4882a593Smuzhiyun 		 *	v6 mapped
419*4882a593Smuzhiyun 		 */
420*4882a593Smuzhiyun 		newsk = dccp_v4_request_recv_sock(sk, skb, req, dst,
421*4882a593Smuzhiyun 						  req_unhash, own_req);
422*4882a593Smuzhiyun 		if (newsk == NULL)
423*4882a593Smuzhiyun 			return NULL;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 		newdp6 = (struct dccp6_sock *)newsk;
426*4882a593Smuzhiyun 		newinet = inet_sk(newsk);
427*4882a593Smuzhiyun 		newinet->pinet6 = &newdp6->inet6;
428*4882a593Smuzhiyun 		newnp = inet6_sk(newsk);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 		memcpy(newnp, np, sizeof(struct ipv6_pinfo));
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 		newnp->saddr = newsk->sk_v6_rcv_saddr;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 		inet_csk(newsk)->icsk_af_ops = &dccp_ipv6_mapped;
435*4882a593Smuzhiyun 		newsk->sk_backlog_rcv = dccp_v4_do_rcv;
436*4882a593Smuzhiyun 		newnp->pktoptions  = NULL;
437*4882a593Smuzhiyun 		newnp->opt	   = NULL;
438*4882a593Smuzhiyun 		newnp->ipv6_mc_list = NULL;
439*4882a593Smuzhiyun 		newnp->ipv6_ac_list = NULL;
440*4882a593Smuzhiyun 		newnp->ipv6_fl_list = NULL;
441*4882a593Smuzhiyun 		newnp->mcast_oif   = inet_iif(skb);
442*4882a593Smuzhiyun 		newnp->mcast_hops  = ip_hdr(skb)->ttl;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 		/*
445*4882a593Smuzhiyun 		 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
446*4882a593Smuzhiyun 		 * here, dccp_create_openreq_child now does this for us, see the comment in
447*4882a593Smuzhiyun 		 * that function for the gory details. -acme
448*4882a593Smuzhiyun 		 */
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 		/* It is tricky place. Until this moment IPv4 tcp
451*4882a593Smuzhiyun 		   worked with IPv6 icsk.icsk_af_ops.
452*4882a593Smuzhiyun 		   Sync it now.
453*4882a593Smuzhiyun 		 */
454*4882a593Smuzhiyun 		dccp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 		return newsk;
457*4882a593Smuzhiyun 	}
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	if (sk_acceptq_is_full(sk))
461*4882a593Smuzhiyun 		goto out_overflow;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	if (!dst) {
464*4882a593Smuzhiyun 		struct flowi6 fl6;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 		dst = inet6_csk_route_req(sk, &fl6, req, IPPROTO_DCCP);
467*4882a593Smuzhiyun 		if (!dst)
468*4882a593Smuzhiyun 			goto out;
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	newsk = dccp_create_openreq_child(sk, req, skb);
472*4882a593Smuzhiyun 	if (newsk == NULL)
473*4882a593Smuzhiyun 		goto out_nonewsk;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	/*
476*4882a593Smuzhiyun 	 * No need to charge this sock to the relevant IPv6 refcnt debug socks
477*4882a593Smuzhiyun 	 * count here, dccp_create_openreq_child now does this for us, see the
478*4882a593Smuzhiyun 	 * comment in that function for the gory details. -acme
479*4882a593Smuzhiyun 	 */
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	ip6_dst_store(newsk, dst, NULL, NULL);
482*4882a593Smuzhiyun 	newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
483*4882a593Smuzhiyun 						      NETIF_F_TSO);
484*4882a593Smuzhiyun 	newdp6 = (struct dccp6_sock *)newsk;
485*4882a593Smuzhiyun 	newinet = inet_sk(newsk);
486*4882a593Smuzhiyun 	newinet->pinet6 = &newdp6->inet6;
487*4882a593Smuzhiyun 	newnp = inet6_sk(newsk);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	newsk->sk_v6_daddr	= ireq->ir_v6_rmt_addr;
492*4882a593Smuzhiyun 	newnp->saddr		= ireq->ir_v6_loc_addr;
493*4882a593Smuzhiyun 	newsk->sk_v6_rcv_saddr	= ireq->ir_v6_loc_addr;
494*4882a593Smuzhiyun 	newsk->sk_bound_dev_if	= ireq->ir_iif;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	/* Now IPv6 options...
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	   First: no IPv4 options.
499*4882a593Smuzhiyun 	 */
500*4882a593Smuzhiyun 	newinet->inet_opt = NULL;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	/* Clone RX bits */
503*4882a593Smuzhiyun 	newnp->rxopt.all = np->rxopt.all;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	newnp->ipv6_mc_list = NULL;
506*4882a593Smuzhiyun 	newnp->ipv6_ac_list = NULL;
507*4882a593Smuzhiyun 	newnp->ipv6_fl_list = NULL;
508*4882a593Smuzhiyun 	newnp->pktoptions = NULL;
509*4882a593Smuzhiyun 	newnp->opt	  = NULL;
510*4882a593Smuzhiyun 	newnp->mcast_oif  = inet6_iif(skb);
511*4882a593Smuzhiyun 	newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	/*
514*4882a593Smuzhiyun 	 * Clone native IPv6 options from listening socket (if any)
515*4882a593Smuzhiyun 	 *
516*4882a593Smuzhiyun 	 * Yes, keeping reference count would be much more clever, but we make
517*4882a593Smuzhiyun 	 * one more one thing there: reattach optmem to newsk.
518*4882a593Smuzhiyun 	 */
519*4882a593Smuzhiyun 	opt = ireq->ipv6_opt;
520*4882a593Smuzhiyun 	if (!opt)
521*4882a593Smuzhiyun 		opt = rcu_dereference(np->opt);
522*4882a593Smuzhiyun 	if (opt) {
523*4882a593Smuzhiyun 		opt = ipv6_dup_options(newsk, opt);
524*4882a593Smuzhiyun 		RCU_INIT_POINTER(newnp->opt, opt);
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 	inet_csk(newsk)->icsk_ext_hdr_len = 0;
527*4882a593Smuzhiyun 	if (opt)
528*4882a593Smuzhiyun 		inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen +
529*4882a593Smuzhiyun 						    opt->opt_flen;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	dccp_sync_mss(newsk, dst_mtu(dst));
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
534*4882a593Smuzhiyun 	newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	if (__inet_inherit_port(sk, newsk) < 0) {
537*4882a593Smuzhiyun 		inet_csk_prepare_forced_close(newsk);
538*4882a593Smuzhiyun 		dccp_done(newsk);
539*4882a593Smuzhiyun 		goto out;
540*4882a593Smuzhiyun 	}
541*4882a593Smuzhiyun 	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL);
542*4882a593Smuzhiyun 	/* Clone pktoptions received with SYN, if we own the req */
543*4882a593Smuzhiyun 	if (*own_req && ireq->pktopts) {
544*4882a593Smuzhiyun 		newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC);
545*4882a593Smuzhiyun 		consume_skb(ireq->pktopts);
546*4882a593Smuzhiyun 		ireq->pktopts = NULL;
547*4882a593Smuzhiyun 		if (newnp->pktoptions)
548*4882a593Smuzhiyun 			skb_set_owner_r(newnp->pktoptions, newsk);
549*4882a593Smuzhiyun 	}
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	return newsk;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun out_overflow:
554*4882a593Smuzhiyun 	__NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
555*4882a593Smuzhiyun out_nonewsk:
556*4882a593Smuzhiyun 	dst_release(dst);
557*4882a593Smuzhiyun out:
558*4882a593Smuzhiyun 	__NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS);
559*4882a593Smuzhiyun 	return NULL;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun /* The socket must have it's spinlock held when we get
563*4882a593Smuzhiyun  * here.
564*4882a593Smuzhiyun  *
565*4882a593Smuzhiyun  * We have a potential double-lock case here, so even when
566*4882a593Smuzhiyun  * doing backlog processing we use the BH locking scheme.
567*4882a593Smuzhiyun  * This is because we cannot sleep with the original spinlock
568*4882a593Smuzhiyun  * held.
569*4882a593Smuzhiyun  */
dccp_v6_do_rcv(struct sock * sk,struct sk_buff * skb)570*4882a593Smuzhiyun static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	struct ipv6_pinfo *np = inet6_sk(sk);
573*4882a593Smuzhiyun 	struct sk_buff *opt_skb = NULL;
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	/* Imagine: socket is IPv6. IPv4 packet arrives,
576*4882a593Smuzhiyun 	   goes to IPv4 receive handler and backlogged.
577*4882a593Smuzhiyun 	   From backlog it always goes here. Kerboom...
578*4882a593Smuzhiyun 	   Fortunately, dccp_rcv_established and rcv_established
579*4882a593Smuzhiyun 	   handle them correctly, but it is not case with
580*4882a593Smuzhiyun 	   dccp_v6_hnd_req and dccp_v6_ctl_send_reset().   --ANK
581*4882a593Smuzhiyun 	 */
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	if (skb->protocol == htons(ETH_P_IP))
584*4882a593Smuzhiyun 		return dccp_v4_do_rcv(sk, skb);
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	if (sk_filter(sk, skb))
587*4882a593Smuzhiyun 		goto discard;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	/*
590*4882a593Smuzhiyun 	 * socket locking is here for SMP purposes as backlog rcv is currently
591*4882a593Smuzhiyun 	 * called with bh processing disabled.
592*4882a593Smuzhiyun 	 */
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	/* Do Stevens' IPV6_PKTOPTIONS.
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	   Yes, guys, it is the only place in our code, where we
597*4882a593Smuzhiyun 	   may make it not affecting IPv4.
598*4882a593Smuzhiyun 	   The rest of code is protocol independent,
599*4882a593Smuzhiyun 	   and I do not like idea to uglify IPv4.
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	   Actually, all the idea behind IPV6_PKTOPTIONS
602*4882a593Smuzhiyun 	   looks not very well thought. For now we latch
603*4882a593Smuzhiyun 	   options, received in the last packet, enqueued
604*4882a593Smuzhiyun 	   by tcp. Feel free to propose better solution.
605*4882a593Smuzhiyun 					       --ANK (980728)
606*4882a593Smuzhiyun 	 */
607*4882a593Smuzhiyun 	if (np->rxopt.all)
608*4882a593Smuzhiyun 		opt_skb = skb_clone(skb, GFP_ATOMIC);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	if (sk->sk_state == DCCP_OPEN) { /* Fast path */
611*4882a593Smuzhiyun 		if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
612*4882a593Smuzhiyun 			goto reset;
613*4882a593Smuzhiyun 		if (opt_skb)
614*4882a593Smuzhiyun 			goto ipv6_pktoptions;
615*4882a593Smuzhiyun 		return 0;
616*4882a593Smuzhiyun 	}
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	/*
619*4882a593Smuzhiyun 	 *  Step 3: Process LISTEN state
620*4882a593Smuzhiyun 	 *     If S.state == LISTEN,
621*4882a593Smuzhiyun 	 *	 If P.type == Request or P contains a valid Init Cookie option,
622*4882a593Smuzhiyun 	 *	      (* Must scan the packet's options to check for Init
623*4882a593Smuzhiyun 	 *		 Cookies.  Only Init Cookies are processed here,
624*4882a593Smuzhiyun 	 *		 however; other options are processed in Step 8.  This
625*4882a593Smuzhiyun 	 *		 scan need only be performed if the endpoint uses Init
626*4882a593Smuzhiyun 	 *		 Cookies *)
627*4882a593Smuzhiyun 	 *	      (* Generate a new socket and switch to that socket *)
628*4882a593Smuzhiyun 	 *	      Set S := new socket for this port pair
629*4882a593Smuzhiyun 	 *	      S.state = RESPOND
630*4882a593Smuzhiyun 	 *	      Choose S.ISS (initial seqno) or set from Init Cookies
631*4882a593Smuzhiyun 	 *	      Initialize S.GAR := S.ISS
632*4882a593Smuzhiyun 	 *	      Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
633*4882a593Smuzhiyun 	 *	      Continue with S.state == RESPOND
634*4882a593Smuzhiyun 	 *	      (* A Response packet will be generated in Step 11 *)
635*4882a593Smuzhiyun 	 *	 Otherwise,
636*4882a593Smuzhiyun 	 *	      Generate Reset(No Connection) unless P.type == Reset
637*4882a593Smuzhiyun 	 *	      Drop packet and return
638*4882a593Smuzhiyun 	 *
639*4882a593Smuzhiyun 	 * NOTE: the check for the packet types is done in
640*4882a593Smuzhiyun 	 *	 dccp_rcv_state_process
641*4882a593Smuzhiyun 	 */
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
644*4882a593Smuzhiyun 		goto reset;
645*4882a593Smuzhiyun 	if (opt_skb)
646*4882a593Smuzhiyun 		goto ipv6_pktoptions;
647*4882a593Smuzhiyun 	return 0;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun reset:
650*4882a593Smuzhiyun 	dccp_v6_ctl_send_reset(sk, skb);
651*4882a593Smuzhiyun discard:
652*4882a593Smuzhiyun 	if (opt_skb != NULL)
653*4882a593Smuzhiyun 		__kfree_skb(opt_skb);
654*4882a593Smuzhiyun 	kfree_skb(skb);
655*4882a593Smuzhiyun 	return 0;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun /* Handling IPV6_PKTOPTIONS skb the similar
658*4882a593Smuzhiyun  * way it's done for net/ipv6/tcp_ipv6.c
659*4882a593Smuzhiyun  */
660*4882a593Smuzhiyun ipv6_pktoptions:
661*4882a593Smuzhiyun 	if (!((1 << sk->sk_state) & (DCCPF_CLOSED | DCCPF_LISTEN))) {
662*4882a593Smuzhiyun 		if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
663*4882a593Smuzhiyun 			np->mcast_oif = inet6_iif(opt_skb);
664*4882a593Smuzhiyun 		if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
665*4882a593Smuzhiyun 			np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
666*4882a593Smuzhiyun 		if (np->rxopt.bits.rxflow || np->rxopt.bits.rxtclass)
667*4882a593Smuzhiyun 			np->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(opt_skb));
668*4882a593Smuzhiyun 		if (np->repflow)
669*4882a593Smuzhiyun 			np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb));
670*4882a593Smuzhiyun 		if (ipv6_opt_accepted(sk, opt_skb,
671*4882a593Smuzhiyun 				      &DCCP_SKB_CB(opt_skb)->header.h6)) {
672*4882a593Smuzhiyun 			skb_set_owner_r(opt_skb, sk);
673*4882a593Smuzhiyun 			memmove(IP6CB(opt_skb),
674*4882a593Smuzhiyun 				&DCCP_SKB_CB(opt_skb)->header.h6,
675*4882a593Smuzhiyun 				sizeof(struct inet6_skb_parm));
676*4882a593Smuzhiyun 			opt_skb = xchg(&np->pktoptions, opt_skb);
677*4882a593Smuzhiyun 		} else {
678*4882a593Smuzhiyun 			__kfree_skb(opt_skb);
679*4882a593Smuzhiyun 			opt_skb = xchg(&np->pktoptions, NULL);
680*4882a593Smuzhiyun 		}
681*4882a593Smuzhiyun 	}
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	kfree_skb(opt_skb);
684*4882a593Smuzhiyun 	return 0;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun 
dccp_v6_rcv(struct sk_buff * skb)687*4882a593Smuzhiyun static int dccp_v6_rcv(struct sk_buff *skb)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	const struct dccp_hdr *dh;
690*4882a593Smuzhiyun 	bool refcounted;
691*4882a593Smuzhiyun 	struct sock *sk;
692*4882a593Smuzhiyun 	int min_cov;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	/* Step 1: Check header basics */
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	if (dccp_invalid_packet(skb))
697*4882a593Smuzhiyun 		goto discard_it;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	/* Step 1: If header checksum is incorrect, drop packet and return. */
700*4882a593Smuzhiyun 	if (dccp_v6_csum_finish(skb, &ipv6_hdr(skb)->saddr,
701*4882a593Smuzhiyun 				     &ipv6_hdr(skb)->daddr)) {
702*4882a593Smuzhiyun 		DCCP_WARN("dropped packet with invalid checksum\n");
703*4882a593Smuzhiyun 		goto discard_it;
704*4882a593Smuzhiyun 	}
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	dh = dccp_hdr(skb);
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(dh);
709*4882a593Smuzhiyun 	DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	if (dccp_packet_without_ack(skb))
712*4882a593Smuzhiyun 		DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
713*4882a593Smuzhiyun 	else
714*4882a593Smuzhiyun 		DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun lookup:
717*4882a593Smuzhiyun 	sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
718*4882a593Smuzhiyun 			        dh->dccph_sport, dh->dccph_dport,
719*4882a593Smuzhiyun 				inet6_iif(skb), 0, &refcounted);
720*4882a593Smuzhiyun 	if (!sk) {
721*4882a593Smuzhiyun 		dccp_pr_debug("failed to look up flow ID in table and "
722*4882a593Smuzhiyun 			      "get corresponding socket\n");
723*4882a593Smuzhiyun 		goto no_dccp_socket;
724*4882a593Smuzhiyun 	}
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	/*
727*4882a593Smuzhiyun 	 * Step 2:
728*4882a593Smuzhiyun 	 *	... or S.state == TIMEWAIT,
729*4882a593Smuzhiyun 	 *		Generate Reset(No Connection) unless P.type == Reset
730*4882a593Smuzhiyun 	 *		Drop packet and return
731*4882a593Smuzhiyun 	 */
732*4882a593Smuzhiyun 	if (sk->sk_state == DCCP_TIME_WAIT) {
733*4882a593Smuzhiyun 		dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");
734*4882a593Smuzhiyun 		inet_twsk_put(inet_twsk(sk));
735*4882a593Smuzhiyun 		goto no_dccp_socket;
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	if (sk->sk_state == DCCP_NEW_SYN_RECV) {
739*4882a593Smuzhiyun 		struct request_sock *req = inet_reqsk(sk);
740*4882a593Smuzhiyun 		struct sock *nsk;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 		sk = req->rsk_listener;
743*4882a593Smuzhiyun 		if (unlikely(sk->sk_state != DCCP_LISTEN)) {
744*4882a593Smuzhiyun 			inet_csk_reqsk_queue_drop_and_put(sk, req);
745*4882a593Smuzhiyun 			goto lookup;
746*4882a593Smuzhiyun 		}
747*4882a593Smuzhiyun 		sock_hold(sk);
748*4882a593Smuzhiyun 		refcounted = true;
749*4882a593Smuzhiyun 		nsk = dccp_check_req(sk, skb, req);
750*4882a593Smuzhiyun 		if (!nsk) {
751*4882a593Smuzhiyun 			reqsk_put(req);
752*4882a593Smuzhiyun 			goto discard_and_relse;
753*4882a593Smuzhiyun 		}
754*4882a593Smuzhiyun 		if (nsk == sk) {
755*4882a593Smuzhiyun 			reqsk_put(req);
756*4882a593Smuzhiyun 		} else if (dccp_child_process(sk, nsk, skb)) {
757*4882a593Smuzhiyun 			dccp_v6_ctl_send_reset(sk, skb);
758*4882a593Smuzhiyun 			goto discard_and_relse;
759*4882a593Smuzhiyun 		} else {
760*4882a593Smuzhiyun 			sock_put(sk);
761*4882a593Smuzhiyun 			return 0;
762*4882a593Smuzhiyun 		}
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 	/*
765*4882a593Smuzhiyun 	 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
766*4882a593Smuzhiyun 	 *	o if MinCsCov = 0, only packets with CsCov = 0 are accepted
767*4882a593Smuzhiyun 	 *	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
768*4882a593Smuzhiyun 	 */
769*4882a593Smuzhiyun 	min_cov = dccp_sk(sk)->dccps_pcrlen;
770*4882a593Smuzhiyun 	if (dh->dccph_cscov  &&  (min_cov == 0 || dh->dccph_cscov < min_cov))  {
771*4882a593Smuzhiyun 		dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
772*4882a593Smuzhiyun 			      dh->dccph_cscov, min_cov);
773*4882a593Smuzhiyun 		/* FIXME: send Data Dropped option (see also dccp_v4_rcv) */
774*4882a593Smuzhiyun 		goto discard_and_relse;
775*4882a593Smuzhiyun 	}
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
778*4882a593Smuzhiyun 		goto discard_and_relse;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4,
781*4882a593Smuzhiyun 				refcounted) ? -1 : 0;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun no_dccp_socket:
784*4882a593Smuzhiyun 	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
785*4882a593Smuzhiyun 		goto discard_it;
786*4882a593Smuzhiyun 	/*
787*4882a593Smuzhiyun 	 * Step 2:
788*4882a593Smuzhiyun 	 *	If no socket ...
789*4882a593Smuzhiyun 	 *		Generate Reset(No Connection) unless P.type == Reset
790*4882a593Smuzhiyun 	 *		Drop packet and return
791*4882a593Smuzhiyun 	 */
792*4882a593Smuzhiyun 	if (dh->dccph_type != DCCP_PKT_RESET) {
793*4882a593Smuzhiyun 		DCCP_SKB_CB(skb)->dccpd_reset_code =
794*4882a593Smuzhiyun 					DCCP_RESET_CODE_NO_CONNECTION;
795*4882a593Smuzhiyun 		dccp_v6_ctl_send_reset(sk, skb);
796*4882a593Smuzhiyun 	}
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun discard_it:
799*4882a593Smuzhiyun 	kfree_skb(skb);
800*4882a593Smuzhiyun 	return 0;
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun discard_and_relse:
803*4882a593Smuzhiyun 	if (refcounted)
804*4882a593Smuzhiyun 		sock_put(sk);
805*4882a593Smuzhiyun 	goto discard_it;
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun 
dccp_v6_connect(struct sock * sk,struct sockaddr * uaddr,int addr_len)808*4882a593Smuzhiyun static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
809*4882a593Smuzhiyun 			   int addr_len)
810*4882a593Smuzhiyun {
811*4882a593Smuzhiyun 	struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
812*4882a593Smuzhiyun 	struct inet_connection_sock *icsk = inet_csk(sk);
813*4882a593Smuzhiyun 	struct inet_sock *inet = inet_sk(sk);
814*4882a593Smuzhiyun 	struct ipv6_pinfo *np = inet6_sk(sk);
815*4882a593Smuzhiyun 	struct dccp_sock *dp = dccp_sk(sk);
816*4882a593Smuzhiyun 	struct in6_addr *saddr = NULL, *final_p, final;
817*4882a593Smuzhiyun 	struct ipv6_txoptions *opt;
818*4882a593Smuzhiyun 	struct flowi6 fl6;
819*4882a593Smuzhiyun 	struct dst_entry *dst;
820*4882a593Smuzhiyun 	int addr_type;
821*4882a593Smuzhiyun 	int err;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	dp->dccps_role = DCCP_ROLE_CLIENT;
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	if (addr_len < SIN6_LEN_RFC2133)
826*4882a593Smuzhiyun 		return -EINVAL;
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	if (usin->sin6_family != AF_INET6)
829*4882a593Smuzhiyun 		return -EAFNOSUPPORT;
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	memset(&fl6, 0, sizeof(fl6));
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	if (np->sndflow) {
834*4882a593Smuzhiyun 		fl6.flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
835*4882a593Smuzhiyun 		IP6_ECN_flow_init(fl6.flowlabel);
836*4882a593Smuzhiyun 		if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
837*4882a593Smuzhiyun 			struct ip6_flowlabel *flowlabel;
838*4882a593Smuzhiyun 			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
839*4882a593Smuzhiyun 			if (IS_ERR(flowlabel))
840*4882a593Smuzhiyun 				return -EINVAL;
841*4882a593Smuzhiyun 			fl6_sock_release(flowlabel);
842*4882a593Smuzhiyun 		}
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 	/*
845*4882a593Smuzhiyun 	 * connect() to INADDR_ANY means loopback (BSD'ism).
846*4882a593Smuzhiyun 	 */
847*4882a593Smuzhiyun 	if (ipv6_addr_any(&usin->sin6_addr))
848*4882a593Smuzhiyun 		usin->sin6_addr.s6_addr[15] = 1;
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	addr_type = ipv6_addr_type(&usin->sin6_addr);
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	if (addr_type & IPV6_ADDR_MULTICAST)
853*4882a593Smuzhiyun 		return -ENETUNREACH;
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	if (addr_type & IPV6_ADDR_LINKLOCAL) {
856*4882a593Smuzhiyun 		if (addr_len >= sizeof(struct sockaddr_in6) &&
857*4882a593Smuzhiyun 		    usin->sin6_scope_id) {
858*4882a593Smuzhiyun 			/* If interface is set while binding, indices
859*4882a593Smuzhiyun 			 * must coincide.
860*4882a593Smuzhiyun 			 */
861*4882a593Smuzhiyun 			if (sk->sk_bound_dev_if &&
862*4882a593Smuzhiyun 			    sk->sk_bound_dev_if != usin->sin6_scope_id)
863*4882a593Smuzhiyun 				return -EINVAL;
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 			sk->sk_bound_dev_if = usin->sin6_scope_id;
866*4882a593Smuzhiyun 		}
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 		/* Connect to link-local address requires an interface */
869*4882a593Smuzhiyun 		if (!sk->sk_bound_dev_if)
870*4882a593Smuzhiyun 			return -EINVAL;
871*4882a593Smuzhiyun 	}
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	sk->sk_v6_daddr = usin->sin6_addr;
874*4882a593Smuzhiyun 	np->flow_label = fl6.flowlabel;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	/*
877*4882a593Smuzhiyun 	 * DCCP over IPv4
878*4882a593Smuzhiyun 	 */
879*4882a593Smuzhiyun 	if (addr_type == IPV6_ADDR_MAPPED) {
880*4882a593Smuzhiyun 		u32 exthdrlen = icsk->icsk_ext_hdr_len;
881*4882a593Smuzhiyun 		struct sockaddr_in sin;
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 		SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 		if (__ipv6_only_sock(sk))
886*4882a593Smuzhiyun 			return -ENETUNREACH;
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 		sin.sin_family = AF_INET;
889*4882a593Smuzhiyun 		sin.sin_port = usin->sin6_port;
890*4882a593Smuzhiyun 		sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 		icsk->icsk_af_ops = &dccp_ipv6_mapped;
893*4882a593Smuzhiyun 		sk->sk_backlog_rcv = dccp_v4_do_rcv;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 		err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
896*4882a593Smuzhiyun 		if (err) {
897*4882a593Smuzhiyun 			icsk->icsk_ext_hdr_len = exthdrlen;
898*4882a593Smuzhiyun 			icsk->icsk_af_ops = &dccp_ipv6_af_ops;
899*4882a593Smuzhiyun 			sk->sk_backlog_rcv = dccp_v6_do_rcv;
900*4882a593Smuzhiyun 			goto failure;
901*4882a593Smuzhiyun 		}
902*4882a593Smuzhiyun 		np->saddr = sk->sk_v6_rcv_saddr;
903*4882a593Smuzhiyun 		return err;
904*4882a593Smuzhiyun 	}
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr))
907*4882a593Smuzhiyun 		saddr = &sk->sk_v6_rcv_saddr;
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	fl6.flowi6_proto = IPPROTO_DCCP;
910*4882a593Smuzhiyun 	fl6.daddr = sk->sk_v6_daddr;
911*4882a593Smuzhiyun 	fl6.saddr = saddr ? *saddr : np->saddr;
912*4882a593Smuzhiyun 	fl6.flowi6_oif = sk->sk_bound_dev_if;
913*4882a593Smuzhiyun 	fl6.fl6_dport = usin->sin6_port;
914*4882a593Smuzhiyun 	fl6.fl6_sport = inet->inet_sport;
915*4882a593Smuzhiyun 	security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun 	opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
918*4882a593Smuzhiyun 	final_p = fl6_update_dst(&fl6, opt, &final);
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
921*4882a593Smuzhiyun 	if (IS_ERR(dst)) {
922*4882a593Smuzhiyun 		err = PTR_ERR(dst);
923*4882a593Smuzhiyun 		goto failure;
924*4882a593Smuzhiyun 	}
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 	if (saddr == NULL) {
927*4882a593Smuzhiyun 		saddr = &fl6.saddr;
928*4882a593Smuzhiyun 		sk->sk_v6_rcv_saddr = *saddr;
929*4882a593Smuzhiyun 	}
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	/* set the source address */
932*4882a593Smuzhiyun 	np->saddr = *saddr;
933*4882a593Smuzhiyun 	inet->inet_rcv_saddr = LOOPBACK4_IPV6;
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 	ip6_dst_store(sk, dst, NULL, NULL);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	icsk->icsk_ext_hdr_len = 0;
938*4882a593Smuzhiyun 	if (opt)
939*4882a593Smuzhiyun 		icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	inet->inet_dport = usin->sin6_port;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	dccp_set_state(sk, DCCP_REQUESTING);
944*4882a593Smuzhiyun 	err = inet6_hash_connect(&dccp_death_row, sk);
945*4882a593Smuzhiyun 	if (err)
946*4882a593Smuzhiyun 		goto late_failure;
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32,
949*4882a593Smuzhiyun 						      sk->sk_v6_daddr.s6_addr32,
950*4882a593Smuzhiyun 						      inet->inet_sport,
951*4882a593Smuzhiyun 						      inet->inet_dport);
952*4882a593Smuzhiyun 	err = dccp_connect(sk);
953*4882a593Smuzhiyun 	if (err)
954*4882a593Smuzhiyun 		goto late_failure;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	return 0;
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun late_failure:
959*4882a593Smuzhiyun 	dccp_set_state(sk, DCCP_CLOSED);
960*4882a593Smuzhiyun 	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
961*4882a593Smuzhiyun 		inet_reset_saddr(sk);
962*4882a593Smuzhiyun 	__sk_dst_reset(sk);
963*4882a593Smuzhiyun failure:
964*4882a593Smuzhiyun 	inet->inet_dport = 0;
965*4882a593Smuzhiyun 	sk->sk_route_caps = 0;
966*4882a593Smuzhiyun 	return err;
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
970*4882a593Smuzhiyun 	.queue_xmit	   = inet6_csk_xmit,
971*4882a593Smuzhiyun 	.send_check	   = dccp_v6_send_check,
972*4882a593Smuzhiyun 	.rebuild_header	   = inet6_sk_rebuild_header,
973*4882a593Smuzhiyun 	.conn_request	   = dccp_v6_conn_request,
974*4882a593Smuzhiyun 	.syn_recv_sock	   = dccp_v6_request_recv_sock,
975*4882a593Smuzhiyun 	.net_header_len	   = sizeof(struct ipv6hdr),
976*4882a593Smuzhiyun 	.setsockopt	   = ipv6_setsockopt,
977*4882a593Smuzhiyun 	.getsockopt	   = ipv6_getsockopt,
978*4882a593Smuzhiyun 	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
979*4882a593Smuzhiyun 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
980*4882a593Smuzhiyun };
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun /*
983*4882a593Smuzhiyun  *	DCCP over IPv4 via INET6 API
984*4882a593Smuzhiyun  */
985*4882a593Smuzhiyun static const struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
986*4882a593Smuzhiyun 	.queue_xmit	   = ip_queue_xmit,
987*4882a593Smuzhiyun 	.send_check	   = dccp_v4_send_check,
988*4882a593Smuzhiyun 	.rebuild_header	   = inet_sk_rebuild_header,
989*4882a593Smuzhiyun 	.conn_request	   = dccp_v6_conn_request,
990*4882a593Smuzhiyun 	.syn_recv_sock	   = dccp_v6_request_recv_sock,
991*4882a593Smuzhiyun 	.net_header_len	   = sizeof(struct iphdr),
992*4882a593Smuzhiyun 	.setsockopt	   = ipv6_setsockopt,
993*4882a593Smuzhiyun 	.getsockopt	   = ipv6_getsockopt,
994*4882a593Smuzhiyun 	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
995*4882a593Smuzhiyun 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
996*4882a593Smuzhiyun };
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun /* NOTE: A lot of things set to zero explicitly by call to
999*4882a593Smuzhiyun  *       sk_alloc() so need not be done here.
1000*4882a593Smuzhiyun  */
dccp_v6_init_sock(struct sock * sk)1001*4882a593Smuzhiyun static int dccp_v6_init_sock(struct sock *sk)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun 	static __u8 dccp_v6_ctl_sock_initialized;
1004*4882a593Smuzhiyun 	int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	if (err == 0) {
1007*4882a593Smuzhiyun 		if (unlikely(!dccp_v6_ctl_sock_initialized))
1008*4882a593Smuzhiyun 			dccp_v6_ctl_sock_initialized = 1;
1009*4882a593Smuzhiyun 		inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
1010*4882a593Smuzhiyun 	}
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	return err;
1013*4882a593Smuzhiyun }
1014*4882a593Smuzhiyun 
dccp_v6_destroy_sock(struct sock * sk)1015*4882a593Smuzhiyun static void dccp_v6_destroy_sock(struct sock *sk)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun 	dccp_destroy_sock(sk);
1018*4882a593Smuzhiyun 	inet6_destroy_sock(sk);
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun static struct timewait_sock_ops dccp6_timewait_sock_ops = {
1022*4882a593Smuzhiyun 	.twsk_obj_size	= sizeof(struct dccp6_timewait_sock),
1023*4882a593Smuzhiyun };
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun static struct proto dccp_v6_prot = {
1026*4882a593Smuzhiyun 	.name		   = "DCCPv6",
1027*4882a593Smuzhiyun 	.owner		   = THIS_MODULE,
1028*4882a593Smuzhiyun 	.close		   = dccp_close,
1029*4882a593Smuzhiyun 	.connect	   = dccp_v6_connect,
1030*4882a593Smuzhiyun 	.disconnect	   = dccp_disconnect,
1031*4882a593Smuzhiyun 	.ioctl		   = dccp_ioctl,
1032*4882a593Smuzhiyun 	.init		   = dccp_v6_init_sock,
1033*4882a593Smuzhiyun 	.setsockopt	   = dccp_setsockopt,
1034*4882a593Smuzhiyun 	.getsockopt	   = dccp_getsockopt,
1035*4882a593Smuzhiyun 	.sendmsg	   = dccp_sendmsg,
1036*4882a593Smuzhiyun 	.recvmsg	   = dccp_recvmsg,
1037*4882a593Smuzhiyun 	.backlog_rcv	   = dccp_v6_do_rcv,
1038*4882a593Smuzhiyun 	.hash		   = inet6_hash,
1039*4882a593Smuzhiyun 	.unhash		   = inet_unhash,
1040*4882a593Smuzhiyun 	.accept		   = inet_csk_accept,
1041*4882a593Smuzhiyun 	.get_port	   = inet_csk_get_port,
1042*4882a593Smuzhiyun 	.shutdown	   = dccp_shutdown,
1043*4882a593Smuzhiyun 	.destroy	   = dccp_v6_destroy_sock,
1044*4882a593Smuzhiyun 	.orphan_count	   = &dccp_orphan_count,
1045*4882a593Smuzhiyun 	.max_header	   = MAX_DCCP_HEADER,
1046*4882a593Smuzhiyun 	.obj_size	   = sizeof(struct dccp6_sock),
1047*4882a593Smuzhiyun 	.slab_flags	   = SLAB_TYPESAFE_BY_RCU,
1048*4882a593Smuzhiyun 	.rsk_prot	   = &dccp6_request_sock_ops,
1049*4882a593Smuzhiyun 	.twsk_prot	   = &dccp6_timewait_sock_ops,
1050*4882a593Smuzhiyun 	.h.hashinfo	   = &dccp_hashinfo,
1051*4882a593Smuzhiyun };
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun static const struct inet6_protocol dccp_v6_protocol = {
1054*4882a593Smuzhiyun 	.handler	= dccp_v6_rcv,
1055*4882a593Smuzhiyun 	.err_handler	= dccp_v6_err,
1056*4882a593Smuzhiyun 	.flags		= INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
1057*4882a593Smuzhiyun };
1058*4882a593Smuzhiyun 
1059*4882a593Smuzhiyun static const struct proto_ops inet6_dccp_ops = {
1060*4882a593Smuzhiyun 	.family		   = PF_INET6,
1061*4882a593Smuzhiyun 	.owner		   = THIS_MODULE,
1062*4882a593Smuzhiyun 	.release	   = inet6_release,
1063*4882a593Smuzhiyun 	.bind		   = inet6_bind,
1064*4882a593Smuzhiyun 	.connect	   = inet_stream_connect,
1065*4882a593Smuzhiyun 	.socketpair	   = sock_no_socketpair,
1066*4882a593Smuzhiyun 	.accept		   = inet_accept,
1067*4882a593Smuzhiyun 	.getname	   = inet6_getname,
1068*4882a593Smuzhiyun 	.poll		   = dccp_poll,
1069*4882a593Smuzhiyun 	.ioctl		   = inet6_ioctl,
1070*4882a593Smuzhiyun 	.gettstamp	   = sock_gettstamp,
1071*4882a593Smuzhiyun 	.listen		   = inet_dccp_listen,
1072*4882a593Smuzhiyun 	.shutdown	   = inet_shutdown,
1073*4882a593Smuzhiyun 	.setsockopt	   = sock_common_setsockopt,
1074*4882a593Smuzhiyun 	.getsockopt	   = sock_common_getsockopt,
1075*4882a593Smuzhiyun 	.sendmsg	   = inet_sendmsg,
1076*4882a593Smuzhiyun 	.recvmsg	   = sock_common_recvmsg,
1077*4882a593Smuzhiyun 	.mmap		   = sock_no_mmap,
1078*4882a593Smuzhiyun 	.sendpage	   = sock_no_sendpage,
1079*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
1080*4882a593Smuzhiyun 	.compat_ioctl	   = inet6_compat_ioctl,
1081*4882a593Smuzhiyun #endif
1082*4882a593Smuzhiyun };
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun static struct inet_protosw dccp_v6_protosw = {
1085*4882a593Smuzhiyun 	.type		= SOCK_DCCP,
1086*4882a593Smuzhiyun 	.protocol	= IPPROTO_DCCP,
1087*4882a593Smuzhiyun 	.prot		= &dccp_v6_prot,
1088*4882a593Smuzhiyun 	.ops		= &inet6_dccp_ops,
1089*4882a593Smuzhiyun 	.flags		= INET_PROTOSW_ICSK,
1090*4882a593Smuzhiyun };
1091*4882a593Smuzhiyun 
dccp_v6_init_net(struct net * net)1092*4882a593Smuzhiyun static int __net_init dccp_v6_init_net(struct net *net)
1093*4882a593Smuzhiyun {
1094*4882a593Smuzhiyun 	if (dccp_hashinfo.bhash == NULL)
1095*4882a593Smuzhiyun 		return -ESOCKTNOSUPPORT;
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
1098*4882a593Smuzhiyun 				    SOCK_DCCP, IPPROTO_DCCP, net);
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun 
dccp_v6_exit_net(struct net * net)1101*4882a593Smuzhiyun static void __net_exit dccp_v6_exit_net(struct net *net)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun 	inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
dccp_v6_exit_batch(struct list_head * net_exit_list)1106*4882a593Smuzhiyun static void __net_exit dccp_v6_exit_batch(struct list_head *net_exit_list)
1107*4882a593Smuzhiyun {
1108*4882a593Smuzhiyun 	inet_twsk_purge(&dccp_hashinfo, AF_INET6);
1109*4882a593Smuzhiyun }
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun static struct pernet_operations dccp_v6_ops = {
1112*4882a593Smuzhiyun 	.init   = dccp_v6_init_net,
1113*4882a593Smuzhiyun 	.exit   = dccp_v6_exit_net,
1114*4882a593Smuzhiyun 	.exit_batch = dccp_v6_exit_batch,
1115*4882a593Smuzhiyun };
1116*4882a593Smuzhiyun 
dccp_v6_init(void)1117*4882a593Smuzhiyun static int __init dccp_v6_init(void)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun 	int err = proto_register(&dccp_v6_prot, 1);
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	if (err)
1122*4882a593Smuzhiyun 		goto out;
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun 	inet6_register_protosw(&dccp_v6_protosw);
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 	err = register_pernet_subsys(&dccp_v6_ops);
1127*4882a593Smuzhiyun 	if (err)
1128*4882a593Smuzhiyun 		goto out_destroy_ctl_sock;
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun 	err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1131*4882a593Smuzhiyun 	if (err)
1132*4882a593Smuzhiyun 		goto out_unregister_proto;
1133*4882a593Smuzhiyun 
1134*4882a593Smuzhiyun out:
1135*4882a593Smuzhiyun 	return err;
1136*4882a593Smuzhiyun out_unregister_proto:
1137*4882a593Smuzhiyun 	unregister_pernet_subsys(&dccp_v6_ops);
1138*4882a593Smuzhiyun out_destroy_ctl_sock:
1139*4882a593Smuzhiyun 	inet6_unregister_protosw(&dccp_v6_protosw);
1140*4882a593Smuzhiyun 	proto_unregister(&dccp_v6_prot);
1141*4882a593Smuzhiyun 	goto out;
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun 
dccp_v6_exit(void)1144*4882a593Smuzhiyun static void __exit dccp_v6_exit(void)
1145*4882a593Smuzhiyun {
1146*4882a593Smuzhiyun 	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1147*4882a593Smuzhiyun 	unregister_pernet_subsys(&dccp_v6_ops);
1148*4882a593Smuzhiyun 	inet6_unregister_protosw(&dccp_v6_protosw);
1149*4882a593Smuzhiyun 	proto_unregister(&dccp_v6_prot);
1150*4882a593Smuzhiyun }
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun module_init(dccp_v6_init);
1153*4882a593Smuzhiyun module_exit(dccp_v6_exit);
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun /*
1156*4882a593Smuzhiyun  * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1157*4882a593Smuzhiyun  * values directly, Also cover the case where the protocol is not specified,
1158*4882a593Smuzhiyun  * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP
1159*4882a593Smuzhiyun  */
1160*4882a593Smuzhiyun MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6);
1161*4882a593Smuzhiyun MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6);
1162*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1163*4882a593Smuzhiyun MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1164*4882a593Smuzhiyun MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");
1165