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 --- |