Skip to content
This repository has been archived by the owner on Aug 27, 2022. It is now read-only.

Commit

Permalink
[NetLabel]: rework the Netlink attribute handling (part 1)
Browse files Browse the repository at this point in the history
At the suggestion of Thomas Graf, rewrite NetLabel's use of Netlink attributes
to better follow the common Netlink attribute usage.

Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
pcmoore authored and davem330 committed Sep 25, 2006
1 parent 4fe5d5c commit fcd4828
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 604 deletions.
16 changes: 7 additions & 9 deletions include/net/cipso_ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ extern int cipso_v4_rbm_strictvalid;
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head));
struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
struct sk_buff *cipso_v4_doi_dump_all(size_t headroom);
struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom);
int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg);
int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain);
int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
const char *domain);
Expand All @@ -152,14 +153,11 @@ static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
return NULL;
}

static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom)
static inline int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg)
{
return NULL;
}

static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
{
return NULL;
return 0;
}

static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
Expand Down
49 changes: 2 additions & 47 deletions include/net/netlabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@
* The payload is dependent on the subsystem specified in the
* 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions
* should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c
* file. All of the fields in the NetLabel payload are NETLINK attributes, the
* length of each field is the length of the NETLINK attribute payload, see
* include/net/netlink.h for more information on NETLINK attributes.
* file. All of the fields in the NetLabel payload are NETLINK attributes, see
* the include/net/netlink.h file for more information on NETLINK attributes.
*
*/

Expand All @@ -82,50 +81,6 @@
#define NETLBL_NLTYPE_UNLABELED 5
#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL"

/* NetLabel return codes */
#define NETLBL_E_OK 0

/*
* Helper functions
*/

#define NETLBL_LEN_U8 nla_total_size(sizeof(u8))
#define NETLBL_LEN_U16 nla_total_size(sizeof(u16))
#define NETLBL_LEN_U32 nla_total_size(sizeof(u32))

/**
* netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer
* @head: the amount of headroom in bytes
* @body: the desired size (minus headroom) in bytes
* @gfp_flags: the alloc flags to pass to alloc_skb()
*
* Description:
* Allocate a NETLINK message buffer based on the sizes given in @head and
* @body. If @head is greater than zero skb_reserve() is called to reserve
* @head bytes at the start of the buffer. Returns a valid sk_buff pointer on
* success, NULL on failure.
*
*/
static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head,
size_t body,
gfp_t gfp_flags)
{
struct sk_buff *skb;

skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags);
if (skb == NULL)
return NULL;
if (head > 0) {
skb_reserve(skb, head);
if (skb_tailroom(skb) < body) {
kfree_skb(skb);
return NULL;
}
}

return skb;
}

/*
* NetLabel - Kernel API for accessing the network packet label mappings.
*
Expand Down
203 changes: 24 additions & 179 deletions net/ipv4/cipso_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
}

/**
* cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff
* @headroom: the amount of headroom to allocate for the sk_buff
* cipso_v4_doi_walk - Iterate through the DOI definitions
* @skip_cnt: skip past this number of DOI definitions, updated
* @callback: callback for each DOI definition
* @cb_arg: argument for the callback function
*
* Description:
* Dump a list of all the configured DOI values into a sk_buff. The returned
* sk_buff has room at the front of the sk_buff for @headroom bytes. See
* net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This
* function may fail if another process is changing the DOI list at the same
* time. Returns a pointer to a sk_buff on success, NULL on error.
* Iterate over the DOI definition list, skipping the first @skip_cnt entries.
* For each entry call @callback, if @callback returns a negative value stop
* 'walking' through the list and return. Updates the value in @skip_cnt upon
* return. Returns zero on success, negative values on failure.
*
*/
struct sk_buff *cipso_v4_doi_dump_all(size_t headroom)
int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg)
{
struct sk_buff *skb = NULL;
struct cipso_v4_doi *iter;
int ret_val = -ENOENT;
u32 doi_cnt = 0;
ssize_t buf_len;

buf_len = NETLBL_LEN_U32;
rcu_read_lock();
list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
if (iter->valid) {
doi_cnt += 1;
buf_len += 2 * NETLBL_LEN_U32;
}

skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
if (skb == NULL)
goto doi_dump_all_failure;

if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0)
goto doi_dump_all_failure;
buf_len -= NETLBL_LEN_U32;
list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
if (iter->valid) {
if (buf_len < 2 * NETLBL_LEN_U32)
goto doi_dump_all_failure;
if (nla_put_u32(skb, NLA_U32, iter->doi) != 0)
goto doi_dump_all_failure;
if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
goto doi_dump_all_failure;
buf_len -= 2 * NETLBL_LEN_U32;
}
rcu_read_unlock();

