1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * TLV and XTLV support 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Copyright (C) 2020, Broadcom. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Unless you and Broadcom execute a separate written software license 7*4882a593Smuzhiyun * agreement governing use of this software, this software is licensed to you 8*4882a593Smuzhiyun * under the terms of the GNU General Public License version 2 (the "GPL"), 9*4882a593Smuzhiyun * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10*4882a593Smuzhiyun * following added to such license: 11*4882a593Smuzhiyun * 12*4882a593Smuzhiyun * As a special exception, the copyright holders of this software give you 13*4882a593Smuzhiyun * permission to link this software with independent modules, and to copy and 14*4882a593Smuzhiyun * distribute the resulting executable under terms of your choice, provided that 15*4882a593Smuzhiyun * you also meet, for each linked independent module, the terms and conditions of 16*4882a593Smuzhiyun * the license of that module. An independent module is a module which is not 17*4882a593Smuzhiyun * derived from this software. The special exception does not apply to any 18*4882a593Smuzhiyun * modifications of the software. 19*4882a593Smuzhiyun * 20*4882a593Smuzhiyun * 21*4882a593Smuzhiyun * <<Broadcom-WL-IPTag/Dual:>> 22*4882a593Smuzhiyun */ 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun #ifndef _bcmtlv_h_ 25*4882a593Smuzhiyun #define _bcmtlv_h_ 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun #include <typedefs.h> 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun #ifdef __cplusplus 30*4882a593Smuzhiyun extern "C" { 31*4882a593Smuzhiyun #endif /* __cplusplus */ 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun /* begin tlvs - used in 802.11 IEs etc. */ 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun /* type(aka id)/length/value buffer triple */ 36*4882a593Smuzhiyun typedef struct bcm_tlv { 37*4882a593Smuzhiyun uint8 id; 38*4882a593Smuzhiyun uint8 len; 39*4882a593Smuzhiyun uint8 data[1]; 40*4882a593Smuzhiyun } bcm_tlv_t; 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun /* size of tlv including data */ 43*4882a593Smuzhiyun #define BCM_TLV_SIZE(_tlv) ((_tlv) ? (OFFSETOF(bcm_tlv_t, data) + (_tlv)->len) : 0u) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun /* get next tlv - no length checks */ 46*4882a593Smuzhiyun #define BCM_TLV_NEXT(_tlv) (bcm_tlv_t *)((uint8 *)(_tlv)+ BCM_TLV_SIZE(_tlv)) 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun /* tlv length is restricted to 1 byte */ 49*4882a593Smuzhiyun #define BCM_TLV_MAX_DATA_SIZE (255) 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun /* tlv header - two bytes */ 52*4882a593Smuzhiyun #define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data)) 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun /* Check that bcm_tlv_t fits into the given buffer len */ 55*4882a593Smuzhiyun #define bcm_valid_tlv(elt, buflen) \ 56*4882a593Smuzhiyun ((elt != NULL) && \ 57*4882a593Smuzhiyun ((buflen) >= (uint)BCM_TLV_HDR_SIZE) && \ 58*4882a593Smuzhiyun ((buflen) >= (uint)(BCM_TLV_HDR_SIZE + (elt)->len))) 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun /* type(aka id)/length/ext/value buffer */ 61*4882a593Smuzhiyun typedef struct bcm_tlv_ext { 62*4882a593Smuzhiyun uint8 id; 63*4882a593Smuzhiyun uint8 len; 64*4882a593Smuzhiyun uint8 ext; 65*4882a593Smuzhiyun uint8 data[1]; 66*4882a593Smuzhiyun } bcm_tlv_ext_t; 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun /* get next tlv_ext - no length checks */ 69*4882a593Smuzhiyun #define BCM_TLV_EXT_NEXT(_tlv_ext) \ 70*4882a593Smuzhiyun (bcm_tlv_ext_t *)((uint8 *)(_tlv_ext)+ BCM_TLV_EXT_SIZE(_tlv_ext)) 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun /* tlv_ext length is restricted to 1 byte */ 73*4882a593Smuzhiyun #define BCM_TLV_EXT_MAX_DATA_SIZE (254u) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun /* tlv_ext header - three bytes */ 76*4882a593Smuzhiyun #define BCM_TLV_EXT_HDR_SIZE (OFFSETOF(bcm_tlv_ext_t, data)) 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun /* size of tlv_ext including data */ 79*4882a593Smuzhiyun #define BCM_TLV_EXT_SIZE(_tlv_ext) (BCM_TLV_EXT_HDR_SIZE + (_tlv_ext)->len) 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun /* find the next tlv */ 82*4882a593Smuzhiyun bcm_tlv_t *bcm_next_tlv(const bcm_tlv_t *elt, uint *buflen); 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun /* move buffer/buflen up to the given tlv, or set to NULL/0 on error */ 85*4882a593Smuzhiyun void bcm_tlv_buffer_advance_to(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen); 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* move buffer/buflen past the given tlv, or set to NULL/0 on error */ 88*4882a593Smuzhiyun void bcm_tlv_buffer_advance_past(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen); 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun /* find the tlv for a given id */ 91*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs(const void *buf, uint buflen, uint key); 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun /* advancement modes for bcm_parse_tlvs_advance() */ 94*4882a593Smuzhiyun typedef enum { 95*4882a593Smuzhiyun BCM_TLV_ADVANCE_NONE = 0, // do not adjust the buffer/buflen 96*4882a593Smuzhiyun BCM_TLV_ADVANCE_TO = 1, // advance to the found tlv 97*4882a593Smuzhiyun BCM_TLV_ADVANCE_PAST = 2 // advance past the found tlv 98*4882a593Smuzhiyun } bcm_tlv_advance_mode_t; 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun /* Find an IE of a specific type from a buffer. 101*4882a593Smuzhiyun * tlvs: buffer to search for IE 102*4882a593Smuzhiyun * tlvs_len: buffer length 103*4882a593Smuzhiyun * tag: IE tag 104*4882a593Smuzhiyun * oui_len: length of the OUI 105*4882a593Smuzhiyun * oui: Specific OUI to match 106*4882a593Smuzhiyun * type: OUI type 107*4882a593Smuzhiyun * Return the matched IE, else return null. 108*4882a593Smuzhiyun */ 109*4882a593Smuzhiyun extern bcm_tlv_t *bcm_find_ie(const uint8 *tlvs, uint tlvs_len, uint8 tag, 110*4882a593Smuzhiyun uint8 oui_len, const char *oui, uint8 type); 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun /* search for a matching tlv id, and adjust the parse buffer pointer/length */ 113*4882a593Smuzhiyun const bcm_tlv_t *bcm_parse_tlvs_advance(const uint8 **buf, uint *buflen, uint key, 114*4882a593Smuzhiyun bcm_tlv_advance_mode_t advance); 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun /* 117*4882a593Smuzhiyun * Traverse tlvs and return pointer to the first tlv that 118*4882a593Smuzhiyun * matches the key. Return NULL if not found or tlv len < min_bodylen 119*4882a593Smuzhiyun */ 120*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs_min_bodylen(const void *buf, uint buflen, uint key, uint min_bodylen); 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun /* 123*4882a593Smuzhiyun * Traverse tlvs and return pointer to the first tlv that 124*4882a593Smuzhiyun * matches the key. Return NULL if not found or tlv size > max_len or < min_len 125*4882a593Smuzhiyun */ 126*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs_minmax_len(const void *buf, uint buflen, uint key, 127*4882a593Smuzhiyun uint min_len, uint max_len); 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun /* parse tlvs for dot11 - same as parse_tlvs but supports 802.11 id extension */ 130*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs_dot11(const void *buf, uint buflen, uint key, bool id_ext); 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun /* same as parse_tlvs, but stops when found id > key */ 133*4882a593Smuzhiyun const bcm_tlv_t *bcm_parse_ordered_tlvs(const void *buf, uint buflen, uint key); 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun /* find a tlv with DOT11_MNG_PROPR_ID as id, and the given oui and type */ 136*4882a593Smuzhiyun bcm_tlv_t *bcm_find_vendor_ie(const void *tlvs, uint tlvs_len, const char *voui, 137*4882a593Smuzhiyun uint8 *type, uint type_len); 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun /* write tlv at dst and return next tlv ptr */ 140*4882a593Smuzhiyun uint8 *bcm_write_tlv(int type, const void *data, uint datalen, uint8 *dst); 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun /* write tlv_ext at dst and return next tlv ptr */ 143*4882a593Smuzhiyun uint8 *bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst); 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun /* write tlv at dst if space permits and return next tlv ptr */ 146*4882a593Smuzhiyun uint8 *bcm_write_tlv_safe(int type, const void *data, uint datalen, uint8 *dst, 147*4882a593Smuzhiyun uint dst_maxlen); 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun /* copy a tlv and return next tlv ptr */ 150*4882a593Smuzhiyun uint8 *bcm_copy_tlv(const void *src, uint8 *dst); 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun /* copy a tlv if space permits and return next tlv ptr */ 153*4882a593Smuzhiyun uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, uint dst_maxlen); 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun /* end tlvs */ 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun /* begin xtlv - used for iovars, nan attributes etc. */ 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun /* bcm type(id), length, value with w/16 bit id/len. The structure below 160*4882a593Smuzhiyun * is nominal, and is used to support variable length id and type. See 161*4882a593Smuzhiyun * xtlv options below. 162*4882a593Smuzhiyun */ 163*4882a593Smuzhiyun typedef struct bcm_xtlv { 164*4882a593Smuzhiyun uint16 id; 165*4882a593Smuzhiyun uint16 len; 166*4882a593Smuzhiyun uint8 data[1]; 167*4882a593Smuzhiyun } bcm_xtlv_t; 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun /* xtlv options */ 170*4882a593Smuzhiyun #define BCM_XTLV_OPTION_NONE 0x0000u 171*4882a593Smuzhiyun #define BCM_XTLV_OPTION_ALIGN32 0x0001u /* 32bit alignment of type.len.data */ 172*4882a593Smuzhiyun #define BCM_XTLV_OPTION_IDU8 0x0002u /* shorter id */ 173*4882a593Smuzhiyun #define BCM_XTLV_OPTION_LENU8 0x0004u /* shorted length */ 174*4882a593Smuzhiyun #define BCM_XTLV_OPTION_IDBE 0x0008u /* big endian format id */ 175*4882a593Smuzhiyun #define BCM_XTLV_OPTION_LENBE 0x0010u /* big endian format length */ 176*4882a593Smuzhiyun typedef uint16 bcm_xtlv_opts_t; 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun /* header size. depends on options. Macros names ending w/ _EX are where 179*4882a593Smuzhiyun * options are explcitly specified that may be less common. The ones 180*4882a593Smuzhiyun * without use default values that correspond to ...OPTION_NONE 181*4882a593Smuzhiyun */ 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun /* xtlv header size depends on options */ 184*4882a593Smuzhiyun #define BCM_XTLV_HDR_SIZE 4u 185*4882a593Smuzhiyun #define BCM_XTLV_HDR_SIZE_EX(_opts) bcm_xtlv_hdr_size(_opts) 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun /* note: xtlv len only stores the value's length without padding */ 188*4882a593Smuzhiyun #define BCM_XTLV_LEN(_elt) ltoh16_ua(&(_elt)->len) 189*4882a593Smuzhiyun #define BCM_XTLV_LEN_EX(_elt, _opts) bcm_xtlv_len(_elt, _opts) 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun #define BCM_XTLV_ID(_elt) ltoh16_ua(&(_elt)->id) 192*4882a593Smuzhiyun #define BCM_XTLV_ID_EX(_elt, _opts) bcm_xtlv_id(_elt, _opts) 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun /* entire size of the XTLV including header, data, and optional padding */ 195*4882a593Smuzhiyun #define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts) 196*4882a593Smuzhiyun #define BCM_XTLV_SIZE_EX(_elt, _opts) bcm_xtlv_size(_elt, _opts) 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun /* max xtlv data size */ 199*4882a593Smuzhiyun #define BCM_XTLV_MAX_DATA_SIZE 65535u 200*4882a593Smuzhiyun #define BCM_XTLV_MAX_DATA_SIZE_EX(_opts) ((_opts & BCM_XTLV_OPTION_LENU8) ? \ 201*4882a593Smuzhiyun 255u : 65535u) 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun /* descriptor of xtlv data, packing(src) and unpacking(dst) support */ 204*4882a593Smuzhiyun typedef struct { 205*4882a593Smuzhiyun uint16 type; 206*4882a593Smuzhiyun uint16 len; 207*4882a593Smuzhiyun void *ptr; /* ptr to memory location */ 208*4882a593Smuzhiyun } xtlv_desc_t; 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun /* xtlv buffer - packing/unpacking support */ 211*4882a593Smuzhiyun struct bcm_xtlvbuf { 212*4882a593Smuzhiyun bcm_xtlv_opts_t opts; 213*4882a593Smuzhiyun uint16 size; 214*4882a593Smuzhiyun uint8 *head; /* point to head of buffer */ 215*4882a593Smuzhiyun uint8 *buf; /* current position of buffer */ 216*4882a593Smuzhiyun /* allocated buffer may follow, but not necessarily */ 217*4882a593Smuzhiyun }; 218*4882a593Smuzhiyun typedef struct bcm_xtlvbuf bcm_xtlvbuf_t; 219*4882a593Smuzhiyun 220*4882a593Smuzhiyun /* valid xtlv ? */ 221*4882a593Smuzhiyun bool bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts); 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun /* return the next xtlv element, and update buffer len (remaining). Buffer length 224*4882a593Smuzhiyun * updated includes padding as specified by options 225*4882a593Smuzhiyun */ 226*4882a593Smuzhiyun bcm_xtlv_t *bcm_next_xtlv(const bcm_xtlv_t *elt, int *buf_len, bcm_xtlv_opts_t opts); 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun /* initialize an xtlv buffer. Use options specified for packing/unpacking using 229*4882a593Smuzhiyun * the buffer. Caller is responsible for allocating both buffers. 230*4882a593Smuzhiyun */ 231*4882a593Smuzhiyun int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len, 232*4882a593Smuzhiyun bcm_xtlv_opts_t opts); 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun /* length of data in the xtlv buffer */ 235*4882a593Smuzhiyun uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf); 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun /* remaining space in the xtlv buffer */ 238*4882a593Smuzhiyun uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf); 239*4882a593Smuzhiyun 240*4882a593Smuzhiyun /* write ptr */ 241*4882a593Smuzhiyun uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf); 242*4882a593Smuzhiyun 243*4882a593Smuzhiyun /* head */ 244*4882a593Smuzhiyun uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf); 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun /* put a data buffer into xtlv */ 247*4882a593Smuzhiyun int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n); 248*4882a593Smuzhiyun 249*4882a593Smuzhiyun /* put one or more u16 elts into xtlv */ 250*4882a593Smuzhiyun int bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n); 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun /* put one or more u32 elts into xtlv */ 253*4882a593Smuzhiyun int bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n); 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun /* put one or more u64 elts into xtlv */ 256*4882a593Smuzhiyun int bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n); 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun /* note: there are no get equivalent of integer unpacking, becasuse bcmendian.h 259*4882a593Smuzhiyun * can be used directly using pointers returned in the buffer being processed. 260*4882a593Smuzhiyun */ 261*4882a593Smuzhiyun 262*4882a593Smuzhiyun /* unpack a single xtlv entry, advances buffer and copies data to dst_data on match 263*4882a593Smuzhiyun * type and length match must be exact 264*4882a593Smuzhiyun */ 265*4882a593Smuzhiyun int bcm_unpack_xtlv_entry(const uint8 **buf, uint16 expected_type, uint16 expected_len, 266*4882a593Smuzhiyun uint8 *dst_data, bcm_xtlv_opts_t opts); 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun /* packs an xtlv into buffer, and advances buffer, decreements buffer length. 269*4882a593Smuzhiyun * buffer length is checked and must be >= size of xtlv - otherwise BCME_BADLEN 270*4882a593Smuzhiyun */ 271*4882a593Smuzhiyun int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len, 272*4882a593Smuzhiyun const uint8 *src_data, bcm_xtlv_opts_t opts); 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun /* accessors and lengths for element given options */ 275*4882a593Smuzhiyun int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); 276*4882a593Smuzhiyun int bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts); 277*4882a593Smuzhiyun int bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); 278*4882a593Smuzhiyun int bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); 279*4882a593Smuzhiyun int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts); 280*4882a593Smuzhiyun 281*4882a593Smuzhiyun /* compute size needed for number of tlvs whose total data len is given */ 282*4882a593Smuzhiyun #define BCM_XTLV_SIZE_FOR_TLVS(_data_len, _num_tlvs, _opts) (\ 283*4882a593Smuzhiyun bcm_xtlv_size_for_data(_data_len, _opts) + (\ 284*4882a593Smuzhiyun (_num_tlvs) * BCM_XTLV_HDR_SIZE_EX(_opts))) 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun /* unsafe copy xtlv */ 287*4882a593Smuzhiyun #define BCM_XTLV_BCOPY(_src, _dst, _opts) \ 288*4882a593Smuzhiyun bcm_xtlv_bcopy(_src, _dst, BCM_XTLV_MAX_DATA_SIZE_EX(_opts), \ 289*4882a593Smuzhiyun BCM_XTLV_MAX_DATA_SIZE_EX(_opts), _opts) 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun /* copy xtlv - note: src->dst bcopy order - to be compatible w/ tlv version */ 292*4882a593Smuzhiyun bcm_xtlv_t* bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst, 293*4882a593Smuzhiyun int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts); 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun /* callback for unpacking xtlv from a buffer into context. */ 296*4882a593Smuzhiyun typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, const uint8 *buf, 297*4882a593Smuzhiyun uint16 type, uint16 len); 298*4882a593Smuzhiyun 299*4882a593Smuzhiyun /* unpack a tlv buffer using buffer, options, and callback */ 300*4882a593Smuzhiyun int bcm_unpack_xtlv_buf(void *ctx, const uint8 *buf, uint16 buflen, 301*4882a593Smuzhiyun bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn); 302*4882a593Smuzhiyun 303*4882a593Smuzhiyun /* unpack a set of tlvs from the buffer using provided xtlv descriptors */ 304*4882a593Smuzhiyun int bcm_unpack_xtlv_buf_to_mem(const uint8 *buf, int *buflen, xtlv_desc_t *items, 305*4882a593Smuzhiyun bcm_xtlv_opts_t opts); 306*4882a593Smuzhiyun 307*4882a593Smuzhiyun /* pack a set of tlvs into buffer using provided xtlv descriptors */ 308*4882a593Smuzhiyun int bcm_pack_xtlv_buf_from_mem(uint8 **buf, uint16 *buflen, 309*4882a593Smuzhiyun const xtlv_desc_t *items, bcm_xtlv_opts_t opts); 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun /* return data pointer and data length of a given id from xtlv buffer 312*4882a593Smuzhiyun * data_len may be NULL 313*4882a593Smuzhiyun */ 314*4882a593Smuzhiyun const uint8* bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen, 315*4882a593Smuzhiyun uint16 id, uint16 *datalen, bcm_xtlv_opts_t opts); 316*4882a593Smuzhiyun 317*4882a593Smuzhiyun /* callback to return next tlv id and len to pack, if there is more tlvs to come and 318*4882a593Smuzhiyun * options e.g. alignment 319*4882a593Smuzhiyun */ 320*4882a593Smuzhiyun typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len); 321*4882a593Smuzhiyun 322*4882a593Smuzhiyun /* callback to pack the tlv into length validated buffer */ 323*4882a593Smuzhiyun typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx, 324*4882a593Smuzhiyun uint16 tlv_id, uint16 tlv_len, uint8* buf); 325*4882a593Smuzhiyun 326*4882a593Smuzhiyun /* pack a set of tlvs into buffer using get_next to interate */ 327*4882a593Smuzhiyun int bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, 328*4882a593Smuzhiyun bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next, 329*4882a593Smuzhiyun bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen); 330*4882a593Smuzhiyun 331*4882a593Smuzhiyun /* pack an xtlv. does not do any error checking. if data is not NULL 332*4882a593Smuzhiyun * data of given length is copied to buffer (xtlv) 333*4882a593Smuzhiyun */ 334*4882a593Smuzhiyun void bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len, 335*4882a593Smuzhiyun const uint8 *data, bcm_xtlv_opts_t opts); 336*4882a593Smuzhiyun 337*4882a593Smuzhiyun /* unpack an xtlv and return ptr to data, and data length */ 338*4882a593Smuzhiyun void bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len, 339*4882a593Smuzhiyun const uint8 **data, bcm_xtlv_opts_t opts); 340*4882a593Smuzhiyun 341*4882a593Smuzhiyun /* end xtlvs */ 342*4882a593Smuzhiyun 343*4882a593Smuzhiyun /* length value pairs */ 344*4882a593Smuzhiyun struct bcm_xlv { 345*4882a593Smuzhiyun uint16 len; 346*4882a593Smuzhiyun uint8 data[1]; 347*4882a593Smuzhiyun }; 348*4882a593Smuzhiyun typedef struct bcm_xlv bcm_xlv_t; 349*4882a593Smuzhiyun 350*4882a593Smuzhiyun struct bcm_xlvp { 351*4882a593Smuzhiyun uint16 len; 352*4882a593Smuzhiyun uint8 *data; 353*4882a593Smuzhiyun }; 354*4882a593Smuzhiyun typedef struct bcm_xlvp bcm_xlvp_t; 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun struct bcm_const_xlvp { 357*4882a593Smuzhiyun uint16 len; 358*4882a593Smuzhiyun const uint8 *data; 359*4882a593Smuzhiyun }; 360*4882a593Smuzhiyun 361*4882a593Smuzhiyun typedef struct bcm_const_xlvp bcm_const_xlvp_t; 362*4882a593Smuzhiyun 363*4882a593Smuzhiyun struct bcm_const_ulvp { 364*4882a593Smuzhiyun uint32 len; 365*4882a593Smuzhiyun const uint8 *data; 366*4882a593Smuzhiyun }; 367*4882a593Smuzhiyun 368*4882a593Smuzhiyun typedef struct bcm_const_ulvp bcm_const_ulvp_t; 369*4882a593Smuzhiyun 370*4882a593Smuzhiyun /* end length value pairs */ 371*4882a593Smuzhiyun #ifdef __cplusplus 372*4882a593Smuzhiyun } 373*4882a593Smuzhiyun #endif /* __cplusplus */ 374*4882a593Smuzhiyun 375*4882a593Smuzhiyun #endif /* _bcmtlv_h_ */ 376