~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/dccp/ipv6.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
 
55
55
/* add pseudo-header to DCCP checksum stored in skb->csum */
56
56
static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
57
 
                                      struct in6_addr *saddr,
58
 
                                      struct in6_addr *daddr)
 
57
                                      const struct in6_addr *saddr,
 
58
                                      const struct in6_addr *daddr)
59
59
{
60
60
        return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
61
61
}
87
87
static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
88
88
                        u8 type, u8 code, int offset, __be32 info)
89
89
{
90
 
        struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
 
90
        const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
91
91
        const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
92
92
        struct dccp_sock *dp;
93
93
        struct ipv6_pinfo *np;
147
147
                dst = __sk_dst_check(sk, np->dst_cookie);
148
148
                if (dst == NULL) {
149
149
                        struct inet_sock *inet = inet_sk(sk);
150
 
                        struct flowi fl;
 
150
                        struct flowi6 fl6;
151
151
 
152
152
                        /* BUGGG_FUTURE: Again, it is not clear how
153
153
                           to handle rthdr case. Ignore this complexity
154
154
                           for now.
155
155
                         */
156
 
                        memset(&fl, 0, sizeof(fl));
157
 
                        fl.proto = IPPROTO_DCCP;
158
 
                        ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
159
 
                        ipv6_addr_copy(&fl.fl6_src, &np->saddr);
160
 
                        fl.oif = sk->sk_bound_dev_if;
161
 
                        fl.fl_ip_dport = inet->inet_dport;
162
 
                        fl.fl_ip_sport = inet->inet_sport;
163
 
                        security_sk_classify_flow(sk, &fl);
164
 
 
165
 
                        err = ip6_dst_lookup(sk, &dst, &fl);
166
 
                        if (err) {
167
 
                                sk->sk_err_soft = -err;
168
 
                                goto out;
169
 
                        }
170
 
 
171
 
                        err = xfrm_lookup(net, &dst, &fl, sk, 0);
172
 
                        if (err < 0) {
173
 
                                sk->sk_err_soft = -err;
 
156
                        memset(&fl6, 0, sizeof(fl6));
 
157
                        fl6.flowi6_proto = IPPROTO_DCCP;
 
158
                        ipv6_addr_copy(&fl6.daddr, &np->daddr);
 
159
                        ipv6_addr_copy(&fl6.saddr, &np->saddr);
 
160
                        fl6.flowi6_oif = sk->sk_bound_dev_if;
 
161
                        fl6.fl6_dport = inet->inet_dport;
 
162
                        fl6.fl6_sport = inet->inet_sport;
 
163
                        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
164
 
 
165
                        dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false);
 
166
                        if (IS_ERR(dst)) {
 
167
                                sk->sk_err_soft = -PTR_ERR(dst);
174
168
                                goto out;
175
169
                        }
176
170
                } else
249
243
        struct sk_buff *skb;
250
244
        struct ipv6_txoptions *opt = NULL;
251
245
        struct in6_addr *final_p, final;
252
 
        struct flowi fl;
 
246
        struct flowi6 fl6;
253
247
        int err = -1;
254
248
        struct dst_entry *dst;
255
249
 
256
 
        memset(&fl, 0, sizeof(fl));
257
 
        fl.proto = IPPROTO_DCCP;
258
 
        ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
259
 
        ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
260
 
        fl.fl6_flowlabel = 0;
261
 
        fl.oif = ireq6->iif;
262
 
        fl.fl_ip_dport = inet_rsk(req)->rmt_port;
263
 
        fl.fl_ip_sport = inet_rsk(req)->loc_port;
264
 
        security_req_classify_flow(req, &fl);
 
250
        memset(&fl6, 0, sizeof(fl6));
 
251
        fl6.flowi6_proto = IPPROTO_DCCP;
 
252
        ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
 
253
        ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr);
 
254
        fl6.flowlabel = 0;
 
255
        fl6.flowi6_oif = ireq6->iif;
 
256
        fl6.fl6_dport = inet_rsk(req)->rmt_port;
 
257
        fl6.fl6_sport = inet_rsk(req)->loc_port;
 
258
        security_req_classify_flow(req, flowi6_to_flowi(&fl6));
265
259
 
266
260
        opt = np->opt;
267
261
 
268
 
        final_p = fl6_update_dst(&fl, opt, &final);
269
 
 
270
 
        err = ip6_dst_lookup(sk, &dst, &fl);
271
 
        if (err)
272
 
                goto done;
273
 
 
274
 
        if (final_p)
275
 
                ipv6_addr_copy(&fl.fl6_dst, final_p);
276
 
 
277
 
        err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0);
278
 
        if (err < 0)
279
 
                goto done;
 
262
        final_p = fl6_update_dst(&fl6, opt, &final);
 
263
 
 
264
        dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
 
