ip6_flowlabel.c (188933ac139a6f8ab06cad369bd0200af947b00d) ip6_flowlabel.c (63159f29be1df7f93563a8a0f78c5e65fc844ed6)
1/*
2 * ip6_flowlabel.c IPv6 flowlabel manager.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *

--- 86 unchanged lines hidden (view full) ---

95}
96
97
98static void fl_free(struct ip6_flowlabel *fl)
99{
100 if (fl) {
101 if (fl->share == IPV6_FL_S_PROCESS)
102 put_pid(fl->owner.pid);
1/*
2 * ip6_flowlabel.c IPv6 flowlabel manager.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *

--- 86 unchanged lines hidden (view full) ---

95}
96
97
98static void fl_free(struct ip6_flowlabel *fl)
99{
100 if (fl) {
101 if (fl->share == IPV6_FL_S_PROCESS)
102 put_pid(fl->owner.pid);
103 release_net(fl->fl_net);
104 kfree(fl->opt);
105 kfree_rcu(fl, rcu);
106 }
107}
108
109static void fl_release(struct ip6_flowlabel *fl)
110{
111 spin_lock_bh(&ip6_fl_lock);

--- 89 unchanged lines hidden (view full) ---

201 fl->label = label & IPV6_FLOWLABEL_MASK;
202
203 spin_lock_bh(&ip6_fl_lock);
204 if (label == 0) {
205 for (;;) {
206 fl->label = htonl(prandom_u32())&IPV6_FLOWLABEL_MASK;
207 if (fl->label) {
208 lfl = __fl_lookup(net, fl->label);
103 kfree(fl->opt);
104 kfree_rcu(fl, rcu);
105 }
106}
107
108static void fl_release(struct ip6_flowlabel *fl)
109{
110 spin_lock_bh(&ip6_fl_lock);

--- 89 unchanged lines hidden (view full) ---

200 fl->label = label & IPV6_FLOWLABEL_MASK;
201
202 spin_lock_bh(&ip6_fl_lock);
203 if (label == 0) {
204 for (;;) {
205 fl->label = htonl(prandom_u32())&IPV6_FLOWLABEL_MASK;
206 if (fl->label) {
207 lfl = __fl_lookup(net, fl->label);
209 if (lfl == NULL)
208 if (!lfl)
210 break;
211 }
212 }
213 } else {
214 /*
215 * we dropper the ip6_fl_lock, so this entry could reappear
216 * and we need to recheck with it.
217 *

--- 75 unchanged lines hidden (view full) ---

293 */
294
295struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
296 struct ip6_flowlabel *fl,
297 struct ipv6_txoptions *fopt)
298{
299 struct ipv6_txoptions *fl_opt = fl->opt;
300
209 break;
210 }
211 }
212 } else {
213 /*
214 * we dropper the ip6_fl_lock, so this entry could reappear
215 * and we need to recheck with it.
216 *

--- 75 unchanged lines hidden (view full) ---

292 */
293
294struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
295 struct ip6_flowlabel *fl,
296 struct ipv6_txoptions *fopt)
297{
298 struct ipv6_txoptions *fl_opt = fl->opt;
299
301 if (fopt == NULL || fopt->opt_flen == 0)
300 if (!fopt || fopt->opt_flen == 0)
302 return fl_opt;
303
304 if (fl_opt != NULL) {
305 opt_space->hopopt = fl_opt->hopopt;
306 opt_space->dst0opt = fl_opt->dst0opt;
307 opt_space->srcrt = fl_opt->srcrt;
308 opt_space->opt_nflen = fl_opt->opt_nflen;
309 } else {

--- 52 unchanged lines hidden (view full) ---

362
363 olen = optlen - CMSG_ALIGN(sizeof(*freq));
364 err = -EINVAL;
365 if (olen > 64 * 1024)
366 goto done;
367
368 err = -ENOMEM;
369 fl = kzalloc(sizeof(*fl), GFP_KERNEL);
301 return fl_opt;
302
303 if (fl_opt != NULL) {
304 opt_space->hopopt = fl_opt->hopopt;
305 opt_space->dst0opt = fl_opt->dst0opt;
306 opt_space->srcrt = fl_opt->srcrt;
307 opt_space->opt_nflen = fl_opt->opt_nflen;
308 } else {

--- 52 unchanged lines hidden (view full) ---

361
362 olen = optlen - CMSG_ALIGN(sizeof(*freq));
363 err = -EINVAL;
364 if (olen > 64 * 1024)
365 goto done;
366
367 err = -ENOMEM;
368 fl = kzalloc(sizeof(*fl), GFP_KERNEL);
370 if (fl == NULL)
369 if (!fl)
371 goto done;
372
373 if (olen > 0) {
374 struct msghdr msg;
375 struct flowi6 flowi6;
376 int junk;
377
378 err = -ENOMEM;
379 fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL);
370 goto done;
371
372 if (olen > 0) {
373 struct msghdr msg;
374 struct flowi6 flowi6;
375 int junk;
376
377 err = -ENOMEM;
378 fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL);
380 if (fl->opt == NULL)
379 if (!fl->opt)
381 goto done;
382
383 memset(fl->opt, 0, sizeof(*fl->opt));
384 fl->opt->tot_len = sizeof(*fl->opt) + olen;
385 err = -EFAULT;
386 if (copy_from_user(fl->opt+1, optval+CMSG_ALIGN(sizeof(*freq)), olen))
387 goto done;
388

--- 9 unchanged lines hidden (view full) ---

398 if (fl->opt->opt_flen)
399 goto done;
400 if (fl->opt->opt_nflen == 0) {
401 kfree(fl->opt);
402 fl->opt = NULL;
403 }
404 }
405
380 goto done;
381
382 memset(fl->opt, 0, sizeof(*fl->opt));
383 fl->opt->tot_len = sizeof(*fl->opt) + olen;
384 err = -EFAULT;
385 if (copy_from_user(fl->opt+1, optval+CMSG_ALIGN(sizeof(*freq)), olen))
386 goto done;
387

--- 9 unchanged lines hidden (view full) ---

397 if (fl->opt->opt_flen)
398 goto done;
399 if (fl->opt->opt_nflen == 0) {
400 kfree(fl->opt);
401 fl->opt = NULL;
402 }
403 }
404
406 fl->fl_net = hold_net(net);
405 fl->fl_net = net;
407 fl->expires = jiffies;
408 err = fl6_renew(fl, freq->flr_linger, freq->flr_expires);
409 if (err)
410 goto done;
411 fl->share = freq->flr_share;
412 addr_type = ipv6_addr_type(&freq->flr_dst);
413 if ((addr_type & IPV6_ADDR_MAPPED) ||
414 addr_type == IPV6_ADDR_ANY) {

--- 177 unchanged lines hidden (view full) ---

592 np->repflow = 1;
593 return 0;
594 }
595
596 if (freq.flr_label & ~IPV6_FLOWLABEL_MASK)
597 return -EINVAL;
598
599 fl = fl_create(net, sk, &freq, optval, optlen, &err);
406 fl->expires = jiffies;
407 err = fl6_renew(fl, freq->flr_linger, freq->flr_expires);
408 if (err)
409 goto done;
410 fl->share = freq->flr_share;
411 addr_type = ipv6_addr_type(&freq->flr_dst);
412 if ((addr_type & IPV6_ADDR_MAPPED) ||
413 addr_type == IPV6_ADDR_ANY) {

--- 177 unchanged lines hidden (view full) ---

591 np->repflow = 1;
592 return 0;
593 }
594
595 if (freq.flr_label & ~IPV6_FLOWLABEL_MASK)
596 return -EINVAL;
597
598 fl = fl_create(net, sk, &freq, optval, optlen, &err);
600 if (fl == NULL)
599 if (!fl)
601 return err;
602 sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);
603
604 if (freq.flr_label) {
605 err = -EEXIST;
606 rcu_read_lock_bh();
607 for_each_sk_fl_rcu(np, sfl) {
608 if (sfl->fl->label == freq.flr_label) {
609 if (freq.flr_flags&IPV6_FL_F_EXCL) {
610 rcu_read_unlock_bh();
611 goto done;
612 }
613 fl1 = sfl->fl;
614 atomic_inc(&fl1->users);
615 break;
616 }
617 }
618 rcu_read_unlock_bh();
619
600 return err;
601 sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);
602
603 if (freq.flr_label) {
604 err = -EEXIST;
605 rcu_read_lock_bh();
606 for_each_sk_fl_rcu(np, sfl) {
607 if (sfl->fl->label == freq.flr_label) {
608 if (freq.flr_flags&IPV6_FL_F_EXCL) {
609 rcu_read_unlock_bh();
610 goto done;
611 }
612 fl1 = sfl->fl;
613 atomic_inc(&fl1->users);
614 break;
615 }
616 }
617 rcu_read_unlock_bh();
618
620 if (fl1 == NULL)
619 if (!fl1)
621 fl1 = fl_lookup(net, freq.flr_label);
622 if (fl1) {
623recheck:
624 err = -EEXIST;
625 if (freq.flr_flags&IPV6_FL_F_EXCL)
626 goto release;
627 err = -EPERM;
628 if (fl1->share == IPV6_FL_S_EXCL ||
629 fl1->share != fl->share ||
630 ((fl1->share == IPV6_FL_S_PROCESS) &&
631 (fl1->owner.pid == fl->owner.pid)) ||
632 ((fl1->share == IPV6_FL_S_USER) &&
633 uid_eq(fl1->owner.uid, fl->owner.uid)))
634 goto release;
635
636 err = -ENOMEM;
620 fl1 = fl_lookup(net, freq.flr_label);
621 if (fl1) {
622recheck:
623 err = -EEXIST;
624 if (freq.flr_flags&IPV6_FL_F_EXCL)
625 goto release;
626 err = -EPERM;
627 if (fl1->share == IPV6_FL_S_EXCL ||
628 fl1->share != fl->share ||
629 ((fl1->share == IPV6_FL_S_PROCESS) &&
630 (fl1->owner.pid == fl->owner.pid)) ||
631 ((fl1->share == IPV6_FL_S_USER) &&
632 uid_eq(fl1->owner.uid, fl->owner.uid)))
633 goto release;
634
635 err = -ENOMEM;
637 if (sfl1 == NULL)
636 if (!sfl1)
638 goto release;
639 if (fl->linger > fl1->linger)
640 fl1->linger = fl->linger;
641 if ((long)(fl->expires - fl1->expires) > 0)
642 fl1->expires = fl->expires;
643 fl_link(np, sfl1, fl1);
644 fl_free(fl);
645 return 0;
646
647release:
648 fl_release(fl1);
649 goto done;
650 }
651 }
652 err = -ENOENT;
653 if (!(freq.flr_flags&IPV6_FL_F_CREATE))
654 goto done;
655
656 err = -ENOMEM;
637 goto release;
638 if (fl->linger > fl1->linger)
639 fl1->linger = fl->linger;
640 if ((long)(fl->expires - fl1->expires) > 0)
641 fl1->expires = fl->expires;
642 fl_link(np, sfl1, fl1);
643 fl_free(fl);
644 return 0;
645
646release:
647 fl_release(fl1);
648 goto done;
649 }
650 }
651 err = -ENOENT;
652 if (!(freq.flr_flags&IPV6_FL_F_CREATE))
653 goto done;
654
655 err = -ENOMEM;
657 if (sfl1 == NULL)
656 if (!sfl1)
658 goto done;
659
660 err = mem_check(sk);
661 if (err != 0)
662 goto done;
663
664 fl1 = fl_intern(net, fl, freq.flr_label);
665 if (fl1 != NULL)

--- 217 unchanged lines hidden ---
657 goto done;
658
659 err = mem_check(sk);
660 if (err != 0)
661 goto done;
662
663 fl1 = fl_intern(net, fl, freq.flr_label);
664 if (fl1 != NULL)

--- 217 unchanged lines hidden ---