blobmsg.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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_DOUBLE,
  32. __BLOBMSG_TYPE_LAST,
  33. BLOBMSG_TYPE_LAST = __BLOBMSG_TYPE_LAST - 1,
  34. BLOBMSG_TYPE_BOOL = BLOBMSG_TYPE_INT8,
  35. BLOBMSG_CAST_INT64,
  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->name;
  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_add_double(struct blob_buf *buf, const char *name, double val)
  154. {
  155. union {
  156. double d;
  157. uint64_t u64;
  158. } v;
  159. v.d = val;
  160. v.u64 = cpu_to_be64(v.u64);
  161. return blobmsg_add_field(buf, BLOBMSG_TYPE_DOUBLE, name, &v.u64, 8);
  162. }
  163. static inline int
  164. blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val)
  165. {
  166. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT8, name, &val, 1);
  167. }
  168. static inline int
  169. blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val)
  170. {
  171. val = cpu_to_be16(val);
  172. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT16, name, &val, 2);
  173. }
  174. static inline int
  175. blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val)
  176. {
  177. val = cpu_to_be32(val);
  178. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT32, name, &val, 4);
  179. }
  180. static inline int
  181. blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)
  182. {
  183. val = cpu_to_be64(val);
  184. return blobmsg_add_field(buf, BLOBMSG_TYPE_INT64, name, &val, 8);
  185. }
  186. static inline int
  187. blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)
  188. {
  189. return blobmsg_add_field(buf, BLOBMSG_TYPE_STRING, name, string, strlen(string) + 1);
  190. }
  191. static inline int
  192. blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr)
  193. {
  194. return blobmsg_add_field(buf, blobmsg_type(attr), blobmsg_name(attr),
  195. blobmsg_data(attr), blobmsg_data_len(attr));
  196. }
  197. void *blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array);
  198. static inline void *
  199. blobmsg_open_array(struct blob_buf *buf, const char *name)
  200. {
  201. return blobmsg_open_nested(buf, name, true);
  202. }
  203. static inline void *
  204. blobmsg_open_table(struct blob_buf *buf, const char *name)
  205. {
  206. return blobmsg_open_nested(buf, name, false);
  207. }
  208. static inline void
  209. blobmsg_close_array(struct blob_buf *buf, void *cookie)
  210. {
  211. blob_nest_end(buf, cookie);
  212. }
  213. static inline void
  214. blobmsg_close_table(struct blob_buf *buf, void *cookie)
  215. {
  216. blob_nest_end(buf, cookie);
  217. }
  218. static inline int blobmsg_buf_init(struct blob_buf *buf)
  219. {
  220. return blob_buf_init(buf, BLOBMSG_TYPE_TABLE);
  221. }
  222. static inline uint8_t blobmsg_get_u8(struct blob_attr *attr)
  223. {
  224. return *(uint8_t *) blobmsg_data(attr);
  225. }
  226. static inline bool blobmsg_get_bool(struct blob_attr *attr)
  227. {
  228. return *(uint8_t *) blobmsg_data(attr);
  229. }
  230. static inline uint16_t blobmsg_get_u16(struct blob_attr *attr)
  231. {
  232. return be16_to_cpu(*(uint16_t *) blobmsg_data(attr));
  233. }
  234. static inline uint32_t blobmsg_get_u32(struct blob_attr *attr)
  235. {
  236. return be32_to_cpu(*(uint32_t *) blobmsg_data(attr));
  237. }
  238. static inline uint64_t blobmsg_get_u64(struct blob_attr *attr)
  239. {
  240. uint32_t *ptr = (uint32_t *) blobmsg_data(attr);
  241. uint64_t tmp = ((uint64_t) be32_to_cpu(ptr[0])) << 32;
  242. tmp |= be32_to_cpu(ptr[1]);
  243. return tmp;
  244. }
  245. static inline uint64_t blobmsg_cast_u64(struct blob_attr *attr)
  246. {
  247. uint64_t tmp = 0;
  248. if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
  249. tmp = blobmsg_get_u64(attr);
  250. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
  251. tmp = blobmsg_get_u32(attr);
  252. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
  253. tmp = blobmsg_get_u16(attr);
  254. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
  255. tmp = blobmsg_get_u8(attr);
  256. return tmp;
  257. }
  258. static inline int64_t blobmsg_cast_s64(struct blob_attr *attr)
  259. {
  260. int64_t tmp = 0;
  261. if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
  262. tmp = blobmsg_get_u64(attr);
  263. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
  264. tmp = (int32_t)blobmsg_get_u32(attr);
  265. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
  266. tmp = (int16_t)blobmsg_get_u16(attr);
  267. else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
  268. tmp = (int8_t)blobmsg_get_u8(attr);
  269. return tmp;
  270. }
  271. static inline double blobmsg_get_double(struct blob_attr *attr)
  272. {
  273. union {
  274. double d;
  275. uint64_t u64;
  276. } v;
  277. v.u64 = blobmsg_get_u64(attr);
  278. return v.d;
  279. }
  280. static inline char *blobmsg_get_string(struct blob_attr *attr)
  281. {
  282. if (!attr)
  283. return NULL;
  284. return (char *) blobmsg_data(attr);
  285. }
  286. void *blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen);
  287. void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen);
  288. void blobmsg_add_string_buffer(struct blob_buf *buf);
  289. int blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg);
  290. int blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...)
  291. __attribute__((format(printf, 3, 4)));
  292. #define blobmsg_for_each_attr(pos, attr, rem) \
  293. for (rem = attr ? blobmsg_data_len(attr) : 0, \
  294. pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
  295. rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
  296. (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
  297. rem -= blob_pad_len(pos), pos = blob_next(pos))
  298. #define __blobmsg_for_each_attr(pos, attr, rem) \
  299. for (pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
  300. rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
  301. (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
  302. rem -= blob_pad_len(pos), pos = blob_next(pos))
  303. #endif