return skb;

doi_dump_all_failure:
rcu_read_unlock();
kfree(skb);
return NULL;
}

/**
* cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff
* @doi: the DOI value
* @headroom: the amount of headroom to allocate for the sk_buff
*
* Description:
* Lookup the DOI definition matching @doi and dump it's contents into a
* sk_buff. The returned sk_buff has room at the front of the sk_buff for
* @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message
* format. This function may fail if another process is changing the DOI list
* at the same time. Returns a pointer to a sk_buff on success, NULL on error.
*
*/
struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
{
struct sk_buff *skb = NULL;
struct cipso_v4_doi *iter;
u32 tag_cnt = 0;
u32 lvl_cnt = 0;
u32 cat_cnt = 0;
ssize_t buf_len;
ssize_t tmp;
struct cipso_v4_doi *iter_doi;

rcu_read_lock();
iter = cipso_v4_doi_getdef(doi);
if (iter == NULL)
goto doi_dump_failure;
buf_len = NETLBL_LEN_U32;
switch (iter->type) {
case CIPSO_V4_MAP_PASS:
buf_len += NETLBL_LEN_U32;
while(tag_cnt < CIPSO_V4_TAG_MAXCNT &&
iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
tag_cnt += 1;
buf_len += NETLBL_LEN_U8;
}
break;
case CIPSO_V4_MAP_STD:
buf_len += 3 * NETLBL_LEN_U32;
while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
tag_cnt += 1;
buf_len += NETLBL_LEN_U8;
}
for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
if (iter->map.std->lvl.local[tmp] !=
CIPSO_V4_INV_LVL) {
lvl_cnt += 1;
buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8;
list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
if (iter_doi->valid) {
if (doi_cnt++ < *skip_cnt)
continue;
ret_val = callback(iter_doi, cb_arg);
if (ret_val < 0) {
doi_cnt--;
goto doi_walk_return;
}
for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
if (iter->map.std->cat.local[tmp] !=
CIPSO_V4_INV_CAT) {
cat_cnt += 1;
buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16;
}
break;
}

skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
if (skb == NULL)
goto doi_dump_failure;

if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
goto doi_dump_failure;
buf_len -= NETLBL_LEN_U32;
if (iter != cipso_v4_doi_getdef(doi))
goto doi_dump_failure;
switch (iter->type) {
case CIPSO_V4_MAP_PASS:
if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
goto doi_dump_failure;
buf_len -= NETLBL_LEN_U32;
for (tmp = 0;
tmp < CIPSO_V4_TAG_MAXCNT &&
iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
tmp++) {
if (buf_len < NETLBL_LEN_U8)
goto doi_dump_failure;
if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
goto doi_dump_failure;
buf_len -= NETLBL_LEN_U8;
}
break;
case CIPSO_V4_MAP_STD:
if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
goto doi_dump_failure;
if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0)
goto doi_dump_failure;
if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0)
goto doi_dump_failure;
buf_len -= 3 * NETLBL_LEN_U32;
for (tmp = 0;
tmp < CIPSO_V4_TAG_MAXCNT &&
iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
tmp++) {
if (buf_len < NETLBL_LEN_U8)
goto doi_dump_failure;
if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
goto doi_dump_failure;
buf_len -= NETLBL_LEN_U8;
}
for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
if (iter->map.std->lvl.local[tmp] !=
CIPSO_V4_INV_LVL) {
if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8)
goto doi_dump_failure;
if (nla_put_u32(skb, NLA_U32, tmp) != 0)
goto doi_dump_failure;
if (nla_put_u8(skb,
NLA_U8,
iter->map.std->lvl.local[tmp]) != 0)
goto doi_dump_failure;
buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8;
}
for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
if (iter->map.std->cat.local[tmp] !=
CIPSO_V4_INV_CAT) {
if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16)
goto doi_dump_failure;
if (nla_put_u32(skb, NLA_U32, tmp) != 0)
goto doi_dump_failure;
if (nla_put_u16(skb,
NLA_U16,
iter->map.std->cat.local[tmp]) != 0)
goto doi_dump_failure;
buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16;
}
break;
}
rcu_read_unlock();

return skb;

doi_dump_failure:
doi_walk_return:
rcu_read_unlock();
kfree(skb);
return NULL;
*skip_cnt = doi_cnt;
return ret_val;
}

/**
Expand Down
Loading

0 comments on commit fcd4828

Please sign in to comment.