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