From 2172fa59a529d7dafece875ccde7d7a0e5d75460 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 14 Dec 2017 10:02:44 +0000 Subject: [PATCH] enhanced the constant value handling --- qse/include/qse/cmn/path.h | 9 +- qse/include/qse/rad/raddic.h | 118 +++++++----- qse/lib/rad/raddic.c | 347 +++++++++++++++++++++-------------- qse/samples/rad/raddic01.c | 52 ++++-- 4 files changed, 329 insertions(+), 197 deletions(-) diff --git a/qse/include/qse/cmn/path.h b/qse/include/qse/cmn/path.h index e7f7e0e2..6ae6d183 100644 --- a/qse/include/qse/cmn/path.h +++ b/qse/include/qse/cmn/path.h @@ -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, diff --git a/qse/include/qse/rad/raddic.h b/qse/include/qse/rad/raddic.h index 8b5b7ecc..16f35e94 100644 --- a/qse/include/qse/rad/raddic.h +++ b/qse/include/qse/rad/raddic.h @@ -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 ); diff --git a/qse/lib/rad/raddic.c b/qse/lib/rad/raddic.c index 6cd2381f..c06aae99 100644 --- a/qse/lib/rad/raddic.c +++ b/qse/lib/rad/raddic.c @@ -56,10 +56,6 @@ #include #include -#include -#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); } diff --git a/qse/samples/rad/raddic01.c b/qse/samples/rad/raddic01.c index 28cdb228..6dd31875 100644 --- a/qse/samples/rad/raddic01.c +++ b/qse/samples/rad/raddic01.c @@ -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; }