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