blobmsg.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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. #include <stdarg.h>
  19. #include "blob.h"
  20. #define BLOBMSG_ALIGN 2
  21. #define BLOBMSG_PADDING(len) (((len) + (1 << BLOBMSG_ALIGN) - 1) & ~((1 << BLOBMSG_ALIGN) - 1))
  22. enum blobmsg_type {
  23. BLOBMSG_TYPE_UNSPEC,
  24. BLOBMSG_TYPE_ARRAY,
  25. BLOBMSG_TYPE_TABLE,
  26. BLOBMSG_TYPE_STRING,
  27. BLOBMSG_TYPE_INT64,
  28. BLOBMSG_TYPE_INT32,
  29. BLOBMSG_TYPE_INT16,
  30. BLOBMSG_TYPE_INT8,
  31. BLOBMSG_TYPE_BOOL = BLOBMSG_TYPE_INT8,
  32. BLOBMSG_TYPE_DOUBLE,
  33. __BLOBMSG_TYPE_LAST,
  34. BLOBMSG_TYPE_LAST = __BLOBMSG_TYPE_LAST - 1,
  35. BLOBMSG_CAST_INT64 = __BLOBMSG_TYPE_LAST,
  36. };
  37. struct blobmsg_hdr {
  38. uint16_t namelen;
  39. uint8_t name[];
  40. } __packed;
  41. struct blobmsg_policy {
  42. const char *name;
  43. enum blobmsg_type type;
  44. };
  45. static inline int blobmsg_hdrlen(unsigned int namelen)
  46. {
  47. return BLOBMSG_PADDING(sizeof(struct blobmsg_hdr) + namelen + 1);
  48. }
  49. static inline void blobmsg_clear_name(struct blob_attr *attr)
  50. {
  51. struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr);
  52. hdr->name[0] = 0;
  53. }
  54. static inline const char *blobmsg_name(const struct blob_attr *attr)
  55. {
  56. struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr);
  57. return (const char *)(hdr + 1);
  58. }
  59. static inline int blobmsg_type(const struct blob_attr *attr)
  60. {
  61. return blob_id(attr);
  62. }
  63. static uint16_t blobmsg_namelen(const struct blobmsg_hdr *hdr)
  64. {
  65. return be16_to_cpu(hdr->namelen);
  66. }
  67. static inline void *blobmsg_data(const struct blob_attr *attr)
  68. {
  69. struct blobmsg_hdr *hdr;
  70. char *data;
  71. if (!attr)
  72. return NULL;
  73. hdr = (struct blobmsg_hdr *) blob_data(attr);
  74. data = (char *) blob_data(attr);
  75. if (blob_is_extended(attr))
  76. data += blobmsg_hdrlen(blobmsg_namelen(hdr));
  77. return data;
  78. }
  79. static inline size_t blobmsg_data_len(const struct blob_attr *attr)
  80. {
  81. uint8_t *start, *end;
  82. if (!attr)
  83. return 0;
  84. start = (uint8_t *) blob_data(attr);
  85. end = (uint8_t *) blobmsg_data(attr);
  86. return blob_len(attr) - (end - start);
  87. }
  88. static inline size_t blobmsg_len(const struct blob_attr *attr)
  89. {
  90. return blobmsg_data_len(attr);
  91. }
  92. /*
  93. * blobmsg_check_attr: validate a list of attributes
  94. *
  95. * This method may be used with trusted data only. Providing
  96. * malformed blobs will cause out of bounds memory access.
  97. */
  98. bool blobmsg_check_attr(const struct blob_attr *attr, bool name);
  99. /*
  100. * blobmsg_check_attr_len: validate a list of attributes
  101. *
  102. * This method should be safer implementation of blobmsg_check_attr.
  103. * It will limit all memory access performed on the blob to the
  104. * range [attr, attr + len] (upper bound non inclusive) and is
  105. * thus suited for checking of untrusted blob attributes.
  106. */
  107. bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len);
  108. /*
  109. * blobmsg_check_attr_list: validate a list of attributes
  110. *
  111. * This method may be used with trusted data only. Providing
  112. * malformed blobs will cause out of bounds memory access.
  113. */
  114. bool blobmsg_check_attr_list(const struct blob_attr *attr, int type);
  115. /*
  116. * blobmsg_check_attr_list_len: validate a list of untrusted attributes
  117. *
  118. * This method should be safer implementation of blobmsg_check_attr_list.
  119. * It will limit all memory access performed on the blob to the
  120. * range [attr, attr + len] (upper bound non inclusive) and is
  121. * thus suited for checking of untrusted blob attributes.
  122. */
  123. bool blobmsg_check_attr_list_len(const struct blob_attr *attr, int type, size_t len);
  124. /*
  125. * blobmsg_check_array: validate array/table and return size
  126. *
  127. * Checks if all elements of an array or table are valid and have
  128. * the specified type. Returns the number of elements in the array
  129. *
  130. * This method may be used with trusted data only. Providing
  131. * malformed blobs will cause out of bounds memory access.
  132. */
  133. int blobmsg_check_array(const struct blob_attr *attr, int type);
  134. /*
  135. * blobmsg_check_array_len: validate untrusted array/table and return size
  136. *
  137. * Checks if all elements of an array or table are valid and have
  138. * the specified type. Returns the number of elements in the array.
  139. *
  140. * This method should be safer implementation of blobmsg_check_array.
  141. * It will limit all memory access performed on the blob to the
  142. * range [attr, attr + len] (upper bound non inclusive) and is
  143. * thus suited for checking of untrusted blob attributes.
  144. */
  145. int blobmsg_check_array_len(const struct blob_attr *attr, int type, size_t len);
  146. int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len,
  147. struct blob_attr **tb, void *data, unsigned int len);
  148. int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len,
  149. struct blob_attr **tb, void *data, unsigned int len);
  150. int blobmsg_add_field(struct blob_buf *buf, int type, const char *name,
  151. const void *data, unsigned int len);
  152. static inline int
  153. blobmsg_parse_attr(const struct blobmsg_policy *policy, int policy_len,
  154. struct blob_attr **tb, struct blob_attr *data)
  155. {
  156. return blobmsg_parse(policy, policy_len, tb, blobmsg_data(data), blobmsg_len(data));
  157. }
  158. static inline int
  159. blobmsg_parse_array_attr(const struct blobmsg_policy *policy, int policy_len,
  160. struct blob_attr **tb, struct blob_attr *data)
  161. {
  162. return blobmsg_parse_array(policy, policy_len, tb, blobmsg_data(data), blobmsg_len(data));
  163. }
  164. static inline int
  165. blobmsg_add_double(struct blob_buf *buf, const char *name, double val)
  166. {
  167. union {
  168. double d;
  169. uint64_t u64;
  170. } v;
  171. v.d = val;
  172. v.u64 = cpu_to_be64(v.u64);
  173. return blobmsg_add_field(buf, BLOBMSG_TYPE_DOUBLE, name, &v.u64, 8);
  174. }
  175. static inline int
  176. blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val)
  177. {
  178. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT8, name, &val, 1);
  179. }
  180. static inline int
  181. blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val)
  182. {
  183. val = cpu_to_be16(val);
  184. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT16, name, &val, 2);
  185. }
  186. static inline int
  187. blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val)
  188. {
  189. val = cpu_to_be32(val);
  190. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT32, name, &val, 4);
  191. }
  192. static inline int
  193. blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)
  194. {
  195. val = cpu_to_be64(val);
  196. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT64, name, &val, 8);
  197. }
  198. static inline int
  199. blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)
  200. {
  201. return blobmsg_add_field(buf, BLOBMSG_TYPE_STRING, name, string, strlen(string) + 1);
  202. }
  203. static inline int
  204. blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr)
  205. {
  206. return blobmsg_add_field(buf, blobmsg_type(attr), blobmsg_name(attr),
  207. blobmsg_data(attr), blobmsg_data_len(attr));
  208. }
  209. void *blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array);
  210. static inline void *
  211. blobmsg_open_array(struct blob_buf *buf, const char *name)
  212. {
  213. return blobmsg_open_nested(buf, name, true);
  214. }
  215. static inline void *
  216. blobmsg_open_table(struct blob_buf *buf, const char *name)
  217. {
  218. return blobmsg_open_nested(buf, name, false);
  219. }
  220. static inline void
  221. blobmsg_close_array(struct blob_buf *buf, void *cookie)
  222. {
  223. blob_nest_end(buf, cookie);
  224. }
  225. static inline void
  226. blobmsg_close_table(struct blob_buf *buf, void *cookie)
  227. {
  228. blob_nest_end(buf, cookie);
  229. }
  230. static inline int blobmsg_buf_init(struct blob_buf *buf)
  231. {
  232. return blob_buf_init(buf, BLOBMSG_TYPE_TABLE);
  233. }
  234. static inline uint8_t blobmsg_get_u8(struct blob_attr *attr)
  235. {
  236. return *(uint8_t *) blobmsg_data(attr);
  237. }
  238. static inline bool blobmsg_get_bool(struct blob_attr *attr)
  239. {
  240. return *(uint8_t *) blobmsg_data(attr);
  241. }
  242. static inline uint16_t blobmsg_get_u16(struct blob_attr *attr)
  243. {
  244. return be16_to_cpu(*(uint16_t *) blobmsg_data(attr));
  245. }
  246. static inline uint32_t blobmsg_get_u32(struct blob_attr *attr)
  247. {
  248. return be32_to_cpu(*(uint32_t *) blobmsg_data(attr));
  249. }
  250. static inline uint64_t blobmsg_get_u64(struct blob_attr *attr)
  251. {
  252. uint32_t *ptr = (uint32_t *) blobmsg_data(attr);
  253. uint64_t tmp = ((uint64_t) be32_to_cpu(ptr[0])) << 32;
  254. tmp |= be32_to_cpu(ptr[1]);
  255. return tmp;
  256. }
  257. static inline uint64_t blobmsg_cast_u64(struct blob_attr *attr)
  258. {
  259. uint64_t tmp = 0;
  260. if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
  261. tmp = blobmsg_get_u64(attr);
  262. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
  263. tmp = blobmsg_get_u32(attr);
  264. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
  265. tmp = blobmsg_get_u16(attr);
  266. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
  267. tmp = blobmsg_get_u8(attr);
  268. return tmp;
  269. }
  270. static inline int64_t blobmsg_cast_s64(struct blob_attr *attr)
  271. {
  272. int64_t tmp = 0;
  273. if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
  274. tmp = blobmsg_get_u64(attr);
  275. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
  276. tmp = (int32_t)blobmsg_get_u32(attr);
  277. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
  278. tmp = (int16_t)blobmsg_get_u16(attr);
  279. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
  280. tmp = (int8_t)blobmsg_get_u8(attr);
  281. return tmp;
  282. }
  283. static inline double blobmsg_get_double(struct blob_attr *attr)
  284. {
  285. union {
  286. double d;
  287. uint64_t u64;
  288. } v;
  289. v.u64 = blobmsg_get_u64(attr);
  290. return v.d;
  291. }
  292. static inline char *blobmsg_get_string(struct blob_attr *attr)
  293. {
  294. if (!attr)
  295. return NULL;
  296. return (char *) blobmsg_data(attr);
  297. }
  298. void *blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen);
  299. void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen);
  300. void blobmsg_add_string_buffer(struct blob_buf *buf);
  301. int blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg);
  302. int blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...)
  303. __attribute__((format(printf, 3, 4)));
  304. #define blobmsg_for_each_attr(pos, attr, rem) \
  305. for (rem = attr ? blobmsg_data_len(attr) : 0, \
  306. pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
  307. rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
  308. (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
  309. rem -= blob_pad_len(pos), pos = blob_next(pos))
  310. #define __blobmsg_for_each_attr(pos, attr, rem) \
  311. for (pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
  312. rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
  313. (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
  314. rem -= blob_pad_len(pos), pos = blob_next(pos))
  315. #endif