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