diff options
| -rw-r--r-- | include/net/cipso_ipv4.h | 16 | ||||
| -rw-r--r-- | include/net/netlabel.h | 49 | ||||
| -rw-r--r-- | net/ipv4/cipso_ipv4.c | 203 | ||||
| -rw-r--r-- | net/netlabel/netlabel_domainhash.c | 183 | ||||
| -rw-r--r-- | net/netlabel/netlabel_domainhash.h | 6 | ||||
| -rw-r--r-- | net/netlabel/netlabel_user.c | 82 | ||||
| -rw-r--r-- | net/netlabel/netlabel_user.h | 141 |
7 files changed, 76 insertions, 604 deletions
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 6718452a5cd0..2d72496c2029 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h | |||
| @@ -130,8 +130,9 @@ extern int cipso_v4_rbm_strictvalid; | |||
| 130 | int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); | 130 | int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); |
| 131 | int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)); | 131 | int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)); |
| 132 | struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); | 132 | struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); |
| 133 | struct sk_buff *cipso_v4_doi_dump_all(size_t headroom); | 133 | int cipso_v4_doi_walk(u32 *skip_cnt, |
| 134 | struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom); | 134 | int (*callback) (struct cipso_v4_doi *doi_def, void *arg), |
| 135 | void *cb_arg); | ||
| 135 | int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); | 136 | int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); |
| 136 | int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, | 137 | int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, |
| 137 | const char *domain); | 138 | const char *domain); |
| @@ -152,14 +153,11 @@ static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) | |||
| 152 | return NULL; | 153 | return NULL; |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) | 156 | static inline int cipso_v4_doi_walk(u32 *skip_cnt, |
| 157 | int (*callback) (struct cipso_v4_doi *doi_def, void *arg), | ||
| 158 | void *cb_arg) | ||
| 156 | { | 159 | { |
| 157 | return NULL; | 160 | return 0; |
| 158 | } | ||
| 159 | |||
| 160 | static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) | ||
| 161 | { | ||
| 162 | return NULL; | ||
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, | 163 | static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, |
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index bf7b564e3540..6692430063fd 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
| @@ -57,9 +57,8 @@ | |||
| 57 | * The payload is dependent on the subsystem specified in the | 57 | * The payload is dependent on the subsystem specified in the |
| 58 | * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions | 58 | * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions |
| 59 | * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c | 59 | * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c |
| 60 | * file. All of the fields in the NetLabel payload are NETLINK attributes, the | 60 | * file. All of the fields in the NetLabel payload are NETLINK attributes, see |
| 61 | * length of each field is the length of the NETLINK attribute payload, see | 61 | * the include/net/netlink.h file for more information on NETLINK attributes. |
| 62 | * include/net/netlink.h for more information on NETLINK attributes. | ||
| 63 | * | 62 | * |
| 64 | */ | 63 | */ |
| 65 | 64 | ||
| @@ -82,50 +81,6 @@ | |||
| 82 | #define NETLBL_NLTYPE_UNLABELED 5 | 81 | #define NETLBL_NLTYPE_UNLABELED 5 |
| 83 | #define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" | 82 | #define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" |
| 84 | 83 | ||
| 85 | /* NetLabel return codes */ | ||
| 86 | #define NETLBL_E_OK 0 | ||
| 87 | |||
| 88 | /* | ||
| 89 | * Helper functions | ||
| 90 | */ | ||
| 91 | |||
| 92 | #define NETLBL_LEN_U8 nla_total_size(sizeof(u8)) | ||
| 93 | #define NETLBL_LEN_U16 nla_total_size(sizeof(u16)) | ||
| 94 | #define NETLBL_LEN_U32 nla_total_size(sizeof(u32)) | ||
| 95 | |||
| 96 | /** | ||
| 97 | * netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer | ||
| 98 | * @head: the amount of headroom in bytes | ||
| 99 | * @body: the desired size (minus headroom) in bytes | ||
| 100 | * @gfp_flags: the alloc flags to pass to alloc_skb() | ||
| 101 | * | ||
| 102 | * Description: | ||
| 103 | * Allocate a NETLINK message buffer based on the sizes given in @head and | ||
| 104 | * @body. If @head is greater than zero skb_reserve() is called to reserve | ||
| 105 | * @head bytes at the start of the buffer. Returns a valid sk_buff pointer on | ||
| 106 | * success, NULL on failure. | ||
| 107 | * | ||
| 108 | */ | ||
| 109 | static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head, | ||
| 110 | size_t body, | ||
| 111 | gfp_t gfp_flags) | ||
| 112 | { | ||
| 113 | struct sk_buff *skb; | ||
| 114 | |||
| 115 | skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags); | ||
| 116 | if (skb == NULL) | ||
| 117 | return NULL; | ||
| 118 | if (head > 0) { | ||
| 119 | skb_reserve(skb, head); | ||
| 120 | if (skb_tailroom(skb) < body) { | ||
| 121 | kfree_skb(skb); | ||
| 122 | return NULL; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | return skb; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | 84 | /* |
| 130 | * NetLabel - Kernel API for accessing the network packet label mappings. | 85 | * NetLabel - Kernel API for accessing the network packet label mappings. |
| 131 | * | 86 | * |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 87e71563335d..e6ce0b3ba62a 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
| @@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) | |||
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | /** | 532 | /** |
| 533 | * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff | 533 | * cipso_v4_doi_walk - Iterate through the DOI definitions |
| 534 | * @headroom: the amount of headroom to allocate for the sk_buff | 534 | * @skip_cnt: skip past this number of DOI definitions, updated |
| 535 | * @callback: callback for each DOI definition | ||
| 536 | * @cb_arg: argument for the callback function | ||
| 535 | * | 537 | * |
| 536 | * Description: | 538 | * Description: |
| 537 | * Dump a list of all the configured DOI values into a sk_buff. The returned | 539 | * Iterate over the DOI definition list, skipping the first @skip_cnt entries. |
| 538 | * sk_buff has room at the front of the sk_buff for @headroom bytes. See | 540 | * For each entry call @callback, if @callback returns a negative value stop |
| 539 | * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This | 541 | * 'walking' through the list and return. Updates the value in @skip_cnt upon |
| 540 | * function may fail if another process is changing the DOI list at the same | 542 | * return. Returns zero on success, negative values on failure. |
| 541 | * time. Returns a pointer to a sk_buff on success, NULL on error. | ||
| 542 | * | 543 | * |
| 543 | */ | 544 | */ |
| 544 | struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) | 545 | int cipso_v4_doi_walk(u32 *skip_cnt, |
| 546 | int (*callback) (struct cipso_v4_doi *doi_def, void *arg), | ||
| 547 | void *cb_arg) | ||
| 545 | { | 548 | { |
| 546 | struct sk_buff *skb = NULL; | 549 | int ret_val = -ENOENT; |
| 547 | struct cipso_v4_doi *iter; | ||
| 548 | u32 doi_cnt = 0; | 550 | u32 doi_cnt = 0; |
| 549 | ssize_t buf_len; | 551 | struct cipso_v4_doi *iter_doi; |
| 550 | |||
| 551 | buf_len = NETLBL_LEN_U32; | ||
| 552 | rcu_read_lock(); | ||
| 553 | list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) | ||
| 554 | if (iter->valid) { | ||
| 555 | doi_cnt += 1; | ||
| 556 | buf_len += 2 * NETLBL_LEN_U32; | ||
| 557 | } | ||
| 558 | |||
| 559 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
| 560 | if (skb == NULL) | ||
| 561 | goto doi_dump_all_failure; | ||
| 562 | |||
| 563 | if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0) | ||
| 564 | goto doi_dump_all_failure; | ||
| 565 | buf_len -= NETLBL_LEN_U32; | ||
| 566 | list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) | ||
| 567 | if (iter->valid) { | ||
| 568 | if (buf_len < 2 * NETLBL_LEN_U32) | ||
| 569 | goto doi_dump_all_failure; | ||
| 570 | if (nla_put_u32(skb, NLA_U32, iter->doi) != 0) | ||
| 571 | goto doi_dump_all_failure; | ||
| 572 | if (nla_put_u32(skb, NLA_U32, iter->type) != 0) | ||
| 573 | goto doi_dump_all_failure; | ||
| 574 | buf_len -= 2 * NETLBL_LEN_U32; | ||
| 575 | } | ||
| 576 | rcu_read_unlock(); | ||
| 577 | |||
| 578 | return skb; | ||
| 579 | |||
| 580 | doi_dump_all_failure: | ||
| 581 | rcu_read_unlock(); | ||
| 582 | kfree(skb); | ||
| 583 | return NULL; | ||
| 584 | } | ||
| 585 | |||
| 586 | /** | ||
| 587 | * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff | ||
| 588 | * @doi: the DOI value | ||
| 589 | * @headroom: the amount of headroom to allocate for the sk_buff | ||
| 590 | * | ||
| 591 | * Description: | ||
| 592 | * Lookup the DOI definition matching @doi and dump it's contents into a | ||
| 593 | * sk_buff. The returned sk_buff has room at the front of the sk_buff for | ||
| 594 | * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message | ||
| 595 | * format. This function may fail if another process is changing the DOI list | ||
| 596 | * at the same time. Returns a pointer to a sk_buff on success, NULL on error. | ||
| 597 | * | ||
| 598 | */ | ||
| 599 | struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) | ||
| 600 | { | ||
| 601 | struct sk_buff *skb = NULL; | ||
| 602 | struct cipso_v4_doi *iter; | ||
| 603 | u32 tag_cnt = 0; | ||
| 604 | u32 lvl_cnt = 0; | ||
| 605 | u32 cat_cnt = 0; | ||
| 606 | ssize_t buf_len; | ||
| 607 | ssize_t tmp; | ||
| 608 | 552 | ||
| 609 | rcu_read_lock(); | 553 | rcu_read_lock(); |
| 610 | iter = cipso_v4_doi_getdef(doi); | 554 | list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list) |
| 611 | if (iter == NULL) | 555 | if (iter_doi->valid) { |
| 612 | goto doi_dump_failure; | 556 | if (doi_cnt++ < *skip_cnt) |
| 613 | buf_len = NETLBL_LEN_U32; | 557 | continue; |
| 614 | switch (iter->type) { | 558 | ret_val = callback(iter_doi, cb_arg); |
| 615 | case CIPSO_V4_MAP_PASS: | 559 | if (ret_val < 0) { |
| 616 | buf_len += NETLBL_LEN_U32; | 560 | doi_cnt--; |
| 617 | while(tag_cnt < CIPSO_V4_TAG_MAXCNT && | 561 | goto doi_walk_return; |
| 618 | iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) { | ||
| 619 | tag_cnt += 1; | ||
| 620 | buf_len += NETLBL_LEN_U8; | ||
| 621 | } | ||
| 622 | break; | ||
| 623 | case CIPSO_V4_MAP_STD: | ||
| 624 | buf_len += 3 * NETLBL_LEN_U32; | ||
| 625 | while (tag_cnt < CIPSO_V4_TAG_MAXCNT && | ||
| 626 | iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) { | ||
| 627 | tag_cnt += 1; | ||
| 628 | buf_len += NETLBL_LEN_U8; | ||
| 629 | } | ||
| 630 | for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++) | ||
| 631 | if (iter->map.std->lvl.local[tmp] != | ||
| 632 | CIPSO_V4_INV_LVL) { | ||
| 633 | lvl_cnt += 1; | ||
| 634 | buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8; | ||
| 635 | } | 562 | } |
| 636 | for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++) | ||
| 637 | if (iter->map.std->cat.local[tmp] != | ||
| 638 | CIPSO_V4_INV_CAT) { | ||
| 639 | cat_cnt += 1; | ||
| 640 | buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16; | ||
| 641 | } | ||
| 642 | break; | ||
| 643 | } | ||
| 644 | |||
| 645 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
| 646 | if (skb == NULL) | ||
| 647 | goto doi_dump_failure; | ||
| 648 | |||
| 649 | if (nla_put_u32(skb, NLA_U32, iter->type) != 0) | ||
| 650 | goto doi_dump_failure; | ||
| 651 | buf_len -= NETLBL_LEN_U32; | ||
| 652 | if (iter != cipso_v4_doi_getdef(doi)) | ||
| 653 | goto doi_dump_failure; | ||
| 654 | switch (iter->type) { | ||
| 655 | case CIPSO_V4_MAP_PASS: | ||
| 656 | if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0) | ||
| 657 | goto doi_dump_failure; | ||
| 658 | buf_len -= NETLBL_LEN_U32; | ||
| 659 | for (tmp = 0; | ||
| 660 | tmp < CIPSO_V4_TAG_MAXCNT && | ||
| 661 | iter->tags[tmp] != CIPSO_V4_TAG_INVALID; | ||
| 662 | tmp++) { | ||
| 663 | if (buf_len < NETLBL_LEN_U8) | ||
| 664 | goto doi_dump_failure; | ||
| 665 | if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0) | ||
| 666 | goto doi_dump_failure; | ||
| 667 | buf_len -= NETLBL_LEN_U8; | ||
| 668 | } | 563 | } |
| 669 | break; | ||
| 670 | case CIPSO_V4_MAP_STD: | ||
| 671 | if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0) | ||
| 672 | goto doi_dump_failure; | ||
| 673 | if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0) | ||
| 674 | goto doi_dump_failure; | ||
| 675 | if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0) | ||
| 676 | goto doi_dump_failure; | ||
| 677 | buf_len -= 3 * NETLBL_LEN_U32; | ||
| 678 | for (tmp = 0; | ||
| 679 | tmp < CIPSO_V4_TAG_MAXCNT && | ||
| 680 | iter->tags[tmp] != CIPSO_V4_TAG_INVALID; | ||
| 681 | tmp++) { | ||
| 682 | if (buf_len < NETLBL_LEN_U8) | ||
| 683 | goto doi_dump_failure; | ||
| 684 | if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0) | ||
| 685 | goto doi_dump_failure; | ||
| 686 | buf_len -= NETLBL_LEN_U8; | ||
| 687 | } | ||
| 688 | for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++) | ||
| 689 | if (iter->map.std->lvl.local[tmp] != | ||
| 690 | CIPSO_V4_INV_LVL) { | ||
| 691 | if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8) | ||
| 692 | goto doi_dump_failure; | ||
| 693 | if (nla_put_u32(skb, NLA_U32, tmp) != 0) | ||
| 694 | goto doi_dump_failure; | ||
| 695 | if (nla_put_u8(skb, | ||
| 696 | NLA_U8, | ||
| 697 | iter->map.std->lvl.local[tmp]) != 0) | ||
| 698 | goto doi_dump_failure; | ||
| 699 | buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8; | ||
| 700 | } | ||
| 701 | for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++) | ||
| 702 | if (iter->map.std->cat.local[tmp] != | ||
| 703 | CIPSO_V4_INV_CAT) { | ||
| 704 | if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16) | ||
| 705 | goto doi_dump_failure; | ||
| 706 | if (nla_put_u32(skb, NLA_U32, tmp) != 0) | ||
| 707 | goto doi_dump_failure; | ||
| 708 | if (nla_put_u16(skb, | ||
| 709 | NLA_U16, | ||
| 710 | iter->map.std->cat.local[tmp]) != 0) | ||
| 711 | goto doi_dump_failure; | ||
| 712 | buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16; | ||
| 713 | } | ||
| 714 | break; | ||
| 715 | } | ||
| 716 | rcu_read_unlock(); | ||
| 717 | |||
| 718 | return skb; | ||
| 719 | 564 | ||
| 720 | doi_dump_failure: | 565 | doi_walk_return: |
| 721 | rcu_read_unlock(); | 566 | rcu_read_unlock(); |
| 722 | kfree(skb); | 567 | *skip_cnt = doi_cnt; |
| 723 | return NULL; | 568 | return ret_val; |
| 724 | } | 569 | } |
| 725 | 570 | ||
| 726 | /** | 571 | /** |
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 0489a1378101..f56d7a8ac7b7 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
| @@ -354,160 +354,51 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) | |||
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | /** | 356 | /** |
| 357 | * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff | 357 | * netlbl_domhsh_walk - Iterate through the domain mapping hash table |
| 358 | * @skip_bkt: the number of buckets to skip at the start | ||
| 359 | * @skip_chain: the number of entries to skip in the first iterated bucket | ||
| 360 | * @callback: callback for each entry | ||
| 361 | * @cb_arg: argument for the callback function | ||
| 358 | * | 362 | * |
| 359 | * Description: | 363 | * Description: |
| 360 | * Dump the domain hash table into a buffer suitable for returning to an | 364 | * Interate over the domain mapping hash table, skipping the first @skip_bkt |
| 361 | * application in response to a NetLabel management DOMAIN message. This | 365 | * buckets and @skip_chain entries. For each entry in the table call |
| 362 | * function may fail if another process is growing the hash table at the same | 366 | * @callback, if @callback returns a negative value stop 'walking' through the |
| 363 | * time. The returned sk_buff has room at the front of the sk_buff for | 367 | * table and return. Updates the values in @skip_bkt and @skip_chain on |
| 364 | * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a | 368 | * return. Returns zero on succcess, negative values on failure. |
| 365 | * pointer to a sk_buff on success, NULL on error. | ||
| 366 | * | 369 | * |
| 367 | */ | 370 | */ |
| 368 | struct sk_buff *netlbl_domhsh_dump(size_t headroom) | 371 | int netlbl_domhsh_walk(u32 *skip_bkt, |
| 372 | u32 *skip_chain, | ||
| 373 | int (*callback) (struct netlbl_dom_map *entry, void *arg), | ||
| 374 | void *cb_arg) | ||
| 369 | { | 375 | { |
| 370 | struct sk_buff *skb = NULL; | 376 | int ret_val = -ENOENT; |
| 371 | ssize_t buf_len; | 377 | u32 iter_bkt; |
| 372 | u32 bkt_iter; | 378 | struct netlbl_dom_map *iter_entry; |
| 373 | u32 dom_cnt = 0; | 379 | u32 chain_cnt = 0; |
| 374 | struct netlbl_domhsh_tbl *hsh_tbl; | ||
| 375 | struct netlbl_dom_map *list_iter; | ||
| 376 | ssize_t tmp_len; | ||
| 377 | 380 | ||
| 378 | buf_len = NETLBL_LEN_U32; | ||
| 379 | rcu_read_lock(); | 381 | rcu_read_lock(); |
| 380 | hsh_tbl = rcu_dereference(netlbl_domhsh); | 382 | for (iter_bkt = *skip_bkt; |
| 381 | for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) | 383 | iter_bkt < rcu_dereference(netlbl_domhsh)->size; |
| 382 | list_for_each_entry_rcu(list_iter, | 384 | iter_bkt++, chain_cnt = 0) { |
| 383 | &hsh_tbl->tbl[bkt_iter], list) { | 385 | list_for_each_entry_rcu(iter_entry, |
| 384 | buf_len += NETLBL_LEN_U32 + | 386 | &netlbl_domhsh->tbl[iter_bkt], |
| 385 | nla_total_size(strlen(list_iter->domain) + 1); | 387 | list) |
| 386 | switch (list_iter->type) { | 388 | if (iter_entry->valid) { |
| 387 | case NETLBL_NLTYPE_UNLABELED: | 389 | if (chain_cnt++ < *skip_chain) |
| 388 | break; | 390 | continue; |
| 389 | case NETLBL_NLTYPE_CIPSOV4: | 391 | ret_val = callback(iter_entry, cb_arg); |
| 390 | buf_len += 2 * NETLBL_LEN_U32; | 392 | if (ret_val < 0) { |
| 391 | break; | 393 | chain_cnt--; |
| 392 | } | 394 | goto walk_return; |
| 393 | dom_cnt++; | 395 | } |
| 394 | } | ||
| 395 | |||
| 396 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
| 397 | if (skb == NULL) | ||
| 398 | goto dump_failure; | ||
| 399 | |||
| 400 | if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0) | ||
| 401 | goto dump_failure; | ||
| 402 | buf_len -= NETLBL_LEN_U32; | ||
| 403 | hsh_tbl = rcu_dereference(netlbl_domhsh); | ||
| 404 | for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) | ||
| 405 | list_for_each_entry_rcu(list_iter, | ||
| 406 | &hsh_tbl->tbl[bkt_iter], list) { | ||
| 407 | tmp_len = nla_total_size(strlen(list_iter->domain) + | ||
| 408 | 1); | ||
| 409 | if (buf_len < NETLBL_LEN_U32 + tmp_len) | ||
| 410 | goto dump_failure; | ||
| 411 | if (nla_put_string(skb, | ||
| 412 | NLA_STRING, | ||
| 413 | list_iter->domain) != 0) | ||
| 414 | goto dump_failure; | ||
| 415 | if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0) | ||
| 416 | goto dump_failure; | ||
| 417 | buf_len -= NETLBL_LEN_U32 + tmp_len; | ||
| 418 | switch (list_iter->type) { | ||
| 419 | case NETLBL_NLTYPE_UNLABELED: | ||
| 420 | break; | ||
| 421 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 422 | if (buf_len < 2 * NETLBL_LEN_U32) | ||
| 423 | goto dump_failure; | ||
| 424 | if (nla_put_u32(skb, | ||
| 425 | NLA_U32, | ||
| 426 | list_iter->type_def.cipsov4->type) != 0) | ||
| 427 | goto dump_failure; | ||
| 428 | if (nla_put_u32(skb, | ||
| 429 | NLA_U32, | ||
| 430 | list_iter->type_def.cipsov4->doi) != 0) | ||
| 431 | goto dump_failure; | ||
| 432 | buf_len -= 2 * NETLBL_LEN_U32; | ||
| 433 | break; | ||
| 434 | } | 396 | } |
| 435 | } | 397 | } |
| 436 | rcu_read_unlock(); | ||
| 437 | |||
| 438 | return skb; | ||
| 439 | |||
| 440 | dump_failure: | ||
| 441 | rcu_read_unlock(); | ||
| 442 | kfree_skb(skb); | ||
| 443 | return NULL; | ||
| 444 | } | ||
| 445 | |||
| 446 | /** | ||
| 447 | * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff | ||
| 448 | * | ||
| 449 | * Description: | ||
| 450 | * Dump the default domain mapping into a buffer suitable for returning to an | ||
| 451 | * application in response to a NetLabel management DEFDOMAIN message. This | ||
| 452 | * function may fail if another process is changing the default domain mapping | ||
| 453 | * at the same time. The returned sk_buff has room at the front of the | ||
| 454 | * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message | ||
| 455 | * format. Returns a pointer to a sk_buff on success, NULL on error. | ||
| 456 | * | ||
| 457 | */ | ||
| 458 | struct sk_buff *netlbl_domhsh_dump_default(size_t headroom) | ||
| 459 | { | ||
| 460 | struct sk_buff *skb; | ||
| 461 | ssize_t buf_len; | ||
| 462 | struct netlbl_dom_map *entry; | ||
| 463 | |||
| 464 | buf_len = NETLBL_LEN_U32; | ||
| 465 | rcu_read_lock(); | ||
| 466 | entry = rcu_dereference(netlbl_domhsh_def); | ||
| 467 | if (entry != NULL) | ||
| 468 | switch (entry->type) { | ||
| 469 | case NETLBL_NLTYPE_UNLABELED: | ||
| 470 | break; | ||
| 471 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 472 | buf_len += 2 * NETLBL_LEN_U32; | ||
| 473 | break; | ||
| 474 | } | ||
| 475 | |||
| 476 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
| 477 | if (skb == NULL) | ||
| 478 | goto dump_default_failure; | ||
| 479 | |||
| 480 | if (entry != rcu_dereference(netlbl_domhsh_def)) | ||
| 481 | goto dump_default_failure; | ||
| 482 | if (entry != NULL) { | ||
| 483 | if (nla_put_u32(skb, NLA_U32, entry->type) != 0) | ||
| 484 | goto dump_default_failure; | ||
| 485 | buf_len -= NETLBL_LEN_U32; | ||
| 486 | switch (entry->type) { | ||
| 487 | case NETLBL_NLTYPE_UNLABELED: | ||
| 488 | break; | ||
| 489 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 490 | if (buf_len < 2 * NETLBL_LEN_U32) | ||
| 491 | goto dump_default_failure; | ||
| 492 | if (nla_put_u32(skb, | ||
| 493 | NLA_U32, | ||
| 494 | entry->type_def.cipsov4->type) != 0) | ||
| 495 | goto dump_default_failure; | ||
| 496 | if (nla_put_u32(skb, | ||
| 497 | NLA_U32, | ||
| 498 | entry->type_def.cipsov4->doi) != 0) | ||
| 499 | goto dump_default_failure; | ||
| 500 | buf_len -= 2 * NETLBL_LEN_U32; | ||
| 501 | break; | ||
| 502 | } | ||
| 503 | } else | ||
| 504 | nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE); | ||
| 505 | rcu_read_unlock(); | ||
| 506 | |||
| 507 | return skb; | ||
| 508 | 398 | ||
| 509 | dump_default_failure: | 399 | walk_return: |
| 510 | rcu_read_unlock(); | 400 | rcu_read_unlock(); |
| 511 | kfree_skb(skb); | 401 | *skip_bkt = iter_bkt; |
| 512 | return NULL; | 402 | *skip_chain = chain_cnt; |
| 403 | return ret_val; | ||
| 513 | } | 404 | } |
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h index 99a2287de246..02af72a7877c 100644 --- a/net/netlabel/netlabel_domainhash.h +++ b/net/netlabel/netlabel_domainhash.h | |||
| @@ -61,7 +61,9 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry); | |||
| 61 | int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); | 61 | int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); |
| 62 | int netlbl_domhsh_remove_default(void); | 62 | int netlbl_domhsh_remove_default(void); |
| 63 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); | 63 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); |
| 64 | struct sk_buff *netlbl_domhsh_dump(size_t headroom); | 64 | int netlbl_domhsh_walk(u32 *skip_bkt, |
| 65 | struct sk_buff *netlbl_domhsh_dump_default(size_t headroom); | 65 | u32 *skip_chain, |
| 66 | int (*callback) (struct netlbl_dom_map *entry, void *arg), | ||
| 67 | void *cb_arg); | ||
| 66 | 68 | ||
| 67 | #endif | 69 | #endif |
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 73cbe66e42ff..eeb7d768d2bb 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c | |||
| @@ -74,85 +74,3 @@ int netlbl_netlink_init(void) | |||
| 74 | 74 | ||
| 75 | return 0; | 75 | return 0; |
| 76 | } | 76 | } |
| 77 | |||
| 78 | /* | ||
| 79 | * NetLabel Common Protocol Functions | ||
| 80 | */ | ||
| 81 | |||
| 82 | /** | ||
| 83 | * netlbl_netlink_send_ack - Send an ACK message | ||
| 84 | * @info: the generic NETLINK information | ||
| 85 | * @genl_family: the generic NETLINK family ID value | ||
| 86 | * @ack_cmd: the generic NETLINK family ACK command value | ||
| 87 | * @ret_code: return code to use | ||
| 88 | * | ||
| 89 | * Description: | ||
| 90 | * This function sends an ACK message to the sender of the NETLINK message | ||
| 91 | * specified by @info. | ||
| 92 | * | ||
| 93 | */ | ||
| 94 | void netlbl_netlink_send_ack(const struct genl_info *info, | ||
| 95 | u32 genl_family, | ||
| 96 | u8 ack_cmd, | ||
| 97 | u32 ret_code) | ||
| 98 | { | ||
| 99 | size_t data_size; | ||
| 100 | struct sk_buff *skb; | ||
| 101 | |||
| 102 | data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32; | ||
| 103 | skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); | ||
| 104 | if (skb == NULL) | ||
| 105 | return; | ||
| 106 | |||
| 107 | if (netlbl_netlink_hdr_put(skb, | ||
| 108 | info->snd_pid, | ||
| 109 | 0, | ||
| 110 | genl_family, | ||
| 111 | ack_cmd) == NULL) | ||
| 112 | goto send_ack_failure; | ||
| 113 | |||
| 114 | if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0) | ||
| 115 | goto send_ack_failure; | ||
| 116 | if (nla_put_u32(skb, NLA_U32, ret_code) != 0) | ||
| 117 | goto send_ack_failure; | ||
| 118 | |||
| 119 | netlbl_netlink_snd(skb, info->snd_pid); | ||
| 120 | return; | ||
| 121 | |||
| 122 | send_ack_failure: | ||
| 123 | kfree_skb(skb); | ||
| 124 | } | ||
| 125 | |||
| 126 | /* | ||
| 127 | * NETLINK I/O Functions | ||
| 128 | */ | ||
| 129 | |||
| 130 | /** | ||
| 131 | * netlbl_netlink_snd - Send a NetLabel message | ||
| 132 | * @skb: NetLabel message | ||
| 133 | * @pid: destination PID | ||
| 134 | * | ||
| 135 | * Description: | ||
| 136 | * Sends a unicast NetLabel message over the NETLINK socket. | ||
| 137 | * | ||
| 138 | */ | ||
| 139 | int netlbl_netlink_snd(struct sk_buff *skb, u32 pid) | ||
| 140 | { | ||
| 141 | return genlmsg_unicast(skb, pid); | ||
| 142 | } | ||
| 143 | |||
| 144 | /** | ||
| 145 | * netlbl_netlink_snd - Send a NetLabel message | ||
| 146 | * @skb: NetLabel message | ||
| 147 | * @pid: sending PID | ||
| 148 | * @group: multicast group id | ||
| 149 | * | ||
| 150 | * Description: | ||
| 151 | * Sends a multicast NetLabel message over the NETLINK socket to all members | ||
| 152 | * of @group except @pid. | ||
| 153 | * | ||
| 154 | */ | ||
| 155 | int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group) | ||
| 156 | { | ||
| 157 | return genlmsg_multicast(skb, pid, group, GFP_KERNEL); | ||
| 158 | } | ||
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h index 385a6c7488c6..3f9386b917df 100644 --- a/net/netlabel/netlabel_user.h +++ b/net/netlabel/netlabel_user.h | |||
| @@ -41,72 +41,6 @@ | |||
| 41 | /* NetLabel NETLINK helper functions */ | 41 | /* NetLabel NETLINK helper functions */ |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * netlbl_netlink_cap_check - Check the NETLINK msg capabilities | ||
| 45 | * @skb: the NETLINK buffer | ||
| 46 | * @req_cap: the required capability | ||
| 47 | * | ||
| 48 | * Description: | ||
| 49 | * Check the NETLINK buffer's capabilities against the required capabilities. | ||
| 50 | * Returns zero on success, negative values on failure. | ||
| 51 | * | ||
| 52 | */ | ||
| 53 | static inline int netlbl_netlink_cap_check(const struct sk_buff *skb, | ||
| 54 | kernel_cap_t req_cap) | ||
| 55 | { | ||
| 56 | if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap)) | ||
| 57 | return 0; | ||
| 58 | return -EPERM; | ||
| 59 | } | ||
| 60 | |||
| 61 | /** | ||
| 62 | * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on | ||
| 63 | * @nla: the attribute | ||
| 64 | * @rem_len: remaining length | ||
| 65 | * | ||
| 66 | * Description: | ||
| 67 | * Return a u8 value pointed to by @nla and advance it to the next attribute. | ||
| 68 | * | ||
| 69 | */ | ||
| 70 | static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len) | ||
| 71 | { | ||
| 72 | u8 val = nla_get_u8(*nla); | ||
| 73 | *nla = nla_next(*nla, rem_len); | ||
| 74 | return val; | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on | ||
| 79 | * @nla: the attribute | ||
| 80 | * @rem_len: remaining length | ||
| 81 | * | ||
| 82 | * Description: | ||
| 83 | * Return a u16 value pointed to by @nla and advance it to the next attribute. | ||
| 84 | * | ||
| 85 | */ | ||
| 86 | static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len) | ||
| 87 | { | ||
| 88 | u16 val = nla_get_u16(*nla); | ||
| 89 | *nla = nla_next(*nla, rem_len); | ||
| 90 | return val; | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on | ||
| 95 | * @nla: the attribute | ||
| 96 | * @rem_len: remaining length | ||
| 97 | * | ||
| 98 | * Description: | ||
| 99 | * Return a u32 value pointed to by @nla and advance it to the next attribute. | ||
| 100 | * | ||
| 101 | */ | ||
| 102 | static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len) | ||
| 103 | { | ||
| 104 | u32 val = nla_get_u32(*nla); | ||
| 105 | *nla = nla_next(*nla, rem_len); | ||
| 106 | return val; | ||
| 107 | } | ||
| 108 | |||
| 109 | /** | ||
| 110 | * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff | 44 | * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff |
| 111 | * @skb: the packet | 45 | * @skb: the packet |
| 112 | * @pid: the PID of the receipient | 46 | * @pid: the PID of the receipient |
| @@ -124,6 +58,7 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, | |||
| 124 | u32 pid, | 58 | u32 pid, |
| 125 | u32 seq, | 59 | u32 seq, |
| 126 | int type, | 60 | int type, |
| 61 | int flags, | ||
| 127 | u8 cmd) | 62 | u8 cmd) |
| 128 | { | 63 | { |
| 129 | return genlmsg_put(skb, | 64 | return genlmsg_put(skb, |
| @@ -131,85 +66,13 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, | |||
| 131 | seq, | 66 | seq, |
| 132 | type, | 67 | type, |
| 133 | 0, | 68 | 0, |
| 134 | 0, | 69 | flags, |
| 135 | cmd, | 70 | cmd, |
| 136 | NETLBL_PROTO_VERSION); | 71 | NETLBL_PROTO_VERSION); |
| 137 | } | 72 | } |
| 138 | 73 | ||
| 139 | /** | ||
| 140 | * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff | ||
| 141 | * @skb: the packet | ||
| 142 | * @pid: the PID of the receipient | ||
| 143 | * @seq: the sequence number | ||
| 144 | * @type: the generic NETLINK message family type | ||
| 145 | * @cmd: command | ||
| 146 | * | ||
| 147 | * Description: | ||
| 148 | * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr | ||
| 149 | * struct to the packet. | ||
| 150 | * | ||
| 151 | */ | ||
| 152 | static inline void netlbl_netlink_hdr_push(struct sk_buff *skb, | ||
| 153 | u32 pid, | ||
| 154 | u32 seq, | ||
| 155 | int type, | ||
| 156 | u8 cmd) | ||
| 157 | |||
| 158 | { | ||
| 159 | struct nlmsghdr *nlh; | ||
| 160 | struct genlmsghdr *hdr; | ||
| 161 | |||
| 162 | nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN)); | ||
| 163 | nlh->nlmsg_type = type; | ||
| 164 | nlh->nlmsg_len = skb->len; | ||
| 165 | nlh->nlmsg_flags = 0; | ||
| 166 | nlh->nlmsg_pid = pid; | ||
| 167 | nlh->nlmsg_seq = seq; | ||
| 168 | |||
| 169 | hdr = nlmsg_data(nlh); | ||
| 170 | hdr->cmd = cmd; | ||
| 171 | hdr->version = NETLBL_PROTO_VERSION; | ||
| 172 | hdr->reserved = 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * netlbl_netlink_payload_len - Return the length of the payload | ||
| 177 | * @skb: the NETLINK buffer | ||
| 178 | * | ||
| 179 | * Description: | ||
| 180 | * This function returns the length of the NetLabel payload. | ||
| 181 | * | ||
| 182 | */ | ||
| 183 | static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb) | ||
| 184 | { | ||
| 185 | return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN; | ||
| 186 | } | ||
| 187 | |||
| 188 | /** | ||
| 189 | * netlbl_netlink_payload_data - Returns a pointer to the start of the payload | ||
| 190 | * @skb: the NETLINK buffer | ||
| 191 | * | ||
| 192 | * Description: | ||
| 193 | * This function returns a pointer to the start of the NetLabel payload. | ||
| 194 | * | ||
| 195 | */ | ||
| 196 | static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb) | ||
| 197 | { | ||
| 198 | return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) + | ||
| 199 | GENL_HDRLEN; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* NetLabel common protocol functions */ | ||
| 203 | |||
| 204 | void netlbl_netlink_send_ack(const struct genl_info *info, | ||
| 205 | u32 genl_family, | ||
| 206 | u8 ack_cmd, | ||
| 207 | u32 ret_code); | ||
| 208 | |||
| 209 | /* NetLabel NETLINK I/O functions */ | 74 | /* NetLabel NETLINK I/O functions */ |
| 210 | 75 | ||
| 211 | int netlbl_netlink_init(void); | 76 | int netlbl_netlink_init(void); |
| 212 | int netlbl_netlink_snd(struct sk_buff *skb, u32 pid); | ||
| 213 | int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group); | ||
| 214 | 77 | ||
| 215 | #endif | 78 | #endif |