265
        if (IS_ERR(dst)) {
 
266
                err = PTR_ERR(dst);
 
267
                dst = NULL;
 
268
                goto done;
 
269
        }
280
270
 
281
271
        skb = dccp_make_response(sk, dst, req);
282
272
        if (skb != NULL) {
285
275
                dh->dccph_checksum = dccp_v6_csum_finish(skb,
286
276
                                                         &ireq6->loc_addr,
287
277
                                                         &ireq6->rmt_addr);
288
 
                ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
289
 
                err = ip6_xmit(sk, skb, &fl, opt);
 
278
                ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
 
279
                err = ip6_xmit(sk, skb, &fl6, opt);
290
280
                err = net_xmit_eval(err);
291
281
        }
292
282
 
306
296
 
307
297
static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
308
298
{
309
 
        struct ipv6hdr *rxip6h;
 
299
        const struct ipv6hdr *rxip6h;
310
300
        struct sk_buff *skb;
311
 
        struct flowi fl;
 
301
        struct flowi6 fl6;
312
302
        struct net *net = dev_net(skb_dst(rxskb)->dev);
313
303
        struct sock *ctl_sk = net->dccp.v6_ctl_sk;
314
304
        struct dst_entry *dst;
327
317
        dccp_hdr(skb)->dccph_checksum = dccp_v6_csum_finish(skb, &rxip6h->saddr,
328
318
                                                            &rxip6h->daddr);
329
319
 
330
 
        memset(&fl, 0, sizeof(fl));
331
 
        ipv6_addr_copy(&fl.fl6_dst, &rxip6h->saddr);
332
 
        ipv6_addr_copy(&fl.fl6_src, &rxip6h->daddr);
 
320
        memset(&fl6, 0, sizeof(fl6));
 
321
        ipv6_addr_copy(&fl6.daddr, &rxip6h->saddr);
 
322
        ipv6_addr_copy(&fl6.saddr, &rxip6h->daddr);
333
323
 
334
 
        fl.proto = IPPROTO_DCCP;
335
 
        fl.oif = inet6_iif(rxskb);
336
 
        fl.fl_ip_dport = dccp_hdr(skb)->dccph_dport;
337
 
        fl.fl_ip_sport = dccp_hdr(skb)->dccph_sport;
338
 
        security_skb_classify_flow(rxskb, &fl);
 
324
        fl6.flowi6_proto = IPPROTO_DCCP;
 
325
        fl6.flowi6_oif = inet6_iif(rxskb);
 
326
        fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
 
327
        fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
 
328
        security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
339
329
 
340
330
        /* sk = NULL, but it is safe for now. RST socket required. */
341
 
        if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) {
342
 
                if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) {
343
 
                        skb_dst_set(skb, dst);
344
 
                        ip6_xmit(ctl_sk, skb, &fl, NULL);
345
 
                        DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
346
 
                        DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
347
 
                        return;
348
 
                }
 
331
        dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
 
332
        if (!IS_ERR(dst)) {
 
333
                skb_dst_set(skb, dst);
 
334
                ip6_xmit(ctl_sk, skb, &fl6, NULL);
 
335
                DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
 
336
                DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
 
337
                return;
349
338
        }
350
339
 
351
340
        kfree_skb(skb);
484
473
        struct inet6_request_sock *ireq6 = inet6_rsk(req);
485
474
        struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
486
475
        struct inet_sock *newinet;
487
 
        struct dccp_sock *newdp;
488
476
        struct dccp6_sock *newdp6;
489
477
        struct sock *newsk;
490
478
        struct ipv6_txoptions *opt;
498
486
                        return NULL;
499
487
 
500
488
                newdp6 = (struct dccp6_sock *)newsk;
501
 
                newdp = dccp_sk(newsk);
502
489
                newinet = inet_sk(newsk);
503
490
                newinet->pinet6 = &newdp6->inet6;
504
491
                newnp = inet6_sk(newsk);
540
527
 
541
528
        if (dst == NULL) {
542
529
                struct in6_addr *final_p, final;
543
 
                struct flowi fl;
544
 
 
545
 
                memset(&fl, 0, sizeof(fl));
546
 
                fl.proto = IPPROTO_DCCP;
547
 
                ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
548
 
                final_p = fl6_update_dst(&fl, opt, &final);
549
 
                ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
550
 
                fl.oif = sk->sk_bound_dev_if;
551
 
                fl.fl_ip_dport = inet_rsk(req)->rmt_port;
552
 
                fl.fl_ip_sport = inet_rsk(req)->loc_port;
553
 
                security_sk_classify_flow(sk, &fl);
554
 
 
555
 
                if (ip6_dst_lookup(sk, &dst, &fl))
556
 
                        goto out;
557
 
 
558
 
                if (final_p)
559
 
                        ipv6_addr_copy(&fl.fl6_dst, final_p);
560
 
 
561
 
                if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
 
530
                struct flowi6 fl6;
 
531
 
 
532
                memset(&fl6, 0, sizeof(fl6));
 
533
                fl6.flowi6_proto = IPPROTO_DCCP;
 
534
                ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
 
535
                final_p = fl6_update_dst(&fl6, opt, &final);
 
536
                ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr);
 
