Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
*.d
+30
View File
@@ -0,0 +1,30 @@
# SPDX-License-Identifier: GPL-2.0
CC=gcc
CFLAGS += -std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow
ifeq ("$(DEBUG)","1")
CFLAGS += -g -fsanitize=address -fsanitize=leak -static-libasan
endif
SRCS=$(wildcard *.c)
OBJS=$(patsubst %.c,%.o,${SRCS})
include $(wildcard *.d)
all: ynl.a
ynl.a: $(OBJS)
@echo -e "\tAR $@"
@$(AR) rcs $@ $(OBJS)
clean:
rm -f *.o *.d *~
distclean: clean
rm -f *.a
%.o: %.c
$(COMPILE.c) -MMD -c -o $@ $<
.PHONY: all clean distclean
.DEFAULT_GOAL=all
+478
View File
@@ -0,0 +1,478 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
#ifndef __YNL_C_PRIV_H
#define __YNL_C_PRIV_H 1
#include <stdbool.h>
#include <stddef.h>
#include <linux/types.h>
struct ynl_parse_arg;
/*
* YNL internals / low level stuff
*/
enum ynl_policy_type {
YNL_PT_REJECT = 1,
YNL_PT_IGNORE,
YNL_PT_NEST,
YNL_PT_FLAG,
YNL_PT_BINARY,
YNL_PT_U8,
YNL_PT_U16,
YNL_PT_U32,
YNL_PT_U64,
YNL_PT_UINT,
YNL_PT_NUL_STR,
YNL_PT_BITFIELD32,
YNL_PT_SUBMSG,
};
enum ynl_parse_result {
YNL_PARSE_CB_ERROR = -1,
YNL_PARSE_CB_STOP = 0,
YNL_PARSE_CB_OK = 1,
};
#define YNL_SOCKET_BUFFER_SIZE (1 << 17)
#define YNL_ARRAY_SIZE(array) (sizeof(array) ? \
sizeof(array) / sizeof(array[0]) : 0)
typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,
struct ynl_parse_arg *yarg);
struct ynl_policy_attr {
enum ynl_policy_type type:8;
__u8 is_submsg:1;
__u8 is_selector:1;
__u16 selector_type;
unsigned int len;
const char *name;
const struct ynl_policy_nest *nest;
};
struct ynl_policy_nest {
unsigned int max_attr;
const struct ynl_policy_attr *table;
};
struct ynl_parse_arg {
struct ynl_sock *ys;
const struct ynl_policy_nest *rsp_policy;
void *data;
};
struct ynl_dump_list_type {
struct ynl_dump_list_type *next;
unsigned char data[] __attribute__((aligned(8)));
};
extern struct ynl_dump_list_type *YNL_LIST_END;
static inline bool ynl_dump_obj_is_last(void *obj)
{
unsigned long uptr = (unsigned long)obj;
uptr -= offsetof(struct ynl_dump_list_type, data);
return uptr == (unsigned long)YNL_LIST_END;
}
static inline void *ynl_dump_obj_next(void *obj)
{
unsigned long uptr = (unsigned long)obj;
struct ynl_dump_list_type *list;
uptr -= offsetof(struct ynl_dump_list_type, data);
list = (struct ynl_dump_list_type *)uptr;
uptr = (unsigned long)list->next;
uptr += offsetof(struct ynl_dump_list_type, data);
return (void *)uptr;
}
struct ynl_ntf_base_type {
__u16 family;
__u8 cmd;
struct ynl_ntf_base_type *next;
void (*free)(struct ynl_ntf_base_type *ntf);
unsigned char data[] __attribute__((aligned(8)));
};
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags);
struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id);
struct nlmsghdr *
ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
struct nlmsghdr *
ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
const char *sel_name);
/* YNL specific helpers used by the auto-generated code */
struct ynl_req_state {
struct ynl_parse_arg yarg;
ynl_parse_cb_t cb;
__u32 rsp_cmd;
};
struct ynl_dump_state {
struct ynl_parse_arg yarg;
void *first;
struct ynl_dump_list_type *last;
size_t alloc_sz;
ynl_parse_cb_t cb;
__u32 rsp_cmd;
};
struct ynl_ntf_info {
const struct ynl_policy_nest *policy;
ynl_parse_cb_t cb;
size_t alloc_sz;
void (*free)(struct ynl_ntf_base_type *ntf);
};
int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
struct ynl_req_state *yrs);
int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
struct ynl_dump_state *yds);
void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
/* Netlink message handling helpers */
#define YNL_MSG_OVERFLOW 1
static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)
{
struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
memset(nlh, 0, sizeof(*nlh));
nlh->nlmsg_len = NLMSG_HDRLEN;
return nlh;
}
static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)
{
return nlh->nlmsg_len - NLMSG_HDRLEN;
}
static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)
{
return (unsigned char *)nlh + NLMSG_HDRLEN;
}
static inline void *
ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)
{
return (unsigned char *)nlh + NLMSG_HDRLEN + offset;
}
static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)
{
return (char *)nlh + nlh->nlmsg_len;
}
static inline void *
ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)
{
void *tail = ynl_nlmsg_end_addr(nlh);
nlh->nlmsg_len += NLMSG_ALIGN(size);
return tail;
}
/* Netlink attribute helpers */
static inline unsigned int ynl_attr_type(const struct nlattr *attr)
{
return attr->nla_type & NLA_TYPE_MASK;
}
static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)
{
return attr->nla_len - NLA_HDRLEN;
}
static inline void *ynl_attr_data(const struct nlattr *attr)
{
return (unsigned char *)attr + NLA_HDRLEN;
}
static inline void *ynl_attr_data_end(const struct nlattr *attr)
{
return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);
}
#define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \
for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \
NLMSG_HDRLEN + fixed_hdr_sz); attr; \
(attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
#define ynl_attr_for_each_nested_off(attr, outer, offset) \
for ((attr) = ynl_attr_first(outer, outer->nla_len, \
sizeof(struct nlattr) + offset); \
attr; \
(attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
#define ynl_attr_for_each_nested(attr, outer) \
ynl_attr_for_each_nested_off(attr, outer, 0)
#define ynl_attr_for_each_payload(start, len, attr) \
for ((attr) = ynl_attr_first(start, len, 0); attr; \
(attr) = ynl_attr_next(start + len, attr))
static inline struct nlattr *
ynl_attr_if_good(const void *end, struct nlattr *attr)
{
if (attr + 1 > (const struct nlattr *)end)
return NULL;
if (ynl_attr_data_end(attr) > end)
return NULL;
return attr;
}
static inline struct nlattr *
ynl_attr_next(const void *end, const struct nlattr *prev)
{
struct nlattr *attr;
attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));
return ynl_attr_if_good(end, attr);
}
static inline struct nlattr *
ynl_attr_first(const void *start, size_t len, size_t skip)
{
struct nlattr *attr;
attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));
return ynl_attr_if_good((char *)start + len, attr);
}
static inline bool
__ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)
{
bool o;
/* ynl_msg_start() stashed buffer length in nlmsg_pid. */
o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;
if (o)
/* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
* are guaranteed to fail.
*/
nlh->nlmsg_pid = YNL_MSG_OVERFLOW;
return o;
}
static inline struct nlattr *
ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)
{
struct nlattr *attr;
if (__ynl_attr_put_overflow(nlh, 0))
return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;
attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
attr->nla_type = attr_type | NLA_F_NESTED;
nlh->nlmsg_len += NLA_HDRLEN;
return attr;
}
static inline void
ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)
{
attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;
}
static inline void
ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,
const void *value, size_t size)
{
struct nlattr *attr;
if (__ynl_attr_put_overflow(nlh, size))
return;
attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
attr->nla_type = attr_type;
attr->nla_len = NLA_HDRLEN + size;
memcpy(ynl_attr_data(attr), value, size);
nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
}
static inline void
ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)
{
struct nlattr *attr;
size_t len;
len = strlen(str) + 1;
if (__ynl_attr_put_overflow(nlh, len))
return;
attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
attr->nla_type = attr_type;
strcpy((char *)ynl_attr_data(attr), str);
attr->nla_len = NLA_HDRLEN + len;
nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
}
static inline const char *ynl_attr_get_str(const struct nlattr *attr)
{
return (const char *)ynl_attr_data(attr);
}
static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)
{
return *(__s8 *)ynl_attr_data(attr);
}
static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)
{
return *(__s16 *)ynl_attr_data(attr);
}
static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)
{
return *(__s32 *)ynl_attr_data(attr);
}
static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)
{
__s64 tmp;
memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
return tmp;
}
static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)
{
return *(__u8 *)ynl_attr_data(attr);
}
static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)
{
return *(__u16 *)ynl_attr_data(attr);
}
static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)
{
return *(__u32 *)ynl_attr_data(attr);
}
static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)
{
__u64 tmp;
memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
return tmp;
}
static inline void
ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline void
ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)
{
ynl_attr_put(nlh, attr_type, &value, sizeof(value));
}
static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)
{
switch (ynl_attr_data_len(attr)) {
case 4:
return ynl_attr_get_u32(attr);
case 8:
return ynl_attr_get_u64(attr);
default:
return 0;
}
}
static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)
{
switch (ynl_attr_data_len(attr)) {
case 4:
return ynl_attr_get_s32(attr);
case 8:
return ynl_attr_get_s64(attr);
default:
return 0;
}
}
static inline void
ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)
{
if ((__u32)data == (__u64)data)
ynl_attr_put_u32(nlh, type, data);
else
ynl_attr_put_u64(nlh, type, data);
}
static inline void
ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
{
if ((__s32)data == (__s64)data)
ynl_attr_put_s32(nlh, type, data);
else
ynl_attr_put_s64(nlh, type, data);
}
int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
unsigned int type);
static inline int ynl_attr_validate(struct ynl_parse_arg *yarg,
const struct nlattr *attr)
{
return __ynl_attr_validate(yarg, attr, ynl_attr_type(attr));
}
#endif
File diff suppressed because it is too large Load Diff
+143
View File
@@ -0,0 +1,143 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
#ifndef __YNL_C_H
#define __YNL_C_H 1
#include <stdbool.h>
#include <stddef.h>
#include <linux/genetlink.h>
#include <linux/types.h>
#include "ynl-priv.h"
enum ynl_error_code {
YNL_ERROR_NONE = 0,
__YNL_ERRNO_END = 4096,
YNL_ERROR_INTERNAL,
YNL_ERROR_DUMP_INTER,
YNL_ERROR_EXPECT_ACK,
YNL_ERROR_EXPECT_MSG,
YNL_ERROR_UNEXPECT_MSG,
YNL_ERROR_ATTR_MISSING,
YNL_ERROR_ATTR_INVALID,
YNL_ERROR_UNKNOWN_NTF,
YNL_ERROR_INV_RESP,
YNL_ERROR_INPUT_INVALID,
YNL_ERROR_INPUT_TOO_BIG,
YNL_ERROR_SUBMSG_KEY,
};
/**
* struct ynl_error - error encountered by YNL
* @code: errno (low values) or YNL error code (enum ynl_error_code)
* @attr_offs: offset of bad attribute (for very advanced users)
* @msg: error message
*
* Error information for when YNL operations fail.
* Users should interact with the err member of struct ynl_sock directly.
* The main exception to that rule is ynl_sock_create().
*/
struct ynl_error {
enum ynl_error_code code;
unsigned int attr_offs;
char msg[512];
};
/**
* struct ynl_family - YNL family info
* Family description generated by codegen. Pass to ynl_sock_create().
*/
struct ynl_family {
/* private: */
const char *name;
size_t hdr_len;
bool is_classic;
__u16 classic_id;
const struct ynl_ntf_info *ntf_info;
unsigned int ntf_info_size;
};
/**
* struct ynl_sock - YNL wrapped netlink socket
* @err: YNL error descriptor, cleared on every request.
*/
struct ynl_sock {
struct ynl_error err;
/* private: */
const struct ynl_family *family;
int socket;
__u32 seq;
__u32 portid;
__u16 family_id;
unsigned int n_mcast_groups;
struct {
unsigned int id;
char name[GENL_NAMSIZ];
} *mcast_groups;
struct ynl_ntf_base_type *ntf_first;
struct ynl_ntf_base_type **ntf_last_next;
struct nlmsghdr *nlh;
const struct ynl_policy_nest *req_policy;
size_t req_hdr_len;
unsigned char *tx_buf;
unsigned char *rx_buf;
unsigned char raw_buf[];
};
/**
* struct ynl_string - parsed individual string
* @len: length of the string (excluding terminating character)
* @str: value of the string
*
* Parsed and nul-terminated string. This struct is only used for arrays of
* strings. Non-array string members are placed directly in respective types.
*/
struct ynl_string {
unsigned int len;
char str[];
};
struct ynl_sock *
ynl_sock_create(const struct ynl_family *yf, struct ynl_error *e);
void ynl_sock_destroy(struct ynl_sock *ys);
#define ynl_dump_foreach(dump, iter) \
for (typeof(dump->obj) *iter = &dump->obj; \
!ynl_dump_obj_is_last(iter); \
iter = ynl_dump_obj_next(iter))
/**
* ynl_dump_empty() - does the dump have no entries
* @dump: pointer to the dump list, as returned by a dump call
*
* Check if the dump is empty, i.e. contains no objects.
* Dump calls return NULL on error, and terminator element if empty.
*/
static inline bool ynl_dump_empty(void *dump)
{
return dump == (void *)YNL_LIST_END;
}
int ynl_subscribe(struct ynl_sock *ys, const char *grp_name);
int ynl_socket_get_fd(struct ynl_sock *ys);
int ynl_ntf_check(struct ynl_sock *ys);
/**
* ynl_has_ntf() - check if socket has *parsed* notifications
* @ys: active YNL socket
*
* Note that this does not take into account notifications sitting
* in netlink socket, just the notifications which have already been
* read and parsed (e.g. during a ynl_ntf_check() call).
*/
static inline bool ynl_has_ntf(struct ynl_sock *ys)
{
return ys->ntf_last_next != &ys->ntf_first;
}
struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys);
void ynl_ntf_free(struct ynl_ntf_base_type *ntf);
#endif