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