From 0e85526d95f6d997a4c818acd3a06436676f326a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 13 Aug 2021 03:43:46 +0000 Subject: [PATCH] enhanced radius message handling functions --- hio/lib/hio-rad.h | 264 ++++++++++++++------- hio/lib/rad-msg.c | 593 +++++++++++++++++++++++++++++++--------------- hio/t/Makefile.am | 8 +- hio/t/Makefile.in | 47 +++- hio/t/t-003.c | 241 +++++++++++++++++++ 5 files changed, 865 insertions(+), 288 deletions(-) create mode 100644 hio/t/t-003.c diff --git a/hio/lib/hio-rad.h b/hio/lib/hio-rad.h index 6179deb..484d780 100644 --- a/hio/lib/hio-rad.h +++ b/hio/lib/hio-rad.h @@ -167,8 +167,27 @@ typedef int (*hio_rad_attr_walker_t) ( void* ctx ); -enum hio_rad_attr_type_t +#define HIO_RAD_ATTR_IS_SHORT_EXTENDED(attrtype) ((attrtype) >= HIO_RAD_ATTR_EXTENDED_1 && (attrtype) <= HIO_RAD_ATTR_EXTENDED_4) +#define HIO_RAD_ATTR_IS_LONG_EXTENDED(attrtype) ((attrtype) >= HIO_RAD_ATTR_EXTENDED_5 && (attrtype) <= HIO_RAD_ATTR_EXTENDED_6) +#define HIO_RAD_ATTR_IS_EXTENDED(attrtype) ((attrtype) >= HIO_RAD_ATTR_EXTENDED_1 && (attrtype) <= HIO_RAD_ATTR_EXTENDED_6) + +/* The attribute code is an attribute type encoded in 2 byte integer. */ +#define HIO_RAD_ATTR_CODE_MAKE(hi,lo) ((hio_uint16_t)((hi) & 0xFF) << 8 | ((lo) & 0xFF)) +#define HIO_RAD_ATTR_CODE_HI(attrtype) (((attrtype) >> 8) & 0xFF) +#define HIO_RAD_ATTR_CODE_LO(attrtype) ((attrtype) & 0xFF) + +#define HIO_RAD_ATTR_CODE_EXTENDED_1(lo) HIO_RAD_ATTR_CODE_MAKE(HIO_RAD_ATTR_EXTENDED_1, lo) +#define HIO_RAD_ATTR_CODE_EXTENDED_2(lo) HIO_RAD_ATTR_CODE_MAKE(HIO_RAD_ATTR_EXTENDED_2, lo) +#define HIO_RAD_ATTR_CODE_EXTENDED_3(lo) HIO_RAD_ATTR_CODE_MAKE(HIO_RAD_ATTR_EXTENDED_3, lo) +#define HIO_RAD_ATTR_CODE_EXTENDED_4(lo) HIO_RAD_ATTR_CODE_MAKE(HIO_RAD_ATTR_EXTENDED_4, lo) +#define HIO_RAD_ATTR_CODE_EXTENDED_5(lo) HIO_RAD_ATTR_CODE_MAKE(HIO_RAD_ATTR_EXTENDED_5, lo) +#define HIO_RAD_ATTR_CODE_EXTENDED_6(lo) HIO_RAD_ATTR_CODE_MAKE(HIO_RAD_ATTR_EXTENDED_6, lo) + +enum hio_rad_attr_code_t { + /* ----------------------------------------------------------- + * 1 byte attribute types. they can be used as a code or a type + * ----------------------------------------------------------- */ HIO_RAD_ATTR_USER_NAME = 1, /* string */ HIO_RAD_ATTR_USER_PASSWORD = 2, /* string encrypted */ HIO_RAD_ATTR_NAS_IP_ADDRESS = 4, /* ipaddr */ @@ -195,7 +214,7 @@ enum hio_rad_attr_type_t HIO_RAD_ATTR_NAS_PORT_TYPE = 61, /* integer */ HIO_RAD_ATTR_ACCT_INTERIM_INTERVAL = 85, /* integer */ HIO_RAD_ATTR_NAS_PORT_ID = 87, /* string */ - HIO_RAD_ATTR_FRAMED_IPV6_PREFIX = 97, /* ipv6prefix */ + HIO_RAD_ATTR_FRAMED_IPV6_PREFIX = 97, /* ipv6prefix */ HIO_RAD_ATTR_EXTENDED_1 = 241, HIO_RAD_ATTR_EXTENDED_2 = 242, @@ -203,11 +222,14 @@ enum hio_rad_attr_type_t HIO_RAD_ATTR_EXTENDED_4 = 244, HIO_RAD_ATTR_EXTENDED_5 = 245, /* long extended */ HIO_RAD_ATTR_EXTENDED_6 = 246, /* long extended */ + + /* ----------------------------------------------------------- + * 2-byte attribute codes. represented extended attributes. + * ----------------------------------------------------------- */ + HIO_RAD_ATTR_CODE_FRAG_STATUS = HIO_RAD_ATTR_CODE_EXTENDED_1(1), + HIO_RAD_ATTR_CODE_PROXY_STATE_LENGTH = HIO_RAD_ATTR_CODE_EXTENDED_1(2), }; -#define HIO_RAD_ATTR_IS_SHORT_EXTENDED(attrtype) ((attrtype) >= HIO_RAD_ATTR_EXTENDED_1 && (attrtype) <= HIO_RAD_ATTR_EXTENDED_4) -#define HIO_RAD_ATTR_IS_LONG_EXTENDED(attrtype) ((attrtype) >= HIO_RAD_ATTR_EXTENDED_5 && (attrtype) <= HIO_RAD_ATTR_EXTENDED_6) -#define HIO_RAD_ATTR_IS_EXTENDED(attrtype) ((attrtype) >= HIO_RAD_ATTR_EXTENDED_1 && (attrtype) <= HIO_RAD_ATTR_EXTENDED_6) enum hio_rad_attr_acct_status_type_t { @@ -252,80 +274,98 @@ enum hio_rad_attr_nas_port_type_t /* TODO: more types */ }; - #if defined(__cplusplus) extern "C" { #endif -/* ----------------------------------------------------------- - * RARIUS MESSAGE FUNCTIONS - * ----------------------------------------------------------- */ +/* ----------------------------------------------------------------------- */ + HIO_EXPORT void hio_rad_initialize ( hio_rad_hdr_t* hdr, hio_rad_code_t code, hio_uint8_t id ); -HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_find_attribute ( - hio_rad_hdr_t* hdr, - hio_uint8_t attrtype, - int index -); - -HIO_EXPORT hio_rad_vsattr_hdr_t* hio_rad_find_vsattr ( - hio_rad_hdr_t* hdr, - hio_uint32_t vendor, - hio_uint8_t attrtype, - int index -); - -HIO_EXPORT hio_rad_xvsattr_hdr_t* hio_rad_find_extended_vsattr ( - hio_rad_hdr_t* hdr, - hio_uint32_t vendor, - hio_uint8_t xtype, - hio_uint8_t attrtype, - int index -); - -HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_find_vendor_specific_attribute ( - hio_rad_hdr_t* hdr, - hio_uint32_t vendor, - hio_uint8_t id, - int index -); - HIO_EXPORT int hio_rad_walk_attributes ( const hio_rad_hdr_t* hdr, hio_rad_attr_walker_t walker, void* ctx ); -HIO_EXPORT int hio_rad_insert_attribute ( - hio_rad_hdr_t* auth, - int max, + +/* ----------------------------------------------------------------------- */ + +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_find_attr ( + hio_rad_hdr_t* hdr, + hio_uint16_t attrcode, + int index +); + +HIO_EXPORT hio_rad_vsattr_hdr_t* hio_rad_find_vsattr ( + hio_rad_hdr_t* hdr, + hio_uint32_t vendor, + hio_uint16_t attrcode, + int index +); + +HIO_EXPORT int hio_rad_delete_attr ( + hio_rad_hdr_t* hdr, + hio_uint16_t attrcode, + int index +); + +HIO_EXPORT int hio_rad_delete_vsattr ( + hio_rad_hdr_t* hdr, + hio_uint32_t vendor, + hio_uint16_t attrcode, + int index +); + +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_attr ( + hio_rad_hdr_t* auth, + int max, + hio_uint16_t attrcode, + const void* ptr, + hio_uint16_t len +); + +HIO_EXPORT hio_rad_vsattr_hdr_t* hio_rad_insert_vsattr ( + hio_rad_hdr_t* auth, + int max, + hio_uint32_t vendor, + hio_uint16_t attrcode, + const void* ptr, + hio_uint16_t len +); + +/* ----------------------------------------------------------------------- */ + +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_find_attribute ( + hio_rad_hdr_t* hdr, + hio_uint8_t attrtype, + int index +); + +HIO_EXPORT hio_rad_xattr_hdr_t* hio_rad_find_extended_attribute ( + hio_rad_hdr_t* hdr, + hio_uint8_t xtype, + hio_uint8_t attrtype, + int index +); + +HIO_EXPORT hio_rad_vsattr_hdr_t* hio_rad_find_vendor_specific_attribute ( + hio_rad_hdr_t* hdr, + hio_uint32_t vendor, hio_uint8_t id, - const void* ptr, - hio_uint8_t len + int index ); -HIO_EXPORT int hio_rad_insert_vendor_specific_attribute ( - hio_rad_hdr_t* auth, - int max, +HIO_EXPORT hio_rad_xvsattr_hdr_t* hio_rad_find_extended_vendor_specific_attribute ( + hio_rad_hdr_t* hdr, hio_uint32_t vendor, - hio_uint8_t attrtype, - const void* ptr, - hio_uint8_t len -); - -HIO_EXPORT int hio_rad_insert_extended_vendor_specific_attribute ( - hio_rad_hdr_t* auth, - int max, - hio_uint32_t vendor, - hio_uint8_t xtype, /* HIO_RAD_ATTR_EXTENDED_X */ - hio_uint8_t attrtype, - const void* ptr, - hio_uint8_t len, - hio_uint8_t lxflags + hio_uint8_t xtype, + hio_uint8_t attrtype, + int index ); HIO_EXPORT int hio_rad_delete_attribute ( @@ -334,6 +374,13 @@ HIO_EXPORT int hio_rad_delete_attribute ( int index ); +HIO_EXPORT int hio_rad_delete_extended_attribute ( + hio_rad_hdr_t* auth, + hio_uint8_t xtype, + hio_uint8_t attrtype, + int index +); + HIO_EXPORT int hio_rad_delete_vendor_specific_attribute ( hio_rad_hdr_t* auth, hio_uint32_t vendor, @@ -349,7 +396,46 @@ HIO_EXPORT int hio_rad_delete_extended_vendor_specific_attribute ( int index ); -HIO_EXPORT int hio_rad_insert_attribute_with_bcstr ( +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_attribute ( + hio_rad_hdr_t* auth, + int max, + hio_uint8_t id, + const void* ptr, + hio_uint8_t len +); + +HIO_EXPORT hio_rad_xattr_hdr_t* hio_rad_insert_extended_attribute ( + hio_rad_hdr_t* auth, + int max, + hio_uint8_t xtype, + hio_uint8_t attrtype, + const void* ptr, + hio_uint8_t len, + hio_uint8_t lxflags +); + +HIO_EXPORT hio_rad_vsattr_hdr_t* hio_rad_insert_vendor_specific_attribute ( + hio_rad_hdr_t* auth, + int max, + hio_uint32_t vendor, + hio_uint8_t attrtype, + const void* ptr, + hio_uint8_t len +); + +HIO_EXPORT hio_rad_xvsattr_hdr_t* hio_rad_insert_extended_vendor_specific_attribute ( + hio_rad_hdr_t* auth, + int max, + hio_uint32_t vendor, + hio_uint8_t xtype, /* HIO_RAD_ATTR_EXTENDED_X */ + hio_uint8_t attrtype, + const void* ptr, + hio_uint8_t len, + hio_uint8_t lxflags +); + + +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_bcstr ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, /* in host-byte order */ @@ -357,7 +443,7 @@ HIO_EXPORT int hio_rad_insert_attribute_with_bcstr ( const hio_bch_t* value ); -HIO_EXPORT int hio_rad_insert_attribute_ucstr ( +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_attribute_ucstr ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, /* in host-byte order */ @@ -365,7 +451,7 @@ HIO_EXPORT int hio_rad_insert_attribute_ucstr ( const hio_uch_t* value ); -HIO_EXPORT int hio_rad_insert_attribute_with_bchars ( +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_bchars ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, /* in host-byte order */ @@ -374,7 +460,7 @@ HIO_EXPORT int hio_rad_insert_attribute_with_bchars ( hio_uint8_t length ); -HIO_EXPORT int hio_rad_insert_attribute_with_uchars ( +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_uchars ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, /* in host-byte order */ @@ -383,7 +469,7 @@ HIO_EXPORT int hio_rad_insert_attribute_with_uchars ( hio_uint8_t length ); -HIO_EXPORT int hio_rad_insert_uint32_attribute ( +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_uint32_attribute ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, /* in host-byte order */ @@ -391,43 +477,47 @@ HIO_EXPORT int hio_rad_insert_uint32_attribute ( hio_uint32_t value /* in host-byte order */ ); -HIO_EXPORT int hio_rad_insert_ipv6prefix_attribute ( - hio_rad_hdr_t* auth, - int max, - hio_uint32_t vendor, /* in host-byte order */ - hio_uint8_t id, - hio_uint8_t prefix_bits, - const hio_ip6ad_t* value +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_ipv6prefix_attribute ( + hio_rad_hdr_t* auth, + int max, + hio_uint32_t vendor, /* in host-byte order */ + hio_uint8_t id, + hio_uint8_t prefix_bits, + const hio_ip6ad_t* value ); -HIO_EXPORT int hio_rad_insert_giga_attribute ( - hio_rad_hdr_t* auth, - int max, - hio_uint32_t vendor, - int low_id, - int high_id, - hio_uint64_t value +#if (HIO_SIZEOF_UINT64_T > 0) +HIO_EXPORT hio_rad_attr_hdr_t* hio_rad_insert_giga_attribute ( + hio_rad_hdr_t* auth, + int max, + hio_uint32_t vendor, + int low_id, + int high_id, + hio_uint64_t value ); +#endif +/* ----------------------------------------------------------------------- */ + HIO_EXPORT int hio_rad_set_user_password ( - hio_rad_hdr_t* auth, - int max, - const hio_bch_t* password, - const hio_bch_t* secret + hio_rad_hdr_t* auth, + int max, + const hio_bch_t* password, + const hio_bch_t* secret ); HIO_EXPORT void hio_rad_fill_authenticator ( - hio_rad_hdr_t* auth + hio_rad_hdr_t* auth ); HIO_EXPORT void hio_rad_copy_authenticator ( - hio_rad_hdr_t* dst, - const hio_rad_hdr_t* src + hio_rad_hdr_t* dst, + const hio_rad_hdr_t* src ); HIO_EXPORT int hio_rad_set_authenticator ( - hio_rad_hdr_t* req, - const hio_bch_t* secret + hio_rad_hdr_t* req, + const hio_bch_t* secret ); /* diff --git a/hio/lib/rad-msg.c b/hio/lib/rad-msg.c index 941144d..afb51ce 100644 --- a/hio/lib/rad-msg.c +++ b/hio/lib/rad-msg.c @@ -33,10 +33,10 @@ void hio_rad_initialize (hio_rad_hdr_t* hdr, hio_rad_code_t code, hio_uint8_t id) { - HIO_MEMSET (hdr, 0, sizeof(*hdr)); + HIO_MEMSET (hdr, 0, HIO_SIZEOF(*hdr)); hdr->code = code; hdr->id = id; - hdr->length = hio_hton16(sizeof(*hdr)); + hdr->length = hio_hton16(HIO_SIZEOF(*hdr)); } static HIO_INLINE void xor (void* p, void* q, int length) @@ -51,11 +51,9 @@ static void fill_authenticator_randomly (void* authenticator, int length) { hio_uint8_t* v = (hio_uint8_t*)authenticator; int total = 0; - -#if defined(__linux) int fd; - fd = open("/dev/urandom", O_RDONLY, 0); /* Linux: get *real* random numbers */ + fd = open("/dev/urandom", O_RDONLY, 0); if (fd >= 0) { while (total < length) @@ -66,7 +64,6 @@ static void fill_authenticator_randomly (void* authenticator, int length) } close (fd); } -#endif if (total < length) { @@ -86,6 +83,60 @@ static void fill_authenticator_randomly (void* authenticator, int length) } } +int hio_rad_walk_attributes (const hio_rad_hdr_t* hdr, hio_rad_attr_walker_t walker, void* ctx) +{ + int totlen, rem; + hio_rad_attr_hdr_t* attr; + + totlen = hio_ntoh16(hdr->length); + if (totlen < HIO_SIZEOF(*hdr)) return -1; + + rem = totlen - HIO_SIZEOF(*hdr); + attr = (hio_rad_attr_hdr_t*)(hdr + 1); + while (rem >= HIO_SIZEOF(*attr)) + { + /* sanity checks */ + if (rem < attr->length) return -1; + if (attr->length < HIO_SIZEOF(*attr)) + { + /* attribute length cannot be less than the header size. + * the packet could be corrupted... */ + return -1; + } + + rem -= attr->length; + + if (attr->type == HIO_RAD_ATTR_VENDOR_SPECIFIC) + { + hio_rad_vsattr_hdr_t* vsattr; + int val_len; + + if (attr->length < HIO_SIZEOF(*vsattr)) return -1; + vsattr = (hio_rad_vsattr_hdr_t*)attr; + + val_len = (int)vsattr->length - HIO_SIZEOF(*vsattr); + if ((int)vsattr->vs.length != val_len + HIO_SIZEOF(vsattr->vs)) return -1; + + /* if this vendor happens to be 0, walker can't tell + * if it is vendor specific or not because 0 is passed in + * for non-VSAs. but i don't care. in reality, + * 0 is reserved in IANA enterpirse number assignments. + * (http://www.iana.org/assignments/enterprise-numbers) */ + if (walker(hdr, hio_ntoh32(vsattr->vendor), &vsattr->vs, ctx) <= -1) return -1; + } + else + { + if (walker(hdr, 0, attr, ctx) <= -1) return -1; + } + + attr = (hio_rad_attr_hdr_t*)((hio_uint8_t*) attr + attr->length); + } + + return 0; +} + +/* ---------------------------------------------------------------- */ + static hio_rad_attr_hdr_t* find_attribute (hio_rad_attr_hdr_t* attr, int* len, hio_uint8_t attrtype) { int rem = *len; @@ -189,7 +240,7 @@ hio_rad_attr_hdr_t* hio_rad_find_attribute (hio_rad_hdr_t* hdr, hio_uint8_t attr return HIO_NULL; } -hio_rad_attr_hdr_t* hio_rad_find_extended_attribute (hio_rad_hdr_t* hdr, hio_uint8_t xtype, hio_uint8_t attrtype, int index) +hio_rad_xattr_hdr_t* hio_rad_find_extended_attribute (hio_rad_hdr_t* hdr, hio_uint8_t xtype, hio_uint8_t attrtype, int index) { hio_rad_attr_hdr_t *attr = (hio_rad_attr_hdr_t*)(hdr + 1); @@ -199,7 +250,7 @@ hio_rad_attr_hdr_t* hio_rad_find_extended_attribute (hio_rad_hdr_t* hdr, hio_uin attr = find_extended_attribute(attr, &len, xtype, attrtype); while (attr) { - if (index <= 0) return attr; + if (index <= 0) return (hio_rad_xattr_hdr_t*)attr; index--; attr = find_extended_attribute((hio_rad_attr_hdr_t*)((hio_uint8_t*)attr + attr->length), &len, xtype, attrtype); } @@ -208,7 +259,7 @@ hio_rad_attr_hdr_t* hio_rad_find_extended_attribute (hio_rad_hdr_t* hdr, hio_uin return HIO_NULL; } -hio_rad_vsattr_hdr_t* hio_rad_find_vsattr (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint8_t attrtype, int index) +hio_rad_vsattr_hdr_t* hio_rad_find_vendor_specific_attribute (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint8_t attrtype, int index) { hio_rad_attr_hdr_t *attr = (hio_rad_attr_hdr_t*)(hdr+1); @@ -246,7 +297,8 @@ hio_rad_vsattr_hdr_t* hio_rad_find_vsattr (hio_rad_hdr_t* hdr, hio_uint32_t vend return HIO_NULL; } -hio_rad_xvsattr_hdr_t* hio_rad_find_extended_vsattr (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint8_t xtype, hio_uint8_t attrtype, int index) + +hio_rad_xvsattr_hdr_t* hio_rad_find_extended_vendor_specific_attribute (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint8_t xtype, hio_uint8_t attrtype, int index) { hio_rad_attr_hdr_t *attr = (hio_rad_attr_hdr_t*)(hdr+1); @@ -309,115 +361,7 @@ hio_rad_xvsattr_hdr_t* hio_rad_find_extended_vsattr (hio_rad_hdr_t* hdr, hio_uin return HIO_NULL; } -hio_rad_attr_hdr_t* hio_rad_find_vendor_specific_attribute (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint8_t attrtype, int index) -{ - hio_rad_vsattr_hdr_t* vsattr; - vsattr = hio_rad_find_vsattr(hdr, vendor, attrtype, index); - return vsattr? &vsattr->vs: HIO_NULL; -} - -int hio_rad_walk_attributes (const hio_rad_hdr_t* hdr, hio_rad_attr_walker_t walker, void* ctx) -{ - int totlen, rem; - hio_rad_attr_hdr_t* attr; - - totlen = hio_ntoh16(hdr->length); - if (totlen < HIO_SIZEOF(*hdr)) return -1; - - rem = totlen - HIO_SIZEOF(*hdr); - attr = (hio_rad_attr_hdr_t*)(hdr + 1); - while (rem >= HIO_SIZEOF(*attr)) - { - /* sanity checks */ - if (rem < attr->length) return -1; - if (attr->length < HIO_SIZEOF(*attr)) - { - /* attribute length cannot be less than the header size. - * the packet could be corrupted... */ - return -1; - } - - rem -= attr->length; - - if (attr->type == HIO_RAD_ATTR_VENDOR_SPECIFIC) - { - hio_rad_vsattr_hdr_t* vsattr; - int val_len; - - if (attr->length < HIO_SIZEOF(*vsattr)) return -1; - vsattr = (hio_rad_vsattr_hdr_t*)attr; - - val_len = (int)vsattr->length - HIO_SIZEOF(*vsattr); - if ((int)vsattr->vs.length != val_len + HIO_SIZEOF(vsattr->vs)) return -1; - - /* if this vendor happens to be 0, walker can't tell - * if it is vendor specific or not because 0 is passed in - * for non-VSAs. but i don't care. in reality, - * 0 is reserved in IANA enterpirse number assignments. - * (http://www.iana.org/assignments/enterprise-numbers) */ - if (walker(hdr, hio_ntoh32(vsattr->vendor), &vsattr->vs, ctx) <= -1) return -1; - } - else - { - if (walker(hdr, 0, attr, ctx) <= -1) return -1; - } - - attr = (hio_rad_attr_hdr_t*)((hio_uint8_t*) attr + attr->length); - } - - return 0; -} - - -int hio_rad_insert_attribute ( - hio_rad_hdr_t* auth, int max, - hio_uint8_t id, const void* ptr, hio_uint8_t len) -{ - hio_rad_attr_hdr_t* attr; - int auth_len = hio_ntoh16(auth->length); - int new_auth_len; - - /*if (len > HIO_RAD_MAX_ATTR_VALUE_LEN) return -1;*/ - if (len > HIO_RAD_MAX_ATTR_VALUE_LEN) len = HIO_RAD_MAX_ATTR_VALUE_LEN; - new_auth_len = auth_len + len + HIO_SIZEOF(*attr); - - if (new_auth_len > max) return -1; - - attr = (hio_rad_attr_hdr_t*)((hio_uint8_t*)auth + auth_len); - attr->type = id; - attr->length = new_auth_len - auth_len; - HIO_MEMCPY (attr + 1, ptr, len); - auth->length = hio_hton16(new_auth_len); - - return 0; -} - -int hio_rad_insert_vendor_specific_attribute ( - hio_rad_hdr_t* auth, int max, - hio_uint32_t vendor, hio_uint8_t attrtype, const void* ptr, hio_uint8_t len) -{ - hio_rad_vsattr_hdr_t* vsattr; - int auth_len = hio_ntoh16(auth->length); - int new_auth_len; - - /*if (len > HIO_RAD_MAX_VSATTR_VALUE_LEN) return -1;*/ - if (len > HIO_RAD_MAX_VSATTR_VALUE_LEN) len = HIO_RAD_MAX_VSATTR_VALUE_LEN; - new_auth_len = auth_len + HIO_SIZEOF(*vsattr) + len; - - if (new_auth_len > max) return -1; - - vsattr = (hio_rad_vsattr_hdr_t*)((hio_uint8_t*)auth + auth_len); - vsattr->type = HIO_RAD_ATTR_VENDOR_SPECIFIC; - vsattr->length = new_auth_len - auth_len; - vsattr->vendor = hio_hton32(vendor); - - vsattr->vs.type = attrtype; - vsattr->vs.length = HIO_SIZEOF(vsattr->vs) + len; - HIO_MEMCPY (vsattr + 1, ptr, len); - - auth->length = hio_hton16(new_auth_len); - return 0; -} +/* ---------------------------------------------------------------- */ static int delete_attribute (hio_rad_hdr_t* auth, hio_rad_attr_hdr_t* attr) { @@ -444,12 +388,21 @@ int hio_rad_delete_attribute (hio_rad_hdr_t* auth, hio_uint8_t attrtype, int ind return (delete_attribute(auth, attr) <= -1)? -1: 1; } +int hio_rad_delete_extended_attribute (hio_rad_hdr_t* auth, hio_uint8_t xtype, hio_uint8_t attrtype, int index) +{ + hio_rad_xattr_hdr_t* attr; + + attr = hio_rad_find_extended_attribute(auth, xtype, attrtype, index); + if (!attr) return 0; /* not found */ + return (delete_attribute(auth, (hio_rad_attr_hdr_t*)attr) <= -1)? -1: 1; +} + int hio_rad_delete_vendor_specific_attribute ( hio_rad_hdr_t* auth, hio_uint32_t vendor, hio_uint8_t attrtype, int index) { hio_rad_vsattr_hdr_t* vsattr; - vsattr = hio_rad_find_vsattr(auth, vendor, attrtype, 0); + vsattr = hio_rad_find_vendor_specific_attribute(auth, vendor, attrtype, 0); if (!vsattr) return 0; /* not found */ return (delete_attribute(auth, (hio_rad_attr_hdr_t*)vsattr) <= -1)? -1: 1; } @@ -459,76 +412,225 @@ int hio_rad_delete_extended_vendor_specific_attribute ( { hio_rad_xvsattr_hdr_t* xvsattr; - xvsattr = hio_rad_find_extended_vsattr(auth, vendor, xtype, attrtype, 0); + xvsattr = hio_rad_find_extended_vendor_specific_attribute(auth, vendor, xtype, attrtype, 0); if (!xvsattr) return 0; /* not found */ return (delete_attribute(auth, (hio_rad_attr_hdr_t*)xvsattr) <= -1)? -1: 1; } -int hio_rad_insert_attribute_with_bcstr ( +/* ---------------------------------------------------------------- */ + +hio_rad_attr_hdr_t* hio_rad_insert_attribute ( + hio_rad_hdr_t* auth, int max, + hio_uint8_t attrtype, const void* ptr, hio_uint8_t len) +{ + hio_rad_attr_hdr_t* attr; + int auth_len = hio_ntoh16(auth->length); + int new_auth_len; + + /*if (len > HIO_RAD_MAX_ATTR_VALUE_LEN) return HIO_NULL;*/ + if (len > HIO_RAD_MAX_ATTR_VALUE_LEN) len = HIO_RAD_MAX_ATTR_VALUE_LEN; + new_auth_len = auth_len + HIO_SIZEOF(*attr) + len; + + if (new_auth_len > max) return HIO_NULL; + + attr = (hio_rad_attr_hdr_t*)((hio_uint8_t*)auth + auth_len); + attr->type = attrtype; + attr->length = new_auth_len - auth_len; + HIO_MEMCPY (attr + 1, ptr, len); + auth->length = hio_hton16(new_auth_len); + + return attr; +} + +hio_rad_xattr_hdr_t* hio_rad_insert_extended_attribute ( + hio_rad_hdr_t* auth, int max, hio_uint8_t xtype, + hio_uint8_t attrtype, const void* ptr, hio_uint8_t len, hio_uint8_t lxflags) +{ + hio_rad_xattr_hdr_t* xattr; + int auth_len = hio_ntoh16(auth->length); + int new_auth_len, maxvallen, hdrlen; + + if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(xtype)) + { + maxvallen = HIO_RAD_MAX_XATTR_VALUE_LEN; + hdrlen = HIO_SIZEOF(hio_rad_xattr_hdr_t); + } + else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(xtype)) + { + maxvallen = HIO_RAD_MAX_LXATTR_VALUE_LEN; + hdrlen = HIO_SIZEOF(hio_rad_lxattr_hdr_t); + } + else return HIO_NULL; + + /*if (len > maxvallen) return HIO_NULL;*/ + if (len > maxvallen) len = maxvallen; + new_auth_len = auth_len + hdrlen + len; + + if (new_auth_len > max) return HIO_NULL; + + xattr = (hio_rad_xattr_hdr_t*)((hio_uint8_t*)auth + auth_len); + xattr->type = xtype; + xattr->length = new_auth_len - auth_len; + if (HIO_RAD_ATTR_IS_LONG_EXTENDED(xtype)) + { + hio_rad_lxattr_hdr_t* lxattr; + lxattr = (hio_rad_lxattr_hdr_t*)xattr; + lxattr->xtype = attrtype; + lxattr->xflags = lxflags; + HIO_MEMCPY (lxattr + 1, ptr, len); + } + else + { + xattr->xtype = attrtype; + HIO_MEMCPY (xattr + 1, ptr, len); + } + auth->length = hio_hton16(new_auth_len); + + return xattr; +} + +hio_rad_vsattr_hdr_t* hio_rad_insert_vendor_specific_attribute ( + hio_rad_hdr_t* auth, int max, + hio_uint32_t vendor, hio_uint8_t attrtype, const void* ptr, hio_uint8_t len) +{ + hio_rad_vsattr_hdr_t* vsattr; + int auth_len = hio_ntoh16(auth->length); + int new_auth_len; + + /*if (len > HIO_RAD_MAX_VSATTR_VALUE_LEN) return HIO_NULL;*/ + if (len > HIO_RAD_MAX_VSATTR_VALUE_LEN) len = HIO_RAD_MAX_VSATTR_VALUE_LEN; + new_auth_len = auth_len + HIO_SIZEOF(*vsattr) + len; + + if (new_auth_len > max) return HIO_NULL; + + vsattr = (hio_rad_vsattr_hdr_t*)((hio_uint8_t*)auth + auth_len); + vsattr->type = HIO_RAD_ATTR_VENDOR_SPECIFIC; + vsattr->length = new_auth_len - auth_len; + vsattr->vendor = hio_hton32(vendor); + + vsattr->vs.type = attrtype; + vsattr->vs.length = HIO_SIZEOF(vsattr->vs) + len; + HIO_MEMCPY (vsattr + 1, ptr, len); + + auth->length = hio_hton16(new_auth_len); + return vsattr; +} + +hio_rad_xvsattr_hdr_t* hio_rad_insert_extended_vendor_specific_attribute ( + hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t xtype, + hio_uint8_t attrtype, const void* ptr, hio_uint8_t len, hio_uint8_t lxflags) +{ + /* RFC6929 */ + hio_rad_xvsattr_hdr_t* xvsattr; + int auth_len = hio_ntoh16(auth->length); + int new_auth_len, maxvallen, hdrlen; + + if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(xtype)) + { + maxvallen = HIO_RAD_MAX_XVSATTR_VALUE_LEN; + hdrlen = HIO_SIZEOF(hio_rad_xvsattr_hdr_t); + } + else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(xtype)) + { + maxvallen = HIO_RAD_MAX_LXVSATTR_VALUE_LEN; + hdrlen = HIO_SIZEOF(hio_rad_lxvsattr_hdr_t); + } + else return HIO_NULL; + + /*if (len > maxvallen) return HIO_NULL;*/ + if (len > maxvallen) len = HIO_RAD_MAX_XVSATTR_VALUE_LEN; + new_auth_len = auth_len + hdrlen + len; + + if (new_auth_len > max) return HIO_NULL; + + xvsattr = (hio_rad_xvsattr_hdr_t*)((hio_uint8_t*)auth + auth_len); + xvsattr->type = xtype; + xvsattr->length = new_auth_len - auth_len; + xvsattr->xtype = HIO_RAD_ATTR_VENDOR_SPECIFIC; + xvsattr->vendor = hio_hton32(vendor); + + if (HIO_RAD_ATTR_IS_LONG_EXTENDED(xtype)) + { + /* this function is still low-level. it doesn't handle continuation of big data */ + hio_rad_lxvsattr_hdr_t* lxvsattr; + lxvsattr = (hio_rad_lxvsattr_hdr_t*)xvsattr; + lxvsattr->lxvs.type = attrtype; + lxvsattr->lxvs.flags = lxflags; + lxvsattr->lxvs.length = len + HIO_SIZEOF(lxvsattr->lxvs); + HIO_MEMCPY (lxvsattr + 1, ptr, len); + } + else + { + xvsattr->xvs.type = attrtype; + xvsattr->xvs.length = len + HIO_SIZEOF(xvsattr->xvs); + HIO_MEMCPY (xvsattr + 1, ptr, len); + } + + auth->length = hio_hton16(new_auth_len); + return xvsattr; +} + +/* ---------------------------------------------------------------- */ + +hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_bcstr ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t id, const hio_bch_t* value) { return (vendor == 0)? hio_rad_insert_attribute(auth, max, id, value, hio_count_bcstr(value)): - hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, value, hio_count_bcstr(value)); + (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, value, hio_count_bcstr(value)); } -int hio_rad_insert_attribute_with_ucstr ( +hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_ucstr ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t id, const hio_uch_t* value) { - int n; hio_oow_t bcslen, ucslen; hio_bch_t bcsval[HIO_RAD_MAX_ATTR_VALUE_LEN + 1]; bcslen = HIO_COUNTOF(bcsval); - if (hio_conv_ucstr_to_utf8(value, &ucslen, bcsval, &bcslen) <= -1) return -1; - n = (vendor == 0)? + if (hio_conv_ucstr_to_utf8(value, &ucslen, bcsval, &bcslen) <= -1) return HIO_NULL; + return (vendor == 0)? hio_rad_insert_attribute(auth, max, id, bcsval, bcslen): - hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, bcsval, bcslen); - - return n; + (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, bcsval, bcslen); } -int hio_rad_insert_attribute_with_bchars ( +hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_bchars ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t id, const hio_bch_t* value, hio_uint8_t length) { return (vendor == 0)? hio_rad_insert_attribute(auth, max, id, value, length): - hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, value, length); + (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, value, length); } -int hio_rad_insert_attribute_with_uchars ( +hio_rad_attr_hdr_t* hio_rad_insert_attribute_with_uchars ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t id, const hio_uch_t* value, hio_uint8_t length) { - int n; hio_oow_t bcslen, ucslen; hio_bch_t bcsval[HIO_RAD_MAX_ATTR_VALUE_LEN]; ucslen = length; bcslen = HIO_COUNTOF(bcsval); - if (hio_conv_uchars_to_utf8(value, &ucslen, bcsval, &bcslen) <= -1) return -1; + if (hio_conv_uchars_to_utf8(value, &ucslen, bcsval, &bcslen) <= -1) return HIO_NULL; - n = (vendor == 0)? + return (vendor == 0)? hio_rad_insert_attribute(auth, max, id, bcsval, bcslen): - hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, bcsval, bcslen); - - return n; + (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, bcsval, bcslen); } -int hio_rad_insert_uint32_attribute ( +hio_rad_attr_hdr_t* hio_rad_insert_uint32_attribute ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t id, hio_uint32_t value) { hio_uint32_t val = hio_hton32(value); return (vendor == 0)? hio_rad_insert_attribute(auth, max, id, &val, HIO_SIZEOF(val)): - hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, &val, HIO_SIZEOF(val)); + (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, &val, HIO_SIZEOF(val)); } -int hio_rad_insert_ipv6prefix_attribute ( +hio_rad_attr_hdr_t* hio_rad_insert_ipv6prefix_attribute ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t id, hio_uint8_t prefix_bits, const hio_ip6ad_t* value) { @@ -544,7 +646,7 @@ int hio_rad_insert_ipv6prefix_attribute ( if (prefix_bits > 128) prefix_bits = 128; - HIO_MEMSET (&ipv6prefix, 0, sizeof(ipv6prefix)); + HIO_MEMSET (&ipv6prefix, 0, HIO_SIZEOF(ipv6prefix)); ipv6prefix.bits = prefix_bits; for (i = 0, j = 0; i < prefix_bits; i += 8, j++) @@ -571,98 +673,197 @@ int hio_rad_insert_ipv6prefix_attribute ( return (vendor == 0)? hio_rad_insert_attribute(auth, max, id, &ipv6prefix, j + 2): - hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, &ipv6prefix, j + 2); + (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, id, &ipv6prefix, j + 2); } -int hio_rad_insert_giga_attribute ( +#if (HIO_SIZEOF_UINT64_T > 0) +hio_rad_attr_hdr_t* hio_rad_insert_giga_attribute ( hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, int low_id, int high_id, hio_uint64_t value) { + hio_rad_attr_hdr_t* hdr; hio_uint32_t low; low = value & HIO_TYPE_MAX(hio_uint32_t); low = hio_hton32(low); if (vendor == 0) { - if (hio_rad_insert_attribute(auth, max, low_id, &low, HIO_SIZEOF(low)) <= -1) return -1; + hdr = hio_rad_insert_attribute(auth, max, low_id, &low, HIO_SIZEOF(low)); + if (!hdr) return HIO_NULL; if (value > HIO_TYPE_MAX(hio_uint32_t)) { hio_uint32_t high; high = value >> (HIO_SIZEOF(hio_uint32_t) * 8); high = hio_hton32(high); - if (hio_rad_insert_attribute(auth, max, high_id, &high, HIO_SIZEOF(high)) <= -1) return -1; + if (!hio_rad_insert_attribute(auth, max, high_id, &high, HIO_SIZEOF(high))) return HIO_NULL; } } else { - if (hio_rad_insert_vendor_specific_attribute(auth, max, vendor, low_id, &low, HIO_SIZEOF(low)) <= -1) return -1; + hdr = (hio_rad_attr_hdr_t*)hio_rad_insert_vendor_specific_attribute(auth, max, vendor, low_id, &low, HIO_SIZEOF(low)); + if (!hdr) return HIO_NULL; if (value > HIO_TYPE_MAX(hio_uint32_t)) { hio_uint32_t high; high = value >> (HIO_SIZEOF(hio_uint32_t) * 8); high = hio_hton32(high); - if (hio_rad_insert_vendor_specific_attribute(auth, max, vendor, high_id, &high, HIO_SIZEOF(high)) <= -1) return -1; + if (!hio_rad_insert_vendor_specific_attribute(auth, max, vendor, high_id, &high, HIO_SIZEOF(high))) return HIO_NULL; } } - return 0; + return hdr; } +#endif -int hio_rad_insert_extended_vendor_specific_attribute ( - hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint8_t xtype, - hio_uint8_t attrtype, const void* ptr, hio_uint8_t len, hio_uint8_t lxflags) +/* ----------------------------------------------------------------------- + * HIGH-LEVEL ATTRIBUTE FUNCTIONS + * ----------------------------------------------------------------------- */ + +hio_rad_attr_hdr_t* hio_rad_find_attr (hio_rad_hdr_t* hdr, hio_uint16_t attrcode, int index) { - /* RFC6929 */ - hio_rad_xvsattr_hdr_t* xvsattr; - int auth_len = hio_ntoh16(auth->length); - int new_auth_len, maxvallen, hdrlen; + hio_uint8_t hi, lo; - if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(xtype)) + hi = HIO_RAD_ATTR_CODE_HI(attrcode); + lo = HIO_RAD_ATTR_CODE_LO(attrcode); + + if (!hi) { - maxvallen = HIO_RAD_MAX_XVSATTR_VALUE_LEN; - hdrlen = HIO_SIZEOF(hio_rad_xvsattr_hdr_t); + return hio_rad_find_attribute(hdr, lo, index); } - else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(xtype)) + else if (HIO_RAD_ATTR_IS_EXTENDED(hi)) { - maxvallen = HIO_RAD_MAX_LXVSATTR_VALUE_LEN; - hdrlen = HIO_SIZEOF(hio_rad_lxvsattr_hdr_t); + /* both short and long */ + return (hio_rad_attr_hdr_t*)hio_rad_find_extended_attribute(hdr, hi, lo, index); } - else return -1; - /*if (len > maxvallen) return -1;*/ - if (len > maxvallen) len = HIO_RAD_MAX_XVSATTR_VALUE_LEN; - new_auth_len = auth_len + hdrlen + len; - - if (new_auth_len > max) return -1; - - xvsattr = (hio_rad_xvsattr_hdr_t*)((hio_uint8_t*)auth + auth_len); - xvsattr->type = xtype; - xvsattr->length = new_auth_len - auth_len; - xvsattr->xtype = HIO_RAD_ATTR_VENDOR_SPECIFIC; - xvsattr->vendor = hio_hton32(vendor); - - if (HIO_RAD_ATTR_IS_LONG_EXTENDED(xtype)) - { - /* this function is still low-level. it doesn't handle continuation of big data */ - hio_rad_lxvsattr_hdr_t* lxvsattr; - lxvsattr = (hio_rad_lxvsattr_hdr_t*)xvsattr; - lxvsattr->lxvs.type = attrtype; - lxvsattr->lxvs.flags = lxflags; - lxvsattr->lxvs.length = len + HIO_SIZEOF(lxvsattr->lxvs); - HIO_MEMCPY (lxvsattr + 1, ptr, len); - } - else - { - xvsattr->xvs.type = attrtype; - xvsattr->xvs.length = len + HIO_SIZEOF(xvsattr->xvs); - HIO_MEMCPY (xvsattr + 1, ptr, len); - } - - auth->length = hio_hton16(new_auth_len); - return 0; + /* attribute code out of range */ + return HIO_NULL; } + +hio_rad_vsattr_hdr_t* hio_rad_find_vsattr (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint16_t attrcode, int index) +{ + hio_uint8_t hi, lo; + + hi = HIO_RAD_ATTR_CODE_HI(attrcode); + lo = HIO_RAD_ATTR_CODE_LO(attrcode); + + if (!hi) + { + return hio_rad_find_vendor_specific_attribute(hdr, vendor, lo, index); + } + else if (HIO_RAD_ATTR_IS_EXTENDED(hi)) + { + /* both short and long */ + return (hio_rad_vsattr_hdr_t*)hio_rad_find_extended_vendor_specific_attribute(hdr, vendor, hi, lo, index); + } + + /* attribute code out of range */ + return HIO_NULL; +} + + +int hio_rad_delete_attr (hio_rad_hdr_t* hdr, hio_uint16_t attrcode, int index) +{ + hio_uint8_t hi, lo; + + hi = HIO_RAD_ATTR_CODE_HI(attrcode); + lo = HIO_RAD_ATTR_CODE_LO(attrcode); + + if (!hi) + { + return hio_rad_delete_attribute(hdr, lo, index); + } + else if (HIO_RAD_ATTR_IS_EXTENDED(hi)) + { + /* both short and long */ + return hio_rad_delete_extended_attribute(hdr, hi, lo, index); + } + + /* attribute code out of range */ + return -2; +} + + +int hio_rad_delete_vsattr (hio_rad_hdr_t* hdr, hio_uint32_t vendor, hio_uint16_t attrcode, int index) +{ + hio_uint8_t hi, lo; + + hi = HIO_RAD_ATTR_CODE_HI(attrcode); + lo = HIO_RAD_ATTR_CODE_LO(attrcode); + + if (!hi) + { + return hio_rad_delete_vendor_specific_attribute(hdr, vendor, lo, index); + } + else if (HIO_RAD_ATTR_IS_EXTENDED(hi)) + { + /* both short and long */ + return hio_rad_delete_extended_vendor_specific_attribute(hdr, vendor, hi, lo, index); + } + + /* attribute code out of range */ + return -2; +} + +hio_rad_attr_hdr_t* hio_rad_insert_attr (hio_rad_hdr_t* auth, int max, hio_uint16_t attrcode, const void* ptr, hio_uint16_t len) +{ + hio_uint8_t hi, lo; + + hi = HIO_RAD_ATTR_CODE_HI(attrcode); + lo = HIO_RAD_ATTR_CODE_LO(attrcode); + + if (!hi) + { + /* classical attribute */ + return hio_rad_insert_attribute(auth, max, lo, ptr, len); + } + else if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(hi)) + { + return (hio_rad_attr_hdr_t*)hio_rad_insert_extended_attribute(auth, max, hi, lo, ptr, len, 0); + } + else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(hi)) + { + /* TODO: mutliple attributes if data is long */ + return (hio_rad_attr_hdr_t*)hio_rad_insert_extended_attribute(auth, max, hi, lo, ptr, len, 0); + } + + /* attribute code out of range */ + return HIO_NULL; +} + + +hio_rad_vsattr_hdr_t* hio_rad_insert_vsattr (hio_rad_hdr_t* auth, int max, hio_uint32_t vendor, hio_uint16_t attrcode, const void* ptr, hio_uint16_t len) +{ + hio_uint8_t hi, lo; + + hi = HIO_RAD_ATTR_CODE_HI(attrcode); + lo = HIO_RAD_ATTR_CODE_LO(attrcode); + + if (!hi) + { + /* classical attribute */ + return hio_rad_insert_vendor_specific_attribute(auth, max, vendor, lo, ptr, len); + } + else if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(hi)) + { + return (hio_rad_vsattr_hdr_t*)hio_rad_insert_extended_vendor_specific_attribute(auth, max, vendor, hi, lo, ptr, len, 0); + } + else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(hi)) + { + /* TODO: if len is greater than the maxm add multiple extended attributes with continuation */ + return (hio_rad_vsattr_hdr_t*)hio_rad_insert_extended_vendor_specific_attribute(auth, max, vendor, hi, lo, ptr, len, 0); + } + + /* attribute code out of range */ + return HIO_NULL; +} + +/* ----------------------------------------------------------------------- + * UTILITY FUNCTIONS + * ----------------------------------------------------------------------- */ + #define PASS_BLKSIZE HIO_RAD_MAX_AUTHENTICATOR_LEN #define ALIGN(x,factor) ((((x) + (factor) - 1) / (factor)) * (factor)) @@ -727,7 +928,7 @@ int hio_rad_set_user_password (hio_rad_hdr_t* auth, int max, const hio_bch_t* pa if (n <= -1) goto oops; if (n == 0) break; } - if (hio_rad_insert_attribute(auth, max, HIO_RAD_ATTR_USER_PASSWORD, hashed, padlen) <= -1) goto oops; + if (!hio_rad_insert_attribute(auth, max, HIO_RAD_ATTR_USER_PASSWORD, hashed, padlen)) goto oops; return 0; diff --git a/hio/t/Makefile.am b/hio/t/Makefile.am index 61846a6..dfd4099 100644 --- a/hio/t/Makefile.am +++ b/hio/t/Makefile.am @@ -17,7 +17,7 @@ check_SCRIPTS = ##noinst_SCRIPTS = $(check_SCRIPTS) EXTRA_DIST = $(check_SCRIPTS) -check_PROGRAMS = t-001 t-002 +check_PROGRAMS = t-001 t-002 t-003 t_001_SOURCES = t-001.c t.h t_001_CPPFLAGS = $(CPPFLAGS_COMMON) @@ -31,6 +31,12 @@ t_002_CFLAGS = $(CFLAGS_COMMON) t_002_LDFLAGS = $(LDFLAGS_COMMON) t_002_LDADD = $(LIBADD_COMMON) +t_003_SOURCES = t-003.c t.h +t_003_CPPFLAGS = $(CPPFLAGS_COMMON) +t_003_CFLAGS = $(CFLAGS_COMMON) +t_003_LDFLAGS = $(LDFLAGS_COMMON) +t_003_LDADD = $(LIBADD_COMMON) + TESTS = $(check_PROGRAMS) $(check_SCRIPTS) diff --git a/hio/t/Makefile.in b/hio/t/Makefile.in index 5cdd756..410df55 100644 --- a/hio/t/Makefile.in +++ b/hio/t/Makefile.in @@ -87,7 +87,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -check_PROGRAMS = t-001$(EXEEXT) t-002$(EXEEXT) +check_PROGRAMS = t-001$(EXEEXT) t-002$(EXEEXT) t-003$(EXEEXT) TESTS = $(check_PROGRAMS) $(am__EXEEXT_1) subdir = t ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -122,6 +122,12 @@ t_002_DEPENDENCIES = $(am__DEPENDENCIES_2) t_002_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_002_CFLAGS) $(CFLAGS) \ $(t_002_LDFLAGS) $(LDFLAGS) -o $@ +am_t_003_OBJECTS = t_003-t-003.$(OBJEXT) +t_003_OBJECTS = $(am_t_003_OBJECTS) +t_003_DEPENDENCIES = $(am__DEPENDENCIES_2) +t_003_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_003_CFLAGS) $(CFLAGS) \ + $(t_003_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -138,7 +144,7 @@ DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/ac/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/t_001-t-001.Po \ - ./$(DEPDIR)/t_002-t-002.Po + ./$(DEPDIR)/t_002-t-002.Po ./$(DEPDIR)/t_003-t-003.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -158,8 +164,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) -DIST_SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) +SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) $(t_003_SOURCES) +DIST_SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) $(t_003_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -553,6 +559,11 @@ t_002_CPPFLAGS = $(CPPFLAGS_COMMON) t_002_CFLAGS = $(CFLAGS_COMMON) t_002_LDFLAGS = $(LDFLAGS_COMMON) t_002_LDADD = $(LIBADD_COMMON) +t_003_SOURCES = t-003.c t.h +t_003_CPPFLAGS = $(CPPFLAGS_COMMON) +t_003_CFLAGS = $(CFLAGS_COMMON) +t_003_LDFLAGS = $(LDFLAGS_COMMON) +t_003_LDADD = $(LIBADD_COMMON) all: all-am .SUFFIXES: @@ -604,6 +615,10 @@ t-002$(EXEEXT): $(t_002_OBJECTS) $(t_002_DEPENDENCIES) $(EXTRA_t_002_DEPENDENCIE @rm -f t-002$(EXEEXT) $(AM_V_CCLD)$(t_002_LINK) $(t_002_OBJECTS) $(t_002_LDADD) $(LIBS) +t-003$(EXEEXT): $(t_003_OBJECTS) $(t_003_DEPENDENCIES) $(EXTRA_t_003_DEPENDENCIES) + @rm -f t-003$(EXEEXT) + $(AM_V_CCLD)$(t_003_LINK) $(t_003_OBJECTS) $(t_003_LDADD) $(LIBS) + mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -612,6 +627,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_001-t-001.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_002-t-002.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_003-t-003.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -671,6 +687,20 @@ t_002-t-002.obj: t-002.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_002_CPPFLAGS) $(CPPFLAGS) $(t_002_CFLAGS) $(CFLAGS) -c -o t_002-t-002.obj `if test -f 't-002.c'; then $(CYGPATH_W) 't-002.c'; else $(CYGPATH_W) '$(srcdir)/t-002.c'; fi` +t_003-t-003.o: t-003.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_003_CPPFLAGS) $(CPPFLAGS) $(t_003_CFLAGS) $(CFLAGS) -MT t_003-t-003.o -MD -MP -MF $(DEPDIR)/t_003-t-003.Tpo -c -o t_003-t-003.o `test -f 't-003.c' || echo '$(srcdir)/'`t-003.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_003-t-003.Tpo $(DEPDIR)/t_003-t-003.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-003.c' object='t_003-t-003.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_003_CPPFLAGS) $(CPPFLAGS) $(t_003_CFLAGS) $(CFLAGS) -c -o t_003-t-003.o `test -f 't-003.c' || echo '$(srcdir)/'`t-003.c + +t_003-t-003.obj: t-003.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_003_CPPFLAGS) $(CPPFLAGS) $(t_003_CFLAGS) $(CFLAGS) -MT t_003-t-003.obj -MD -MP -MF $(DEPDIR)/t_003-t-003.Tpo -c -o t_003-t-003.obj `if test -f 't-003.c'; then $(CYGPATH_W) 't-003.c'; else $(CYGPATH_W) '$(srcdir)/t-003.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_003-t-003.Tpo $(DEPDIR)/t_003-t-003.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-003.c' object='t_003-t-003.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_003_CPPFLAGS) $(CPPFLAGS) $(t_003_CFLAGS) $(CFLAGS) -c -o t_003-t-003.obj `if test -f 't-003.c'; then $(CYGPATH_W) 't-003.c'; else $(CYGPATH_W) '$(srcdir)/t-003.c'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -884,6 +914,13 @@ t-002.log: t-002$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +t-003.log: t-003$(EXEEXT) + @p='t-003$(EXEEXT)'; \ + b='t-003'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ @@ -979,6 +1016,7 @@ clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ distclean: distclean-am -rm -f ./$(DEPDIR)/t_001-t-001.Po -rm -f ./$(DEPDIR)/t_002-t-002.Po + -rm -f ./$(DEPDIR)/t_003-t-003.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1026,6 +1064,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/t_001-t-001.Po -rm -f ./$(DEPDIR)/t_002-t-002.Po + -rm -f ./$(DEPDIR)/t_003-t-003.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/hio/t/t-003.c b/hio/t/t-003.c new file mode 100644 index 0000000..59ae198 --- /dev/null +++ b/hio/t/t-003.c @@ -0,0 +1,241 @@ + +#include +#include +#include "t.h" + + +#include +#include +#include + +int main () +{ + { + hio_uint8_t buf[10240]; + hio_rad_hdr_t* hdr = buf; + + + int i, j, n, exptotlen; + + struct + { + int index; /* index among same attributes */ + int vendor; + int attrcode; + void* ptr; + int len; + } data[] = { + { 0, 0, HIO_RAD_ATTR_REPLY_MESSAGE, "reply message", 13 }, + { 1, 0, HIO_RAD_ATTR_REPLY_MESSAGE, "reply message 2", 15 }, + { 0, 10415, 1, "470010171566423", 15 }, + { 0, 10415, 8, "imsi-mcc-mnc", 12 }, + { 0, 4329, 5, "ssid", 4 }, + { 0, 0, HIO_RAD_ATTR_NAS_IDENTIFIER, "nas identifier", 14 }, + { 1, 10415, 8, "imsi-mcc-mnc-2", 14 }, + + /* Frag-Status 241.1 integer. */ + { 0, 0, HIO_RAD_ATTR_CODE_EXTENDED_1(1), "\x02", 1 }, + { 1, 0, HIO_RAD_ATTR_CODE_EXTENDED_1(1), "\x01", 1 }, + { 2, 0, HIO_RAD_ATTR_CODE_EXTENDED_1(1), "\x00", 1 }, + /* Proxy-State-Length 241.2 integer. */ + { 0, 0, HIO_RAD_ATTR_CODE_EXTENDED_1(2), "\xFF", 1 }, + + { 3, 0, HIO_RAD_ATTR_CODE_EXTENDED_1(1), "\x03", 1 }, + { 1, 0, HIO_RAD_ATTR_CODE_EXTENDED_1(2), "\xDD", 1 }, + + + { 0, 6527, HIO_RAD_ATTR_CODE_EXTENDED_1(2), "evs attribute", 13 }, + { 1, 6527, HIO_RAD_ATTR_CODE_EXTENDED_1(2), "evs attribute 2", 15 }, + { 0, 8888, HIO_RAD_ATTR_CODE_EXTENDED_4(444), "evs attribute", 13 }, + + { 2, 0, HIO_RAD_ATTR_REPLY_MESSAGE, "reply message 3", 15 }, + }; + + hio_rad_initialize (buf, HIO_RAD_ACCESS_REQUEST, 255); + T_ASSERT1 (hdr->code == HIO_RAD_ACCESS_REQUEST, "hdr->code not ok"); + T_ASSERT1 (hdr->id == 255, "hdr->id not ok"); + exptotlen = HIO_SIZEOF(*hdr); + T_ASSERT1 (hdr->length == HIO_CONST_HTON16(HIO_SIZEOF(*hdr)), "hdr->length not ok"); + + for (i = 0; i < HIO_COUNTOF(data); i++) + { + if (data[i].vendor) + { + hio_rad_vsattr_hdr_t* vsattr; + hio_rad_xvsattr_hdr_t* xvsattr; + hio_rad_lxvsattr_hdr_t* lxvsattr; + + vsattr = hio_rad_insert_vsattr(hdr, HIO_SIZEOF(buf), data[i].vendor, data[i].attrcode, data[i].ptr, data[i].len); + T_ASSERT1 (vsattr != HIO_NULL, "attribute insertion failure"); + T_ASSERT1 (hio_ntoh16(hdr->length) == exptotlen + vsattr->length, "hdr->length not ok after attribute insertion"); + + if (HIO_RAD_ATTR_IS_LONG_EXTENDED(vsattr->type)) + { + exptotlen += HIO_SIZEOF(*lxvsattr); + lxvsattr = vsattr; + T_ASSERT1 (lxvsattr->length == HIO_SIZEOF(*lxvsattr) + data[i].len, "wrong attribute length"); + } + else if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(vsattr->type)) + { + exptotlen += HIO_SIZEOF(*xvsattr); + xvsattr = vsattr; + T_ASSERT1 (xvsattr->length == HIO_SIZEOF(*xvsattr) + data[i].len, "wrong attribute length"); + } + else + { + exptotlen += HIO_SIZEOF(*vsattr); + T_ASSERT1 (vsattr->length == HIO_SIZEOF(*vsattr) + data[i].len, "wrong attribute length"); + } + } + else + { + hio_rad_attr_hdr_t* attr; + hio_rad_xattr_hdr_t* xattr; + hio_rad_lxattr_hdr_t* lxattr; + + attr = hio_rad_insert_attr(hdr, HIO_SIZEOF(buf), data[i].attrcode, data[i].ptr, data[i].len); + T_ASSERT1 (attr != HIO_NULL, "attribute insertion failure"); + T_ASSERT1 (hio_ntoh16(hdr->length) == exptotlen + attr->length, "hdr->length not ok after attribute insertion"); + + if (HIO_RAD_ATTR_IS_LONG_EXTENDED(attr->type)) + { + exptotlen += HIO_SIZEOF(*lxattr); + lxattr = attr; + T_ASSERT1 (lxattr->length == HIO_SIZEOF(*lxattr) + data[i].len, "wrong attribute length"); + } + else if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(attr->type)) + { + exptotlen += HIO_SIZEOF(*xattr); + xattr = attr; + T_ASSERT1 (xattr->length == HIO_SIZEOF(*xattr) + data[i].len, "wrong attribute length"); + } + else + { + exptotlen += HIO_SIZEOF(*attr); + T_ASSERT1 (attr->length == HIO_SIZEOF(*attr) + data[i].len, "wrong attribute length"); + } + } + T_ASSERT1 (hio_comp_bchars((hio_uint8_t*)hdr + hio_ntoh16(hdr->length) - data[i].len, data[i].len, data[i].ptr, data[i].len, 0) == 0, "wrong attribute value"); + exptotlen += data[i].len; + T_ASSERT1 (hio_ntoh16(hdr->length) == exptotlen, "hdr->length not ok after attribute insertion"); + + for (j = 0; j < HIO_COUNTOF(data); j++) + { + if (data[j].vendor) + { + hio_rad_vsattr_hdr_t* vsattr; + + vsattr = hio_rad_find_vsattr(hdr, data[j].vendor, data[j].attrcode, data[j].index); + if (j <= i) + { + void* val_ptr; + int val_len; + + T_ASSERT1 (vsattr != HIO_NULL, "find failure"); + + if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(vsattr->type)) + { + hio_rad_xvsattr_hdr_t* xvsattr = (hio_rad_xvsattr_hdr_t*)vsattr; + T_ASSERT1 (hio_ntoh32(xvsattr->vendor) == data[j].vendor, "wrong vendor code"); + T_ASSERT1 (xvsattr->type == HIO_RAD_ATTR_CODE_HI(data[j].attrcode), "wrong attribute base"); + T_ASSERT1 (xvsattr->length == HIO_SIZEOF(*xvsattr) + data[j].len, "wrong attribute length"); + T_ASSERT1 (xvsattr->xvs.type == HIO_RAD_ATTR_CODE_LO(data[j].attrcode), "wrong vendor-specific attribute type"); + T_ASSERT1 (xvsattr->xvs.length == HIO_SIZEOF(xvsattr->xvs) + data[j].len, "wrong attribute length"); + val_ptr = xvsattr + 1; + val_len = xvsattr->xvs.length - HIO_SIZEOF(xvsattr->xvs); + } + else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(vsattr->type)) + { + hio_rad_lxvsattr_hdr_t* lxvsattr = (hio_rad_lxvsattr_hdr_t*)vsattr; + T_ASSERT1 (hio_ntoh32(lxvsattr->vendor) == data[j].vendor, "wrong vendor code"); + T_ASSERT1 (lxvsattr->type == HIO_RAD_ATTR_CODE_HI(data[j].attrcode), "wrong attribute base"); + T_ASSERT1 (lxvsattr->length == HIO_SIZEOF(*lxvsattr) + data[j].len, "wrong attribute length"); + T_ASSERT1 (lxvsattr->lxvs.type == HIO_RAD_ATTR_CODE_LO(data[j].attrcode), "wrong vendor-specific attribute type"); + T_ASSERT1 (lxvsattr->lxvs.length == HIO_SIZEOF(lxvsattr->lxvs) + data[j].len, "wrong attribute length"); + val_ptr = lxvsattr + 1; + val_len = lxvsattr->lxvs.length - HIO_SIZEOF(lxvsattr->lxvs); + } + else + { + T_ASSERT1 (hio_ntoh32(vsattr->vendor) == data[j].vendor, "wrong vendor code"); + T_ASSERT1 (vsattr->type == HIO_RAD_ATTR_VENDOR_SPECIFIC, "wrong attribute type"); + T_ASSERT1 (vsattr->length == HIO_SIZEOF(*vsattr) + data[j].len, "wrong attribute length"); + T_ASSERT1 (vsattr->vs.type == data[j].attrcode, "wrong vendor-specific attribute type"); + T_ASSERT1 (vsattr->vs.length == HIO_SIZEOF(vsattr->vs) + data[j].len, "wrong attribute length"); + val_ptr = vsattr + 1; + val_len = vsattr->vs.length - HIO_SIZEOF(vsattr->vs); + } + + T_ASSERT1 (hio_comp_bchars(val_ptr, val_len, data[j].ptr, data[j].len, 0) == 0, "wrong attribute value"); + } + else + { + T_ASSERT1 (vsattr == HIO_NULL, "find failure"); + } + } + else + { + hio_rad_attr_hdr_t* attr; + + attr = hio_rad_find_attr(hdr, data[j].attrcode, data[j].index); + if (j <= i) + { + void* val_ptr; + int val_len; + T_ASSERT1 (attr != HIO_NULL, "find failure"); + + if (HIO_RAD_ATTR_IS_SHORT_EXTENDED(attr->type)) + { + hio_rad_xattr_hdr_t* xattr = (hio_rad_xattr_hdr_t*)attr; + T_ASSERT1 (HIO_RAD_ATTR_CODE_HI(data[j].attrcode) == xattr->type, "wrong extended attribute base"); + T_ASSERT1 (HIO_RAD_ATTR_CODE_LO(data[j].attrcode) == xattr->xtype, "wrong extended attribute type"); + T_ASSERT1 (xattr->length == HIO_SIZEOF(*xattr) + data[j].len, "wrong attribute length"); + val_ptr = xattr + 1; + val_len = xattr->length - HIO_SIZEOF(*xattr); + } + else if (HIO_RAD_ATTR_IS_LONG_EXTENDED(attr->type)) + { + hio_rad_lxattr_hdr_t* lxattr = (hio_rad_lxattr_hdr_t*)attr; + T_ASSERT1 (HIO_RAD_ATTR_CODE_HI(data[j].attrcode) == lxattr->type, "wrong long extended attribute base"); + T_ASSERT1 (HIO_RAD_ATTR_CODE_LO(data[j].attrcode) == lxattr->xtype, "wrong long extended attribute type"); + T_ASSERT1 (lxattr->length == HIO_SIZEOF(*lxattr) + data[j].len, "wrong attribute length"); + val_ptr = lxattr + 1; + val_len = lxattr->length - HIO_SIZEOF(*lxattr); + } + else + { + T_ASSERT1 (attr->type == data[j].attrcode, "wrong attribute type"); + T_ASSERT1 (attr->length == HIO_SIZEOF(*attr) + data[j].len, "wrong attribute length"); + val_ptr = attr + 1; + val_len = attr->length - HIO_SIZEOF(*attr); + } + + T_ASSERT1 (hio_comp_bchars(val_ptr, val_len, data[j].ptr, data[j].len, 0) == 0, "wrong attribute value"); + } + else + { + T_ASSERT1 (attr == HIO_NULL, "find failure"); + } + } + } + } + + +#if 1 + { + int s = socket(AF_INET, SOCK_DGRAM, 0); + struct sockaddr_in sin; + memset (&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr("192.168.1.1"); + sin.sin_port = HIO_CONST_HTON16(1812); + sendto (s, hdr, hio_ntoh16(hdr->length), 0, &sin, sizeof(sin)); + } +#endif + } + + return 0; + +oops: + return -1; +}