aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-09-25 18:56:09 -0400
committerDavid S. Miller <davem@davemloft.net>2006-09-25 18:56:09 -0400
commitfcd48280643e92ec6cb29a04e9079dd7b6b5bfef (patch)
treec594e16a021262e97f8b41493529c95bd616529e /net/netlabel
parent4fe5d5c07ab615a52fd1b0ceba5aeed7c612821a (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.c183
-rw-r--r--net/netlabel/netlabel_domainhash.h6
-rw-r--r--net/netlabel/netlabel_user.c82
-rw-r--r--net/netlabel/netlabel_user.h141
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 */
368struct sk_buff *netlbl_domhsh_dump(size_t headroom) 371int 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
440dump_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 */
458struct 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
509dump_default_failure: 399walk_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);
61int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); 61int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
62int netlbl_domhsh_remove_default(void); 62int netlbl_domhsh_remove_default(void);
63struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); 63struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
64struct sk_buff *netlbl_domhsh_dump(size_t headroom); 64int netlbl_domhsh_walk(u32 *skip_bkt,
65struct 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 */
94void 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
122send_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 */
139int 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 */
155int 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 */
53static 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 */
70static 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 */
86static 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 */
102static 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 */
152static 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 */
183static 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 */
196static 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
204void 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
211int netlbl_netlink_init(void); 76int netlbl_netlink_init(void);
212int netlbl_netlink_snd(struct sk_buff *skb, u32 pid);
213int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group);
214 77
215#endif 78#endif