From 42ecad1e384abd04ade27c2adf35d74e3767803e Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 18 Dec 2017 06:27:54 +0000 Subject: [PATCH] added an experimental function qse_rad_insert_extended_vendor_specific_attribute() to support EVS. yet a lot of wors are to be done to support tag, extended, long-extended, tlv --- qse/include/qse/rad/raddic.h | 36 +++-- qse/include/qse/rad/radmsg.h | 71 +++++++-- qse/lib/rad/raddic.c | 296 ++++++++++++++++++++++------------- qse/lib/rad/radmsg.c | 39 ++++- qse/samples/rad/raddic01.c | 116 +++++++++----- 5 files changed, 374 insertions(+), 184 deletions(-) diff --git a/qse/include/qse/rad/raddic.h b/qse/include/qse/rad/raddic.h index 16f35e94..9e41a0b1 100644 --- a/qse/include/qse/rad/raddic.h +++ b/qse/include/qse/rad/raddic.h @@ -30,6 +30,8 @@ #include #include +/* TODO: extended, long-extended, tlv, evs */ + enum qse_raddic_opt_t { QSE_RADDIC_TRAIT @@ -182,7 +184,7 @@ typedef struct qse_raddic_const_t qse_raddic_const_t; struct qse_raddic_const_t { qse_uint32_t attr; /* vendor + attribute-value */ - qse_raddic_const_value_t value; + qse_uintmax_t value; qse_raddic_const_t* nextc; qse_char_t name[1]; }; @@ -190,7 +192,7 @@ struct qse_raddic_const_t typedef struct qse_raddic_vendor_t qse_raddic_vendor_t; struct qse_raddic_vendor_t { - int vendorpec; + unsigned int vendorpec; int type; int length; int flags; @@ -265,13 +267,13 @@ QSE_EXPORT qse_raddic_vendor_t* qse_raddic_findvendorbyname ( QSE_EXPORT qse_raddic_vendor_t* qse_raddic_findvendorbyvalue ( qse_raddic_t* dic, - int vendorpec + unsigned int vendorpec ); QSE_EXPORT qse_raddic_vendor_t* qse_raddic_addvendor ( qse_raddic_t* dic, const qse_char_t* name, - int vendorpec + unsigned int vendorpec ); QSE_EXPORT int qse_raddic_deletevendorbyname ( @@ -281,7 +283,7 @@ QSE_EXPORT int qse_raddic_deletevendorbyname ( QSE_EXPORT int qse_raddic_deletevendorbyvalue ( qse_raddic_t* dic, - int vendorpec + unsigned int vendorpec ); @@ -298,9 +300,9 @@ QSE_EXPORT qse_raddic_attr_t* qse_raddic_findattrbyvalue ( QSE_EXPORT qse_raddic_attr_t* qse_raddic_addattr ( qse_raddic_t* dic, const qse_char_t* name, - int vendor, + unsigned int vendor, qse_raddic_attr_type_t type, - int value, + unsigned int value, const qse_raddic_attr_flags_t* flags ); @@ -322,16 +324,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, - const qse_raddic_const_value_t* value + qse_raddic_t* dic, + qse_uint32_t attr, + qse_uintmax_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, - const qse_raddic_const_value_t* value + qse_raddic_t* dic, + const qse_char_t* name, + const qse_char_t* attrstr, + qse_uintmax_t value ); QSE_EXPORT int qse_raddic_deleteconstbyname ( @@ -341,9 +343,9 @@ QSE_EXPORT int qse_raddic_deleteconstbyname ( ); QSE_EXPORT int qse_raddic_deleteconstbyvalue ( - qse_raddic_t* dic, - qse_uint32_t attr, - const qse_raddic_const_value_t* value + qse_raddic_t* dic, + qse_uint32_t attr, + qse_uintmax_t value ); diff --git a/qse/include/qse/rad/radmsg.h b/qse/include/qse/rad/radmsg.h index 418f62f9..840499a1 100644 --- a/qse/include/qse/rad/radmsg.h +++ b/qse/include/qse/rad/radmsg.h @@ -27,6 +27,8 @@ #ifndef _QSE_RAD_RADMSG_H_ #define _QSE_RAD_RADMSG_H_ +/* TODO: tag, extended, long-extended, tlv, evs */ + #include #include #include @@ -56,12 +58,18 @@ typedef enum qse_rad_code_t qse_rad_code_t; #define QSE_RAD_MAX_AUTHENTICATOR_LEN 16 #define QSE_RAD_MAX_ATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_attr_hdr_t)) #define QSE_RAD_MAX_VSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_attr_hdr_t) - QSE_SIZEOF(qse_rad_vsattr_hdr_t)) +#define QSE_RAD_MAX_EXTVSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_extvsattr_hdr_t)) typedef struct qse_rad_hdr_t qse_rad_hdr_t; typedef struct qse_rad_attr_hdr_t qse_rad_attr_hdr_t; typedef struct qse_rad_vsattr_hdr_t qse_rad_vsattr_hdr_t; -typedef struct qse_rad_attr_int_t qse_rad_attr_int_t; +typedef struct qse_rad_extvsattr_hdr_t qse_rad_extvsattr_hdr_t; /* evs */ + +typedef struct qse_rad_attr_uint32_t qse_rad_attr_uint32_t; +#if (QSE_SIZEOF_UINT64_T > 0) +typedef struct qse_rad_attr_uint64_t qse_rad_attr_uint64_t; +#endif #include struct qse_rad_hdr_t @@ -80,24 +88,42 @@ struct qse_rad_attr_hdr_t struct qse_rad_vsattr_hdr_t { - qse_uint8_t id; - qse_uint8_t length; + qse_uint8_t id; /* type */ + qse_uint8_t length; /* length */ qse_uint32_t vendor; /* in network-byte order */ }; -struct qse_rad_attr_int_t +struct qse_rad_extvsattr_hdr_t +{ + qse_uint8_t id; /* one of 241-244 */ + qse_uint8_t length; + qse_uint8_t xid; /* extended type. 26 for evs */ + qse_uint32_t vendor; /* in network-byte order */ + qse_uint8_t evsid; +}; + +struct qse_rad_attr_uint32_t { qse_rad_attr_hdr_t hdr; qse_uint32_t val; }; + +#if (QSE_SIZEOF_UINT64_T > 0) +struct qse_rad_attr_uint64_t +{ + qse_rad_attr_hdr_t hdr; + qse_uint64_t val; +}; +#endif + #include typedef int (*qse_rad_attr_walker_t) ( const qse_rad_hdr_t* hdr, - qse_uint32_t vendor, /* in host-byte order */ + qse_uint32_t vendor, /* in host-byte order */ const qse_rad_attr_hdr_t* attr, - void* ctx + void* ctx ); enum qse_rad_attr_id_t @@ -223,7 +249,7 @@ QSE_EXPORT int qse_rad_insert_vendor_specific_attribute ( QSE_EXPORT int qse_rad_delete_attribute ( qse_rad_hdr_t* hdr, - qse_uint8_t attrid + qse_uint8_t attrid ); QSE_EXPORT int qse_rad_delete_vendor_specific_attribute ( @@ -249,7 +275,7 @@ QSE_EXPORT int qse_rad_insert_wide_string_attribute ( ); QSE_EXPORT int qse_rad_insert_string_attribute_with_length ( - qse_rad_hdr_t* auth, + qse_rad_hdr_t* auth, int max, qse_uint32_t vendor, /* in host-byte order */ qse_uint8_t id, @@ -258,7 +284,7 @@ QSE_EXPORT int qse_rad_insert_string_attribute_with_length ( ); QSE_EXPORT int qse_rad_insert_wide_string_attribute_with_length ( - qse_rad_hdr_t* auth, + qse_rad_hdr_t* auth, int max, qse_uint32_t vendor, /* in host-byte order */ qse_uint8_t id, @@ -266,16 +292,16 @@ QSE_EXPORT int qse_rad_insert_wide_string_attribute_with_length ( qse_uint8_t length ); -QSE_EXPORT int qse_rad_insert_integer_attribute ( - qse_rad_hdr_t* auth, - int max, - qse_uint32_t vendor, /* in host-byte order */ - qse_uint8_t id, - qse_uint32_t value /* in host-byte order */ +QSE_EXPORT int qse_rad_insert_uint32_attribute ( + qse_rad_hdr_t* auth, + int max, + qse_uint32_t vendor, /* in host-byte order */ + qse_uint8_t id, + qse_uint32_t value /* in host-byte order */ ); QSE_EXPORT int qse_rad_insert_ipv6prefix_attribute ( - qse_rad_hdr_t* auth, + qse_rad_hdr_t* auth, int max, qse_uint32_t vendor, /* in host-byte order */ qse_uint8_t id, @@ -292,6 +318,18 @@ QSE_EXPORT int qse_rad_insert_giga_attribute ( qse_uint64_t value ); +QSE_EXPORT int qse_rad_insert_extended_vendor_specific_attribute ( + qse_rad_hdr_t* auth, + int max, + qse_uint8_t base, /* one of 241-244 */ + qse_uint32_t vendor, + qse_uint8_t attrid, + const void* ptr, + qse_uint8_t len +); + +/* TODO: QSE_EXPORT int qse_rad_delete_extended_vendor_specific_attribute () */ + QSE_EXPORT int qse_rad_set_user_password ( qse_rad_hdr_t* auth, int max, @@ -329,7 +367,6 @@ QSE_EXPORT int qse_rad_verify_response ( const qse_mchar_t* secret ); - #ifdef __cplusplus } #endif diff --git a/qse/lib/rad/raddic.c b/qse/lib/rad/raddic.c index c06aae99..3acbe705 100644 --- a/qse/lib/rad/raddic.c +++ b/qse/lib/rad/raddic.c @@ -62,6 +62,8 @@ struct const_fixup_t { const_fixup_t* next; qse_raddic_const_t* dval; + qse_size_t line; + qse_char_t* fn; qse_char_t attrstr[1]; }; @@ -341,13 +343,10 @@ 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; - if (a->value.type != b->value.type) return -2; /* cannot really compare */ + if (a->value < b->value) return -1; + if (a->value > b->value) return 1; - /* 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)); + return 0; } /* -------------------------------------------------------------------------- */ @@ -555,7 +554,7 @@ qse_raddic_vendor_t* qse_raddic_findvendorbyname (qse_raddic_t* dic, const qse_c /* * Return the vendor struct based on the PEC. */ -qse_raddic_vendor_t* qse_raddic_findvendorbyvalue (qse_raddic_t* dic, int vendorpec) +qse_raddic_vendor_t* qse_raddic_findvendorbyvalue (qse_raddic_t* dic, unsigned int vendorpec) { qse_htl_node_t* np; qse_raddic_vendor_t dv; @@ -564,13 +563,13 @@ qse_raddic_vendor_t* qse_raddic_findvendorbyvalue (qse_raddic_t* dic, int vendor np = qse_htl_search (&dic->vendors_byvalue, &dv); if (!np) { - qse_raddic_seterrfmt (dic, QSE_RADDIC_ENOENT, QSE_T("cannot find a vendor of value %d"), vendorpec); + qse_raddic_seterrfmt (dic, QSE_RADDIC_ENOENT, QSE_T("cannot find a vendor of value %u"), vendorpec); return QSE_NULL; } return (qse_raddic_vendor_t*)np->data; } -qse_raddic_vendor_t* qse_raddic_addvendor (qse_raddic_t* dic, const qse_char_t* name, int vendorpec) +qse_raddic_vendor_t* qse_raddic_addvendor (qse_raddic_t* dic, const qse_char_t* name, unsigned int vendorpec) { qse_size_t length; qse_raddic_vendor_t* dv, * old_dv; @@ -578,7 +577,7 @@ qse_raddic_vendor_t* qse_raddic_addvendor (qse_raddic_t* dic, const qse_char_t* if (vendorpec <= 0 || vendorpec > 65535) { - qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("vendor value %d out of accepted range"), vendorpec); + qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("vendor value %u out of accepted range"), vendorpec); return QSE_NULL; } @@ -678,7 +677,7 @@ int qse_raddic_deletevendorbyname (qse_raddic_t* dic, const qse_char_t* name) return 0; } -int qse_raddic_deletevendorbyvalue (qse_raddic_t* dic, int vendorpec) +int qse_raddic_deletevendorbyvalue (qse_raddic_t* dic, unsigned int vendorpec) { qse_raddic_vendor_t* dv; @@ -734,21 +733,21 @@ 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, qse_raddic_attr_type_t 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, unsigned int vendor, qse_raddic_attr_type_t type, unsigned int value, const qse_raddic_attr_flags_t* flags) { qse_size_t length; qse_raddic_attr_t* dv, * old_dv; qse_htl_node_t* np; - if (vendor < 0 || vendor > 65535) + if (vendor < 0 || vendor > 65535u) { - qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("vendor %d out of accepted range"), vendor); + qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("vendor %u out of accepted range"), vendor); return QSE_NULL; /* 0 is allowed to mean no vendor */ } - if (value < 0 || value > 65535) + if (value < 0 || value > 65535u) { /* the upper bound is not 255 because there are vendors defining values in 16-bit format */ - qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("attribute value %d out of accepted range"), value); + qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("attribute value %u out of accepted range"), value); return QSE_NULL; } @@ -915,13 +914,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, const qse_raddic_const_value_t* value) +qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, qse_uintmax_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) { @@ -931,12 +930,64 @@ 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, const qse_raddic_const_value_t* value) +static qse_raddic_const_t* __add_const (qse_raddic_t* dic, qse_raddic_const_t* dval) +{ + qse_htl_node_t* np; + qse_raddic_const_t* old_dval; + + /* return an existing item or insert a new item */ + np = qse_htl_ensert(&dic->consts_byname, dval); + if (!np || np->data != dval) + { + /* insertion failure or existing item found */ + if (!np) + { + qse_raddic_seterrnum (dic, QSE_RADDIC_ENOMEM); + } + else + { + if ((dic->opt.trait & QSE_RADDIC_ALLOW_DUPLICATE_CONST) && + ((qse_raddic_const_t*)np->data)->value == dval->value) + { + QSE_MMGR_FREE (dic->mmgr, dval); + return np->data; + } + qse_raddic_seterrfmt (dic, QSE_RADDIC_EEXIST, QSE_T("existing constant %s"), dval->name); + } + + QSE_MMGR_FREE (dic->mmgr, dval); + return QSE_NULL; + } + + /* attempt to update the lookup table by value */ + np = qse_htl_upyank(&dic->consts_byvalue, dval, (void**)&old_dval); + if (np) + { + /* 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); + dval->nextc = old_dval; + } + else + { + /* update failure, this entry must be new. try insertion */ + if (!qse_htl_insert (&dic->consts_byvalue, dval)) + { + qse_raddic_seterrnum (dic, QSE_RADDIC_ENOMEM); + qse_htl_delete (&dic->consts_byname, dval); + return QSE_NULL; + } + } + + return dval; +} + +static qse_raddic_const_t* add_const (qse_raddic_t* dic, const qse_char_t* name, const qse_char_t* attrstr, qse_uintmax_t value, const qse_char_t* fn, qse_size_t line) { qse_size_t length; - qse_raddic_const_t* dval, * old_dval; + qse_raddic_const_t* dval; qse_raddic_attr_t* dattr; - qse_htl_node_t* np; length = qse_strlen(name); @@ -949,7 +1000,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; /* @@ -972,27 +1023,48 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na */ if (dattr) { +#if 0 if (dattr->type != value->type) { - qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("conflicts between attribute type and constant value")); + qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("conflicts between attribute type(%d) and constant value type(%d)"), (int)dattr->type, (int)value->type); return QSE_NULL; } +#endif dval->attr = dattr->attr; -#if 0 - /* - * Enforce valid values - * Don't worry about fixups... - */ switch (dattr->type) { - case QSE_RADDIC_ATTR_TYPE_BYTE: - if (value < 0 || value > 255) goto wrong_value; + case QSE_RADDIC_ATTR_TYPE_UINT8: + if (value < QSE_TYPE_MIN(qse_uint8_t) || value > QSE_TYPE_MAX(qse_uint8_t)) goto wrong_value; break; - case QSE_RADDIC_ATTR_TYPE_SHORT: - if (value < 0 || value > 65535) goto wrong_value; + case QSE_RADDIC_ATTR_TYPE_UINT16: + if (value < QSE_TYPE_MIN(qse_uint16_t) || value > QSE_TYPE_MAX(qse_uint16_t)) goto wrong_value; + break; + + case QSE_RADDIC_ATTR_TYPE_UINT32: + if (value < QSE_TYPE_MIN(qse_uint32_t) || value > QSE_TYPE_MAX(qse_uint32_t)) goto wrong_value; + break; + + case QSE_RADDIC_ATTR_TYPE_UINT64: + if (value < QSE_TYPE_MIN(qse_uint64_t) || value > QSE_TYPE_MAX(qse_uint64_t)) goto wrong_value; + break; + + case QSE_RADDIC_ATTR_TYPE_INT8: + if (value < QSE_TYPE_MIN(qse_int8_t) || value > QSE_TYPE_MAX(qse_int8_t)) goto wrong_value; + break; + + case QSE_RADDIC_ATTR_TYPE_INT16: + if (value < QSE_TYPE_MIN(qse_int16_t) || value > QSE_TYPE_MAX(qse_int16_t)) goto wrong_value; + break; + + case QSE_RADDIC_ATTR_TYPE_INT32: + if (value < QSE_TYPE_MIN(qse_int32_t) || value > QSE_TYPE_MAX(qse_int32_t)) goto wrong_value; + break; + + case QSE_RADDIC_ATTR_TYPE_INT64: + if (value < QSE_TYPE_MIN(qse_int64_t) || value > QSE_TYPE_MAX(qse_int64_t)) goto wrong_value; break; /* @@ -1000,25 +1072,29 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na * of dictionary.cablelabs */ case QSE_RADDIC_ATTR_TYPE_OCTETS: - case QSE_RADDIC_ATTR_TYPE_INTEGER: break; default: /* cannot define VALUE for other types */ wrong_value: - qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("value %d for a constant %s not allowed for an attribute %s for type %d"), value, name, attrstr, (int)dattr->type); + qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("value %jd for a constant %s not allowed for an attribute %s of type %d"), value, name, attrstr, (int)dattr->type); QSE_MMGR_FREE (dic->mmgr, dval); return QSE_NULL; } -#endif + dattr->flags.has_value = 1; } else { - if (dic->opt.trait & QSE_RADDIC_ALLOW_CONST_WITHOUT_ATTR) + if (fn && (dic->opt.trait & QSE_RADDIC_ALLOW_CONST_WITHOUT_ATTR)) { const_fixup_t* fixup; + qse_size_t attrstrlen, fnlen; - fixup = QSE_MMGR_ALLOC(dic->mmgr, QSE_SIZEOF(*fixup) + (qse_strlen(attrstr) * QSE_SIZEOF(*attrstr))); + attrstrlen = qse_strlen(attrstr); + fnlen = qse_strlen(fn); + + /* TODO: don't copy fn again and again */ + fixup = QSE_MMGR_ALLOC(dic->mmgr, QSE_SIZEOF(*fixup) + ((attrstrlen + fnlen + 1) * QSE_SIZEOF(*attrstr))); if (!fixup) { qse_raddic_seterrnum (dic, QSE_RADDIC_ENOMEM); @@ -1030,6 +1106,10 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na qse_strcpy (fixup->attrstr, attrstr); fixup->dval = dval; fixup->next = dic->const_fixup; + fixup->line = line; + fixup->fn = fixup->attrstr + attrstrlen + 1; + qse_strcpy (fixup->fn, fn); /* TODO: don't copy fn again and again */ + dic->const_fixup = fixup; return dval; /* this is not complete */ @@ -1042,52 +1122,12 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na } } - /* return an existing item or insert a new item */ - np = qse_htl_ensert(&dic->consts_byname, dval); - if (!np || np->data != dval) - { - /* insertion failure or existing item found */ - if (!np) - { - qse_raddic_seterrnum (dic, QSE_RADDIC_ENOMEM); - } - else - { - 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; - } - qse_raddic_seterrfmt (dic, QSE_RADDIC_EEXIST, QSE_T("existing constant %s"), name); - } + return __add_const(dic, dval); +} - QSE_MMGR_FREE (dic->mmgr, dval); - return QSE_NULL; - } - - /* attempt to update the lookup table by value */ - np = qse_htl_upyank(&dic->consts_byvalue, dval, (void**)&old_dval); - if (np) - { - /* updated the existing item successfully. - * link the old item to the current item */ - QSE_ASSERT (np->data == dval); - QSE_ASSERT (QSE_MEMCMP(&dval->value, &old_dval->value, QSE_SIZEOF(dval->value)) == 0); - dval->nextc = old_dval; - } - else - { - /* update failure, this entry must be new. try insertion */ - if (!qse_htl_insert (&dic->consts_byvalue, dval)) - { - qse_raddic_seterrnum (dic, QSE_RADDIC_ENOMEM); - qse_htl_delete (&dic->consts_byname, dval); - return QSE_NULL; - } - } - - return dval; +qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* name, const qse_char_t* attrstr, qse_uintmax_t value) +{ + return add_const (dic, name, attrstr, value, QSE_NULL, 0); } int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qse_char_t* name) @@ -1098,7 +1138,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) @@ -1106,7 +1146,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 (QSE_MEMCMP (&dv->value, &dv2->value, QSE_SIZEOF(dv->value)) == 0); + QSE_ASSERT (dv->value ==dv2->value); QSE_ASSERT (dv->attr == dv2->attr); /* when the constibute of the given name is not the first one @@ -1138,7 +1178,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, const qse_raddic_const_value_t* value) +int qse_raddic_deleteconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, qse_uintmax_t value) { qse_raddic_const_t* dv; @@ -1197,6 +1237,29 @@ static int sscanf_i (qse_raddic_t* dic, const qse_char_t* str, int* pvalue) return 0; } +static int sscanf_ui (qse_raddic_t* dic, const qse_char_t* str, qse_uintmax_t* pvalue) +{ + qse_uintmax_t v; + const qse_char_t* end; + + 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 (*end != '\0') + { + qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("invalid unsigned number - %s"), str); + return -1; + } + + *pvalue = v; + 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; @@ -1239,8 +1302,8 @@ static int process_attribute ( qse_raddic_t* dic, const qse_char_t* fn, const qse_size_t line, int block_vendor, qse_raddic_attr_t* block_tlv, qse_char_t** argv, int argc) { - int vendor = 0; - unsigned int value; + unsigned int vendor = 0; + qse_uintmax_t value; int type; qse_raddic_attr_flags_t flags; qse_char_t* p; @@ -1257,7 +1320,7 @@ static int process_attribute ( /* * Validate all entries */ - if (sscanf_i(dic, argv[1], &value) <= -1) + if (sscanf_ui(dic, argv[1], &value) <= -1 || value > QSE_TYPE_MAX(qse_uint16_t)) { qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid attribute value %s"), fn, line, argv[1]); return -1; @@ -1326,7 +1389,7 @@ static int process_attribute ( Currently valid is just type 2, Tunnel-Password style, which can only be applied to strings. */ - unsigned int ev; + 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); @@ -1427,9 +1490,8 @@ 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) { - qse_raddic_const_value_t value; + qse_uintmax_t value; int n; - qse_uint32_t v1, v2; if (argc != 3) { @@ -1446,27 +1508,17 @@ static int process_constant(qse_raddic_t* dic, const qse_char_t* fn, const qse_s * Validate all entries */ - if ((n = sscanf_ui32(dic, argv[2], &v1, &v2)) <= -1) + if ((n = sscanf_ui(dic, argv[2], &value)) <= -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; } - 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) + if (add_const(dic, argv[1], argv[0], value, fn, line) == 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); + qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: cannot add a constant \"%s\" - %s"), fn, line, argv[1], dic->errmsg2); return -1; } @@ -1765,7 +1817,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* fn, const qse_char_t* vendor = qse_raddic_findvendorbyname(dic, argv[1]); if (!vendor) { - qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: unknown vendor %s"), fname, line, argv[1]); + qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: unknown vendor \"%s\""), fname, line, argv[1]); goto oops; } @@ -1784,7 +1836,6 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* fn, const qse_char_t* */ qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid keyword \"%s\""), fname, line, argv[0]); goto oops; - } qse_sio_close (sio); @@ -1799,5 +1850,36 @@ oops: int qse_raddic_load (qse_raddic_t* dic, const qse_char_t* file) { - return load_file (dic, file, QSE_NULL, 0); + int n; + + n = load_file (dic, file, QSE_NULL, 0); + + while (dic->const_fixup) + { + qse_raddic_attr_t* attr; + const_fixup_t* fixup = dic->const_fixup; + dic->const_fixup = dic->const_fixup->next; + + if (n >= 0) + { + attr = qse_raddic_findattrbyname (dic, fixup->attrstr); + if (attr) + { + fixup->dval->attr = attr->attr; + attr->flags.has_value = 1; + if (__add_const(dic, fixup->dval) != QSE_NULL) goto fixed; + } + else + { + qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: constant \"%s\" defined for an unknown attribute \"%s\""), fixup->fn, fixup->line, fixup->dval->name, fixup->attrstr); + n = -1; + } + } + + QSE_MMGR_FREE (dic->mmgr, fixup->dval); + fixed: + QSE_MMGR_FREE (dic->mmgr, fixup); + } + + return n; } diff --git a/qse/lib/rad/radmsg.c b/qse/lib/rad/radmsg.c index f458d149..a71378ee 100644 --- a/qse/lib/rad/radmsg.c +++ b/qse/lib/rad/radmsg.c @@ -368,7 +368,7 @@ int qse_rad_insert_wide_string_attribute_with_length ( return n; } -int qse_rad_insert_integer_attribute ( +int qse_rad_insert_uint32_attribute ( qse_rad_hdr_t* auth, int max, qse_uint32_t vendor, qse_uint8_t id, qse_uint32_t value) { qse_uint32_t val = qse_hton32(value); @@ -455,9 +455,44 @@ int qse_rad_insert_giga_attribute ( } } - return 0; + return 0; } + +int qse_rad_insert_extended_vendor_specific_attribute ( + qse_rad_hdr_t* auth, int max, qse_uint8_t base, qse_uint32_t vendor, + qse_uint8_t attrid, const void* ptr, qse_uint8_t len) +{ + /* RFC6929 */ + qse_rad_extvsattr_hdr_t* attr; + int auth_len = qse_ntoh16(auth->length); + int new_auth_len; + + if (base < 241 && base > 244) return -1; +/* TODO: for 245 and 246, switch to long-extended format */ + + /*if (len > QSE_RAD_MAX_EXTVSATTR_VALUE_LEN) return -1;*/ + if (len > QSE_RAD_MAX_EXTVSATTR_VALUE_LEN) len = QSE_RAD_MAX_EXTVSATTR_VALUE_LEN; + new_auth_len = auth_len + len + QSE_SIZEOF(*attr); + + if (new_auth_len > max) return -1; + + attr = (qse_rad_extvsattr_hdr_t*) ((char*)auth + auth_len); + attr->id = base; + attr->length = new_auth_len - auth_len; + attr->xid = QSE_RAD_ATTR_VENDOR_SPECIFIC; + attr->vendor = qse_hton32(vendor); + attr->evsid = attrid; + + /* no special header for the evs-value */ + QSE_MEMCPY (attr + 1, ptr, len); + + auth->length = qse_hton16(new_auth_len); + return 0; +} + + + #define PASS_BLKSIZE QSE_RAD_MAX_AUTHENTICATOR_LEN #define ALIGN(x,factor) ((((x) + (factor) - 1) / (factor)) * (factor)) diff --git a/qse/samples/rad/raddic01.c b/qse/samples/rad/raddic01.c index 6dd31875..6e291db5 100644 --- a/qse/samples/rad/raddic01.c +++ b/qse/samples/rad/raddic01.c @@ -4,14 +4,23 @@ #include #include +#if 0 +#include +#include +#include +#include +#endif + #define R(f) \ do { \ qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \ - if (f() == -1) return -1; \ + if (f() == -1) goto oops; \ } while (0) #define FAIL(msg) qse_printf(QSE_T("FAILURE in %hs line %d - %s\n"), __func__, __LINE__, msg) -#define _assert(test,msg) do { if (!(test)) { FAIL(msg); return -1; } } while(0) +#define FAIL2(msg1,msg2) qse_printf(QSE_T("FAILURE in %hs line %d - %s - %s\n"), __func__, __LINE__, msg1, msg2) +#define _assert(test,msg) do { if (!(test)) { FAIL(msg); goto oops; } } while(0) +#define _assert2(test,msg1,msg2) do { if (!(test)) { FAIL2(msg1,msg2); goto oops; } } while(0) #define _verify(test) do { int r=test(); tests_run++; if(r) return r; } while(0) static int test1 () @@ -165,6 +174,10 @@ static int test1 () qse_raddic_close (dic); return 0; + +oops: + if (dic) qse_raddic_close (dic); + return -1; } @@ -300,7 +313,7 @@ static int test2 () _assert (qse_strcasecmp(attr->name, tmp) == 0, QSE_T("wrong attr name")); attr = qse_raddic_findattrbyname (dic, tmpx); - _assert (attr == QSE_NULL, QSE_T("errorneous search success")); + _assert (attr == QSE_NULL, QSE_T("erroneous search success")); attr = qse_raddic_findattrbyname (dic, tmpy); _assert (attr != QSE_NULL, QSE_T("unable to add an attribute")); @@ -324,13 +337,13 @@ static int test2 () { int n; n = qse_raddic_deleteattrbyvalue (dic, QSE_RADDIC_ATTR_MAKE(0, 0)); - _assert (n == 0, QSE_T("errorneous deletion failure by value")); + _assert (n == 0, QSE_T("erroneous deletion failure by value")); n = qse_raddic_deleteattrbyvalue (dic, QSE_RADDIC_ATTR_MAKE(0, 0)); - _assert (n == 0, QSE_T("errorneous deletion failure by value")); + _assert (n == 0, QSE_T("erroneous deletion failure by value")); n = qse_raddic_deleteattrbyvalue (dic, QSE_RADDIC_ATTR_MAKE(0, 0)); - _assert (n <= -1, QSE_T("errorneous deletion success by value")); + _assert (n <= -1, QSE_T("erroneous deletion success by value")); } @@ -339,17 +352,12 @@ 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, &v); - _assert (con != QSE_NULL, QSE_T("unable to add an constant")); - _assert (con->value.type == QSE_RADDIC_ATTR_TYPE_UINT32 || con->value.u.ui32 == 10, QSE_T("wrong constant value")); + con = qse_raddic_addconst (dic, constr, attrstr, 10); + _assert2 (con != QSE_NULL, QSE_T("unable to add an constant"), qse_raddic_geterrmsg(dic)); + _assert (con->value == 10, QSE_T("wrong constant value")); _assert (qse_strcasecmp(con->name, constr) == 0, QSE_T("wrong constant name")); } } @@ -359,55 +367,46 @@ 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.type == QSE_RADDIC_ATTR_TYPE_UINT32 || con->value.u.ui32 == 10, QSE_T("wrong constant value")); + _assert (con->value == 10, QSE_T("wrong constant value")); - con = qse_raddic_findconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(j, i), &v); + con = qse_raddic_findconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(j, i), 10); _assert (con != QSE_NULL, QSE_T("unable to find an constant")); - _assert (con->value.type == QSE_RADDIC_ATTR_TYPE_UINT32 || con->value.u.ui32 == 10, QSE_T("wrong constant value")); + _assert (con->value == 10, QSE_T("wrong constant value")); _assert (con->attr == QSE_RADDIC_ATTR_MAKE(j, i), QSE_T("wrong constant value")); } } - { 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")); + _assert (n == 0, QSE_T("erroneous 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")); + _assert (n <= -1, QSE_T("erroneous constant deletion success")); - 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), 20); + _assert (n <= -1, QSE_T("erroneous constant deletion success")); - 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); + _assert (n == 0, QSE_T("erroneous constant deletion success")); - 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")); + n = qse_raddic_deleteconstbyvalue (dic, QSE_RADDIC_ATTR_MAKE(2,2), 10); + _assert (n <= -1, QSE_T("erroneous constant deletion success")); } qse_raddic_close (dic); return 0; + +oops: + if (dic) qse_raddic_close (dic); + return -1; } static int test3 () @@ -424,25 +423,60 @@ 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("fr2/dictionary")); - _assert (n == 0, qse_raddic_geterrmsg(dic)); + n = qse_raddic_load (dic, QSE_T("fr/dictionary")); + _assert2 (n == 0, QSE_T("unabled to load dictionary"), 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")); + _assert (c && c->value == 20, QSE_T("wrong constant value")); qse_raddic_close (dic); return 0; + +oops: + if (dic) qse_raddic_close (dic); + return -1; } +#if 0 +static int test10() +{ + struct sockaddr_in sin; + int s; + char buf[10000]; + + if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1; + + memset (&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr("192.168.1.2"); + sin.sin_port = htons(1812); + + qse_rad_initialize (buf, QSE_RAD_ACCESS_REQUEST, 99); + qse_rad_insert_extended_vendor_specific_attribute (buf, sizeof(buf), 243, 12345, 5, "xxxxxx", 6); + + sendto (s, buf, ntohs(((qse_rad_hdr_t*)buf)->length), 0, &sin, sizeof(sin)); + + close (s); + return 0; +} +#endif + int main () { qse_open_stdsios (); + R (test1); R (test2); R (test3); + +#if 0 + R (test10); +#endif + +oops: qse_close_stdsios (); return 0; }