~ubuntu-branches/ubuntu/trusty/linux-linaro-omap/trusty

« back to all changes in this revision

Viewing changes to net/ipv6/ip6_output.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-57i0gl3v99b3lkfg
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
596
596
        return offset;
597
597
}
598
598
 
 
599
static u32 hashidentrnd __read_mostly;
 
600
#define FID_HASH_SZ 16
 
601
static u32 ipv6_fragmentation_id[FID_HASH_SZ];
 
602
 
 
603
void __init initialize_hashidentrnd(void)
 
604
{
 
605
        get_random_bytes(&hashidentrnd, sizeof(hashidentrnd));
 
606
}
 
607
 
 
608
static u32 __ipv6_select_ident(const struct in6_addr *addr)
 
609
{
 
610
        u32 newid, oldid, hash = jhash2((u32 *)addr, 4, hashidentrnd);
 
611
        u32 *pid = &ipv6_fragmentation_id[hash % FID_HASH_SZ];
 
612
 
 
613
        do {
 
614
                oldid = *pid;
 
615
                newid = oldid + 1;
 
616
                if (!(hash + newid))
 
617
                        newid++;
 
618
        } while (cmpxchg(pid, oldid, newid) != oldid);
 
619
 
 
620
        return hash + newid;
 
621
}
 
622
 
 
623
void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
 
624
{
 
625
        fhdr->identification = htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
 
626
}
 
627
 
599
628
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
600
629
{
601
630
        struct sk_buff *frag;
680
709
                skb_reset_network_header(skb);
681
710
                memcpy(skb_network_header(skb), tmp_hdr, hlen);
682
711
 
683
 
                ipv6_select_ident(fh);
 
712
                ipv6_select_ident(fh, rt);
684
713
                fh->nexthdr = nexthdr;
685
714
                fh->reserved = 0;
686
715
                fh->frag_off = htons(IP6_MF);
826
855
                fh->nexthdr = nexthdr;
827
856
                fh->reserved = 0;
828
857
                if (!frag_id) {
829
 
                        ipv6_select_ident(fh);
 
858
                        ipv6_select_ident(fh, rt);
830
859
                        frag_id = fh->identification;
831
860
                } else
832
861
                        fh->identification = frag_id;
869
898
        return err;
870
899
}
871
900
 
872
 
static inline int ip6_rt_check(struct rt6key *rt_key,
873
 
                               struct in6_addr *fl_addr,
874
 
                               struct in6_addr *addr_cache)
 
901
static inline int ip6_rt_check(const struct rt6key *rt_key,
 
902
                               const struct in6_addr *fl_addr,
 
903
                               const struct in6_addr *addr_cache)
875
904
{
876
905
        return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) &&
877
906
                (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache));
879
908
 
880
909
static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
881
910
                                          struct dst_entry *dst,
882
 
                                          struct flowi6 *fl6)
 
911
                                          const struct flowi6 *fl6)
883
912
{
884
913
        struct ipv6_pinfo *np = inet6_sk(sk);
885
914
        struct rt6_info *rt = (struct rt6_info *)dst;
930
959
                goto out_err_release;
931
960
 
932
961
        if (ipv6_addr_any(&fl6->saddr)) {
933
 
                err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
934
 
                                         &fl6->daddr,
935
 
                                         sk ? inet6_sk(sk)->srcprefs : 0,
936
 
                                         &fl6->saddr);
 
962
                struct rt6_info *rt = (struct rt6_info *) *dst;
 
963
                err = ip6_route_get_saddr(net, rt, &fl6->daddr,
 
964
                                          sk ? inet6_sk(sk)->srcprefs : 0,
 
965
                                          &fl6->saddr);
937
966
                if (err)
938
967
                        goto out_err_release;
939
968
        }
1072
1101
                        int getfrag(void *from, char *to, int offset, int len,
1073
1102
                        int odd, struct sk_buff *skb),
1074
1103
                        void *from, int length, int hh_len, int fragheaderlen,
1075
 
                        int transhdrlen, int mtu,unsigned int flags)
 
1104
                        int transhdrlen, int mtu,unsigned int flags,
 
1105
                        struct rt6_info *rt)
1076
1106
 
1077
1107
{
1078
1108
        struct sk_buff *skb;
1116
1146
                skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1117
1147
                                             sizeof(struct frag_hdr)) & ~7;
1118
1148
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1119
 
                ipv6_select_ident(&fhdr);
 
1149
                ipv6_select_ident(&fhdr, rt);
1120
1150
                skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1121
1151
                __skb_queue_tail(&sk->sk_write_queue, skb);
1122
1152
 
