1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016 Intel Corporation 3 */ 4 5 /* 6 * Security Policies 7 */ 8 #include <sys/types.h> 9 #include <netinet/in.h> 10 #include <netinet/ip6.h> 11 12 #include <rte_acl.h> 13 #include <rte_ip.h> 14 15 #include "ipsec.h" 16 #include "parser.h" 17 18 #define MAX_ACL_RULE_NUM 1024 19 20 #define IPV6_FROM_SP(acr, fidx_low, fidx_high) \ 21 (((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \ 22 (acr).field[(fidx_low)].value.u32) 23 24 #define IPV6_DST_FROM_SP(addr, acr) do {\ 25 (addr).ip.ip6.ip6[0] = rte_cpu_to_be_64(IPV6_FROM_SP((acr), \ 26 IP6_DST1, IP6_DST0));\ 27 (addr).ip.ip6.ip6[1] = rte_cpu_to_be_64(IPV6_FROM_SP((acr), \ 28 IP6_DST3, IP6_DST2));\ 29 } while (0) 30 31 #define IPV6_SRC_FROM_SP(addr, acr) do {\ 32 (addr).ip.ip6.ip6[0] = rte_cpu_to_be_64(IPV6_FROM_SP((acr), \ 33 IP6_SRC1, IP6_SRC0));\ 34 (addr).ip.ip6.ip6[1] = rte_cpu_to_be_64(IPV6_FROM_SP((acr), \ 35 IP6_SRC3, IP6_SRC2));\ 36 } while (0) 37 38 #define IPV6_DST_MASK_FROM_SP(mask, acr) \ 39 ((mask) = (acr).field[IP6_DST0].mask_range.u32 + \ 40 (acr).field[IP6_DST1].mask_range.u32 + \ 41 (acr).field[IP6_DST2].mask_range.u32 + \ 42 (acr).field[IP6_DST3].mask_range.u32) 43 44 #define IPV6_SRC_MASK_FROM_SP(mask, acr) \ 45 ((mask) = (acr).field[IP6_SRC0].mask_range.u32 + \ 46 (acr).field[IP6_SRC1].mask_range.u32 + \ 47 (acr).field[IP6_SRC2].mask_range.u32 + \ 48 (acr).field[IP6_SRC3].mask_range.u32) 49 50 enum { 51 IP6_PROTO, 52 IP6_SRC0, 53 IP6_SRC1, 54 IP6_SRC2, 55 IP6_SRC3, 56 IP6_DST0, 57 IP6_DST1, 58 IP6_DST2, 59 IP6_DST3, 60 IP6_SRCP, 61 IP6_DSTP, 62 IP6_NUM 63 }; 64 65 #define IP6_ADDR_SIZE 16 66 67 static struct rte_acl_field_def ip6_defs[IP6_NUM] = { 68 { 69 .type = RTE_ACL_FIELD_TYPE_BITMASK, 70 .size = sizeof(uint8_t), 71 .field_index = IP6_PROTO, 72 .input_index = IP6_PROTO, 73 .offset = 0, 74 }, 75 { 76 .type = RTE_ACL_FIELD_TYPE_MASK, 77 .size = 4, 78 .field_index = IP6_SRC0, 79 .input_index = IP6_SRC0, 80 .offset = 2 81 }, 82 { 83 .type = RTE_ACL_FIELD_TYPE_MASK, 84 .size = 4, 85 .field_index = IP6_SRC1, 86 .input_index = IP6_SRC1, 87 .offset = 6 88 }, 89 { 90 .type = RTE_ACL_FIELD_TYPE_MASK, 91 .size = 4, 92 .field_index = IP6_SRC2, 93 .input_index = IP6_SRC2, 94 .offset = 10 95 }, 96 { 97 .type = RTE_ACL_FIELD_TYPE_MASK, 98 .size = 4, 99 .field_index = IP6_SRC3, 100 .input_index = IP6_SRC3, 101 .offset = 14 102 }, 103 { 104 .type = RTE_ACL_FIELD_TYPE_MASK, 105 .size = 4, 106 .field_index = IP6_DST0, 107 .input_index = IP6_DST0, 108 .offset = 18 109 }, 110 { 111 .type = RTE_ACL_FIELD_TYPE_MASK, 112 .size = 4, 113 .field_index = IP6_DST1, 114 .input_index = IP6_DST1, 115 .offset = 22 116 }, 117 { 118 .type = RTE_ACL_FIELD_TYPE_MASK, 119 .size = 4, 120 .field_index = IP6_DST2, 121 .input_index = IP6_DST2, 122 .offset = 26 123 }, 124 { 125 .type = RTE_ACL_FIELD_TYPE_MASK, 126 .size = 4, 127 .field_index = IP6_DST3, 128 .input_index = IP6_DST3, 129 .offset = 30 130 }, 131 { 132 .type = RTE_ACL_FIELD_TYPE_RANGE, 133 .size = sizeof(uint16_t), 134 .field_index = IP6_SRCP, 135 .input_index = IP6_SRCP, 136 .offset = 34 137 }, 138 { 139 .type = RTE_ACL_FIELD_TYPE_RANGE, 140 .size = sizeof(uint16_t), 141 .field_index = IP6_DSTP, 142 .input_index = IP6_SRCP, 143 .offset = 36 144 } 145 }; 146 147 RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs)); 148 149 static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM]; 150 static uint32_t nb_acl6_rules_out; 151 152 static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM]; 153 static uint32_t nb_acl6_rules_in; 154 155 void 156 parse_sp6_tokens(char **tokens, uint32_t n_tokens, 157 struct parse_status *status) 158 { 159 struct acl6_rules *rule_ipv6 = NULL; 160 161 uint32_t *ri = NULL; /* rule index */ 162 uint32_t ti = 0; /* token index */ 163 uint32_t tv; 164 165 uint32_t esp_p = 0; 166 uint32_t protect_p = 0; 167 uint32_t bypass_p = 0; 168 uint32_t discard_p = 0; 169 uint32_t pri_p = 0; 170 uint32_t src_p = 0; 171 uint32_t dst_p = 0; 172 uint32_t proto_p = 0; 173 uint32_t sport_p = 0; 174 uint32_t dport_p = 0; 175 176 if (strcmp(tokens[1], "in") == 0) { 177 ri = &nb_acl6_rules_in; 178 179 APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " 180 "many sp rules, abort insertion\n"); 181 if (status->status < 0) 182 return; 183 184 rule_ipv6 = &acl6_rules_in[*ri]; 185 186 } else if (strcmp(tokens[1], "out") == 0) { 187 ri = &nb_acl6_rules_out; 188 189 APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " 190 "many sp rules, abort insertion\n"); 191 if (status->status < 0) 192 return; 193 194 rule_ipv6 = &acl6_rules_out[*ri]; 195 196 } else { 197 APP_CHECK(0, status, "unrecognized input \"%s\", expect" 198 " \"in\" or \"out\"\n", tokens[ti]); 199 return; 200 } 201 202 rule_ipv6->data.category_mask = 1; 203 204 205 for (ti = 2; ti < n_tokens; ti++) { 206 if (strcmp(tokens[ti], "esp") == 0) { 207 /* currently do nothing */ 208 APP_CHECK_PRESENCE(esp_p, tokens[ti], status); 209 if (status->status < 0) 210 return; 211 esp_p = 1; 212 continue; 213 } 214 215 if (strcmp(tokens[ti], "protect") == 0) { 216 APP_CHECK_PRESENCE(protect_p, tokens[ti], status); 217 if (status->status < 0) 218 return; 219 APP_CHECK(bypass_p == 0, status, "conflict item " 220 "between \"%s\" and \"%s\"", tokens[ti], 221 "bypass"); 222 if (status->status < 0) 223 return; 224 APP_CHECK(discard_p == 0, status, "conflict item " 225 "between \"%s\" and \"%s\"", tokens[ti], 226 "discard"); 227 if (status->status < 0) 228 return; 229 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 230 if (status->status < 0) 231 return; 232 APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 233 if (status->status < 0) 234 return; 235 236 tv = atoi(tokens[ti]); 237 APP_CHECK(tv != DISCARD && tv != BYPASS, status, 238 "invalid SPI: %s", tokens[ti]); 239 if (status->status < 0) 240 return; 241 rule_ipv6->data.userdata = tv; 242 243 protect_p = 1; 244 continue; 245 } 246 247 if (strcmp(tokens[ti], "bypass") == 0) { 248 APP_CHECK_PRESENCE(bypass_p, tokens[ti], status); 249 if (status->status < 0) 250 return; 251 APP_CHECK(protect_p == 0, status, "conflict item " 252 "between \"%s\" and \"%s\"", tokens[ti], 253 "protect"); 254 if (status->status < 0) 255 return; 256 APP_CHECK(discard_p == 0, status, "conflict item " 257 "between \"%s\" and \"%s\"", tokens[ti], 258 "discard"); 259 if (status->status < 0) 260 return; 261 262 rule_ipv6->data.userdata = BYPASS; 263 264 bypass_p = 1; 265 continue; 266 } 267 268 if (strcmp(tokens[ti], "discard") == 0) { 269 APP_CHECK_PRESENCE(discard_p, tokens[ti], status); 270 if (status->status < 0) 271 return; 272 APP_CHECK(protect_p == 0, status, "conflict item " 273 "between \"%s\" and \"%s\"", tokens[ti], 274 "protect"); 275 if (status->status < 0) 276 return; 277 APP_CHECK(bypass_p == 0, status, "conflict item " 278 "between \"%s\" and \"%s\"", tokens[ti], 279 "discard"); 280 if (status->status < 0) 281 return; 282 283 rule_ipv6->data.userdata = DISCARD; 284 285 discard_p = 1; 286 continue; 287 } 288 289 if (strcmp(tokens[ti], "pri") == 0) { 290 APP_CHECK_PRESENCE(pri_p, tokens[ti], status); 291 if (status->status < 0) 292 return; 293 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 294 if (status->status < 0) 295 return; 296 APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); 297 if (status->status < 0) 298 return; 299 300 rule_ipv6->data.priority = atoi(tokens[ti]); 301 302 pri_p = 1; 303 continue; 304 } 305 306 if (strcmp(tokens[ti], "src") == 0) { 307 struct in6_addr ip; 308 uint32_t depth; 309 310 APP_CHECK_PRESENCE(src_p, tokens[ti], status); 311 if (status->status < 0) 312 return; 313 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 314 if (status->status < 0) 315 return; 316 317 APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 318 &depth) == 0, status, "unrecognized " 319 "input \"%s\", expect valid ipv6 " 320 "addr", tokens[ti]); 321 if (status->status < 0) 322 return; 323 324 rule_ipv6->field[1].value.u32 = 325 (uint32_t)ip.s6_addr[0] << 24 | 326 (uint32_t)ip.s6_addr[1] << 16 | 327 (uint32_t)ip.s6_addr[2] << 8 | 328 (uint32_t)ip.s6_addr[3]; 329 rule_ipv6->field[1].mask_range.u32 = 330 (depth > 32) ? 32 : depth; 331 depth = (depth > 32) ? (depth - 32) : 0; 332 rule_ipv6->field[2].value.u32 = 333 (uint32_t)ip.s6_addr[4] << 24 | 334 (uint32_t)ip.s6_addr[5] << 16 | 335 (uint32_t)ip.s6_addr[6] << 8 | 336 (uint32_t)ip.s6_addr[7]; 337 rule_ipv6->field[2].mask_range.u32 = 338 (depth > 32) ? 32 : depth; 339 depth = (depth > 32) ? (depth - 32) : 0; 340 rule_ipv6->field[3].value.u32 = 341 (uint32_t)ip.s6_addr[8] << 24 | 342 (uint32_t)ip.s6_addr[9] << 16 | 343 (uint32_t)ip.s6_addr[10] << 8 | 344 (uint32_t)ip.s6_addr[11]; 345 rule_ipv6->field[3].mask_range.u32 = 346 (depth > 32) ? 32 : depth; 347 depth = (depth > 32) ? (depth - 32) : 0; 348 rule_ipv6->field[4].value.u32 = 349 (uint32_t)ip.s6_addr[12] << 24 | 350 (uint32_t)ip.s6_addr[13] << 16 | 351 (uint32_t)ip.s6_addr[14] << 8 | 352 (uint32_t)ip.s6_addr[15]; 353 rule_ipv6->field[4].mask_range.u32 = 354 (depth > 32) ? 32 : depth; 355 356 src_p = 1; 357 continue; 358 } 359 360 if (strcmp(tokens[ti], "dst") == 0) { 361 struct in6_addr ip; 362 uint32_t depth; 363 364 APP_CHECK_PRESENCE(dst_p, tokens[ti], status); 365 if (status->status < 0) 366 return; 367 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 368 if (status->status < 0) 369 return; 370 371 APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 372 &depth) == 0, status, "unrecognized " 373 "input \"%s\", expect valid ipv6 " 374 "addr", tokens[ti]); 375 if (status->status < 0) 376 return; 377 378 rule_ipv6->field[5].value.u32 = 379 (uint32_t)ip.s6_addr[0] << 24 | 380 (uint32_t)ip.s6_addr[1] << 16 | 381 (uint32_t)ip.s6_addr[2] << 8 | 382 (uint32_t)ip.s6_addr[3]; 383 rule_ipv6->field[5].mask_range.u32 = 384 (depth > 32) ? 32 : depth; 385 depth = (depth > 32) ? (depth - 32) : 0; 386 rule_ipv6->field[6].value.u32 = 387 (uint32_t)ip.s6_addr[4] << 24 | 388 (uint32_t)ip.s6_addr[5] << 16 | 389 (uint32_t)ip.s6_addr[6] << 8 | 390 (uint32_t)ip.s6_addr[7]; 391 rule_ipv6->field[6].mask_range.u32 = 392 (depth > 32) ? 32 : depth; 393 depth = (depth > 32) ? (depth - 32) : 0; 394 rule_ipv6->field[7].value.u32 = 395 (uint32_t)ip.s6_addr[8] << 24 | 396 (uint32_t)ip.s6_addr[9] << 16 | 397 (uint32_t)ip.s6_addr[10] << 8 | 398 (uint32_t)ip.s6_addr[11]; 399 rule_ipv6->field[7].mask_range.u32 = 400 (depth > 32) ? 32 : depth; 401 depth = (depth > 32) ? (depth - 32) : 0; 402 rule_ipv6->field[8].value.u32 = 403 (uint32_t)ip.s6_addr[12] << 24 | 404 (uint32_t)ip.s6_addr[13] << 16 | 405 (uint32_t)ip.s6_addr[14] << 8 | 406 (uint32_t)ip.s6_addr[15]; 407 rule_ipv6->field[8].mask_range.u32 = 408 (depth > 32) ? 32 : depth; 409 410 dst_p = 1; 411 continue; 412 } 413 414 if (strcmp(tokens[ti], "proto") == 0) { 415 uint16_t low, high; 416 417 APP_CHECK_PRESENCE(proto_p, tokens[ti], status); 418 if (status->status < 0) 419 return; 420 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 421 if (status->status < 0) 422 return; 423 424 APP_CHECK(parse_range(tokens[ti], &low, &high) 425 == 0, status, "unrecognized input \"%s\"" 426 ", expect \"from:to\"", tokens[ti]); 427 if (status->status < 0) 428 return; 429 APP_CHECK(low <= 0xff, status, "proto low " 430 "over-limit"); 431 if (status->status < 0) 432 return; 433 APP_CHECK(high <= 0xff, status, "proto high " 434 "over-limit"); 435 if (status->status < 0) 436 return; 437 438 rule_ipv6->field[0].value.u8 = (uint8_t)low; 439 rule_ipv6->field[0].mask_range.u8 = (uint8_t)high; 440 441 proto_p = 1; 442 continue; 443 } 444 445 if (strcmp(tokens[ti], "sport") == 0) { 446 uint16_t port_low, port_high; 447 448 APP_CHECK_PRESENCE(sport_p, tokens[ti], status); 449 if (status->status < 0) 450 return; 451 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 452 if (status->status < 0) 453 return; 454 455 APP_CHECK(parse_range(tokens[ti], &port_low, 456 &port_high) == 0, status, "unrecognized " 457 "input \"%s\", expect \"port_from:" 458 "port_to\"", tokens[ti]); 459 if (status->status < 0) 460 return; 461 462 rule_ipv6->field[9].value.u16 = port_low; 463 rule_ipv6->field[9].mask_range.u16 = port_high; 464 465 sport_p = 1; 466 continue; 467 } 468 469 if (strcmp(tokens[ti], "dport") == 0) { 470 uint16_t port_low, port_high; 471 472 APP_CHECK_PRESENCE(dport_p, tokens[ti], status); 473 if (status->status < 0) 474 return; 475 INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 476 if (status->status < 0) 477 return; 478 479 APP_CHECK(parse_range(tokens[ti], &port_low, 480 &port_high) == 0, status, "unrecognized " 481 "input \"%s\", expect \"port_from:" 482 "port_to\"", tokens[ti]); 483 if (status->status < 0) 484 return; 485 486 rule_ipv6->field[10].value.u16 = port_low; 487 rule_ipv6->field[10].mask_range.u16 = port_high; 488 489 dport_p = 1; 490 continue; 491 } 492 493 /* unrecognizeable input */ 494 APP_CHECK(0, status, "unrecognized input \"%s\"", 495 tokens[ti]); 496 return; 497 } 498 499 /* check if argument(s) are missing */ 500 APP_CHECK(esp_p == 1, status, "missing argument \"esp\""); 501 if (status->status < 0) 502 return; 503 504 APP_CHECK(protect_p | bypass_p | discard_p, status, "missing " 505 "argument \"protect\", \"bypass\", or \"discard\""); 506 if (status->status < 0) 507 return; 508 509 *ri = *ri + 1; 510 } 511 512 static inline void 513 print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra) 514 { 515 uint8_t a, b, c, d; 516 517 uint32_t_to_char(rule->field[IP6_SRC0].value.u32, 518 &a, &b, &c, &d); 519 printf("%.2x%.2x:%.2x%.2x", a, b, c, d); 520 uint32_t_to_char(rule->field[IP6_SRC1].value.u32, 521 &a, &b, &c, &d); 522 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 523 uint32_t_to_char(rule->field[IP6_SRC2].value.u32, 524 &a, &b, &c, &d); 525 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 526 uint32_t_to_char(rule->field[IP6_SRC3].value.u32, 527 &a, &b, &c, &d); 528 printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, 529 rule->field[IP6_SRC0].mask_range.u32 530 + rule->field[IP6_SRC1].mask_range.u32 531 + rule->field[IP6_SRC2].mask_range.u32 532 + rule->field[IP6_SRC3].mask_range.u32); 533 534 uint32_t_to_char(rule->field[IP6_DST0].value.u32, 535 &a, &b, &c, &d); 536 printf("%.2x%.2x:%.2x%.2x", a, b, c, d); 537 uint32_t_to_char(rule->field[IP6_DST1].value.u32, 538 &a, &b, &c, &d); 539 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 540 uint32_t_to_char(rule->field[IP6_DST2].value.u32, 541 &a, &b, &c, &d); 542 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 543 uint32_t_to_char(rule->field[IP6_DST3].value.u32, 544 &a, &b, &c, &d); 545 printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, 546 rule->field[IP6_DST0].mask_range.u32 547 + rule->field[IP6_DST1].mask_range.u32 548 + rule->field[IP6_DST2].mask_range.u32 549 + rule->field[IP6_DST3].mask_range.u32); 550 551 printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", 552 rule->field[IP6_SRCP].value.u16, 553 rule->field[IP6_SRCP].mask_range.u16, 554 rule->field[IP6_DSTP].value.u16, 555 rule->field[IP6_DSTP].mask_range.u16, 556 rule->field[IP6_PROTO].value.u8, 557 rule->field[IP6_PROTO].mask_range.u8); 558 if (extra) 559 printf("0x%x-0x%x-0x%x ", 560 rule->data.category_mask, 561 rule->data.priority, 562 rule->data.userdata); 563 } 564 565 static inline void 566 dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra) 567 { 568 int32_t i; 569 570 for (i = 0; i < num; i++, rule++) { 571 printf("\t%d:", i + 1); 572 print_one_ip6_rule(rule, extra); 573 printf("\n"); 574 } 575 } 576 577 static struct rte_acl_ctx * 578 acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules, 579 uint32_t rules_nb) 580 { 581 char s[PATH_MAX]; 582 struct rte_acl_param acl_param; 583 struct rte_acl_config acl_build_param; 584 struct rte_acl_ctx *ctx; 585 586 printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM); 587 588 memset(&acl_param, 0, sizeof(acl_param)); 589 590 /* Create ACL contexts */ 591 snprintf(s, sizeof(s), "%s_%d", name, socketid); 592 593 printf("IPv4 %s entries [%u]:\n", s, rules_nb); 594 dump_ip6_rules(rules, rules_nb, 1); 595 596 acl_param.name = s; 597 acl_param.socket_id = socketid; 598 acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs)); 599 acl_param.max_rule_num = MAX_ACL_RULE_NUM; 600 601 ctx = rte_acl_create(&acl_param); 602 if (ctx == NULL) 603 rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); 604 605 if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules, 606 rules_nb) < 0) 607 rte_exit(EXIT_FAILURE, "add rules failed\n"); 608 609 /* Perform builds */ 610 memset(&acl_build_param, 0, sizeof(acl_build_param)); 611 612 acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; 613 acl_build_param.num_fields = RTE_DIM(ip6_defs); 614 memcpy(&acl_build_param.defs, ip6_defs, sizeof(ip6_defs)); 615 616 if (rte_acl_build(ctx, &acl_build_param) != 0) 617 rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); 618 619 rte_acl_dump(ctx); 620 621 return ctx; 622 } 623 624 /* 625 * check that for each rule it's SPI has a correspondent entry in SAD 626 */ 627 static int 628 check_spi_value(int inbound) 629 { 630 uint32_t i, num, spi; 631 const struct acl6_rules *acr; 632 633 if (inbound != 0) { 634 acr = acl6_rules_in; 635 num = nb_acl6_rules_in; 636 } else { 637 acr = acl6_rules_out; 638 num = nb_acl6_rules_out; 639 } 640 641 for (i = 0; i != num; i++) { 642 spi = acr[i].data.userdata; 643 if (spi != DISCARD && spi != BYPASS && 644 sa_spi_present(spi, inbound) < 0) { 645 RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n", 646 spi); 647 return -ENOENT; 648 } 649 } 650 651 return 0; 652 } 653 654 void 655 sp6_init(struct socket_ctx *ctx, int32_t socket_id) 656 { 657 const char *name; 658 659 if (ctx == NULL) 660 rte_exit(EXIT_FAILURE, "NULL context.\n"); 661 662 if (ctx->sp_ip6_in != NULL) 663 rte_exit(EXIT_FAILURE, "Inbound IPv6 SP DB for socket %u " 664 "already initialized\n", socket_id); 665 666 if (ctx->sp_ip6_out != NULL) 667 rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u " 668 "already initialized\n", socket_id); 669 670 if (check_spi_value(1) < 0) 671 rte_exit(EXIT_FAILURE, 672 "Inbound IPv6 SP DB has unmatched in SAD SPIs\n"); 673 674 if (check_spi_value(0) < 0) 675 rte_exit(EXIT_FAILURE, 676 "Outbound IPv6 SP DB has unmatched in SAD SPIs\n"); 677 678 if (nb_acl6_rules_in > 0) { 679 name = "sp_ip6_in"; 680 ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, 681 socket_id, acl6_rules_in, nb_acl6_rules_in); 682 } else 683 RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule " 684 "specified\n"); 685 686 if (nb_acl6_rules_out > 0) { 687 name = "sp_ip6_out"; 688 ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, 689 socket_id, acl6_rules_out, nb_acl6_rules_out); 690 } else 691 RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule " 692 "specified\n"); 693 } 694 695 /* 696 * Search though SP rules for given SPI. 697 */ 698 int 699 sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], 700 uint32_t mask[2]) 701 { 702 uint32_t i, num; 703 const struct acl6_rules *acr; 704 705 if (inbound != 0) { 706 acr = acl6_rules_in; 707 num = nb_acl6_rules_in; 708 } else { 709 acr = acl6_rules_out; 710 num = nb_acl6_rules_out; 711 } 712 713 for (i = 0; i != num; i++) { 714 if (acr[i].data.userdata == spi) { 715 if (NULL != ip_addr && NULL != mask) { 716 IPV6_SRC_FROM_SP(ip_addr[0], acr[i]); 717 IPV6_DST_FROM_SP(ip_addr[1], acr[i]); 718 IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]); 719 IPV6_DST_MASK_FROM_SP(mask[1], acr[i]); 720 } 721 return i; 722 } 723 } 724 725 return -ENOENT; 726 } 727