OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [netlabel/] [netlabel_cipso_v4.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * NetLabel CIPSO/IPv4 Support
3
 *
4
 * This file defines the CIPSO/IPv4 functions for the NetLabel system.  The
5
 * NetLabel system manages static and dynamic label mappings for network
6
 * protocols such as CIPSO and RIPSO.
7
 *
8
 * Author: Paul Moore <paul.moore@hp.com>
9
 *
10
 */
11
 
12
/*
13
 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
14
 *
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
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY;  without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23
 * the GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program;  if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
 *
29
 */
30
 
31
#include <linux/types.h>
32
#include <linux/socket.h>
33
#include <linux/string.h>
34
#include <linux/skbuff.h>
35
#include <linux/audit.h>
36
#include <net/sock.h>
37
#include <net/netlink.h>
38
#include <net/genetlink.h>
39
#include <net/netlabel.h>
40
#include <net/cipso_ipv4.h>
41
 
42
#include "netlabel_user.h"
43
#include "netlabel_cipso_v4.h"
44
#include "netlabel_mgmt.h"
45
 
46
/* Argument struct for cipso_v4_doi_walk() */
47
struct netlbl_cipsov4_doiwalk_arg {
48
        struct netlink_callback *nl_cb;
49
        struct sk_buff *skb;
50
        u32 seq;
51
};
52
 
53
/* NetLabel Generic NETLINK CIPSOv4 family */
54
static struct genl_family netlbl_cipsov4_gnl_family = {
55
        .id = GENL_ID_GENERATE,
56
        .hdrsize = 0,
57
        .name = NETLBL_NLTYPE_CIPSOV4_NAME,
58
        .version = NETLBL_PROTO_VERSION,
59
        .maxattr = NLBL_CIPSOV4_A_MAX,
60
};
61
 
62
/* NetLabel Netlink attribute policy */
63
static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
64
        [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
65
        [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
66
        [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
67
        [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
68
        [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
69
        [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
70
        [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
71
        [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
72
        [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
73
        [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
74
        [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
75
        [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
76
};
77
 
78
/*
79
 * Helper Functions
80
 */
81
 
82
/**
83
 * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition
84
 * @entry: the entry's RCU field
85
 *
86
 * Description:
87
 * This function is designed to be used as a callback to the call_rcu()
88
 * function so that the memory allocated to the DOI definition can be released
89
 * safely.
90
 *
91
 */
92
static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
93
{
94
        struct cipso_v4_doi *ptr;
95
 
96
        ptr = container_of(entry, struct cipso_v4_doi, rcu);
97
        switch (ptr->type) {
98
        case CIPSO_V4_MAP_STD:
99
                kfree(ptr->map.std->lvl.cipso);
100
                kfree(ptr->map.std->lvl.local);
101
                kfree(ptr->map.std->cat.cipso);
102
                kfree(ptr->map.std->cat.local);
103
                break;
104
        }
105
        kfree(ptr);
106
}
107
 
108
/**
109
 * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
110
 * @info: the Generic NETLINK info block
111
 * @doi_def: the CIPSO V4 DOI definition
112
 *
113
 * Description:
114
 * Parse the common sections of a ADD message and fill in the related values
115
 * in @doi_def.  Returns zero on success, negative values on failure.
116
 *
117
 */
118
static int netlbl_cipsov4_add_common(struct genl_info *info,
119
                                     struct cipso_v4_doi *doi_def)
120
{
121
        struct nlattr *nla;
122
        int nla_rem;
123
        u32 iter = 0;
124
 
125
        doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
126
 
127
        if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST],
128
                                NLBL_CIPSOV4_A_MAX,
129
                                netlbl_cipsov4_genl_policy) != 0)
130
                return -EINVAL;
131
 
132
        nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
133
                if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) {
134
                        if (iter >= CIPSO_V4_TAG_MAXCNT)
135
                                return -EINVAL;
136
                        doi_def->tags[iter++] = nla_get_u8(nla);
137
                }
138
        while (iter < CIPSO_V4_TAG_MAXCNT)
139
                doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
140
 
141
        return 0;
142
}
143
 
144
/*
145
 * NetLabel Command Handlers
146
 */
147
 
148
/**
149
 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
150
 * @info: the Generic NETLINK info block
151
 *
152
 * Description:
153
 * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
154
 * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
155
 * error.
156
 *
157
 */
158
static int netlbl_cipsov4_add_std(struct genl_info *info)
159
{
160
        int ret_val = -EINVAL;
161
        struct cipso_v4_doi *doi_def = NULL;
162
        struct nlattr *nla_a;
163
        struct nlattr *nla_b;
164
        int nla_a_rem;
165
        int nla_b_rem;
166
        u32 iter;
167
 
168
        if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
169
            !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
170
                return -EINVAL;
171
 
172
        if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
173
                                NLBL_CIPSOV4_A_MAX,
174
                                netlbl_cipsov4_genl_policy) != 0)
175
                return -EINVAL;
176
 
177
        doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
178
        if (doi_def == NULL)
179
                return -ENOMEM;
180
        doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
181
        if (doi_def->map.std == NULL) {
182
                ret_val = -ENOMEM;
183
                goto add_std_failure;
184
        }
185
        doi_def->type = CIPSO_V4_MAP_STD;
186
 
187
        ret_val = netlbl_cipsov4_add_common(info, doi_def);
188
        if (ret_val != 0)
189
                goto add_std_failure;
190
        ret_val = -EINVAL;
191
 
192
        nla_for_each_nested(nla_a,
193
                            info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
194
                            nla_a_rem)
195
                if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
196
                        if (nla_validate_nested(nla_a,
197
                                            NLBL_CIPSOV4_A_MAX,
198
                                            netlbl_cipsov4_genl_policy) != 0)
199
                                        goto add_std_failure;
200
                        nla_for_each_nested(nla_b, nla_a, nla_b_rem)
201
                                switch (nla_type(nla_b)) {
202
                                case NLBL_CIPSOV4_A_MLSLVLLOC:
203
                                        if (nla_get_u32(nla_b) >
204
                                            CIPSO_V4_MAX_LOC_LVLS)
205
                                                goto add_std_failure;
206
                                        if (nla_get_u32(nla_b) >=
207
                                            doi_def->map.std->lvl.local_size)
208
                                             doi_def->map.std->lvl.local_size =
209
                                                     nla_get_u32(nla_b) + 1;
210
                                        break;
211
                                case NLBL_CIPSOV4_A_MLSLVLREM:
212
                                        if (nla_get_u32(nla_b) >
213
                                            CIPSO_V4_MAX_REM_LVLS)
214
                                                goto add_std_failure;
215
                                        if (nla_get_u32(nla_b) >=
216
                                            doi_def->map.std->lvl.cipso_size)
217
                                             doi_def->map.std->lvl.cipso_size =
218
                                                     nla_get_u32(nla_b) + 1;
219
                                        break;
220
                                }
221
                }
222
        doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
223
                                              sizeof(u32),
224
                                              GFP_KERNEL);
225
        if (doi_def->map.std->lvl.local == NULL) {
226
                ret_val = -ENOMEM;
227
                goto add_std_failure;
228
        }
229
        doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
230
                                              sizeof(u32),
231
                                              GFP_KERNEL);
232
        if (doi_def->map.std->lvl.cipso == NULL) {
233
                ret_val = -ENOMEM;
234
                goto add_std_failure;
235
        }
236
        for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
237
                doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
238
        for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
239
                doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
240
        nla_for_each_nested(nla_a,
241
                            info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
242
                            nla_a_rem)
243
                if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
244
                        struct nlattr *lvl_loc;
245
                        struct nlattr *lvl_rem;
246
 
247
                        lvl_loc = nla_find_nested(nla_a,
248
                                                  NLBL_CIPSOV4_A_MLSLVLLOC);
249
                        lvl_rem = nla_find_nested(nla_a,
250
                                                  NLBL_CIPSOV4_A_MLSLVLREM);
251
                        if (lvl_loc == NULL || lvl_rem == NULL)
252
                                goto add_std_failure;
253
                        doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
254
                                nla_get_u32(lvl_rem);
255
                        doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
256
                                nla_get_u32(lvl_loc);
257
                }
258
 
259
        if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
260
                if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
261
                                        NLBL_CIPSOV4_A_MAX,
262
                                        netlbl_cipsov4_genl_policy) != 0)
263
                        goto add_std_failure;
264
 
265
                nla_for_each_nested(nla_a,
266
                                    info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
267
                                    nla_a_rem)
268
                        if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
269
                                if (nla_validate_nested(nla_a,
270
                                              NLBL_CIPSOV4_A_MAX,
271
                                              netlbl_cipsov4_genl_policy) != 0)
272
                                        goto add_std_failure;
273
                                nla_for_each_nested(nla_b, nla_a, nla_b_rem)
274
                                        switch (nla_type(nla_b)) {
275
                                        case NLBL_CIPSOV4_A_MLSCATLOC:
276
                                                if (nla_get_u32(nla_b) >
277
                                                    CIPSO_V4_MAX_LOC_CATS)
278
                                                        goto add_std_failure;
279
                                                if (nla_get_u32(nla_b) >=
280
                                              doi_def->map.std->cat.local_size)
281
                                             doi_def->map.std->cat.local_size =
282
                                                     nla_get_u32(nla_b) + 1;
283
                                                break;
284
                                        case NLBL_CIPSOV4_A_MLSCATREM:
285
                                                if (nla_get_u32(nla_b) >
286
                                                    CIPSO_V4_MAX_REM_CATS)
287
                                                        goto add_std_failure;
288
                                                if (nla_get_u32(nla_b) >=
289
                                              doi_def->map.std->cat.cipso_size)
290
                                             doi_def->map.std->cat.cipso_size =
291
                                                     nla_get_u32(nla_b) + 1;
292
                                                break;
293
                                        }
294
                        }
295
                doi_def->map.std->cat.local = kcalloc(
296
                                              doi_def->map.std->cat.local_size,
297
                                              sizeof(u32),
298
                                              GFP_KERNEL);
299
                if (doi_def->map.std->cat.local == NULL) {
300
                        ret_val = -ENOMEM;
301
                        goto add_std_failure;
302
                }
303
                doi_def->map.std->cat.cipso = kcalloc(
304
                                              doi_def->map.std->cat.cipso_size,
305
                                              sizeof(u32),
306
                                              GFP_KERNEL);
307
                if (doi_def->map.std->cat.cipso == NULL) {
308
                        ret_val = -ENOMEM;
309
                        goto add_std_failure;
310
                }
311
                for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
312
                        doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
313
                for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
314
                        doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
315
                nla_for_each_nested(nla_a,
316
                                    info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
317
                                    nla_a_rem)
318
                        if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
319
                                struct nlattr *cat_loc;
320
                                struct nlattr *cat_rem;
321
 
322
                                cat_loc = nla_find_nested(nla_a,
323
                                                     NLBL_CIPSOV4_A_MLSCATLOC);
324
                                cat_rem = nla_find_nested(nla_a,
325
                                                     NLBL_CIPSOV4_A_MLSCATREM);
326
                                if (cat_loc == NULL || cat_rem == NULL)
