brintos

brintos / linux-shallow public Read only

0
0
Text · 10.3 KiB · 3c09a7b Raw
458 lines · c
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */2#ifndef __YNL_C_PRIV_H3#define __YNL_C_PRIV_H 14 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 stuff13 */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};29 30enum ynl_parse_result {31	YNL_PARSE_CB_ERROR = -1,32	YNL_PARSE_CB_STOP = 0,33	YNL_PARSE_CB_OK = 1,34};35 36#define YNL_SOCKET_BUFFER_SIZE		(1 << 17)37 38#define YNL_ARRAY_SIZE(array)	(sizeof(array) ?			\39				 sizeof(array) / sizeof(array[0]) : 0)40 41typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,42			      struct ynl_parse_arg *yarg);43 44struct ynl_policy_attr {45	enum ynl_policy_type type;46	unsigned int len;47	const char *name;48	const struct ynl_policy_nest *nest;49};50 51struct ynl_policy_nest {52	unsigned int max_attr;53	const struct ynl_policy_attr *table;54};55 56struct ynl_parse_arg {57	struct ynl_sock *ys;58	const struct ynl_policy_nest *rsp_policy;59	void *data;60};61 62struct ynl_dump_list_type {63	struct ynl_dump_list_type *next;64	unsigned char data[] __attribute__((aligned(8)));65};66extern struct ynl_dump_list_type *YNL_LIST_END;67 68static inline bool ynl_dump_obj_is_last(void *obj)69{70	unsigned long uptr = (unsigned long)obj;71 72	uptr -= offsetof(struct ynl_dump_list_type, data);73	return uptr == (unsigned long)YNL_LIST_END;74}75 76static inline void *ynl_dump_obj_next(void *obj)77{78	unsigned long uptr = (unsigned long)obj;79	struct ynl_dump_list_type *list;80 81	uptr -= offsetof(struct ynl_dump_list_type, data);82	list = (struct ynl_dump_list_type *)uptr;83	uptr = (unsigned long)list->next;84	uptr += offsetof(struct ynl_dump_list_type, data);85 86	return (void *)uptr;87}88 89struct ynl_ntf_base_type {90	__u16 family;91	__u8 cmd;92	struct ynl_ntf_base_type *next;93	void (*free)(struct ynl_ntf_base_type *ntf);94	unsigned char data[] __attribute__((aligned(8)));95};96 97struct nlmsghdr *98ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);99struct nlmsghdr *100ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);101 102int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr);103 104/* YNL specific helpers used by the auto-generated code */105 106struct ynl_req_state {107	struct ynl_parse_arg yarg;108	ynl_parse_cb_t cb;109	__u32 rsp_cmd;110};111 112struct ynl_dump_state {113	struct ynl_parse_arg yarg;114	void *first;115	struct ynl_dump_list_type *last;116	size_t alloc_sz;117	ynl_parse_cb_t cb;118	__u32 rsp_cmd;119};120 121struct ynl_ntf_info {122	const struct ynl_policy_nest *policy;123	ynl_parse_cb_t cb;124	size_t alloc_sz;125	void (*free)(struct ynl_ntf_base_type *ntf);126};127 128int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,129	     struct ynl_req_state *yrs);130int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,131		  struct ynl_dump_state *yds);132 133void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);134int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);135 136/* Netlink message handling helpers */137 138#define YNL_MSG_OVERFLOW	1139 140static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)141{142	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;143 144	memset(nlh, 0, sizeof(*nlh));145	nlh->nlmsg_len = NLMSG_HDRLEN;146 147	return nlh;148}149 150static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)151{152	return nlh->nlmsg_len - NLMSG_HDRLEN;153}154 155static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)156{157	return (unsigned char *)nlh + NLMSG_HDRLEN;158}159 160static inline void *161ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)162{163	return (unsigned char *)nlh + NLMSG_HDRLEN + offset;164}165 166static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)167{168	return (char *)nlh + nlh->nlmsg_len;169}170 171static inline void *172ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)173{174	void *tail = ynl_nlmsg_end_addr(nlh);175 176	nlh->nlmsg_len += NLMSG_ALIGN(size);177	return tail;178}179 180/* Netlink attribute helpers */181 182static inline unsigned int ynl_attr_type(const struct nlattr *attr)183{184	return attr->nla_type & NLA_TYPE_MASK;185}186 187static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)188{189	return attr->nla_len - NLA_HDRLEN;190}191 192static inline void *ynl_attr_data(const struct nlattr *attr)193{194	return (unsigned char *)attr + NLA_HDRLEN;195}196 197static inline void *ynl_attr_data_end(const struct nlattr *attr)198{199	return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);200}201 202#define ynl_attr_for_each(attr, nlh, fixed_hdr_sz)			\203	for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len,		\204				     NLMSG_HDRLEN + fixed_hdr_sz); attr; \205	     (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))206 207#define ynl_attr_for_each_nested(attr, outer)				\208	for ((attr) = ynl_attr_first(outer, outer->nla_len,		\209				     sizeof(struct nlattr)); attr;	\210	     (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))211 212#define ynl_attr_for_each_payload(start, len, attr)			\213	for ((attr) = ynl_attr_first(start, len, 0); attr;		\214	     (attr) = ynl_attr_next(start + len, attr))215 216static inline struct nlattr *217ynl_attr_if_good(const void *end, struct nlattr *attr)218{219	if (attr + 1 > (const struct nlattr *)end)220		return NULL;221	if (ynl_attr_data_end(attr) > end)222		return NULL;223	return attr;224}225 226static inline struct nlattr *227ynl_attr_next(const void *end, const struct nlattr *prev)228{229	struct nlattr *attr;230 231	attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));232	return ynl_attr_if_good(end, attr);233}234 235static inline struct nlattr *236ynl_attr_first(const void *start, size_t len, size_t skip)237{238	struct nlattr *attr;239 240	attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));241	return ynl_attr_if_good((char *)start + len, attr);242}243 244static inline bool245__ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)246{247	bool o;248 249	/* ynl_msg_start() stashed buffer length in nlmsg_pid. */250	o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;251	if (o)252		/* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks253		 * are guaranteed to fail.254		 */255		nlh->nlmsg_pid = YNL_MSG_OVERFLOW;256	return o;257}258 259static inline struct nlattr *260ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)261{262	struct nlattr *attr;263 264	if (__ynl_attr_put_overflow(nlh, 0))265		return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;266 267	attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);268	attr->nla_type = attr_type | NLA_F_NESTED;269	nlh->nlmsg_len += NLA_HDRLEN;270 271	return attr;272}273 274static inline void275ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)276{277	attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;278}279 280static inline void281ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,282	     const void *value, size_t size)283{284	struct nlattr *attr;285 286	if (__ynl_attr_put_overflow(nlh, size))287		return;288 289	attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);290	attr->nla_type = attr_type;291	attr->nla_len = NLA_HDRLEN + size;292 293	memcpy(ynl_attr_data(attr), value, size);294 295	nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);296}297 298static inline void299ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)300{301	struct nlattr *attr;302	size_t len;303 304	len = strlen(str);305	if (__ynl_attr_put_overflow(nlh, len))306		return;307 308	attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);309	attr->nla_type = attr_type;310 311	strcpy((char *)ynl_attr_data(attr), str);312	attr->nla_len = NLA_HDRLEN + NLA_ALIGN(len);313 314	nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);315}316 317static inline const char *ynl_attr_get_str(const struct nlattr *attr)318{319	return (const char *)ynl_attr_data(attr);320}321 322static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)323{324	return *(__s8 *)ynl_attr_data(attr);325}326 327static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)328{329	return *(__s16 *)ynl_attr_data(attr);330}331 332static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)333{334	return *(__s32 *)ynl_attr_data(attr);335}336 337static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)338{339	__s64 tmp;340 341	memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));342	return tmp;343}344 345static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)346{347	return *(__u8 *)ynl_attr_data(attr);348}349 350static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)351{352	return *(__u16 *)ynl_attr_data(attr);353}354 355static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)356{357	return *(__u32 *)ynl_attr_data(attr);358}359 360static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)361{362	__u64 tmp;363 364	memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));365	return tmp;366}367 368static inline void369ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)370{371	ynl_attr_put(nlh, attr_type, &value, sizeof(value));372}373 374static inline void375ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)376{377	ynl_attr_put(nlh, attr_type, &value, sizeof(value));378}379 380static inline void381ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)382{383	ynl_attr_put(nlh, attr_type, &value, sizeof(value));384}385 386static inline void387ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)388{389	ynl_attr_put(nlh, attr_type, &value, sizeof(value));390}391 392static inline void393ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)394{395	ynl_attr_put(nlh, attr_type, &value, sizeof(value));396}397 398static inline void399ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)400{401	ynl_attr_put(nlh, attr_type, &value, sizeof(value));402}403 404static inline void405ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)406{407	ynl_attr_put(nlh, attr_type, &value, sizeof(value));408}409 410static inline void411ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)412{413	ynl_attr_put(nlh, attr_type, &value, sizeof(value));414}415 416static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)417{418	switch (ynl_attr_data_len(attr)) {419	case 4:420		return ynl_attr_get_u32(attr);421	case 8:422		return ynl_attr_get_u64(attr);423	default:424		return 0;425	}426}427 428static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)429{430	switch (ynl_attr_data_len(attr)) {431	case 4:432		return ynl_attr_get_s32(attr);433	case 8:434		return ynl_attr_get_s64(attr);435	default:436		return 0;437	}438}439 440static inline void441ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)442{443	if ((__u32)data == (__u64)data)444		ynl_attr_put_u32(nlh, type, data);445	else446		ynl_attr_put_u64(nlh, type, data);447}448 449static inline void450ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)451{452	if ((__s32)data == (__s64)data)453		ynl_attr_put_s32(nlh, type, data);454	else455		ynl_attr_put_s64(nlh, type, data);456}457#endif458