original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
@@ -0,0 +1,906 @@
/*
******************************************************************************
* 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 <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 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 <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_sock.h>
#include <ipcom_syslog.h>
#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
****************************************************************************
*/