327
                                        goto add_std_failure;
328
                                doi_def->map.std->cat.local[
329
                                                        nla_get_u32(cat_loc)] =
330
                                        nla_get_u32(cat_rem);
331
                                doi_def->map.std->cat.cipso[
332
                                                        nla_get_u32(cat_rem)] =
333
                                        nla_get_u32(cat_loc);
334
                        }
335
        }
336
 
337
        ret_val = cipso_v4_doi_add(doi_def);
338
        if (ret_val != 0)
339
                goto add_std_failure;
340
        return 0;
341
 
342
add_std_failure:
343
        if (doi_def)
344
                netlbl_cipsov4_doi_free(&doi_def->rcu);
345
        return ret_val;
346
}
347
 
348
/**
349
 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
350
 * @info: the Generic NETLINK info block
351
 *
352
 * Description:
353
 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
354
 * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
355
 * error.
356
 *
357
 */
358
static int netlbl_cipsov4_add_pass(struct genl_info *info)
359
{
360
        int ret_val;
361
        struct cipso_v4_doi *doi_def = NULL;
362
 
363
        if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
364
                return -EINVAL;
365
 
366
        doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
367
        if (doi_def == NULL)
368
                return -ENOMEM;
369
        doi_def->type = CIPSO_V4_MAP_PASS;
370
 
371
        ret_val = netlbl_cipsov4_add_common(info, doi_def);
372
        if (ret_val != 0)
373
                goto add_pass_failure;
374
 
375
        ret_val = cipso_v4_doi_add(doi_def);
376
        if (ret_val != 0)
377
                goto add_pass_failure;
378
        return 0;
379
 
380
add_pass_failure:
381
        netlbl_cipsov4_doi_free(&doi_def->rcu);
382
        return ret_val;
383
}
384
 
385
/**
386
 * netlbl_cipsov4_add - Handle an ADD message
387
 * @skb: the NETLINK buffer
388
 * @info: the Generic NETLINK info block
389
 *
390
 * Description:
391
 * Create a new DOI definition based on the given ADD message and add it to the
392
 * CIPSO V4 engine.  Returns zero on success, negative values on failure.
393
 *
394
 */