1150
1180
{
1151
1181
        struct inet_sock *inet = inet_sk(sk);
1152
1182
        struct ipv6_pinfo *np = inet6_sk(sk);
 
1183
        struct inet_cork *cork;
1153
1184
        struct sk_buff *skb;
1154
1185
        unsigned int maxfraglen, fragheaderlen;
1155
1186
        int exthdrlen;
1163
1194
 
1164
1195
        if (flags&MSG_PROBE)
1165
1196
                return 0;
 
1197
        cork = &inet->cork.base;
1166
1198
        if (skb_queue_empty(&sk->sk_write_queue)) {
1167
1199
                /*
1168
1200
                 * setup for corking
1202
1234
                        /* need source address above miyazawa*/
1203
1235
                }
1204
1236
                dst_hold(&rt->dst);
1205
 
                inet->cork.dst = &rt->dst;
 
1237
                cork->dst = &rt->dst;
1206
1238
                inet->cork.fl.u.ip6 = *fl6;
1207
1239
                np->cork.hop_limit = hlimit;
1208
1240
                np->cork.tclass = tclass;
1212
1244
                        if (np->frag_size)
1213
1245
                                mtu = np->frag_size;
1214
1246
                }
1215
 
                inet->cork.fragsize = mtu;
 
1247
                cork->fragsize = mtu;
1216
1248
                if (dst_allfrag(rt->dst.path))
1217
 
                        inet->cork.flags |= IPCORK_ALLFRAG;
1218
 
                inet->cork.length = 0;
 
1249
                        cork->flags |= IPCORK_ALLFRAG;
 
1250
                cork->length = 0;
1219
1251
                sk->sk_sndmsg_page = NULL;
1220
1252
                sk->sk_sndmsg_off = 0;
1221
1253
                exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) -
1223
1255
                length += exthdrlen;
1224
1256
                transhdrlen += exthdrlen;
1225
1257
        } else {
1226
 
                rt = (struct rt6_info *)inet->cork.dst;
 
1258
                rt = (struct rt6_info *)cork->dst;
1227
1259
                fl6 = &inet->cork.fl.u.ip6;
1228
1260
                opt = np->cork.opt;
1229
1261
                transhdrlen = 0;
1230
1262
                exthdrlen = 0;
1231
 
                mtu = inet->cork.fragsize;
 
1263
                mtu = cork->fragsize;
1232
1264
        }
1233
1265
 
1234
1266
        hh_len = LL_RESERVED_SPACE(rt->dst.dev);
1238
1270
        maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
1239
1271
 
1240
1272
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
1241
 
                if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
 
1273
                if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
1242
1274
                        ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
1243
1275
                        return -EMSGSIZE;
1244
1276
                }
1267
1299
         * --yoshfuji
1268
1300
         */
1269
1301
 
1270
 
        inet->cork.length += length;
 
1302
        cork->length += length;
1271
1303
        if (length > mtu) {
1272
1304
                int proto = sk->sk_protocol;
1273
1305
                if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
1280
1312
 
1281
1313
                        err = ip6_ufo_append_data(sk, getfrag, from, length,
1282
1314
                                                  hh_len, fragheaderlen,
1283
 
                                                  transhdrlen, mtu, flags);
 
1315
                                                  transhdrlen, mtu, flags, rt);
1284
1316
                        if (err)
1285
1317
                                goto error;
1286
1318
                        return 0;
1292
1324
 
1293
1325
        while (length > 0) {
1294
1326
                /* Check if the remaining data fits into current packet. */
1295
 
                copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
 
1327
                copy = (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
1296
1328
                if (copy < length)
1297
1329
                        copy = maxfraglen - skb->len;
1298
1330
 
1317
1349
                         * we know we need more fragment(s).
1318
1350
                         */
1319
1351
                        datalen = length + fraggap;
1320
 
                        if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
 
1352
                        if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
1321
1353
                                datalen = maxfraglen - fragheaderlen;
1322
1354
 
1323
1355
                        fraglen = datalen + fragheaderlen;
1481
1513
        }
1482
1514
        return 0;
1483
1515
error:
1484
 
        inet->cork.length -= length;
 
1516
        cork->length -= length;
1485
1517
        IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
1486
1518
        return err;
1487
1519
}
1497
1529
                np->cork.opt = NULL;
1498
1530
        }
1499
1531
 
1500
 
        if (inet->cork.dst) {
1501
 
                dst_release(inet->cork.dst);
1502
 
                inet->cork.dst = NULL;
1503
 
                inet->cork.flags &= ~IPCORK_ALLFRAG;
 
1532
        if (inet->cork.base.dst) {
 
1533
                dst_release(inet->cork.base.dst);
 
1534
                inet->cork.base.dst = NULL;
 
1535
                inet->cork.base.flags &= ~IPCORK_ALLFRAG;
1504
1536
        }
1505
1537
        memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
1506
1538
}
1515
1547
        struct net *net = sock_net(sk);
1516
1548
        struct ipv6hdr *hdr;
1517
1549
        struct ipv6_txoptions *opt = np->cork.opt;
1518
 
        struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
 
1550
        struct rt6_info *rt = (struct rt6_info *)inet->cork.base.dst;
1519
1551
        struct flowi6 *fl6 = &inet->cork.fl.u.ip6;
1520
1552
        unsigned char proto = fl6->flowi6_proto;
1521
1553
        int err = 0;