[DCCP]: Support for partial checksums (RFC 4340, sec. 9.2)
[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>
17#include <linux/xfrm.h>
18
19#include <net/addrconf.h>
20#include <net/inet_common.h>
21#include <net/inet_hashtables.h>
14c85021 22#include <net/inet_sock.h>
3df80d93
ACM
23#include <net/inet6_connection_sock.h>
24#include <net/inet6_hashtables.h>
25#include <net/ip6_route.h>
26#include <net/ipv6.h>
27#include <net/protocol.h>
28#include <net/transp_v6.h>
aa0e4e4a 29#include <net/ip6_checksum.h>
3df80d93
ACM
30#include <net/xfrm.h>
31
32#include "dccp.h"
33#include "ipv6.h"
4b79f0af 34#include "feat.h"
3df80d93 35
72478873
ACM
36/* Socket used for sending RSTs and ACKs */
37static struct socket *dccp_v6_ctl_socket;
38
3df80d93
ACM
39static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
40static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
41
42static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
43{
44 return inet_csk_get_port(&dccp_hashinfo, sk, snum,
45 inet6_csk_bind_conflict);
46}
47
48static void dccp_v6_hash(struct sock *sk)
49{
50 if (sk->sk_state != DCCP_CLOSED) {
51 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
c985ed70 52 dccp_hash(sk);
3df80d93
ACM
53 return;
54 }
55 local_bh_disable();
56 __inet6_hash(&dccp_hashinfo, sk);
57 local_bh_enable();
58 }
59}
60
6f4e5fff
GR
61/* add pseudo-header to DCCP checksum stored in skb->csum */
62static inline u16 dccp_v6_csum_finish(struct sk_buff *skb,
63 struct in6_addr *saddr,
64 struct in6_addr *daddr)
3df80d93 65{
6f4e5fff
GR
66 return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
67}
68
69static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
70 struct sk_buff *skb)
71{
72 struct ipv6_pinfo *np = inet6_sk(sk);
73 struct dccp_hdr *dh = dccp_hdr(skb);
74
75 dccp_csum_outgoing(skb);
76 dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
3df80d93
ACM
77}
78
79static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
80{
81 const struct dccp_hdr *dh = dccp_hdr(skb);
82
83 if (skb->protocol == htons(ETH_P_IPV6))
84 return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
85 skb->nh.ipv6h->saddr.s6_addr32,
86 dh->dccph_dport,
87 dh->dccph_sport);
45329e71
ACM
88
89 return secure_dccp_sequence_number(skb->nh.iph->daddr,
90 skb->nh.iph->saddr,
91 dh->dccph_dport,
92 dh->dccph_sport);
3df80d93
ACM
93}
94
3df80d93 95static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
60fe62e7 96 int type, int code, int offset, __be32 info)
3df80d93
ACM
97{
98 struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
99 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
100 struct ipv6_pinfo *np;
101 struct sock *sk;
102 int err;
103 __u64 seq;
104
105 sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
f2776ff0 106 &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
3df80d93
ACM
107
108 if (sk == NULL) {
109 ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
110 return;
111 }
112
113 if (sk->sk_state == DCCP_TIME_WAIT) {
9469c7b4 114 inet_twsk_put(inet_twsk(sk));
3df80d93
ACM
115 return;
116 }
117
118 bh_lock_sock(sk);
119 if (sock_owned_by_user(sk))
120 NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
121
122 if (sk->sk_state == DCCP_CLOSED)
123 goto out;
124
125 np = inet6_sk(sk);
126
127 if (type == ICMPV6_PKT_TOOBIG) {
3df80d93
ACM
128 struct dst_entry *dst = NULL;
129
130 if (sock_owned_by_user(sk))
131 goto out;
132 if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED))
133 goto out;
134
135 /* icmp should have updated the destination cache entry */
136 dst = __sk_dst_check(sk, np->dst_cookie);
3df80d93
ACM
137 if (dst == NULL) {
138 struct inet_sock *inet = inet_sk(sk);
139 struct flowi fl;
140
141 /* BUGGG_FUTURE: Again, it is not clear how
142 to handle rthdr case. Ignore this complexity
143 for now.
144 */
145 memset(&fl, 0, sizeof(fl));
146 fl.proto = IPPROTO_DCCP;
147 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
148 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
149 fl.oif = sk->sk_bound_dev_if;
150 fl.fl_ip_dport = inet->dport;
151 fl.fl_ip_sport = inet->sport;
beb8d13b 152 security_sk_classify_flow(sk, &fl);
3df80d93 153
45329e71
ACM
154 err = ip6_dst_lookup(sk, &dst, &fl);
155 if (err) {
3df80d93
ACM
156 sk->sk_err_soft = -err;
157 goto out;
158 }
159
45329e71
ACM
160 err = xfrm_lookup(&dst, &fl, sk, 0);
161 if (err < 0) {
3df80d93
ACM
162 sk->sk_err_soft = -err;
163 goto out;
164 }
3df80d93
ACM
165 } else
166 dst_hold(dst);
167
d83d8461 168 if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
3df80d93
ACM
169 dccp_sync_mss(sk, dst_mtu(dst));
170 } /* else let the usual retransmit timer handle it */
171 dst_release(dst);
172 goto out;
173 }
174
175 icmpv6_err_convert(type, code, &err);
176
177 seq = DCCP_SKB_CB(skb)->dccpd_seq;
178 /* Might be for an request_sock */
179 switch (sk->sk_state) {
180 struct request_sock *req, **prev;
181 case DCCP_LISTEN:
182 if (sock_owned_by_user(sk))
183 goto out;
184
185 req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
186 &hdr->daddr, &hdr->saddr,
187 inet6_iif(skb));
45329e71 188 if (req == NULL)
3df80d93
ACM
189 goto out;
190
45329e71
ACM
191 /*
192 * ICMPs are not backlogged, hence we cannot get an established
193 * socket here.
3df80d93
ACM
194 */
195 BUG_TRAP(req->sk == NULL);
196
197 if (seq != dccp_rsk(req)->dreq_iss) {
198 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
199 goto out;
200 }
201
202 inet_csk_reqsk_queue_drop(sk, req, prev);
203 goto out;
204
205 case DCCP_REQUESTING:
206 case DCCP_RESPOND: /* Cannot happen.
45329e71 207 It can, it SYNs are crossed. --ANK */
3df80d93
ACM
208 if (!sock_owned_by_user(sk)) {
209 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
210 sk->sk_err = err;
211 /*
212 * Wake people up to see the error
213 * (see connect in sock.c)
214 */
215 sk->sk_error_report(sk);
3df80d93
ACM
216 dccp_done(sk);
217 } else
218 sk->sk_err_soft = err;
219 goto out;
220 }
221
222 if (!sock_owned_by_user(sk) && np->recverr) {
223 sk->sk_err = err;
224 sk->sk_error_report(sk);
225 } else
226 sk->sk_err_soft = err;
227
228out:
229 bh_unlock_sock(sk);
230 sock_put(sk);
231}
232
233
234static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
235 struct dst_entry *dst)
236{
237 struct inet6_request_sock *ireq6 = inet6_rsk(req);
238 struct ipv6_pinfo *np = inet6_sk(sk);
239 struct sk_buff *skb;
240 struct ipv6_txoptions *opt = NULL;
241 struct in6_addr *final_p = NULL, final;
242 struct flowi fl;
243 int err = -1;
244
245 memset(&fl, 0, sizeof(fl));
246 fl.proto = IPPROTO_DCCP;
247 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
248 ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
249 fl.fl6_flowlabel = 0;
250 fl.oif = ireq6->iif;
251 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
252 fl.fl_ip_sport = inet_sk(sk)->sport;
4237c75c 253 security_req_classify_flow(req, &fl);
3df80d93
ACM
254
255 if (dst == NULL) {
256 opt = np->opt;
257 if (opt == NULL &&
258 np->rxopt.bits.osrcrt == 2 &&
259 ireq6->pktopts) {
260 struct sk_buff *pktopts = ireq6->pktopts;
261 struct inet6_skb_parm *rxopt = IP6CB(pktopts);
45329e71 262
3df80d93
ACM
263 if (rxopt->srcrt)
264 opt = ipv6_invert_rthdr(sk,
265 (struct ipv6_rt_hdr *)(pktopts->nh.raw +
266 rxopt->srcrt));
267 }
268
45329e71
ACM
269 if (opt != NULL && opt->srcrt != NULL) {
270 const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
271
3df80d93
ACM
272 ipv6_addr_copy(&final, &fl.fl6_dst);
273 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
274 final_p = &final;
275 }
276
277 err = ip6_dst_lookup(sk, &dst, &fl);
278 if (err)
279 goto done;
45329e71 280
3df80d93
ACM
281 if (final_p)
282 ipv6_addr_copy(&fl.fl6_dst, final_p);
45329e71
ACM
283
284 err = xfrm_lookup(&dst, &fl, sk, 0);
285 if (err < 0)
3df80d93
ACM
286 goto done;
287 }
288
289 skb = dccp_make_response(sk, dst, req);
290 if (skb != NULL) {
291 struct dccp_hdr *dh = dccp_hdr(skb);
45329e71 292
6f4e5fff
GR
293 dh->dccph_checksum = dccp_v6_csum_finish(skb,
294 &ireq6->loc_addr,
295 &ireq6->rmt_addr);
3df80d93
ACM
296 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
297 err = ip6_xmit(sk, skb, &fl, opt, 0);
298 if (err == NET_XMIT_CN)
299 err = 0;
300 }
301
302done:
45329e71 303 if (opt != NULL && opt != np->opt)
3df80d93 304 sock_kfree_s(sk, opt, opt->tot_len);
0cbd7825 305 dst_release(dst);
3df80d93
ACM
306 return err;
307}
308
309static void dccp_v6_reqsk_destructor(struct request_sock *req)
310{
311 if (inet6_rsk(req)->pktopts != NULL)
312 kfree_skb(inet6_rsk(req)->pktopts);
313}
314
3df80d93
ACM
315static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
316{
45329e71 317 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
118b2c95 318 const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
3df80d93
ACM
319 sizeof(struct dccp_hdr_ext) +
320 sizeof(struct dccp_hdr_reset);
321 struct sk_buff *skb;
322 struct flowi fl;
323 u64 seqno;
324
325 if (rxdh->dccph_type == DCCP_PKT_RESET)
326 return;
327
328 if (!ipv6_unicast_destination(rxskb))
45329e71 329 return;
3df80d93 330
118b2c95
ACM
331 skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
332 GFP_ATOMIC);
45329e71 333 if (skb == NULL)
3df80d93
ACM
334 return;
335
118b2c95 336 skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
3df80d93 337
9b42078e 338 dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
3df80d93
ACM
339
340 /* Swap the send and the receive. */
341 dh->dccph_type = DCCP_PKT_RESET;
342 dh->dccph_sport = rxdh->dccph_dport;
343 dh->dccph_dport = rxdh->dccph_sport;
344 dh->dccph_doff = dccp_hdr_reset_len / 4;
345 dh->dccph_x = 1;
346 dccp_hdr_reset(skb)->dccph_reset_code =
347 DCCP_SKB_CB(rxskb)->dccpd_reset_code;
348
0e64e94e 349 /* See "8.3.1. Abnormal Termination" in RFC 4340 */
3df80d93
ACM
350 seqno = 0;
351 if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
352 dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
353
354 dccp_hdr_set_seq(dh, seqno);
355 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
356 DCCP_SKB_CB(rxskb)->dccpd_seq);
357
6f4e5fff
GR
358 dccp_csum_outgoing(skb);
359 dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
360 &rxskb->nh.ipv6h->daddr);
361
3df80d93
ACM
362 memset(&fl, 0, sizeof(fl));
363 ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
364 ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
6f4e5fff 365
3df80d93
ACM
366 fl.proto = IPPROTO_DCCP;
367 fl.oif = inet6_iif(rxskb);
368 fl.fl_ip_dport = dh->dccph_dport;
369 fl.fl_ip_sport = dh->dccph_sport;
beb8d13b 370 security_skb_classify_flow(rxskb, &fl);
3df80d93
ACM
371
372 /* sk = NULL, but it is safe for now. RST socket required. */
373 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
374 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
72478873 375 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
3df80d93
ACM
376 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
377 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
378 return;
379 }
380 }
381
382 kfree_skb(skb);
383}
384
73c9e02c
GR
385static struct request_sock_ops dccp6_request_sock_ops = {
386 .family = AF_INET6,
387 .obj_size = sizeof(struct dccp6_request_sock),
388 .rtx_syn_ack = dccp_v6_send_response,
389 .send_ack = dccp_reqsk_send_ack,
390 .destructor = dccp_v6_reqsk_destructor,
391 .send_reset = dccp_v6_ctl_send_reset,
392};
393
3df80d93
ACM
394static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
395{
396 const struct dccp_hdr *dh = dccp_hdr(skb);
397 const struct ipv6hdr *iph = skb->nh.ipv6h;
398 struct sock *nsk;
399 struct request_sock **prev;
400 /* Find possible connection requests. */
401 struct request_sock *req = inet6_csk_search_req(sk, &prev,
402 dh->dccph_sport,
403 &iph->saddr,
404 &iph->daddr,
405 inet6_iif(skb));
406 if (req != NULL)
407 return dccp_check_req(sk, skb, req, prev);
408
409 nsk = __inet6_lookup_established(&dccp_hashinfo,
410 &iph->saddr, dh->dccph_sport,
411 &iph->daddr, ntohs(dh->dccph_dport),
412 inet6_iif(skb));
3df80d93
ACM
413 if (nsk != NULL) {
414 if (nsk->sk_state != DCCP_TIME_WAIT) {
415 bh_lock_sock(nsk);
416 return nsk;
417 }
9469c7b4 418 inet_twsk_put(inet_twsk(nsk));
3df80d93
ACM
419 return NULL;
420 }
421
422 return sk;
423}
424
425static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
426{
3df80d93
ACM
427 struct request_sock *req;
428 struct dccp_request_sock *dreq;
429 struct inet6_request_sock *ireq6;
430 struct ipv6_pinfo *np = inet6_sk(sk);
60fe62e7 431 const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
3df80d93
ACM
432 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
433 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
434
435 if (skb->protocol == htons(ETH_P_IP))
436 return dccp_v4_conn_request(sk, skb);
437
438 if (!ipv6_unicast_destination(skb))
45329e71 439 goto drop;
3df80d93
ACM
440
441 if (dccp_bad_service_code(sk, service)) {
442 reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
443 goto drop;
444 }
445 /*
45329e71 446 * There are no SYN attacks on IPv6, yet...
3df80d93
ACM
447 */
448 if (inet_csk_reqsk_queue_is_full(sk))
45329e71 449 goto drop;
3df80d93
ACM
450
451 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
452 goto drop;
453
82709531 454 req = inet6_reqsk_alloc(&dccp6_request_sock_ops);
3df80d93
ACM
455 if (req == NULL)
456 goto drop;
457
cf557926
GR
458 if (dccp_parse_options(sk, skb))
459 goto drop_and_free;
3df80d93 460
cf557926 461 dccp_reqsk_init(req, skb);
3df80d93 462
4237c75c
VY
463 if (security_inet_conn_request(sk, skb, req))
464 goto drop_and_free;
465
3df80d93 466 ireq6 = inet6_rsk(req);
3df80d93
ACM
467 ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
468 ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
3df80d93
ACM
469 ireq6->pktopts = NULL;
470
471 if (ipv6_opt_accepted(sk, skb) ||
472 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
473 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
474 atomic_inc(&skb->users);
475 ireq6->pktopts = skb;
476 }
477 ireq6->iif = sk->sk_bound_dev_if;
478
479 /* So that link locals have meaning */
480 if (!sk->sk_bound_dev_if &&
481 ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
482 ireq6->iif = inet6_iif(skb);
483
45329e71 484 /*
3df80d93
ACM
485 * Step 3: Process LISTEN state
486 *
d83ca5ac 487 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
3df80d93 488 *
d83ca5ac
GR
489 * In fact we defer setting S.GSR, S.SWL, S.SWH to
490 * dccp_create_openreq_child.
3df80d93
ACM
491 */
492 dreq = dccp_rsk(req);
493 dreq->dreq_isr = dcb->dccpd_seq;
494 dreq->dreq_iss = dccp_v6_init_sequence(sk, skb);
495 dreq->dreq_service = service;
496
497 if (dccp_v6_send_response(sk, req, NULL))
498 goto drop_and_free;
499
500 inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
501 return 0;
502
503drop_and_free:
504 reqsk_free(req);
505drop:
506 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
507 dcb->dccpd_reset_code = reset_code;
508 return -1;
509}
510
511static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
512 struct sk_buff *skb,
513 struct request_sock *req,
514 struct dst_entry *dst)
515{
516 struct inet6_request_sock *ireq6 = inet6_rsk(req);
517 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
518 struct inet_sock *newinet;
519 struct dccp_sock *newdp;
520 struct dccp6_sock *newdp6;
521 struct sock *newsk;
522 struct ipv6_txoptions *opt;
523
524 if (skb->protocol == htons(ETH_P_IP)) {
525 /*
526 * v6 mapped
527 */
3df80d93 528 newsk = dccp_v4_request_recv_sock(sk, skb, req, dst);
45329e71 529 if (newsk == NULL)
3df80d93
ACM
530 return NULL;
531
532 newdp6 = (struct dccp6_sock *)newsk;
533 newdp = dccp_sk(newsk);
534 newinet = inet_sk(newsk);
535 newinet->pinet6 = &newdp6->inet6;
536 newnp = inet6_sk(newsk);
537
538 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
539
540 ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF),
541 newinet->daddr);
542
543 ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF),
544 newinet->saddr);
545
546 ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);
547
548 inet_csk(newsk)->icsk_af_ops = &dccp_ipv6_mapped;
549 newsk->sk_backlog_rcv = dccp_v4_do_rcv;
550 newnp->pktoptions = NULL;
551 newnp->opt = NULL;
552 newnp->mcast_oif = inet6_iif(skb);
553 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
554
555 /*
556 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
557 * here, dccp_create_openreq_child now does this for us, see the comment in
558 * that function for the gory details. -acme
559 */
560
561 /* It is tricky place. Until this moment IPv4 tcp
562 worked with IPv6 icsk.icsk_af_ops.
563 Sync it now.
564 */
d83d8461 565 dccp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
3df80d93
ACM
566
567 return newsk;
568 }
569
570 opt = np->opt;
571
572 if (sk_acceptq_is_full(sk))
573 goto out_overflow;
574
45329e71
ACM
575 if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) {
576 const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
577
3df80d93
ACM
578 if (rxopt->srcrt)
579 opt = ipv6_invert_rthdr(sk,
580 (struct ipv6_rt_hdr *)(ireq6->pktopts->nh.raw +
581 rxopt->srcrt));
582 }
583
584 if (dst == NULL) {
585 struct in6_addr *final_p = NULL, final;
586 struct flowi fl;
587
588 memset(&fl, 0, sizeof(fl));
589 fl.proto = IPPROTO_DCCP;
590 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
45329e71
ACM
591 if (opt != NULL && opt->srcrt != NULL) {
592 const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
593
3df80d93
ACM
594 ipv6_addr_copy(&final, &fl.fl6_dst);
595 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
596 final_p = &final;
597 }
598 ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
599 fl.oif = sk->sk_bound_dev_if;
600 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
601 fl.fl_ip_sport = inet_sk(sk)->sport;
beb8d13b 602 security_sk_classify_flow(sk, &fl);
3df80d93
ACM
603
604 if (ip6_dst_lookup(sk, &dst, &fl))
605 goto out;
606
607 if (final_p)
608 ipv6_addr_copy(&fl.fl6_dst, final_p);
609
610 if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
611 goto out;
45329e71 612 }
3df80d93
ACM
613
614 newsk = dccp_create_openreq_child(sk, req, skb);
615 if (newsk == NULL)
616 goto out;
617
618 /*
619 * No need to charge this sock to the relevant IPv6 refcnt debug socks
620 * count here, dccp_create_openreq_child now does this for us, see the
621 * comment in that function for the gory details. -acme
622 */
623
8e1ef0a9 624 __ip6_dst_store(newsk, dst, NULL, NULL);
45329e71
ACM
625 newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
626 NETIF_F_TSO);
3df80d93
ACM
627 newdp6 = (struct dccp6_sock *)newsk;
628 newinet = inet_sk(newsk);
629 newinet->pinet6 = &newdp6->inet6;
630 newdp = dccp_sk(newsk);
631 newnp = inet6_sk(newsk);
632
633 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
634
635 ipv6_addr_copy(&newnp->daddr, &ireq6->rmt_addr);
636 ipv6_addr_copy(&newnp->saddr, &ireq6->loc_addr);
637 ipv6_addr_copy(&newnp->rcv_saddr, &ireq6->loc_addr);
638 newsk->sk_bound_dev_if = ireq6->iif;
639
45329e71 640 /* Now IPv6 options...
3df80d93
ACM
641
642 First: no IPv4 options.
643 */
644 newinet->opt = NULL;
645
646 /* Clone RX bits */
647 newnp->rxopt.all = np->rxopt.all;
648
649 /* Clone pktoptions received with SYN */
650 newnp->pktoptions = NULL;
651 if (ireq6->pktopts != NULL) {
652 newnp->pktoptions = skb_clone(ireq6->pktopts, GFP_ATOMIC);
653 kfree_skb(ireq6->pktopts);
654 ireq6->pktopts = NULL;
655 if (newnp->pktoptions)
656 skb_set_owner_r(newnp->pktoptions, newsk);
657 }
658 newnp->opt = NULL;
659 newnp->mcast_oif = inet6_iif(skb);
660 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
661
45329e71
ACM
662 /*
663 * Clone native IPv6 options from listening socket (if any)
664 *
665 * Yes, keeping reference count would be much more clever, but we make
666 * one more one thing there: reattach optmem to newsk.
3df80d93 667 */
45329e71 668 if (opt != NULL) {
3df80d93
ACM
669 newnp->opt = ipv6_dup_options(newsk, opt);
670 if (opt != np->opt)
671 sock_kfree_s(sk, opt, opt->tot_len);
672 }
673
d83d8461 674 inet_csk(newsk)->icsk_ext_hdr_len = 0;
45329e71 675 if (newnp->opt != NULL)
d83d8461
ACM
676 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
677 newnp->opt->opt_flen);
3df80d93
ACM
678
679 dccp_sync_mss(newsk, dst_mtu(dst));
680
681 newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
682
683 __inet6_hash(&dccp_hashinfo, newsk);
684 inet_inherit_port(&dccp_hashinfo, sk, newsk);
685
686 return newsk;
687
688out_overflow:
689 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
690out:
691 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
45329e71 692 if (opt != NULL && opt != np->opt)
3df80d93
ACM
693 sock_kfree_s(sk, opt, opt->tot_len);
694 dst_release(dst);
695 return NULL;
696}
697
698/* The socket must have it's spinlock held when we get
699 * here.
700 *
701 * We have a potential double-lock case here, so even when
702 * doing backlog processing we use the BH locking scheme.
703 * This is because we cannot sleep with the original spinlock
704 * held.
705 */
706static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
707{
708 struct ipv6_pinfo *np = inet6_sk(sk);
709 struct sk_buff *opt_skb = NULL;
710
711 /* Imagine: socket is IPv6. IPv4 packet arrives,
712 goes to IPv4 receive handler and backlogged.
713 From backlog it always goes here. Kerboom...
714 Fortunately, dccp_rcv_established and rcv_established
715 handle them correctly, but it is not case with
716 dccp_v6_hnd_req and dccp_v6_ctl_send_reset(). --ANK
717 */
718
719 if (skb->protocol == htons(ETH_P_IP))
720 return dccp_v4_do_rcv(sk, skb);
721
fda9ef5d 722 if (sk_filter(sk, skb))
3df80d93
ACM
723 goto discard;
724
725 /*
45329e71
ACM
726 * socket locking is here for SMP purposes as backlog rcv is currently
727 * called with bh processing disabled.
3df80d93
ACM
728 */
729
730 /* Do Stevens' IPV6_PKTOPTIONS.
731
732 Yes, guys, it is the only place in our code, where we
733 may make it not affecting IPv4.
734 The rest of code is protocol independent,
735 and I do not like idea to uglify IPv4.
736
737 Actually, all the idea behind IPV6_PKTOPTIONS
738 looks not very well thought. For now we latch
739 options, received in the last packet, enqueued
740 by tcp. Feel free to propose better solution.
741 --ANK (980728)
742 */
743 if (np->rxopt.all)
89e7e577
GR
744 /*
745 * FIXME: Add handling of IPV6_PKTOPTIONS skb. See the comments below
746 * (wrt ipv6_pktopions) and net/ipv6/tcp_ipv6.c for an example.
747 */
3df80d93
ACM
748 opt_skb = skb_clone(skb, GFP_ATOMIC);
749
750 if (sk->sk_state == DCCP_OPEN) { /* Fast path */
751 if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
752 goto reset;
fd169f15 753 if (opt_skb) {
89e7e577 754 /* XXX This is where we would goto ipv6_pktoptions. */
fd169f15
DM
755 __kfree_skb(opt_skb);
756 }
3df80d93
ACM
757 return 0;
758 }
759
d83ca5ac
GR
760 /*
761 * Step 3: Process LISTEN state
762 * If S.state == LISTEN,
763 * If P.type == Request or P contains a valid Init Cookie option,
764 * (* Must scan the packet's options to check for Init
765 * Cookies. Only Init Cookies are processed here,
766 * however; other options are processed in Step 8. This
767 * scan need only be performed if the endpoint uses Init
768 * Cookies *)
769 * (* Generate a new socket and switch to that socket *)
770 * Set S := new socket for this port pair
771 * S.state = RESPOND
772 * Choose S.ISS (initial seqno) or set from Init Cookies
773 * Initialize S.GAR := S.ISS
774 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
775 * Continue with S.state == RESPOND
776 * (* A Response packet will be generated in Step 11 *)
777 * Otherwise,
778 * Generate Reset(No Connection) unless P.type == Reset
779 * Drop packet and return
780 *
781 * NOTE: the check for the packet types is done in
782 * dccp_rcv_state_process
783 */
45329e71 784 if (sk->sk_state == DCCP_LISTEN) {
3df80d93 785 struct sock *nsk = dccp_v6_hnd_req(sk, skb);
3df80d93 786
45329e71
ACM
787 if (nsk == NULL)
788 goto discard;
3df80d93
ACM
789 /*
790 * Queue it on the new socket if the new socket is active,
791 * otherwise we just shortcircuit this and continue with
792 * the new socket..
793 */
45329e71 794 if (nsk != sk) {
3df80d93
ACM
795 if (dccp_child_process(sk, nsk, skb))
796 goto reset;
45329e71 797 if (opt_skb != NULL)
3df80d93
ACM
798 __kfree_skb(opt_skb);
799 return 0;
800 }
801 }
802
803 if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
804 goto reset;
fd169f15 805 if (opt_skb) {
89e7e577 806 /* XXX This is where we would goto ipv6_pktoptions. */
fd169f15
DM
807 __kfree_skb(opt_skb);
808 }
3df80d93
ACM
809 return 0;
810
811reset:
812 dccp_v6_ctl_send_reset(skb);
813discard:
45329e71 814 if (opt_skb != NULL)
3df80d93
ACM
815 __kfree_skb(opt_skb);
816 kfree_skb(skb);
817 return 0;
818}
819
951dbc8a 820static int dccp_v6_rcv(struct sk_buff **pskb)
3df80d93
ACM
821{
822 const struct dccp_hdr *dh;
823 struct sk_buff *skb = *pskb;
824 struct sock *sk;
6f4e5fff 825 int min_cov;
3df80d93 826
6f4e5fff 827 /* Step 1: Check header basics */
3df80d93
ACM
828
829 if (dccp_invalid_packet(skb))
830 goto discard_it;
831
6f4e5fff
GR
832 /* Step 1: If header checksum is incorrect, drop packet and return. */
833 if (dccp_v6_csum_finish(skb, &skb->nh.ipv6h->saddr,
834 &skb->nh.ipv6h->daddr)) {
835 LIMIT_NETDEBUG(KERN_WARNING
836 "%s: dropped packet with invalid checksum\n",
837 __FUNCTION__);
838 goto discard_it;
839 }
840
3df80d93
ACM
841 dh = dccp_hdr(skb);
842
843 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
844 DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
845
846 if (dccp_packet_without_ack(skb))
847 DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
848 else
849 DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
850
851 /* Step 2:
852 * Look up flow ID in table and get corresponding socket */
853 sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
854 dh->dccph_sport,
855 &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
856 inet6_iif(skb));
45329e71 857 /*
3df80d93
ACM
858 * Step 2:
859 * If no socket ...
3df80d93 860 */
d23c7107
GR
861 if (sk == NULL) {
862 dccp_pr_debug("failed to look up flow ID in table and "
863 "get corresponding socket\n");
3df80d93 864 goto no_dccp_socket;
d23c7107 865 }
3df80d93 866
45329e71 867 /*
3df80d93
ACM
868 * Step 2:
869 * ... or S.state == TIMEWAIT,
870 * Generate Reset(No Connection) unless P.type == Reset
871 * Drop packet and return
872 */
d23c7107
GR
873 if (sk->sk_state == DCCP_TIME_WAIT) {
874 dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");
875 inet_twsk_put(inet_twsk(sk));
876 goto no_dccp_socket;
877 }
3df80d93 878
6f4e5fff
GR
879 /*
880 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
881 * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
882 * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
883 */
884 min_cov = dccp_sk(sk)->dccps_pcrlen;
885 if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
886 dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
887 dh->dccph_cscov, min_cov);
888 /* FIXME: send Data Dropped option (see also dccp_v4_rcv) */
889 goto discard_and_relse;
890 }
891
3df80d93
ACM
892 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
893 goto discard_and_relse;
894
25995ff5 895 return sk_receive_skb(sk, skb) ? -1 : 0;
3df80d93
ACM
896
897no_dccp_socket:
898 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
899 goto discard_it;
900 /*
901 * Step 2:
d83ca5ac 902 * If no socket ...
3df80d93
ACM
903 * Generate Reset(No Connection) unless P.type == Reset
904 * Drop packet and return
905 */
906 if (dh->dccph_type != DCCP_PKT_RESET) {
907 DCCP_SKB_CB(skb)->dccpd_reset_code =
908 DCCP_RESET_CODE_NO_CONNECTION;
909 dccp_v6_ctl_send_reset(skb);
910 }
3df80d93 911
d23c7107 912discard_it:
3df80d93
ACM
913 kfree_skb(skb);
914 return 0;
915
916discard_and_relse:
917 sock_put(sk);
918 goto discard_it;
3df80d93
ACM
919}
920
73c9e02c
GR
921static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
922 int addr_len)
923{
924 struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
925 struct inet_connection_sock *icsk = inet_csk(sk);
926 struct inet_sock *inet = inet_sk(sk);
927 struct ipv6_pinfo *np = inet6_sk(sk);
928 struct dccp_sock *dp = dccp_sk(sk);
929 struct in6_addr *saddr = NULL, *final_p = NULL, final;
930 struct flowi fl;
931 struct dst_entry *dst;
932 int addr_type;
933 int err;
934
935 dp->dccps_role = DCCP_ROLE_CLIENT;
936
937 if (addr_len < SIN6_LEN_RFC2133)
938 return -EINVAL;
939
940 if (usin->sin6_family != AF_INET6)
941 return -EAFNOSUPPORT;
942
943 memset(&fl, 0, sizeof(fl));
944
945 if (np->sndflow) {
946 fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
947 IP6_ECN_flow_init(fl.fl6_flowlabel);
948 if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
949 struct ip6_flowlabel *flowlabel;
950 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
951 if (flowlabel == NULL)
952 return -EINVAL;
953 ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
954 fl6_sock_release(flowlabel);
955 }
956 }
957 /*
958 * connect() to INADDR_ANY means loopback (BSD'ism).
959 */
960 if (ipv6_addr_any(&usin->sin6_addr))
961 usin->sin6_addr.s6_addr[15] = 1;
962
963 addr_type = ipv6_addr_type(&usin->sin6_addr);
964
965 if (addr_type & IPV6_ADDR_MULTICAST)
966 return -ENETUNREACH;
967
968 if (addr_type & IPV6_ADDR_LINKLOCAL) {
969 if (addr_len >= sizeof(struct sockaddr_in6) &&
970 usin->sin6_scope_id) {
971 /* If interface is set while binding, indices
972 * must coincide.
973 */
974 if (sk->sk_bound_dev_if &&
975 sk->sk_bound_dev_if != usin->sin6_scope_id)
976 return -EINVAL;
977
978 sk->sk_bound_dev_if = usin->sin6_scope_id;
979 }
980
981 /* Connect to link-local address requires an interface */
982 if (!sk->sk_bound_dev_if)
983 return -EINVAL;
984 }
985
986 ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
987 np->flow_label = fl.fl6_flowlabel;
988
989 /*
990 * DCCP over IPv4
991 */
992 if (addr_type == IPV6_ADDR_MAPPED) {
993 u32 exthdrlen = icsk->icsk_ext_hdr_len;
994 struct sockaddr_in sin;
995
996 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
997
998 if (__ipv6_only_sock(sk))
999 return -ENETUNREACH;
1000
1001 sin.sin_family = AF_INET;
1002 sin.sin_port = usin->sin6_port;
1003 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
1004
1005 icsk->icsk_af_ops = &dccp_ipv6_mapped;
1006 sk->sk_backlog_rcv = dccp_v4_do_rcv;
1007
1008 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
1009 if (err) {
1010 icsk->icsk_ext_hdr_len = exthdrlen;
1011 icsk->icsk_af_ops = &dccp_ipv6_af_ops;
1012 sk->sk_backlog_rcv = dccp_v6_do_rcv;
1013 goto failure;
1014 } else {
1015 ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
1016 inet->saddr);
1017 ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
1018 inet->rcv_saddr);
1019 }
1020
1021 return err;
1022 }
1023
1024 if (!ipv6_addr_any(&np->rcv_saddr))
1025 saddr = &np->rcv_saddr;
1026
1027 fl.proto = IPPROTO_DCCP;
1028 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1029 ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
1030 fl.oif = sk->sk_bound_dev_if;
1031 fl.fl_ip_dport = usin->sin6_port;
1032 fl.fl_ip_sport = inet->sport;
1033 security_sk_classify_flow(sk, &fl);
1034
1035 if (np->opt != NULL && np->opt->srcrt != NULL) {
1036 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
1037
1038 ipv6_addr_copy(&final, &fl.fl6_dst);
1039 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1040 final_p = &final;
1041 }
1042
1043 err = ip6_dst_lookup(sk, &dst, &fl);
1044 if (err)
1045 goto failure;
1046
1047 if (final_p)
1048 ipv6_addr_copy(&fl.fl6_dst, final_p);
1049
1050 err = xfrm_lookup(&dst, &fl, sk, 0);
1051 if (err < 0)
1052 goto failure;
1053
1054 if (saddr == NULL) {
1055 saddr = &fl.fl6_src;
1056 ipv6_addr_copy(&np->rcv_saddr, saddr);
1057 }
1058
1059 /* set the source address */
1060 ipv6_addr_copy(&np->saddr, saddr);
1061 inet->rcv_saddr = LOOPBACK4_IPV6;
1062
1063 __ip6_dst_store(sk, dst, NULL, NULL);
1064
1065 icsk->icsk_ext_hdr_len = 0;
1066 if (np->opt != NULL)
1067 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
1068 np->opt->opt_nflen);
1069
1070 inet->dport = usin->sin6_port;
1071
1072 dccp_set_state(sk, DCCP_REQUESTING);
1073 err = inet6_hash_connect(&dccp_death_row, sk);
1074 if (err)
1075 goto late_failure;
1076 /* FIXME */
1077#if 0
1078 dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
1079 np->daddr.s6_addr32,
1080 inet->sport,
1081 inet->dport);
1082#endif
1083 err = dccp_connect(sk);
1084 if (err)
1085 goto late_failure;
1086
1087 return 0;
1088
1089late_failure:
1090 dccp_set_state(sk, DCCP_CLOSED);
1091 __sk_dst_reset(sk);
1092failure:
1093 inet->dport = 0;
1094 sk->sk_route_caps = 0;
1095 return err;
1096}
1097
3df80d93 1098static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
543d9cfe
ACM
1099 .queue_xmit = inet6_csk_xmit,
1100 .send_check = dccp_v6_send_check,
1101 .rebuild_header = inet6_sk_rebuild_header,
1102 .conn_request = dccp_v6_conn_request,
1103 .syn_recv_sock = dccp_v6_request_recv_sock,
1104 .net_header_len = sizeof(struct ipv6hdr),
1105 .setsockopt = ipv6_setsockopt,
1106 .getsockopt = ipv6_getsockopt,
1107 .addr2sockaddr = inet6_csk_addr2sockaddr,
1108 .sockaddr_len = sizeof(struct sockaddr_in6),
3fdadf7d 1109#ifdef CONFIG_COMPAT
543d9cfe
ACM
1110 .compat_setsockopt = compat_ipv6_setsockopt,
1111 .compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d 1112#endif
3df80d93
ACM
1113};
1114
1115/*
1116 * DCCP over IPv4 via INET6 API
1117 */
1118static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
543d9cfe
ACM
1119 .queue_xmit = ip_queue_xmit,
1120 .send_check = dccp_v4_send_check,
1121 .rebuild_header = inet_sk_rebuild_header,
1122 .conn_request = dccp_v6_conn_request,
1123 .syn_recv_sock = dccp_v6_request_recv_sock,
1124 .net_header_len = sizeof(struct iphdr),
1125 .setsockopt = ipv6_setsockopt,
1126 .getsockopt = ipv6_getsockopt,
1127 .addr2sockaddr = inet6_csk_addr2sockaddr,
1128 .sockaddr_len = sizeof(struct sockaddr_in6),
3fdadf7d 1129#ifdef CONFIG_COMPAT
543d9cfe
ACM
1130 .compat_setsockopt = compat_ipv6_setsockopt,
1131 .compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d 1132#endif
3df80d93
ACM
1133};
1134
1135/* NOTE: A lot of things set to zero explicitly by call to
1136 * sk_alloc() so need not be done here.
1137 */
1138static int dccp_v6_init_sock(struct sock *sk)
1139{
72478873
ACM
1140 static __u8 dccp_v6_ctl_sock_initialized;
1141 int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
3df80d93 1142
72478873
ACM
1143 if (err == 0) {
1144 if (unlikely(!dccp_v6_ctl_sock_initialized))
1145 dccp_v6_ctl_sock_initialized = 1;
3df80d93 1146 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
72478873 1147 }
3df80d93
ACM
1148
1149 return err;
1150}
1151
1152static int dccp_v6_destroy_sock(struct sock *sk)
1153{
3e0fadc5 1154 dccp_destroy_sock(sk);
3df80d93
ACM
1155 return inet6_destroy_sock(sk);
1156}
1157
73c9e02c
GR
1158static struct timewait_sock_ops dccp6_timewait_sock_ops = {
1159 .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
1160};
1161
3df80d93 1162static struct proto dccp_v6_prot = {
543d9cfe
ACM
1163 .name = "DCCPv6",
1164 .owner = THIS_MODULE,
1165 .close = dccp_close,
1166 .connect = dccp_v6_connect,
1167 .disconnect = dccp_disconnect,
1168 .ioctl = dccp_ioctl,
1169 .init = dccp_v6_init_sock,
1170 .setsockopt = dccp_setsockopt,
1171 .getsockopt = dccp_getsockopt,
1172 .sendmsg = dccp_sendmsg,
1173 .recvmsg = dccp_recvmsg,
1174 .backlog_rcv = dccp_v6_do_rcv,
1175 .hash = dccp_v6_hash,
1176 .unhash = dccp_unhash,
1177 .accept = inet_csk_accept,
1178 .get_port = dccp_v6_get_port,
1179 .shutdown = dccp_shutdown,
1180 .destroy = dccp_v6_destroy_sock,
1181 .orphan_count = &dccp_orphan_count,
1182 .max_header = MAX_DCCP_HEADER,
1183 .obj_size = sizeof(struct dccp6_sock),
1184 .rsk_prot = &dccp6_request_sock_ops,
1185 .twsk_prot = &dccp6_timewait_sock_ops,
3fdadf7d 1186#ifdef CONFIG_COMPAT
543d9cfe
ACM
1187 .compat_setsockopt = compat_dccp_setsockopt,
1188 .compat_getsockopt = compat_dccp_getsockopt,
3fdadf7d 1189#endif
3df80d93
ACM
1190};
1191
1192static struct inet6_protocol dccp_v6_protocol = {
45329e71
ACM
1193 .handler = dccp_v6_rcv,
1194 .err_handler = dccp_v6_err,
1195 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
3df80d93
ACM
1196};
1197
1198static struct proto_ops inet6_dccp_ops = {
543d9cfe
ACM
1199 .family = PF_INET6,
1200 .owner = THIS_MODULE,
1201 .release = inet6_release,
1202 .bind = inet6_bind,
1203 .connect = inet_stream_connect,
1204 .socketpair = sock_no_socketpair,
1205 .accept = inet_accept,
1206 .getname = inet6_getname,
1207 .poll = dccp_poll,
1208 .ioctl = inet6_ioctl,
1209 .listen = inet_dccp_listen,
1210 .shutdown = inet_shutdown,
1211 .setsockopt = sock_common_setsockopt,
1212 .getsockopt = sock_common_getsockopt,
1213 .sendmsg = inet_sendmsg,
1214 .recvmsg = sock_common_recvmsg,
1215 .mmap = sock_no_mmap,
1216 .sendpage = sock_no_sendpage,
3fdadf7d 1217#ifdef CONFIG_COMPAT
543d9cfe
ACM
1218 .compat_setsockopt = compat_sock_common_setsockopt,
1219 .compat_getsockopt = compat_sock_common_getsockopt,
3fdadf7d 1220#endif
3df80d93
ACM
1221};
1222
1223static struct inet_protosw dccp_v6_protosw = {
1224 .type = SOCK_DCCP,
1225 .protocol = IPPROTO_DCCP,
1226 .prot = &dccp_v6_prot,
1227 .ops = &inet6_dccp_ops,
1228 .capability = -1,
d83d8461 1229 .flags = INET_PROTOSW_ICSK,
3df80d93
ACM
1230};
1231
1232static int __init dccp_v6_init(void)
1233{
1234 int err = proto_register(&dccp_v6_prot, 1);
1235
1236 if (err != 0)
1237 goto out;
1238
1239 err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1240 if (err != 0)
1241 goto out_unregister_proto;
1242
1243 inet6_register_protosw(&dccp_v6_protosw);
72478873 1244
c4d93909
ACM
1245 err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6,
1246 SOCK_DCCP, IPPROTO_DCCP);
1247 if (err != 0)
72478873 1248 goto out_unregister_protosw;
3df80d93
ACM
1249out:
1250 return err;
72478873
ACM
1251out_unregister_protosw:
1252 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1253 inet6_unregister_protosw(&dccp_v6_protosw);
3df80d93
ACM
1254out_unregister_proto:
1255 proto_unregister(&dccp_v6_prot);
1256 goto out;
1257}
1258
1259static void __exit dccp_v6_exit(void)
1260{
1261 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1262 inet6_unregister_protosw(&dccp_v6_protosw);
1263 proto_unregister(&dccp_v6_prot);
1264}
1265
1266module_init(dccp_v6_init);
1267module_exit(dccp_v6_exit);
1268
1269/*
1270 * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1271 * values directly, Also cover the case where the protocol is not specified,
1272 * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP
1273 */
1274MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-33-type-6");
1275MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-0-type-6");
1276MODULE_LICENSE("GPL");
1277MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1278MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");