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