diff options
author | Paul Moore <paul.moore@hp.com> | 2006-09-25 18:56:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-09-25 18:56:09 -0400 |
commit | fcd48280643e92ec6cb29a04e9079dd7b6b5bfef (patch) | |
tree | c594e16a021262e97f8b41493529c95bd616529e /net/netlabel | |
parent | 4fe5d5c07ab615a52fd1b0ceba5aeed7c612821a (diff) |
[NetLabel]: rework the Netlink attribute handling (part 1)
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>
Diffstat (limited to 'net/netlabel')
-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 |
4 files changed, 43 insertions, 369 deletions
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 |