ip_fw_table_algo.c (269227) | ip_fw_table_algo.c (269252) |
---|---|
1/*- 2 * Copyright (c) 2004 Ruslan Ermilov and Vsevolod Lobko. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 500 unchanged lines hidden (view full) --- 509 struct ta_buf_cidr *tb; 510 511 tb = (struct ta_buf_cidr *)ta_buf; 512 513 if (tb->ent_ptr != NULL) 514 free(tb->ent_ptr, M_IPFW_TBL); 515} 516 | 1/*- 2 * Copyright (c) 2004 Ruslan Ermilov and Vsevolod Lobko. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 500 unchanged lines hidden (view full) --- 509 struct ta_buf_cidr *tb; 510 511 tb = (struct ta_buf_cidr *)ta_buf; 512 513 if (tb->ent_ptr != NULL) 514 free(tb->ent_ptr, M_IPFW_TBL); 515} 516 |
517struct table_algo radix_cidr = { | 517struct table_algo cidr_radix = { |
518 .name = "cidr:radix", 519 .lookup = ta_lookup_radix, 520 .init = ta_init_radix, 521 .destroy = ta_destroy_radix, 522 .prepare_add = ta_prepare_add_cidr, 523 .prepare_del = ta_prepare_del_cidr, 524 .add = ta_add_cidr, 525 .del = ta_del_cidr, 526 .flush_entry = ta_flush_cidr_entry, 527 .foreach = ta_foreach_radix, 528 .dump_tentry = ta_dump_radix_tentry, 529 .find_tentry = ta_find_radix_tentry, 530}; 531 532 533/* | 518 .name = "cidr:radix", 519 .lookup = ta_lookup_radix, 520 .init = ta_init_radix, 521 .destroy = ta_destroy_radix, 522 .prepare_add = ta_prepare_add_cidr, 523 .prepare_del = ta_prepare_del_cidr, 524 .add = ta_add_cidr, 525 .del = ta_del_cidr, 526 .flush_entry = ta_flush_cidr_entry, 527 .foreach = ta_foreach_radix, 528 .dump_tentry = ta_dump_radix_tentry, 529 .find_tentry = ta_find_radix_tentry, 530}; 531 532 533/* |
534 * cidr:hash cmds 535 * 536 * 537 * ti->data: 538 * [inv.mask4][inv.mask6][log2hsize4][log2hsize6] 539 * [ 8][ 8[ 8][ 8] 540 * 541 * inv.mask4: 32 - mask 542 * inv.mask6: 543 * 1) _slow lookup: mask 544 * 2) _aligned: (128 - mask) / 8 545 * 3) _64: 8 546 */ 547 548struct chashentry; 549 550SLIST_HEAD(chashbhead, chashentry); 551 552struct chash_cfg { 553 struct chashbhead *head4; 554 struct chashbhead *head6; 555 size_t size4; 556 size_t size6; 557 size_t items; 558 uint8_t mask4; 559 uint8_t mask6; 560}; 561 562struct chashentry { 563 SLIST_ENTRY(chashentry) next; 564 uint32_t value; 565 uint32_t type; 566 union { 567 uint32_t a4; /* Host format */ 568 struct in6_addr a6; /* Network format */ 569 } a; 570}; 571 572static __inline uint32_t 573hash_ip(uint32_t addr, int hsize) 574{ 575 576 return (addr % (hsize - 1)); 577} 578 579static __inline uint32_t 580hash_ip6(struct in6_addr *addr6, int hsize) 581{ 582 uint32_t i; 583 584 i = addr6->s6_addr32[0] ^ addr6->s6_addr32[1] ^ 585 addr6->s6_addr32[2] ^ addr6->s6_addr32[3]; 586 587 return (i % (hsize - 1)); 588} 589 590 591static __inline uint16_t 592hash_ip64(struct in6_addr *addr6, int hsize) 593{ 594 uint32_t i; 595 596 i = addr6->s6_addr32[0] ^ addr6->s6_addr32[1]; 597 598 return (i % (hsize - 1)); 599} 600 601 602static __inline uint32_t 603hash_ip6_slow(struct in6_addr *addr6, void *key, int mask, int hsize) 604{ 605 struct in6_addr mask6; 606 607 ipv6_writemask(&mask6, mask); 608 memcpy(addr6, key, sizeof(struct in6_addr)); 609 APPLY_MASK(addr6, &mask6); 610 return (hash_ip6(addr6, hsize)); 611} 612 613static __inline uint32_t 614hash_ip6_al(struct in6_addr *addr6, void *key, int mask, int hsize) 615{ 616 uint64_t *paddr; 617 618 paddr = (uint64_t *)addr6; 619 *paddr = 0; 620 *(paddr + 1) = 0; 621 memcpy(addr6, key, mask); 622 return (hash_ip6(addr6, hsize)); 623} 624 625static int 626ta_lookup_chash_slow(struct table_info *ti, void *key, uint32_t keylen, 627 uint32_t *val) 628{ 629 struct chashbhead *head; 630 struct chashentry *ent; 631 uint16_t hash, hsize; 632 uint8_t imask; 633 634 if (keylen == sizeof(in_addr_t)) { 635 head = (struct chashbhead *)ti->state; 636 imask = ti->data >> 24; 637 hsize = 1 << ((ti->data & 0xFFFF) >> 8); 638 uint32_t a; 639 a = ntohl(*((in_addr_t *)key)); 640 a = a >> imask; 641 hash = hash_ip(a, hsize); 642 SLIST_FOREACH(ent, &head[hash], next) { 643 if (ent->a.a4 == a) { 644 *val = ent->value; 645 return (1); 646 } 647 } 648 } else { 649 /* IPv6: worst scenario: non-round mask */ 650 struct in6_addr addr6; 651 head = (struct chashbhead *)ti->xstate; 652 imask = (ti->data & 0xFF0000) >> 16; 653 hsize = 1 << (ti->data & 0xFF); 654 hash = hash_ip6_slow(&addr6, key, imask, hsize); 655 SLIST_FOREACH(ent, &head[hash], next) { 656 if (memcmp(&ent->a.a6, &addr6, 16) == 0) { 657 *val = ent->value; 658 return (1); 659 } 660 } 661 } 662 663 return (0); 664} 665 666static int 667ta_lookup_chash_aligned(struct table_info *ti, void *key, uint32_t keylen, 668 uint32_t *val) 669{ 670 struct chashbhead *head; 671 struct chashentry *ent; 672 uint16_t hash, hsize; 673 uint8_t imask; 674 675 if (keylen == sizeof(in_addr_t)) { 676 head = (struct chashbhead *)ti->state; 677 imask = ti->data >> 24; 678 hsize = 1 << ((ti->data & 0xFFFF) >> 8); 679 uint32_t a; 680 a = ntohl(*((in_addr_t *)key)); 681 a = a >> imask; 682 hash = hash_ip(a, hsize); 683 SLIST_FOREACH(ent, &head[hash], next) { 684 if (ent->a.a4 == a) { 685 *val = ent->value; 686 return (1); 687 } 688 } 689 } else { 690 /* IPv6: aligned to 8bit mask */ 691 struct in6_addr addr6; 692 uint64_t *paddr, *ptmp; 693 head = (struct chashbhead *)ti->xstate; 694 imask = (ti->data & 0xFF0000) >> 16; 695 hsize = 1 << (ti->data & 0xFF); 696 697 hash = hash_ip6_al(&addr6, key, imask, hsize); 698 paddr = (uint64_t *)&addr6; 699 SLIST_FOREACH(ent, &head[hash], next) { 700 ptmp = (uint64_t *)&ent->a.a6; 701 if (paddr[0] == ptmp[0] && paddr[1] == ptmp[1]) { 702 *val = ent->value; 703 return (1); 704 } 705 } 706 } 707 708 return (0); 709} 710 711static int 712ta_lookup_chash_64(struct table_info *ti, void *key, uint32_t keylen, 713 uint32_t *val) 714{ 715 struct chashbhead *head; 716 struct chashentry *ent; 717 uint16_t hash, hsize; 718 uint8_t imask; 719 720 if (keylen == sizeof(in_addr_t)) { 721 head = (struct chashbhead *)ti->state; 722 imask = ti->data >> 24; 723 hsize = 1 << ((ti->data & 0xFFFF) >> 8); 724 uint32_t a; 725 a = ntohl(*((in_addr_t *)key)); 726 a = a >> imask; 727 hash = hash_ip(a, hsize); 728 SLIST_FOREACH(ent, &head[hash], next) { 729 if (ent->a.a4 == a) { 730 *val = ent->value; 731 return (1); 732 } 733 } 734 } else { 735 /* IPv6: /64 */ 736 uint64_t a6, *paddr; 737 head = (struct chashbhead *)ti->xstate; 738 paddr = (uint64_t *)key; 739 hsize = 1 << (ti->data & 0xFF); 740 a6 = *paddr; 741 hash = hash_ip64((struct in6_addr *)key, hsize); 742 SLIST_FOREACH(ent, &head[hash], next) { 743 paddr = (uint64_t *)&ent->a.a6; 744 if (a6 == *paddr) { 745 *val = ent->value; 746 return (1); 747 } 748 } 749 } 750 751 return (0); 752} 753 754static int 755chash_parse_opts(struct chash_cfg *ccfg, char *data) 756{ 757 char *pdel, *pend, *s; 758 int mask4, mask6; 759 760 mask4 = ccfg->mask4; 761 mask6 = ccfg->mask6; 762 763 if (data == NULL) 764 return (0); 765 if ((pdel = strchr(data, ' ')) == NULL) 766 return (0); 767 while (*pdel == ' ') 768 pdel++; 769 if (strncmp(pdel, "masks=", 6) != 0) 770 return (EINVAL); 771 if ((s = strchr(pdel, ' ')) != NULL) 772 *s++ = '\0'; 773 774 pdel += 6; 775 /* Need /XX[,/YY] */ 776 if (*pdel++ != '/') 777 return (EINVAL); 778 mask4 = strtol(pdel, &pend, 10); 779 if (*pend == ',') { 780 /* ,/YY */ 781 pdel = pend + 1; 782 if (*pdel++ != '/') 783 return (EINVAL); 784 mask6 = strtol(pdel, &pend, 10); 785 if (*pend != '\0') 786 return (EINVAL); 787 } else if (*pend != '\0') 788 return (EINVAL); 789 790 if (mask4 < 0 || mask4 > 32 || mask6 < 0 || mask6 > 128) 791 return (EINVAL); 792 793 ccfg->mask4 = mask4; 794 ccfg->mask6 = mask6; 795 796 return (0); 797} 798 799static void 800ta_print_chash_config(void *ta_state, struct table_info *ti, char *buf, 801 size_t bufsize) 802{ 803 struct chash_cfg *ccfg; 804 805 ccfg = (struct chash_cfg *)ta_state; 806 807 if (ccfg->mask4 != 32 || ccfg->mask6 != 128) 808 snprintf(buf, bufsize, "%s masks=/%d,/%d", "cidr:hash", 809 ccfg->mask4, ccfg->mask6); 810 else 811 snprintf(buf, bufsize, "%s", "cidr:hash"); 812} 813 814 815/* 816 * New table. 817 * We assume 'data' to be either NULL or the following format: 818 * 'cidr:hash [masks=/32[,/128]]' 819 */ 820static int 821ta_init_chash(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, 822 char *data) 823{ 824 int error, i; 825 int v4, v6; 826 struct chash_cfg *ccfg; 827 828 ccfg = malloc(sizeof(struct chash_cfg), M_IPFW, M_WAITOK | M_ZERO); 829 830 ccfg->mask4 = 32; 831 ccfg->mask6 = 128; 832 833 if ((error = chash_parse_opts(ccfg, data)) != 0) { 834 free(ccfg, M_IPFW); 835 return (error); 836 } 837 838 v4 = 7; 839 v6 = 7; 840 ccfg->size4 = 1 << v4; 841 ccfg->size6 = 1 << v6; 842 843 ccfg->head4 = malloc(sizeof(struct chashbhead) * ccfg->size4, M_IPFW, 844 M_WAITOK | M_ZERO); 845 ccfg->head6 = malloc(sizeof(struct chashbhead) * ccfg->size6, M_IPFW, 846 M_WAITOK | M_ZERO); 847 for (i = 0; i < ccfg->size4; i++) 848 SLIST_INIT(&ccfg->head4[i]); 849 for (i = 0; i < ccfg->size6; i++) 850 SLIST_INIT(&ccfg->head6[i]); 851 852 853 *ta_state = ccfg; 854 ti->state = ccfg->head4; 855 ti->xstate = ccfg->head6; 856 857 /* Store data depending on v6 mask length */ 858 if (ccfg->mask6 == 64) { 859 ti->data = (32 - ccfg->mask4) << 24 | (128 - ccfg->mask6) << 16 | 860 v4 << 8 | v6; 861 ti->lookup = ta_lookup_chash_64; 862 } else if ((ccfg->mask6 % 8) == 0) { 863 ti->data = (32 - ccfg->mask4) << 24 | 864 ccfg->mask6 << 13 | v4 << 8 | v6; 865 ti->lookup = ta_lookup_chash_aligned; 866 } else { 867 /* don't do that! */ 868 ti->data = (32 - ccfg->mask4) << 24 | 869 ccfg->mask6 << 16 | v4 << 8 | v6; 870 ti->lookup = ta_lookup_chash_slow; 871 } 872 873 return (0); 874} 875 876static void 877ta_destroy_chash(void *ta_state, struct table_info *ti) 878{ 879 struct chash_cfg *ccfg; 880 struct chashentry *ent, *ent_next; 881 int i; 882 883 ccfg = (struct chash_cfg *)ta_state; 884 885 for (i = 0; i < ccfg->size4; i++) 886 SLIST_FOREACH_SAFE(ent, &ccfg->head4[i], next, ent_next) 887 free(ent, M_IPFW_TBL); 888 889 for (i = 0; i < ccfg->size6; i++) 890 SLIST_FOREACH_SAFE(ent, &ccfg->head6[i], next, ent_next) 891 free(ent, M_IPFW_TBL); 892 893 free(ccfg->head4, M_IPFW); 894 free(ccfg->head6, M_IPFW); 895} 896 897static int 898ta_dump_chash_tentry(void *ta_state, struct table_info *ti, void *e, 899 ipfw_obj_tentry *tent) 900{ 901 struct chash_cfg *ccfg; 902 struct chashentry *ent; 903 904 ccfg = (struct chash_cfg *)ta_state; 905 ent = (struct chashentry *)e; 906 907 if (ent->type == AF_INET) { 908 tent->k.addr.s_addr = htonl(ent->a.a4 << (32 - ccfg->mask4)); 909 tent->masklen = ccfg->mask4; 910 tent->subtype = AF_INET; 911 tent->value = ent->value; 912#ifdef INET6 913 } else { 914 memcpy(&tent->k, &ent->a.a6, sizeof(struct in6_addr)); 915 tent->masklen = ccfg->mask6; 916 tent->subtype = AF_INET6; 917 tent->value = ent->value; 918#endif 919 } 920 921 return (0); 922} 923 924static int 925ta_find_chash_tentry(void *ta_state, struct table_info *ti, void *key, 926 uint32_t keylen, ipfw_obj_tentry *tent) 927{ 928#if 0 929 struct radix_node_head *rnh; 930 void *e; 931 932 e = NULL; 933 if (keylen == sizeof(in_addr_t)) { 934 struct sockaddr_in sa; 935 KEY_LEN(sa) = KEY_LEN_INET; 936 sa.sin_addr.s_addr = *((in_addr_t *)key); 937 rnh = (struct radix_node_head *)ti->state; 938 e = rnh->rnh_matchaddr(&sa, rnh); 939 } else { 940 struct sa_in6 sa6; 941 KEY_LEN(sa6) = KEY_LEN_INET6; 942 memcpy(&sa6.sin6_addr, key, sizeof(struct in6_addr)); 943 rnh = (struct radix_node_head *)ti->xstate; 944 e = rnh->rnh_matchaddr(&sa6, rnh); 945 } 946 947 if (e != NULL) { 948 ta_dump_radix_tentry(ta_state, ti, e, tent); 949 return (0); 950 } 951#endif 952 return (ENOENT); 953} 954 955static void 956ta_foreach_chash(void *ta_state, struct table_info *ti, ta_foreach_f *f, 957 void *arg) 958{ 959 struct chash_cfg *ccfg; 960 struct chashentry *ent, *ent_next; 961 int i; 962 963 ccfg = (struct chash_cfg *)ta_state; 964 965 for (i = 0; i < ccfg->size4; i++) 966 SLIST_FOREACH_SAFE(ent, &ccfg->head4[i], next, ent_next) 967 f(ent, arg); 968 969 for (i = 0; i < ccfg->size6; i++) 970 SLIST_FOREACH_SAFE(ent, &ccfg->head6[i], next, ent_next) 971 f(ent, arg); 972} 973 974 975struct ta_buf_chash 976{ 977 void *ent_ptr; 978 int type; 979 union { 980 uint32_t a4; 981 struct in6_addr a6; 982 } a; 983}; 984 985static int 986ta_prepare_add_chash(struct ip_fw_chain *ch, struct tentry_info *tei, 987 void *ta_buf) 988{ 989 struct ta_buf_chash *tb; 990 struct chashentry *ent; 991 int mlen; 992 struct in6_addr mask6; 993 994 tb = (struct ta_buf_chash *)ta_buf; 995 memset(tb, 0, sizeof(struct ta_buf_chash)); 996 997 mlen = tei->masklen; 998 999 if (tei->subtype == AF_INET) { 1000#ifdef INET 1001 if (mlen > 32) 1002 return (EINVAL); 1003 ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO); 1004 ent->value = tei->value; 1005 ent->type = AF_INET; 1006 1007 /* Calculate mask */ 1008 ent->a.a4 = ntohl(*((in_addr_t *)tei->paddr)) >> (32 - mlen); 1009 tb->ent_ptr = ent; 1010#endif 1011#ifdef INET6 1012 } else if (tei->subtype == AF_INET6) { 1013 /* IPv6 case */ 1014 if (mlen > 128) 1015 return (EINVAL); 1016 ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO); 1017 ent->value = tei->value; 1018 ent->type = AF_INET6; 1019 1020 ipv6_writemask(&mask6, mlen); 1021 memcpy(&ent->a.a6, tei->paddr, sizeof(struct in6_addr)); 1022 APPLY_MASK(&ent->a.a6, &mask6); 1023 tb->ent_ptr = ent; 1024#endif 1025 } else { 1026 /* Unknown CIDR type */ 1027 return (EINVAL); 1028 } 1029 1030 return (0); 1031} 1032 1033static int 1034ta_add_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei, 1035 void *ta_buf, uint64_t *pflags, uint32_t *pnum) 1036{ 1037 struct chash_cfg *ccfg; 1038 struct chashbhead *head; 1039 struct chashentry *ent, *tmp; 1040 struct ta_buf_chash *tb; 1041 int exists; 1042 uint32_t hash; 1043 1044 ccfg = (struct chash_cfg *)ta_state; 1045 tb = (struct ta_buf_chash *)ta_buf; 1046 ent = (struct chashentry *)tb->ent_ptr; 1047 hash = 0; 1048 exists = 0; 1049 1050 if (tei->subtype == AF_INET) { 1051 if (tei->masklen != ccfg->mask4) 1052 return (EINVAL); 1053 head = ccfg->head4; 1054 hash = hash_ip(ent->a.a4, ccfg->size4); 1055 /* Check for existence */ 1056 SLIST_FOREACH(tmp, &head[hash], next) { 1057 if (tmp->a.a4 == ent->a.a4) { 1058 exists = 1; 1059 break; 1060 } 1061 } 1062 } else { 1063 if (tei->masklen != ccfg->mask6) 1064 return (EINVAL); 1065 head = ccfg->head6; 1066 if (tei->masklen == 64) 1067 hash = hash_ip64(&ent->a.a6, ccfg->size6); 1068 else 1069 hash = hash_ip6(&ent->a.a6, ccfg->size6); 1070 /* Check for existence */ 1071 SLIST_FOREACH(tmp, &head[hash], next) { 1072 if (memcmp(&tmp->a.a6, &ent->a.a6, 16)) { 1073 exists = 1; 1074 break; 1075 } 1076 } 1077 } 1078 1079 if (exists == 1) { 1080 if ((tei->flags & TEI_FLAGS_UPDATE) == 0) 1081 return (EEXIST); 1082 /* Record already exists. Update value if we're asked to */ 1083 tmp->value = tei->value; 1084 /* Indicate that update has happened instead of addition */ 1085 tei->flags |= TEI_FLAGS_UPDATED; 1086 *pnum = 0; 1087 } else { 1088 SLIST_INSERT_HEAD(&head[hash], ent, next); 1089 tb->ent_ptr = NULL; 1090 *pnum = 1; 1091 } 1092 1093 return (0); 1094} 1095 1096static int 1097ta_prepare_del_chash(struct ip_fw_chain *ch, struct tentry_info *tei, 1098 void *ta_buf) 1099{ 1100 struct ta_buf_chash *tb; 1101 int mlen; 1102 struct in6_addr mask6; 1103 1104 tb = (struct ta_buf_chash *)ta_buf; 1105 memset(tb, 0, sizeof(struct ta_buf_chash)); 1106 1107 mlen = tei->masklen; 1108 1109 if (tei->subtype == AF_INET) { 1110#ifdef INET 1111 if (mlen > 32) 1112 return (EINVAL); 1113 tb->type = AF_INET; 1114 1115 /* Calculate masked address */ 1116 tb->a.a4 = ntohl(*((in_addr_t *)tei->paddr)) >> (32 - mlen); 1117#endif 1118#ifdef INET6 1119 } else if (tei->subtype == AF_INET6) { 1120 /* IPv6 case */ 1121 if (mlen > 128) 1122 return (EINVAL); 1123 tb->type = AF_INET6; 1124 1125 ipv6_writemask(&mask6, mlen); 1126 memcpy(&tb->a.a6, tei->paddr, sizeof(struct in6_addr)); 1127 APPLY_MASK(&tb->a.a6, &mask6); 1128#endif 1129 } else { 1130 /* Unknown CIDR type */ 1131 return (EINVAL); 1132 } 1133 1134 return (0); 1135} 1136 1137static int 1138ta_del_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei, 1139 void *ta_buf, uint64_t *pflags, uint32_t *pnum) 1140{ 1141 struct chash_cfg *ccfg; 1142 struct chashbhead *head; 1143 struct chashentry *ent, *tmp_next; 1144 struct ta_buf_chash *tb; 1145 uint32_t hash; 1146 1147 ccfg = (struct chash_cfg *)ta_state; 1148 tb = (struct ta_buf_chash *)ta_buf; 1149 1150 if (tei->subtype == AF_INET) { 1151 if (tei->masklen != ccfg->mask4) 1152 return (EINVAL); 1153 head = ccfg->head4; 1154 hash = hash_ip(tb->a.a4, ccfg->size4); 1155 1156 SLIST_FOREACH_SAFE(ent, &head[hash], next, tmp_next) { 1157 if (ent->a.a4 == tb->a.a4) { 1158 SLIST_REMOVE(&head[hash], ent, chashentry,next); 1159 *pnum = 1; 1160 return (0); 1161 } 1162 } 1163 } else { 1164 if (tei->masklen != ccfg->mask6) 1165 return (EINVAL); 1166 head = ccfg->head6; 1167 if (tei->masklen == 64) 1168 hash = hash_ip64(&tb->a.a6, ccfg->size6); 1169 else 1170 hash = hash_ip6(&tb->a.a6, ccfg->size6); 1171 1172 SLIST_FOREACH_SAFE(ent, &head[hash], next, tmp_next) { 1173 if (memcmp(&ent->a.a6, &tb->a.a6, 16)) { 1174 SLIST_REMOVE(&head[hash], ent, chashentry,next); 1175 *pnum = 1; 1176 return (0); 1177 } 1178 } 1179 } 1180 1181 return (ENOENT); 1182} 1183 1184static void 1185ta_flush_chash_entry(struct ip_fw_chain *ch, struct tentry_info *tei, 1186 void *ta_buf) 1187{ 1188 struct ta_buf_chash *tb; 1189 1190 tb = (struct ta_buf_chash *)ta_buf; 1191 1192 if (tb->ent_ptr != NULL) 1193 free(tb->ent_ptr, M_IPFW_TBL); 1194} 1195 1196struct table_algo cidr_hash = { 1197 .name = "cidr:hash", 1198 .lookup = ta_lookup_chash_slow, 1199 .init = ta_init_chash, 1200 .destroy = ta_destroy_chash, 1201 .prepare_add = ta_prepare_add_chash, 1202 .prepare_del = ta_prepare_del_chash, 1203 .add = ta_add_chash, 1204 .del = ta_del_chash, 1205 .flush_entry = ta_flush_chash_entry, 1206 .foreach = ta_foreach_chash, 1207 .dump_tentry = ta_dump_chash_tentry, 1208 .find_tentry = ta_find_chash_tentry, 1209 .print_config = ta_print_chash_config, 1210}; 1211 1212 1213/* |
|
534 * Iface table cmds. 535 * 536 * Implementation: 537 * 538 * Runtime part: 539 * - sorted array of "struct ifidx" pointed by ti->state. 540 * Array is allocated with routing up to IFIDX_CHUNK. Only existing 541 * interfaces are stored in array, however its allocated size is --- 13 unchanged lines hidden (view full) --- 555}; 556 557struct iftable_cfg; 558 559struct ifentry { 560 struct named_object no; 561 struct ipfw_ifc ic; 562 struct iftable_cfg *icfg; | 1214 * Iface table cmds. 1215 * 1216 * Implementation: 1217 * 1218 * Runtime part: 1219 * - sorted array of "struct ifidx" pointed by ti->state. 1220 * Array is allocated with routing up to IFIDX_CHUNK. Only existing 1221 * interfaces are stored in array, however its allocated size is --- 13 unchanged lines hidden (view full) --- 1235}; 1236 1237struct iftable_cfg; 1238 1239struct ifentry { 1240 struct named_object no; 1241 struct ipfw_ifc ic; 1242 struct iftable_cfg *icfg; |
563 TAILQ_ENTRY(ifentry) next; | |
564 uint32_t value; 565 int linked; 566}; 567 568struct iftable_cfg { 569 struct namedobj_instance *ii; 570 struct ip_fw_chain *ch; 571 struct table_info *ti; --- 211 unchanged lines hidden (view full) --- 783ta_prepare_add_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei, 784 void *ta_buf) 785{ 786 struct ta_buf_ifidx *tb; 787 char *ifname; 788 struct ifentry *ife; 789 790 tb = (struct ta_buf_ifidx *)ta_buf; | 1243 uint32_t value; 1244 int linked; 1245}; 1246 1247struct iftable_cfg { 1248 struct namedobj_instance *ii; 1249 struct ip_fw_chain *ch; 1250 struct table_info *ti; --- 211 unchanged lines hidden (view full) --- 1462ta_prepare_add_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei, 1463 void *ta_buf) 1464{ 1465 struct ta_buf_ifidx *tb; 1466 char *ifname; 1467 struct ifentry *ife; 1468 1469 tb = (struct ta_buf_ifidx *)ta_buf; |
791 memset(tb, 0, sizeof(struct ta_buf_cidr)); | 1470 memset(tb, 0, sizeof(struct ta_buf_ifidx)); |
792 793 /* Check if string is terminated */ 794 ifname = (char *)tei->paddr; 795 if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE) 796 return (EINVAL); 797 798 ife = malloc(sizeof(struct ifentry), M_IPFW_TBL, M_WAITOK | M_ZERO); 799 ife->value = tei->value; --- 72 unchanged lines hidden (view full) --- 872/* 873 * Prepare to delete key from table. 874 * Do basic interface name checks. 875 */ 876static int 877ta_prepare_del_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei, 878 void *ta_buf) 879{ | 1471 1472 /* Check if string is terminated */ 1473 ifname = (char *)tei->paddr; 1474 if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE) 1475 return (EINVAL); 1476 1477 ife = malloc(sizeof(struct ifentry), M_IPFW_TBL, M_WAITOK | M_ZERO); 1478 ife->value = tei->value; --- 72 unchanged lines hidden (view full) --- 1551/* 1552 * Prepare to delete key from table. 1553 * Do basic interface name checks. 1554 */ 1555static int 1556ta_prepare_del_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei, 1557 void *ta_buf) 1558{ |
880 struct ta_buf_iface *tb; | 1559 struct ta_buf_ifidx *tb; |
881 char *ifname; 882 | 1560 char *ifname; 1561 |
883 tb = (struct ta_buf_iface *)ta_buf; 884 memset(tb, 0, sizeof(struct ta_buf_cidr)); | 1562 tb = (struct ta_buf_ifidx *)ta_buf; 1563 memset(tb, 0, sizeof(struct ta_buf_ifidx)); |
885 886 /* Check if string is terminated */ 887 ifname = (char *)tei->paddr; 888 if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE) 889 return (EINVAL); 890 891 return (0); 892} --- 269 unchanged lines hidden (view full) --- 1162 icfg = (struct iftable_cfg *)ta_state; 1163 1164 wa.f = f; 1165 wa.arg = arg; 1166 1167 ipfw_objhash_foreach(icfg->ii, foreach_ifidx, &wa); 1168} 1169 | 1564 1565 /* Check if string is terminated */ 1566 ifname = (char *)tei->paddr; 1567 if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE) 1568 return (EINVAL); 1569 1570 return (0); 1571} --- 269 unchanged lines hidden (view full) --- 1841 icfg = (struct iftable_cfg *)ta_state; 1842 1843 wa.f = f; 1844 wa.arg = arg; 1845 1846 ipfw_objhash_foreach(icfg->ii, foreach_ifidx, &wa); 1847} 1848 |
1170struct table_algo idx_iface = { | 1849struct table_algo iface_idx = { |
1171 .name = "iface:array", 1172 .lookup = ta_lookup_ifidx, 1173 .init = ta_init_ifidx, 1174 .destroy = ta_destroy_ifidx, 1175 .prepare_add = ta_prepare_add_ifidx, 1176 .prepare_del = ta_prepare_del_ifidx, 1177 .add = ta_add_ifidx, 1178 .del = ta_del_ifidx, --- 9 unchanged lines hidden (view full) --- 1188}; 1189 1190void 1191ipfw_table_algo_init(struct ip_fw_chain *chain) 1192{ 1193 /* 1194 * Register all algorithms presented here. 1195 */ | 1850 .name = "iface:array", 1851 .lookup = ta_lookup_ifidx, 1852 .init = ta_init_ifidx, 1853 .destroy = ta_destroy_ifidx, 1854 .prepare_add = ta_prepare_add_ifidx, 1855 .prepare_del = ta_prepare_del_ifidx, 1856 .add = ta_add_ifidx, 1857 .del = ta_del_ifidx, --- 9 unchanged lines hidden (view full) --- 1867}; 1868 1869void 1870ipfw_table_algo_init(struct ip_fw_chain *chain) 1871{ 1872 /* 1873 * Register all algorithms presented here. 1874 */ |
1196 ipfw_add_table_algo(chain, &radix_cidr); 1197 ipfw_add_table_algo(chain, &idx_iface); | 1875 ipfw_add_table_algo(chain, &cidr_radix); 1876 ipfw_add_table_algo(chain, &cidr_hash); 1877 ipfw_add_table_algo(chain, &iface_idx); |
1198} 1199 1200void 1201ipfw_table_algo_destroy(struct ip_fw_chain *chain) 1202{ 1203 /* Do nothing */ 1204} 1205 1206 | 1878} 1879 1880void 1881ipfw_table_algo_destroy(struct ip_fw_chain *chain) 1882{ 1883 /* Do nothing */ 1884} 1885 1886 |