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