acl.c (23904B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Access Control Lists (ACL) related CLI commands. 8 */ 9 10 #include <shared/bsl.h> 11 #include <appl/diag/shell.h> 12 #include <appl/diag/system.h> 13 #include <appl/diag/parse.h> 14 #include <appl/acl/acl.h> 15 #include <appl/diag/diag.h> 16 #include "../../acl/acl_util.h" 17 18 #include <bcmx/lplist.h> 19 #include <bcmx/lport.h> 20 #include <bcmx/port.h> 21 #include <bcm/error.h> 22 23 #include "bcmx.h" 24 25 #if defined(INCLUDE_ACL) 26 27 #define BCMA_ACL_NUMB_LISTS 16 /* Max. number of lists in diag. code. */ 28 #define BCMA_ACL_NUMB_RULES 16 /* Max. number of rules in each list. */ 29 30 /* 31 * Macro: 32 * ACL_CHECK_RETURN 33 * Purpose: 34 * Check the return value from an API call. Output either a failed 35 * message or okay along with the function name. 36 */ 37 #define ACL_CHECK_RETURN(retval, funct_name) \ 38 if ((retval) != BCM_E_NONE) { \ 39 cli_out("%s() failed: %s\n", (funct_name), bcm_errmsg(retval)); \ 40 return CMD_FAIL; \ 41 } \ 42 cli_out("%s() okay\n", (funct_name)); 43 44 /* 45 * Macro: 46 * ACL_GET_NUMB 47 * Purpose: 48 * Get a numerical value from stdin. 49 */ 50 #define ACL_GET_NUMB(numb, str, args) \ 51 if (((str) = ARG_GET(args)) == NULL) { \ 52 return CMD_USAGE; \ 53 } \ 54 (numb) = parse_integer(str); 55 56 /* 57 * Macro: 58 * ACL_GET_PORT 59 * Purpose: 60 * Get a numerical value from stdin. 61 */ 62 #define ACL_GET_PORT(_unit, _port, _str, _args) \ 63 if (((_str) = ARG_GET(_args)) == NULL) { \ 64 return CMD_USAGE; \ 65 } \ 66 if (parse_port((_unit), (_str), &(_port)) < 0) { \ 67 ACL_ERR(("ERROR: invalid port string: \"%s\"\n", (_str))); \ 68 return CMD_FAIL; \ 69 } 70 71 #define MAC_IS_CLEAR(mac) \ 72 ((mac)[5] == 0 && (mac)[4] == 0 && (mac)[3] == 0 && (mac)[2] == 0 && \ 73 (mac)[1] == 0 && (mac)[0] == 0 ? TRUE : FALSE) 74 75 #define IP6_IS_CLEAR(ip6) \ 76 ((ip6)[15] == 0 && (ip6)[14] == 0 && (ip6)[13] == 0 && (ip6)[12] == 0 && \ 77 (ip6)[11] == 0 && (ip6)[10] == 0 && (ip6)[ 9] == 0 && (ip6)[ 8] == 0 && \ 78 (ip6)[ 7] == 0 && (ip6)[ 6] == 0 && (ip6)[ 5] == 0 && (ip6)[ 4] == 0 && \ 79 (ip6)[ 3] == 0 && (ip6)[ 2] == 0 && (ip6)[ 1] == 0 && (ip6)[ 0] == 0 \ 80 ? TRUE : FALSE) 81 82 83 /* 84 * Marker for last element in qualification table 85 */ 86 #define ACL_TABLE_END_STR "tbl_end" 87 88 #define ACL_STAT_STR_SZ 256 89 90 /* 91 * local typedefs 92 */ 93 94 typedef struct cmd_acl_list_s { 95 bcma_acl_t list; 96 bcma_acl_rule_t *rules[BCMA_ACL_NUMB_RULES]; 97 } cmd_acl_list_t; 98 99 100 cmd_acl_list_t *acl_lists[BCMA_ACL_NUMB_LISTS]; 101 102 103 /* 104 * local function prototypes 105 */ 106 cmd_result_t bcmx_cmd_aclcreate(int unit, args_t *args) ; 107 cmd_result_t bcmx_cmd_acldetach(int unit, args_t *args) ; 108 cmd_result_t bcmx_cmd_aclinit(int unit, args_t *args); 109 cmd_result_t bcmx_cmd_aclinstall(int unit, args_t *args); 110 cmd_result_t bcmx_cmd_acluninstall(int unit, args_t *args); 111 112 #ifdef BROADCOM_DEBUG 113 cmd_result_t bcmx_cmd_aclshow(int unit, args_t *args) ; 114 #endif /*BROADCOM_DEBUG*/ 115 116 cmd_result_t bcmx_cmd_acl_list(int unit, args_t *args); 117 cmd_result_t bcmx_cmd_acl_list_create(int unit, args_t *args); 118 cmd_result_t bcmx_cmd_acl_list_destroy(int unit, args_t *args); 119 120 cmd_result_t bcmx_cmd_aclrule(int unit, args_t *args); 121 122 STATIC void _cmd_acl_list_destroy(cmd_acl_list_t *list); 123 STATIC bcma_acl_t *_cmd_acl_list_alloc(bcma_acl_list_id_t list_id); 124 STATIC int _bcmx_acl_rule_id_get(void); 125 int _bcmx_acl_rule_add(bcma_acl_list_id_t list_id, bcma_acl_rule_t *rule); 126 STATIC bcma_acl_rule_t * _bcmx_acl_rule_alloc(void); 127 128 #define BCMA_ACL_LIST_NUMB 4 129 130 static int acl_init_flg = FALSE; 131 static int list_id_cur, list_id_max; 132 static int rule_id_max; 133 134 char bcmx_cmd_acl_usage[] = 135 #ifdef COMPILER_STRING_CONST_LIMIT 136 "Parameters: [acl_id] <cmd> <opt>\n" 137 #else /* !COMPILER_STRING_CONST_LIMIT */ 138 "Parameters: [acl_id] <cmd> <opt>\n" 139 " Where <cmd> is:\n" 140 "\tlist create <list_id> <user-port-list>\t- Create an ACL on a set of ports\n" 141 "\t destroy id=<list_id>\n" 142 "\trule {Permit=<T/F>|Deny=<T/F>|Log=<T/F>}\n" 143 "\t [RedirPort=<user-port>] [MirrorPort=<user-port>]\n" 144 "\t [SrcMac=<val>] [DstMac=<val>]\n" 145 "\t [SrcIp=<val>] [SrcIpMask=<val>] [DstIp=<val>] [DstIpMask=<val>]\n" 146 "\t [SrcIp6=<val>] [SrcIp6Mask=<val>] [DstIp6=<val>] [DstIp6Mask=<val>]\n" 147 "\t [SrcPortMIn=<val>] [SrcPortMAx=<val>]\n" 148 "\t [DstPortMIn=<val>] [DstPortMAx=<val>]\n" 149 "\t [VlanMIn=<id>] [VlanMAx=<id>\n" 150 "\t [IpProtocol=<protocol>] [EtherType=<type>\n" 151 "\tdetach\n" 152 "\tinit\n" 153 "\tinstall\n" 154 "\tuninstall\n" 155 "\tshow\n" 156 #endif /* !COMPILER_STRING_CONST_LIMIT */ 157 ; 158 159 static cmd_t acl_cmd_list[] = { 160 {"Init", bcmx_cmd_aclinit, 161 "acl init", 162 "Initialize ACL"}, 163 164 {"Detach", bcmx_cmd_acldetach, 165 "acl detach", 166 "Detach ACL"}, 167 168 {"Rule", bcmx_cmd_aclrule, 169 "acl rule {Permit|Deny|Redirect|Log}", 170 "Specify an access control list rule"}, 171 172 {"List", bcmx_cmd_acl_list, 173 "acl list {create | destroy}", 174 "Create or destroy access control list"}, 175 176 #ifdef BROADCOM_DEBUG 177 {"Show", bcmx_cmd_aclshow, 178 "acl show", 179 "Show an access control list" }, 180 #endif /* BROADCOM_DEBUG */ 181 182 {"Install", bcmx_cmd_aclinstall, 183 "acl install", 184 "Install the ACL lists in harware"}, 185 186 {"Uninstall", bcmx_cmd_acluninstall, 187 "acl uninstall", 188 "Remove the ACL lists from harware"} 189 }; 190 191 static cmd_t acl_list_cmd_list[] = { 192 {"Create", bcmx_cmd_acl_list_create, 193 "acl list create", 194 "Create an ACL list" }, 195 196 {"Destroy", bcmx_cmd_acl_list_destroy, 197 "acl list destroy", 198 "destroy an ACL list" } 199 }; 200 201 static 202 char *bcma_acl_ip_protocol_text[256] = { 203 "0", "ICMP", "IGMP", "GGP", "IP", "ST", "TCP", "UCL", 204 "EGP", "IGP", "10", "11", "PUP", "ARGUS", "EMCON", "XNET", 205 "CHAOS", "UDP", "MUX", "19", "HMP", "PRM", "22", "23", 206 "24", "LEAF1", "LEAF2", "RDP", "IRTP", "29", "NETBLT", "31", 207 "32", "SEP", "3PC", "IDRP", "XTP", "DDP", "38", "TP++", 208 "IL", "SIP", "SDRP", "43", "44", "IDRP", "RSVP", "GRE", 209 "48", "49", "50", "51", "52", "53", "54", "55", 210 }; 211 212 /* Section: top level commands */ 213 214 /* 215 * Function: 216 * bcmx_cmd_acl 217 * Purpose: 218 * Access Control List CLI interface 219 * Parameters: 220 * unit - SOC unit # 221 * args - pointer to command line arguments 222 * Returns: 223 * CMD_OK 224 */ 225 cmd_result_t 226 bcmx_cmd_acl(int unit, args_t *args) { 227 char *initial_cmd = ARG_CMD(args); 228 char *key; 229 cmd_t *cmd; 230 char *param; 231 cmd_result_t retval = CMD_OK; 232 233 if ((key = ARG_GET(args)) == NULL) { 234 sal_printf("%s: Subcommand required\n", initial_cmd); 235 return CMD_USAGE; 236 } 237 238 if (isint(key)) { 239 list_id_cur = parse_integer(key); 240 if ((key = ARG_GET(args)) == NULL) { 241 sal_printf("%s: Subcommand required\n", initial_cmd); 242 return CMD_USAGE; 243 } 244 } 245 246 cmd = (cmd_t *) parse_lookup(key, acl_cmd_list, sizeof(cmd_t), 247 COUNTOF(acl_cmd_list)); 248 249 if (cmd == NULL) 250 { 251 sal_printf("%s: Unknown subcommand %s\n", initial_cmd, key); 252 return CMD_USAGE; 253 } 254 255 /* If next param is "?", just display help for command */ 256 param = ARG_CUR(args); 257 if (param != NULL) { 258 if (sal_strcmp(param, "?") == 0) 259 { 260 ARG_GET(args); /* Consume "?" */ 261 if ((cmd->c_usage != NULL) && 262 (soc_property_get(unit, spn_HELP_CLI_ENABLE, 1))) { 263 sal_printf("Usage: %s\n", cmd->c_usage); 264 } 265 if ((cmd->c_help != NULL) && 266 (soc_property_get(unit, spn_HELP_CLI_ENABLE, 1))){ 267 sal_printf("Help : %s\n", cmd->c_help); 268 } 269 return retval; 270 } 271 } 272 273 return cmd->c_f(unit, args); 274 } 275 276 277 /* Section: 2nd level commands */ 278 279 /* 280 * Function: bcmx_cmd_acldetach 281 * 282 * Purpose: 283 * 284 * Parameters: 285 * 286 * Returns: 287 */ 288 cmd_result_t 289 bcmx_cmd_acldetach(int unit, args_t *args) { 290 int retval; 291 int idx; 292 293 /* Do the actual ACL detach. */ 294 retval = bcma_acl_detach(); 295 ACL_CHECK_RETURN(retval, "bcma_acl_detach"); 296 297 /* Get rid of any locally allocated lists. */ 298 for (idx = 0; idx < BCMA_ACL_NUMB_LISTS; idx++) { 299 if (acl_lists[idx] != NULL) { 300 _cmd_acl_list_destroy(acl_lists[idx]); 301 acl_lists[idx] = NULL; 302 } 303 } 304 305 acl_init_flg = FALSE; 306 307 return CMD_OK; 308 } 309 310 /* 311 * Function: _cmd_acl_list_destroy 312 * 313 * Purpose: 314 * free any locally allocated ACL lists, including all rules in list. 315 * 316 * Parameters: 317 * 318 * Returns: 319 */ 320 STATIC void 321 _cmd_acl_list_destroy(cmd_acl_list_t *cmd_list) 322 { 323 int idx; 324 325 assert(cmd_list != NULL); 326 327 for (idx = 0; idx < BCMA_ACL_NUMB_RULES; idx++) { 328 if (cmd_list->rules[idx] != NULL) { 329 bcma_acl_rule_remove(cmd_list->list.list_id, cmd_list->rules[idx]->rule_id); 330 sal_free(cmd_list->rules[idx]); 331 cmd_list->rules[idx] = NULL; 332 } 333 } 334 sal_free(cmd_list); 335 } 336 337 /* 338 * Function: bcmx_cmd_aclinit 339 * 340 * Purpose: 341 * 342 * Parameters: 343 * 344 * Returns: 345 */ 346 cmd_result_t 347 bcmx_cmd_aclinit(int unit, args_t *args) { 348 int idx; 349 350 /* Clean up first, if previously initialized. */ 351 if (acl_init_flg == TRUE) { 352 /* Get rid of any locally allocated lists. */ 353 for (idx = 0; idx < BCMA_ACL_NUMB_LISTS; idx++) { 354 if (acl_lists[idx] != NULL) { 355 _cmd_acl_list_destroy(acl_lists[idx]); 356 acl_lists[idx] = NULL; 357 } 358 } 359 } 360 361 /* Zero out local list data. */ 362 sal_memset(acl_lists, 0, sizeof(cmd_acl_list_t*) * BCMA_ACL_NUMB_LISTS); 363 list_id_cur = list_id_max = 1; 364 rule_id_max = 1; 365 366 /* Initialize the ACL module itself. */ 367 bcma_acl_init(); 368 acl_init_flg = TRUE; 369 return CMD_OK; 370 } 371 372 /* 373 * Function: bcmx_cmd_aclinstall 374 * 375 * Purpose: 376 * 377 * Parameters: 378 * 379 * Returns: 380 */ 381 cmd_result_t 382 bcmx_cmd_aclinstall(int unit, args_t *args) { 383 int retval; 384 385 retval = bcma_acl_install(); 386 ACL_CHECK_RETURN(retval, "bcma_acl_install"); 387 388 return CMD_OK; 389 } 390 /* 391 * Function: bcmx_cmd_acluninstall 392 * 393 * Purpose: 394 * 395 * Parameters: 396 * 397 * Returns: 398 */ 399 cmd_result_t 400 bcmx_cmd_acluninstall(int unit, args_t *args) { 401 int retval; 402 403 retval = bcma_acl_uninstall(); 404 ACL_CHECK_RETURN(retval, "bcma_acl_install"); 405 406 return CMD_OK; 407 } 408 409 410 #ifdef BROADCOM_DEBUG 411 /* 412 * Function: bcmx_cmd_aclshow 413 * 414 * Purpose: 415 * 416 * Parameters: 417 * 418 * Returns: 419 */ 420 cmd_result_t 421 bcmx_cmd_aclshow(int unit, args_t *args) { 422 int retval; 423 char *subcmd = NULL; 424 425 if ((subcmd = ARG_GET(args)) == NULL) { 426 /* If no List ID specified, show all lists. */ 427 retval = bcma_acl_show(); 428 ACL_CHECK_RETURN(retval, "bcma_acl_show"); 429 return CMD_OK; 430 } 431 432 /* Use the command line List ID. */ 433 if (!isint(subcmd)) { 434 return CMD_USAGE; 435 } 436 437 retval = bcma_acl_list_show(parse_integer(subcmd)); 438 ACL_CHECK_RETURN(retval, "bcma_acl_list_show"); 439 440 return CMD_OK; 441 } 442 #endif /*BROADCOM_DEBUG*/ 443 444 445 /* Section: List Commands {Create | Destroy} */ 446 cmd_result_t 447 bcmx_cmd_acl_list(int unit, args_t *args) { 448 return subcommand_execute(unit, args, 449 acl_list_cmd_list, 450 COUNTOF(acl_list_cmd_list)); 451 } 452 453 /* 454 * Function: bcmx_cmd_acl_list_create 455 * 456 * Purpose: 457 * CLI handler to create an ACL list. 458 * 459 * Parameters: 460 * 461 * Returns: 462 * CMD_OK - Success 463 * CMD_FAIL - could not initialize port list or list add failure. 464 * CMD_USAGE - improper CLI 465 */ 466 cmd_result_t 467 bcmx_cmd_acl_list_create(int unit, args_t *args) { 468 bcma_acl_list_id_t list_id = list_id_max + 1; 469 bcma_acl_t *list_p; 470 char *str; 471 472 /* Read the List ID. */ 473 str = ARG_GET(args); 474 if (str) { 475 list_id = parse_integer(str); 476 } else { 477 return CMD_USAGE; 478 } 479 480 list_p = _cmd_acl_list_alloc(list_id); 481 if (list_p == NULL) { 482 cli_out("ACL: list ID=%d allocation failure\n", list_id); 483 return CMD_FAIL; 484 } 485 486 /* Read the user port list. */ 487 str = ARG_GET(args); 488 if (str) { 489 if (BCM_FAILURE(bcmx_lplist_parse(&list_p->lplist, str))) { 490 cli_out("Can't parse UserPortList \"%s\"\n", str); 491 return CMD_USAGE; 492 } 493 /* Read the priority */ 494 str = ARG_GET(args); 495 list_p->prio = (str) ? parse_integer(str) : 0; 496 } else { 497 bcmx_port_lplist_populate(&list_p->lplist, BCMX_PORT_LP_ALL); 498 } 499 500 list_id_cur = list_id; 501 list_p->list_id = list_id; 502 503 if (BCM_FAILURE(bcma_acl_add(list_p))) { 504 return CMD_FAIL; 505 } 506 507 cli_out("ACL: list ID=%d created\n", list_id); 508 509 return CMD_OK; 510 } 511 512 /* 513 * Function: _cmd_acl_list_alloc 514 * 515 * Purpose: 516 * Allocate a command list struct from local array 517 * 518 * Parameters: 519 * none 520 * 521 * Returns: 522 * pointer to bcma_acl_t list 523 * or 524 * NULL on allocation failure 525 */ 526 STATIC bcma_acl_t * 527 _cmd_acl_list_alloc(bcma_acl_list_id_t list_id) 528 { 529 int idx; 530 cmd_acl_list_t *list = NULL; 531 532 /* Find an unused slot in acl_list array. */ 533 for (idx = 0; idx < BCMA_ACL_NUMB_LISTS; idx++) { 534 if (acl_lists[idx] == NULL) { 535 /* Allocate the cmd_list struct. */ 536 list = sal_alloc(sizeof(cmd_acl_list_t), "CMD ACL"); 537 if (list == NULL) { 538 return NULL; 539 } 540 /* Put it in acl_list array. */ 541 acl_lists[idx] = list; 542 543 /* Zero out cmd_list struct. */ 544 sal_memset(list, 0, sizeof(cmd_acl_list_t)); 545 546 bcmx_lplist_init(&list->list.lplist, 0, 0); 547 list->list.list_id = list_id; 548 549 /* Return pointer to bcma_acl_t list. */ 550 return &list->list; 551 } 552 } 553 554 /* Return pointer to bcma_acl_t list. */ 555 return NULL; 556 } 557 558 cmd_result_t 559 bcmx_cmd_acl_list_destroy(int unit, args_t *args) { 560 parse_table_t pt; 561 cmd_result_t retval; 562 bcma_acl_list_id_t list_id; 563 564 parse_table_init(unit, &pt); 565 parse_table_add(&pt, "id", PQ_DFL | PQ_INT, 0, 566 (void *)&list_id, 0); 567 568 if(!parseEndOk(args, &pt, &retval)) { 569 return CMD_USAGE; 570 } 571 572 if (BCM_FAILURE(bcma_acl_remove(list_id))) { 573 cli_out("ACL: failed to destroy list ID=%d \n", list_id); 574 return CMD_FAIL; 575 } 576 577 cli_out("ACL: List ID=%d destroyed\n", list_id); 578 579 return CMD_OK; 580 } 581 582 /* Section: rule Commands {Create | Destroy} */ 583 584 STATIC int 585 _bcmx_acl_rule_id_get(void) { 586 int rule_id; /* output */ 587 588 rule_id_max++; 589 rule_id = rule_id_max; 590 591 return rule_id; 592 } 593 594 /* 595 * Function: bcmx_cmd_aclrule 596 * 597 * Purpose: 598 * Create a list rule. 599 * 600 * Parameters: 601 * 602 * Returns: 603 */ 604 cmd_result_t 605 bcmx_cmd_aclrule(int unit, args_t *args) { 606 bcma_acl_rule_t *rule; 607 parse_table_t pt; 608 cmd_result_t retval; 609 uint32 permit_flag=0, deny_flag=0, log_flag=0; 610 char *redir_port_str = NULL; 611 char *mirror_port_str = NULL; 612 bcmx_lport_t lport; 613 bcmx_uport_t uport; 614 uint32 vlan_min = 0, vlan_max = 0; 615 uint32 ethertype = 0; 616 617 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 618 (BSL_META_U(unit, 619 "BEGIN bcmx_cmd_aclrule()\n"))); 620 621 rule = _bcmx_acl_rule_alloc(); 622 if (rule == NULL) { 623 return CMD_FAIL; 624 } 625 626 rule->rule_id = _bcmx_acl_rule_id_get() ; 627 rule->ip_protocol = BCMA_ACL_IPPROTO_ANY; 628 rule->actions.redir_port = -1; 629 rule->actions.mirror_port = -1; 630 631 parse_table_init(unit, &pt); 632 633 /* Actions */ 634 parse_table_add(&pt, "Permit", PQ_DFL | PQ_NO_EQ_OPT | PQ_BOOL, 0, 635 (void *)&permit_flag, 0); 636 parse_table_add(&pt, "Deny", PQ_DFL | PQ_NO_EQ_OPT | PQ_BOOL, 0, 637 (void *)&deny_flag, 0); 638 parse_table_add(&pt, "Log", PQ_DFL | PQ_NO_EQ_OPT | PQ_BOOL, 0, 639 (void *)&log_flag, 0); 640 641 parse_table_add(&pt, "RedirPort", PQ_DFL | PQ_STRING, 0, 642 (void *)&redir_port_str, NULL); 643 parse_table_add(&pt, "MirrorPort", PQ_DFL | PQ_STRING, 0, 644 (void *)&mirror_port_str, NULL); 645 646 /* Matching parameters */ 647 parse_table_add(&pt, "SrcMac", PQ_DFL | PQ_MAC, 0, 648 (void *)&rule->src_mac, 0); 649 parse_table_add(&pt, "DstMac", PQ_DFL | PQ_MAC, 0, 650 (void *)&rule->dst_mac, 0); 651 652 parse_table_add(&pt, "SrcIp", PQ_DFL | PQ_IP, 0, 653 (void *)&rule->src_ip, 0); 654 parse_table_add(&pt, "SrcIpMask", PQ_DFL | PQ_IP, 0, 655 (void *)&rule->src_ip_mask, 0); 656 parse_table_add(&pt, "DstIp", PQ_DFL | PQ_IP, 0, 657 (void *)&rule->dst_ip, 0); 658 parse_table_add(&pt, "DstIpMask", PQ_DFL | PQ_IP, 0, 659 (void *)&rule->dst_ip_mask, 0); 660 661 parse_table_add(&pt, "SrcIp6", PQ_DFL | PQ_IP6, 0, 662 (void *)&rule->src_ip6, 0); 663 parse_table_add(&pt, "SrcIp6Mask", PQ_DFL | PQ_IP6, 0, 664 (void *)&rule->src_ip6_mask, 0); 665 parse_table_add(&pt, "DstIp6", PQ_DFL | PQ_IP6, 0, 666 (void *)&rule->dst_ip6, 0); 667 parse_table_add(&pt, "DstIp6Mask", PQ_DFL | PQ_IP6, 0, 668 (void *)&rule->dst_ip6_mask, 0); 669 670 parse_table_add(&pt, "SrcPortMIn", PQ_DFL | PQ_INT, 0, 671 (void *)&rule->src_port_min, 0); 672 parse_table_add(&pt, "SrcPortMAx", PQ_DFL | PQ_INT, 0, 673 (void *)&rule->src_port_max, 0); 674 675 parse_table_add(&pt, "DstPortMIn", PQ_DFL | PQ_INT, 0, 676 (void *)&rule->dst_port_min, 0); 677 parse_table_add(&pt, "DstPortMAx", PQ_DFL | PQ_INT, 0, 678 (void *)&rule->dst_port_max, 0); 679 680 parse_table_add(&pt, "VlanMIn", PQ_DFL | PQ_INT, 0, 681 (void *)&vlan_min, 0); 682 parse_table_add(&pt, "VlanMAx", PQ_DFL | PQ_INT, 0, 683 (void *)&vlan_max, 0); 684 685 parse_table_add(&pt, "IpProtocol", PQ_DFL | PQ_MULTI , 0, 686 (void *)&rule->ip_protocol, bcma_acl_ip_protocol_text); 687 parse_table_add(&pt, "EtherType", PQ_DFL | PQ_HEX, 0, 688 (void *)ðertype, 0); 689 690 /* Parse redirection port, if specified. */ 691 if (pt.pt_entries[3].pq_type & PQ_PARSED && redir_port_str != NULL) { 692 uport = bcmx_uport_parse(redir_port_str, NULL); 693 lport = bcmx_uport_to_lport(uport); 694 695 if (lport == BCMX_NO_SUCH_LPORT) { 696 sal_printf("%s: bad redirection port given: %s\n", 697 ARG_CMD(args), redir_port_str); 698 parse_arg_eq_done(&pt); 699 return CMD_FAIL; 700 } else { 701 rule->actions.flags |= BCMA_ACL_ACTION_REDIR; 702 rule->actions.redir_port = lport; 703 } 704 } 705 706 /* Parse mirror-to-port, if specified. */ 707 if (pt.pt_entries[4].pq_type & PQ_PARSED && mirror_port_str != NULL) { 708 uport = bcmx_uport_parse(mirror_port_str, NULL); 709 lport = bcmx_uport_to_lport(uport); 710 711 if (lport == BCMX_NO_SUCH_LPORT) { 712 sal_printf("%s: bad mirror port given: %s\n", 713 ARG_CMD(args), mirror_port_str); 714 parse_arg_eq_done(&pt); 715 return CMD_FAIL; 716 } else { 717 rule->actions.flags |= BCMA_ACL_ACTION_MIRROR; 718 rule->actions.mirror_port = lport; 719 } 720 } 721 722 if(!parseEndOk(args, &pt, &retval)) { 723 return retval; 724 } 725 if (permit_flag) { 726 rule->actions.flags |= BCMA_ACL_ACTION_PERMIT; 727 } 728 if (deny_flag) { 729 rule->actions.flags |= BCMA_ACL_ACTION_DENY; 730 } 731 732 if (log_flag) { 733 rule->actions.flags |= BCMA_ACL_ACTION_LOG; 734 } 735 736 737 if (!MAC_IS_CLEAR(rule->src_mac)) { 738 rule->flags |= BCMA_ACL_RULE_SRC_MAC; 739 } 740 741 if (!MAC_IS_CLEAR(rule->dst_mac)) { 742 rule->flags |= BCMA_ACL_RULE_DST_MAC; 743 } 744 745 if (rule->src_port_min != 0) { 746 rule->flags |= BCMA_ACL_RULE_L4_SRC_PORT; 747 if (rule->src_port_max == 0) { 748 rule->src_port_max = rule->src_port_min; 749 } 750 } 751 752 if (rule->src_port_max != 0) { 753 rule->flags |= BCMA_ACL_RULE_L4_SRC_PORT; 754 if (rule->src_port_min == 0) { 755 rule->src_port_min = rule->src_port_max; 756 } 757 } 758 759 if (rule->dst_port_min != 0) { 760 rule->flags |= BCMA_ACL_RULE_L4_DST_PORT; 761 if (rule->dst_port_max == 0) { 762 rule->dst_port_max = rule->dst_port_min; 763 } 764 } 765 766 if (rule->dst_port_max != 0) { 767 rule->flags |= BCMA_ACL_RULE_L4_DST_PORT; 768 if (rule->dst_port_min == 0) { 769 rule->dst_port_min = rule->dst_port_max; 770 } 771 } 772 773 if (rule->src_ip || rule->src_ip_mask) { 774 rule->flags |= BCMA_ACL_RULE_SRC_IP4; 775 } 776 777 if (rule->dst_ip || rule->dst_ip_mask) { 778 rule->flags |= BCMA_ACL_RULE_DST_IP4; 779 } 780 781 if (!IP6_IS_CLEAR(rule->src_ip6)) { 782 rule->flags |= BCMA_ACL_RULE_SRC_IP6; 783 } 784 785 if (!IP6_IS_CLEAR(rule->dst_ip6)) { 786 rule->flags |= BCMA_ACL_RULE_DST_IP6; 787 } 788 789 if (vlan_min || vlan_max) { 790 rule->flags |= BCMA_ACL_RULE_VLAN; 791 rule->vlan_min = vlan_min; 792 rule->vlan_max = vlan_max; 793 } 794 795 if (rule->ip_protocol != BCMA_ACL_IPPROTO_ANY) { 796 rule->flags |= BCMA_ACL_RULE_IPPROTOCOL; 797 } 798 799 if (ethertype > 0xffff) { 800 cli_out("Ethertype=%#x too large (>0xffff).\n", ethertype); 801 sal_free(rule); 802 return CMD_FAIL; 803 } 804 805 if (ethertype != 0) { 806 rule->flags |= BCMA_ACL_RULE_ETHERTYPE; 807 rule->ether_type = ethertype; 808 } 809 810 if (BCM_FAILURE(bcma_acl_rule_add(list_id_cur, rule))) { 811 cli_out("ACL: rule add failed (rule_id=%d).\n", rule->rule_id); 812 sal_free(rule); 813 return CMD_FAIL; 814 } 815 816 return CMD_OK; 817 } 818 819 /* 820 * Function: 821 * _bcmx_acl_rule_add 822 * Purpose: 823 * 824 * Returns: 825 * pointer to new rule or NULL on error 826 */ 827 int 828 _bcmx_acl_rule_add(bcma_acl_list_id_t list_id, bcma_acl_rule_t *rule) 829 { 830 int idx1, idx2; 831 832 assert(rule != NULL); 833 834 /* Find the corresponding cmd_acl_list_t */ 835 for (idx1 = 0; idx1 < BCMA_ACL_NUMB_LISTS; idx1++) { 836 if (acl_lists[idx1] == NULL) { 837 continue; 838 } 839 if (acl_lists[idx1]->list.list_id == list_id) { 840 /* find an unused rule in list. */ 841 for (idx2 = 0; idx2 < BCMA_ACL_NUMB_LISTS; idx2++) { 842 if (acl_lists[idx1]->rules[idx2] == NULL) { 843 acl_lists[idx1]->rules[idx2] = rule; 844 return BCM_E_NONE; 845 } 846 } 847 return BCM_E_RESOURCE; 848 } 849 } 850 return BCM_E_NOT_FOUND; 851 } 852 853 854 /* 855 * Function: 856 * _bcmx_acl_rule_alloc 857 * Purpose: 858 * Allocate a new rule and zero it out. 859 * Returns: 860 * pointer to new rule or NULL on error 861 */ 862 STATIC bcma_acl_rule_t * 863 _bcmx_acl_rule_alloc(void) { 864 bcma_acl_rule_t *rule_new; 865 866 LOG_DEBUG(BSL_LS_APPL_ACCESSCTRLLIST, 867 (BSL_META("BEGIN _bcmx_acl_rule_alloc()\n"))); 868 rule_new = sal_alloc(sizeof(bcma_acl_rule_t), "acl rule"); 869 if (rule_new == NULL) { 870 cli_out("ACL Error: allocation failure\n"); 871 return NULL; 872 } 873 sal_memset(rule_new, 0, sizeof(bcma_acl_rule_t)); 874 875 return rule_new; 876 } 877 878 #endif /* INCLUDE_ACL */