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