daaa9fc8444b7320acb8a48d5bdfb0ece6d734cc
2 * Copyright (C) 2010-2012 Felix Fietkau <nbd@openwrt.org>
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.
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.
18 static const int blob_type
[__BLOBMSG_TYPE_LAST
] = {
19 [BLOBMSG_TYPE_INT8
] = BLOB_ATTR_INT8
,
20 [BLOBMSG_TYPE_INT16
] = BLOB_ATTR_INT16
,
21 [BLOBMSG_TYPE_INT32
] = BLOB_ATTR_INT32
,
22 [BLOBMSG_TYPE_INT64
] = BLOB_ATTR_INT64
,
23 [BLOBMSG_TYPE_DOUBLE
] = BLOB_ATTR_DOUBLE
,
24 [BLOBMSG_TYPE_STRING
] = BLOB_ATTR_STRING
,
25 [BLOBMSG_TYPE_UNSPEC
] = BLOB_ATTR_BINARY
,
28 bool blobmsg_check_attr(const struct blob_attr
*attr
, bool name
)
30 return blobmsg_check_attr_len(attr
, name
, blob_raw_len(attr
));
33 static const struct blobmsg_hdr
* blobmsg_hdr_from_blob(const struct blob_attr
*attr
, size_t len
)
35 if (len
< sizeof(struct blob_attr
) + sizeof(struct blobmsg_hdr
))
38 return blob_data(attr
);
41 static bool blobmsg_hdr_valid_namelen(const struct blobmsg_hdr
*hdr
, size_t len
)
43 if (len
< sizeof(struct blob_attr
) + sizeof(struct blobmsg_hdr
) + blobmsg_namelen(hdr
) + 1)
49 static bool blobmsg_check_name(const struct blob_attr
*attr
, size_t len
, bool name
)
51 char *limit
= (char *) attr
+ len
;
52 const struct blobmsg_hdr
*hdr
;
54 hdr
= blobmsg_hdr_from_blob(attr
, len
);
58 if (name
&& !hdr
->namelen
)
61 if (name
&& !blobmsg_hdr_valid_namelen(hdr
, len
))
64 if ((char *) hdr
->name
+ blobmsg_namelen(hdr
) + 1 > limit
)
67 if (blobmsg_namelen(hdr
) > (blob_len(attr
) - sizeof(struct blobmsg_hdr
)))
70 if (hdr
->name
[blobmsg_namelen(hdr
)] != 0)
76 static const char* blobmsg_check_data(const struct blob_attr
*attr
, size_t len
, size_t *data_len
)
78 char *limit
= (char *) attr
+ len
;
81 *data_len
= blobmsg_data_len(attr
);
82 if (*data_len
> blob_raw_len(attr
))
85 data
= blobmsg_data(attr
);
86 if (data
+ *data_len
> limit
)
92 bool blobmsg_check_attr_len(const struct blob_attr
*attr
, bool name
, size_t len
)
98 if (!blobmsg_check_name(attr
, len
, name
))
102 if (id
> BLOBMSG_TYPE_LAST
)
108 data
= blobmsg_check_data(attr
, len
, &data_len
);
112 return blob_check_type(data
, data_len
, blob_type
[id
]);
115 int blobmsg_check_array(const struct blob_attr
*attr
, int type
)
117 return blobmsg_check_array_len(attr
, type
, blob_raw_len(attr
));
120 int blobmsg_check_array_len(const struct blob_attr
*attr
, int type
,
123 struct blob_attr
*cur
;
128 if (type
> BLOBMSG_TYPE_LAST
)
131 if (!blobmsg_check_attr_len(attr
, false, blob_len
))
134 switch (blobmsg_type(attr
)) {
135 case BLOBMSG_TYPE_TABLE
:
138 case BLOBMSG_TYPE_ARRAY
:
145 blobmsg_for_each_attr(cur
, attr
, rem
) {
146 if (type
!= BLOBMSG_TYPE_UNSPEC
&& blobmsg_type(cur
) != type
)
149 if (!blobmsg_check_attr_len(cur
, name
, rem
))
158 bool blobmsg_check_attr_list(const struct blob_attr
*attr
, int type
)
160 return blobmsg_check_array(attr
, type
) >= 0;
163 bool blobmsg_check_attr_list_len(const struct blob_attr
*attr
, int type
, size_t len
)
165 return blobmsg_check_array_len(attr
, type
, len
) >= 0;
168 int blobmsg_parse_array(const struct blobmsg_policy
*policy
, int policy_len
,
169 struct blob_attr
**tb
, void *data
, unsigned int len
)
171 struct blob_attr
*attr
;
174 memset(tb
, 0, policy_len
* sizeof(*tb
));
175 __blob_for_each_attr(attr
, data
, len
) {
176 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
177 blob_id(attr
) != policy
[i
].type
)
180 if (!blobmsg_check_attr_len(attr
, false, len
))
194 int blobmsg_parse(const struct blobmsg_policy
*policy
, int policy_len
,
195 struct blob_attr
**tb
, void *data
, unsigned int len
)
197 const struct blobmsg_hdr
*hdr
;
198 struct blob_attr
*attr
;
202 memset(tb
, 0, policy_len
* sizeof(*tb
));
205 pslen
= alloca(policy_len
);
206 for (i
= 0; i
< policy_len
; i
++) {
210 pslen
[i
] = strlen(policy
[i
].name
);
213 __blob_for_each_attr(attr
, data
, len
) {
214 hdr
= blobmsg_hdr_from_blob(attr
, len
);
218 if (!blobmsg_hdr_valid_namelen(hdr
, len
))
221 for (i
= 0; i
< policy_len
; i
++) {
225 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
226 blob_id(attr
) != policy
[i
].type
)
229 if (blobmsg_namelen(hdr
) != pslen
[i
])
232 if (!blobmsg_check_attr_len(attr
, true, len
))
238 if (strcmp(policy
[i
].name
, (char *) hdr
->name
) != 0)
249 static struct blob_attr
*
250 blobmsg_new(struct blob_buf
*buf
, int type
, const char *name
, int payload_len
, void **data
)
252 struct blob_attr
*attr
;
253 struct blobmsg_hdr
*hdr
;
254 int attrlen
, namelen
;
255 char *pad_start
, *pad_end
;
260 namelen
= strlen(name
);
261 attrlen
= blobmsg_hdrlen(namelen
) + payload_len
;
262 attr
= blob_new(buf
, type
, attrlen
);
266 attr
->id_len
|= be32_to_cpu(BLOB_ATTR_EXTENDED
);
267 hdr
= blob_data(attr
);
268 hdr
->namelen
= cpu_to_be16(namelen
);
270 memcpy(hdr
->name
, name
, namelen
);
271 hdr
->name
[namelen
] = '\0';
273 pad_end
= *data
= blobmsg_data(attr
);
274 pad_start
= (char *) &hdr
->name
[namelen
];
275 if (pad_start
< pad_end
)
276 memset(pad_start
, 0, pad_end
- pad_start
);
282 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
284 return (char *)attr
- (char *) buf
->buf
+ BLOB_COOKIE
;
289 blobmsg_open_nested(struct blob_buf
*buf
, const char *name
, bool array
)
291 struct blob_attr
*head
;
292 int type
= array
? BLOBMSG_TYPE_ARRAY
: BLOBMSG_TYPE_TABLE
;
293 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
299 head
= blobmsg_new(buf
, type
, name
, 0, &data
);
302 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blobmsg_hdrlen(strlen(name
)));
304 return (void *)offset
;
307 __attribute__((format(printf
, 3, 0)))
308 int blobmsg_vprintf(struct blob_buf
*buf
, const char *name
, const char *format
, va_list arg
)
316 len
= vsnprintf(&cbuf
, sizeof(cbuf
), format
, arg2
);
322 sbuf
= blobmsg_alloc_string_buffer(buf
, name
, len
+ 1);
326 ret
= vsnprintf(sbuf
, len
+ 1, format
, arg
);
330 blobmsg_add_string_buffer(buf
);
335 __attribute__((format(printf
, 3, 4)))
336 int blobmsg_printf(struct blob_buf
*buf
, const char *name
, const char *format
, ...)
341 va_start(ap
, format
);
342 ret
= blobmsg_vprintf(buf
, name
, format
, ap
);
349 blobmsg_alloc_string_buffer(struct blob_buf
*buf
, const char *name
, unsigned int maxlen
)
351 struct blob_attr
*attr
;
354 attr
= blobmsg_new(buf
, BLOBMSG_TYPE_STRING
, name
, maxlen
, &data_dest
);
358 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blob_pad_len(attr
));
359 blob_set_raw_len(attr
, blob_raw_len(attr
) - maxlen
);
365 blobmsg_realloc_string_buffer(struct blob_buf
*buf
, unsigned int maxlen
)
367 struct blob_attr
*attr
= blob_next(buf
->head
);
368 int offset
= attr_to_offset(buf
, blob_next(buf
->head
)) + blob_pad_len(attr
) - BLOB_COOKIE
;
369 int required
= maxlen
- (buf
->buflen
- offset
);
374 if (!blob_buf_grow(buf
, required
))
376 attr
= blob_next(buf
->head
);
379 return blobmsg_data(attr
);
383 blobmsg_add_string_buffer(struct blob_buf
*buf
)
385 struct blob_attr
*attr
;
388 attr
= blob_next(buf
->head
);
389 len
= strlen(blobmsg_data(attr
)) + 1;
391 attrlen
= blob_raw_len(attr
) + len
;
392 blob_set_raw_len(attr
, attrlen
);
395 blob_set_raw_len(buf
->head
, blob_raw_len(buf
->head
) + blob_pad_len(attr
));
399 blobmsg_add_field(struct blob_buf
*buf
, int type
, const char *name
,
400 const void *data
, unsigned int len
)
402 struct blob_attr
*attr
;
405 attr
= blobmsg_new(buf
, type
, name
, len
, &data_dest
);
410 memcpy(data_dest
, data
, len
);