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_STRING
] = BLOB_ATTR_STRING
,
24 [BLOBMSG_TYPE_UNSPEC
] = BLOB_ATTR_BINARY
,
28 blobmsg_namelen(const struct blobmsg_hdr
*hdr
)
30 return be16_to_cpu(hdr
->namelen
);
33 bool blobmsg_check_attr(const struct blob_attr
*attr
, bool name
)
35 const struct blobmsg_hdr
*hdr
;
39 if (blob_len(attr
) < sizeof(struct blobmsg_hdr
))
42 hdr
= (void *) attr
->data
;
43 if (!hdr
->namelen
&& name
)
46 if (blobmsg_namelen(hdr
) > blob_len(attr
) - sizeof(struct blobmsg_hdr
))
49 if (hdr
->name
[blobmsg_namelen(hdr
)] != 0)
53 len
= blobmsg_data_len(attr
);
54 data
= blobmsg_data(attr
);
56 if (id
> BLOBMSG_TYPE_LAST
)
62 return blob_check_type(data
, len
, blob_type
[id
]);
65 bool blobmsg_check_attr_list(const struct blob_attr
*attr
, int type
)
67 struct blob_attr
*cur
;
71 switch (blobmsg_type(attr
)) {
72 case BLOBMSG_TYPE_TABLE
:
75 case BLOBMSG_TYPE_ARRAY
:
82 blobmsg_for_each_attr(cur
, attr
, rem
) {
83 if (blobmsg_type(cur
) != type
)
86 if (!blobmsg_check_attr(cur
, name
))
93 int blobmsg_parse_array(const struct blobmsg_policy
*policy
, int policy_len
,
94 struct blob_attr
**tb
, void *data
, int len
)
96 struct blob_attr
*attr
;
99 memset(tb
, 0, policy_len
* sizeof(*tb
));
100 __blob_for_each_attr(attr
, data
, len
) {
101 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
102 blob_id(attr
) != policy
[i
].type
)
105 if (!blobmsg_check_attr(attr
, false))
120 int blobmsg_parse(const struct blobmsg_policy
*policy
, int policy_len
,
121 struct blob_attr
**tb
, void *data
, int len
)
123 struct blobmsg_hdr
*hdr
;
124 struct blob_attr
*attr
;
128 memset(tb
, 0, policy_len
* sizeof(*tb
));
129 pslen
= alloca(policy_len
);
130 for (i
= 0; i
< policy_len
; i
++) {
134 pslen
[i
] = strlen(policy
[i
].name
);
137 __blob_for_each_attr(attr
, data
, len
) {
138 hdr
= blob_data(attr
);
139 for (i
= 0; i
< policy_len
; i
++) {
143 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
144 blob_id(attr
) != policy
[i
].type
)
147 if (blobmsg_namelen(hdr
) != pslen
[i
])
150 if (!blobmsg_check_attr(attr
, true))
156 if (strcmp(policy
[i
].name
, (char *) hdr
->name
) != 0)
167 static struct blob_attr
*
168 blobmsg_new(struct blob_buf
*buf
, int type
, const char *name
, int payload_len
, void **data
)
170 struct blob_attr
*attr
;
171 struct blobmsg_hdr
*hdr
;
172 int attrlen
, namelen
;
173 char *pad_start
, *pad_end
;
178 namelen
= strlen(name
);
179 attrlen
= blobmsg_hdrlen(namelen
) + payload_len
;
180 attr
= blob_new(buf
, type
, attrlen
);
184 hdr
= blob_data(attr
);
185 hdr
->namelen
= cpu_to_be16(namelen
);
186 strcpy((char *) hdr
->name
, (const char *)name
);
187 pad_end
= *data
= blobmsg_data(attr
);
188 pad_start
= (char *) &hdr
->name
[namelen
];
189 if (pad_start
< pad_end
)
190 memset(pad_start
, 0, pad_end
- pad_start
);
196 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
198 return (char *)attr
- (char *) buf
->buf
;
203 blobmsg_open_nested(struct blob_buf
*buf
, const char *name
, bool array
)
205 struct blob_attr
*head
= buf
->head
;
206 int type
= array
? BLOBMSG_TYPE_ARRAY
: BLOBMSG_TYPE_TABLE
;
207 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
213 head
= blobmsg_new(buf
, type
, name
, 0, &data
);
214 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blobmsg_hdrlen(strlen(name
)));
216 return (void *)offset
;
220 blobmsg_alloc_string_buffer(struct blob_buf
*buf
, const char *name
, int maxlen
)
222 struct blob_attr
*attr
;
225 attr
= blobmsg_new(buf
, BLOBMSG_TYPE_STRING
, name
, maxlen
, &data_dest
);
229 data_dest
= blobmsg_data(attr
);
230 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blob_pad_len(attr
));
231 blob_set_raw_len(attr
, blob_raw_len(attr
) - maxlen
);
237 blobmsg_add_string_buffer(struct blob_buf
*buf
)
239 struct blob_attr
*attr
;
242 attr
= blob_next(buf
->head
);
243 len
= strlen(blobmsg_data(attr
)) + 1;
245 attrlen
= blob_raw_len(attr
) + len
;
246 blob_set_raw_len(attr
, attrlen
);
249 blob_set_raw_len(buf
->head
, blob_raw_len(buf
->head
) + blob_pad_len(attr
));
253 blobmsg_add_field(struct blob_buf
*buf
, int type
, const char *name
,
254 const void *data
, int len
)
256 struct blob_attr
*attr
;
259 attr
= blobmsg_new(buf
, type
, name
, len
, &data_dest
);
264 memcpy(data_dest
, data
, len
);