395
static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
396
 
397
{
398
        int ret_val = -EINVAL;
399
        u32 type;
400
        u32 doi;
401
        const char *type_str = "(unknown)";
402
        struct audit_buffer *audit_buf;
403
        struct netlbl_audit audit_info;
404
 
405
        if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
406
            !info->attrs[NLBL_CIPSOV4_A_MTYPE])
407
                return -EINVAL;
408
 
409
        doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
410
        netlbl_netlink_auditinfo(skb, &audit_info);
411
 
412
        type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
413
        switch (type) {
414
        case CIPSO_V4_MAP_STD:
415
                type_str = "std";
416
                ret_val = netlbl_cipsov4_add_std(info);
417
                break;
418
        case CIPSO_V4_MAP_PASS:
419
                type_str = "pass";
420
                ret_val = netlbl_cipsov4_add_pass(info);
421
                break;
422
        }
423
        if (ret_val == 0)
424
                netlbl_mgmt_protocount_inc();
425
 
426
        audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
427
                                              &audit_info);
428
        if (audit_buf != NULL) {
429
                audit_log_format(audit_buf,
430
                                 " cipso_doi=%u cipso_type=%s res=%u",
431
                                 doi,
432
                                 type_str,
433
                                 ret_val == 0 ? 1 : 0);
434
                audit_log_end(audit_buf);
435
        }
436
 
437
        return ret_val;
438
}
439
 
440
/**
441
 * netlbl_cipsov4_list - Handle a LIST message
442
 * @skb: the NETLINK buffer
443
 * @info: the Generic NETLINK info block
444
 *
445
 * Description:
446
 * Process a user generated LIST message and respond accordingly.  While the
447
 * response message generated by the kernel is straightforward, determining
448
 * before hand the size of the buffer to allocate is not (we have to generate
449
 * the message to know the size).  In order to keep this function sane what we
450
 * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
451
 * that size, if we fail then we restart with a larger buffer and try again.
452
 * We continue in this manner until we hit a limit of failed attempts then we
453
 * give up and just send an error message.  Returns zero on success and
454
 * negative values on error.
455
 *
456
 */
457
static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
458
{
459
        int ret_val;
460
        struct sk_buff *ans_skb = NULL;
461
        u32 nlsze_mult = 1;
462
        void *data;
463
        u32 doi;
464
        struct nlattr *nla_a;
465
        struct nlattr *nla_b;
466
        struct cipso_v4_doi *doi_def;
467
        u32 iter;
468
 
469
        if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
470
                ret_val = -EINVAL;
471
                goto list_failure;
472
        }
473
 
474
list_start:
475
        ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
476
        if (ans_skb == NULL) {
477
                ret_val = -ENOMEM;
478
                goto list_failure;
479
        }
480
        data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family,
481
                                 0, NLBL_CIPSOV4_C_LIST);
482
        if (data == NULL) {
483
                ret_val = -ENOMEM;
484
                goto list_failure;
485
        }
486
 
487
        doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
488
 
489
        rcu_read_lock();
490
        doi_def = cipso_v4_doi_getdef(doi);
491
        if (doi_def == NULL) {
492
                ret_val = -EINVAL;
493
                goto list_failure;
494
        }
495
 
496
        ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
497
        if (ret_val != 0)
498
                goto list_failure_lock;
499
 
500
        nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
501
        if (nla_a == NULL) {
502
                ret_val = -ENOMEM;
503
                goto list_failure_lock;
504
        }
505
        for (iter = 0;
506
             iter < CIPSO_V4_TAG_MAXCNT &&
507
               doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
508
             iter++) {
509
                ret_val = nla_put_u8(ans_skb,
510
                                     NLBL_CIPSOV4_A_TAG,
511
                                     doi_def->tags[iter]);
512
                if (ret_val != 0)
513
                        goto list_failure_lock;
514
        }
515
        nla_nest_end(ans_skb, nla_a);
516
 
