/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_classifier.c,v $ $Revision: 1.18.54.2 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_classifier.c,v $ * $Author: svc-cmnet $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* Generic classifier for IPv4 and IPv6 packets This module is used to map packet content to a tag. The tag is an integer. */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifndef IPCOM_KERNEL #define IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include "ipnet_classifier.h" #include "ipnet_h.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* All fields must be in network byte order */ typedef struct Ipnet_classifier_map_struct { Ipcom_list list; /* The tag packets matching these fields are mapped to */ int tag; /* The ID of this rule to tag mapping */ int id; /* Rule to determine which packetets that will get the tag */ struct Ipnet_classifier_rule rule; } Ipnet_classifier_map; /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_classifier_addr_match *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ip_bool ipnet_classifier_addr_match(const void *addr_arg, const struct Ipnet_classifier_rule *cr, Ip_bool is_src) { int byte; int bytes; int bits; const Ip_u8 *addr = (const Ip_u8 *) addr_arg; const Ip_u8 *key; if (is_src) { key = (const Ip_u8 *) &cr->saddr; bits = cr->saddr_prefixlen; } else { key = (const Ip_u8 *) &cr->daddr; bits = cr->daddr_prefixlen; } bytes = (bits + 7) >> 3; for (byte = 0; byte < bytes; byte++, bits -= 8) if ((addr[byte] ^ key[byte]) >= (1 << (8 - IP_MIN(bits, 8)))) { if (addr[byte] != key[byte]) return IP_FALSE; } return IP_TRUE; } /* *=========================================================================== * ipnet_classifier_port_match *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ip_bool ipnet_classifier_port_match(const Ipnet_pkt_udp *udp, const struct Ipnet_classifier_rule *cr) { Ip_u16 sport = ip_ntohs(udp->sport); Ip_u16 dport = ip_ntohs(udp->dport); if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_SPORT) && (sport < cr->sport_low || sport > cr->sport_high)) return IP_FALSE; if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_DPORT) && (dport < cr->dport_low || dport > cr->dport_high)) return IP_FALSE; return IP_TRUE; } /* *=========================================================================== * ipnet_classifier_ip4_get_tag *=========================================================================== * Description: Returns the tag for an IPv4 packet. * Parameters: * Returns: * */ #ifdef IPCOM_USE_INET IP_STATIC int ipnet_classifier_ip4_get_tag(Ipnet_classifier *c, Ipcom_pkt *pkt) { Ipnet_classifier_map *cm; Ipnet_pkt_ip *ip; Ipnet_pkt_udp *udp; ip = (Ipnet_pkt_ip *) &pkt->data[pkt->ipstart]; if (ip->p == IP_IPPROTO_UDP || ip->p == IP_IPPROTO_TCP || ip->p == IP_IPPROTO_SCTP) udp = (Ipnet_pkt_udp *) &pkt->data[pkt->ipstart + IPNET_IP4_GET_HDR_LEN(ip) * 4]; else udp = IP_NULL; for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_NEXT(&cm->list)) { #if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA) /* ONLY for differ server, maybe ugly */ if (c == ipnet->diffserv.classifier) { /* if this is a forwarding packet, use the forward rule */ if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_FORWARDED) && IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_LOCAL)) continue; /* if this is a local packet, use the local rule */ if (IP_BIT_ISFALSE(pkt->flags, IPCOM_PKT_FLAG_FORWARDED) && IP_BIT_ISFALSE(cm->rule.mask, IPNET_CLS_RULE_LOCAL)) continue; } #endif if (cm->rule.af != 0 && cm->rule.af != IP_AF_INET) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_DS) && ip->tos != cm->rule.ds) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_PROTO) && ip->p != cm->rule.proto) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_SADDR) && !ipnet_classifier_addr_match(ip->src, &cm->rule, IP_TRUE)) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_DADDR) && !ipnet_classifier_addr_match(ip->dst, &cm->rule, IP_FALSE)) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_SPORT | IPNET_CLS_RULE_DPORT) && udp != IP_NULL && !ipnet_classifier_port_match(udp, &cm->rule)) continue; return cm->tag; } return IPNET_CLASSIFIER_INVALID_TAG; } #endif /* IPCOM_USE_INET */ /* *=========================================================================== * ipnet_classifier_ip6_get_tag *=========================================================================== * Description: Returns the tag for an IPv6 packet. * Parameters: * Returns: * */ #ifdef IPCOM_USE_INET6 IP_STATIC int ipnet_classifier_ip6_get_tag(Ipnet_classifier *c, Ipcom_pkt *pkt) { Ipnet_classifier_map *cm; Ipnet_pkt_udp *udp; Ipnet_pkt_ip6 *ip6; Ip_u8 tclass; int first_nonexthdr; ip6 = (Ipnet_pkt_ip6 *) &pkt->data[pkt->ipstart]; tclass = IPNET_IP6_GET_CLASS(ip6); first_nonexthdr = ipnet_ip6_get_first_nonexthdr(ip6, (Ip_u8 **)&udp); if (first_nonexthdr != IP_IPPROTO_UDP && first_nonexthdr != IP_IPPROTO_TCP && first_nonexthdr != IP_IPPROTO_SCTP) udp = IP_NULL; for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_NEXT(&cm->list)) { #if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA) /* ONLY for differ server, maybe ugly */ if (c == ipnet->diffserv.classifier) { /* if this is a forwarding packet, use the forward rule */ if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_FORWARDED) && IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_LOCAL)) continue; /* if this is a local packet, use the local rule */ if (IP_BIT_ISFALSE(pkt->flags, IPCOM_PKT_FLAG_FORWARDED) && IP_BIT_ISFALSE(cm->rule.mask, IPNET_CLS_RULE_LOCAL)) continue; } #endif if (cm->rule.af != 0 && cm->rule.af != IP_AF_INET6) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_DS) && tclass != cm->rule.ds) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_PROTO) && ip6->nxt != cm->rule.proto) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_SADDR) && !ipnet_classifier_addr_match(&ip6->src, &cm->rule, IP_TRUE)) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_DADDR) && !ipnet_classifier_addr_match(&ip6->dst, &cm->rule, IP_FALSE)) continue; if (IP_BIT_ISSET(cm->rule.mask, IPNET_CLS_RULE_SPORT | IPNET_CLS_RULE_DPORT) && udp != IP_NULL && !ipnet_classifier_port_match(udp, &cm->rule)) continue; return cm->tag; } return IPNET_CLASSIFIER_INVALID_TAG; } #endif /* IPCOM_USE_INET6 */ /* *=========================================================================== * ipnet_classifier_get_map *=========================================================================== * Description: Returns the mapping that matches the ID. * Parameters: c - A classifier. * id - The ID of the mapping to return. * Returns: The matching mapping or IP_NULL if not found. * */ IP_STATIC Ipnet_classifier_map * ipnet_classifier_get_map(Ipnet_classifier *c, int id) { Ipnet_classifier_map *cm; for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_NEXT(&cm->list)) if (id == cm->id) return cm; return IP_NULL; } /* *=========================================================================== * ipnet_classifier_set_prefixlen *=========================================================================== * Description: Adds a new packet fields to tag mapping in a classifier. * Parameters: c - The classifier this mapping should be inserted into. * rule - The fields that must match. * id - An unique identifier for this rule. * Returns: 0 = success. * <0 = error code. * */ IP_STATIC int ipnet_classifier_set_prefixlen(struct Ipnet_classifier_rule *rule) { Ip_u8 addr_bit_len; ip_assert(IP_NULL != rule); switch (rule->af) { #ifdef IPCOM_USE_INET case IP_AF_INET: addr_bit_len = sizeof(struct Ip_in_addr) * 8u; break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: addr_bit_len = sizeof(struct Ip_in6_addr) * 8u; break; #endif default: if (IP_BIT_ISSET(rule->mask, IPNET_CLS_RULE_DADDR) || IP_BIT_ISSET(rule->mask, IPNET_CLS_RULE_SADDR)) { IPCOM_LOG1(ERR, "Packet classifier: Address field used but no domain specified %d", rule->af); return -IP_ERRNO_EINVAL; } addr_bit_len = 0; break; } if (rule->saddr_prefixlen == 0) rule->saddr_prefixlen = addr_bit_len; if (rule->daddr_prefixlen == 0) rule->daddr_prefixlen = addr_bit_len; if (rule->saddr_prefixlen > addr_bit_len || rule->daddr_prefixlen > addr_bit_len) { IPCOM_LOG1(ERR, "Packet classifier: prefixlen is too big, max is %d bits", addr_bit_len); return -IP_ERRNO_EINVAL; } return 0; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_classifier_pkt_to_tag *=========================================================================== * Description: Returns the tag that matches the specified packet. * Parameters: fields - Array of hashtables with exact (or net) matches. * wildecards - Array of masks for tags that match any value. * pkt - The packet to match to a tag, pkt->ipstart must be * the offset to the IP header. * Returns: The matching tag or -1 if no tag matches. * */ IP_GLOBAL int ipnet_classifier_pkt_to_tag(Ipnet_classifier *c, Ipcom_pkt *pkt) { if (pkt->ipstart < pkt->start || pkt->ipstart >= pkt->end) /* Not a IPv4 or IPv6 packet */ return IPNET_CLASSIFIER_INVALID_TAG; switch (pkt->data[pkt->ipstart] & 0xf0) { #ifdef IPCOM_USE_INET case 0x40: return ipnet_classifier_ip4_get_tag(c, pkt); #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 case 0x60: return ipnet_classifier_ip6_get_tag(c, pkt); #endif /* IPCOM_USE_INET6 */ default: IP_PANIC2(); return IPNET_CLASSIFIER_INVALID_TAG; } } /* *=========================================================================== * ipnet_classifier_set_tag *=========================================================================== * Description: Sets the tag value for a specific mapping. * Parameters: c - A classifier. * id - ID of the mapping. * tag - Tag to set on the mapping. * Returns: 0 = success * <0 = error code. * */ IP_GLOBAL int ipnet_classifier_set_tag(Ipnet_classifier *c, int id, int tag) { Ipnet_classifier_map *map; map = ipnet_classifier_get_map(c, id); if (map == IP_NULL) return -IP_ERRNO_ESRCH; map->tag = tag; return 0; } /* *=========================================================================== * ipnet_classifier_invalidate_tag *=========================================================================== * Description: Invalidates all entries matching the specified tag. * Parameters: c - A classifier. * tag - Tag to invalidate. * Returns: * */ IP_GLOBAL void ipnet_classifier_invalidate_tag(Ipnet_classifier *c, int tag) { Ipnet_classifier_map *cm; for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_NEXT(&cm->list)) { if (cm->tag == tag) cm->tag = IPNET_CLASSIFIER_INVALID_TAG; } } /* *=========================================================================== * ipnet_classifier_get_smallest_unused_tag *=========================================================================== * Description: Returns the smalles tag that is not in used in the specified * classifier. * Parameters: c - A classifier. * Returns: The smallest unused tag. * */ IP_GLOBAL int ipnet_classifier_get_smallest_unused_id(Ipnet_classifier *c) { int id = 0; while (ipnet_classifier_get_map(c, id) != IP_NULL) id++; return id; } /* *=========================================================================== * ipnet_classifier_add_mapping *=========================================================================== * Description: Adds a new packet fields to tag mapping in a classifier. * Parameters: c - The classifier this mapping should be inserted into. * rule - The fields that must match. * id - An unique identifier for this rule. * Returns: 0 = success. * <0 = error code. * */ IP_GLOBAL int ipnet_classifier_add_mapping(Ipnet_classifier *c, struct Ipnet_classifier_rule *rule, int id) { Ipnet_classifier_map *map; Ipnet_classifier_map *cur_map; Ip_u8 max_prefixlen = 0; if (ipnet_classifier_get_map(c, id) != IP_NULL) { IPCOM_LOG1(ERR, "Packet classifier: ID %d already exists", id); return -IP_ERRNO_EEXIST; } map = ipcom_calloc(1, sizeof(Ipnet_classifier_map)); if (map == IP_NULL) { IPCOM_LOG1(CRIT, "Packet classifier: Failed to allocate memory (%d bytes) for a map", sizeof(Ipnet_classifier_map)); return -IP_ERRNO_ENOMEM; } ipcom_memcpy(&map->rule, rule, sizeof(map->rule)); map->id = id; map->tag = -1; if (ipnet_classifier_set_prefixlen(&map->rule) < 0) { ipcom_free(map); return -IP_ERRNO_EINVAL; } if (map->rule.sport_low > map->rule.sport_high || map->rule.dport_low > map->rule.dport_high) { IPCOM_LOG0(ERR, "Packet classifier: low port must be equal-to or smaller than high port"); ipcom_free(map); return -IP_ERRNO_EINVAL; } /* * NOTE : we assume that the port and address range SHOULD NOT overlape. * 1, if exist we will apply the rule with first match * 2, the search sequence is the same as display command */ for (cur_map = IPCOM_LIST_FIRST(&c->rules); cur_map != IP_NULL; cur_map = IPCOM_LIST_NEXT(&cur_map->list)) { if (cur_map->rule.af != map->rule.af) continue; /* Current entry has dst_port and new not -> insert after this entry */ if (IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_DPORT) && IP_BIT_ISFALSE(map->rule.mask, IPNET_CLS_RULE_DPORT)) continue; /* New entry has dst_port and current not -> insert before this entry */ if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_DPORT) && IP_BIT_ISFALSE(cur_map->rule.mask, IPNET_CLS_RULE_DPORT)) break; if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_DPORT) && IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_DPORT)) { /* Current entry is exact dst_port and new a range -> insert after this entry */ if (cur_map->rule.dport_low == cur_map->rule.dport_high && map->rule.dport_low != map->rule.dport_high) continue; /* New entry is exact dst_port and current a range -> insert before this entry */ if (map->rule.dport_low == map->rule.dport_high && cur_map->rule.dport_low != cur_map->rule.dport_high) break; } /* Current entry has src_port and new not -> insert after this entry */ if (IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_SPORT) && IP_BIT_ISFALSE(map->rule.mask, IPNET_CLS_RULE_SPORT)) continue; /* New entry has src_port and current not -> insert before this entry */ if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_SPORT) && IP_BIT_ISFALSE(cur_map->rule.mask, IPNET_CLS_RULE_SPORT)) break; if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_SPORT) && IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_SPORT)) { /* Current entry is exact src_port and new a range -> insert after this entry */ if (cur_map->rule.sport_low == cur_map->rule.sport_high && map->rule.sport_low != map->rule.sport_high) continue; /* New entry is exact src_port and current a range -> insert before this entry */ if (map->rule.sport_low == map->rule.sport_high && cur_map->rule.sport_low != cur_map->rule.sport_high) break; } #ifdef IPCOM_USE_INET if (cur_map->rule.af == IP_AF_INET) max_prefixlen = 32; #endif #ifdef IPCOM_USE_INET6 if (cur_map->rule.af == IP_AF_INET6) max_prefixlen = 128; #endif /* ip_assert(0 != max_prefixlen); */ /* Destination address */ /* Current entry has dst_addr and new not -> insert after this entry */ if (IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_DADDR) && IP_BIT_ISFALSE(map->rule.mask, IPNET_CLS_RULE_DADDR)) continue; /* New entry has dst_addr and current not -> insert before this entry */ if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_DADDR) && IP_BIT_ISFALSE(cur_map->rule.mask, IPNET_CLS_RULE_DADDR)) break; if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_DADDR) && IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_DADDR)) { /* Current entry is host and new a subnet -> insert after this entry */ if (cur_map->rule.daddr_prefixlen == max_prefixlen && map->rule.daddr_prefixlen < max_prefixlen) continue; /* New entry is host and current a subnet -> insert before this entry */ if (map->rule.daddr_prefixlen == max_prefixlen && cur_map->rule.daddr_prefixlen < max_prefixlen) break; /* New entry has smaller dst mask than current -> insert after this entry */ if (map->rule.daddr_prefixlen < cur_map->rule.daddr_prefixlen) continue; /* New entry has larger dst mask than current -> insert before this entry */ if (map->rule.daddr_prefixlen > cur_map->rule.daddr_prefixlen) break; } /* Source address */ /* Current entry has src_addr and new not -> insert after this entry */ if (IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_SADDR) && IP_BIT_ISFALSE(map->rule.mask, IPNET_CLS_RULE_SADDR)) continue; /* New entry has src_addr and current not -> insert before this entry */ if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_SADDR) && IP_BIT_ISFALSE(cur_map->rule.mask, IPNET_CLS_RULE_SADDR)) break; if (IP_BIT_ISSET(map->rule.mask, IPNET_CLS_RULE_SADDR) && IP_BIT_ISSET(cur_map->rule.mask, IPNET_CLS_RULE_SADDR)) { /* Current entry is host and new a subnet -> insert after this entry */ if (cur_map->rule.saddr_prefixlen == max_prefixlen && map->rule.saddr_prefixlen < max_prefixlen) continue; /* New entry is host and current a subnet -> insert before this entry */ if (map->rule.saddr_prefixlen == max_prefixlen && cur_map->rule.saddr_prefixlen < max_prefixlen) break; /* New entry has smaller src mask than current -> insert after this entry */ if (map->rule.saddr_prefixlen < cur_map->rule.saddr_prefixlen) continue; /* New entry has larger src mask than current -> insert before this entry */ if (map->rule.saddr_prefixlen > cur_map->rule.saddr_prefixlen) break; } } if (cur_map != IP_NULL) ipcom_list_insert_before(&cur_map->list, &map->list); else ipcom_list_insert_last(&c->rules, &map->list); return 0; } /* *=========================================================================== * ipnet_classifier_del_mapping *=========================================================================== * Description: Deletes a packet to tag mapping. * Parameters: c - The classifier to operate on. * id - Id of the mapping to remove. * Returns: * */ IP_GLOBAL int ipnet_classifier_del_mapping(Ipnet_classifier *c, int id) { Ipnet_classifier_map *cm; cm = ipnet_classifier_get_map(c, id); if (cm == IP_NULL) return -IP_ERRNO_ESRCH; ipcom_list_remove(&cm->list); ipcom_free(cm); return 0; } #if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA) /* *=========================================================================== * ipnet_classifier_get_filter *=========================================================================== * Description: Returns the mapping that matches the DS get inforamtion. * Parameters: c - A classifier. * gi - The information of the mapping to match. * Returns: The matching mapping or IP_NULL if not found. * */ IP_GLOBAL int ipnet_classifier_get_filter(Ipnet_classifier *c, struct Ipnet_ds_get_infor *gi) { Ipnet_classifier_map *cm; ip_assert(IP_NULL != c); ip_assert(IP_NULL != gi); if (ipnet_classifier_set_prefixlen(&gi->f.rule) < 0) return -IP_ERRNO_EINVAL; for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_NEXT(&cm->list)) { /* compare each entry */ if (ipcom_memcmp(&gi->f.rule, &cm->rule, sizeof(cm->rule))) continue; gi->f.id = cm->id; gi->ds.id = cm->tag; return 0; } return -IP_ERRNO_ESRCH; } /* *=========================================================================== * ipnet_classifier_get_next_filter *=========================================================================== * Description: Returns the next mapping that matches the DS get inforamtion. * Parameters: c - A classifier. * gi - The information of the mapping to match. * Returns: The next matching mapping or IP_NULL if not found. * */ IP_GLOBAL int ipnet_classifier_get_next_filter(Ipnet_classifier *c, struct Ipnet_ds_get_infor *gi) { Ipnet_classifier_map *cm; Ipnet_classifier_map *cm_next = IP_NULL; Ipnet_diffserv_handlers *h; ip_assert(IP_NULL != c); ip_assert(IP_NULL != gi); for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_NEXT(&cm->list)) { /* get the first entry */ if (gi->f.id < 0) { cm_next = cm; break; } /* get the next entry */ else if (gi->f.id == cm->id) { cm_next = IPCOM_LIST_NEXT(&cm->list); break; } } if (IP_NULL == cm_next) { gi->f.id = -1; return 0; } ipcom_memcpy((void *)&gi->f.rule, (void *)&cm_next->rule, (Ip_size_t)sizeof(cm_next->rule)); gi->f.id = cm_next->id; h = ipnet->diffserv.handlers[cm_next->tag]; ip_assert(IP_NULL != h); ip_assert(IP_NULL != h->get_conf); /* get the detail configuration */ h->get_conf(h, &gi->ds); return 0; } #endif /* *=========================================================================== * ipnet_classifier_new *=========================================================================== * Description: Creating a new classifier database. * Parameters: * Returns: An empty classifier. * */ IP_GLOBAL Ipnet_classifier * ipnet_classifier_new(void) { Ipnet_classifier *c; c = ipcom_calloc(1, sizeof(Ipnet_classifier)); if (c == IP_NULL) { IPCOM_LOG1(CRIT, "Packet classifier: Out of memory when allocating %d bytes", sizeof(Ipnet_classifier)); return IP_NULL; } ipcom_list_init(&c->rules); return c; } /* *=========================================================================== * ipnet_classifier_delete *=========================================================================== * Description: Frees all resources allocated by the classifier. * Parameters: c - The classifier to delete. * Returns: * */ IP_GLOBAL void ipnet_classifier_delete(Ipnet_classifier *c) { Ipnet_classifier_map *cm; for (cm = IPCOM_LIST_FIRST(&c->rules); cm != IP_NULL; cm = IPCOM_LIST_FIRST(&c->rules)) { ipcom_list_remove(&cm->list); ipcom_free(cm); } ipcom_free(c); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */