This source file includes following definitions.
- netlbl_cipsov4_add_common
- netlbl_cipsov4_add_std
- netlbl_cipsov4_add_pass
- netlbl_cipsov4_add_local
- netlbl_cipsov4_add
- netlbl_cipsov4_list
- netlbl_cipsov4_listall_cb
- netlbl_cipsov4_listall
- netlbl_cipsov4_remove_cb
- netlbl_cipsov4_remove
- netlbl_cipsov4_genl_init
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 #include <linux/types.h>
  17 #include <linux/socket.h>
  18 #include <linux/string.h>
  19 #include <linux/skbuff.h>
  20 #include <linux/audit.h>
  21 #include <linux/slab.h>
  22 #include <net/sock.h>
  23 #include <net/netlink.h>
  24 #include <net/genetlink.h>
  25 #include <net/netlabel.h>
  26 #include <net/cipso_ipv4.h>
  27 #include <linux/atomic.h>
  28 
  29 #include "netlabel_user.h"
  30 #include "netlabel_cipso_v4.h"
  31 #include "netlabel_mgmt.h"
  32 #include "netlabel_domainhash.h"
  33 
  34 
  35 struct netlbl_cipsov4_doiwalk_arg {
  36         struct netlink_callback *nl_cb;
  37         struct sk_buff *skb;
  38         u32 seq;
  39 };
  40 
  41 
  42 struct netlbl_domhsh_walk_arg {
  43         struct netlbl_audit *audit_info;
  44         u32 doi;
  45 };
  46 
  47 
  48 static struct genl_family netlbl_cipsov4_gnl_family;
  49 
  50 static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
  51         [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
  52         [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
  53         [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
  54         [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
  55         [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
  56         [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
  57         [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
  58         [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
  59         [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
  60         [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
  61         [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
  62         [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
  63 };
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 static int netlbl_cipsov4_add_common(struct genl_info *info,
  80                                      struct cipso_v4_doi *doi_def)
  81 {
  82         struct nlattr *nla;
  83         int nla_rem;
  84         u32 iter = 0;
  85 
  86         doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
  87 
  88         if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_TAGLST],
  89                                            NLBL_CIPSOV4_A_MAX,
  90                                            netlbl_cipsov4_genl_policy,
  91                                            NULL) != 0)
  92                 return -EINVAL;
  93 
  94         nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
  95                 if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) {
  96                         if (iter >= CIPSO_V4_TAG_MAXCNT)
  97                                 return -EINVAL;
  98                         doi_def->tags[iter++] = nla_get_u8(nla);
  99                 }
 100         while (iter < CIPSO_V4_TAG_MAXCNT)
 101                 doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
 102 
 103         return 0;
 104 }
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 static int netlbl_cipsov4_add_std(struct genl_info *info,
 122                                   struct netlbl_audit *audit_info)
 123 {
 124         int ret_val = -EINVAL;
 125         struct cipso_v4_doi *doi_def = NULL;
 126         struct nlattr *nla_a;
 127         struct nlattr *nla_b;
 128         int nla_a_rem;
 129         int nla_b_rem;
 130         u32 iter;
 131 
 132         if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
 133             !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
 134                 return -EINVAL;
 135 
 136         if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
 137                                            NLBL_CIPSOV4_A_MAX,
 138                                            netlbl_cipsov4_genl_policy,
 139                                            NULL) != 0)
 140                 return -EINVAL;
 141 
 142         doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
 143         if (doi_def == NULL)
 144                 return -ENOMEM;
 145         doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
 146         if (doi_def->map.std == NULL) {
 147                 ret_val = -ENOMEM;
 148                 goto add_std_failure;
 149         }
 150         doi_def->type = CIPSO_V4_MAP_TRANS;
 151 
 152         ret_val = netlbl_cipsov4_add_common(info, doi_def);
 153         if (ret_val != 0)
 154                 goto add_std_failure;
 155         ret_val = -EINVAL;
 156 
 157         nla_for_each_nested(nla_a,
 158                             info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
 159                             nla_a_rem)
 160                 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
 161                         if (nla_validate_nested_deprecated(nla_a,
 162                                                            NLBL_CIPSOV4_A_MAX,
 163                                                            netlbl_cipsov4_genl_policy,
 164                                                            NULL) != 0)
 165                                 goto add_std_failure;
 166                         nla_for_each_nested(nla_b, nla_a, nla_b_rem)
 167                                 switch (nla_type(nla_b)) {
 168                                 case NLBL_CIPSOV4_A_MLSLVLLOC:
 169                                         if (nla_get_u32(nla_b) >
 170                                             CIPSO_V4_MAX_LOC_LVLS)
 171                                                 goto add_std_failure;
 172                                         if (nla_get_u32(nla_b) >=
 173                                             doi_def->map.std->lvl.local_size)
 174                                              doi_def->map.std->lvl.local_size =
 175                                                      nla_get_u32(nla_b) + 1;
 176                                         break;
 177                                 case NLBL_CIPSOV4_A_MLSLVLREM:
 178                                         if (nla_get_u32(nla_b) >
 179                                             CIPSO_V4_MAX_REM_LVLS)
 180                                                 goto add_std_failure;
 181                                         if (nla_get_u32(nla_b) >=
 182                                             doi_def->map.std->lvl.cipso_size)
 183                                              doi_def->map.std->lvl.cipso_size =
 184                                                      nla_get_u32(nla_b) + 1;
 185                                         break;
 186                                 }
 187                 }
 188         doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
 189                                               sizeof(u32),
 190                                               GFP_KERNEL);
 191         if (doi_def->map.std->lvl.local == NULL) {
 192                 ret_val = -ENOMEM;
 193                 goto add_std_failure;
 194         }
 195         doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
 196                                               sizeof(u32),
 197                                               GFP_KERNEL);
 198         if (doi_def->map.std->lvl.cipso == NULL) {
 199                 ret_val = -ENOMEM;
 200                 goto add_std_failure;
 201         }
 202         for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
 203                 doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
 204         for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
 205                 doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
 206         nla_for_each_nested(nla_a,
 207                             info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
 208                             nla_a_rem)
 209                 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
 210                         struct nlattr *lvl_loc;
 211                         struct nlattr *lvl_rem;
 212 
 213                         lvl_loc = nla_find_nested(nla_a,
 214                                                   NLBL_CIPSOV4_A_MLSLVLLOC);
 215                         lvl_rem = nla_find_nested(nla_a,
 216                                                   NLBL_CIPSOV4_A_MLSLVLREM);
 217                         if (lvl_loc == NULL || lvl_rem == NULL)
 218                                 goto add_std_failure;
 219                         doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
 220                                 nla_get_u32(lvl_rem);
 221                         doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
 222                                 nla_get_u32(lvl_loc);
 223                 }
 224 
 225         if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
 226                 if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
 227                                                    NLBL_CIPSOV4_A_MAX,
 228                                                    netlbl_cipsov4_genl_policy,
 229                                                    NULL) != 0)
 230                         goto add_std_failure;
 231 
 232                 nla_for_each_nested(nla_a,
 233                                     info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
 234                                     nla_a_rem)
 235                         if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
 236                                 if (nla_validate_nested_deprecated(nla_a,
 237                                                                    NLBL_CIPSOV4_A_MAX,
 238                                                                    netlbl_cipsov4_genl_policy,
 239                                                                    NULL) != 0)
 240                                         goto add_std_failure;
 241                                 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
 242                                         switch (nla_type(nla_b)) {
 243                                         case NLBL_CIPSOV4_A_MLSCATLOC:
 244                                                 if (nla_get_u32(nla_b) >
 245                                                     CIPSO_V4_MAX_LOC_CATS)
 246                                                         goto add_std_failure;
 247                                                 if (nla_get_u32(nla_b) >=
 248                                               doi_def->map.std->cat.local_size)
 249                                              doi_def->map.std->cat.local_size =
 250                                                      nla_get_u32(nla_b) + 1;
 251                                                 break;
 252                                         case NLBL_CIPSOV4_A_MLSCATREM:
 253                                                 if (nla_get_u32(nla_b) >
 254                                                     CIPSO_V4_MAX_REM_CATS)
 255                                                         goto add_std_failure;
 256                                                 if (nla_get_u32(nla_b) >=
 257                                               doi_def->map.std->cat.cipso_size)
 258                                              doi_def->map.std->cat.cipso_size =
 259                                                      nla_get_u32(nla_b) + 1;
 260                                                 break;
 261                                         }
 262                         }
 263                 doi_def->map.std->cat.local = kcalloc(
 264                                               doi_def->map.std->cat.local_size,
 265                                               sizeof(u32),
 266                                               GFP_KERNEL);
 267                 if (doi_def->map.std->cat.local == NULL) {
 268                         ret_val = -ENOMEM;
 269                         goto add_std_failure;
 270                 }
 271                 doi_def->map.std->cat.cipso = kcalloc(
 272                                               doi_def->map.std->cat.cipso_size,
 273                                               sizeof(u32),
 274                                               GFP_KERNEL);
 275                 if (doi_def->map.std->cat.cipso == NULL) {
 276                         ret_val = -ENOMEM;
 277                         goto add_std_failure;
 278                 }
 279                 for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
 280                         doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
 281                 for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
 282                         doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
 283                 nla_for_each_nested(nla_a,
 284                                     info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
 285                                     nla_a_rem)
 286                         if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
 287                                 struct nlattr *cat_loc;
 288                                 struct nlattr *cat_rem;
 289 
 290                                 cat_loc = nla_find_nested(nla_a,
 291                                                      NLBL_CIPSOV4_A_MLSCATLOC);
 292                                 cat_rem = nla_find_nested(nla_a,
 293                                                      NLBL_CIPSOV4_A_MLSCATREM);
 294                                 if (cat_loc == NULL || cat_rem == NULL)
 295                                         goto add_std_failure;
 296                                 doi_def->map.std->cat.local[
 297                                                         nla_get_u32(cat_loc)] =
 298                                         nla_get_u32(cat_rem);
 299                                 doi_def->map.std->cat.cipso[
 300                                                         nla_get_u32(cat_rem)] =
 301                                         nla_get_u32(cat_loc);
 302                         }
 303         }
 304 
 305         ret_val = cipso_v4_doi_add(doi_def, audit_info);
 306         if (ret_val != 0)
 307                 goto add_std_failure;
 308         return 0;
 309 
 310 add_std_failure:
 311         cipso_v4_doi_free(doi_def);
 312         return ret_val;
 313 }
 314 
 315 
 316 
 317 
 318 
 319 
 320 
 321 
 322 
 323 
 324 
 325 
 326 static int netlbl_cipsov4_add_pass(struct genl_info *info,
 327                                    struct netlbl_audit *audit_info)
 328 {
 329         int ret_val;
 330         struct cipso_v4_doi *doi_def = NULL;
 331 
 332         if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
 333                 return -EINVAL;
 334 
 335         doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
 336         if (doi_def == NULL)
 337                 return -ENOMEM;
 338         doi_def->type = CIPSO_V4_MAP_PASS;
 339 
 340         ret_val = netlbl_cipsov4_add_common(info, doi_def);
 341         if (ret_val != 0)
 342                 goto add_pass_failure;
 343 
 344         ret_val = cipso_v4_doi_add(doi_def, audit_info);
 345         if (ret_val != 0)
 346                 goto add_pass_failure;
 347         return 0;
 348 
 349 add_pass_failure:
 350         cipso_v4_doi_free(doi_def);
 351         return ret_val;
 352 }
 353 
 354 
 355 
 356 
 357 
 358 
 359 
 360 
 361 
 362 
 363 
 364 
 365 static int netlbl_cipsov4_add_local(struct genl_info *info,
 366                                     struct netlbl_audit *audit_info)
 367 {
 368         int ret_val;
 369         struct cipso_v4_doi *doi_def = NULL;
 370 
 371         if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
 372                 return -EINVAL;
 373 
 374         doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
 375         if (doi_def == NULL)
 376                 return -ENOMEM;
 377         doi_def->type = CIPSO_V4_MAP_LOCAL;
 378 
 379         ret_val = netlbl_cipsov4_add_common(info, doi_def);
 380         if (ret_val != 0)
 381                 goto add_local_failure;
 382 
 383         ret_val = cipso_v4_doi_add(doi_def, audit_info);
 384         if (ret_val != 0)
 385                 goto add_local_failure;
 386         return 0;
 387 
 388 add_local_failure:
 389         cipso_v4_doi_free(doi_def);
 390         return ret_val;
 391 }
 392 
 393 
 394 
 395 
 396 
 397 
 398 
 399 
 400 
 401 
 402 
 403 static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
 404 
 405 {
 406         int ret_val = -EINVAL;
 407         struct netlbl_audit audit_info;
 408 
 409         if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
 410             !info->attrs[NLBL_CIPSOV4_A_MTYPE])
 411                 return -EINVAL;
 412 
 413         netlbl_netlink_auditinfo(skb, &audit_info);
 414         switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {
 415         case CIPSO_V4_MAP_TRANS:
 416                 ret_val = netlbl_cipsov4_add_std(info, &audit_info);
 417                 break;
 418         case CIPSO_V4_MAP_PASS:
 419                 ret_val = netlbl_cipsov4_add_pass(info, &audit_info);
 420                 break;
 421         case CIPSO_V4_MAP_LOCAL:
 422                 ret_val = netlbl_cipsov4_add_local(info, &audit_info);
 423                 break;
 424         }
 425         if (ret_val == 0)
 426                 atomic_inc(&netlabel_mgmt_protocount);
 427 
 428         return ret_val;
 429 }
 430 
 431 
 432 
 433 
 434 
 435 
 436 
 437 
 438 
 439 
 440 
 441 
 442 
 443 
 444 
 445 
 446 
 447 
 448 static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
 449 {
 450         int ret_val;
 451         struct sk_buff *ans_skb = NULL;
 452         u32 nlsze_mult = 1;
 453         void *data;
 454         u32 doi;
 455         struct nlattr *nla_a;
 456         struct nlattr *nla_b;
 457         struct cipso_v4_doi *doi_def;
 458         u32 iter;
 459 
 460         if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
 461                 ret_val = -EINVAL;
 462                 goto list_failure;
 463         }
 464 
 465 list_start:
 466         ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
 467         if (ans_skb == NULL) {
 468                 ret_val = -ENOMEM;
 469                 goto list_failure;
 470         }
 471         data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family,
 472                                  0, NLBL_CIPSOV4_C_LIST);
 473         if (data == NULL) {
 474                 ret_val = -ENOMEM;
 475                 goto list_failure;
 476         }
 477 
 478         doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
 479 
 480         rcu_read_lock();
 481         doi_def = cipso_v4_doi_getdef(doi);
 482         if (doi_def == NULL) {
 483                 ret_val = -EINVAL;
 484                 goto list_failure_lock;
 485         }
 486 
 487         ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
 488         if (ret_val != 0)
 489                 goto list_failure_lock;
 490 
 491         nla_a = nla_nest_start_noflag(ans_skb, NLBL_CIPSOV4_A_TAGLST);
 492         if (nla_a == NULL) {
 493                 ret_val = -ENOMEM;
 494                 goto list_failure_lock;
 495         }
 496         for (iter = 0;
 497              iter < CIPSO_V4_TAG_MAXCNT &&
 498                doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
 499              iter++) {
 500                 ret_val = nla_put_u8(ans_skb,
 501                                      NLBL_CIPSOV4_A_TAG,
 502                                      doi_def->tags[iter]);
 503                 if (ret_val != 0)
 504                         goto list_failure_lock;
 505         }
 506         nla_nest_end(ans_skb, nla_a);
 507 
 508         switch (doi_def->type) {
 509         case CIPSO_V4_MAP_TRANS:
 510                 nla_a = nla_nest_start_noflag(ans_skb,
 511                                               NLBL_CIPSOV4_A_MLSLVLLST);
 512                 if (nla_a == NULL) {
 513                         ret_val = -ENOMEM;
 514                         goto list_failure_lock;
 515                 }
 516                 for (iter = 0;
 517                      iter < doi_def->map.std->lvl.local_size;
 518                      iter++) {
 519                         if (doi_def->map.std->lvl.local[iter] ==
 520                             CIPSO_V4_INV_LVL)
 521                                 continue;
 522 
 523                         nla_b = nla_nest_start_noflag(ans_skb,
 524                                                       NLBL_CIPSOV4_A_MLSLVL);
 525                         if (nla_b == NULL) {
 526                                 ret_val = -ENOMEM;
 527                                 goto list_retry;
 528                         }
 529                         ret_val = nla_put_u32(ans_skb,
 530                                               NLBL_CIPSOV4_A_MLSLVLLOC,
 531                                               iter);
 532                         if (ret_val != 0)
 533                                 goto list_retry;
 534                         ret_val = nla_put_u32(ans_skb,
 535                                             NLBL_CIPSOV4_A_MLSLVLREM,
 536                                             doi_def->map.std->lvl.local[iter]);
 537                         if (ret_val != 0)
 538                                 goto list_retry;
 539                         nla_nest_end(ans_skb, nla_b);
 540                 }
 541                 nla_nest_end(ans_skb, nla_a);
 542 
 543                 nla_a = nla_nest_start_noflag(ans_skb,
 544                                               NLBL_CIPSOV4_A_MLSCATLST);
 545                 if (nla_a == NULL) {
 546                         ret_val = -ENOMEM;
 547                         goto list_retry;
 548                 }
 549                 for (iter = 0;
 550                      iter < doi_def->map.std->cat.local_size;
 551                      iter++) {
 552                         if (doi_def->map.std->cat.local[iter] ==
 553                             CIPSO_V4_INV_CAT)
 554                                 continue;
 555 
 556                         nla_b = nla_nest_start_noflag(ans_skb,
 557                                                       NLBL_CIPSOV4_A_MLSCAT);
 558                         if (nla_b == NULL) {
 559                                 ret_val = -ENOMEM;
 560                                 goto list_retry;
 561                         }
 562                         ret_val = nla_put_u32(ans_skb,
 563                                               NLBL_CIPSOV4_A_MLSCATLOC,
 564                                               iter);
 565                         if (ret_val != 0)
 566                                 goto list_retry;
 567                         ret_val = nla_put_u32(ans_skb,
 568                                             NLBL_CIPSOV4_A_MLSCATREM,
 569                                             doi_def->map.std->cat.local[iter]);
 570                         if (ret_val != 0)
 571                                 goto list_retry;
 572                         nla_nest_end(ans_skb, nla_b);
 573                 }
 574                 nla_nest_end(ans_skb, nla_a);
 575 
 576                 break;
 577         }
 578         rcu_read_unlock();
 579 
 580         genlmsg_end(ans_skb, data);
 581         return genlmsg_reply(ans_skb, info);
 582 
 583 list_retry:
 584         
 585         if (nlsze_mult < 4) {
 586                 rcu_read_unlock();
 587                 kfree_skb(ans_skb);
 588                 nlsze_mult *= 2;
 589                 goto list_start;
 590         }
 591 list_failure_lock:
 592         rcu_read_unlock();
 593 list_failure:
 594         kfree_skb(ans_skb);
 595         return ret_val;
 596 }
 597 
 598 
 599 
 600 
 601 
 602 
 603 
 604 
 605 
 606 
 607 
 608 
 609 
 610 static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
 611 {
 612         int ret_val = -ENOMEM;
 613         struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
 614         void *data;
 615 
 616         data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
 617                            cb_arg->seq, &netlbl_cipsov4_gnl_family,
 618                            NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL);
 619         if (data == NULL)
 620                 goto listall_cb_failure;
 621 
 622         ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
 623         if (ret_val != 0)
 624                 goto listall_cb_failure;
 625         ret_val = nla_put_u32(cb_arg->skb,
 626                               NLBL_CIPSOV4_A_MTYPE,
 627                               doi_def->type);
 628         if (ret_val != 0)
 629                 goto listall_cb_failure;
 630 
 631         genlmsg_end(cb_arg->skb, data);
 632         return 0;
 633 
 634 listall_cb_failure:
 635         genlmsg_cancel(cb_arg->skb, data);
 636         return ret_val;
 637 }
 638 
 639 
 640 
 641 
 642 
 643 
 644 
 645 
 646 
 647 
 648 
 649 static int netlbl_cipsov4_listall(struct sk_buff *skb,
 650                                   struct netlink_callback *cb)
 651 {
 652         struct netlbl_cipsov4_doiwalk_arg cb_arg;
 653         u32 doi_skip = cb->args[0];
 654 
 655         cb_arg.nl_cb = cb;
 656         cb_arg.skb = skb;
 657         cb_arg.seq = cb->nlh->nlmsg_seq;
 658 
 659         cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
 660 
 661         cb->args[0] = doi_skip;
 662         return skb->len;
 663 }
 664 
 665 
 666 
 667 
 668 
 669 
 670 
 671 
 672 
 673 
 674 
 675 
 676 
 677 static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg)
 678 {
 679         struct netlbl_domhsh_walk_arg *cb_arg = arg;
 680 
 681         if (entry->def.type == NETLBL_NLTYPE_CIPSOV4 &&
 682             entry->def.cipso->doi == cb_arg->doi)
 683                 return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
 684 
 685         return 0;
 686 }
 687 
 688 
 689 
 690 
 691 
 692 
 693 
 694 
 695 
 696 
 697 
 698 static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
 699 {
 700         int ret_val = -EINVAL;
 701         struct netlbl_domhsh_walk_arg cb_arg;
 702         struct netlbl_audit audit_info;
 703         u32 skip_bkt = 0;
 704         u32 skip_chain = 0;
 705 
 706         if (!info->attrs[NLBL_CIPSOV4_A_DOI])
 707                 return -EINVAL;
 708 
 709         netlbl_netlink_auditinfo(skb, &audit_info);
 710         cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
 711         cb_arg.audit_info = &audit_info;
 712         ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
 713                                      netlbl_cipsov4_remove_cb, &cb_arg);
 714         if (ret_val == 0 || ret_val == -ENOENT) {
 715                 ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info);
 716                 if (ret_val == 0)
 717                         atomic_dec(&netlabel_mgmt_protocount);
 718         }
 719 
 720         return ret_val;
 721 }
 722 
 723 
 724 
 725 
 726 
 727 static const struct genl_ops netlbl_cipsov4_ops[] = {
 728         {
 729         .cmd = NLBL_CIPSOV4_C_ADD,
 730         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 731         .flags = GENL_ADMIN_PERM,
 732         .doit = netlbl_cipsov4_add,
 733         .dumpit = NULL,
 734         },
 735         {
 736         .cmd = NLBL_CIPSOV4_C_REMOVE,
 737         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 738         .flags = GENL_ADMIN_PERM,
 739         .doit = netlbl_cipsov4_remove,
 740         .dumpit = NULL,
 741         },
 742         {
 743         .cmd = NLBL_CIPSOV4_C_LIST,
 744         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 745         .flags = 0,
 746         .doit = netlbl_cipsov4_list,
 747         .dumpit = NULL,
 748         },
 749         {
 750         .cmd = NLBL_CIPSOV4_C_LISTALL,
 751         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 752         .flags = 0,
 753         .doit = NULL,
 754         .dumpit = netlbl_cipsov4_listall,
 755         },
 756 };
 757 
 758 static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = {
 759         .hdrsize = 0,
 760         .name = NETLBL_NLTYPE_CIPSOV4_NAME,
 761         .version = NETLBL_PROTO_VERSION,
 762         .maxattr = NLBL_CIPSOV4_A_MAX,
 763         .policy = netlbl_cipsov4_genl_policy,
 764         .module = THIS_MODULE,
 765         .ops = netlbl_cipsov4_ops,
 766         .n_ops = ARRAY_SIZE(netlbl_cipsov4_ops),
 767 };
 768 
 769 
 770 
 771 
 772 
 773 
 774 
 775 
 776 
 777 
 778 
 779 
 780 
 781 int __init netlbl_cipsov4_genl_init(void)
 782 {
 783         return genl_register_family(&netlbl_cipsov4_gnl_family);
 784 }