enhanced the constant value handling

This commit is contained in:
hyung-hwan 2017-12-14 10:02:44 +00:00
parent 1f56b6cf93
commit 2172fa59a5
4 changed files with 329 additions and 197 deletions

View File

@ -132,6 +132,10 @@ QSE_EXPORT const qse_mchar_t* qse_mbsbasename (
const qse_mchar_t* path
);
/**
* The qse_substmbsbasenamedup() function creates a new string composed of
* the base directory part of the given \a path and \a file combined.
*/
QSE_EXPORT qse_mchar_t* qse_substmbsbasenamedup (
const qse_mchar_t* path,
const qse_mchar_t* file,
@ -289,7 +293,10 @@ QSE_EXPORT qse_size_t qse_canonwcspath (
int flags
);
/**
* The qse_substwcsbasenamedup() function creates a new string composed of
* the base directory part of the given \a path and \a file combined.
*/
QSE_EXPORT qse_wchar_t* qse_mergewcspathdup (
const qse_wchar_t* dir,
const qse_wchar_t* file,

View File

@ -39,7 +39,8 @@ typedef enum qse_raddic_opt_t qse_raddic_opt_t;
enum qse_raddic_trait_t
{
QSE_RADDIC_ALLOW_CONST_WITHOUT_ATTR = (1 << 0),
QSE_RADDIC_ALLOW_DUPLICATE_CONST = (1 << 1)
QSE_RADDIC_ALLOW_DUPLICATE_CONST = (1 << 1),
QSE_RADDIC_IGNORE_UNKNOWN_ATTR_FLAG = (1 << 2)
};
typedef enum qse_raddic_trait_t qse_raddic_trait_t;
@ -59,24 +60,6 @@ enum qse_raddic_errnum_t
typedef enum qse_raddic_errnum_t qse_raddic_errnum_t;
#if 0
#define QSE_RADDIC_ATTR_TYPE_STRING 0
#define QSE_RADDIC_ATTR_TYPE_INTEGER 1
#define QSE_RADDIC_ATTR_TYPE_IPADDR 2
#define QSE_RADDIC_ATTR_TYPE_DATE 3
#define QSE_RADDIC_ATTR_TYPE_ABINARY 4
#define QSE_RADDIC_ATTR_TYPE_OCTETS 5
#define QSE_RADDIC_ATTR_TYPE_IFID 6
#define QSE_RADDIC_ATTR_TYPE_IPV6ADDR 7
#define QSE_RADDIC_ATTR_TYPE_IPV6PREFIX 8
#define QSE_RADDIC_ATTR_TYPE_BYTE 9
#define QSE_RADDIC_ATTR_TYPE_SHORT 10
#define QSE_RADDIC_ATTR_TYPE_ETHERNET 11
#define QSE_RADDIC_ATTR_TYPE_SIGNED 12
#define QSE_RADDIC_ATTR_TYPE_COMBO_IP 13
#define QSE_RADDIC_ATTR_TYPE_TLV 14
#endif
enum qse_raddic_attr_type_t
{
QSE_RADDIC_ATTR_TYPE_INVALID = 0,
@ -130,20 +113,34 @@ enum qse_raddic_attr_type_t
};
typedef enum qse_raddic_attr_type_t qse_raddic_attr_type_t;
enum qse_raddic_attr_flag_encrypt_t
{
QSE_RADDIC_ATTR_FLAG_ENCRYPT_NONE = 0, /* keep this entry on top */
QSE_RADDIC_ATTR_FLAG_ENCRYPT_USER_PASSWORD, /* RFC2865 */
QSE_RADDIC_ATTR_FLAG_ENCRYPT_TUNNEL_PASSWORD, /* RFC2868 */
QSE_RADDIC_ATTR_FLAG_ENCRYPT_ASCEND_SECRET,
QSE_RADDIC_ATTR_FLAG_ENCRYPT_OTHER /* keep this entry at the bottom */
};
typedef enum qse_raddic_attr_flag_encrypt_t qse_raddic_attr_flag_encrypt_t;
struct qse_raddic_attr_flags_t
{
unsigned int addport : 1; /* add NAS-Port to IP address */
unsigned int has_tag : 1; /* tagged attribute */
unsigned int do_xlat : 1; /* strvalue is dynamic */
unsigned int unknown_attr : 1; /* not in dictionary */
unsigned int array : 1; /* pack multiples into 1 attr */
unsigned int has_value : 1; /* has a value */
unsigned int has_value_alias : 1; /* has a value alias */
unsigned int has_tlv : 1; /* has sub attributes */
unsigned int is_tlv : 1; /* is a sub attribute */
unsigned int encoded : 1; /* has been put into packet */
qse_int8_t tag; /* tag for tunneled attributes */
qse_uint8_t encrypt; /* encryption method */
unsigned int addport: 1; /* add NAS-Port to IP address */
unsigned int has_tag: 1; /* tagged attribute */
unsigned int unknown_attr: 1; /* not in dictionary */
unsigned int array: 1; /* pack multiples into 1 attr */
unsigned int concat: 1;
unsigned int internal: 1; /* internal use only */
unsigned int has_value: 1; /* has a value */
unsigned int has_tlv: 1; /* has sub attributes */
unsigned int is_tlv: 1; /* is a sub attribute */
qse_int8_t tag; /* tag for tunneled attributes */
qse_uint8_t length;
qse_raddic_attr_flag_encrypt_t encrypt; /* encryption method */
};
typedef struct qse_raddic_attr_flags_t qse_raddic_attr_flags_t;
@ -151,20 +148,43 @@ typedef struct qse_raddic_attr_t qse_raddic_attr_t;
struct qse_raddic_attr_t
{
qse_uint32_t attr;
int type;
qse_raddic_attr_type_t type;
int vendor;
qse_raddic_attr_flags_t flags;
qse_raddic_attr_t* nexta;
qse_char_t name[1];
};
typedef struct qse_raddic_const_value_t qse_raddic_const_value_t;
struct qse_raddic_const_value_t
{
qse_raddic_attr_type_t type;
union
{
qse_uint8_t ui8;
qse_uint16_t ui16;
qse_uint32_t ui32;
qse_uint64_t ui64;
qse_int8_t i8;
qse_int16_t i16;
qse_int32_t i32;
qse_int64_t i64;
qse_flt_t f32;
qse_flt_t f64;
/* TODO: more to come like ip address */
} u;
};
typedef struct qse_raddic_const_t qse_raddic_const_t;
struct qse_raddic_const_t
{
qse_uint32_t attr; /* vendor + attribute-value */
int value;
qse_raddic_const_t* nextc;
qse_char_t name[1];
qse_uint32_t attr; /* vendor + attribute-value */
qse_raddic_const_value_t value;
qse_raddic_const_t* nextc;
qse_char_t name[1];
};
typedef struct qse_raddic_vendor_t qse_raddic_vendor_t;
@ -265,8 +285,6 @@ QSE_EXPORT int qse_raddic_deletevendorbyvalue (
);
QSE_EXPORT qse_raddic_attr_t* qse_raddic_findattrbyname (
qse_raddic_t* dic,
const qse_char_t* name
@ -281,7 +299,7 @@ QSE_EXPORT qse_raddic_attr_t* qse_raddic_addattr (
qse_raddic_t* dic,
const qse_char_t* name,
int vendor,
int type,
qse_raddic_attr_type_t type,
int value,
const qse_raddic_attr_flags_t* flags
);
@ -293,7 +311,7 @@ QSE_EXPORT int qse_raddic_deleteattrbyname (
QSE_EXPORT int qse_raddic_deleteattrbyvalue (
qse_raddic_t* dic,
int attr
qse_uint32_t attr
);
@ -304,16 +322,16 @@ QSE_EXPORT qse_raddic_const_t* qse_raddic_findconstbyname (
);
QSE_EXPORT qse_raddic_const_t* qse_raddic_findconstbyvalue (
qse_raddic_t* dic,
qse_uint32_t attr,
int value
qse_raddic_t* dic,
qse_uint32_t attr,
const qse_raddic_const_value_t* value
);
QSE_EXPORT qse_raddic_const_t* qse_raddic_addconst (
qse_raddic_t* dic,
const qse_char_t* name,
const qse_char_t* attrstr,
int value
qse_raddic_t* dic,
const qse_char_t* name,
const qse_char_t* attrstr,
const qse_raddic_const_value_t* value
);
QSE_EXPORT int qse_raddic_deleteconstbyname (
@ -323,9 +341,9 @@ QSE_EXPORT int qse_raddic_deleteconstbyname (
);
QSE_EXPORT int qse_raddic_deleteconstbyvalue (
qse_raddic_t* dic,
qse_uint32_t attr,
int value
qse_raddic_t* dic,
qse_uint32_t attr,
const qse_raddic_const_value_t* value
);

View File

@ -56,10 +56,6 @@
#include <qse/si/sio.h>
#include <stdarg.h>
#include <stdio.h>
#define fr_strerror_printf printf
typedef struct const_fixup_t const_fixup_t;
struct const_fixup_t
@ -98,95 +94,82 @@ struct name_id_t
{
const qse_char_t* name;
int id;
int length;
};
static const name_id_t type_table[] =
{
{ QSE_T("string"), QSE_RADDIC_ATTR_TYPE_STRING },
{ QSE_T("octets"), QSE_RADDIC_ATTR_TYPE_OCTETS },
{ QSE_T("string"), QSE_RADDIC_ATTR_TYPE_STRING, -1 },
{ QSE_T("octets"), QSE_RADDIC_ATTR_TYPE_OCTETS, -1 },
{ QSE_T("ipaddr"), QSE_RADDIC_ATTR_TYPE_IPV4_ADDR },
{ QSE_T("ipv4prefix"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX },
{ QSE_T("ipv6addr"), QSE_RADDIC_ATTR_TYPE_IPV6_ADDR },
{ QSE_T("ipv6prefix"), QSE_RADDIC_ATTR_TYPE_IPV6_PREFIX },
{ QSE_T("ifid"), QSE_RADDIC_ATTR_TYPE_IFID },
{ QSE_T("combo-ip"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_ADDR },
{ QSE_T("combo-prefix"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_PREFIX },
{ QSE_T("ether"), QSE_RADDIC_ATTR_TYPE_ETHERNET },
{ QSE_T("ipaddr"), QSE_RADDIC_ATTR_TYPE_IPV4_ADDR, 4 },
{ QSE_T("ipv4prefix"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX, -1 },
{ QSE_T("ipv6addr"), QSE_RADDIC_ATTR_TYPE_IPV6_ADDR, 16 },
{ QSE_T("ipv6prefix"), QSE_RADDIC_ATTR_TYPE_IPV6_PREFIX, -1 },
{ QSE_T("ifid"), QSE_RADDIC_ATTR_TYPE_IFID, 8 },
{ QSE_T("combo-ip"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_ADDR, -1 },
{ QSE_T("combo-prefix"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_PREFIX, -1 },
{ QSE_T("ether"), QSE_RADDIC_ATTR_TYPE_ETHERNET, 6 },
{ QSE_T("bool"), QSE_RADDIC_ATTR_TYPE_BOOL },
{ QSE_T("bool"), QSE_RADDIC_ATTR_TYPE_BOOL, 1 },
{ QSE_T("uint8"), QSE_RADDIC_ATTR_TYPE_UINT8 },
{ QSE_T("uint16"), QSE_RADDIC_ATTR_TYPE_UINT16 },
{ QSE_T("uint32"), QSE_RADDIC_ATTR_TYPE_UINT32 },
{ QSE_T("uint64"), QSE_RADDIC_ATTR_TYPE_UINT64 },
{ QSE_T("uint8"), QSE_RADDIC_ATTR_TYPE_UINT8, 1 },
{ QSE_T("uint16"), QSE_RADDIC_ATTR_TYPE_UINT16, 2 },
{ QSE_T("uint32"), QSE_RADDIC_ATTR_TYPE_UINT32, 4 },
{ QSE_T("uint64"), QSE_RADDIC_ATTR_TYPE_UINT64, 8 },
{ QSE_T("int8"), QSE_RADDIC_ATTR_TYPE_INT8 },
{ QSE_T("int16"), QSE_RADDIC_ATTR_TYPE_INT16 },
{ QSE_T("int32"), QSE_RADDIC_ATTR_TYPE_INT32 },
{ QSE_T("int64"), QSE_RADDIC_ATTR_TYPE_INT64 },
{ QSE_T("int8"), QSE_RADDIC_ATTR_TYPE_INT8, 1 },
{ QSE_T("int16"), QSE_RADDIC_ATTR_TYPE_INT16, 2 },
{ QSE_T("int32"), QSE_RADDIC_ATTR_TYPE_INT32, 4 },
{ QSE_T("int64"), QSE_RADDIC_ATTR_TYPE_INT64, 8 },
{ QSE_T("float32"), QSE_RADDIC_ATTR_TYPE_FLOAT32 },
{ QSE_T("float64"), QSE_RADDIC_ATTR_TYPE_FLOAT64 },
{ QSE_T("float32"), QSE_RADDIC_ATTR_TYPE_FLOAT32, 4 },
{ QSE_T("float64"), QSE_RADDIC_ATTR_TYPE_FLOAT64, 8 },
{ QSE_T("timeval"), QSE_RADDIC_ATTR_TYPE_TIMEVAL },
{ QSE_T("date"), QSE_RADDIC_ATTR_TYPE_DATE },
{ QSE_T("date_milliseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MILLISECONDS },
{ QSE_T("date_microseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MICROSECONDS },
{ QSE_T("date_nanoseconds"), QSE_RADDIC_ATTR_TYPE_DATE_NANOSECONDS },
{ QSE_T("timeval"), QSE_RADDIC_ATTR_TYPE_TIMEVAL, -1 },
{ QSE_T("date"), QSE_RADDIC_ATTR_TYPE_DATE, 4 },
{ QSE_T("date_milliseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MILLISECONDS, -1 },
{ QSE_T("date_microseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MICROSECONDS, -1 },
{ QSE_T("date_nanoseconds"), QSE_RADDIC_ATTR_TYPE_DATE_NANOSECONDS, -1 },
{ QSE_T("abinary"), QSE_RADDIC_ATTR_TYPE_ABINARY },
{ QSE_T("abinary"), QSE_RADDIC_ATTR_TYPE_ABINARY, -1 },
{ QSE_T("size"), QSE_RADDIC_ATTR_TYPE_SIZE },
{ QSE_T("size"), QSE_RADDIC_ATTR_TYPE_SIZE, 8 },
{ QSE_T("tlv"), QSE_RADDIC_ATTR_TYPE_TLV },
{ QSE_T("struct"), QSE_RADDIC_ATTR_TYPE_STRUCT },
{ QSE_T("tlv"), QSE_RADDIC_ATTR_TYPE_TLV, -1 },
{ QSE_T("struct"), QSE_RADDIC_ATTR_TYPE_STRUCT, -1 },
{ QSE_T("extended"), QSE_RADDIC_ATTR_TYPE_EXTENDED },
{ QSE_T("long-extended"), QSE_RADDIC_ATTR_TYPE_LONG_EXTENDED },
{ QSE_T("extended"), QSE_RADDIC_ATTR_TYPE_EXTENDED, 0 },
{ QSE_T("long-extended"), QSE_RADDIC_ATTR_TYPE_LONG_EXTENDED, 0 },
{ QSE_T("vsa"), QSE_RADDIC_ATTR_TYPE_VSA },
{ QSE_T("evs"), QSE_RADDIC_ATTR_TYPE_EVS },
{ QSE_T("vendor"), QSE_RADDIC_ATTR_TYPE_VENDOR },
{ QSE_T("vsa"), QSE_RADDIC_ATTR_TYPE_VSA, -1 },
{ QSE_T("evs"), QSE_RADDIC_ATTR_TYPE_EVS, -1 },
{ QSE_T("vendor"), QSE_RADDIC_ATTR_TYPE_VENDOR, -1 },
/*
* Alternative names
*/
{ QSE_T("cidr"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX },
{ QSE_T("byte"), QSE_RADDIC_ATTR_TYPE_UINT8 },
{ QSE_T("short"), QSE_RADDIC_ATTR_TYPE_UINT16 },
{ QSE_T("integer"), QSE_RADDIC_ATTR_TYPE_UINT32 },
{ QSE_T("integer64"), QSE_RADDIC_ATTR_TYPE_UINT64 },
{ QSE_T("decimal"), QSE_RADDIC_ATTR_TYPE_FLOAT64 },
{ QSE_T("signed"), QSE_RADDIC_ATTR_TYPE_INT32 },
#if 0
{ QSE_T("integer"), QSE_RADDIC_ATTR_TYPE_INTEGER },
{ QSE_T("string"), QSE_RADDIC_ATTR_TYPE_STRING },
{ QSE_T("ipaddr"), QSE_RADDIC_ATTR_TYPE_IPADDR },
{ QSE_T("date"), QSE_RADDIC_ATTR_TYPE_DATE },
{ QSE_T("abinary"), QSE_RADDIC_ATTR_TYPE_ABINARY },
{ QSE_T("octets"), QSE_RADDIC_ATTR_TYPE_OCTETS },
{ QSE_T("ifid"), QSE_RADDIC_ATTR_TYPE_IFID },
{ QSE_T("ipv6addr"), QSE_RADDIC_ATTR_TYPE_IPV6ADDR },
{ QSE_T("ipv6prefix"), QSE_RADDIC_ATTR_TYPE_IPV6PREFIX },
{ QSE_T("byte"), QSE_RADDIC_ATTR_TYPE_BYTE },
{ QSE_T("short"), QSE_RADDIC_ATTR_TYPE_SHORT },
{ QSE_T("ether"), QSE_RADDIC_ATTR_TYPE_ETHERNET },
{ QSE_T("combo-ip"), QSE_RADDIC_ATTR_TYPE_COMBO_IP },
{ QSE_T("tlv"), QSE_RADDIC_ATTR_TYPE_TLV },
{ QSE_T("signed"), QSE_RADDIC_ATTR_TYPE_SIGNED },
#endif
{ QSE_T("cidr"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX, -1 },
{ QSE_T("byte"), QSE_RADDIC_ATTR_TYPE_UINT8, 1 },
{ QSE_T("short"), QSE_RADDIC_ATTR_TYPE_UINT16, 2 },
{ QSE_T("integer"), QSE_RADDIC_ATTR_TYPE_UINT32, 4 },
{ QSE_T("integer64"), QSE_RADDIC_ATTR_TYPE_UINT64, 8 },
{ QSE_T("decimal"), QSE_RADDIC_ATTR_TYPE_FLOAT64, 8 },
{ QSE_T("signed"), QSE_RADDIC_ATTR_TYPE_INT32, 4 }
};
/* -------------------------------------------------------------------------- */
static int str_to_type (qse_raddic_t* dic, const qse_char_t* name)
static int str_to_type (qse_raddic_t* dic, const qse_char_t* name, int* length)
{
int i;
for (i = 0; i < QSE_COUNTOF(type_table); i++)
{
if (qse_strcmp(name, type_table[i].name) == 0) return type_table[i].id;
if (qse_strcmp(name, type_table[i].name) == 0)
{
if (length) *length = type_table[i].length;
return type_table[i].id;
}
}
dic->errnum = QSE_RADDIC_EINVAL;
@ -281,7 +264,10 @@ static int dict_attr_value_cmp (qse_htl_t* htl, const void* one, const void* two
if (a->vendor < b->vendor) return -1;
if (a->vendor > b->vendor) return 1;
return a->attr - b->attr;
if (a->attr < b->attr) return -1;
if (a->attr > b->attr) return 1;
return 0;
}
/* -------------------------------------------------------------------------- */
@ -355,23 +341,34 @@ static int dict_const_value_cmp (qse_htl_t* htl, const void* one, const void* tw
if (a->attr < b->attr) return -1;
if (a->attr > b->attr) return 1;
return a->value - b->value;
if (a->value.type != b->value.type) return -2; /* cannot really compare */
/* this function actuall requires to check equality.
* it doesn't have to return greaterness or lessness.
* it also assumes that the unused space in the 'value'
* union field is all initialized to zero */
return QSE_MEMCMP(&a->value, &b->value, QSE_SIZEOF(a->value));
}
/* -------------------------------------------------------------------------- */
int qse_raddic_init (qse_raddic_t* dic, qse_mmgr_t* mmgr)
{
int count = 0;
QSE_MEMSET (dic, 0, QSE_SIZEOF(*dic));
dic->mmgr = mmgr;
qse_raddic_seterrnum (dic, QSE_RADDIC_ENOERR);
qse_htl_init (&dic->vendors_byname, mmgr, 1);
qse_htl_init (&dic->vendors_byvalue, mmgr, 1);
qse_htl_init (&dic->attrs_byname, mmgr, 1);
qse_htl_init (&dic->attrs_byvalue, mmgr, 1);
qse_htl_init (&dic->consts_byname, mmgr, 1);
qse_htl_init (&dic->consts_byvalue, mmgr, 1);
if (qse_htl_init(&dic->vendors_byname, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->vendors_byvalue, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->attrs_byname, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->attrs_byvalue, mmgr, 1) <= -1 ||(++count == 0) ||
qse_htl_init(&dic->consts_byname, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->consts_byvalue, mmgr, 1) <= -1 || (++count == 0))
{
goto oops;
}
qse_htl_sethasher (&dic->vendors_byname, dict_vendor_name_hash);
qse_htl_setcomper (&dic->vendors_byname, dict_vendor_name_cmp);
@ -398,18 +395,28 @@ int qse_raddic_init (qse_raddic_t* dic, qse_mmgr_t* mmgr)
/* no freeer for dic->consts_byvalue */
return 0;
oops:
if (count >= 6) qse_htl_fini (&dic->consts_byvalue);
if (count >= 5) qse_htl_fini (&dic->consts_byname);
if (count >= 4) qse_htl_fini (&dic->attrs_byvalue);
if (count >= 3) qse_htl_fini (&dic->attrs_byname);
if (count >= 2) qse_htl_fini (&dic->vendors_byvalue);
if (count >= 1) qse_htl_fini (&dic->vendors_byname);
return -1;
}
void qse_raddic_fini (qse_raddic_t* dic)
{
qse_raddic_clear (dic);
qse_htl_fini (&dic->vendors_byname);
qse_htl_fini (&dic->vendors_byvalue);
qse_htl_fini (&dic->attrs_byname);
qse_htl_fini (&dic->attrs_byvalue);
qse_htl_fini (&dic->consts_byvalue);
qse_htl_fini (&dic->consts_byname);
qse_htl_fini (&dic->attrs_byvalue);
qse_htl_fini (&dic->attrs_byname);
qse_htl_fini (&dic->vendors_byvalue);
qse_htl_fini (&dic->vendors_byname);
}
qse_raddic_t* qse_raddic_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
@ -727,7 +734,7 @@ qse_raddic_attr_t* qse_raddic_findattrbyvalue (qse_raddic_t* dic, qse_uint32_t a
return (qse_raddic_attr_t*)np->data;
}
qse_raddic_attr_t* qse_raddic_addattr (qse_raddic_t* dic, const qse_char_t* name, int vendor, int type, int value, const qse_raddic_attr_flags_t* flags)
qse_raddic_attr_t* qse_raddic_addattr (qse_raddic_t* dic, const qse_char_t* name, int vendor, qse_raddic_attr_type_t type, int value, const qse_raddic_attr_flags_t* flags)
{
qse_size_t length;
qse_raddic_attr_t* dv, * old_dv;
@ -857,7 +864,7 @@ int qse_raddic_deleteattrbyname (qse_raddic_t* dic, const qse_char_t* name)
return 0;
}
int qse_raddic_deleteattrbyvalue (qse_raddic_t* dic, int attr)
int qse_raddic_deleteattrbyvalue (qse_raddic_t* dic, qse_uint32_t attr)
{
qse_raddic_attr_t* dv;
@ -908,13 +915,13 @@ qse_raddic_const_t* qse_raddic_findconstbyname (qse_raddic_t* dic, qse_uint32_t
return (qse_raddic_const_t*)np->data;
}
qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, int value)
qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, const qse_raddic_const_value_t* value)
{
qse_htl_node_t* np;
qse_raddic_const_t dval;
dval.attr = attr;
dval.value = value;
dval.value = *value;
np = qse_htl_search (&dic->consts_byvalue, &dval);
if (!np)
{
@ -924,7 +931,7 @@ qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t
return (qse_raddic_const_t*)np->data;
}
qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* name, const qse_char_t* attrstr, int value)
qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* name, const qse_char_t* attrstr, const qse_raddic_const_value_t* value)
{
qse_size_t length;
qse_raddic_const_t* dval, * old_dval;
@ -942,7 +949,7 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
}
qse_strcpy(dval->name, name);
dval->value = value;
dval->value = *value;
dval->nextc = QSE_NULL;
/*
@ -965,9 +972,9 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
*/
if (dattr)
{
if (dattr->flags.has_value_alias)
if (dattr->type != value->type)
{
/* cannot add a VALUE for an attribute having a VALUE_ALIAS */
qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("conflicts between attribute type and constant value"));
return QSE_NULL;
}
@ -1046,7 +1053,8 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
}
else
{
if ((dic->opt.trait & QSE_RADDIC_ALLOW_DUPLICATE_CONST) && ((qse_raddic_const_t*)np->data)->value == dval->value)
if ((dic->opt.trait & QSE_RADDIC_ALLOW_DUPLICATE_CONST) &&
QSE_MEMCMP(&((qse_raddic_const_t*)np->data)->value, &dval->value, QSE_SIZEOF(dval->value)) == 0)
{
QSE_MMGR_FREE (dic->mmgr, dval);
return np->data;
@ -1065,7 +1073,7 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
/* updated the existing item successfully.
* link the old item to the current item */
QSE_ASSERT (np->data == dval);
QSE_ASSERT (dval->value == old_dval->value);
QSE_ASSERT (QSE_MEMCMP(&dval->value, &old_dval->value, QSE_SIZEOF(dval->value)) == 0);
dval->nextc = old_dval;
}
else
@ -1090,7 +1098,7 @@ int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qs
if (!dv) return -1;
QSE_ASSERT (attr == dv->attr);
dv2 = qse_raddic_findconstbyvalue(dic, attr, dv->value);
dv2 = qse_raddic_findconstbyvalue(dic, attr, &dv->value);
QSE_ASSERT (dv2 != QSE_NULL);
if (dv != dv2)
@ -1098,7 +1106,7 @@ int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qs
qse_raddic_const_t* x, * y;
QSE_ASSERT (qse_strcasecmp(dv->name, dv2->name) != 0);
QSE_ASSERT (dv->value == dv2->value);
QSE_ASSERT (QSE_MEMCMP (&dv->value, &dv2->value, QSE_SIZEOF(dv->value)) == 0);
QSE_ASSERT (dv->attr == dv2->attr);
/* when the constibute of the given name is not the first one
@ -1130,7 +1138,7 @@ int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qs
return 0;
}
int qse_raddic_deleteconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, int value)
int qse_raddic_deleteconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, const qse_raddic_const_value_t* value)
{
qse_raddic_const_t* dv;
@ -1178,6 +1186,7 @@ static int sscanf_i (qse_raddic_t* dic, const qse_char_t* str, int* pvalue)
{
qse_long_t v;
const qse_char_t* end;
QSE_STRTONUM (v, str, &end, 0);
if (*end != '\0')
{
@ -1188,6 +1197,41 @@ static int sscanf_i (qse_raddic_t* dic, const qse_char_t* str, int* pvalue)
return 0;
}
static int sscanf_ui32 (qse_raddic_t* dic, const qse_char_t* str, qse_uint32_t* pvalue, qse_uint32_t* pvalue2)
{
qse_long_t v, v2;
const qse_char_t* end;
const qse_char_t* start2 = QSE_NULL;
if (!QSE_ISDIGIT(*str) && *str != QSE_T('+'))
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("invalid unsigned number - %s"), str);
return -1;
}
QSE_STRTONUM (v, str, &end, 0);
if (pvalue2 && *end == '.')
{
start2 = end + 1;
QSE_STRTONUM (v2, start2, &end, 0);
}
if (*end != '\0')
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("invalid unsigned number - %s"), str);
return -1;
}
*pvalue = v;
if (start2)
{
*pvalue2 = v2;
return (int)(end - start2); /* the value must not be very long. so i cast it to 'int' */
}
return 0;
}
/*
* Process the ATTRIBUTE command
*/
@ -1196,9 +1240,11 @@ static int process_attribute (
int block_vendor, qse_raddic_attr_t* block_tlv, qse_char_t** argv, int argc)
{
int vendor = 0;
int value;
unsigned int value;
int type;
qse_raddic_attr_flags_t flags;
qse_char_t* p;
int typelen = -1;
if ((argc < 3) || (argc > 4))
{
@ -1206,33 +1252,62 @@ static int process_attribute (
return -1;
}
QSE_MEMSET (&flags, 0, QSE_SIZEOF(flags));
/*
* Validate all entries
*/
if (sscanf_i(dic, argv[1], &value) <= -1)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid value %s"), fn, line, argv[1]);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid attribute value %s"), fn, line, argv[1]);
return -1;
}
/*
* find the type of the attribute.
*/
type = str_to_type(dic, argv[2]);
p = qse_strchr(argv[2], QSE_T('[')); /* for instance, octets[20] */
if (p)
{
qse_char_t* q;
*p = QSE_T('\0');
q = qse_strchr(p + 1, QSE_T(']'));
if (!q || q[1] != QSE_T('\0'))
{
*p = QSE_T('[');
goto invalid_type;
}
*q = QSE_T('\0');
if (sscanf_i(dic, p + 1, &typelen) <= -1 || typelen <= 0 || typelen > 253)
{
*p = QSE_T('[');
*q = QSE_T(']');
goto invalid_type;
}
flags.length = typelen;
}
type = str_to_type(dic, argv[2], &typelen);
if (type < 0)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid type \"%s\""), fn, line, argv[2]);
invalid_type:
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid attribute type \"%s\""), fn, line, argv[2]);
return -1;
}
if (flags.length <= 0 && typelen >= 0) flags.length = typelen;
/*
* Only look up the vendor if the string
* is non-empty.
*/
QSE_MEMSET (&flags, 0, QSE_SIZEOF(flags));
if (argc == 4)
if (argc >= 4)
{
qse_char_t* key, * next, * last;
qse_char_t* key, * next;
key = argv[3];
do
@ -1240,49 +1315,40 @@ static int process_attribute (
next = qse_strchr(key, QSE_T(','));
if (next) *(next++) = QSE_T('\0');
if (qse_strcmp(key, QSE_T("has_tag")) == 0 ||
qse_strcmp(key, QSE_T("has_tag=1")) == 0)
if (qse_strcasecmp(key, QSE_T("has_tag")) == 0 ||
qse_strcasecmp(key, QSE_T("has_tag=1")) == 0)
{
/* Boolean flag, means this is a
tagged attribute */
flags.has_tag = 1;
}
else if (qse_strzcmp(key, QSE_T("encrypt="), 8) == 0)
else if (qse_strzcasecmp(key, QSE_T("encrypt="), 8) == 0)
{
/* Encryption method, defaults to 0 (none).
Currently valid is just type 2,
Tunnel-Password style, which can only
be applied to strings. */
flags.encrypt = qse_strtol(key + 8, 0);
#if 0
if (*last)
unsigned int ev;
if (sscanf_i(dic, key + 8, &ev) <= -1 || ev < QSE_RADDIC_ATTR_FLAG_ENCRYPT_NONE || ev > QSE_RADDIC_ATTR_FLAG_ENCRYPT_OTHER)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid option %s"), fn, line, key);
return -1;
}
#endif
flags.encrypt = ev;
}
else if (qse_strcmp(key, QSE_T("array")) == 0)
else if (qse_strcasecmp(key, QSE_T("array")) == 0)
{
flags.array = 1;
/* TODO: ... */
switch (type)
{
case QSE_RADDIC_ATTR_TYPE_IPV4_ADDR:
case QSE_RADDIC_ATTR_TYPE_UINT8:
case QSE_RADDIC_ATTR_TYPE_UINT16:
case QSE_RADDIC_ATTR_TYPE_UINT32:
case QSE_RADDIC_ATTR_TYPE_DATE:
break;
default:
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] Only IP addresses can have the \"array\" flag set."), fn, line);
return -1;
}
} else {
}
else if (qse_strcasecmp(key, QSE_T("concat")) == 0)
{
flags.concat = 1;
}
else if (qse_strcasecmp(key, QSE_T("internal")) == 0)
{
flags.internal = 1;
}
else
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: unknown option \"%s\""), fn, line, key);
return -1;
}
@ -1361,7 +1427,9 @@ static int process_attribute (
static int process_constant(qse_raddic_t* dic, const qse_char_t* fn, const qse_size_t line, qse_char_t** argv, int argc)
{
int value;
qse_raddic_const_value_t value;
int n;
qse_uint32_t v1, v2;
if (argc != 3)
{
@ -1377,14 +1445,25 @@ static int process_constant(qse_raddic_t* dic, const qse_char_t* fn, const qse_s
/*
* Validate all entries
*/
if (sscanf_i(dic, argv[2], &value) <= -1)
if ((n = sscanf_ui32(dic, argv[2], &v1, &v2)) <= -1)
{
qse_strcpy (dic->errmsg2, dic->errmsg);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid constant value - %s"), fn, line, dic->errmsg2);
return -1;
}
if (qse_raddic_addconst(dic, argv[1], argv[0], value) == QSE_NULL)
QSE_MEMSET (&value, 0, QSE_SIZEOF(value));
value.type = QSE_RADDIC_ATTR_TYPE_UINT32;
value.u.ui32 = v1;
if (n >= 1)
{
value.type = QSE_RADDIC_ATTR_TYPE_FLOAT64;
value.u.f64 = (qse_flt_t)v1 + ((qse_flt_t)v2 / (pow(10, n))); /* TOOD: XXXXXXXXXXXXX device a way to prepresent this */
}
value.type = (n == 0)? QSE_RADDIC_ATTR_TYPE_UINT32: QSE_RADDIC_ATTR_TYPE_FLOAT64;
if (qse_raddic_addconst(dic, argv[1], argv[0], &value) == QSE_NULL)
{
qse_strcpy (dic->errmsg2, dic->errmsg);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: cannot add a constant - %s"), fn, line, dic->errmsg2);
@ -1508,7 +1587,7 @@ static int process_vendor (qse_raddic_t* dic, const qse_char_t* fn, const qse_si
return 0;
}
static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t* fn, const qse_char_t* src_file, qse_size_t src_line)
static int load_file (qse_raddic_t* dic, const qse_char_t* fn, const qse_char_t* src_file, qse_size_t src_line)
{
qse_sio_t* sio = QSE_NULL;
qse_char_t buf[256]; /* TODO: is this a good size? */
@ -1543,7 +1622,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t
if (src_file)
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: cannot open %s"), src_file, src_line, fname);
else
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("cannot open %s"), fname);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("cannot open \"%s\""), fname);
goto oops;
}
@ -1568,7 +1647,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t
if (argc == 1)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid entry"), fname, line);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid entry \"%s\""), fname, line, argv[0]);
goto oops;
}
@ -1595,7 +1674,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t
*/
if (qse_strcasecmp(argv[0], QSE_T("$INCLUDE")) == 0)
{
if (load_file(dic, dir, argv[1], fname, line) < 0) goto oops;
if (load_file(dic, argv[1], fname, line) < 0) goto oops;
continue;
} /* $INCLUDE */
@ -1720,5 +1799,5 @@ oops:
int qse_raddic_load (qse_raddic_t* dic, const qse_char_t* file)
{
return load_file (dic, QSE_NULL, file, QSE_NULL, 0);
return load_file (dic, file, QSE_NULL, 0);
}

View File

@ -187,7 +187,7 @@ static int test2 ()
{
qse_char_t tmp[64];
qse_strxfmt(tmp, QSE_COUNTOF(tmp), QSE_T("test-%d-%d"), j, i);
attr = qse_raddic_addattr (dic, tmp, j, QSE_RADDIC_ATTR_TYPE_STRING, i, &f);
attr = qse_raddic_addattr (dic, tmp, j, QSE_RADDIC_ATTR_TYPE_UINT32, i, &f);
_assert (attr != QSE_NULL, QSE_T("unable to add an attribute"));
_assert (attr->attr == QSE_RADDIC_ATTR_MAKE(j, i), QSE_T("wrong attr value"));
_assert (qse_strcasecmp(attr->name, tmp) == 0, QSE_T("wrong attr name"));
@ -218,13 +218,13 @@ static int test2 ()
{
qse_char_t tmp[64];
qse_strxfmt(tmp, QSE_COUNTOF(tmp), QSE_T("testx-%d-%d"), j, i);
attr = qse_raddic_addattr (dic, tmp, j, QSE_RADDIC_ATTR_TYPE_STRING, i, &f);
attr = qse_raddic_addattr (dic, tmp, j, QSE_RADDIC_ATTR_TYPE_UINT32, i, &f);
_assert (attr != QSE_NULL, QSE_T("unable to add an attribute"));
_assert (attr->attr == QSE_RADDIC_ATTR_MAKE(j, i), QSE_T("wrong attr value"));
_assert (qse_strcasecmp(attr->name, tmp) == 0, QSE_T("wrong attr name"));
qse_strxfmt(tmp, QSE_COUNTOF(tmp), QSE_T("testy-%d-%d"), j, i);
attr = qse_raddic_addattr (dic, tmp, j, QSE_RADDIC_ATTR_TYPE_STRING, i, &f);
attr = qse_raddic_addattr (dic, tmp, j, QSE_RADDIC_ATTR_TYPE_UINT32, i, &f);
_assert (attr != QSE_NULL, QSE_T("unable to add an attribute"));
_assert (attr->attr == QSE_RADDIC_ATTR_MAKE(j, i), QSE_T("wrong attr value"));
_assert (qse_strcasecmp(attr->name, tmp) == 0, QSE_T("wrong attr name"));
@ -339,11 +339,17 @@ static int test2 ()
for (i = 1; i <= 255; i++)
{
qse_char_t constr[64], attrstr[64];
qse_raddic_const_value_t v;
memset (&v, 0, QSE_SIZEOF(v));
v.type = QSE_RADDIC_ATTR_TYPE_UINT32;
v.u.ui32 = 10;
qse_strxfmt(attrstr, QSE_COUNTOF(attrstr), QSE_T("test-%d-%d"), j, i);
qse_strxfmt(constr, QSE_COUNTOF(constr), QSE_T("const-%d-%d"), j, i);
con = qse_raddic_addconst (dic, constr, attrstr, 10);
con = qse_raddic_addconst (dic, constr, attrstr, &v);
_assert (con != QSE_NULL, QSE_T("unable to add an constant"));
_assert (con->value == 10, QSE_T("wrong constant value"));
_assert (con->value.type == QSE_RADDIC_ATTR_TYPE_UINT32 || con->value.u.ui32 == 10, QSE_T("wrong constant value"));
_assert (qse_strcasecmp(con->name, constr) == 0, QSE_T("wrong constant name"));
}
}
@ -353,16 +359,22 @@ static int test2 ()
for (i = 1; i <= 255; i++)
{
qse_char_t constr[64];
qse_raddic_const_value_t v;
memset (&v, 0, QSE_SIZEOF(v));
v.type = QSE_RADDIC_ATTR_TYPE_UINT32;
v.u.ui32 = 10;
qse_strxfmt(constr, QSE_COUNTOF(constr), QSE_T("const-%d-%d"), j, i);
con = qse_raddic_findconstbyname (dic, QSE_RADDIC_ATTR_MAKE(j, i), constr);
_assert (con != QSE_NULL, QSE_T("unable to find an constant"));
_assert (con->attr == QSE_RADDIC_ATTR_MAKE(j, i), QSE_T("wrong constant value"));
_assert (con->value == 10, QSE_T("wrong constant value"));
_assert (con->value.type == QSE_RADDIC_ATTR_TYPE_UINT32 || con->value.u.ui32 == 10, QSE_T("wrong constant value"));
con = qse_raddic_findconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(j, i), 10);
con = qse_raddic_findconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(j, i), &v);
_assert (con != QSE_NULL, QSE_T("unable to find an constant"));
_assert (con->value == 10, QSE_T("wrong constant value"));
_assert (con->value.type == QSE_RADDIC_ATTR_TYPE_UINT32 || con->value.u.ui32 == 10, QSE_T("wrong constant value"));
_assert (con->attr == QSE_RADDIC_ATTR_MAKE(j, i), QSE_T("wrong constant value"));
}
}
@ -370,19 +382,27 @@ static int test2 ()
{
int n;
qse_raddic_const_value_t v;
memset (&v, 0, QSE_SIZEOF(v));
v.type = QSE_RADDIC_ATTR_TYPE_UINT32;
n = qse_raddic_deleteconstbyname (dic, QSE_RADDIC_ATTR_MAKE(1,1), QSE_T("const-1-1"));
_assert (n == 0, QSE_T("errorneous constant deletion failure"));
n = qse_raddic_deleteconstbyname (dic, QSE_RADDIC_ATTR_MAKE(1,1), QSE_T("const-1-1"));
_assert (n <= -1, QSE_T("errorneous constant deletion success"));
n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), 20);
v.u.ui32 = 20;
n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), &v);
_assert (n <= -1, QSE_T("errorneous constant deletion success"));
n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), 10);
v.u.ui32 = 10;
n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), &v);
_assert (n == 0, QSE_T("errorneous constant deletion success"));
n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), 10);
v.u.ui32 = 10;
n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), &v);
_assert (n <= -1, QSE_T("errorneous constant deletion success"));
}
@ -393,6 +413,8 @@ static int test2 ()
static int test3 ()
{
qse_raddic_t* dic;
qse_raddic_vendor_t* v;
qse_raddic_const_t* c;
int n, trait;
dic = qse_raddic_open (QSE_MMGR_GETDFL(), 0);
@ -402,9 +424,15 @@ static int test3 ()
n = qse_raddic_setopt (dic, QSE_RADDIC_TRAIT, &trait);
_assert (n == 0, QSE_T("cannot set trait"));
n = qse_raddic_load (dic, QSE_T("fr/dictionary"));
n = qse_raddic_load (dic, QSE_T("fr2/dictionary"));
_assert (n == 0, qse_raddic_geterrmsg(dic));
v = qse_raddic_findvendorbyname (dic, QSE_T("cisco"));
_assert (v && v->vendorpec == 9, "wrong vendor value");
c = qse_raddic_findconstbyname (dic, QSE_RADDIC_ATTR_MAKE(0,49), QSE_T("Reauthentication-Failure"));
_assert (c && c->value.type == QSE_RADDIC_ATTR_TYPE_UINT32 && c->value.u.ui32 == 20, QSE_T("wrong constant value"));
qse_raddic_close (dic);
return 0;
}