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