aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-09-25 18:56:37 -0400
committerDavid S. Miller <davem@davemloft.net>2006-09-25 18:56:37 -0400
commitfd3858554b62c3af6b7664b5c58ad864c87116c9 (patch)
tree9b01a61ed88a19331565649f04373a08ca3d3aa6
parentfcd48280643e92ec6cb29a04e9079dd7b6b5bfef (diff)
[NetLabel]: rework the Netlink attribute handling (part 2)
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>
-rw-r--r--net/netlabel/netlabel_cipso_v4.c628
-rw-r--r--net/netlabel/netlabel_cipso_v4.h225
-rw-r--r--net/netlabel/netlabel_mgmt.c541
-rw-r--r--net/netlabel/netlabel_mgmt.h211
-rw-r--r--net/netlabel/netlabel_unlabeled.c79
-rw-r--r--net/netlabel/netlabel_unlabeled.h41
6 files changed, 895 insertions, 830 deletions
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index a4f40adc447b..4125a55f469f 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -41,15 +41,37 @@
41#include "netlabel_user.h" 41#include "netlabel_user.h"
42#include "netlabel_cipso_v4.h" 42#include "netlabel_cipso_v4.h"
43 43
44/* Argument struct for cipso_v4_doi_walk() */
45struct netlbl_cipsov4_doiwalk_arg {
46 struct netlink_callback *nl_cb;
47 struct sk_buff *skb;
48 u32 seq;
49};
50
44/* NetLabel Generic NETLINK CIPSOv4 family */ 51/* NetLabel Generic NETLINK CIPSOv4 family */
45static struct genl_family netlbl_cipsov4_gnl_family = { 52static struct genl_family netlbl_cipsov4_gnl_family = {
46 .id = GENL_ID_GENERATE, 53 .id = GENL_ID_GENERATE,
47 .hdrsize = 0, 54 .hdrsize = 0,
48 .name = NETLBL_NLTYPE_CIPSOV4_NAME, 55 .name = NETLBL_NLTYPE_CIPSOV4_NAME,
49 .version = NETLBL_PROTO_VERSION, 56 .version = NETLBL_PROTO_VERSION,
50 .maxattr = 0, 57 .maxattr = NLBL_CIPSOV4_A_MAX,
51}; 58};
52 59
60/* NetLabel Netlink attribute policy */
61static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
62 [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
63 [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
64 [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
65 [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
66 [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
67 [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
68 [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
69 [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
70 [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
71 [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
72 [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
73 [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
74};
53 75
54/* 76/*
55 * Helper Functions 77 * Helper Functions
@@ -81,6 +103,41 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
81 kfree(ptr); 103 kfree(ptr);
82} 104}
83 105
106/**
107 * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
108 * @info: the Generic NETLINK info block
109 * @doi_def: the CIPSO V4 DOI definition
110 *
111 * Description:
112 * Parse the common sections of a ADD message and fill in the related values
113 * in @doi_def. Returns zero on success, negative values on failure.
114 *
115 */
116static int netlbl_cipsov4_add_common(struct genl_info *info,
117 struct cipso_v4_doi *doi_def)
118{
119 struct nlattr *nla;
120 int nla_rem;
121 u32 iter = 0;
122
123 doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
124
125 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST],
126 NLBL_CIPSOV4_A_MAX,
127 netlbl_cipsov4_genl_policy) != 0)
128 return -EINVAL;
129
130 nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
131 if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
132 if (iter > CIPSO_V4_TAG_MAXCNT)
133 return -EINVAL;
134 doi_def->tags[iter++] = nla_get_u8(nla);
135 }
136 if (iter < CIPSO_V4_TAG_MAXCNT)
137 doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
138
139 return 0;
140}
84 141
85/* 142/*
86 * NetLabel Command Handlers 143 * NetLabel Command Handlers
@@ -88,9 +145,7 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
88 145
89/** 146/**
90 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 147 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
91 * @doi: the DOI value 148 * @info: the Generic NETLINK info block
92 * @msg: the ADD message data
93 * @msg_size: the size of the ADD message buffer
94 * 149 *
95 * Description: 150 * Description:
96 * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message 151 * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
@@ -98,29 +153,28 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
98 * error. 153 * error.
99 * 154 *
100 */ 155 */
101static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) 156static int netlbl_cipsov4_add_std(struct genl_info *info)
102{ 157{
103 int ret_val = -EINVAL; 158 int ret_val = -EINVAL;
104 int msg_len = msg_size;
105 u32 num_tags;
106 u32 num_lvls;
107 u32 num_cats;
108 struct cipso_v4_doi *doi_def = NULL; 159 struct cipso_v4_doi *doi_def = NULL;
109 u32 iter; 160 struct nlattr *nla_a;
110 u32 tmp_val_a; 161 struct nlattr *nla_b;
111 u32 tmp_val_b; 162 int nla_a_rem;
163 int nla_b_rem;
112 164
113 if (msg_len < NETLBL_LEN_U32) 165 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
114 goto add_std_failure; 166 !info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
115 num_tags = netlbl_getinc_u32(&msg, &msg_len); 167 !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
116 if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) 168 return -EINVAL;
117 goto add_std_failure; 169
170 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
171 NLBL_CIPSOV4_A_MAX,
172 netlbl_cipsov4_genl_policy) != 0)
173 return -EINVAL;
118 174
119 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 175 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
120 if (doi_def == NULL) { 176 if (doi_def == NULL)
121 ret_val = -ENOMEM; 177 return -ENOMEM;
122 goto add_std_failure;
123 }
124 doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 178 doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
125 if (doi_def->map.std == NULL) { 179 if (doi_def->map.std == NULL) {
126 ret_val = -ENOMEM; 180 ret_val = -ENOMEM;
@@ -128,28 +182,32 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
128 } 182 }
129 doi_def->type = CIPSO_V4_MAP_STD; 183 doi_def->type = CIPSO_V4_MAP_STD;
130 184
131 for (iter = 0; iter < num_tags; iter++) { 185 ret_val = netlbl_cipsov4_add_common(info, doi_def);
132 if (msg_len < NETLBL_LEN_U8) 186 if (ret_val != 0)
133 goto add_std_failure;
134 doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
135 switch (doi_def->tags[iter]) {
136 case CIPSO_V4_TAG_RBITMAP:
137 break;
138 default:
139 goto add_std_failure;
140 }
141 }
142 if (iter < CIPSO_V4_TAG_MAXCNT)
143 doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
144
145 if (msg_len < 6 * NETLBL_LEN_U32)
146 goto add_std_failure; 187 goto add_std_failure;
147 188
148 num_lvls = netlbl_getinc_u32(&msg, &msg_len); 189 nla_for_each_nested(nla_a,
149 if (num_lvls == 0) 190 info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
150 goto add_std_failure; 191 nla_a_rem)
151 doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len); 192 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
152 if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS) 193 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
194 switch (nla_b->nla_type) {
195 case NLBL_CIPSOV4_A_MLSLVLLOC:
196 if (nla_get_u32(nla_b) >=
197 doi_def->map.std->lvl.local_size)
198 doi_def->map.std->lvl.local_size =
199 nla_get_u32(nla_b) + 1;
200 break;
201 case NLBL_CIPSOV4_A_MLSLVLREM:
202 if (nla_get_u32(nla_b) >=
203 doi_def->map.std->lvl.cipso_size)
204 doi_def->map.std->lvl.cipso_size =
205 nla_get_u32(nla_b) + 1;
206 break;
207 }
208 }
209 if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS ||
210 doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
153 goto add_std_failure; 211 goto add_std_failure;
154 doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 212 doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
155 sizeof(u32), 213 sizeof(u32),
@@ -158,9 +216,6 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
158 ret_val = -ENOMEM; 216 ret_val = -ENOMEM;
159 goto add_std_failure; 217 goto add_std_failure;
160 } 218 }
161 doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len);
162 if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
163 goto add_std_failure;
164 doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 219 doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
165 sizeof(u32), 220 sizeof(u32),
166 GFP_KERNEL); 221 GFP_KERNEL);
@@ -168,68 +223,101 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
168 ret_val = -ENOMEM; 223 ret_val = -ENOMEM;
169 goto add_std_failure; 224 goto add_std_failure;
170 } 225 }
226 nla_for_each_nested(nla_a,
227 info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
228 nla_a_rem)
229 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
230 struct nlattr *lvl_loc;
231 struct nlattr *lvl_rem;
232
233 if (nla_validate_nested(nla_a,
234 NLBL_CIPSOV4_A_MAX,
235 netlbl_cipsov4_genl_policy) != 0)
236 goto add_std_failure;
237
238 lvl_loc = nla_find_nested(nla_a,
239 NLBL_CIPSOV4_A_MLSLVLLOC);
240 lvl_rem = nla_find_nested(nla_a,
241 NLBL_CIPSOV4_A_MLSLVLREM);
242 if (lvl_loc == NULL || lvl_rem == NULL)
243 goto add_std_failure;
244 doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
245 nla_get_u32(lvl_rem);
246 doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
247 nla_get_u32(lvl_loc);
248 }
171 249
172 num_cats = netlbl_getinc_u32(&msg, &msg_len); 250 if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
173 doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len); 251 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
174 if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS) 252 NLBL_CIPSOV4_A_MAX,
175 goto add_std_failure; 253 netlbl_cipsov4_genl_policy) != 0)
176 doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size, 254 goto add_std_failure;
255
256 nla_for_each_nested(nla_a,
257 info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
258 nla_a_rem)
259 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
260 if (nla_validate_nested(nla_a,
261 NLBL_CIPSOV4_A_MAX,
262 netlbl_cipsov4_genl_policy) != 0)
263 goto add_std_failure;
264 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
265 switch (nla_b->nla_type) {
266 case NLBL_CIPSOV4_A_MLSCATLOC:
267 if (nla_get_u32(nla_b) >=
268 doi_def->map.std->cat.local_size)
269 doi_def->map.std->cat.local_size =
270 nla_get_u32(nla_b) + 1;
271 break;
272 case NLBL_CIPSOV4_A_MLSCATREM:
273 if (nla_get_u32(nla_b) >=
274 doi_def->map.std->cat.cipso_size)
275 doi_def->map.std->cat.cipso_size =
276 nla_get_u32(nla_b) + 1;
277 break;
278 }
279 }
280 if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS ||
281 doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
282 goto add_std_failure;
283 doi_def->map.std->cat.local = kcalloc(
284 doi_def->map.std->cat.local_size,
177 sizeof(u32), 285 sizeof(u32),
178 GFP_KERNEL); 286 GFP_KERNEL);
179 if (doi_def->map.std->cat.local == NULL) { 287 if (doi_def->map.std->cat.local == NULL) {
180 ret_val = -ENOMEM; 288 ret_val = -ENOMEM;
181 goto add_std_failure; 289 goto add_std_failure;
182 } 290 }
183 doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len); 291 doi_def->map.std->cat.cipso = kcalloc(
184 if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) 292 doi_def->map.std->cat.cipso_size,
185 goto add_std_failure;
186 doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size,
187 sizeof(u32), 293 sizeof(u32),
188 GFP_KERNEL); 294 GFP_KERNEL);
189 if (doi_def->map.std->cat.cipso == NULL) { 295 if (doi_def->map.std->cat.cipso == NULL) {
190 ret_val = -ENOMEM; 296 ret_val = -ENOMEM;
191 goto add_std_failure;
192 }
193
194 if (msg_len <
195 num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) +
196 num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16))
197 goto add_std_failure;
198
199 for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
200 doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
201 for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
202 doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
203 for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
204 doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
205 for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
206 doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
207
208 for (iter = 0; iter < num_lvls; iter++) {
209 tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
210 tmp_val_b = netlbl_getinc_u8(&msg, &msg_len);
211
212 if (tmp_val_a >= doi_def->map.std->lvl.local_size ||
213 tmp_val_b >= doi_def->map.std->lvl.cipso_size)
214 goto add_std_failure;
215
216 doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a;
217 doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b;
218 }
219
220 for (iter = 0; iter < num_cats; iter++) {
221 tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
222 tmp_val_b = netlbl_getinc_u16(&msg, &msg_len);
223
224 if (tmp_val_a >= doi_def->map.std->cat.local_size ||
225 tmp_val_b >= doi_def->map.std->cat.cipso_size)
226 goto add_std_failure; 297 goto add_std_failure;
227 298 }
228 doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a; 299 nla_for_each_nested(nla_a,
229 doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b; 300 info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
301 nla_a_rem)
302 if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
303 struct nlattr *cat_loc;
304 struct nlattr *cat_rem;
305
306 cat_loc = nla_find_nested(nla_a,
307 NLBL_CIPSOV4_A_MLSCATLOC);
308 cat_rem = nla_find_nested(nla_a,
309 NLBL_CIPSOV4_A_MLSCATREM);
310 if (cat_loc == NULL || cat_rem == NULL)
311 goto add_std_failure;
312 doi_def->map.std->cat.local[
313 nla_get_u32(cat_loc)] =
314 nla_get_u32(cat_rem);
315 doi_def->map.std->cat.cipso[
316 nla_get_u32(cat_rem)] =
317 nla_get_u32(cat_loc);
318 }
230 } 319 }
231 320
232 doi_def->doi = doi;
233 ret_val = cipso_v4_doi_add(doi_def); 321 ret_val = cipso_v4_doi_add(doi_def);
234 if (ret_val != 0) 322 if (ret_val != 0)
235 goto add_std_failure; 323 goto add_std_failure;
@@ -243,9 +331,7 @@ add_std_failure:
243 331
244/** 332/**
245 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 333 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
246 * @doi: the DOI value 334 * @info: the Generic NETLINK info block
247 * @msg: the ADD message data
248 * @msg_size: the size of the ADD message buffer
249 * 335 *
250 * Description: 336 * Description:
251 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 337 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
@@ -253,52 +339,31 @@ add_std_failure:
253 * error. 339 * error.
254 * 340 *
255 */ 341 */
256static int netlbl_cipsov4_add_pass(u32 doi, 342static int netlbl_cipsov4_add_pass(struct genl_info *info)
257 struct nlattr *msg,
258 size_t msg_size)
259{ 343{
260 int ret_val = -EINVAL; 344 int ret_val;
261 int msg_len = msg_size;
262 u32 num_tags;
263 struct cipso_v4_doi *doi_def = NULL; 345 struct cipso_v4_doi *doi_def = NULL;
264 u32 iter;
265 346
266 if (msg_len < NETLBL_LEN_U32) 347 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
267 goto add_pass_failure; 348 !info->attrs[NLBL_CIPSOV4_A_TAGLST])
268 num_tags = netlbl_getinc_u32(&msg, &msg_len); 349 return -EINVAL;
269 if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
270 goto add_pass_failure;
271 350
272 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 351 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
273 if (doi_def == NULL) { 352 if (doi_def == NULL)
274 ret_val = -ENOMEM; 353 return -ENOMEM;
275 goto add_pass_failure;
276 }
277 doi_def->type = CIPSO_V4_MAP_PASS; 354 doi_def->type = CIPSO_V4_MAP_PASS;
278 355
279 for (iter = 0; iter < num_tags; iter++) { 356 ret_val = netlbl_cipsov4_add_common(info, doi_def);
280 if (msg_len < NETLBL_LEN_U8) 357 if (ret_val != 0)
281 goto add_pass_failure; 358 goto add_pass_failure;
282 doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
283 switch (doi_def->tags[iter]) {
284 case CIPSO_V4_TAG_RBITMAP:
285 break;
286 default:
287 goto add_pass_failure;
288 }
289 }
290 if (iter < CIPSO_V4_TAG_MAXCNT)
291 doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
292 359
293 doi_def->doi = doi;
294 ret_val = cipso_v4_doi_add(doi_def); 360 ret_val = cipso_v4_doi_add(doi_def);
295 if (ret_val != 0) 361 if (ret_val != 0)
296 goto add_pass_failure; 362 goto add_pass_failure;
297 return 0; 363 return 0;
298 364
299add_pass_failure: 365add_pass_failure:
300 if (doi_def) 366 netlbl_cipsov4_doi_free(&doi_def->rcu);
301 netlbl_cipsov4_doi_free(&doi_def->rcu);
302 return ret_val; 367 return ret_val;
303} 368}
304 369
@@ -316,34 +381,21 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
316 381
317{ 382{
318 int ret_val = -EINVAL; 383 int ret_val = -EINVAL;
319 u32 doi;
320 u32 map_type; 384 u32 map_type;
321 int msg_len = netlbl_netlink_payload_len(skb);
322 struct nlattr *msg = netlbl_netlink_payload_data(skb);
323
324 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
325 if (ret_val != 0)
326 goto add_return;
327 385
328 if (msg_len < 2 * NETLBL_LEN_U32) 386 if (!info->attrs[NLBL_CIPSOV4_A_MTYPE])
329 goto add_return; 387 return -EINVAL;
330 388
331 doi = netlbl_getinc_u32(&msg, &msg_len); 389 map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
332 map_type = netlbl_getinc_u32(&msg, &msg_len);
333 switch (map_type) { 390 switch (map_type) {
334 case CIPSO_V4_MAP_STD: 391 case CIPSO_V4_MAP_STD:
335 ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len); 392 ret_val = netlbl_cipsov4_add_std(info);
336 break; 393 break;
337 case CIPSO_V4_MAP_PASS: 394 case CIPSO_V4_MAP_PASS:
338 ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len); 395 ret_val = netlbl_cipsov4_add_pass(info);
339 break; 396 break;
340 } 397 }
341 398
342add_return:
343 netlbl_netlink_send_ack(info,
344 netlbl_cipsov4_gnl_family.id,
345 NLBL_CIPSOV4_C_ACK,
346 -ret_val);
347 return ret_val; 399 return ret_val;
348} 400}
349 401
@@ -353,84 +405,239 @@ add_return:
353 * @info: the Generic NETLINK info block 405 * @info: the Generic NETLINK info block
354 * 406 *
355 * Description: 407 * Description:
356 * Process a user generated LIST message and respond accordingly. Returns 408 * Process a user generated LIST message and respond accordingly. While the
357 * zero on success and negative values on error. 409 * response message generated by the kernel is straightforward, determining
410 * before hand the size of the buffer to allocate is not (we have to generate
411 * the message to know the size). In order to keep this function sane what we
412 * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
413 * that size, if we fail then we restart with a larger buffer and try again.
414 * We continue in this manner until we hit a limit of failed attempts then we
415 * give up and just send an error message. Returns zero on success and
416 * negative values on error.
358 * 417 *
359 */ 418 */
360static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) 419static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
361{ 420{
362 int ret_val = -EINVAL; 421 int ret_val;
422 struct sk_buff *ans_skb = NULL;
423 u32 nlsze_mult = 1;
424 void *data;
363 u32 doi; 425 u32 doi;
364 struct nlattr *msg = netlbl_netlink_payload_data(skb); 426 struct nlattr *nla_a;
365 struct sk_buff *ans_skb; 427 struct nlattr *nla_b;
428 struct cipso_v4_doi *doi_def;
429 u32 iter;
366 430
367 if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) 431 if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
432 ret_val = -EINVAL;
368 goto list_failure; 433 goto list_failure;
434 }
369 435
370 doi = nla_get_u32(msg); 436list_start:
371 ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN)); 437 ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
372 if (ans_skb == NULL) { 438 if (ans_skb == NULL) {
373 ret_val = -ENOMEM; 439 ret_val = -ENOMEM;
374 goto list_failure; 440 goto list_failure;
375 } 441 }
376 netlbl_netlink_hdr_push(ans_skb, 442 data = netlbl_netlink_hdr_put(ans_skb,
377 info->snd_pid, 443 info->snd_pid,
378 0, 444 info->snd_seq,
379 netlbl_cipsov4_gnl_family.id, 445 netlbl_cipsov4_gnl_family.id,
380 NLBL_CIPSOV4_C_LIST); 446 0,
447 NLBL_CIPSOV4_C_LIST);
448 if (data == NULL) {
449 ret_val = -ENOMEM;
450 goto list_failure;
451 }
452
453 doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
454
455 rcu_read_lock();
456 doi_def = cipso_v4_doi_getdef(doi);
457 if (doi_def == NULL) {
458 ret_val = -EINVAL;
459 goto list_failure;
460 }
461
462 ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
463 if (ret_val != 0)
464 goto list_failure_lock;
465
466 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
467 if (nla_a == NULL) {
468 ret_val = -ENOMEM;
469 goto list_failure_lock;
470 }
471 for (iter = 0;
472 iter < CIPSO_V4_TAG_MAXCNT &&
473 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
474 iter++) {
475 ret_val = nla_put_u8(ans_skb,
476 NLBL_CIPSOV4_A_TAG,
477 doi_def->tags[iter]);
478 if (ret_val != 0)
479 goto list_failure_lock;
480 }
481 nla_nest_end(ans_skb, nla_a);
482
483 switch (doi_def->type) {
484 case CIPSO_V4_MAP_STD:
485 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
486 if (nla_a == NULL) {
487 ret_val = -ENOMEM;
488 goto list_failure_lock;
489 }
490 for (iter = 0;
491 iter < doi_def->map.std->lvl.local_size;
492 iter++) {
493 if (doi_def->map.std->lvl.local[iter] ==
494 CIPSO_V4_INV_LVL)
495 continue;
496
497 nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
498 if (nla_b == NULL) {
499 ret_val = -ENOMEM;
500 goto list_retry;
501 }
502 ret_val = nla_put_u32(ans_skb,
503 NLBL_CIPSOV4_A_MLSLVLLOC,
504 iter);
505 if (ret_val != 0)
506 goto list_retry;
507 ret_val = nla_put_u32(ans_skb,
508 NLBL_CIPSOV4_A_MLSLVLREM,
509 doi_def->map.std->lvl.local[iter]);
510 if (ret_val != 0)
511 goto list_retry;
512 nla_nest_end(ans_skb, nla_b);
513 }
514 nla_nest_end(ans_skb, nla_a);
515
516 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
517 if (nla_a == NULL) {
518 ret_val = -ENOMEM;
519 goto list_retry;
520 }
521 for (iter = 0;
522 iter < doi_def->map.std->cat.local_size;
523 iter++) {
524 if (doi_def->map.std->cat.local[iter] ==
525 CIPSO_V4_INV_CAT)
526 continue;
527
528 nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
529 if (nla_b == NULL) {
530 ret_val = -ENOMEM;
531 goto list_retry;
532 }
533 ret_val = nla_put_u32(ans_skb,
534 NLBL_CIPSOV4_A_MLSCATLOC,
535 iter);
536 if (ret_val != 0)
537 goto list_retry;
538 ret_val = nla_put_u32(ans_skb,
539 NLBL_CIPSOV4_A_MLSCATREM,
540 doi_def->map.std->cat.local[iter]);
541 if (ret_val != 0)
542 goto list_retry;
543 nla_nest_end(ans_skb, nla_b);
544 }
545 nla_nest_end(ans_skb, nla_a);
546
547 break;
548 }
549 rcu_read_unlock();
381 550
382 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 551 genlmsg_end(ans_skb, data);
552
553 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
383 if (ret_val != 0) 554 if (ret_val != 0)
384 goto list_failure; 555 goto list_failure;
385 556
386 return 0; 557 return 0;
387 558
559list_retry:
560 /* XXX - this limit is a guesstimate */
561 if (nlsze_mult < 4) {
562 rcu_read_unlock();
563 kfree_skb(ans_skb);
564 nlsze_mult++;
565 goto list_start;
566 }
567list_failure_lock:
568 rcu_read_unlock();
388list_failure: 569list_failure:
389 netlbl_netlink_send_ack(info, 570 kfree_skb(ans_skb);
390 netlbl_cipsov4_gnl_family.id, 571 return ret_val;
391 NLBL_CIPSOV4_C_ACK, 572}
392 -ret_val); 573
574/**
575 * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
576 * @doi_def: the CIPSOv4 DOI definition
577 * @arg: the netlbl_cipsov4_doiwalk_arg structure
578 *
579 * Description:
580 * This function is designed to be used as a callback to the
581 * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
582 * message. Returns the size of the message on success, negative values on
583 * failure.
584 *
585 */
586static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
587{
588 int ret_val = -ENOMEM;
589 struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
590 void *data;
591
592 data = netlbl_netlink_hdr_put(cb_arg->skb,
593 NETLINK_CB(cb_arg->nl_cb->skb).pid,
594 cb_arg->seq,
595 netlbl_cipsov4_gnl_family.id,
596 NLM_F_MULTI,
597 NLBL_CIPSOV4_C_LISTALL);
598 if (data == NULL)
599 goto listall_cb_failure;
600
601 ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
602 if (ret_val != 0)
603 goto listall_cb_failure;
604 ret_val = nla_put_u32(cb_arg->skb,
605 NLBL_CIPSOV4_A_MTYPE,
606 doi_def->type);
607 if (ret_val != 0)
608 goto listall_cb_failure;
609
610 return genlmsg_end(cb_arg->skb, data);
611
612listall_cb_failure:
613 genlmsg_cancel(cb_arg->skb, data);
393 return ret_val; 614 return ret_val;
394} 615}
395 616
396/** 617/**
397 * netlbl_cipsov4_listall - Handle a LISTALL message 618 * netlbl_cipsov4_listall - Handle a LISTALL message
398 * @skb: the NETLINK buffer 619 * @skb: the NETLINK buffer
399 * @info: the Generic NETLINK info block 620 * @cb: the NETLINK callback
400 * 621 *
401 * Description: 622 * Description:
402 * Process a user generated LISTALL message and respond accordingly. Returns 623 * Process a user generated LISTALL message and respond accordingly. Returns
403 * zero on success and negative values on error. 624 * zero on success and negative values on error.
404 * 625 *
405 */ 626 */
406static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info) 627static int netlbl_cipsov4_listall(struct sk_buff *skb,
628 struct netlink_callback *cb)
407{ 629{
408 int ret_val = -EINVAL; 630 struct netlbl_cipsov4_doiwalk_arg cb_arg;
409 struct sk_buff *ans_skb; 631 int doi_skip = cb->args[0];
410 632
411 ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN)); 633 cb_arg.nl_cb = cb;
412 if (ans_skb == NULL) { 634 cb_arg.skb = skb;
413 ret_val = -ENOMEM; 635 cb_arg.seq = cb->nlh->nlmsg_seq;
414 goto listall_failure;
415 }
416 netlbl_netlink_hdr_push(ans_skb,
417 info->snd_pid,
418 0,
419 netlbl_cipsov4_gnl_family.id,
420 NLBL_CIPSOV4_C_LISTALL);
421 636
422 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 637 cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
423 if (ret_val != 0)
424 goto listall_failure;
425
426 return 0;
427 638
428listall_failure: 639 cb->args[0] = doi_skip;
429 netlbl_netlink_send_ack(info, 640 return skb->len;
430 netlbl_cipsov4_gnl_family.id,
431 NLBL_CIPSOV4_C_ACK,
432 -ret_val);
433 return ret_val;
434} 641}
435 642
436/** 643/**
@@ -445,27 +652,14 @@ listall_failure:
445 */ 652 */
446static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 653static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
447{ 654{
448 int ret_val; 655 int ret_val = -EINVAL;
449 u32 doi; 656 u32 doi;
450 struct nlattr *msg = netlbl_netlink_payload_data(skb);
451 657
452 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 658 if (info->attrs[NLBL_CIPSOV4_A_DOI]) {
453 if (ret_val != 0) 659 doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
454 goto remove_return; 660 ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
455
456 if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) {
457 ret_val = -EINVAL;
458 goto remove_return;
459 } 661 }
460 662
461 doi = nla_get_u32(msg);
462 ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
463
464remove_return:
465 netlbl_netlink_send_ack(info,
466 netlbl_cipsov4_gnl_family.id,
467 NLBL_CIPSOV4_C_ACK,
468 -ret_val);
469 return ret_val; 663 return ret_val;
470} 664}
471 665
@@ -475,14 +669,16 @@ remove_return:
475 669
476static struct genl_ops netlbl_cipsov4_genl_c_add = { 670static struct genl_ops netlbl_cipsov4_genl_c_add = {
477 .cmd = NLBL_CIPSOV4_C_ADD, 671 .cmd = NLBL_CIPSOV4_C_ADD,
478 .flags = 0, 672 .flags = GENL_ADMIN_PERM,
673 .policy = netlbl_cipsov4_genl_policy,
479 .doit = netlbl_cipsov4_add, 674 .doit = netlbl_cipsov4_add,
480 .dumpit = NULL, 675 .dumpit = NULL,
481}; 676};
482 677
483static struct genl_ops netlbl_cipsov4_genl_c_remove = { 678static struct genl_ops netlbl_cipsov4_genl_c_remove = {
484 .cmd = NLBL_CIPSOV4_C_REMOVE, 679 .cmd = NLBL_CIPSOV4_C_REMOVE,
485 .flags = 0, 680 .flags = GENL_ADMIN_PERM,
681 .policy = netlbl_cipsov4_genl_policy,
486 .doit = netlbl_cipsov4_remove, 682 .doit = netlbl_cipsov4_remove,
487 .dumpit = NULL, 683 .dumpit = NULL,
488}; 684};
@@ -490,6 +686,7 @@ static struct genl_ops netlbl_cipsov4_genl_c_remove = {
490static struct genl_ops netlbl_cipsov4_genl_c_list = { 686static struct genl_ops netlbl_cipsov4_genl_c_list = {
491 .cmd = NLBL_CIPSOV4_C_LIST, 687 .cmd = NLBL_CIPSOV4_C_LIST,
492 .flags = 0, 688 .flags = 0,
689 .policy = netlbl_cipsov4_genl_policy,
493 .doit = netlbl_cipsov4_list, 690 .doit = netlbl_cipsov4_list,
494 .dumpit = NULL, 691 .dumpit = NULL,
495}; 692};
@@ -497,8 +694,9 @@ static struct genl_ops netlbl_cipsov4_genl_c_list = {
497static struct genl_ops netlbl_cipsov4_genl_c_listall = { 694static struct genl_ops netlbl_cipsov4_genl_c_listall = {
498 .cmd = NLBL_CIPSOV4_C_LISTALL, 695 .cmd = NLBL_CIPSOV4_C_LISTALL,
499 .flags = 0, 696 .flags = 0,
500 .doit = netlbl_cipsov4_listall, 697 .policy = netlbl_cipsov4_genl_policy,
501 .dumpit = NULL, 698 .doit = NULL,
699 .dumpit = netlbl_cipsov4_listall,
502}; 700};
503 701
504/* 702/*
diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h
index 4c6ff4b93004..f03cf9b78286 100644
--- a/net/netlabel/netlabel_cipso_v4.h
+++ b/net/netlabel/netlabel_cipso_v4.h
@@ -34,175 +34,71 @@
34#include <net/netlabel.h> 34#include <net/netlabel.h>
35 35
36/* 36/*
37 * The following NetLabel payloads are supported by the CIPSO subsystem, all 37 * The following NetLabel payloads are supported by the CIPSO subsystem.
38 * of which are preceeded by the nlmsghdr struct.
39 * 38 *
40 * o ACK: 39 * o ADD:
41 * Sent by the kernel in response to an applications message, applications 40 * Sent by an application to add a new DOI mapping table.
42 * should never send this message.
43 * 41 *
44 * +----------------------+-----------------------+ 42 * Required attributes:
45 * | seq number (32 bits) | return code (32 bits) |
46 * +----------------------+-----------------------+
47 * 43 *
48 * seq number: the sequence number of the original message, taken from the 44 * NLBL_CIPSOV4_A_DOI
49 * nlmsghdr structure 45 * NLBL_CIPSOV4_A_MTYPE
50 * return code: return value, based on errno values 46 * NLBL_CIPSOV4_A_TAGLST
51 * 47 *
52 * o ADD: 48 * If using CIPSO_V4_MAP_STD the following attributes are required:
53 * Sent by an application to add a new DOI mapping table, after completion 49 *
54 * of the task the kernel should ACK this message. 50 * NLBL_CIPSOV4_A_MLSLVLLST
55 * 51 * NLBL_CIPSOV4_A_MLSCATLST
56 * +---------------+--------------------+---------------------+ 52 *
57 * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ... 53 * If using CIPSO_V4_MAP_PASS no additional attributes are required.
58 * +---------------+--------------------+---------------------+
59 *
60 * +-----------------+
61 * | tag #X (8 bits) | ... repeated
62 * +-----------------+
63 *
64 * +-------------- ---- --- -- -
65 * | mapping data
66 * +-------------- ---- --- -- -
67 *
68 * DOI: the DOI value
69 * map type: the mapping table type (defined in the cipso_ipv4.h header
70 * as CIPSO_V4_MAP_*)
71 * tag count: the number of tags, must be greater than zero
72 * tag: the CIPSO tag for the DOI, tags listed first are given
73 * higher priorirty when sending packets
74 * mapping data: specific to the map type (see below)
75 *
76 * CIPSO_V4_MAP_STD
77 *
78 * +------------------+-----------------------+----------------------+
79 * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ...
80 * +------------------+-----------------------+----------------------+
81 *
82 * +----------------------+---------------------+---------------------+
83 * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ...
84 * +----------------------+---------------------+---------------------+
85 *
86 * +--------------------------+-------------------------+
87 * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
88 * +--------------------------+-------------------------+
89 *
90 * +-----------------------------+-----------------------------+
91 * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
92 * +-----------------------------+-----------------------------+
93 *
94 * levels: the number of level mappings
95 * max l level: the highest local level
96 * max r level: the highest remote/CIPSO level
97 * categories: the number of category mappings
98 * max l cat: the highest local category
99 * max r cat: the highest remote/CIPSO category
100 * local level: the local part of a level mapping
101 * CIPSO level: the remote/CIPSO part of a level mapping
102 * local category: the local part of a category mapping
103 * CIPSO category: the remote/CIPSO part of a category mapping
104 *
105 * CIPSO_V4_MAP_PASS
106 *
107 * No mapping data is needed for this map type.
108 * 54 *
109 * o REMOVE: 55 * o REMOVE:
110 * Sent by an application to remove a specific DOI mapping table from the 56 * Sent by an application to remove a specific DOI mapping table from the
111 * CIPSO V4 system. The kernel should ACK this message. 57 * CIPSO V4 system.
112 * 58 *
113 * +---------------+ 59 * Required attributes:
114 * | DOI (32 bits) |
115 * +---------------+
116 * 60 *
117 * DOI: the DOI value 61 * NLBL_CIPSOV4_A_DOI
118 * 62 *
119 * o LIST: 63 * o LIST:
120 * Sent by an application to list the details of a DOI definition. The 64 * Sent by an application to list the details of a DOI definition. On
121 * kernel should send an ACK on error or a response as indicated below. The 65 * success the kernel should send a response using the following format.
122 * application generated message format is shown below.
123 * 66 *
124 * +---------------+ 67 * Required attributes:
125 * | DOI (32 bits) |
126 * +---------------+
127 * 68 *
128 * DOI: the DOI value 69 * NLBL_CIPSOV4_A_DOI
129 * 70 *
130 * The valid response message format depends on the type of the DOI mapping, 71 * The valid response message format depends on the type of the DOI mapping,
131 * the known formats are shown below. 72 * the defined formats are shown below.
132 *
133 * +--------------------+
134 * | map type (32 bits) | ...
135 * +--------------------+
136 *
137 * map type: the DOI mapping table type (defined in the cipso_ipv4.h
138 * header as CIPSO_V4_MAP_*)
139 *
140 * (map type == CIPSO_V4_MAP_STD)
141 *
142 * +----------------+------------------+----------------------+
143 * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ...
144 * +----------------+------------------+----------------------+
145 * 73 *
146 * +-----------------+ 74 * Required attributes:
147 * | tag #X (8 bits) | ... repeated
148 * +-----------------+
149 * 75 *
150 * +--------------------------+-------------------------+ 76 * NLBL_CIPSOV4_A_MTYPE
151 * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated 77 * NLBL_CIPSOV4_A_TAGLST
152 * +--------------------------+-------------------------+
153 * 78 *
154 * +-----------------------------+-----------------------------+ 79 * If using CIPSO_V4_MAP_STD the following attributes are required:
155 * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
156 * +-----------------------------+-----------------------------+
157 * 80 *
158 * tags: the number of CIPSO tag types 81 * NLBL_CIPSOV4_A_MLSLVLLST
159 * levels: the number of level mappings 82 * NLBL_CIPSOV4_A_MLSCATLST
160 * categories: the number of category mappings
161 * tag: the tag number, tags listed first are given higher
162 * priority when sending packets
163 * local level: the local part of a level mapping
164 * CIPSO level: the remote/CIPSO part of a level mapping
165 * local category: the local part of a category mapping
166 * CIPSO category: the remote/CIPSO part of a category mapping
167 * 83 *
168 * (map type == CIPSO_V4_MAP_PASS) 84 * If using CIPSO_V4_MAP_PASS no additional attributes are required.
169 *
170 * +----------------+
171 * | tags (32 bits) | ...
172 * +----------------+
173 *
174 * +-----------------+
175 * | tag #X (8 bits) | ... repeated
176 * +-----------------+
177 *
178 * tags: the number of CIPSO tag types
179 * tag: the tag number, tags listed first are given higher
180 * priority when sending packets
181 * 85 *
182 * o LISTALL: 86 * o LISTALL:
183 * This message is sent by an application to list the valid DOIs on the 87 * This message is sent by an application to list the valid DOIs on the
184 * system. There is no payload and the kernel should respond with an ACK 88 * system. When sent by an application there is no payload and the
185 * or the following message. 89 * NLM_F_DUMP flag should be set. The kernel should respond with a series of
186 * 90 * the following messages.
187 * +---------------------+------------------+-----------------------+
188 * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) |
189 * +---------------------+------------------+-----------------------+
190 * 91 *
191 * +-----------------------+ 92 * Required attributes:
192 * | map type #X (32 bits) | ...
193 * +-----------------------+
194 * 93 *
195 * DOI count: the number of DOIs 94 * NLBL_CIPSOV4_A_DOI
196 * DOI: the DOI value 95 * NLBL_CIPSOV4_A_MTYPE
197 * map type: the DOI mapping table type (defined in the cipso_ipv4.h
198 * header as CIPSO_V4_MAP_*)
199 * 96 *
200 */ 97 */
201 98
202/* NetLabel CIPSOv4 commands */ 99/* NetLabel CIPSOv4 commands */
203enum { 100enum {
204 NLBL_CIPSOV4_C_UNSPEC, 101 NLBL_CIPSOV4_C_UNSPEC,
205 NLBL_CIPSOV4_C_ACK,
206 NLBL_CIPSOV4_C_ADD, 102 NLBL_CIPSOV4_C_ADD,
207 NLBL_CIPSOV4_C_REMOVE, 103 NLBL_CIPSOV4_C_REMOVE,
208 NLBL_CIPSOV4_C_LIST, 104 NLBL_CIPSOV4_C_LIST,
@@ -211,6 +107,59 @@ enum {
211}; 107};
212#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1) 108#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1)
213 109
110/* NetLabel CIPSOv4 attributes */
111enum {
112 NLBL_CIPSOV4_A_UNSPEC,
113 NLBL_CIPSOV4_A_DOI,
114 /* (NLA_U32)
115 * the DOI value */
116 NLBL_CIPSOV4_A_MTYPE,
117 /* (NLA_U32)
118 * the mapping table type (defined in the cipso_ipv4.h header as
119 * CIPSO_V4_MAP_*) */
120 NLBL_CIPSOV4_A_TAG,
121 /* (NLA_U8)
122 * a CIPSO tag type, meant to be used within a NLBL_CIPSOV4_A_TAGLST
123 * attribute */
124 NLBL_CIPSOV4_A_TAGLST,
125 /* (NLA_NESTED)
126 * the CIPSO tag list for the DOI, there must be at least one
127 * NLBL_CIPSOV4_A_TAG attribute, tags listed first are given higher
128 * priorirty when sending packets */
129 NLBL_CIPSOV4_A_MLSLVLLOC,
130 /* (NLA_U32)
131 * the local MLS sensitivity level */
132 NLBL_CIPSOV4_A_MLSLVLREM,
133 /* (NLA_U32)
134 * the remote MLS sensitivity level */
135 NLBL_CIPSOV4_A_MLSLVL,
136 /* (NLA_NESTED)
137 * a MLS sensitivity level mapping, must contain only one attribute of
138 * each of the following types: NLBL_CIPSOV4_A_MLSLVLLOC and
139 * NLBL_CIPSOV4_A_MLSLVLREM */
140 NLBL_CIPSOV4_A_MLSLVLLST,
141 /* (NLA_NESTED)
142 * the CIPSO level mappings, there must be at least one
143 * NLBL_CIPSOV4_A_MLSLVL attribute */
144 NLBL_CIPSOV4_A_MLSCATLOC,
145 /* (NLA_U32)
146 * the local MLS category */
147 NLBL_CIPSOV4_A_MLSCATREM,
148 /* (NLA_U32)
149 * the remote MLS category */
150 NLBL_CIPSOV4_A_MLSCAT,
151 /* (NLA_NESTED)
152 * a MLS category mapping, must contain only one attribute of each of
153 * the following types: NLBL_CIPSOV4_A_MLSCATLOC and
154 * NLBL_CIPSOV4_A_MLSCATREM */
155 NLBL_CIPSOV4_A_MLSCATLST,
156 /* (NLA_NESTED)
157 * the CIPSO category mappings, there must be at least one
158 * NLBL_CIPSOV4_A_MLSCAT attribute */
159 __NLBL_CIPSOV4_A_MAX,
160};
161#define NLBL_CIPSOV4_A_MAX (__NLBL_CIPSOV4_A_MAX - 1)
162
214/* NetLabel protocol functions */ 163/* NetLabel protocol functions */
215int netlbl_cipsov4_genl_init(void); 164int netlbl_cipsov4_genl_init(void);
216 165
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 85bc11a1fc46..8626c9f678eb 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -42,15 +42,29 @@
42#include "netlabel_user.h" 42#include "netlabel_user.h"
43#include "netlabel_mgmt.h" 43#include "netlabel_mgmt.h"
44 44
45/* Argument struct for netlbl_domhsh_walk() */
46struct netlbl_domhsh_walk_arg {
47 struct netlink_callback *nl_cb;
48 struct sk_buff *skb;
49 u32 seq;
50};
51
45/* NetLabel Generic NETLINK CIPSOv4 family */ 52/* NetLabel Generic NETLINK CIPSOv4 family */
46static struct genl_family netlbl_mgmt_gnl_family = { 53static struct genl_family netlbl_mgmt_gnl_family = {
47 .id = GENL_ID_GENERATE, 54 .id = GENL_ID_GENERATE,
48 .hdrsize = 0, 55 .hdrsize = 0,
49 .name = NETLBL_NLTYPE_MGMT_NAME, 56 .name = NETLBL_NLTYPE_MGMT_NAME,
50 .version = NETLBL_PROTO_VERSION, 57 .version = NETLBL_PROTO_VERSION,
51 .maxattr = 0, 58 .maxattr = NLBL_MGMT_A_MAX,
52}; 59};
53 60
61/* NetLabel Netlink attribute policy */
62static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
63 [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
64 [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
65 [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
66 [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
67};
54 68
55/* 69/*
56 * NetLabel Command Handlers 70 * NetLabel Command Handlers
@@ -70,97 +84,62 @@ static struct genl_family netlbl_mgmt_gnl_family = {
70static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) 84static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
71{ 85{
72 int ret_val = -EINVAL; 86 int ret_val = -EINVAL;
73 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
74 int msg_len = netlbl_netlink_payload_len(skb);
75 u32 count;
76 struct netlbl_dom_map *entry = NULL; 87 struct netlbl_dom_map *entry = NULL;
77 u32 iter; 88 size_t tmp_size;
78 u32 tmp_val; 89 u32 tmp_val;
79 int tmp_size;
80 90
81 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 91 if (!info->attrs[NLBL_MGMT_A_DOMAIN] ||
82 if (ret_val != 0) 92 !info->attrs[NLBL_MGMT_A_PROTOCOL])
83 goto add_failure; 93 goto add_failure;
84 94
85 if (msg_len < NETLBL_LEN_U32) 95 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
96 if (entry == NULL) {
97 ret_val = -ENOMEM;
98 goto add_failure;
99 }
100 tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
101 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
102 if (entry->domain == NULL) {
103 ret_val = -ENOMEM;
86 goto add_failure; 104 goto add_failure;
87 count = netlbl_getinc_u32(&msg_ptr, &msg_len); 105 }
106 entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
107 nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
88 108
89 for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) { 109 switch (entry->type) {
90 if (msg_len <= 0) { 110 case NETLBL_NLTYPE_UNLABELED:
91 ret_val = -EINVAL; 111 ret_val = netlbl_domhsh_add(entry);
92 goto add_failure; 112 break;
93 } 113 case NETLBL_NLTYPE_CIPSOV4:
94 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 114 if (!info->attrs[NLBL_MGMT_A_CV4DOI])
95 if (entry == NULL) {
96 ret_val = -ENOMEM;
97 goto add_failure;
98 }
99 tmp_size = nla_len(msg_ptr);
100 if (tmp_size <= 0 || tmp_size > msg_len) {
101 ret_val = -EINVAL;
102 goto add_failure;
103 }
104 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
105 if (entry->domain == NULL) {
106 ret_val = -ENOMEM;
107 goto add_failure; 115 goto add_failure;
108 }
109 nla_strlcpy(entry->domain, msg_ptr, tmp_size);
110 entry->domain[tmp_size - 1] = '\0';
111 msg_ptr = nla_next(msg_ptr, &msg_len);
112 116
113 if (msg_len < NETLBL_LEN_U32) { 117 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
114 ret_val = -EINVAL; 118 /* We should be holding a rcu_read_lock() here while we hold
115 goto add_failure; 119 * the result but since the entry will always be deleted when
116 } 120 * the CIPSO DOI is deleted we aren't going to keep the
117 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); 121 * lock. */
118 entry->type = tmp_val; 122 rcu_read_lock();
119 switch (tmp_val) { 123 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
120 case NETLBL_NLTYPE_UNLABELED: 124 if (entry->type_def.cipsov4 == NULL) {
121 ret_val = netlbl_domhsh_add(entry);
122 break;
123 case NETLBL_NLTYPE_CIPSOV4:
124 if (msg_len < NETLBL_LEN_U32) {
125 ret_val = -EINVAL;
126 goto add_failure;
127 }
128 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
129 /* We should be holding a rcu_read_lock() here
130 * while we hold the result but since the entry
131 * will always be deleted when the CIPSO DOI
132 * is deleted we aren't going to keep the lock. */
133 rcu_read_lock();
134 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
135 if (entry->type_def.cipsov4 == NULL) {
136 rcu_read_unlock();
137 ret_val = -EINVAL;
138 goto add_failure;
139 }
140 ret_val = netlbl_domhsh_add(entry);
141 rcu_read_unlock(); 125 rcu_read_unlock();
142 break;
143 default:
144 ret_val = -EINVAL;
145 }
146 if (ret_val != 0)
147 goto add_failure; 126 goto add_failure;
127 }
128 ret_val = netlbl_domhsh_add(entry);
129 rcu_read_unlock();
130 break;
131 default:
132 goto add_failure;
148 } 133 }
134 if (ret_val != 0)
135 goto add_failure;
149 136
150 netlbl_netlink_send_ack(info,
151 netlbl_mgmt_gnl_family.id,
152 NLBL_MGMT_C_ACK,
153 NETLBL_E_OK);
154 return 0; 137 return 0;
155 138
156add_failure: 139add_failure:
157 if (entry) 140 if (entry)
158 kfree(entry->domain); 141 kfree(entry->domain);
159 kfree(entry); 142 kfree(entry);
160 netlbl_netlink_send_ack(info,
161 netlbl_mgmt_gnl_family.id,
162 NLBL_MGMT_C_ACK,
163 -ret_val);
164 return ret_val; 143 return ret_val;
165} 144}
166 145
@@ -176,87 +155,98 @@ add_failure:
176 */ 155 */
177static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) 156static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
178{ 157{
179 int ret_val = -EINVAL; 158 char *domain;
180 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
181 int msg_len = netlbl_netlink_payload_len(skb);
182 u32 count;
183 u32 iter;
184 int tmp_size;
185 unsigned char *domain;
186
187 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
188 if (ret_val != 0)
189 goto remove_return;
190 159
191 if (msg_len < NETLBL_LEN_U32) 160 if (!info->attrs[NLBL_MGMT_A_DOMAIN])
192 goto remove_return; 161 return -EINVAL;
193 count = netlbl_getinc_u32(&msg_ptr, &msg_len);
194 162
195 for (iter = 0; iter < count && msg_len > 0; iter++) { 163 domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
196 if (msg_len <= 0) { 164 return netlbl_domhsh_remove(domain);
197 ret_val = -EINVAL; 165}
198 goto remove_return; 166
199 } 167/**
200 tmp_size = nla_len(msg_ptr); 168 * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
201 domain = nla_data(msg_ptr); 169 * @entry: the domain mapping hash table entry
202 if (tmp_size <= 0 || tmp_size > msg_len || 170 * @arg: the netlbl_domhsh_walk_arg structure
203 domain[tmp_size - 1] != '\0') { 171 *
204 ret_val = -EINVAL; 172 * Description:
205 goto remove_return; 173 * This function is designed to be used as a callback to the
206 } 174 * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
207 ret_val = netlbl_domhsh_remove(domain); 175 * message. Returns the size of the message on success, negative values on
176 * failure.
177 *
178 */
179static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
180{
181 int ret_val = -ENOMEM;
182 struct netlbl_domhsh_walk_arg *cb_arg = arg;
183 void *data;
184
185 data = netlbl_netlink_hdr_put(cb_arg->skb,
186 NETLINK_CB(cb_arg->nl_cb->skb).pid,
187 cb_arg->seq,
188 netlbl_mgmt_gnl_family.id,
189 NLM_F_MULTI,
190 NLBL_MGMT_C_LISTALL);
191 if (data == NULL)
192 goto listall_cb_failure;
193
194 ret_val = nla_put_string(cb_arg->skb,
195 NLBL_MGMT_A_DOMAIN,
196 entry->domain);
197 if (ret_val != 0)
198 goto listall_cb_failure;
199 ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type);
200 if (ret_val != 0)
201 goto listall_cb_failure;
202 switch (entry->type) {
203 case NETLBL_NLTYPE_CIPSOV4:
204 ret_val = nla_put_u32(cb_arg->skb,
205 NLBL_MGMT_A_CV4DOI,
206 entry->type_def.cipsov4->doi);
208 if (ret_val != 0) 207 if (ret_val != 0)
209 goto remove_return; 208 goto listall_cb_failure;
210 msg_ptr = nla_next(msg_ptr, &msg_len); 209 break;
211 } 210 }
212 211
213 ret_val = 0; 212 cb_arg->seq++;
213 return genlmsg_end(cb_arg->skb, data);
214 214
215remove_return: 215listall_cb_failure:
216 netlbl_netlink_send_ack(info, 216 genlmsg_cancel(cb_arg->skb, data);
217 netlbl_mgmt_gnl_family.id,
218 NLBL_MGMT_C_ACK,
219 -ret_val);
220 return ret_val; 217 return ret_val;
221} 218}
222 219
223/** 220/**
224 * netlbl_mgmt_list - Handle a LIST message 221 * netlbl_mgmt_listall - Handle a LISTALL message
225 * @skb: the NETLINK buffer 222 * @skb: the NETLINK buffer
226 * @info: the Generic NETLINK info block 223 * @cb: the NETLINK callback
227 * 224 *
228 * Description: 225 * Description:
229 * Process a user generated LIST message and dumps the domain hash table in a 226 * Process a user generated LISTALL message and dumps the domain hash table in
230 * form suitable for use in a kernel generated LIST message. Returns zero on 227 * a form suitable for use in a kernel generated LISTALL message. Returns zero
231 * success, negative values on failure. 228 * on success, negative values on failure.
232 * 229 *
233 */ 230 */
234static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info) 231static int netlbl_mgmt_listall(struct sk_buff *skb,
232 struct netlink_callback *cb)
235{ 233{
236 int ret_val = -ENOMEM; 234 struct netlbl_domhsh_walk_arg cb_arg;
237 struct sk_buff *ans_skb; 235 u32 skip_bkt = cb->args[0];
238 236 u32 skip_chain = cb->args[1];
239 ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN)); 237
240 if (ans_skb == NULL) 238 cb_arg.nl_cb = cb;
241 goto list_failure; 239 cb_arg.skb = skb;
242 netlbl_netlink_hdr_push(ans_skb, 240 cb_arg.seq = cb->nlh->nlmsg_seq;
243 info->snd_pid, 241
244 0, 242 netlbl_domhsh_walk(&skip_bkt,
245 netlbl_mgmt_gnl_family.id, 243 &skip_chain,
246 NLBL_MGMT_C_LIST); 244 netlbl_mgmt_listall_cb,
247 245 &cb_arg);
248 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 246
249 if (ret_val != 0) 247 cb->args[0] = skip_bkt;
250 goto list_failure; 248 cb->args[1] = skip_chain;
251 249 return skb->len;
252 return 0;
253
254list_failure:
255 netlbl_netlink_send_ack(info,
256 netlbl_mgmt_gnl_family.id,
257 NLBL_MGMT_C_ACK,
258 -ret_val);
259 return ret_val;
260} 250}
261 251
262/** 252/**
@@ -272,68 +262,51 @@ list_failure:
272static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) 262static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
273{ 263{
274 int ret_val = -EINVAL; 264 int ret_val = -EINVAL;
275 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
276 int msg_len = netlbl_netlink_payload_len(skb);
277 struct netlbl_dom_map *entry = NULL; 265 struct netlbl_dom_map *entry = NULL;
278 u32 tmp_val; 266 u32 tmp_val;
279 267
280 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 268 if (!info->attrs[NLBL_MGMT_A_PROTOCOL])
281 if (ret_val != 0)
282 goto adddef_failure;
283
284 if (msg_len < NETLBL_LEN_U32)
285 goto adddef_failure; 269 goto adddef_failure;
286 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
287 270
288 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 271 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
289 if (entry == NULL) { 272 if (entry == NULL) {
290 ret_val = -ENOMEM; 273 ret_val = -ENOMEM;
291 goto adddef_failure; 274 goto adddef_failure;
292 } 275 }
276 entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
293 277
294 entry->type = tmp_val;
295 switch (entry->type) { 278 switch (entry->type) {
296 case NETLBL_NLTYPE_UNLABELED: 279 case NETLBL_NLTYPE_UNLABELED:
297 ret_val = netlbl_domhsh_add_default(entry); 280 ret_val = netlbl_domhsh_add_default(entry);
298 break; 281 break;
299 case NETLBL_NLTYPE_CIPSOV4: 282 case NETLBL_NLTYPE_CIPSOV4:
300 if (msg_len < NETLBL_LEN_U32) { 283 if (!info->attrs[NLBL_MGMT_A_CV4DOI])
301 ret_val = -EINVAL;
302 goto adddef_failure; 284 goto adddef_failure;
303 } 285
304 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); 286 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
305 /* We should be holding a rcu_read_lock here while we 287 /* We should be holding a rcu_read_lock() here while we hold
306 * hold the result but since the entry will always be 288 * the result but since the entry will always be deleted when
307 * deleted when the CIPSO DOI is deleted we are going 289 * the CIPSO DOI is deleted we aren't going to keep the
308 * to skip the lock. */ 290 * lock. */
309 rcu_read_lock(); 291 rcu_read_lock();
310 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); 292 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
311 if (entry->type_def.cipsov4 == NULL) { 293 if (entry->type_def.cipsov4 == NULL) {
312 rcu_read_unlock(); 294 rcu_read_unlock();
313 ret_val = -EINVAL;
314 goto adddef_failure; 295 goto adddef_failure;
315 } 296 }
316 ret_val = netlbl_domhsh_add_default(entry); 297 ret_val = netlbl_domhsh_add_default(entry);
317 rcu_read_unlock(); 298 rcu_read_unlock();
318 break; 299 break;
319 default: 300 default:
320 ret_val = -EINVAL; 301 goto adddef_failure;
321 } 302 }
322 if (ret_val != 0) 303 if (ret_val != 0)
323 goto adddef_failure; 304 goto adddef_failure;
324 305
325 netlbl_netlink_send_ack(info,
326 netlbl_mgmt_gnl_family.id,
327 NLBL_MGMT_C_ACK,
328 NETLBL_E_OK);
329 return 0; 306 return 0;
330 307
331adddef_failure: 308adddef_failure:
332 kfree(entry); 309 kfree(entry);
333 netlbl_netlink_send_ack(info,
334 netlbl_mgmt_gnl_family.id,
335 NLBL_MGMT_C_ACK,
336 -ret_val);
337 return ret_val; 310 return ret_val;
338} 311}
339 312
@@ -349,20 +322,7 @@ adddef_failure:
349 */ 322 */
350static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) 323static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
351{ 324{
352 int ret_val; 325 return netlbl_domhsh_remove_default();
353
354 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
355 if (ret_val != 0)
356 goto removedef_return;
357
358 ret_val = netlbl_domhsh_remove_default();
359
360removedef_return:
361 netlbl_netlink_send_ack(info,
362 netlbl_mgmt_gnl_family.id,
363 NLBL_MGMT_C_ACK,
364 -ret_val);
365 return ret_val;
366} 326}
367 327
368/** 328/**
@@ -379,88 +339,131 @@ removedef_return:
379static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) 339static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
380{ 340{
381 int ret_val = -ENOMEM; 341 int ret_val = -ENOMEM;
382 struct sk_buff *ans_skb; 342 struct sk_buff *ans_skb = NULL;
343 void *data;
344 struct netlbl_dom_map *entry;
383 345
384 ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN)); 346 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
385 if (ans_skb == NULL) 347 if (ans_skb == NULL)
348 return -ENOMEM;
349 data = netlbl_netlink_hdr_put(ans_skb,
350 info->snd_pid,
351 info->snd_seq,
352 netlbl_mgmt_gnl_family.id,
353 0,
354 NLBL_MGMT_C_LISTDEF);
355 if (data == NULL)
386 goto listdef_failure; 356 goto listdef_failure;
387 netlbl_netlink_hdr_push(ans_skb,
388 info->snd_pid,
389 0,
390 netlbl_mgmt_gnl_family.id,
391 NLBL_MGMT_C_LISTDEF);
392 357
393 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 358 rcu_read_lock();
359 entry = netlbl_domhsh_getentry(NULL);
360 if (entry == NULL) {
361 ret_val = -ENOENT;
362 goto listdef_failure_lock;
363 }
364 ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type);
394 if (ret_val != 0) 365 if (ret_val != 0)
395 goto listdef_failure; 366 goto listdef_failure_lock;
367 switch (entry->type) {
368 case NETLBL_NLTYPE_CIPSOV4:
369 ret_val = nla_put_u32(ans_skb,
370 NLBL_MGMT_A_CV4DOI,
371 entry->type_def.cipsov4->doi);
372 if (ret_val != 0)
373 goto listdef_failure_lock;
374 break;
375 }
376 rcu_read_unlock();
396 377
378 genlmsg_end(ans_skb, data);
379
380 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
381 if (ret_val != 0)
382 goto listdef_failure;
397 return 0; 383 return 0;
398 384
385listdef_failure_lock:
386 rcu_read_unlock();
399listdef_failure: 387listdef_failure:
400 netlbl_netlink_send_ack(info, 388 kfree_skb(ans_skb);
401 netlbl_mgmt_gnl_family.id,
402 NLBL_MGMT_C_ACK,
403 -ret_val);
404 return ret_val; 389 return ret_val;
405} 390}
406 391
407/** 392/**
408 * netlbl_mgmt_modules - Handle a MODULES message 393 * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
409 * @skb: the NETLINK buffer 394 * @skb: the skb to write to
410 * @info: the Generic NETLINK info block 395 * @seq: the NETLINK sequence number
396 * @cb: the NETLINK callback
397 * @protocol: the NetLabel protocol to use in the message
411 * 398 *
412 * Description: 399 * Description:
413 * Process a user generated MODULES message and respond accordingly. 400 * This function is to be used in conjunction with netlbl_mgmt_protocols() to
401 * answer a application's PROTOCOLS message. Returns the size of the message
402 * on success, negative values on failure.
414 * 403 *
415 */ 404 */
416static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info) 405static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
406 struct netlink_callback *cb,
407 u32 protocol)
417{ 408{
418 int ret_val = -ENOMEM; 409 int ret_val = -ENOMEM;
419 size_t data_size; 410 void *data;
420 u32 mod_count; 411
421 struct sk_buff *ans_skb = NULL; 412 data = netlbl_netlink_hdr_put(skb,
422 413 NETLINK_CB(cb->skb).pid,
423 /* unlabeled + cipsov4 */ 414 cb->nlh->nlmsg_seq,
424 mod_count = 2; 415 netlbl_mgmt_gnl_family.id,
425 416 NLM_F_MULTI,
426 data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32; 417 NLBL_MGMT_C_PROTOCOLS);
427 ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); 418 if (data == NULL)
428 if (ans_skb == NULL) 419 goto protocols_cb_failure;
429 goto modules_failure; 420
430 421 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
431 if (netlbl_netlink_hdr_put(ans_skb,
432 info->snd_pid,
433 0,
434 netlbl_mgmt_gnl_family.id,
435 NLBL_MGMT_C_MODULES) == NULL)
436 goto modules_failure;
437
438 ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count);
439 if (ret_val != 0)
440 goto modules_failure;
441 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED);
442 if (ret_val != 0) 422 if (ret_val != 0)
443 goto modules_failure; 423 goto protocols_cb_failure;
444 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4);
445 if (ret_val != 0)
446 goto modules_failure;
447
448 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
449 if (ret_val != 0)
450 goto modules_failure;
451 424
452 return 0; 425 return genlmsg_end(skb, data);
453 426
454modules_failure: 427protocols_cb_failure:
455 kfree_skb(ans_skb); 428 genlmsg_cancel(skb, data);
456 netlbl_netlink_send_ack(info,
457 netlbl_mgmt_gnl_family.id,
458 NLBL_MGMT_C_ACK,
459 -ret_val);
460 return ret_val; 429 return ret_val;
461} 430}
462 431
463/** 432/**
433 * netlbl_mgmt_protocols - Handle a PROTOCOLS message
434 * @skb: the NETLINK buffer
435 * @cb: the NETLINK callback
436 *
437 * Description:
438 * Process a user generated PROTOCOLS message and respond accordingly.
439 *
440 */
441static int netlbl_mgmt_protocols(struct sk_buff *skb,
442 struct netlink_callback *cb)
443{
444 u32 protos_sent = cb->args[0];
445
446 if (protos_sent == 0) {
447 if (netlbl_mgmt_protocols_cb(skb,
448 cb,
449 NETLBL_NLTYPE_UNLABELED) < 0)
450 goto protocols_return;
451 protos_sent++;
452 }
453 if (protos_sent == 1) {
454 if (netlbl_mgmt_protocols_cb(skb,
455 cb,
456 NETLBL_NLTYPE_CIPSOV4) < 0)
457 goto protocols_return;
458 protos_sent++;
459 }
460
461protocols_return:
462 cb->args[0] = protos_sent;
463 return skb->len;
464}
465
466/**
464 * netlbl_mgmt_version - Handle a VERSION message 467 * netlbl_mgmt_version - Handle a VERSION message
465 * @skb: the NETLINK buffer 468 * @skb: the NETLINK buffer
466 * @info: the Generic NETLINK info block 469 * @info: the Generic NETLINK info block
@@ -474,35 +477,35 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
474{ 477{
475 int ret_val = -ENOMEM; 478 int ret_val = -ENOMEM;
476 struct sk_buff *ans_skb = NULL; 479 struct sk_buff *ans_skb = NULL;
480 void *data;
477 481
478 ans_skb = netlbl_netlink_alloc_skb(0, 482 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
479 GENL_HDRLEN + NETLBL_LEN_U32,
480 GFP_KERNEL);
481 if (ans_skb == NULL) 483 if (ans_skb == NULL)
482 goto version_failure; 484 return -ENOMEM;
483 if (netlbl_netlink_hdr_put(ans_skb, 485 data = netlbl_netlink_hdr_put(ans_skb,
484 info->snd_pid, 486 info->snd_pid,
485 0, 487 info->snd_seq,
486 netlbl_mgmt_gnl_family.id, 488 netlbl_mgmt_gnl_family.id,
487 NLBL_MGMT_C_VERSION) == NULL) 489 0,
490 NLBL_MGMT_C_VERSION);
491 if (data == NULL)
488 goto version_failure; 492 goto version_failure;
489 493
490 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION); 494 ret_val = nla_put_u32(ans_skb,
495 NLBL_MGMT_A_VERSION,
496 NETLBL_PROTO_VERSION);
491 if (ret_val != 0) 497 if (ret_val != 0)
492 goto version_failure; 498 goto version_failure;
493 499
494 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 500 genlmsg_end(ans_skb, data);
501
502 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
495 if (ret_val != 0) 503 if (ret_val != 0)
496 goto version_failure; 504 goto version_failure;
497
498 return 0; 505 return 0;
499 506
500version_failure: 507version_failure:
501 kfree_skb(ans_skb); 508 kfree_skb(ans_skb);
502 netlbl_netlink_send_ack(info,
503 netlbl_mgmt_gnl_family.id,
504 NLBL_MGMT_C_ACK,
505 -ret_val);
506 return ret_val; 509 return ret_val;
507} 510}
508 511
@@ -513,35 +516,40 @@ version_failure:
513 516
514static struct genl_ops netlbl_mgmt_genl_c_add = { 517static struct genl_ops netlbl_mgmt_genl_c_add = {
515 .cmd = NLBL_MGMT_C_ADD, 518 .cmd = NLBL_MGMT_C_ADD,
516 .flags = 0, 519 .flags = GENL_ADMIN_PERM,
520 .policy = netlbl_mgmt_genl_policy,
517 .doit = netlbl_mgmt_add, 521 .doit = netlbl_mgmt_add,
518 .dumpit = NULL, 522 .dumpit = NULL,
519}; 523};
520 524
521static struct genl_ops netlbl_mgmt_genl_c_remove = { 525static struct genl_ops netlbl_mgmt_genl_c_remove = {
522 .cmd = NLBL_MGMT_C_REMOVE, 526 .cmd = NLBL_MGMT_C_REMOVE,
523 .flags = 0, 527 .flags = GENL_ADMIN_PERM,
528 .policy = netlbl_mgmt_genl_policy,
524 .doit = netlbl_mgmt_remove, 529 .doit = netlbl_mgmt_remove,
525 .dumpit = NULL, 530 .dumpit = NULL,
526}; 531};
527 532
528static struct genl_ops netlbl_mgmt_genl_c_list = { 533static struct genl_ops netlbl_mgmt_genl_c_listall = {
529 .cmd = NLBL_MGMT_C_LIST, 534 .cmd = NLBL_MGMT_C_LISTALL,
530 .flags = 0, 535 .flags = 0,
531 .doit = netlbl_mgmt_list, 536 .policy = netlbl_mgmt_genl_policy,
532 .dumpit = NULL, 537 .doit = NULL,
538 .dumpit = netlbl_mgmt_listall,
533}; 539};
534 540
535static struct genl_ops netlbl_mgmt_genl_c_adddef = { 541static struct genl_ops netlbl_mgmt_genl_c_adddef = {
536 .cmd = NLBL_MGMT_C_ADDDEF, 542 .cmd = NLBL_MGMT_C_ADDDEF,
537 .flags = 0, 543 .flags = GENL_ADMIN_PERM,
544 .policy = netlbl_mgmt_genl_policy,
538 .doit = netlbl_mgmt_adddef, 545 .doit = netlbl_mgmt_adddef,
539 .dumpit = NULL, 546 .dumpit = NULL,
540}; 547};
541 548
542static struct genl_ops netlbl_mgmt_genl_c_removedef = { 549static struct genl_ops netlbl_mgmt_genl_c_removedef = {
543 .cmd = NLBL_MGMT_C_REMOVEDEF, 550 .cmd = NLBL_MGMT_C_REMOVEDEF,
544 .flags = 0, 551 .flags = GENL_ADMIN_PERM,
552 .policy = netlbl_mgmt_genl_policy,
545 .doit = netlbl_mgmt_removedef, 553 .doit = netlbl_mgmt_removedef,
546 .dumpit = NULL, 554 .dumpit = NULL,
547}; 555};
@@ -549,20 +557,23 @@ static struct genl_ops netlbl_mgmt_genl_c_removedef = {
549static struct genl_ops netlbl_mgmt_genl_c_listdef = { 557static struct genl_ops netlbl_mgmt_genl_c_listdef = {
550 .cmd = NLBL_MGMT_C_LISTDEF, 558 .cmd = NLBL_MGMT_C_LISTDEF,
551 .flags = 0, 559 .flags = 0,
560 .policy = netlbl_mgmt_genl_policy,
552 .doit = netlbl_mgmt_listdef, 561 .doit = netlbl_mgmt_listdef,
553 .dumpit = NULL, 562 .dumpit = NULL,
554}; 563};
555 564
556static struct genl_ops netlbl_mgmt_genl_c_modules = { 565static struct genl_ops netlbl_mgmt_genl_c_protocols = {
557 .cmd = NLBL_MGMT_C_MODULES, 566 .cmd = NLBL_MGMT_C_PROTOCOLS,
558 .flags = 0, 567 .flags = 0,
559 .doit = netlbl_mgmt_modules, 568 .policy = netlbl_mgmt_genl_policy,
560 .dumpit = NULL, 569 .doit = NULL,
570 .dumpit = netlbl_mgmt_protocols,
561}; 571};
562 572
563static struct genl_ops netlbl_mgmt_genl_c_version = { 573static struct genl_ops netlbl_mgmt_genl_c_version = {
564 .cmd = NLBL_MGMT_C_VERSION, 574 .cmd = NLBL_MGMT_C_VERSION,
565 .flags = 0, 575 .flags = 0,
576 .policy = netlbl_mgmt_genl_policy,
566 .doit = netlbl_mgmt_version, 577 .doit = netlbl_mgmt_version,
567 .dumpit = NULL, 578 .dumpit = NULL,
568}; 579};
@@ -596,7 +607,7 @@ int netlbl_mgmt_genl_init(void)
596 if (ret_val != 0) 607 if (ret_val != 0)
597 return ret_val; 608 return ret_val;
598 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 609 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
599 &netlbl_mgmt_genl_c_list); 610 &netlbl_mgmt_genl_c_listall);
600 if (ret_val != 0) 611 if (ret_val != 0)
601 return ret_val; 612 return ret_val;
602 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 613 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
@@ -612,7 +623,7 @@ int netlbl_mgmt_genl_init(void)
612 if (ret_val != 0) 623 if (ret_val != 0)
613 return ret_val; 624 return ret_val;
614 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 625 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
615 &netlbl_mgmt_genl_c_modules); 626 &netlbl_mgmt_genl_c_protocols);
616 if (ret_val != 0) 627 if (ret_val != 0)
617 return ret_val; 628 return ret_val;
618 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 629 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h
index fd6c6acbfa08..3642d3bfc8eb 100644
--- a/net/netlabel/netlabel_mgmt.h
+++ b/net/netlabel/netlabel_mgmt.h
@@ -34,212 +34,137 @@
34#include <net/netlabel.h> 34#include <net/netlabel.h>
35 35
36/* 36/*
37 * The following NetLabel payloads are supported by the management interface, 37 * The following NetLabel payloads are supported by the management interface.
38 * all of which are preceeded by the nlmsghdr struct.
39 *
40 * o ACK:
41 * Sent by the kernel in response to an applications message, applications
42 * should never send this message.
43 *
44 * +----------------------+-----------------------+
45 * | seq number (32 bits) | return code (32 bits) |
46 * +----------------------+-----------------------+
47 *
48 * seq number: the sequence number of the original message, taken from the
49 * nlmsghdr structure
50 * return code: return value, based on errno values
51 * 38 *
52 * o ADD: 39 * o ADD:
53 * Sent by an application to add a domain mapping to the NetLabel system. 40 * Sent by an application to add a domain mapping to the NetLabel system.
54 * The kernel should respond with an ACK.
55 *
56 * +-------------------+
57 * | domains (32 bits) | ...
58 * +-------------------+
59 *
60 * domains: the number of domains in the message
61 *
62 * +--------------------------+-------------------------+
63 * | domain string (variable) | protocol type (32 bits) | ...
64 * +--------------------------+-------------------------+
65 * 41 *
66 * +-------------- ---- --- -- - 42 * Required attributes:
67 * | mapping data ... repeated
68 * +-------------- ---- --- -- -
69 * 43 *
70 * domain string: the domain string, NULL terminated 44 * NLBL_MGMT_A_DOMAIN
71 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) 45 * NLBL_MGMT_A_PROTOCOL
72 * mapping data: specific to the map type (see below)
73 * 46 *
74 * NETLBL_NLTYPE_UNLABELED 47 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
75 * 48 *
76 * No mapping data for this protocol type. 49 * NLBL_MGMT_A_CV4DOI
77 * 50 *
78 * NETLBL_NLTYPE_CIPSOV4 51 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
79 *
80 * +---------------+
81 * | doi (32 bits) |
82 * +---------------+
83 *
84 * doi: the CIPSO DOI value
85 * 52 *
86 * o REMOVE: 53 * o REMOVE:
87 * Sent by an application to remove a domain mapping from the NetLabel 54 * Sent by an application to remove a domain mapping from the NetLabel
88 * system. The kernel should ACK this message. 55 * system.
89 *
90 * +-------------------+
91 * | domains (32 bits) | ...
92 * +-------------------+
93 * 56 *
94 * domains: the number of domains in the message 57 * Required attributes:
95 * 58 *
96 * +--------------------------+ 59 * NLBL_MGMT_A_DOMAIN
97 * | domain string (variable) | ...
98 * +--------------------------+
99 * 60 *
100 * domain string: the domain string, NULL terminated 61 * o LISTALL:
101 *
102 * o LIST:
103 * This message can be sent either from an application or by the kernel in 62 * This message can be sent either from an application or by the kernel in
104 * response to an application generated LIST message. When sent by an 63 * response to an application generated LISTALL message. When sent by an
105 * application there is no payload. The kernel should respond to a LIST 64 * application there is no payload and the NLM_F_DUMP flag should be set.
106 * message either with a LIST message on success or an ACK message on 65 * The kernel should respond with a series of the following messages.
107 * failure.
108 *
109 * +-------------------+
110 * | domains (32 bits) | ...
111 * +-------------------+
112 *
113 * domains: the number of domains in the message
114 * 66 *
115 * +--------------------------+ 67 * Required attributes:
116 * | domain string (variable) | ...
117 * +--------------------------+
118 * 68 *
119 * +-------------------------+-------------- ---- --- -- - 69 * NLBL_MGMT_A_DOMAIN
120 * | protocol type (32 bits) | mapping data ... repeated 70 * NLBL_MGMT_A_PROTOCOL
121 * +-------------------------+-------------- ---- --- -- -
122 * 71 *
123 * domain string: the domain string, NULL terminated 72 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
124 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
125 * mapping data: specific to the map type (see below)
126 * 73 *
127 * NETLBL_NLTYPE_UNLABELED 74 * NLBL_MGMT_A_CV4DOI
128 * 75 *
129 * No mapping data for this protocol type. 76 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
130 *
131 * NETLBL_NLTYPE_CIPSOV4
132 *
133 * +----------------+---------------+
134 * | type (32 bits) | doi (32 bits) |
135 * +----------------+---------------+
136 *
137 * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
138 * as CIPSO_V4_MAP_*)
139 * doi: the CIPSO DOI value
140 * 77 *
141 * o ADDDEF: 78 * o ADDDEF:
142 * Sent by an application to set the default domain mapping for the NetLabel 79 * Sent by an application to set the default domain mapping for the NetLabel
143 * system. The kernel should respond with an ACK. 80 * system.
144 * 81 *
145 * +-------------------------+-------------- ---- --- -- - 82 * Required attributes:
146 * | protocol type (32 bits) | mapping data ... repeated
147 * +-------------------------+-------------- ---- --- -- -
148 * 83 *
149 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) 84 * NLBL_MGMT_A_PROTOCOL
150 * mapping data: specific to the map type (see below)
151 * 85 *
152 * NETLBL_NLTYPE_UNLABELED 86 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
153 * 87 *
154 * No mapping data for this protocol type. 88 * NLBL_MGMT_A_CV4DOI
155 * 89 *
156 * NETLBL_NLTYPE_CIPSOV4 90 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
157 *
158 * +---------------+
159 * | doi (32 bits) |
160 * +---------------+
161 *
162 * doi: the CIPSO DOI value
163 * 91 *
164 * o REMOVEDEF: 92 * o REMOVEDEF:
165 * Sent by an application to remove the default domain mapping from the 93 * Sent by an application to remove the default domain mapping from the
166 * NetLabel system, there is no payload. The kernel should ACK this message. 94 * NetLabel system, there is no payload.
167 * 95 *
168 * o LISTDEF: 96 * o LISTDEF:
169 * This message can be sent either from an application or by the kernel in 97 * This message can be sent either from an application or by the kernel in
170 * response to an application generated LISTDEF message. When sent by an 98 * response to an application generated LISTDEF message. When sent by an
171 * application there is no payload. The kernel should respond to a 99 * application there is no payload. On success the kernel should send a
172 * LISTDEF message either with a LISTDEF message on success or an ACK message 100 * response using the following format.
173 * on failure.
174 *
175 * +-------------------------+-------------- ---- --- -- -
176 * | protocol type (32 bits) | mapping data ... repeated
177 * +-------------------------+-------------- ---- --- -- -
178 * 101 *
179 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) 102 * Required attributes:
180 * mapping data: specific to the map type (see below)
181 * 103 *
182 * NETLBL_NLTYPE_UNLABELED 104 * NLBL_MGMT_A_PROTOCOL
183 * 105 *
184 * No mapping data for this protocol type. 106 * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
185 * 107 *
186 * NETLBL_NLTYPE_CIPSOV4 108 * NLBL_MGMT_A_CV4DOI
187 * 109 *
188 * +----------------+---------------+ 110 * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
189 * | type (32 bits) | doi (32 bits) |
190 * +----------------+---------------+
191 * 111 *
192 * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header 112 * o PROTOCOLS:
193 * as CIPSO_V4_MAP_*) 113 * Sent by an application to request a list of configured NetLabel protocols
194 * doi: the CIPSO DOI value 114 * in the kernel. When sent by an application there is no payload and the
115 * NLM_F_DUMP flag should be set. The kernel should respond with a series of
116 * the following messages.
195 * 117 *
196 * o MODULES: 118 * Required attributes:
197 * Sent by an application to request a list of configured NetLabel modules
198 * in the kernel. When sent by an application there is no payload.
199 * 119 *
200 * +-------------------+ 120 * NLBL_MGMT_A_PROTOCOL
201 * | modules (32 bits) | ...
202 * +-------------------+
203 *
204 * modules: the number of modules in the message, if this is an application
205 * generated message and the value is zero then return a list of
206 * the configured modules
207 *
208 * +------------------+
209 * | module (32 bits) | ... repeated
210 * +------------------+
211 *
212 * module: the module number as defined by NETLBL_NLTYPE_*
213 * 121 *
214 * o VERSION: 122 * o VERSION:
215 * Sent by an application to request the NetLabel version string. When sent 123 * Sent by an application to request the NetLabel version. When sent by an
216 * by an application there is no payload. This message type is also used by 124 * application there is no payload. This message type is also used by the
217 * the kernel to respond to an VERSION request. 125 * kernel to respond to an VERSION request.
218 * 126 *
219 * +-------------------+ 127 * Required attributes:
220 * | version (32 bits) |
221 * +-------------------+
222 * 128 *
223 * version: the protocol version number 129 * NLBL_MGMT_A_VERSION
224 * 130 *
225 */ 131 */
226 132
227/* NetLabel Management commands */ 133/* NetLabel Management commands */
228enum { 134enum {
229 NLBL_MGMT_C_UNSPEC, 135 NLBL_MGMT_C_UNSPEC,
230 NLBL_MGMT_C_ACK,
231 NLBL_MGMT_C_ADD, 136 NLBL_MGMT_C_ADD,
232 NLBL_MGMT_C_REMOVE, 137 NLBL_MGMT_C_REMOVE,
233 NLBL_MGMT_C_LIST, 138 NLBL_MGMT_C_LISTALL,
234 NLBL_MGMT_C_ADDDEF, 139 NLBL_MGMT_C_ADDDEF,
235 NLBL_MGMT_C_REMOVEDEF, 140 NLBL_MGMT_C_REMOVEDEF,
236 NLBL_MGMT_C_LISTDEF, 141 NLBL_MGMT_C_LISTDEF,
237 NLBL_MGMT_C_MODULES, 142 NLBL_MGMT_C_PROTOCOLS,
238 NLBL_MGMT_C_VERSION, 143 NLBL_MGMT_C_VERSION,
239 __NLBL_MGMT_C_MAX, 144 __NLBL_MGMT_C_MAX,
240}; 145};
241#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1) 146#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1)
242 147
148/* NetLabel Management attributes */
149enum {
150 NLBL_MGMT_A_UNSPEC,
151 NLBL_MGMT_A_DOMAIN,
152 /* (NLA_NUL_STRING)
153 * the NULL terminated LSM domain string */
154 NLBL_MGMT_A_PROTOCOL,
155 /* (NLA_U32)
156 * the NetLabel protocol type (defined by NETLBL_NLTYPE_*) */
157 NLBL_MGMT_A_VERSION,
158 /* (NLA_U32)
159 * the NetLabel protocol version number (defined by
160 * NETLBL_PROTO_VERSION) */
161 NLBL_MGMT_A_CV4DOI,
162 /* (NLA_U32)
163 * the CIPSOv4 DOI value */
164 __NLBL_MGMT_A_MAX,
165};
166#define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1)
167
243/* NetLabel protocol functions */ 168/* NetLabel protocol functions */
244int netlbl_mgmt_genl_init(void); 169int netlbl_mgmt_genl_init(void);
245 170
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 785f4960e0d3..440f5c4e1e2d 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -55,9 +55,13 @@ static struct genl_family netlbl_unlabel_gnl_family = {
55 .hdrsize = 0, 55 .hdrsize = 0,
56 .name = NETLBL_NLTYPE_UNLABELED_NAME, 56 .name = NETLBL_NLTYPE_UNLABELED_NAME,
57 .version = NETLBL_PROTO_VERSION, 57 .version = NETLBL_PROTO_VERSION,
58 .maxattr = 0, 58 .maxattr = NLBL_UNLABEL_A_MAX,
59}; 59};
60 60
61/* NetLabel Netlink attribute policy */
62static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
63 [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
64};
61 65
62/* 66/*
63 * NetLabel Command Handlers 67 * NetLabel Command Handlers
@@ -75,31 +79,18 @@ static struct genl_family netlbl_unlabel_gnl_family = {
75 */ 79 */
76static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) 80static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
77{ 81{
78 int ret_val; 82 int ret_val = -EINVAL;
79 struct nlattr *data = netlbl_netlink_payload_data(skb); 83 u8 value;
80 u32 value;
81
82 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
83 if (ret_val != 0)
84 return ret_val;
85 84
86 if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) { 85 if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
87 value = nla_get_u32(data); 86 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
88 if (value == 1 || value == 0) { 87 if (value == 1 || value == 0) {
89 atomic_set(&netlabel_unlabel_accept_flg, value); 88 atomic_set(&netlabel_unlabel_accept_flg, value);
90 netlbl_netlink_send_ack(info, 89 ret_val = 0;
91 netlbl_unlabel_gnl_family.id,
92 NLBL_UNLABEL_C_ACK,
93 NETLBL_E_OK);
94 return 0;
95 } 90 }
96 } 91 }
97 92
98 netlbl_netlink_send_ack(info, 93 return ret_val;
99 netlbl_unlabel_gnl_family.id,
100 NLBL_UNLABEL_C_ACK,
101 EINVAL);
102 return -EINVAL;
103} 94}
104 95
105/** 96/**
@@ -114,39 +105,39 @@ static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
114 */ 105 */
115static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) 106static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
116{ 107{
117 int ret_val = -ENOMEM; 108 int ret_val = -EINVAL;
118 struct sk_buff *ans_skb; 109 struct sk_buff *ans_skb;
110 void *data;
119 111
120 ans_skb = netlbl_netlink_alloc_skb(0, 112 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
121 GENL_HDRLEN + NETLBL_LEN_U32,
122 GFP_KERNEL);
123 if (ans_skb == NULL) 113 if (ans_skb == NULL)
124 goto list_failure; 114 goto list_failure;
125 115 data = netlbl_netlink_hdr_put(ans_skb,
126 if (netlbl_netlink_hdr_put(ans_skb, 116 info->snd_pid,
127 info->snd_pid, 117 info->snd_seq,
128 0, 118 netlbl_unlabel_gnl_family.id,
129 netlbl_unlabel_gnl_family.id, 119 0,
130 NLBL_UNLABEL_C_LIST) == NULL) 120 NLBL_UNLABEL_C_LIST);
121 if (data == NULL) {
122 ret_val = -ENOMEM;
131 goto list_failure; 123 goto list_failure;
124 }
132 125
133 ret_val = nla_put_u32(ans_skb, 126 ret_val = nla_put_u8(ans_skb,
134 NLA_U32, 127 NLBL_UNLABEL_A_ACPTFLG,
135 atomic_read(&netlabel_unlabel_accept_flg)); 128 atomic_read(&netlabel_unlabel_accept_flg));
136 if (ret_val != 0) 129 if (ret_val != 0)
137 goto list_failure; 130 goto list_failure;
138 131
139 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 132 genlmsg_end(ans_skb, data);
133
134 ret_val = genlmsg_unicast(ans_skb, info->snd_pid);
140 if (ret_val != 0) 135 if (ret_val != 0)
141 goto list_failure; 136 goto list_failure;
142
143 return 0; 137 return 0;
144 138
145list_failure: 139list_failure:
146 netlbl_netlink_send_ack(info, 140 kfree(ans_skb);
147 netlbl_unlabel_gnl_family.id,
148 NLBL_UNLABEL_C_ACK,
149 -ret_val);
150 return ret_val; 141 return ret_val;
151} 142}
152 143
@@ -157,7 +148,8 @@ list_failure:
157 148
158static struct genl_ops netlbl_unlabel_genl_c_accept = { 149static struct genl_ops netlbl_unlabel_genl_c_accept = {
159 .cmd = NLBL_UNLABEL_C_ACCEPT, 150 .cmd = NLBL_UNLABEL_C_ACCEPT,
160 .flags = 0, 151 .flags = GENL_ADMIN_PERM,
152 .policy = netlbl_unlabel_genl_policy,
161 .doit = netlbl_unlabel_accept, 153 .doit = netlbl_unlabel_accept,
162 .dumpit = NULL, 154 .dumpit = NULL,
163}; 155};
@@ -165,6 +157,7 @@ static struct genl_ops netlbl_unlabel_genl_c_accept = {
165static struct genl_ops netlbl_unlabel_genl_c_list = { 157static struct genl_ops netlbl_unlabel_genl_c_list = {
166 .cmd = NLBL_UNLABEL_C_LIST, 158 .cmd = NLBL_UNLABEL_C_LIST,
167 .flags = 0, 159 .flags = 0,
160 .policy = netlbl_unlabel_genl_policy,
168 .doit = netlbl_unlabel_list, 161 .doit = netlbl_unlabel_list,
169 .dumpit = NULL, 162 .dumpit = NULL,
170}; 163};
@@ -218,10 +211,8 @@ int netlbl_unlabel_genl_init(void)
218 */ 211 */
219int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) 212int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr)
220{ 213{
221 if (atomic_read(&netlabel_unlabel_accept_flg) == 1) { 214 if (atomic_read(&netlabel_unlabel_accept_flg) == 1)
222 memset(secattr, 0, sizeof(*secattr)); 215 return netlbl_secattr_init(secattr);
223 return 0;
224 }
225 216
226 return -ENOMSG; 217 return -ENOMSG;
227} 218}
diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h
index f300e54e14b6..c2917fbb42cf 100644
--- a/net/netlabel/netlabel_unlabeled.h
+++ b/net/netlabel/netlabel_unlabeled.h
@@ -36,56 +36,47 @@
36/* 36/*
37 * The following NetLabel payloads are supported by the Unlabeled subsystem. 37 * The following NetLabel payloads are supported by the Unlabeled subsystem.
38 * 38 *
39 * o ACK:
40 * Sent by the kernel in response to an applications message, applications
41 * should never send this message.
42 *
43 * +----------------------+-----------------------+
44 * | seq number (32 bits) | return code (32 bits) |
45 * +----------------------+-----------------------+
46 *
47 * seq number: the sequence number of the original message, taken from the
48 * nlmsghdr structure
49 * return code: return value, based on errno values
50 *
51 * o ACCEPT 39 * o ACCEPT
52 * This message is sent from an application to specify if the kernel should 40 * This message is sent from an application to specify if the kernel should
53 * allow unlabled packets to pass if they do not match any of the static 41 * allow unlabled packets to pass if they do not match any of the static
54 * mappings defined in the unlabeled module. 42 * mappings defined in the unlabeled module.
55 * 43 *
56 * +-----------------+ 44 * Required attributes:
57 * | allow (32 bits) |
58 * +-----------------+
59 * 45 *
60 * allow: if true (1) then allow the packets to pass, if false (0) then 46 * NLBL_UNLABEL_A_ACPTFLG
61 * reject the packets
62 * 47 *
63 * o LIST 48 * o LIST
64 * This message can be sent either from an application or by the kernel in 49 * This message can be sent either from an application or by the kernel in
65 * response to an application generated LIST message. When sent by an 50 * response to an application generated LIST message. When sent by an
66 * application there is no payload. The kernel should respond to a LIST 51 * application there is no payload. The kernel should respond to a LIST
67 * message either with a LIST message on success or an ACK message on 52 * message with a LIST message on success.
68 * failure.
69 * 53 *
70 * +-----------------------+ 54 * Required attributes:
71 * | accept flag (32 bits) |
72 * +-----------------------+
73 * 55 *
74 * accept flag: if true (1) then unlabeled packets are allowed to pass, 56 * NLBL_UNLABEL_A_ACPTFLG
75 * if false (0) then unlabeled packets are rejected
76 * 57 *
77 */ 58 */
78 59
79/* NetLabel Unlabeled commands */ 60/* NetLabel Unlabeled commands */
80enum { 61enum {
81 NLBL_UNLABEL_C_UNSPEC, 62 NLBL_UNLABEL_C_UNSPEC,
82 NLBL_UNLABEL_C_ACK,
83 NLBL_UNLABEL_C_ACCEPT, 63 NLBL_UNLABEL_C_ACCEPT,
84 NLBL_UNLABEL_C_LIST, 64 NLBL_UNLABEL_C_LIST,
85 __NLBL_UNLABEL_C_MAX, 65 __NLBL_UNLABEL_C_MAX,
86}; 66};
87#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1) 67#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1)
88 68
69/* NetLabel Unlabeled attributes */
70enum {
71 NLBL_UNLABEL_A_UNSPEC,
72 NLBL_UNLABEL_A_ACPTFLG,
73 /* (NLA_U8)
74 * if true then unlabeled packets are allowed to pass, else unlabeled
75 * packets are rejected */
76 __NLBL_UNLABEL_A_MAX,
77};
78#define NLBL_UNLABEL_A_MAX (__NLBL_UNLABEL_A_MAX - 1)
79
89/* NetLabel protocol functions */ 80/* NetLabel protocol functions */
90int netlbl_unlabel_genl_init(void); 81int netlbl_unlabel_genl_init(void);
91 82