Deleted Added
full compact
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