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