diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2008-10-17 12:20:26 -0400 |
---|---|---|
committer | Arjan van de Ven <arjan@linux.intel.com> | 2008-10-17 12:20:26 -0400 |
commit | 651dab4264e4ba0e563f5ff56f748127246e9065 (patch) | |
tree | 016630974bdcb00fe529b673f96d389e0fd6dc94 /net/netlabel/netlabel_mgmt.c | |
parent | 40b8606253552109815786e5d4b0de98782d31f5 (diff) | |
parent | 2e532d68a2b3e2aa6b19731501222069735c741c (diff) |
Merge commit 'linus/master' into merge-linus
Conflicts:
arch/x86/kvm/i8254.c
Diffstat (limited to 'net/netlabel/netlabel_mgmt.c')
-rw-r--r-- | net/netlabel/netlabel_mgmt.c | 410 |
1 files changed, 304 insertions, 106 deletions
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 44be5d5261f4..ee769ecaa13c 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c | |||
@@ -10,7 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
16 | * it under the terms of the GNU General Public License as published by | 16 | * it under the terms of the GNU General Public License as published by |
@@ -32,9 +32,13 @@ | |||
32 | #include <linux/socket.h> | 32 | #include <linux/socket.h> |
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <linux/in.h> | ||
36 | #include <linux/in6.h> | ||
35 | #include <net/sock.h> | 37 | #include <net/sock.h> |
36 | #include <net/netlink.h> | 38 | #include <net/netlink.h> |
37 | #include <net/genetlink.h> | 39 | #include <net/genetlink.h> |
40 | #include <net/ip.h> | ||
41 | #include <net/ipv6.h> | ||
38 | #include <net/netlabel.h> | 42 | #include <net/netlabel.h> |
39 | #include <net/cipso_ipv4.h> | 43 | #include <net/cipso_ipv4.h> |
40 | #include <asm/atomic.h> | 44 | #include <asm/atomic.h> |
@@ -71,86 +75,337 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { | |||
71 | }; | 75 | }; |
72 | 76 | ||
73 | /* | 77 | /* |
74 | * NetLabel Command Handlers | 78 | * Helper Functions |
75 | */ | 79 | */ |
76 | 80 | ||
77 | /** | 81 | /** |
78 | * netlbl_mgmt_add - Handle an ADD message | 82 | * netlbl_mgmt_add - Handle an ADD message |
79 | * @skb: the NETLINK buffer | ||
80 | * @info: the Generic NETLINK info block | 83 | * @info: the Generic NETLINK info block |
84 | * @audit_info: NetLabel audit information | ||
81 | * | 85 | * |
82 | * Description: | 86 | * Description: |
83 | * Process a user generated ADD message and add the domains from the message | 87 | * Helper function for the ADD and ADDDEF messages to add the domain mappings |
84 | * to the hash table. See netlabel.h for a description of the message format. | 88 | * from the message to the hash table. See netlabel.h for a description of the |
85 | * Returns zero on success, negative values on failure. | 89 | * message format. Returns zero on success, negative values on failure. |
86 | * | 90 | * |
87 | */ | 91 | */ |
88 | static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) | 92 | static int netlbl_mgmt_add_common(struct genl_info *info, |
93 | struct netlbl_audit *audit_info) | ||
89 | { | 94 | { |
90 | int ret_val = -EINVAL; | 95 | int ret_val = -EINVAL; |
91 | struct netlbl_dom_map *entry = NULL; | 96 | struct netlbl_dom_map *entry = NULL; |
92 | size_t tmp_size; | 97 | struct netlbl_domaddr_map *addrmap = NULL; |
98 | struct cipso_v4_doi *cipsov4 = NULL; | ||
93 | u32 tmp_val; | 99 | u32 tmp_val; |
94 | struct netlbl_audit audit_info; | ||
95 | |||
96 | if (!info->attrs[NLBL_MGMT_A_DOMAIN] || | ||
97 | !info->attrs[NLBL_MGMT_A_PROTOCOL]) | ||
98 | goto add_failure; | ||
99 | |||
100 | netlbl_netlink_auditinfo(skb, &audit_info); | ||
101 | 100 | ||
102 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 101 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
103 | if (entry == NULL) { | 102 | if (entry == NULL) { |
104 | ret_val = -ENOMEM; | 103 | ret_val = -ENOMEM; |
105 | goto add_failure; | 104 | goto add_failure; |
106 | } | 105 | } |
107 | tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); | ||
108 | entry->domain = kmalloc(tmp_size, GFP_KERNEL); | ||
109 | if (entry->domain == NULL) { | ||
110 | ret_val = -ENOMEM; | ||
111 | goto add_failure; | ||
112 | } | ||
113 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); | 106 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); |
114 | nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); | 107 | if (info->attrs[NLBL_MGMT_A_DOMAIN]) { |
108 | size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); | ||
109 | entry->domain = kmalloc(tmp_size, GFP_KERNEL); | ||
110 | if (entry->domain == NULL) { | ||
111 | ret_val = -ENOMEM; | ||
112 | goto add_failure; | ||
113 | } | ||
114 | nla_strlcpy(entry->domain, | ||
115 | info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); | ||
116 | } | ||
117 | |||
118 | /* NOTE: internally we allow/use a entry->type value of | ||
119 | * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users | ||
120 | * to pass that as a protocol value because we need to know the | ||
121 | * "real" protocol */ | ||
115 | 122 | ||
116 | switch (entry->type) { | 123 | switch (entry->type) { |
117 | case NETLBL_NLTYPE_UNLABELED: | 124 | case NETLBL_NLTYPE_UNLABELED: |
118 | ret_val = netlbl_domhsh_add(entry, &audit_info); | ||
119 | break; | 125 | break; |
120 | case NETLBL_NLTYPE_CIPSOV4: | 126 | case NETLBL_NLTYPE_CIPSOV4: |
121 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) | 127 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) |
122 | goto add_failure; | 128 | goto add_failure; |
123 | 129 | ||
124 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); | 130 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); |
125 | /* We should be holding a rcu_read_lock() here while we hold | 131 | cipsov4 = cipso_v4_doi_getdef(tmp_val); |
126 | * the result but since the entry will always be deleted when | 132 | if (cipsov4 == NULL) |
127 | * the CIPSO DOI is deleted we aren't going to keep the | ||
128 | * lock. */ | ||
129 | rcu_read_lock(); | ||
130 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); | ||
131 | if (entry->type_def.cipsov4 == NULL) { | ||
132 | rcu_read_unlock(); | ||
133 | goto add_failure; | 133 | goto add_failure; |
134 | } | 134 | entry->type_def.cipsov4 = cipsov4; |
135 | ret_val = netlbl_domhsh_add(entry, &audit_info); | ||
136 | rcu_read_unlock(); | ||
137 | break; | 135 | break; |
138 | default: | 136 | default: |
139 | goto add_failure; | 137 | goto add_failure; |
140 | } | 138 | } |
139 | |||
140 | if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) { | ||
141 | struct in_addr *addr; | ||
142 | struct in_addr *mask; | ||
143 | struct netlbl_domaddr4_map *map; | ||
144 | |||
145 | addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); | ||
146 | if (addrmap == NULL) { | ||
147 | ret_val = -ENOMEM; | ||
148 | goto add_failure; | ||
149 | } | ||
150 | INIT_LIST_HEAD(&addrmap->list4); | ||
151 | INIT_LIST_HEAD(&addrmap->list6); | ||
152 | |||
153 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) != | ||
154 | sizeof(struct in_addr)) { | ||
155 | ret_val = -EINVAL; | ||
156 | goto add_failure; | ||
157 | } | ||
158 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) != | ||
159 | sizeof(struct in_addr)) { | ||
160 | ret_val = -EINVAL; | ||
161 | goto add_failure; | ||
162 | } | ||
163 | addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]); | ||
164 | mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]); | ||
165 | |||
166 | map = kzalloc(sizeof(*map), GFP_KERNEL); | ||
167 | if (map == NULL) { | ||
168 | ret_val = -ENOMEM; | ||
169 | goto add_failure; | ||
170 | } | ||
171 | map->list.addr = addr->s_addr & mask->s_addr; | ||
172 | map->list.mask = mask->s_addr; | ||
173 | map->list.valid = 1; | ||
174 | map->type = entry->type; | ||
175 | if (cipsov4) | ||
176 | map->type_def.cipsov4 = cipsov4; | ||
177 | |||
178 | ret_val = netlbl_af4list_add(&map->list, &addrmap->list4); | ||
179 | if (ret_val != 0) { | ||
180 | kfree(map); | ||
181 | goto add_failure; | ||
182 | } | ||
183 | |||
184 | entry->type = NETLBL_NLTYPE_ADDRSELECT; | ||
185 | entry->type_def.addrsel = addrmap; | ||
186 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
187 | } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) { | ||
188 | struct in6_addr *addr; | ||
189 | struct in6_addr *mask; | ||
190 | struct netlbl_domaddr6_map *map; | ||
191 | |||
192 | addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); | ||
193 | if (addrmap == NULL) { | ||
194 | ret_val = -ENOMEM; | ||
195 | goto add_failure; | ||
196 | } | ||
197 | INIT_LIST_HEAD(&addrmap->list4); | ||
198 | INIT_LIST_HEAD(&addrmap->list6); | ||
199 | |||
200 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) != | ||
201 | sizeof(struct in6_addr)) { | ||
202 | ret_val = -EINVAL; | ||
203 | goto add_failure; | ||
204 | } | ||
205 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) != | ||
206 | sizeof(struct in6_addr)) { | ||
207 | ret_val = -EINVAL; | ||
208 | goto add_failure; | ||
209 | } | ||
210 | addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]); | ||
211 | mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]); | ||
212 | |||
213 | map = kzalloc(sizeof(*map), GFP_KERNEL); | ||
214 | if (map == NULL) { | ||
215 | ret_val = -ENOMEM; | ||
216 | goto add_failure; | ||
217 | } | ||
218 | ipv6_addr_copy(&map->list.addr, addr); | ||
219 | map->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; | ||
220 | map->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; | ||
221 | map->list.addr.s6_addr32[2] &= mask->s6_addr32[2]; | ||
222 | map->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; | ||
223 | ipv6_addr_copy(&map->list.mask, mask); | ||
224 | map->list.valid = 1; | ||
225 | map->type = entry->type; | ||
226 | |||
227 | ret_val = netlbl_af6list_add(&map->list, &addrmap->list6); | ||
228 | if (ret_val != 0) { | ||
229 | kfree(map); | ||
230 | goto add_failure; | ||
231 | } | ||
232 | |||
233 | entry->type = NETLBL_NLTYPE_ADDRSELECT; | ||
234 | entry->type_def.addrsel = addrmap; | ||
235 | #endif /* IPv6 */ | ||
236 | } | ||
237 | |||
238 | ret_val = netlbl_domhsh_add(entry, audit_info); | ||
141 | if (ret_val != 0) | 239 | if (ret_val != 0) |
142 | goto add_failure; | 240 | goto add_failure; |
143 | 241 | ||
144 | return 0; | 242 | return 0; |
145 | 243 | ||
146 | add_failure: | 244 | add_failure: |
245 | if (cipsov4) | ||
246 | cipso_v4_doi_putdef(cipsov4); | ||
147 | if (entry) | 247 | if (entry) |
148 | kfree(entry->domain); | 248 | kfree(entry->domain); |
249 | kfree(addrmap); | ||
149 | kfree(entry); | 250 | kfree(entry); |
150 | return ret_val; | 251 | return ret_val; |
151 | } | 252 | } |
152 | 253 | ||
153 | /** | 254 | /** |
255 | * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry | ||
256 | * @skb: the NETLINK buffer | ||
257 | * @entry: the map entry | ||
258 | * | ||
259 | * Description: | ||
260 | * This function is a helper function used by the LISTALL and LISTDEF command | ||
261 | * handlers. The caller is responsibile for ensuring that the RCU read lock | ||
262 | * is held. Returns zero on success, negative values on failure. | ||
263 | * | ||
264 | */ | ||
265 | static int netlbl_mgmt_listentry(struct sk_buff *skb, | ||
266 | struct netlbl_dom_map *entry) | ||
267 | { | ||
268 | int ret_val; | ||
269 | struct nlattr *nla_a; | ||
270 | struct nlattr *nla_b; | ||
271 | struct netlbl_af4list *iter4; | ||
272 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
273 | struct netlbl_af6list *iter6; | ||
274 | #endif | ||
275 | |||
276 | if (entry->domain != NULL) { | ||
277 | ret_val = nla_put_string(skb, | ||
278 | NLBL_MGMT_A_DOMAIN, entry->domain); | ||
279 | if (ret_val != 0) | ||
280 | return ret_val; | ||
281 | } | ||
282 | |||
283 | switch (entry->type) { | ||
284 | case NETLBL_NLTYPE_ADDRSELECT: | ||
285 | nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST); | ||
286 | if (nla_a == NULL) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | netlbl_af4list_foreach_rcu(iter4, | ||
290 | &entry->type_def.addrsel->list4) { | ||
291 | struct netlbl_domaddr4_map *map4; | ||
292 | struct in_addr addr_struct; | ||
293 | |||
294 | nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR); | ||
295 | if (nla_b == NULL) | ||
296 | return -ENOMEM; | ||
297 | |||
298 | addr_struct.s_addr = iter4->addr; | ||
299 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR, | ||
300 | sizeof(struct in_addr), | ||
301 | &addr_struct); | ||
302 | if (ret_val != 0) | ||
303 | return ret_val; | ||
304 | addr_struct.s_addr = iter4->mask; | ||
305 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK, | ||
306 | sizeof(struct in_addr), | ||
307 | &addr_struct); | ||
308 | if (ret_val != 0) | ||
309 | return ret_val; | ||
310 | map4 = netlbl_domhsh_addr4_entry(iter4); | ||
311 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, | ||
312 | map4->type); | ||
313 | if (ret_val != 0) | ||
314 | return ret_val; | ||
315 | switch (map4->type) { | ||
316 | case NETLBL_NLTYPE_CIPSOV4: | ||
317 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, | ||
318 | map4->type_def.cipsov4->doi); | ||
319 | if (ret_val != 0) | ||
320 | return ret_val; | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | nla_nest_end(skb, nla_b); | ||
325 | } | ||
326 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
327 | netlbl_af6list_foreach_rcu(iter6, | ||
328 | &entry->type_def.addrsel->list6) { | ||
329 | struct netlbl_domaddr6_map *map6; | ||
330 | |||
331 | nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR); | ||
332 | if (nla_b == NULL) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR, | ||
336 | sizeof(struct in6_addr), | ||
337 | &iter6->addr); | ||
338 | if (ret_val != 0) | ||
339 | return ret_val; | ||
340 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK, | ||
341 | sizeof(struct in6_addr), | ||
342 | &iter6->mask); | ||
343 | if (ret_val != 0) | ||
344 | return ret_val; | ||
345 | map6 = netlbl_domhsh_addr6_entry(iter6); | ||
346 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, | ||
347 | map6->type); | ||
348 | if (ret_val != 0) | ||
349 | return ret_val; | ||
350 | |||
351 | nla_nest_end(skb, nla_b); | ||
352 | } | ||
353 | #endif /* IPv6 */ | ||
354 | |||
355 | nla_nest_end(skb, nla_a); | ||
356 | break; | ||
357 | case NETLBL_NLTYPE_UNLABELED: | ||
358 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
359 | break; | ||
360 | case NETLBL_NLTYPE_CIPSOV4: | ||
361 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
362 | if (ret_val != 0) | ||
363 | return ret_val; | ||
364 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, | ||
365 | entry->type_def.cipsov4->doi); | ||
366 | break; | ||
367 | } | ||
368 | |||
369 | return ret_val; | ||
370 | } | ||
371 | |||
372 | /* | ||
373 | * NetLabel Command Handlers | ||
374 | */ | ||
375 | |||
376 | /** | ||
377 | * netlbl_mgmt_add - Handle an ADD message | ||
378 | * @skb: the NETLINK buffer | ||
379 | * @info: the Generic NETLINK info block | ||
380 | * | ||
381 | * Description: | ||
382 | * Process a user generated ADD message and add the domains from the message | ||
383 | * to the hash table. See netlabel.h for a description of the message format. | ||
384 | * Returns zero on success, negative values on failure. | ||
385 | * | ||
386 | */ | ||
387 | static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) | ||
388 | { | ||
389 | struct netlbl_audit audit_info; | ||
390 | |||
391 | if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) || | ||
392 | (!info->attrs[NLBL_MGMT_A_PROTOCOL]) || | ||
393 | (info->attrs[NLBL_MGMT_A_IPV4ADDR] && | ||
394 | info->attrs[NLBL_MGMT_A_IPV6ADDR]) || | ||
395 | (info->attrs[NLBL_MGMT_A_IPV4MASK] && | ||
396 | info->attrs[NLBL_MGMT_A_IPV6MASK]) || | ||
397 | ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ | ||
398 | (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || | ||
399 | ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ | ||
400 | (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) | ||
401 | return -EINVAL; | ||
402 | |||
403 | netlbl_netlink_auditinfo(skb, &audit_info); | ||
404 | |||
405 | return netlbl_mgmt_add_common(info, &audit_info); | ||
406 | } | ||
407 | |||
408 | /** | ||
154 | * netlbl_mgmt_remove - Handle a REMOVE message | 409 | * netlbl_mgmt_remove - Handle a REMOVE message |
155 | * @skb: the NETLINK buffer | 410 | * @skb: the NETLINK buffer |
156 | * @info: the Generic NETLINK info block | 411 | * @info: the Generic NETLINK info block |
@@ -198,23 +453,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) | |||
198 | if (data == NULL) | 453 | if (data == NULL) |
199 | goto listall_cb_failure; | 454 | goto listall_cb_failure; |
200 | 455 | ||
201 | ret_val = nla_put_string(cb_arg->skb, | 456 | ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry); |
202 | NLBL_MGMT_A_DOMAIN, | ||
203 | entry->domain); | ||
204 | if (ret_val != 0) | 457 | if (ret_val != 0) |
205 | goto listall_cb_failure; | 458 | goto listall_cb_failure; |
206 | ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
207 | if (ret_val != 0) | ||
208 | goto listall_cb_failure; | ||
209 | switch (entry->type) { | ||
210 | case NETLBL_NLTYPE_CIPSOV4: | ||
211 | ret_val = nla_put_u32(cb_arg->skb, | ||
212 | NLBL_MGMT_A_CV4DOI, | ||
213 | entry->type_def.cipsov4->doi); | ||
214 | if (ret_val != 0) | ||
215 | goto listall_cb_failure; | ||
216 | break; | ||
217 | } | ||
218 | 459 | ||
219 | cb_arg->seq++; | 460 | cb_arg->seq++; |
220 | return genlmsg_end(cb_arg->skb, data); | 461 | return genlmsg_end(cb_arg->skb, data); |
@@ -268,56 +509,22 @@ static int netlbl_mgmt_listall(struct sk_buff *skb, | |||
268 | */ | 509 | */ |
269 | static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) | 510 | static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) |
270 | { | 511 | { |
271 | int ret_val = -EINVAL; | ||
272 | struct netlbl_dom_map *entry = NULL; | ||
273 | u32 tmp_val; | ||
274 | struct netlbl_audit audit_info; | 512 | struct netlbl_audit audit_info; |
275 | 513 | ||
276 | if (!info->attrs[NLBL_MGMT_A_PROTOCOL]) | 514 | if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) || |
277 | goto adddef_failure; | 515 | (info->attrs[NLBL_MGMT_A_IPV4ADDR] && |
516 | info->attrs[NLBL_MGMT_A_IPV6ADDR]) || | ||
517 | (info->attrs[NLBL_MGMT_A_IPV4MASK] && | ||
518 | info->attrs[NLBL_MGMT_A_IPV6MASK]) || | ||
519 | ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ | ||
520 | (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || | ||
521 | ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ | ||
522 | (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) | ||
523 | return -EINVAL; | ||
278 | 524 | ||
279 | netlbl_netlink_auditinfo(skb, &audit_info); | 525 | netlbl_netlink_auditinfo(skb, &audit_info); |
280 | 526 | ||
281 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 527 | return netlbl_mgmt_add_common(info, &audit_info); |
282 | if (entry == NULL) { | ||
283 | ret_val = -ENOMEM; | ||
284 | goto adddef_failure; | ||
285 | } | ||
286 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); | ||
287 | |||
288 | switch (entry->type) { | ||
289 | case NETLBL_NLTYPE_UNLABELED: | ||
290 | ret_val = netlbl_domhsh_add_default(entry, &audit_info); | ||
291 | break; | ||
292 | case NETLBL_NLTYPE_CIPSOV4: | ||
293 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) | ||
294 | goto adddef_failure; | ||
295 | |||
296 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); | ||
297 | /* We should be holding a rcu_read_lock() here while we hold | ||
298 | * the result but since the entry will always be deleted when | ||
299 | * the CIPSO DOI is deleted we aren't going to keep the | ||
300 | * lock. */ | ||
301 | rcu_read_lock(); | ||
302 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); | ||
303 | if (entry->type_def.cipsov4 == NULL) { | ||
304 | rcu_read_unlock(); | ||
305 | goto adddef_failure; | ||
306 | } | ||
307 | ret_val = netlbl_domhsh_add_default(entry, &audit_info); | ||
308 | rcu_read_unlock(); | ||
309 | break; | ||
310 | default: | ||
311 | goto adddef_failure; | ||
312 | } | ||
313 | if (ret_val != 0) | ||
314 | goto adddef_failure; | ||
315 | |||
316 | return 0; | ||
317 | |||
318 | adddef_failure: | ||
319 | kfree(entry); | ||
320 | return ret_val; | ||
321 | } | 528 | } |
322 | 529 | ||
323 | /** | 530 | /** |
@@ -371,19 +578,10 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) | |||
371 | ret_val = -ENOENT; | 578 | ret_val = -ENOENT; |
372 | goto listdef_failure_lock; | 579 | goto listdef_failure_lock; |
373 | } | 580 | } |
374 | ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type); | 581 | ret_val = netlbl_mgmt_listentry(ans_skb, entry); |
375 | if (ret_val != 0) | ||
376 | goto listdef_failure_lock; | ||
377 | switch (entry->type) { | ||
378 | case NETLBL_NLTYPE_CIPSOV4: | ||
379 | ret_val = nla_put_u32(ans_skb, | ||
380 | NLBL_MGMT_A_CV4DOI, | ||
381 | entry->type_def.cipsov4->doi); | ||
382 | if (ret_val != 0) | ||
383 | goto listdef_failure_lock; | ||
384 | break; | ||
385 | } | ||
386 | rcu_read_unlock(); | 582 | rcu_read_unlock(); |
583 | if (ret_val != 0) | ||
584 | goto listdef_failure; | ||
387 | 585 | ||
388 | genlmsg_end(ans_skb, data); | 586 | genlmsg_end(ans_skb, data); |
389 | return genlmsg_reply(ans_skb, info); | 587 | return genlmsg_reply(ans_skb, info); |