517
        switch (doi_def->type) {
518
        case CIPSO_V4_MAP_STD:
519
                nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
520
                if (nla_a == NULL) {
521
                        ret_val = -ENOMEM;
522
                        goto list_failure_lock;
523
                }
524
                for (iter = 0;
525
                     iter < doi_def->map.std->lvl.local_size;
526
                     iter++) {
527
                        if (doi_def->map.std->lvl.local[iter] ==
528
                            CIPSO_V4_INV_LVL)
529
                                continue;
530
 
531
                        nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
532
                        if (nla_b == NULL) {
533
                                ret_val = -ENOMEM;
534
                                goto list_retry;
535
                        }
536
                        ret_val = nla_put_u32(ans_skb,
537
                                              NLBL_CIPSOV4_A_MLSLVLLOC,
538
                                              iter);
539
                        if (ret_val != 0)
540
                                goto list_retry;
541
                        ret_val = nla_put_u32(ans_skb,
542
                                            NLBL_CIPSOV4_A_MLSLVLREM,
543
                                            doi_def->map.std->lvl.local[iter]);
544
                        if (ret_val != 0)
545
                                goto list_retry;
546
                        nla_nest_end(ans_skb, nla_b);
547
                }
548
                nla_nest_end(ans_skb, nla_a);
549
 
550
                nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
551
                if (nla_a == NULL) {
552
                        ret_val = -ENOMEM;
553
                        goto list_retry;
554
                }
555
                for (iter = 0;
556
                     iter < doi_def->map.std->cat.local_size;
557
                     iter++) {
558
                        if (doi_def->map.std->cat.local[iter] ==
559
                            CIPSO_V4_INV_CAT)
560
                                continue;
561
 
562
                        nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
563
                        if (nla_b == NULL) {
564
                                ret_val = -ENOMEM;
565
                                goto list_retry;
566
                        }
567
                        ret_val = nla_put_u32(ans_skb,
568
                                              NLBL_CIPSOV4_A_MLSCATLOC,
569
                                              iter);
570
                        if (ret_val != 0)
571
                                goto list_retry;
572
                        ret_val = nla_put_u32(ans_skb,
573
                                            NLBL_CIPSOV4_A_MLSCATREM,
574
                                            doi_def->map.std->cat.local[iter]);
575
                        if (ret_val != 0)
576
                                goto list_retry;
577
                        nla_nest_end(ans_skb, nla_b);
578
                }
579
                nla_nest_end(ans_skb, nla_a);
580
 
581
                break;
582
        }
583
        rcu_read_unlock();
584
 
585
        genlmsg_end(ans_skb, data);
586
 
587
        ret_val = genlmsg_reply(ans_skb, info);
588
        if (ret_val != 0)
589
                goto list_failure;
590
 
591
        return 0;
592
 
593
list_retry:
594
        /* XXX - this limit is a guesstimate */
595
        if (nlsze_mult < 4) {
596
                rcu_read_unlock();
597
                kfree_skb(ans_skb);
598
                nlsze_mult++;
599
                goto list_start;
600
        }
601
list_failure_lock:
602
        rcu_read_unlock();
603
list_failure:
604
        kfree_skb(ans_skb);
605
        return ret_val;
606
}
607
 
608
/**
609
 * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
610
 * @doi_def: the CIPSOv4 DOI definition
611
 * @arg: the netlbl_cipsov4_doiwalk_arg structure
612
 *
613
 * Description:
614
 * This function is designed to be used as a callback to the
615
 * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
616
 * message.  Returns the size of the message on success, negative values on
617
 * failure.
618
 *
619
 */
620
static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
621
{
622
        int ret_val = -ENOMEM;
623
        struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
624
        void *data;
625
 
626
        data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
627
                           cb_arg->seq, &netlbl_cipsov4_gnl_family,
628
                           NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL);
629
        if (data == NULL)
630
                goto listall_cb_failure;
631
 
632
        ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
633
        if (ret_val != 0)
634
                goto listall_cb_failure;
635
        ret_val = nla_put_u32(cb_arg->skb,
636
                              NLBL_CIPSOV4_A_MTYPE,
637
                              doi_def->type);
638
        if (ret_val != 0)
639
                goto listall_cb_failure;
640
 
641
        return genlmsg_end(cb_arg->skb, data);
642
 
643
listall_cb_failure:
644
        genlmsg_cancel(cb_arg->skb, data);
645
        return ret_val;
646
}
647
 
648
/**
649
 * netlbl_cipsov4_listall - Handle a LISTALL message
650
 * @skb: the NETLINK buffer
651
 * @cb: the NETLINK callback
652
 *
653
 * Description:
654
 * Process a user generated LISTALL message and respond accordingly.  Returns
655
 * zero on success and negative values on error.
656
 *
657
 */
658
static int netlbl_cipsov4_listall(struct sk_buff *skb,
659
                                  struct netlink_callback *cb)
