OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_or32_unified_v2.3/] [net/] [dccp/] [ipv6.c] - Blame information for rev 8

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.