libubox
C utility functions for OpenWrt.
blobmsg.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2012 Felix Fietkau <nbd@openwrt.org>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #ifndef __BLOBMSG_H
17 #define __BLOBMSG_H
18 
19 #include <stdarg.h>
20 #include "blob.h"
21 
22 #define BLOBMSG_ALIGN 2
23 #define BLOBMSG_PADDING(len) (((len) + (1 << BLOBMSG_ALIGN) - 1) & ~((1 << BLOBMSG_ALIGN) - 1))
24 
39 };
40 
41 struct blobmsg_hdr {
42  uint16_t namelen;
43  uint8_t name[];
44 } __packed;
45 
47  const char *name;
48  enum blobmsg_type type;
49 };
50 
51 static inline int blobmsg_hdrlen(unsigned int namelen)
52 {
53  return BLOBMSG_PADDING(sizeof(struct blobmsg_hdr) + namelen + 1);
54 }
55 
56 static inline void blobmsg_clear_name(struct blob_attr *attr)
57 {
58  struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr);
59  hdr->name[0] = 0;
60 }
61 
62 static inline const char *blobmsg_name(const struct blob_attr *attr)
63 {
64  struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr);
65  return (const char *)(hdr + 1);
66 }
67 
68 static inline int blobmsg_type(const struct blob_attr *attr)
69 {
70  return blob_id(attr);
71 }
72 
73 static uint16_t blobmsg_namelen(const struct blobmsg_hdr *hdr)
74 {
75  return be16_to_cpu(hdr->namelen);
76 }
77 
78 static inline void *blobmsg_data(const struct blob_attr *attr)
79 {
80  struct blobmsg_hdr *hdr;
81  char *data;
82 
83  if (!attr)
84  return NULL;
85 
86  hdr = (struct blobmsg_hdr *) blob_data(attr);
87  data = (char *) blob_data(attr);
88 
89  if (blob_is_extended(attr))
91 
92  return data;
93 }
94 
95 static inline size_t blobmsg_data_len(const struct blob_attr *attr)
96 {
97  uint8_t *start, *end;
98 
99  if (!attr)
100  return 0;
101 
102  start = (uint8_t *) blob_data(attr);
103  end = (uint8_t *) blobmsg_data(attr);
104 
105  return blob_len(attr) - (end - start);
106 }
107 
108 static inline size_t blobmsg_len(const struct blob_attr *attr)
109 {
110  return blobmsg_data_len(attr);
111 }
112 
113 /*
114  * blobmsg_check_attr: validate a list of attributes
115  *
116  * This method may be used with trusted data only. Providing
117  * malformed blobs will cause out of bounds memory access.
118  */
119 bool blobmsg_check_attr(const struct blob_attr *attr, bool name);
120 
121 /*
122  * blobmsg_check_attr_len: validate a list of attributes
123  *
124  * This method should be safer implementation of blobmsg_check_attr.
125  * It will limit all memory access performed on the blob to the
126  * range [attr, attr + len] (upper bound non inclusive) and is
127  * thus suited for checking of untrusted blob attributes.
128  */
129 bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len);
130 
131 /*
132  * blobmsg_check_attr_list: validate a list of attributes
133  *
134  * This method may be used with trusted data only. Providing
135  * malformed blobs will cause out of bounds memory access.
136  */
137 bool blobmsg_check_attr_list(const struct blob_attr *attr, int type);
138 
139 /*
140  * blobmsg_check_attr_list_len: validate a list of untrusted attributes
141  *
142  * This method should be safer implementation of blobmsg_check_attr_list.
143  * It will limit all memory access performed on the blob to the
144  * range [attr, attr + len] (upper bound non inclusive) and is
145  * thus suited for checking of untrusted blob attributes.
146  */
147 bool blobmsg_check_attr_list_len(const struct blob_attr *attr, int type, size_t len);
148 
149 /*
150  * blobmsg_check_array: validate array/table and return size
151  *
152  * Checks if all elements of an array or table are valid and have
153  * the specified type. Returns the number of elements in the array
154  *
155  * This method may be used with trusted data only. Providing
156  * malformed blobs will cause out of bounds memory access.
157  */
158 int blobmsg_check_array(const struct blob_attr *attr, int type);
159 
160 /*
161  * blobmsg_check_array_len: validate untrusted array/table and return size
162  *
163  * Checks if all elements of an array or table are valid and have
164  * the specified type. Returns the number of elements in the array.
165  *
166  * This method should be safer implementation of blobmsg_check_array.
167  * It will limit all memory access performed on the blob to the
168  * range [attr, attr + len] (upper bound non inclusive) and is
169  * thus suited for checking of untrusted blob attributes.
170  */
171 int blobmsg_check_array_len(const struct blob_attr *attr, int type, size_t len);
172 
173 int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len,
174  struct blob_attr **tb, void *data, unsigned int len);
175 int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len,
176  struct blob_attr **tb, void *data, unsigned int len);
177 
178 int blobmsg_add_field(struct blob_buf *buf, int type, const char *name,
179  const void *data, unsigned int len);
180 
181 static inline int
182 blobmsg_parse_attr(const struct blobmsg_policy *policy, int policy_len,
183  struct blob_attr **tb, struct blob_attr *data)
184 {
185  return blobmsg_parse(policy, policy_len, tb, blobmsg_data(data), blobmsg_len(data));
186 }
187 
188 static inline int
189 blobmsg_parse_array_attr(const struct blobmsg_policy *policy, int policy_len,
190  struct blob_attr **tb, struct blob_attr *data)
191 {
192  return blobmsg_parse_array(policy, policy_len, tb, blobmsg_data(data), blobmsg_len(data));
193 }
194 
195 static inline int
196 blobmsg_add_double(struct blob_buf *buf, const char *name, double val)
197 {
198  union {
199  double d;
200  uint64_t u64;
201  } v;
202  v.d = val;
203  v.u64 = cpu_to_be64(v.u64);
204  return blobmsg_add_field(buf, BLOBMSG_TYPE_DOUBLE, name, &v.u64, 8);
205 }
206 
207 static inline int
208 blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val)
209 {
210  return blobmsg_add_field(buf, BLOBMSG_TYPE_INT8, name, &val, 1);
211 }
212 
213 static inline int
214 blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val)
215 {
216  val = cpu_to_be16(val);
217  return blobmsg_add_field(buf, BLOBMSG_TYPE_INT16, name, &val, 2);
218 }
219 
220 static inline int
221 blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val)
222 {
223  val = cpu_to_be32(val);
224  return blobmsg_add_field(buf, BLOBMSG_TYPE_INT32, name, &val, 4);
225 }
226 
227 static inline int
228 blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)
229 {
230  val = cpu_to_be64(val);
231  return blobmsg_add_field(buf, BLOBMSG_TYPE_INT64, name, &val, 8);
232 }
233 
234 static inline int
235 blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)
236 {
237  return blobmsg_add_field(buf, BLOBMSG_TYPE_STRING, name, string, strlen(string) + 1);
238 }
239 
240 static inline int
241 blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr)
242 {
243  return blobmsg_add_field(buf, blobmsg_type(attr), blobmsg_name(attr),
244  blobmsg_data(attr), blobmsg_data_len(attr));
245 }
246 
247 void *blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array);
248 
249 static inline void *
250 blobmsg_open_array(struct blob_buf *buf, const char *name)
251 {
252  return blobmsg_open_nested(buf, name, true);
253 }
254 
255 static inline void *
256 blobmsg_open_table(struct blob_buf *buf, const char *name)
257 {
258  return blobmsg_open_nested(buf, name, false);
259 }
260 
261 static inline void
262 blobmsg_close_array(struct blob_buf *buf, void *cookie)
263 {
264  blob_nest_end(buf, cookie);
265 }
266 
267 static inline void
268 blobmsg_close_table(struct blob_buf *buf, void *cookie)
269 {
270  blob_nest_end(buf, cookie);
271 }
272 
273 static inline int blobmsg_buf_init(struct blob_buf *buf)
274 {
275  return blob_buf_init(buf, BLOBMSG_TYPE_TABLE);
276 }
277 
278 static inline uint8_t blobmsg_get_u8(struct blob_attr *attr)
279 {
280  return *(uint8_t *) blobmsg_data(attr);
281 }
282 
283 static inline bool blobmsg_get_bool(struct blob_attr *attr)
284 {
285  return *(uint8_t *) blobmsg_data(attr);
286 }
287 
288 static inline uint16_t blobmsg_get_u16(struct blob_attr *attr)
289 {
290  return be16_to_cpu(*(uint16_t *) blobmsg_data(attr));
291 }
292 
293 static inline uint32_t blobmsg_get_u32(struct blob_attr *attr)
294 {
295  return be32_to_cpu(*(uint32_t *) blobmsg_data(attr));
296 }
297 
298 static inline uint64_t blobmsg_get_u64(struct blob_attr *attr)
299 {
300  uint32_t *ptr = (uint32_t *) blobmsg_data(attr);
301  uint64_t tmp = ((uint64_t) be32_to_cpu(ptr[0])) << 32;
302  tmp |= be32_to_cpu(ptr[1]);
303  return tmp;
304 }
305 
306 static inline uint64_t blobmsg_cast_u64(struct blob_attr *attr)
307 {
308  uint64_t tmp = 0;
309 
310  if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
311  tmp = blobmsg_get_u64(attr);
312  else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
313  tmp = blobmsg_get_u32(attr);
314  else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
315  tmp = blobmsg_get_u16(attr);
316  else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
317  tmp = blobmsg_get_u8(attr);
318 
319  return tmp;
320 }
321 
322 static inline int64_t blobmsg_cast_s64(struct blob_attr *attr)
323 {
324  int64_t tmp = 0;
325 
326  if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
327  tmp = blobmsg_get_u64(attr);
328  else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
329  tmp = (int32_t)blobmsg_get_u32(attr);
330  else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
331  tmp = (int16_t)blobmsg_get_u16(attr);
332  else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
333  tmp = (int8_t)blobmsg_get_u8(attr);
334 
335  return tmp;
336 }
337 
338 static inline double blobmsg_get_double(struct blob_attr *attr)
339 {
340  union {
341  double d;
342  uint64_t u64;
343  } v;
344  v.u64 = blobmsg_get_u64(attr);
345  return v.d;
346 }
347 
348 static inline char *blobmsg_get_string(struct blob_attr *attr)
349 {
350  if (!attr)
351  return NULL;
352 
353  return (char *) blobmsg_data(attr);
354 }
355 
356 void *blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen);
357 void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen);
358 void blobmsg_add_string_buffer(struct blob_buf *buf);
359 
360 int blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg);
361 int blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...)
362  __attribute__((format(printf, 3, 4)));
363 
364 #define blobmsg_for_each_attr(pos, attr, rem) \
365  for (rem = attr ? blobmsg_data_len(attr) : 0, \
366  pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
367  rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
368  (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
369  rem -= blob_pad_len(pos), pos = blob_next(pos))
370 
371 #define __blobmsg_for_each_attr(pos, attr, rem) \
372  for (pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
373  rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
374  (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
375  rem -= blob_pad_len(pos), pos = blob_next(pos))
376 
377 #endif
void blob_nest_end(struct blob_buf *buf, void *cookie)
Definition: blob.c:185
int blob_buf_init(struct blob_buf *buf, int id)
Definition: blob.c:91
static bool blob_is_extended(const struct blob_attr *attr)
Definition: blob.h:91
char data[]
Definition: blob.h:1
static size_t blob_len(const struct blob_attr *attr)
Definition: blob.h:100
static void * blob_data(const struct blob_attr *attr)
Definition: blob.h:75
static unsigned int blob_id(const struct blob_attr *attr)
Definition: blob.h:84
bool blobmsg_check_attr_list(const struct blob_attr *attr, int type)
Definition: blobmsg.c:130
static size_t blobmsg_data_len(const struct blob_attr *attr)
Definition: blobmsg.h:95
static void * blobmsg_open_table(struct blob_buf *buf, const char *name)
Definition: blobmsg.h:256
static int blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr)
Definition: blobmsg.h:241
static size_t blobmsg_len(const struct blob_attr *attr)
Definition: blobmsg.h:108
static void blobmsg_close_table(struct blob_buf *buf, void *cookie)
Definition: blobmsg.h:268
int blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg)
static int blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val)
Definition: blobmsg.h:208
static uint16_t blobmsg_get_u16(struct blob_attr *attr)
Definition: blobmsg.h:288
static const char * blobmsg_name(const struct blob_attr *attr)
Definition: blobmsg.h:62
static int blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)
Definition: blobmsg.h:228
static char * blobmsg_get_string(struct blob_attr *attr)
Definition: blobmsg.h:348
static int blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)
Definition: blobmsg.h:235
static void blobmsg_close_array(struct blob_buf *buf, void *cookie)
Definition: blobmsg.h:262
int blobmsg_printf(struct blob_buf *buf, const char *name, const char *format,...) __attribute__((format(printf
bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len)
Definition: blobmsg.c:58
int blobmsg_add_field(struct blob_buf *buf, int type, const char *name, const void *data, unsigned int len)
Definition: blobmsg.c:377
int blobmsg_check_array_len(const struct blob_attr *attr, int type, size_t len)
Definition: blobmsg.c:92
static int blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val)
Definition: blobmsg.h:214
void * blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array)
Definition: blobmsg.c:266
static uint16_t blobmsg_namelen(const struct blobmsg_hdr *hdr)
Definition: blobmsg.h:73
static int blobmsg_buf_init(struct blob_buf *buf)
Definition: blobmsg.h:273
bool blobmsg_check_attr_list_len(const struct blob_attr *attr, int type, size_t len)
Definition: blobmsg.c:135
void * blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen)
Definition: blobmsg.c:326
static uint32_t blobmsg_get_u32(struct blob_attr *attr)
Definition: blobmsg.h:293
uint8_t name[]
Definition: blobmsg.h:1
static int blobmsg_parse_array_attr(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, struct blob_attr *data)
Definition: blobmsg.h:189
static void blobmsg_clear_name(struct blob_attr *attr)
Definition: blobmsg.h:56
static uint64_t blobmsg_cast_u64(struct blob_attr *attr)
Definition: blobmsg.h:306
static int blobmsg_parse_attr(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, struct blob_attr *data)
Definition: blobmsg.h:182
int blobmsg_check_array(const struct blob_attr *attr, int type)
Definition: blobmsg.c:87
void blobmsg_add_string_buffer(struct blob_buf *buf)
Definition: blobmsg.c:361
bool blobmsg_check_attr(const struct blob_attr *attr, bool name)
Definition: blobmsg.c:28
blobmsg_type
Definition: blobmsg.h:25
@ BLOBMSG_TYPE_LAST
Definition: blobmsg.h:37
@ BLOBMSG_TYPE_TABLE
Definition: blobmsg.h:28
@ __BLOBMSG_TYPE_LAST
Definition: blobmsg.h:36
@ BLOBMSG_TYPE_STRING
Definition: blobmsg.h:29
@ BLOBMSG_TYPE_BOOL
Definition: blobmsg.h:34
@ BLOBMSG_TYPE_INT16
Definition: blobmsg.h:32
@ BLOBMSG_TYPE_ARRAY
Definition: blobmsg.h:27
@ BLOBMSG_TYPE_UNSPEC
Definition: blobmsg.h:26
@ BLOBMSG_TYPE_INT8
Definition: blobmsg.h:33
@ BLOBMSG_TYPE_INT32
Definition: blobmsg.h:31
@ BLOBMSG_TYPE_INT64
Definition: blobmsg.h:30
@ BLOBMSG_TYPE_DOUBLE
Definition: blobmsg.h:35
@ BLOBMSG_CAST_INT64
Definition: blobmsg.h:38
static void * blobmsg_open_array(struct blob_buf *buf, const char *name)
Definition: blobmsg.h:250
static uint64_t blobmsg_get_u64(struct blob_attr *attr)
Definition: blobmsg.h:298
#define BLOBMSG_PADDING(len)
Definition: blobmsg.h:23
static double blobmsg_get_double(struct blob_attr *attr)
Definition: blobmsg.h:338
static int blobmsg_hdrlen(unsigned int namelen)
Definition: blobmsg.h:51
uint16_t namelen
Definition: blobmsg.h:0
static void * blobmsg_data(const struct blob_attr *attr)
Definition: blobmsg.h:78
static int blobmsg_add_double(struct blob_buf *buf, const char *name, double val)
Definition: blobmsg.h:196
static bool blobmsg_get_bool(struct blob_attr *attr)
Definition: blobmsg.h:283
int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len)
Definition: blobmsg.c:140
struct blobmsg_policy __attribute__
static uint8_t blobmsg_get_u8(struct blob_attr *attr)
Definition: blobmsg.h:278
static int64_t blobmsg_cast_s64(struct blob_attr *attr)
Definition: blobmsg.h:322
int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len)
Definition: blobmsg.c:166
static int blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val)
Definition: blobmsg.h:221
void * blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen)
Definition: blobmsg.c:343
Definition: blob.h:52
Definition: blob.h:64
uint16_t namelen
Definition: blobmsg.h:42
uint8_t name[]
Definition: blobmsg.h:43
const char * name
Definition: blobmsg.h:47
enum blobmsg_type type
Definition: blobmsg.h:48
uint8_t type
Definition: udebug-proto.h:0
#define __packed
Definition: utils.h:215
#define be16_to_cpu(x)
Definition: utils.h:168
#define cpu_to_be64(x)
Definition: utils.h:162
#define be32_to_cpu(x)
Definition: utils.h:167
#define cpu_to_be16(x)
Definition: utils.h:164
#define cpu_to_be32(x)
Definition: utils.h:163