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