660
{
661
        struct netlbl_cipsov4_doiwalk_arg cb_arg;
662
        int doi_skip = cb->args[0];
663
 
664
        cb_arg.nl_cb = cb;
665
        cb_arg.skb = skb;
666
        cb_arg.seq = cb->nlh->nlmsg_seq;
667
 
668
        cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
669
 
670
        cb->args[0] = doi_skip;
671
        return skb->len;
672
}
673
 
674
/**
675
 * netlbl_cipsov4_remove - Handle a REMOVE message
676
 * @skb: the NETLINK buffer
677
 * @info: the Generic NETLINK info block
678
 *
679
 * Description:
680
 * Process a user generated REMOVE message and respond accordingly.  Returns
681
 * zero on success, negative values on failure.
682
 *
683
 */
684
static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
685
{
686
        int ret_val = -EINVAL;
687
        u32 doi = 0;
688
        struct audit_buffer *audit_buf;
689
        struct netlbl_audit audit_info;
690
 
691
        if (!info->attrs[NLBL_CIPSOV4_A_DOI])
692
                return -EINVAL;
693
 
694
        doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
695
        netlbl_netlink_auditinfo(skb, &audit_info);
696
 
697
        ret_val = cipso_v4_doi_remove(doi,
698
                                      &audit_info,
699
                                      netlbl_cipsov4_doi_free);
700
        if (ret_val == 0)
701
                netlbl_mgmt_protocount_dec();
702
 
703
        audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
704
                                              &audit_info);
705
        if (audit_buf != NULL) {
706
                audit_log_format(audit_buf,
707
                                 " cipso_doi=%u res=%u",
708
                                 doi,
709
                                 ret_val == 0 ? 1 : 0);
710
                audit_log_end(audit_buf);
711
        }
712
 
713
        return ret_val;
714
}
715
 
716
/*
717
 * NetLabel Generic NETLINK Command Definitions
718
 */
719
 
720
static struct genl_ops netlbl_cipsov4_genl_c_add = {
721
        .cmd = NLBL_CIPSOV4_C_ADD,
722
        .flags = GENL_ADMIN_PERM,
723
        .policy = netlbl_cipsov4_genl_policy,
724
        .doit = netlbl_cipsov4_add,
725
        .dumpit = NULL,
726
};
727
 
728
static struct genl_ops netlbl_cipsov4_genl_c_remove = {
729
        .cmd = NLBL_CIPSOV4_C_REMOVE,
730
        .flags = GENL_ADMIN_PERM,
731
        .policy = netlbl_cipsov4_genl_policy,
732
        .doit = netlbl_cipsov4_remove,
733
        .dumpit = NULL,
734
};
735
 
736
static struct genl_ops netlbl_cipsov4_genl_c_list = {
737
        .cmd = NLBL_CIPSOV4_C_LIST,
738
        .flags = 0,
739
        .policy = netlbl_cipsov4_genl_policy,
740
        .doit = netlbl_cipsov4_list,
741
        .dumpit = NULL,
742
};
743
 
744
static struct genl_ops netlbl_cipsov4_genl_c_listall = {
745
        .cmd = NLBL_CIPSOV4_C_LISTALL,
746
        .flags = 0,
747
        .policy = netlbl_cipsov4_genl_policy,
748
        .doit = NULL,
749
        .dumpit = netlbl_cipsov4_listall,
750
};
751
 
752
/*
753
 * NetLabel Generic NETLINK Protocol Functions
754
 */
755
 
756
/**
757
 * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component
758
 *
759
 * Description:
760
 * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK
761
 * mechanism.  Returns zero on success, negative values on failure.
762
 *
763
 */
764
int netlbl_cipsov4_genl_init(void)
765
{
766
        int ret_val;
767
 
768
        ret_val = genl_register_family(&netlbl_cipsov4_gnl_family);
769
        if (ret_val != 0)
770
                return ret_val;
771
 
772
        ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
773
                                    &netlbl_cipsov4_genl_c_add);
774
        if (ret_val != 0)
775
                return ret_val;
776
        ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
777
                                    &netlbl_cipsov4_genl_c_remove);
778
        if (ret_val != 0)
779
                return ret_val;
780
        ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
781
                                    &netlbl_cipsov4_genl_c_list);
782
        if (ret_val != 0)
783
                return ret_val;
784
        ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
785
                                    &netlbl_cipsov4_genl_c_listall);
786
        if (ret_val != 0)
787
                return ret_val;
788
 
789
        return 0;
790
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.