537
                fl6.flowi6_oif = sk->sk_bound_dev_if;
 
538
                fl6.fl6_dport = inet_rsk(req)->rmt_port;
 
539
                fl6.fl6_sport = inet_rsk(req)->loc_port;
 
540
                security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
541
 
 
542
                dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
 
543
                if (IS_ERR(dst))
562
544
                        goto out;
563
545
        }
564
546
 
578
560
        newdp6 = (struct dccp6_sock *)newsk;
579
561
        newinet = inet_sk(newsk);
580
562
        newinet->pinet6 = &newdp6->inet6;
581
 
        newdp = dccp_sk(newsk);
582
563
        newnp = inet6_sk(newsk);
583
564
 
584
565
        memcpy(newnp, np, sizeof(struct ipv6_pinfo));
592
573
 
593
574
           First: no IPv4 options.
594
575
         */
595
 
        newinet->opt = NULL;
 
576
        newinet->inet_opt = NULL;
596
577
 
597
578
        /* Clone RX bits */
598
579
        newnp->rxopt.all = np->rxopt.all;
878
859
        struct ipv6_pinfo *np = inet6_sk(sk);
879
860
        struct dccp_sock *dp = dccp_sk(sk);
880
861
        struct in6_addr *saddr = NULL, *final_p, final;
881
 
        struct flowi fl;
 
862
        struct flowi6 fl6;
882
863
        struct dst_entry *dst;
883
864
        int addr_type;
884
865
        int err;
891
872
        if (usin->sin6_family != AF_INET6)
892
873
                return -EAFNOSUPPORT;
893
874
 
894
 
        memset(&fl, 0, sizeof(fl));
 
875
        memset(&fl6, 0, sizeof(fl6));
895
876
 
896
877
        if (np->sndflow) {
897
 
                fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
898
 
                IP6_ECN_flow_init(fl.fl6_flowlabel);
899
 
                if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
 
878
                fl6.flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
 
879
                IP6_ECN_flow_init(fl6.flowlabel);
 
880
                if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
900
881
                        struct ip6_flowlabel *flowlabel;
901
 
                        flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
 
882
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
902
883
                        if (flowlabel == NULL)
903
884
                                return -EINVAL;
904
885
                        ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
935
916
        }
936
917
 
937
918
        ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
938
 
        np->flow_label = fl.fl6_flowlabel;
 
919
        np->flow_label = fl6.flowlabel;
939
920
 
940
921
        /*
941
922
         * DCCP over IPv4
972
953
        if (!ipv6_addr_any(&np->rcv_saddr))
973
954
                saddr = &np->rcv_saddr;
974
955
 
975
 
        fl.proto = IPPROTO_DCCP;
976
 
        ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
977
 
        ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
978
 
        fl.oif = sk->sk_bound_dev_if;
979
 
        fl.fl_ip_dport = usin->sin6_port;
980
 
        fl.fl_ip_sport = inet->inet_sport;
981
 
        security_sk_classify_flow(sk, &fl);
982
 
 
983
 
        final_p = fl6_update_dst(&fl, np->opt, &final);
984
 
 
985
 
        err = ip6_dst_lookup(sk, &dst, &fl);
986
 
        if (err)
 
956
        fl6.flowi6_proto = IPPROTO_DCCP;
 
957
        ipv6_addr_copy(&fl6.daddr, &np->daddr);
 
958
        ipv6_addr_copy(&fl6.saddr, saddr ? saddr : &np->saddr);
 
959
        fl6.flowi6_oif = sk->sk_bound_dev_if;
 
960
        fl6.fl6_dport = usin->sin6_port;
 
961
        fl6.fl6_sport = inet->inet_sport;
 
962
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
963
 
 
964
        final_p = fl6_update_dst(&fl6, np->opt, &final);
 
965
 
 
966
        dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
 
967
        if (IS_ERR(dst)) {
 
968
                err = PTR_ERR(dst);
987
969
                goto failure;
988
 
 
989
 
        if (final_p)
990
 
                ipv6_addr_copy(&fl.fl6_dst, final_p);
991
 
 
992
 
        err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
993
 
        if (err < 0) {
994
 
                if (err == -EREMOTE)
995
 
                        err = ip6_dst_blackhole(sk, &dst, &fl);
996
 
                if (err < 0)
997
 
                        goto failure;
998
970
        }
999
971
 
1000
972
        if (saddr == NULL) {
1001
 
                saddr = &fl.fl6_src;
 
973
                saddr = &fl6.saddr;
1002
974
                ipv6_addr_copy(&np->rcv_saddr, saddr);
1003
975
        }
1004
976