ynl-priv.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
  2. #ifndef __YNL_C_PRIV_H
  3. #define __YNL_C_PRIV_H 1
  4. #include <stdbool.h>
  5. #include <stddef.h>
  6. #include <linux/types.h>
  7. struct ynl_parse_arg;
  8. /*
  9. * YNL internals / low level stuff
  10. */
  11. enum ynl_policy_type {
  12. YNL_PT_REJECT = 1,
  13. YNL_PT_IGNORE,
  14. YNL_PT_NEST,
  15. YNL_PT_FLAG,
  16. YNL_PT_BINARY,
  17. YNL_PT_U8,
  18. YNL_PT_U16,
  19. YNL_PT_U32,
  20. YNL_PT_U64,
  21. YNL_PT_UINT,
  22. YNL_PT_NUL_STR,
  23. YNL_PT_BITFIELD32,
  24. };
  25. enum ynl_parse_result {
  26. YNL_PARSE_CB_ERROR = -1,
  27. YNL_PARSE_CB_STOP = 0,
  28. YNL_PARSE_CB_OK = 1,
  29. };
  30. #define YNL_SOCKET_BUFFER_SIZE (1 << 17)
  31. #define YNL_ARRAY_SIZE(array) (sizeof(array) ? \
  32. sizeof(array) / sizeof(array[0]) : 0)
  33. typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,
  34. struct ynl_parse_arg *yarg);
  35. struct ynl_policy_attr {
  36. enum ynl_policy_type type;
  37. unsigned int len;
  38. const char *name;
  39. const struct ynl_policy_nest *nest;
  40. };
  41. struct ynl_policy_nest {
  42. unsigned int max_attr;
  43. const struct ynl_policy_attr *table;
  44. };
  45. struct ynl_parse_arg {
  46. struct ynl_sock *ys;
  47. const struct ynl_policy_nest *rsp_policy;
  48. void *data;
  49. };
  50. struct ynl_dump_list_type {
  51. struct ynl_dump_list_type *next;
  52. unsigned char data[] __attribute__((aligned(8)));
  53. };
  54. extern struct ynl_dump_list_type *YNL_LIST_END;
  55. static inline bool ynl_dump_obj_is_last(void *obj)
  56. {
  57. unsigned long uptr = (unsigned long)obj;
  58. uptr -= offsetof(struct ynl_dump_list_type, data);
  59. return uptr == (unsigned long)YNL_LIST_END;
  60. }
  61. static inline void *ynl_dump_obj_next(void *obj)
  62. {
  63. unsigned long uptr = (unsigned long)obj;
  64. struct ynl_dump_list_type *list;
  65. uptr -= offsetof(struct ynl_dump_list_type, data);
  66. list = (struct ynl_dump_list_type *)uptr;
  67. uptr = (unsigned long)list->next;
  68. uptr += offsetof(struct ynl_dump_list_type, data);
  69. return (void *)uptr;
  70. }
  71. struct ynl_ntf_base_type {
  72. __u16 family;
  73. __u8 cmd;
  74. struct ynl_ntf_base_type *next;
  75. void (*free)(struct ynl_ntf_base_type *ntf);
  76. unsigned char data[] __attribute__((aligned(8)));
  77. };
  78. struct nlmsghdr *
  79. ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
  80. struct nlmsghdr *
  81. ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
  82. int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr);
  83. /* YNL specific helpers used by the auto-generated code */
  84. struct ynl_req_state {
  85. struct ynl_parse_arg yarg;
  86. ynl_parse_cb_t cb;
  87. __u32 rsp_cmd;
  88. };
  89. struct ynl_dump_state {
  90. struct ynl_parse_arg yarg;
  91. void *first;
  92. struct ynl_dump_list_type *last;
  93. size_t alloc_sz;
  94. ynl_parse_cb_t cb;
  95. __u32 rsp_cmd;
  96. };
  97. struct ynl_ntf_info {
  98. const struct ynl_policy_nest *policy;
  99. ynl_parse_cb_t cb;
  100. size_t alloc_sz;
  101. void (*free)(struct ynl_ntf_base_type *ntf);
  102. };
  103. int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
  104. struct ynl_req_state *yrs);
  105. int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
  106. struct ynl_dump_state *yds);
  107. void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
  108. int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
  109. /* Netlink message handling helpers */
  110. #define YNL_MSG_OVERFLOW 1
  111. static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)
  112. {
  113. struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
  114. memset(nlh, 0, sizeof(*nlh));
  115. nlh->nlmsg_len = NLMSG_HDRLEN;
  116. return nlh;
  117. }
  118. static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)
  119. {
  120. return nlh->nlmsg_len - NLMSG_HDRLEN;
  121. }
  122. static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)
  123. {
  124. return (unsigned char *)nlh + NLMSG_HDRLEN;
  125. }
  126. static inline void *
  127. ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)
  128. {
  129. return (unsigned char *)nlh + NLMSG_HDRLEN + offset;
  130. }
  131. static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)
  132. {
  133. return (char *)nlh + nlh->nlmsg_len;
  134. }
  135. static inline void *
  136. ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)
  137. {
  138. void *tail = ynl_nlmsg_end_addr(nlh);
  139. nlh->nlmsg_len += NLMSG_ALIGN(size);
  140. return tail;
  141. }
  142. /* Netlink attribute helpers */
  143. static inline unsigned int ynl_attr_type(const struct nlattr *attr)
  144. {
  145. return attr->nla_type & NLA_TYPE_MASK;
  146. }
  147. static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)
  148. {
  149. return attr->nla_len - NLA_HDRLEN;
  150. }
  151. static inline void *ynl_attr_data(const struct nlattr *attr)
  152. {
  153. return (unsigned char *)attr + NLA_HDRLEN;
  154. }
  155. static inline void *ynl_attr_data_end(const struct nlattr *attr)
  156. {
  157. return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);
  158. }
  159. #define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \
  160. for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \
  161. NLMSG_HDRLEN + fixed_hdr_sz); attr; \
  162. (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
  163. #define ynl_attr_for_each_nested(attr, outer) \
  164. for ((attr) = ynl_attr_first(outer, outer->nla_len, \
  165. sizeof(struct nlattr)); attr; \
  166. (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
  167. #define ynl_attr_for_each_payload(start, len, attr) \
  168. for ((attr) = ynl_attr_first(start, len, 0); attr; \
  169. (attr) = ynl_attr_next(start + len, attr))
  170. static inline struct nlattr *
  171. ynl_attr_if_good(const void *end, struct nlattr *attr)
  172. {
  173. if (attr + 1 > (const struct nlattr *)end)
  174. return NULL;
  175. if (ynl_attr_data_end(attr) > end)
  176. return NULL;
  177. return attr;
  178. }
  179. static inline struct nlattr *
  180. ynl_attr_next(const void *end, const struct nlattr *prev)
  181. {
  182. struct nlattr *attr;
  183. attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));
  184. return ynl_attr_if_good(end, attr);
  185. }
  186. static inline struct nlattr *
  187. ynl_attr_first(const void *start, size_t len, size_t skip)
  188. {
  189. struct nlattr *attr;
  190. attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));
  191. return ynl_attr_if_good((char *)start + len, attr);
  192. }
  193. static inline bool
  194. __ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)
  195. {
  196. bool o;
  197. /* ynl_msg_start() stashed buffer length in nlmsg_pid. */
  198. o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;
  199. if (o)
  200. /* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
  201. * are guaranteed to fail.
  202. */
  203. nlh->nlmsg_pid = YNL_MSG_OVERFLOW;
  204. return o;
  205. }
  206. static inline struct nlattr *
  207. ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)
  208. {
  209. struct nlattr *attr;
  210. if (__ynl_attr_put_overflow(nlh, 0))
  211. return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;
  212. attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
  213. attr->nla_type = attr_type | NLA_F_NESTED;
  214. nlh->nlmsg_len += NLA_HDRLEN;
  215. return attr;
  216. }
  217. static inline void
  218. ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)
  219. {
  220. attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;
  221. }
  222. static inline void
  223. ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,
  224. const void *value, size_t size)
  225. {
  226. struct nlattr *attr;
  227. if (__ynl_attr_put_overflow(nlh, size))
  228. return;
  229. attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
  230. attr->nla_type = attr_type;
  231. attr->nla_len = NLA_HDRLEN + size;
  232. memcpy(ynl_attr_data(attr), value, size);
  233. nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
  234. }
  235. static inline void
  236. ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)
  237. {
  238. struct nlattr *attr;
  239. size_t len;
  240. len = strlen(str);
  241. if (__ynl_attr_put_overflow(nlh, len))
  242. return;
  243. attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
  244. attr->nla_type = attr_type;
  245. strcpy((char *)ynl_attr_data(attr), str);
  246. attr->nla_len = NLA_HDRLEN + NLA_ALIGN(len);
  247. nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
  248. }
  249. static inline const char *ynl_attr_get_str(const struct nlattr *attr)
  250. {
  251. return (const char *)ynl_attr_data(attr);
  252. }
  253. static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)
  254. {
  255. return *(__s8 *)ynl_attr_data(attr);
  256. }
  257. static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)
  258. {
  259. return *(__s16 *)ynl_attr_data(attr);
  260. }
  261. static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)
  262. {
  263. return *(__s32 *)ynl_attr_data(attr);
  264. }
  265. static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)
  266. {
  267. __s64 tmp;
  268. memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
  269. return tmp;
  270. }
  271. static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)
  272. {
  273. return *(__u8 *)ynl_attr_data(attr);
  274. }
  275. static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)
  276. {
  277. return *(__u16 *)ynl_attr_data(attr);
  278. }
  279. static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)
  280. {
  281. return *(__u32 *)ynl_attr_data(attr);
  282. }
  283. static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)
  284. {
  285. __u64 tmp;
  286. memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
  287. return tmp;
  288. }
  289. static inline void
  290. ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)
  291. {
  292. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  293. }
  294. static inline void
  295. ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)
  296. {
  297. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  298. }
  299. static inline void
  300. ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)
  301. {
  302. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  303. }
  304. static inline void
  305. ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)
  306. {
  307. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  308. }
  309. static inline void
  310. ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)
  311. {
  312. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  313. }
  314. static inline void
  315. ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)
  316. {
  317. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  318. }
  319. static inline void
  320. ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)
  321. {
  322. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  323. }
  324. static inline void
  325. ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)
  326. {
  327. ynl_attr_put(nlh, attr_type, &value, sizeof(value));
  328. }
  329. static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)
  330. {
  331. switch (ynl_attr_data_len(attr)) {
  332. case 4:
  333. return ynl_attr_get_u32(attr);
  334. case 8:
  335. return ynl_attr_get_u64(attr);
  336. default:
  337. return 0;
  338. }
  339. }
  340. static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)
  341. {
  342. switch (ynl_attr_data_len(attr)) {
  343. case 4:
  344. return ynl_attr_get_s32(attr);
  345. case 8:
  346. return ynl_attr_get_s64(attr);
  347. default:
  348. return 0;
  349. }
  350. }
  351. static inline void
  352. ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)
  353. {
  354. if ((__u32)data == (__u64)data)
  355. ynl_attr_put_u32(nlh, type, data);
  356. else
  357. ynl_attr_put_u64(nlh, type, data);
  358. }
  359. static inline void
  360. ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
  361. {
  362. if ((__s32)data == (__s64)data)
  363. ynl_attr_put_s32(nlh, type, data);
  364. else
  365. ynl_attr_put_s64(nlh, type, data);
  366. }
  367. #endif