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