| @@ -269,34 +269,15 @@ ip_set_ext_destroy(struct ip_set *set, void *data) · 268 unmodified lines |
| 269 | /* Check that the extension is enabled for the set and | 269 | /* Check that the extension is enabled for the set and |
| 270 | * call it's destroy function for its extension part in data. | 270 | * call it's destroy function for its extension part in data. |
| 271 | */ | 271 | */ |
| 272 | if (SET_WITH_COMMENT(set)) | 272 | if (SET_WITH_COMMENT(set)) { |
| 273 | ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy( | 273 | struct ip_set_comment *c = ext_comment(data, set); |
| 274 | set, ext_comment(data, set)); | | |
| 275 | } | | |
| 276 | | 274 | |
| 277 | static inline int | 275 | ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy(set, c); |
| 278 | ip_set_put_flags(struct sk_buff *skb, struct ip_set *set) | 276 | } |
| 279 | { | | |
| 280 | u32 cadt_flags = 0; | | |
| 281 | | | |
| 282 | if (SET_WITH_TIMEOUT(set)) | | |
| 283 | if (unlikely(nla_put_net32(skb, IPSET_ATTR_TIMEOUT, | | |
| 284 | htonl(set->timeout)))) | | |
| 285 | return -EMSGSIZE; | | |
| 286 | if (SET_WITH_COUNTER(set)) | | |
| 287 | cadt_flags |= IPSET_FLAG_WITH_COUNTERS; | | |
| 288 | if (SET_WITH_COMMENT(set)) | | |
| 289 | cadt_flags |= IPSET_FLAG_WITH_COMMENT; | | |
| 290 | if (SET_WITH_SKBINFO(set)) | | |
| 291 | cadt_flags |= IPSET_FLAG_WITH_SKBINFO; | | |
| 292 | if (SET_WITH_FORCEADD(set)) | | |
| 293 | cadt_flags |= IPSET_FLAG_WITH_FORCEADD; | | |
| 294 | | | |
| 295 | if (!cadt_flags) | | |
| 296 | return 0; | | |
| 297 | return nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(cadt_flags)); | | |
| 298 | } | 277 | } |
| 299 | | 278 | |
| | 279 | int ip_set_put_flags(struct sk_buff *skb, struct ip_set *set); |
| | 280 | |
| 300 | /* Netlink CB args */ | 281 | /* Netlink CB args */ |
| 301 | enum { | 282 | enum { |
| 302 | IPSET_CB_NET = 0, /* net namespace */ | 283 | IPSET_CB_NET = 0, /* net namespace */ |
| @@ -506,144 +487,8 @@ ip_set_timeout_set(unsigned long *timeout, u32 value) · 203 unmodified lines |
| 506 | *timeout = t; | 487 | *timeout = t; |
| 507 | } | 488 | } |
| 508 | | 489 | |
| 509 | static inline u32 | 490 | void ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, |
| 510 | ip_set_timeout_get(const unsigned long *timeout) | 491 | const struct ip_set_ext *ext); |
| 511 | { | | |
| 512 | u32 t; | | |
| 513 | | | |
| 514 | if (*timeout == IPSET_ELEM_PERMANENT) | | |
| 515 | return 0; | | |
| 516 | | | |
| 517 | t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; | | |
| 518 | /* Zero value in userspace means no timeout */ | | |
| 519 | return t == 0 ? 1 : t; | | |
| 520 | } | | |
| 521 | | | |
| 522 | static inline char* | | |
| 523 | ip_set_comment_uget(struct nlattr *tb) | | |
| 524 | { | | |
| 525 | return nla_data(tb); | | |
| 526 | } | | |
| 527 | | | |
| 528 | /* Called from uadd only, protected by the set spinlock. | | |
| 529 | * The kadt functions don't use the comment extensions in any way. | | |
| 530 | */ | | |
| 531 | static inline void | | |
| 532 | ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, | | |
| 533 | const struct ip_set_ext *ext) | | |
| 534 | { | | |
| 535 | struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); | | |
| 536 | size_t len = ext->comment ? strlen(ext->comment) : 0; | | |
| 537 | | | |
| 538 | if (unlikely(c)) { | | |
| 539 | set->ext_size -= sizeof(*c) + strlen(c->str) + 1; | | |
| 540 | kfree_rcu(c, rcu); | | |
| 541 | rcu_assign_pointer(comment->c, NULL); | | |
| 542 | } | | |
| 543 | if (!len) | | |
| 544 | return; | | |
| 545 | if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) | | |
| 546 | len = IPSET_MAX_COMMENT_SIZE; | | |
| 547 | c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); | | |
| 548 | if (unlikely(!c)) | | |
| 549 | return; | | |
| 550 | strlcpy(c->str, ext->comment, len + 1); | | |
| 551 | set->ext_size += sizeof(*c) + strlen(c->str) + 1; | | |
| 552 | rcu_assign_pointer(comment->c, c); | | |
| 553 | } | | |
| 554 | | | |
| 555 | /* Used only when dumping a set, protected by rcu_read_lock() */ | | |
| 556 | static inline int | | |
| 557 | ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) | | |
| 558 | { | | |
| 559 | struct ip_set_comment_rcu *c = rcu_dereference(comment->c); | | |
| 560 | | | |
| 561 | if (!c) | | |
| 562 | return 0; | | |
| 563 | return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); | | |
| 564 | } | | |
| 565 | | | |
| 566 | /* Called from uadd/udel, flush or the garbage collectors protected | | |
| 567 | * by the set spinlock. | | |
| 568 | * Called when the set is destroyed and when there can't be any user | | |
| 569 | * of the set data anymore. | | |
| 570 | */ | | |
| 571 | static inline void | | |
| 572 | ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment) | | |
| 573 | { | | |
| 574 | struct ip_set_comment_rcu *c; | | |
| 575 | | | |
| 576 | c = rcu_dereference_protected(comment->c, 1); | | |
| 577 | if (unlikely(!c)) | | |
| 578 | return; | | |
| 579 | set->ext_size -= sizeof(*c) + strlen(c->str) + 1; | | |
| 580 | kfree_rcu(c, rcu); | | |
| 581 | rcu_assign_pointer(comment->c, NULL); | | |
| 582 | } | | |
| 583 | | | |
| 584 | static inline void | | |
| 585 | ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) | | |
| 586 | { | | |
| 587 | atomic64_add((long long)bytes, &(counter)->bytes); | | |
| 588 | } | | |
| 589 | | | |
| 590 | static inline void | | |
| 591 | ip_set_add_packets(u64 packets, struct ip_set_counter *counter) | | |
| 592 | { | | |
| 593 | atomic64_add((long long)packets, &(counter)->packets); | | |
| 594 | } | | |
| 595 | | | |
| 596 | static inline u64 | | |
| 597 | ip_set_get_bytes(const struct ip_set_counter *counter) | | |
| 598 | { | | |
| 599 | return (u64)atomic64_read(&(counter)->bytes); | | |
| 600 | } | | |
| 601 | | | |
| 602 | static inline u64 | | |
| 603 | ip_set_get_packets(const struct ip_set_counter *counter) | | |
| 604 | { | | |
| 605 | return (u64)atomic64_read(&(counter)->packets); | | |
| 606 | } | | |
| 607 | | | |
| 608 | static inline bool | | |
| 609 | ip_set_match_counter(u64 counter, u64 match, u8 op) | | |
| 610 | { | | |
| 611 | switch (op) { | | |
| 612 | case IPSET_COUNTER_NONE: | | |
| 613 | return true; | | |
| 614 | case IPSET_COUNTER_EQ: | | |
| 615 | return counter == match; | | |
| 616 | case IPSET_COUNTER_NE: | | |
| 617 | return counter != match; | | |
| 618 | case IPSET_COUNTER_LT: | | |
| 619 | return counter < match; | | |
| 620 | case IPSET_COUNTER_GT: | | |
| 621 | return counter > match; | | |
| 622 | } | | |
| 623 | return false; | | |
| 624 | } | | |
| 625 | | | |
| 626 | static inline void | | |
| 627 | ip_set_update_counter(struct ip_set_counter *counter, | | |
| 628 | const struct ip_set_ext *ext, u32 flags) | | |
| 629 | { | | |
| 630 | if (ext->packets != ULLONG_MAX && | | |
| 631 | !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { | | |
| 632 | ip_set_add_bytes(ext->bytes, counter); | | |
| 633 | ip_set_add_packets(ext->packets, counter); | | |
| 634 | } | | |
| 635 | } | | |
| 636 | | | |
| 637 | static inline bool | | |
| 638 | ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) | | |
| 639 | { | | |
| 640 | return nla_put_net64(skb, IPSET_ATTR_BYTES, | | |
| 641 | cpu_to_be64(ip_set_get_bytes(counter)), | | |
| 642 | IPSET_ATTR_PAD) || | | |
| 643 | nla_put_net64(skb, IPSET_ATTR_PACKETS, | | |
| 644 | cpu_to_be64(ip_set_get_packets(counter)), | | |
| 645 | IPSET_ATTR_PAD); | | |
| 646 | } | | |
| 647 | | 492 | |
| 648 | static inline void | 493 | static inline void |
| 649 | ip_set_init_counter(struct ip_set_counter *counter, | 494 | ip_set_init_counter(struct ip_set_counter *counter, |
| @@ -655,31 +500,6 @@ ip_set_init_counter(struct ip_set_counter *counter, · 5 unmodified lines |
| 655 | atomic64_set(&(counter)->packets, (long long)(ext->packets)); | 500 | atomic64_set(&(counter)->packets, (long long)(ext->packets)); |
| 656 | } | 501 | } |
| 657 | | 502 | |
| 658 | static inline void | | |
| 659 | ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, | | |
| 660 | const struct ip_set_ext *ext, | | |
| 661 | struct ip_set_ext *mext, u32 flags) | | |
| 662 | { | | |
| 663 | mext->skbinfo = *skbinfo; | | |
| 664 | } | | |
| 665 | | | |
| 666 | static inline bool | | |
| 667 | ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) | | |
| 668 | { | | |
| 669 | /* Send nonzero parameters only */ | | |
| 670 | return ((skbinfo->skbmark || skbinfo->skbmarkmask) && | | |
| 671 | nla_put_net64(skb, IPSET_ATTR_SKBMARK, | | |
| 672 | cpu_to_be64((u64)skbinfo->skbmark << 32 | | | |
| 673 | skbinfo->skbmarkmask), | | |
| 674 | IPSET_ATTR_PAD)) || | | |
| 675 | (skbinfo->skbprio && | | |
| 676 | nla_put_net32(skb, IPSET_ATTR_SKBPRIO, | | |
| 677 | cpu_to_be32(skbinfo->skbprio))) || | | |
| 678 | (skbinfo->skbqueue && | | |
| 679 | nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, | | |
| 680 | cpu_to_be16(skbinfo->skbqueue))); | | |
| 681 | } | | |
| 682 | | | |
| 683 | static inline void | 503 | static inline void |
| 684 | ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, | 504 | ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, |
| 685 | const struct ip_set_ext *ext) | 505 | const struct ip_set_ext *ext) |