0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/types.h>
0017 #include <linux/socket.h>
0018 #include <linux/string.h>
0019 #include <linux/skbuff.h>
0020 #include <linux/audit.h>
0021 #include <linux/slab.h>
0022 #include <net/sock.h>
0023 #include <net/netlink.h>
0024 #include <net/genetlink.h>
0025 #include <net/netlabel.h>
0026 #include <net/cipso_ipv4.h>
0027 #include <linux/atomic.h>
0028
0029 #include "netlabel_user.h"
0030 #include "netlabel_cipso_v4.h"
0031 #include "netlabel_mgmt.h"
0032 #include "netlabel_domainhash.h"
0033
0034
0035 struct netlbl_cipsov4_doiwalk_arg {
0036 struct netlink_callback *nl_cb;
0037 struct sk_buff *skb;
0038 u32 seq;
0039 };
0040
0041
0042 struct netlbl_domhsh_walk_arg {
0043 struct netlbl_audit *audit_info;
0044 u32 doi;
0045 };
0046
0047
0048 static struct genl_family netlbl_cipsov4_gnl_family;
0049
0050 static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
0051 [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
0052 [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
0053 [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
0054 [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
0055 [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
0056 [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
0057 [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
0058 [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
0059 [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
0060 [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
0061 [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
0062 [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
0063 };
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 static int netlbl_cipsov4_add_common(struct genl_info *info,
0080 struct cipso_v4_doi *doi_def)
0081 {
0082 struct nlattr *nla;
0083 int nla_rem;
0084 u32 iter = 0;
0085
0086 doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
0087
0088 if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_TAGLST],
0089 NLBL_CIPSOV4_A_MAX,
0090 netlbl_cipsov4_genl_policy,
0091 NULL) != 0)
0092 return -EINVAL;
0093
0094 nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
0095 if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) {
0096 if (iter >= CIPSO_V4_TAG_MAXCNT)
0097 return -EINVAL;
0098 doi_def->tags[iter++] = nla_get_u8(nla);
0099 }
0100 while (iter < CIPSO_V4_TAG_MAXCNT)
0101 doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
0102
0103 return 0;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 static int netlbl_cipsov4_add_std(struct genl_info *info,
0122 struct netlbl_audit *audit_info)
0123 {
0124 int ret_val = -EINVAL;
0125 struct cipso_v4_doi *doi_def = NULL;
0126 struct nlattr *nla_a;
0127 struct nlattr *nla_b;
0128 int nla_a_rem;
0129 int nla_b_rem;
0130 u32 iter;
0131
0132 if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
0133 !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
0134 return -EINVAL;
0135
0136 if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
0137 NLBL_CIPSOV4_A_MAX,
0138 netlbl_cipsov4_genl_policy,
0139 NULL) != 0)
0140 return -EINVAL;
0141
0142 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
0143 if (doi_def == NULL)
0144 return -ENOMEM;
0145 doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
0146 if (doi_def->map.std == NULL) {
0147 kfree(doi_def);
0148 return -ENOMEM;
0149 }
0150 doi_def->type = CIPSO_V4_MAP_TRANS;
0151
0152 ret_val = netlbl_cipsov4_add_common(info, doi_def);
0153 if (ret_val != 0)
0154 goto add_std_failure;
0155 ret_val = -EINVAL;
0156
0157 nla_for_each_nested(nla_a,
0158 info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
0159 nla_a_rem)
0160 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
0161 if (nla_validate_nested_deprecated(nla_a,
0162 NLBL_CIPSOV4_A_MAX,
0163 netlbl_cipsov4_genl_policy,
0164 NULL) != 0)
0165 goto add_std_failure;
0166 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
0167 switch (nla_type(nla_b)) {
0168 case NLBL_CIPSOV4_A_MLSLVLLOC:
0169 if (nla_get_u32(nla_b) >
0170 CIPSO_V4_MAX_LOC_LVLS)
0171 goto add_std_failure;
0172 if (nla_get_u32(nla_b) >=
0173 doi_def->map.std->lvl.local_size)
0174 doi_def->map.std->lvl.local_size =
0175 nla_get_u32(nla_b) + 1;
0176 break;
0177 case NLBL_CIPSOV4_A_MLSLVLREM:
0178 if (nla_get_u32(nla_b) >
0179 CIPSO_V4_MAX_REM_LVLS)
0180 goto add_std_failure;
0181 if (nla_get_u32(nla_b) >=
0182 doi_def->map.std->lvl.cipso_size)
0183 doi_def->map.std->lvl.cipso_size =
0184 nla_get_u32(nla_b) + 1;
0185 break;
0186 }
0187 }
0188 doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
0189 sizeof(u32),
0190 GFP_KERNEL | __GFP_NOWARN);
0191 if (doi_def->map.std->lvl.local == NULL) {
0192 ret_val = -ENOMEM;
0193 goto add_std_failure;
0194 }
0195 doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
0196 sizeof(u32),
0197 GFP_KERNEL | __GFP_NOWARN);
0198 if (doi_def->map.std->lvl.cipso == NULL) {
0199 ret_val = -ENOMEM;
0200 goto add_std_failure;
0201 }
0202 for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
0203 doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
0204 for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
0205 doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
0206 nla_for_each_nested(nla_a,
0207 info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
0208 nla_a_rem)
0209 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
0210 struct nlattr *lvl_loc;
0211 struct nlattr *lvl_rem;
0212
0213 lvl_loc = nla_find_nested(nla_a,
0214 NLBL_CIPSOV4_A_MLSLVLLOC);
0215 lvl_rem = nla_find_nested(nla_a,
0216 NLBL_CIPSOV4_A_MLSLVLREM);
0217 if (lvl_loc == NULL || lvl_rem == NULL)
0218 goto add_std_failure;
0219 doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
0220 nla_get_u32(lvl_rem);
0221 doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
0222 nla_get_u32(lvl_loc);
0223 }
0224
0225 if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
0226 if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
0227 NLBL_CIPSOV4_A_MAX,
0228 netlbl_cipsov4_genl_policy,
0229 NULL) != 0)
0230 goto add_std_failure;
0231
0232 nla_for_each_nested(nla_a,
0233 info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
0234 nla_a_rem)
0235 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
0236 if (nla_validate_nested_deprecated(nla_a,
0237 NLBL_CIPSOV4_A_MAX,
0238 netlbl_cipsov4_genl_policy,
0239 NULL) != 0)
0240 goto add_std_failure;
0241 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
0242 switch (nla_type(nla_b)) {
0243 case NLBL_CIPSOV4_A_MLSCATLOC:
0244 if (nla_get_u32(nla_b) >
0245 CIPSO_V4_MAX_LOC_CATS)
0246 goto add_std_failure;
0247 if (nla_get_u32(nla_b) >=
0248 doi_def->map.std->cat.local_size)
0249 doi_def->map.std->cat.local_size =
0250 nla_get_u32(nla_b) + 1;
0251 break;
0252 case NLBL_CIPSOV4_A_MLSCATREM:
0253 if (nla_get_u32(nla_b) >
0254 CIPSO_V4_MAX_REM_CATS)
0255 goto add_std_failure;
0256 if (nla_get_u32(nla_b) >=
0257 doi_def->map.std->cat.cipso_size)
0258 doi_def->map.std->cat.cipso_size =
0259 nla_get_u32(nla_b) + 1;
0260 break;
0261 }
0262 }
0263 doi_def->map.std->cat.local = kcalloc(
0264 doi_def->map.std->cat.local_size,
0265 sizeof(u32),
0266 GFP_KERNEL | __GFP_NOWARN);
0267 if (doi_def->map.std->cat.local == NULL) {
0268 ret_val = -ENOMEM;
0269 goto add_std_failure;
0270 }
0271 doi_def->map.std->cat.cipso = kcalloc(
0272 doi_def->map.std->cat.cipso_size,
0273 sizeof(u32),
0274 GFP_KERNEL | __GFP_NOWARN);
0275 if (doi_def->map.std->cat.cipso == NULL) {
0276 ret_val = -ENOMEM;
0277 goto add_std_failure;
0278 }
0279 for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
0280 doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
0281 for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
0282 doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
0283 nla_for_each_nested(nla_a,
0284 info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
0285 nla_a_rem)
0286 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
0287 struct nlattr *cat_loc;
0288 struct nlattr *cat_rem;
0289
0290 cat_loc = nla_find_nested(nla_a,
0291 NLBL_CIPSOV4_A_MLSCATLOC);
0292 cat_rem = nla_find_nested(nla_a,
0293 NLBL_CIPSOV4_A_MLSCATREM);
0294 if (cat_loc == NULL || cat_rem == NULL)
0295 goto add_std_failure;
0296 doi_def->map.std->cat.local[
0297 nla_get_u32(cat_loc)] =
0298 nla_get_u32(cat_rem);
0299 doi_def->map.std->cat.cipso[
0300 nla_get_u32(cat_rem)] =
0301 nla_get_u32(cat_loc);
0302 }
0303 }
0304
0305 ret_val = cipso_v4_doi_add(doi_def, audit_info);
0306 if (ret_val != 0)
0307 goto add_std_failure;
0308 return 0;
0309
0310 add_std_failure:
0311 cipso_v4_doi_free(doi_def);
0312 return ret_val;
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326 static int netlbl_cipsov4_add_pass(struct genl_info *info,
0327 struct netlbl_audit *audit_info)
0328 {
0329 int ret_val;
0330 struct cipso_v4_doi *doi_def = NULL;
0331
0332 if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
0333 return -EINVAL;
0334
0335 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
0336 if (doi_def == NULL)
0337 return -ENOMEM;
0338 doi_def->type = CIPSO_V4_MAP_PASS;
0339
0340 ret_val = netlbl_cipsov4_add_common(info, doi_def);
0341 if (ret_val != 0)
0342 goto add_pass_failure;
0343
0344 ret_val = cipso_v4_doi_add(doi_def, audit_info);
0345 if (ret_val != 0)
0346 goto add_pass_failure;
0347 return 0;
0348
0349 add_pass_failure:
0350 cipso_v4_doi_free(doi_def);
0351 return ret_val;
0352 }
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 static int netlbl_cipsov4_add_local(struct genl_info *info,
0366 struct netlbl_audit *audit_info)
0367 {
0368 int ret_val;
0369 struct cipso_v4_doi *doi_def = NULL;
0370
0371 if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
0372 return -EINVAL;
0373
0374 doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
0375 if (doi_def == NULL)
0376 return -ENOMEM;
0377 doi_def->type = CIPSO_V4_MAP_LOCAL;
0378
0379 ret_val = netlbl_cipsov4_add_common(info, doi_def);
0380 if (ret_val != 0)
0381 goto add_local_failure;
0382
0383 ret_val = cipso_v4_doi_add(doi_def, audit_info);
0384 if (ret_val != 0)
0385 goto add_local_failure;
0386 return 0;
0387
0388 add_local_failure:
0389 cipso_v4_doi_free(doi_def);
0390 return ret_val;
0391 }
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403 static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
0404
0405 {
0406 int ret_val = -EINVAL;
0407 struct netlbl_audit audit_info;
0408
0409 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
0410 !info->attrs[NLBL_CIPSOV4_A_MTYPE])
0411 return -EINVAL;
0412
0413 netlbl_netlink_auditinfo(&audit_info);
0414 switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {
0415 case CIPSO_V4_MAP_TRANS:
0416 ret_val = netlbl_cipsov4_add_std(info, &audit_info);
0417 break;
0418 case CIPSO_V4_MAP_PASS:
0419 ret_val = netlbl_cipsov4_add_pass(info, &audit_info);
0420 break;
0421 case CIPSO_V4_MAP_LOCAL:
0422 ret_val = netlbl_cipsov4_add_local(info, &audit_info);
0423 break;
0424 }
0425 if (ret_val == 0)
0426 atomic_inc(&netlabel_mgmt_protocount);
0427
0428 return ret_val;
0429 }
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
0449 {
0450 int ret_val;
0451 struct sk_buff *ans_skb = NULL;
0452 u32 nlsze_mult = 1;
0453 void *data;
0454 u32 doi;
0455 struct nlattr *nla_a;
0456 struct nlattr *nla_b;
0457 struct cipso_v4_doi *doi_def;
0458 u32 iter;
0459
0460 if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
0461 ret_val = -EINVAL;
0462 goto list_failure;
0463 }
0464
0465 list_start:
0466 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
0467 if (ans_skb == NULL) {
0468 ret_val = -ENOMEM;
0469 goto list_failure;
0470 }
0471 data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family,
0472 0, NLBL_CIPSOV4_C_LIST);
0473 if (data == NULL) {
0474 ret_val = -ENOMEM;
0475 goto list_failure;
0476 }
0477
0478 doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
0479
0480 rcu_read_lock();
0481 doi_def = cipso_v4_doi_getdef(doi);
0482 if (doi_def == NULL) {
0483 ret_val = -EINVAL;
0484 goto list_failure_lock;
0485 }
0486
0487 ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
0488 if (ret_val != 0)
0489 goto list_failure_lock;
0490
0491 nla_a = nla_nest_start_noflag(ans_skb, NLBL_CIPSOV4_A_TAGLST);
0492 if (nla_a == NULL) {
0493 ret_val = -ENOMEM;
0494 goto list_failure_lock;
0495 }
0496 for (iter = 0;
0497 iter < CIPSO_V4_TAG_MAXCNT &&
0498 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
0499 iter++) {
0500 ret_val = nla_put_u8(ans_skb,
0501 NLBL_CIPSOV4_A_TAG,
0502 doi_def->tags[iter]);
0503 if (ret_val != 0)
0504 goto list_failure_lock;
0505 }
0506 nla_nest_end(ans_skb, nla_a);
0507
0508 switch (doi_def->type) {
0509 case CIPSO_V4_MAP_TRANS:
0510 nla_a = nla_nest_start_noflag(ans_skb,
0511 NLBL_CIPSOV4_A_MLSLVLLST);
0512 if (nla_a == NULL) {
0513 ret_val = -ENOMEM;
0514 goto list_failure_lock;
0515 }
0516 for (iter = 0;
0517 iter < doi_def->map.std->lvl.local_size;
0518 iter++) {
0519 if (doi_def->map.std->lvl.local[iter] ==
0520 CIPSO_V4_INV_LVL)
0521 continue;
0522
0523 nla_b = nla_nest_start_noflag(ans_skb,
0524 NLBL_CIPSOV4_A_MLSLVL);
0525 if (nla_b == NULL) {
0526 ret_val = -ENOMEM;
0527 goto list_retry;
0528 }
0529 ret_val = nla_put_u32(ans_skb,
0530 NLBL_CIPSOV4_A_MLSLVLLOC,
0531 iter);
0532 if (ret_val != 0)
0533 goto list_retry;
0534 ret_val = nla_put_u32(ans_skb,
0535 NLBL_CIPSOV4_A_MLSLVLREM,
0536 doi_def->map.std->lvl.local[iter]);
0537 if (ret_val != 0)
0538 goto list_retry;
0539 nla_nest_end(ans_skb, nla_b);
0540 }
0541 nla_nest_end(ans_skb, nla_a);
0542
0543 nla_a = nla_nest_start_noflag(ans_skb,
0544 NLBL_CIPSOV4_A_MLSCATLST);
0545 if (nla_a == NULL) {
0546 ret_val = -ENOMEM;
0547 goto list_retry;
0548 }
0549 for (iter = 0;
0550 iter < doi_def->map.std->cat.local_size;
0551 iter++) {
0552 if (doi_def->map.std->cat.local[iter] ==
0553 CIPSO_V4_INV_CAT)
0554 continue;
0555
0556 nla_b = nla_nest_start_noflag(ans_skb,
0557 NLBL_CIPSOV4_A_MLSCAT);
0558 if (nla_b == NULL) {
0559 ret_val = -ENOMEM;
0560 goto list_retry;
0561 }
0562 ret_val = nla_put_u32(ans_skb,
0563 NLBL_CIPSOV4_A_MLSCATLOC,
0564 iter);
0565 if (ret_val != 0)
0566 goto list_retry;
0567 ret_val = nla_put_u32(ans_skb,
0568 NLBL_CIPSOV4_A_MLSCATREM,
0569 doi_def->map.std->cat.local[iter]);
0570 if (ret_val != 0)
0571 goto list_retry;
0572 nla_nest_end(ans_skb, nla_b);
0573 }
0574 nla_nest_end(ans_skb, nla_a);
0575
0576 break;
0577 }
0578 cipso_v4_doi_putdef(doi_def);
0579 rcu_read_unlock();
0580
0581 genlmsg_end(ans_skb, data);
0582 return genlmsg_reply(ans_skb, info);
0583
0584 list_retry:
0585
0586 if (nlsze_mult < 4) {
0587 cipso_v4_doi_putdef(doi_def);
0588 rcu_read_unlock();
0589 kfree_skb(ans_skb);
0590 nlsze_mult *= 2;
0591 goto list_start;
0592 }
0593 list_failure_lock:
0594 cipso_v4_doi_putdef(doi_def);
0595 rcu_read_unlock();
0596 list_failure:
0597 kfree_skb(ans_skb);
0598 return ret_val;
0599 }
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613 static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
0614 {
0615 int ret_val = -ENOMEM;
0616 struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
0617 void *data;
0618
0619 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
0620 cb_arg->seq, &netlbl_cipsov4_gnl_family,
0621 NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL);
0622 if (data == NULL)
0623 goto listall_cb_failure;
0624
0625 ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
0626 if (ret_val != 0)
0627 goto listall_cb_failure;
0628 ret_val = nla_put_u32(cb_arg->skb,
0629 NLBL_CIPSOV4_A_MTYPE,
0630 doi_def->type);
0631 if (ret_val != 0)
0632 goto listall_cb_failure;
0633
0634 genlmsg_end(cb_arg->skb, data);
0635 return 0;
0636
0637 listall_cb_failure:
0638 genlmsg_cancel(cb_arg->skb, data);
0639 return ret_val;
0640 }
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652 static int netlbl_cipsov4_listall(struct sk_buff *skb,
0653 struct netlink_callback *cb)
0654 {
0655 struct netlbl_cipsov4_doiwalk_arg cb_arg;
0656 u32 doi_skip = cb->args[0];
0657
0658 cb_arg.nl_cb = cb;
0659 cb_arg.skb = skb;
0660 cb_arg.seq = cb->nlh->nlmsg_seq;
0661
0662 cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
0663
0664 cb->args[0] = doi_skip;
0665 return skb->len;
0666 }
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680 static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg)
0681 {
0682 struct netlbl_domhsh_walk_arg *cb_arg = arg;
0683
0684 if (entry->def.type == NETLBL_NLTYPE_CIPSOV4 &&
0685 entry->def.cipso->doi == cb_arg->doi)
0686 return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
0687
0688 return 0;
0689 }
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701 static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
0702 {
0703 int ret_val = -EINVAL;
0704 struct netlbl_domhsh_walk_arg cb_arg;
0705 struct netlbl_audit audit_info;
0706 u32 skip_bkt = 0;
0707 u32 skip_chain = 0;
0708
0709 if (!info->attrs[NLBL_CIPSOV4_A_DOI])
0710 return -EINVAL;
0711
0712 netlbl_netlink_auditinfo(&audit_info);
0713 cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
0714 cb_arg.audit_info = &audit_info;
0715 ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
0716 netlbl_cipsov4_remove_cb, &cb_arg);
0717 if (ret_val == 0 || ret_val == -ENOENT) {
0718 ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info);
0719 if (ret_val == 0)
0720 atomic_dec(&netlabel_mgmt_protocount);
0721 }
0722
0723 return ret_val;
0724 }
0725
0726
0727
0728
0729
0730 static const struct genl_small_ops netlbl_cipsov4_ops[] = {
0731 {
0732 .cmd = NLBL_CIPSOV4_C_ADD,
0733 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0734 .flags = GENL_ADMIN_PERM,
0735 .doit = netlbl_cipsov4_add,
0736 .dumpit = NULL,
0737 },
0738 {
0739 .cmd = NLBL_CIPSOV4_C_REMOVE,
0740 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0741 .flags = GENL_ADMIN_PERM,
0742 .doit = netlbl_cipsov4_remove,
0743 .dumpit = NULL,
0744 },
0745 {
0746 .cmd = NLBL_CIPSOV4_C_LIST,
0747 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0748 .flags = 0,
0749 .doit = netlbl_cipsov4_list,
0750 .dumpit = NULL,
0751 },
0752 {
0753 .cmd = NLBL_CIPSOV4_C_LISTALL,
0754 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0755 .flags = 0,
0756 .doit = NULL,
0757 .dumpit = netlbl_cipsov4_listall,
0758 },
0759 };
0760
0761 static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = {
0762 .hdrsize = 0,
0763 .name = NETLBL_NLTYPE_CIPSOV4_NAME,
0764 .version = NETLBL_PROTO_VERSION,
0765 .maxattr = NLBL_CIPSOV4_A_MAX,
0766 .policy = netlbl_cipsov4_genl_policy,
0767 .module = THIS_MODULE,
0768 .small_ops = netlbl_cipsov4_ops,
0769 .n_small_ops = ARRAY_SIZE(netlbl_cipsov4_ops),
0770 };
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784 int __init netlbl_cipsov4_genl_init(void)
0785 {
0786 return genl_register_family(&netlbl_cipsov4_gnl_family);
0787 }