FILE
ynl-priv.h
File preview with syntax highlighting.
linux-6.19.14/tools/net/ynl/lib/ynl-priv.h
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 5#include <stdbool.h> 6#include <stddef.h> 7#include <linux/types.h> 8 9struct ynl_parse_arg; 10 11/* 12 * YNL internals / low level stuff 13 */ 14 15enum ynl_policy_type { 16 YNL_PT_REJECT = 1, 17 YNL_PT_IGNORE, 18 YNL_PT_NEST, 19 YNL_PT_FLAG, 20 YNL_PT_BINARY, 21 YNL_PT_U8, 22 YNL_PT_U16, 23 YNL_PT_U32, 24 YNL_PT_U64, 25 YNL_PT_UINT, 26 YNL_PT_NUL_STR, 27 YNL_PT_BITFIELD32, 28 YNL_PT_SUBMSG, 29}; 30 31enum ynl_parse_result { 32 YNL_PARSE_CB_ERROR = -1, 33 YNL_PARSE_CB_STOP = 0, 34 YNL_PARSE_CB_OK = 1, 35}; 36 37#define YNL_SOCKET_BUFFER_SIZE (1 << 17) 38 39#define YNL_ARRAY_SIZE(array) (sizeof(array) ? \ 40 sizeof(array) / sizeof(array[0]) : 0) 41 42typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh, 43 struct ynl_parse_arg *yarg); 44 45struct ynl_policy_attr { 46 enum ynl_policy_type type:8; 47 __u8 is_submsg:1; 48 __u8 is_selector:1; 49 __u16 selector_type; 50 unsigned int len; 51 const char *name; 52 const struct ynl_policy_nest *nest; 53}; 54 55struct ynl_policy_nest { 56 unsigned int max_attr; 57 const struct ynl_policy_attr *table; 58}; 59 60struct ynl_parse_arg { 61 struct ynl_sock *ys; 62 const struct ynl_policy_nest *rsp_policy; 63 void *data; 64}; 65 66struct ynl_dump_list_type { 67 struct ynl_dump_list_type *next; 68 unsigned char data[] __attribute__((aligned(8))); 69}; 70extern struct ynl_dump_list_type *YNL_LIST_END; 71 72static inline bool ynl_dump_obj_is_last(void *obj) 73{ 74 unsigned long uptr = (unsigned long)obj; 75 76 uptr -= offsetof(struct ynl_dump_list_type, data); 77 return uptr == (unsigned long)YNL_LIST_END; 78} 79 80static inline void *ynl_dump_obj_next(void *obj) 81{ 82 unsigned long uptr = (unsigned long)obj; 83 struct ynl_dump_list_type *list; 84 85 uptr -= offsetof(struct ynl_dump_list_type, data); 86 list = (struct ynl_dump_list_type *)uptr; 87 uptr = (unsigned long)list->next; 88 uptr += offsetof(struct ynl_dump_list_type, data); 89 90 return (void *)uptr; 91} 92 93struct ynl_ntf_base_type { 94 __u16 family; 95 __u8 cmd; 96 struct ynl_ntf_base_type *next; 97 void (*free)(struct ynl_ntf_base_type *ntf); 98 unsigned char data[] __attribute__((aligned(8))); 99}; 100 101struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags); 102struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id); 103 104struct nlmsghdr * 105ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version); 106struct nlmsghdr * 107ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version); 108 109int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name, 110 const char *sel_name); 111 112/* YNL specific helpers used by the auto-generated code */ 113 114struct ynl_req_state { 115 struct ynl_parse_arg yarg; 116 ynl_parse_cb_t cb; 117 __u32 rsp_cmd; 118}; 119 120struct ynl_dump_state { 121 struct ynl_parse_arg yarg; 122 void *first; 123 struct ynl_dump_list_type *last; 124 size_t alloc_sz; 125 ynl_parse_cb_t cb; 126 __u32 rsp_cmd; 127}; 128 129struct ynl_ntf_info { 130 const struct ynl_policy_nest *policy; 131 ynl_parse_cb_t cb; 132 size_t alloc_sz; 133 void (*free)(struct ynl_ntf_base_type *ntf); 134}; 135 136int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh, 137 struct ynl_req_state *yrs); 138int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh, 139 struct ynl_dump_state *yds); 140 141void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd); 142int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg); 143 144/* Netlink message handling helpers */ 145 146#define YNL_MSG_OVERFLOW 1 147 148static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf) 149{ 150 struct nlmsghdr *nlh = (struct nlmsghdr *)buf; 151 152 memset(nlh, 0, sizeof(*nlh)); 153 nlh->nlmsg_len = NLMSG_HDRLEN; 154 155 return nlh; 156} 157 158static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh) 159{ 160 return nlh->nlmsg_len - NLMSG_HDRLEN; 161} 162 163static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh) 164{ 165 return (unsigned char *)nlh + NLMSG_HDRLEN; 166} 167 168static inline void * 169ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset) 170{ 171 return (unsigned char *)nlh + NLMSG_HDRLEN + offset; 172} 173 174static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh) 175{ 176 return (char *)nlh + nlh->nlmsg_len; 177} 178 179static inline void * 180ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size) 181{ 182 void *tail = ynl_nlmsg_end_addr(nlh); 183 184 nlh->nlmsg_len += NLMSG_ALIGN(size); 185 return tail; 186} 187 188/* Netlink attribute helpers */ 189 190static inline unsigned int ynl_attr_type(const struct nlattr *attr) 191{ 192 return attr->nla_type & NLA_TYPE_MASK; 193} 194 195static inline unsigned int ynl_attr_data_len(const struct nlattr *attr) 196{ 197 return attr->nla_len - NLA_HDRLEN; 198} 199 200static inline void *ynl_attr_data(const struct nlattr *attr) 201{ 202 return (unsigned char *)attr + NLA_HDRLEN; 203} 204 205static inline void *ynl_attr_data_end(const struct nlattr *attr) 206{ 207 return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr); 208} 209 210#define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \ 211 for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \ 212 NLMSG_HDRLEN + fixed_hdr_sz); attr; \ 213 (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr)) 214 215#define ynl_attr_for_each_nested_off(attr, outer, offset) \ 216 for ((attr) = ynl_attr_first(outer, outer->nla_len, \ 217 sizeof(struct nlattr) + offset); \ 218 attr; \ 219 (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr)) 220 221#define ynl_attr_for_each_nested(attr, outer) \ 222 ynl_attr_for_each_nested_off(attr, outer, 0) 223 224#define ynl_attr_for_each_payload(start, len, attr) \ 225 for ((attr) = ynl_attr_first(start, len, 0); attr; \ 226 (attr) = ynl_attr_next(start + len, attr)) 227 228static inline struct nlattr * 229ynl_attr_if_good(const void *end, struct nlattr *attr) 230{ 231 if (attr + 1 > (const struct nlattr *)end) 232 return NULL; 233 if (ynl_attr_data_end(attr) > end) 234 return NULL; 235 return attr; 236} 237 238static inline struct nlattr * 239ynl_attr_next(const void *end, const struct nlattr *prev) 240{ 241 struct nlattr *attr; 242 243 attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len)); 244 return ynl_attr_if_good(end, attr); 245} 246 247static inline struct nlattr * 248ynl_attr_first(const void *start, size_t len, size_t skip) 249{ 250 struct nlattr *attr; 251 252 attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip)); 253 return ynl_attr_if_good((char *)start + len, attr); 254} 255 256static inline bool 257__ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size) 258{ 259 bool o; 260 261 /* ynl_msg_start() stashed buffer length in nlmsg_pid. */ 262 o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid; 263 if (o) 264 /* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks 265 * are guaranteed to fail. 266 */ 267 nlh->nlmsg_pid = YNL_MSG_OVERFLOW; 268 return o; 269} 270 271static inline struct nlattr * 272ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type) 273{ 274 struct nlattr *attr; 275 276 if (__ynl_attr_put_overflow(nlh, 0)) 277 return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1; 278 279 attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh); 280 attr->nla_type = attr_type | NLA_F_NESTED; 281 nlh->nlmsg_len += NLA_HDRLEN; 282 283 return attr; 284} 285 286static inline void 287ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr) 288{ 289 attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr; 290} 291 292static inline void 293ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type, 294 const void *value, size_t size) 295{ 296 struct nlattr *attr; 297 298 if (__ynl_attr_put_overflow(nlh, size)) 299 return; 300 301 attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh); 302 attr->nla_type = attr_type; 303 attr->nla_len = NLA_HDRLEN + size; 304 305 memcpy(ynl_attr_data(attr), value, size); 306 307 nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len); 308} 309 310static inline void 311ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str) 312{ 313 struct nlattr *attr; 314 size_t len; 315 316 len = strlen(str) + 1; 317 if (__ynl_attr_put_overflow(nlh, len)) 318 return; 319 320 attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh); 321 attr->nla_type = attr_type; 322 323 strcpy((char *)ynl_attr_data(attr), str); 324 attr->nla_len = NLA_HDRLEN + len; 325 326 nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len); 327} 328 329static inline const char *ynl_attr_get_str(const struct nlattr *attr) 330{ 331 return (const char *)ynl_attr_data(attr); 332} 333 334static inline __s8 ynl_attr_get_s8(const struct nlattr *attr) 335{ 336 return *(__s8 *)ynl_attr_data(attr); 337} 338 339static inline __s16 ynl_attr_get_s16(const struct nlattr *attr) 340{ 341 return *(__s16 *)ynl_attr_data(attr); 342} 343 344static inline __s32 ynl_attr_get_s32(const struct nlattr *attr) 345{ 346 return *(__s32 *)ynl_attr_data(attr); 347} 348 349static inline __s64 ynl_attr_get_s64(const struct nlattr *attr) 350{ 351 __s64 tmp; 352 353 memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp)); 354 return tmp; 355} 356 357static inline __u8 ynl_attr_get_u8(const struct nlattr *attr) 358{ 359 return *(__u8 *)ynl_attr_data(attr); 360} 361 362static inline __u16 ynl_attr_get_u16(const struct nlattr *attr) 363{ 364 return *(__u16 *)ynl_attr_data(attr); 365} 366 367static inline __u32 ynl_attr_get_u32(const struct nlattr *attr) 368{ 369 return *(__u32 *)ynl_attr_data(attr); 370} 371 372static inline __u64 ynl_attr_get_u64(const struct nlattr *attr) 373{ 374 __u64 tmp; 375 376 memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp)); 377 return tmp; 378} 379 380static inline void 381ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value) 382{ 383 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 384} 385 386static inline void 387ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value) 388{ 389 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 390} 391 392static inline void 393ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value) 394{ 395 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 396} 397 398static inline void 399ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value) 400{ 401 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 402} 403 404static inline void 405ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value) 406{ 407 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 408} 409 410static inline void 411ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value) 412{ 413 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 414} 415 416static inline void 417ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value) 418{ 419 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 420} 421 422static inline void 423ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value) 424{ 425 ynl_attr_put(nlh, attr_type, &value, sizeof(value)); 426} 427 428static inline __u64 ynl_attr_get_uint(const struct nlattr *attr) 429{ 430 switch (ynl_attr_data_len(attr)) { 431 case 4: 432 return ynl_attr_get_u32(attr); 433 case 8: 434 return ynl_attr_get_u64(attr); 435 default: 436 return 0; 437 } 438} 439 440static inline __s64 ynl_attr_get_sint(const struct nlattr *attr) 441{ 442 switch (ynl_attr_data_len(attr)) { 443 case 4: 444 return ynl_attr_get_s32(attr); 445 case 8: 446 return ynl_attr_get_s64(attr); 447 default: 448 return 0; 449 } 450} 451 452static inline void 453ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data) 454{ 455 if ((__u32)data == (__u64)data) 456 ynl_attr_put_u32(nlh, type, data); 457 else 458 ynl_attr_put_u64(nlh, type, data); 459} 460 461static inline void 462ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data) 463{ 464 if ((__s32)data == (__s64)data) 465 ynl_attr_put_s32(nlh, type, data); 466 else 467 ynl_attr_put_s64(nlh, type, data); 468} 469 470int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr, 471 unsigned int type); 472 473static inline int ynl_attr_validate(struct ynl_parse_arg *yarg, 474 const struct nlattr *attr) 475{ 476 return __ynl_attr_validate(yarg, attr, ynl_attr_type(attr)); 477} 478#endif
~/
Read-only file preview.