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