mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-06 13:17:44 +03:00
Merge pull request #20057 from yuwata/sd-netlink-genl-cleanups
sd-netlink: cleanups for generic netlink
This commit is contained in:
commit
4917c15af7
src
basic
libsystemd
meson.build
sd-netlink
generic-netlink.cgeneric-netlink.hnetlink-genl.cnetlink-genl.hnetlink-internal.hnetlink-message-nfnl.cnetlink-message-rtnl.cnetlink-message.cnetlink-slot.cnetlink-socket.cnetlink-types-genl.cnetlink-types-internal.hnetlink-types-nfnl.cnetlink-types-rtnl.cnetlink-types.cnetlink-types.hnetlink-util.cnetlink-util.hsd-netlink.ctest-netlink.c
network
shared
systemd
102
src/basic/linux/genetlink.h
Normal file
102
src/basic/linux/genetlink.h
Normal file
@ -0,0 +1,102 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI__LINUX_GENERIC_NETLINK_H
|
||||
#define _UAPI__LINUX_GENERIC_NETLINK_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#define GENL_NAMSIZ 16 /* length of family name */
|
||||
|
||||
#define GENL_MIN_ID NLMSG_MIN_TYPE
|
||||
#define GENL_MAX_ID 1023
|
||||
|
||||
struct genlmsghdr {
|
||||
__u8 cmd;
|
||||
__u8 version;
|
||||
__u16 reserved;
|
||||
};
|
||||
|
||||
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
|
||||
|
||||
#define GENL_ADMIN_PERM 0x01
|
||||
#define GENL_CMD_CAP_DO 0x02
|
||||
#define GENL_CMD_CAP_DUMP 0x04
|
||||
#define GENL_CMD_CAP_HASPOL 0x08
|
||||
#define GENL_UNS_ADMIN_PERM 0x10
|
||||
|
||||
/*
|
||||
* List of reserved static generic netlink identifiers:
|
||||
*/
|
||||
#define GENL_ID_CTRL NLMSG_MIN_TYPE
|
||||
#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
|
||||
#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2)
|
||||
/* must be last reserved + 1 */
|
||||
#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)
|
||||
|
||||
/**************************************************************************
|
||||
* Controller
|
||||
**************************************************************************/
|
||||
|
||||
enum {
|
||||
CTRL_CMD_UNSPEC,
|
||||
CTRL_CMD_NEWFAMILY,
|
||||
CTRL_CMD_DELFAMILY,
|
||||
CTRL_CMD_GETFAMILY,
|
||||
CTRL_CMD_NEWOPS,
|
||||
CTRL_CMD_DELOPS,
|
||||
CTRL_CMD_GETOPS,
|
||||
CTRL_CMD_NEWMCAST_GRP,
|
||||
CTRL_CMD_DELMCAST_GRP,
|
||||
CTRL_CMD_GETMCAST_GRP, /* unused */
|
||||
CTRL_CMD_GETPOLICY,
|
||||
__CTRL_CMD_MAX,
|
||||
};
|
||||
|
||||
#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_UNSPEC,
|
||||
CTRL_ATTR_FAMILY_ID,
|
||||
CTRL_ATTR_FAMILY_NAME,
|
||||
CTRL_ATTR_VERSION,
|
||||
CTRL_ATTR_HDRSIZE,
|
||||
CTRL_ATTR_MAXATTR,
|
||||
CTRL_ATTR_OPS,
|
||||
CTRL_ATTR_MCAST_GROUPS,
|
||||
CTRL_ATTR_POLICY,
|
||||
CTRL_ATTR_OP_POLICY,
|
||||
CTRL_ATTR_OP,
|
||||
__CTRL_ATTR_MAX,
|
||||
};
|
||||
|
||||
#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_OP_UNSPEC,
|
||||
CTRL_ATTR_OP_ID,
|
||||
CTRL_ATTR_OP_FLAGS,
|
||||
__CTRL_ATTR_OP_MAX,
|
||||
};
|
||||
|
||||
#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_MCAST_GRP_UNSPEC,
|
||||
CTRL_ATTR_MCAST_GRP_NAME,
|
||||
CTRL_ATTR_MCAST_GRP_ID,
|
||||
__CTRL_ATTR_MCAST_GRP_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_POLICY_UNSPEC,
|
||||
CTRL_ATTR_POLICY_DO,
|
||||
CTRL_ATTR_POLICY_DUMP,
|
||||
|
||||
__CTRL_ATTR_POLICY_DUMP_MAX,
|
||||
CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1
|
||||
};
|
||||
|
||||
#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
|
||||
|
||||
|
||||
#endif /* _UAPI__LINUX_GENERIC_NETLINK_H */
|
@ -83,6 +83,7 @@ basic_sources = files('''
|
||||
linux/can/vxcan.h
|
||||
linux/fib_rules.h
|
||||
linux/fou.h
|
||||
linux/genetlink.h
|
||||
linux/hdlc/ioctl.h
|
||||
linux/if.h
|
||||
linux/if_addr.h
|
||||
|
@ -132,19 +132,23 @@ libsystemd_sources = files('''
|
||||
sd-device/sd-device.c
|
||||
sd-hwdb/hwdb-internal.h
|
||||
sd-hwdb/sd-hwdb.c
|
||||
sd-netlink/generic-netlink.c
|
||||
sd-netlink/generic-netlink.h
|
||||
sd-netlink/netlink-genl.c
|
||||
sd-netlink/netlink-genl.h
|
||||
sd-netlink/netlink-internal.h
|
||||
sd-netlink/netlink-message-nfnl.c
|
||||
sd-netlink/netlink-message-rtnl.c
|
||||
sd-netlink/netlink-message.c
|
||||
sd-netlink/netlink-slot.c
|
||||
sd-netlink/netlink-slot.h
|
||||
sd-netlink/netlink-socket.c
|
||||
sd-netlink/netlink-types-genl.c
|
||||
sd-netlink/netlink-types-internal.h
|
||||
sd-netlink/netlink-types-nfnl.c
|
||||
sd-netlink/netlink-types-rtnl.c
|
||||
sd-netlink/netlink-types.c
|
||||
sd-netlink/netlink-types.h
|
||||
sd-netlink/netlink-util.c
|
||||
sd-netlink/netlink-util.h
|
||||
sd-netlink/nfnl-message.c
|
||||
sd-netlink/rtnl-message.c
|
||||
sd-netlink/sd-netlink.c
|
||||
sd-network/network-util.c
|
||||
sd-network/network-util.h
|
||||
|
@ -1,179 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "generic-netlink.h"
|
||||
#include "netlink-internal.h"
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
uint8_t version;
|
||||
} genl_family;
|
||||
|
||||
static const genl_family genl_families[] = {
|
||||
[SD_GENL_ID_CTRL] = { .name = "", .version = 1 },
|
||||
[SD_GENL_WIREGUARD] = { .name = "wireguard", .version = 1 },
|
||||
[SD_GENL_FOU] = { .name = "fou", .version = 1 },
|
||||
[SD_GENL_L2TP] = { .name = "l2tp", .version = 1 },
|
||||
[SD_GENL_MACSEC] = { .name = "macsec", .version = 1 },
|
||||
[SD_GENL_NL80211] = { .name = "nl80211", .version = 1 },
|
||||
[SD_GENL_BATADV] = { .name = "batadv", .version = 1 },
|
||||
};
|
||||
|
||||
int sd_genl_socket_open(sd_netlink **ret) {
|
||||
return netlink_open_family(ret, NETLINK_GENERIC);
|
||||
}
|
||||
|
||||
static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *genl_cmd_type, *nl_type;
|
||||
const NLTypeSystem *type_system;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = message_new_empty(nl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
size = NLMSG_SPACE(sizeof(struct genlmsghdr));
|
||||
m->hdr = malloc0(size);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
type_get_type_system(genl_cmd_type, &type_system);
|
||||
|
||||
r = type_system_get_type(type_system, &nl_type, cmd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->hdr->nlmsg_len = size;
|
||||
m->hdr->nlmsg_type = nlmsg_type;
|
||||
|
||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||
|
||||
*(struct genlmsghdr *) NLMSG_DATA(m->hdr) = (struct genlmsghdr) {
|
||||
.cmd = cmd,
|
||||
.version = genl_families[family].version,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lookup_nlmsg_type(sd_netlink *nl, sd_genl_family_t family, uint16_t *ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
uint16_t u;
|
||||
void *v;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
if (family == SD_GENL_ID_CTRL) {
|
||||
*ret = GENL_ID_CTRL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
v = hashmap_get(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family));
|
||||
if (v) {
|
||||
*ret = PTR_TO_UINT(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = genl_message_new(nl, SD_GENL_ID_CTRL, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_string(req, CTRL_ATTR_FAMILY_NAME, genl_families[family].name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(nl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_u16(reply, CTRL_ATTR_FAMILY_ID, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_to_nlmsg_type, NULL, INT_TO_PTR(family), UINT_TO_PTR(u));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->nlmsg_type_to_genl_family, NULL, UINT_TO_PTR(u), INT_TO_PTR(family));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret) {
|
||||
uint16_t nlmsg_type = 0; /* Unnecessary initialization to appease gcc */
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = lookup_nlmsg_type(nl, family, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return genl_message_new(nl, family, nlmsg_type, cmd, ret);
|
||||
}
|
||||
|
||||
int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t nlmsg_type, sd_genl_family_t *ret) {
|
||||
void *p;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
if (nlmsg_type == NLMSG_ERROR)
|
||||
*ret = SD_GENL_ERROR;
|
||||
else if (nlmsg_type == NLMSG_DONE)
|
||||
*ret = SD_GENL_DONE;
|
||||
else if (nlmsg_type == GENL_ID_CTRL)
|
||||
*ret = SD_GENL_ID_CTRL;
|
||||
else {
|
||||
p = hashmap_get(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(nlmsg_type));
|
||||
if (!p)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*ret = PTR_TO_INT(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret) {
|
||||
uint16_t nlmsg_type;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return nlmsg_type_to_genl_family(nl, nlmsg_type, ret);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family_t *ret);
|
473
src/libsystemd/sd-netlink/netlink-genl.c
Normal file
473
src/libsystemd/sd-netlink/netlink-genl.c
Normal file
@ -0,0 +1,473 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-types.h"
|
||||
|
||||
typedef struct GenericNetlinkFamily {
|
||||
sd_netlink *genl;
|
||||
|
||||
const NLTypeSystem *type_system;
|
||||
|
||||
uint16_t id; /* a.k.a nlmsg_type */
|
||||
char *name;
|
||||
uint32_t version;
|
||||
uint32_t additional_header_size;
|
||||
Hashmap *multicast_group_by_name;
|
||||
} GenericNetlinkFamily;
|
||||
|
||||
static const GenericNetlinkFamily nlctrl_static = {
|
||||
.id = GENL_ID_CTRL,
|
||||
.name = (char*) CTRL_GENL_NAME,
|
||||
.version = 0x01,
|
||||
};
|
||||
|
||||
static GenericNetlinkFamily *genl_family_free(GenericNetlinkFamily *f) {
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
if (f->genl) {
|
||||
if (f->id > 0)
|
||||
hashmap_remove(f->genl->genl_family_by_id, UINT_TO_PTR(f->id));
|
||||
if (f->name)
|
||||
hashmap_remove(f->genl->genl_family_by_name, f->name);
|
||||
}
|
||||
|
||||
free(f->name);
|
||||
hashmap_free(f->multicast_group_by_name);
|
||||
|
||||
return mfree(f);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(GenericNetlinkFamily*, genl_family_free);
|
||||
|
||||
void genl_clear_family(sd_netlink *nl) {
|
||||
assert(nl);
|
||||
|
||||
nl->genl_family_by_name = hashmap_free_with_destructor(nl->genl_family_by_name, genl_family_free);
|
||||
nl->genl_family_by_id = hashmap_free_with_destructor(nl->genl_family_by_id, genl_family_free);
|
||||
}
|
||||
|
||||
static int genl_family_new(
|
||||
sd_netlink *nl,
|
||||
const char *expected_family_name,
|
||||
const NLTypeSystem *type_system,
|
||||
sd_netlink_message *message,
|
||||
const GenericNetlinkFamily **ret) {
|
||||
|
||||
_cleanup_(genl_family_freep) GenericNetlinkFamily *f = NULL;
|
||||
const char *family_name;
|
||||
uint8_t cmd;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(expected_family_name);
|
||||
assert(type_system);
|
||||
assert(message);
|
||||
assert(ret);
|
||||
|
||||
f = new(GenericNetlinkFamily, 1);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
*f = (GenericNetlinkFamily) {
|
||||
.type_system = type_system,
|
||||
};
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
int e;
|
||||
|
||||
/* Kernel does not support the genl family? To prevent from resolving the family name
|
||||
* again, let's store the family with zero id to indicate that. */
|
||||
|
||||
e = sd_netlink_message_get_errno(message);
|
||||
if (e >= 0) /* Huh? */
|
||||
e = -EOPNOTSUPP;
|
||||
|
||||
f->name = strdup(expected_family_name);
|
||||
if (!f->name)
|
||||
return e;
|
||||
|
||||
if (hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f) < 0)
|
||||
return e;
|
||||
|
||||
f->genl = nl;
|
||||
TAKE_PTR(f);
|
||||
return e;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_family_name(nl, message, &family_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(family_name, CTRL_GENL_NAME))
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_genl_message_get_command(nl, message, &cmd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (cmd != CTRL_CMD_NEWFAMILY)
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_netlink_message_read_u16(message, CTRL_ATTR_FAMILY_ID, &f->id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(message, CTRL_ATTR_FAMILY_NAME, &f->name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(f->name, expected_family_name))
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, CTRL_ATTR_VERSION, &f->version);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, CTRL_ATTR_HDRSIZE, &f->additional_header_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_enter_container(message, CTRL_ATTR_MCAST_GROUPS);
|
||||
if (r >= 0) {
|
||||
for (uint16_t i = 0; i < UINT16_MAX; i++) {
|
||||
_cleanup_free_ char *group_name = NULL;
|
||||
uint32_t group_id;
|
||||
|
||||
r = sd_netlink_message_enter_array(message, i + 1);
|
||||
if (r == -ENODATA)
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, CTRL_ATTR_MCAST_GRP_ID, &group_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(message, CTRL_ATTR_MCAST_GRP_NAME, &group_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (group_id == 0) {
|
||||
log_debug("sd-netlink: received multicast group '%s' for generic netlink family '%s' with id == 0, ignoring",
|
||||
group_name, f->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(&f->multicast_group_by_name, &string_hash_ops_free, group_name, UINT32_TO_PTR(group_id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(group_name);
|
||||
}
|
||||
|
||||
r = sd_netlink_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_id, NULL, UINT_TO_PTR(f->id), f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f);
|
||||
if (r < 0) {
|
||||
hashmap_remove(nl->genl_family_by_id, UINT_TO_PTR(f->id));
|
||||
return r;
|
||||
}
|
||||
|
||||
f->genl = nl;
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const NLTypeSystem *genl_family_get_type_system(const GenericNetlinkFamily *family) {
|
||||
assert(family);
|
||||
|
||||
if (family->type_system)
|
||||
return family->type_system;
|
||||
|
||||
return genl_get_type_system_by_name(family->name);
|
||||
}
|
||||
|
||||
static int genl_message_new(
|
||||
sd_netlink *nl,
|
||||
const GenericNetlinkFamily *family,
|
||||
uint8_t cmd,
|
||||
sd_netlink_message **ret) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLTypeSystem *type_system;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(family);
|
||||
assert(ret);
|
||||
|
||||
type_system = genl_family_get_type_system(family);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = message_new_full(nl, family->id, type_system,
|
||||
sizeof(struct genlmsghdr) + family->additional_header_size, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*(struct genlmsghdr *) NLMSG_DATA(m->hdr) = (struct genlmsghdr) {
|
||||
.cmd = cmd,
|
||||
.version = family->version,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int genl_family_get_by_name_internal(
|
||||
sd_netlink *nl,
|
||||
const GenericNetlinkFamily *ctrl,
|
||||
const char *name,
|
||||
const GenericNetlinkFamily **ret) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
const NLTypeSystem *type_system;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ctrl);
|
||||
assert(name);
|
||||
assert(ret);
|
||||
|
||||
type_system = genl_get_type_system_by_name(name);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = genl_message_new(nl, ctrl, CTRL_CMD_GETFAMILY, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_string(req, CTRL_ATTR_FAMILY_NAME, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(nl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return genl_family_new(nl, name, type_system, reply, ret);
|
||||
}
|
||||
|
||||
static int genl_family_get_by_name(sd_netlink *nl, const char *name, const GenericNetlinkFamily **ret) {
|
||||
const GenericNetlinkFamily *f, *ctrl;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(name);
|
||||
assert(ret);
|
||||
|
||||
f = hashmap_get(nl->genl_family_by_name, name);
|
||||
if (f) {
|
||||
if (f->id == 0) /* kernel does not support the family. */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(name, CTRL_GENL_NAME))
|
||||
return genl_family_get_by_name_internal(nl, &nlctrl_static, CTRL_GENL_NAME, ret);
|
||||
|
||||
ctrl = hashmap_get(nl->genl_family_by_name, CTRL_GENL_NAME);
|
||||
if (!ctrl) {
|
||||
r = genl_family_get_by_name_internal(nl, &nlctrl_static, CTRL_GENL_NAME, &ctrl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return genl_family_get_by_name_internal(nl, ctrl, name, ret);
|
||||
}
|
||||
|
||||
static int genl_family_get_by_id(sd_netlink *nl, uint16_t id, const GenericNetlinkFamily **ret) {
|
||||
const GenericNetlinkFamily *f;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
f = hashmap_get(nl->genl_family_by_id, UINT_TO_PTR(id));
|
||||
if (f) {
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (id == GENL_ID_CTRL) {
|
||||
*ret = &nlctrl_static;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int genl_get_type_system_and_header_size(
|
||||
sd_netlink *nl,
|
||||
uint16_t id,
|
||||
const NLTypeSystem **ret_type_system,
|
||||
size_t *ret_header_size) {
|
||||
|
||||
const GenericNetlinkFamily *f;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
|
||||
r = genl_family_get_by_id(nl, id, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_type_system) {
|
||||
const NLTypeSystem *t;
|
||||
|
||||
t = genl_family_get_type_system(f);
|
||||
if (!t)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*ret_type_system = t;
|
||||
}
|
||||
if (ret_header_size)
|
||||
*ret_header_size = sizeof(struct genlmsghdr) + f->additional_header_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_new(sd_netlink *nl, const char *family_name, uint8_t cmd, sd_netlink_message **ret) {
|
||||
const GenericNetlinkFamily *family;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(family_name, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = genl_family_get_by_name(nl, family_name, &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return genl_message_new(nl, family, cmd, ret);
|
||||
}
|
||||
|
||||
int sd_genl_message_get_family_name(sd_netlink *nl, sd_netlink_message *m, const char **ret) {
|
||||
const GenericNetlinkFamily *family;
|
||||
uint16_t nlmsg_type;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_family_get_by_id(nl, nlmsg_type, &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = family->name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_get_command(sd_netlink *nl, sd_netlink_message *m, uint8_t *ret) {
|
||||
struct genlmsghdr *h;
|
||||
uint16_t nlmsg_type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_get_type_system_and_header_size(nl, nlmsg_type, NULL, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (m->hdr->nlmsg_len < NLMSG_LENGTH(size))
|
||||
return -EBADMSG;
|
||||
|
||||
h = NLMSG_DATA(m->hdr);
|
||||
|
||||
*ret = h->cmd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int genl_family_get_multicast_group_id_by_name(const GenericNetlinkFamily *f, const char *name, uint32_t *ret) {
|
||||
void *p;
|
||||
|
||||
assert(f);
|
||||
assert(name);
|
||||
|
||||
p = hashmap_get(f->multicast_group_by_name, name);
|
||||
if (!p)
|
||||
return -ENOENT;
|
||||
|
||||
if (ret)
|
||||
*ret = PTR_TO_UINT32(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_add_match(
|
||||
sd_netlink *nl,
|
||||
sd_netlink_slot **ret_slot,
|
||||
const char *family_name,
|
||||
const char *multicast_group_name,
|
||||
uint8_t command,
|
||||
sd_netlink_message_handler_t callback,
|
||||
sd_netlink_destroy_t destroy_callback,
|
||||
void *userdata,
|
||||
const char *description) {
|
||||
|
||||
const GenericNetlinkFamily *f;
|
||||
uint32_t multicast_group_id;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(callback, -EINVAL);
|
||||
assert_return(family_name, -EINVAL);
|
||||
assert_return(multicast_group_name, -EINVAL);
|
||||
|
||||
/* If command == 0, then all commands belonging to the multicast group trigger the callback. */
|
||||
|
||||
r = genl_family_get_by_name(nl, family_name, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_family_get_multicast_group_id_by_name(f, multicast_group_name, &multicast_group_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return netlink_add_match_internal(nl, ret_slot, &multicast_group_id, 1, f->id, command,
|
||||
callback, destroy_callback, userdata, description);
|
||||
}
|
||||
|
||||
int sd_genl_socket_open(sd_netlink **ret) {
|
||||
return netlink_open_family(ret, NETLINK_GENERIC);
|
||||
}
|
8
src/libsystemd/sd-netlink/netlink-genl.h
Normal file
8
src/libsystemd/sd-netlink/netlink-genl.h
Normal file
@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#define CTRL_GENL_NAME "nlctrl"
|
||||
|
||||
void genl_clear_family(sd_netlink *nl);
|
@ -10,11 +10,11 @@
|
||||
#include "prioq.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
|
||||
#define NETLINK_DEFAULT_TIMEOUT_USEC ((usec_t) (25 * USEC_PER_SEC))
|
||||
|
||||
#define RTNL_RQUEUE_MAX 64*1024
|
||||
#define NETLINK_RQUEUE_MAX 64*1024
|
||||
|
||||
#define RTNL_CONTAINER_DEPTH 32
|
||||
#define NETLINK_CONTAINER_DEPTH 32
|
||||
|
||||
struct reply_callback {
|
||||
sd_netlink_message_handler_t callback;
|
||||
@ -25,7 +25,10 @@ struct reply_callback {
|
||||
|
||||
struct match_callback {
|
||||
sd_netlink_message_handler_t callback;
|
||||
uint32_t *groups;
|
||||
size_t n_groups;
|
||||
uint16_t type;
|
||||
uint8_t cmd; /* used by genl */
|
||||
|
||||
LIST_FIELDS(struct match_callback, match_callbacks);
|
||||
};
|
||||
@ -95,8 +98,8 @@ struct sd_netlink {
|
||||
sd_event_source *exit_event_source;
|
||||
sd_event *event;
|
||||
|
||||
Hashmap *genl_family_to_nlmsg_type;
|
||||
Hashmap *nlmsg_type_to_genl_family;
|
||||
Hashmap *genl_family_by_name;
|
||||
Hashmap *genl_family_by_id;
|
||||
};
|
||||
|
||||
struct netlink_attribute {
|
||||
@ -118,7 +121,7 @@ struct sd_netlink_message {
|
||||
int protocol;
|
||||
|
||||
struct nlmsghdr *hdr;
|
||||
struct netlink_container containers[RTNL_CONTAINER_DEPTH];
|
||||
struct netlink_container containers[NETLINK_CONTAINER_DEPTH];
|
||||
unsigned n_containers; /* number of containers */
|
||||
bool sealed:1;
|
||||
bool broadcast:1;
|
||||
@ -126,10 +129,22 @@ struct sd_netlink_message {
|
||||
sd_netlink_message *next; /* next in a chain of multi-part messages */
|
||||
};
|
||||
|
||||
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type);
|
||||
int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret);
|
||||
int message_new_empty(sd_netlink *nl, sd_netlink_message **ret);
|
||||
int message_new_full(
|
||||
sd_netlink *nl,
|
||||
uint16_t nlmsg_type,
|
||||
const NLTypeSystem *type_system,
|
||||
size_t header_size,
|
||||
sd_netlink_message **ret);
|
||||
int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type);
|
||||
int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret);
|
||||
uint32_t message_get_serial(sd_netlink_message *m);
|
||||
void message_seal(sd_netlink_message *m);
|
||||
|
||||
int netlink_open_family(sd_netlink **ret, int family);
|
||||
bool netlink_pid_changed(sd_netlink *nl);
|
||||
int netlink_rqueue_make_room(sd_netlink *nl);
|
||||
int netlink_rqueue_partial_make_room(sd_netlink *nl);
|
||||
|
||||
int socket_open(int family);
|
||||
int socket_bind(sd_netlink *nl);
|
||||
@ -139,9 +154,18 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m);
|
||||
int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount);
|
||||
int socket_read_message(sd_netlink *nl);
|
||||
|
||||
int rtnl_rqueue_make_room(sd_netlink *rtnl);
|
||||
int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
|
||||
int netlink_add_match_internal(
|
||||
sd_netlink *nl,
|
||||
sd_netlink_slot **ret_slot,
|
||||
const uint32_t *groups,
|
||||
size_t n_groups,
|
||||
uint16_t type,
|
||||
uint8_t cmd,
|
||||
sd_netlink_message_handler_t callback,
|
||||
sd_netlink_destroy_t destroy_callback,
|
||||
void *userdata,
|
||||
const char *description);
|
||||
|
||||
/* Make sure callbacks don't destroy the rtnl connection */
|
||||
#define NETLINK_DONT_DESTROY(rtnl) \
|
||||
_cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
|
||||
/* Make sure callbacks don't destroy the netlink connection */
|
||||
#define NETLINK_DONT_DESTROY(nl) \
|
||||
_cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##nl = sd_netlink_ref(nl)
|
||||
|
@ -13,48 +13,20 @@
|
||||
#include "format-util.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-types.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t type, uint16_t flags) {
|
||||
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t msg_type, uint16_t flags) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *nl_type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(nfnl, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = type_system_root_get_type(nfnl, &nl_type, NFNL_SUBSYS_NFTABLES);
|
||||
r = message_new(nfnl, &m, NFNL_SUBSYS_NFTABLES << 8 | msg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
r = message_new_empty(nfnl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
size = NLMSG_SPACE(type_get_size(nl_type));
|
||||
|
||||
assert(size >= sizeof(struct nlmsghdr));
|
||||
m->hdr = malloc0(size);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
m->hdr->nlmsg_flags = NLM_F_REQUEST | flags;
|
||||
|
||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||
|
||||
r = type_system_get_type_system(m->containers[0].type_system,
|
||||
&m->containers[0].type_system,
|
||||
type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->hdr->nlmsg_len = size;
|
||||
m->hdr->nlmsg_type = NFNL_SUBSYS_NFTABLES << 8 | type;
|
||||
m->hdr->nlmsg_flags |= flags;
|
||||
|
||||
*(struct nfgenmsg*) NLMSG_DATA(m->hdr) = (struct nfgenmsg) {
|
||||
.nfgen_family = family,
|
||||
@ -66,11 +38,11 @@ static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int famil
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int v) {
|
||||
static int nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, uint16_t msg_type) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = message_new(nfnl, &m, v);
|
||||
r = message_new(nfnl, &m, NFNL_SUBSYS_NONE << 8 | msg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -81,26 +53,31 @@ static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret) {
|
||||
return sd_nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_BEGIN);
|
||||
return nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_BEGIN);
|
||||
}
|
||||
|
||||
int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret) {
|
||||
return sd_nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_END);
|
||||
return nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_END);
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table, const char *chain,
|
||||
const char *type,
|
||||
uint8_t hook, int prio) {
|
||||
int sd_nfnl_nft_message_new_basechain(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *chain,
|
||||
const char *type,
|
||||
uint8_t hook,
|
||||
int prio) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWCHAIN, NLM_F_CREATE | NLM_F_ACK);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWCHAIN, NLM_F_CREATE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -136,12 +113,16 @@ int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table) {
|
||||
int sd_nfnl_nft_message_del_table(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELTABLE, NLM_F_CREATE | NLM_F_ACK);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELTABLE, NLM_F_CREATE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -153,12 +134,16 @@ int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, uint16_t flags) {
|
||||
int sd_nfnl_nft_message_new_table(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWTABLE, NLM_F_CREATE | flags);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWTABLE, NLM_F_CREATE | NLM_F_EXCL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -170,12 +155,17 @@ int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_rule(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *chain) {
|
||||
int sd_nfnl_nft_message_new_rule(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *chain) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWRULE, NLM_F_CREATE | NLM_F_ACK);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWRULE, NLM_F_CREATE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -191,13 +181,19 @@ int sd_nfnl_nft_message_new_rule(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_set(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *set_name,
|
||||
uint32_t set_id, uint32_t klen) {
|
||||
int sd_nfnl_nft_message_new_set(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *set_name,
|
||||
uint32_t set_id,
|
||||
uint32_t klen) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSET, NLM_F_CREATE | NLM_F_ACK);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSET, NLM_F_CREATE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -216,16 +212,22 @@ int sd_nfnl_nft_message_new_set(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
r = sd_netlink_message_append_u32(m, NFTA_SET_KEY_LEN, htobe32(klen));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_setelems_begin(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *set_name) {
|
||||
int sd_nfnl_nft_message_new_setelems_begin(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *set_name) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSETELEM, NLM_F_CREATE | NLM_F_ACK);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSETELEM, NLM_F_CREATE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -245,12 +247,17 @@ int sd_nfnl_nft_message_new_setelems_begin(sd_netlink *nfnl, sd_netlink_message
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_del_setelems_begin(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *set_name) {
|
||||
int sd_nfnl_nft_message_del_setelems_begin(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *set_name) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELSETELEM, NLM_F_ACK);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELSETELEM, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -271,7 +278,9 @@ int sd_nfnl_nft_message_del_setelems_begin(sd_netlink *nfnl, sd_netlink_message
|
||||
}
|
||||
|
||||
static int sd_nfnl_add_data(sd_netlink_message *m, uint16_t attr, const void *data, uint32_t dlen) {
|
||||
int r = sd_netlink_message_open_container(m, attr);
|
||||
int r;
|
||||
|
||||
r = sd_netlink_message_open_container(m, attr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -282,9 +291,14 @@ static int sd_nfnl_add_data(sd_netlink_message *m, uint16_t attr, const void *da
|
||||
return sd_netlink_message_close_container(m); /* attr */
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m, uint32_t num,
|
||||
const void *key, uint32_t klen,
|
||||
const void *data, uint32_t dlen) {
|
||||
int sd_nfnl_nft_message_add_setelem(
|
||||
sd_netlink_message *m,
|
||||
uint32_t num,
|
||||
const void *key,
|
||||
uint32_t klen,
|
||||
const void *data,
|
||||
uint32_t dlen) {
|
||||
|
||||
int r;
|
||||
|
||||
r = sd_netlink_message_open_array(m, num);
|
||||
@ -301,7 +315,8 @@ int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m, uint32_t num,
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
|
||||
cancel:
|
||||
sd_netlink_message_cancel_array(m);
|
||||
return r;
|
@ -271,13 +271,13 @@ int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
}
|
||||
|
||||
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
uint16_t nhmsg_type, int nh_family,
|
||||
uint16_t nlmsg_type, int nh_family,
|
||||
unsigned char nh_protocol) {
|
||||
struct nhmsg *nhm;
|
||||
int r;
|
||||
|
||||
assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
|
||||
switch(nhmsg_type) {
|
||||
assert_return(rtnl_message_type_is_nexthop(nlmsg_type), -EINVAL);
|
||||
switch(nlmsg_type) {
|
||||
case RTM_DELNEXTHOP:
|
||||
assert_return(nh_family == AF_UNSPEC, -EINVAL);
|
||||
_fallthrough_;
|
||||
@ -292,11 +292,11 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
}
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = message_new(rtnl, ret, nhmsg_type);
|
||||
r = message_new(rtnl, ret, nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (nhmsg_type == RTM_NEWNEXTHOP)
|
||||
if (nlmsg_type == RTM_NEWNEXTHOP)
|
||||
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
|
||||
|
||||
nhm = NLMSG_DATA((*ret)->hdr);
|
@ -20,15 +20,14 @@
|
||||
#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
|
||||
#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
|
||||
|
||||
int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
|
||||
int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) {
|
||||
sd_netlink_message *m;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert(nl);
|
||||
assert(ret);
|
||||
|
||||
/* Note that 'rtnl' is currently unused, if we start using it internally
|
||||
we must take care to avoid problems due to mutual references between
|
||||
buses and their queued messages. See sd-bus.
|
||||
*/
|
||||
/* Note that 'nl' is currently unused, if we start using it internally we must take care to
|
||||
* avoid problems due to mutual references between buses and their queued messages. See sd-bus. */
|
||||
|
||||
m = new(sd_netlink_message, 1);
|
||||
if (!m)
|
||||
@ -36,48 +35,80 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
|
||||
|
||||
*m = (sd_netlink_message) {
|
||||
.n_ref = 1,
|
||||
.protocol = rtnl->protocol,
|
||||
.protocol = nl->protocol,
|
||||
.sealed = false,
|
||||
};
|
||||
|
||||
*ret = m;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
|
||||
int message_new_full(
|
||||
sd_netlink *nl,
|
||||
uint16_t nlmsg_type,
|
||||
const NLTypeSystem *type_system,
|
||||
size_t header_size,
|
||||
sd_netlink_message **ret) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *nl_type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(rtnl, -EINVAL);
|
||||
|
||||
r = type_system_root_get_type(rtnl, &nl_type, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
r = message_new_empty(rtnl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
size = NLMSG_SPACE(type_get_size(nl_type));
|
||||
assert(nl);
|
||||
assert(type_system);
|
||||
assert(ret);
|
||||
|
||||
size = NLMSG_SPACE(header_size);
|
||||
assert(size >= sizeof(struct nlmsghdr));
|
||||
|
||||
r = message_new_empty(nl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->containers[0].type_system = type_system;
|
||||
|
||||
m->hdr = malloc0(size);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||
m->hdr->nlmsg_len = size;
|
||||
m->hdr->nlmsg_type = type;
|
||||
m->hdr->nlmsg_type = nlmsg_type;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type) {
|
||||
const NLTypeSystem *type_system;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = type_system_root_get_type_system_and_header_size(nl, type, &type_system, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return message_new_full(nl, type, type_system, size, ret);
|
||||
}
|
||||
|
||||
int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret) {
|
||||
struct nlmsgerr *err;
|
||||
int r;
|
||||
|
||||
assert(error <= 0);
|
||||
|
||||
r = message_new(nl, ret, NLMSG_ERROR);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
message_seal(*ret);
|
||||
(*ret)->hdr->nlmsg_seq = serial;
|
||||
|
||||
err = NLMSG_DATA((*ret)->hdr);
|
||||
err->error = error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -184,13 +215,12 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
|
||||
|
||||
static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) {
|
||||
const NLType *type;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type = type_system_get_type(m->containers[m->n_containers].type_system, attribute_type);
|
||||
if (!type)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (type_get_type(type) != data_type)
|
||||
return -EINVAL;
|
||||
@ -538,7 +568,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
/* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED);
|
||||
if (r < 0) {
|
||||
@ -553,22 +583,23 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system_union = type_system_get_type_system_union(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type);
|
||||
if (!type_system_union)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = type_system_union_protocol_get_type_system(type_system_union,
|
||||
&m->containers[m->n_containers + 1].type_system,
|
||||
family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&m->containers[m->n_containers + 1].type_system,
|
||||
type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
m->containers[m->n_containers + 1].type_system =
|
||||
type_system_union_get_type_system_by_protocol(
|
||||
type_system_union,
|
||||
family);
|
||||
} else
|
||||
m->containers[m->n_containers + 1].type_system =
|
||||
type_system_get_type_system(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type);
|
||||
if (!m->containers[m->n_containers + 1].type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
|
||||
if (r < 0)
|
||||
@ -585,19 +616,22 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system_union = type_system_get_type_system_union(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type);
|
||||
if (!type_system_union)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = type_system_union_get_type_system(type_system_union,
|
||||
&m->containers[m->n_containers + 1].type_system,
|
||||
key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
m->containers[m->n_containers + 1].type_system =
|
||||
type_system_union_get_type_system_by_string(
|
||||
type_system_union,
|
||||
key);
|
||||
if (!m->containers[m->n_containers + 1].type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = sd_netlink_message_append_string(m, type_system_union->match, key);
|
||||
r = sd_netlink_message_append_string(m, type_system_union_get_match_attribute(type_system_union), key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -628,7 +662,7 @@ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
|
||||
if (r < 0)
|
||||
@ -673,7 +707,7 @@ static int netlink_message_read_internal(
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->sealed, -EPERM);
|
||||
|
||||
assert(m->n_containers < RTNL_CONTAINER_DEPTH);
|
||||
assert(m->n_containers < NETLINK_CONTAINER_DEPTH);
|
||||
|
||||
if (!m->containers[m->n_containers].attributes)
|
||||
return -ENODATA;
|
||||
@ -1008,26 +1042,26 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
|
||||
assert_return(m->n_containers < NETLINK_CONTAINER_DEPTH, -EINVAL);
|
||||
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system,
|
||||
&nl_type,
|
||||
container_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
nl_type = type_system_get_type(
|
||||
m->containers[m->n_containers].type_system,
|
||||
container_type);
|
||||
if (!nl_type)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&type_system,
|
||||
container_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system = type_system_get_type_system(
|
||||
m->containers[m->n_containers].type_system,
|
||||
container_type);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = type_system_get_type(type_system, &nl_type, type_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
nl_type = type_system_get_type(type_system, type_id);
|
||||
if (!nl_type)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_STRING)
|
||||
return -EINVAL;
|
||||
@ -1079,7 +1113,7 @@ static int netlink_container_parse(sd_netlink_message *m,
|
||||
return -ENOMEM;
|
||||
|
||||
if (attributes[type].offset != 0)
|
||||
log_debug("rtnl: message parse - overwriting repeated attribute");
|
||||
log_debug("sd-netlink: message parse - overwriting repeated attribute");
|
||||
|
||||
attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
|
||||
attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
|
||||
@ -1104,61 +1138,62 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system,
|
||||
&nl_type,
|
||||
type_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
nl_type = type_system_get_type(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type_id);
|
||||
if (!nl_type)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
type = type_get_type(nl_type);
|
||||
|
||||
if (type == NETLINK_TYPE_NESTED) {
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&type_system,
|
||||
type_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system = type_system_get_type_system(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type_id);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
} else if (type == NETLINK_TYPE_UNION) {
|
||||
const NLTypeSystemUnion *type_system_union;
|
||||
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system,
|
||||
&type_system_union,
|
||||
type_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system_union = type_system_get_type_system_union(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type_id);
|
||||
if (!type_system_union)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (type_system_union->match_type) {
|
||||
case NL_MATCH_SIBLING:
|
||||
{
|
||||
switch (type_system_union_get_match_type(type_system_union)) {
|
||||
case NL_MATCH_SIBLING: {
|
||||
const char *key;
|
||||
|
||||
r = sd_netlink_message_read_string(m, type_system_union->match, &key);
|
||||
r = sd_netlink_message_read_string(
|
||||
m,
|
||||
type_system_union_get_match_attribute(type_system_union),
|
||||
&key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = type_system_union_get_type_system(type_system_union,
|
||||
&type_system,
|
||||
key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system = type_system_union_get_type_system_by_string(
|
||||
type_system_union,
|
||||
key);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
break;
|
||||
}
|
||||
case NL_MATCH_PROTOCOL:
|
||||
{
|
||||
case NL_MATCH_PROTOCOL: {
|
||||
int family;
|
||||
|
||||
r = sd_rtnl_message_get_family(m, &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = type_system_union_protocol_get_type_system(type_system_union,
|
||||
&type_system,
|
||||
family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
type_system = type_system_union_get_type_system_by_protocol(
|
||||
type_system_union,
|
||||
family);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1195,7 +1230,7 @@ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
|
||||
r = netlink_message_read_internal(m, type_id, &container, NULL);
|
||||
if (r < 0)
|
||||
@ -1231,7 +1266,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t rtnl_message_get_serial(sd_netlink_message *m) {
|
||||
uint32_t message_get_serial(sd_netlink_message *m) {
|
||||
assert(m);
|
||||
assert(m->hdr);
|
||||
|
||||
@ -1280,18 +1315,15 @@ static int netlink_message_parse_error(sd_netlink_message *m) {
|
||||
NLMSG_PAYLOAD(m->hdr, hlen));
|
||||
}
|
||||
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
|
||||
const NLType *nl_type;
|
||||
uint16_t type;
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(genl || m->protocol != NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(nl, -EINVAL);
|
||||
|
||||
/* don't allow appending to message once parsed */
|
||||
if (!m->sealed)
|
||||
rtnl_message_seal(m);
|
||||
message_seal(m);
|
||||
|
||||
for (unsigned i = 1; i <= m->n_containers; i++)
|
||||
m->containers[i].attributes = mfree(m->containers[i].attributes);
|
||||
@ -1304,37 +1336,22 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
|
||||
|
||||
assert(m->hdr);
|
||||
|
||||
r = type_system_root_get_type(genl, &nl_type, m->hdr->nlmsg_type);
|
||||
r = type_system_root_get_type_system_and_header_size(nl, m->hdr->nlmsg_type,
|
||||
&m->containers[0].type_system, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
type = type_get_type(nl_type);
|
||||
size = type_get_size(nl_type);
|
||||
if (sd_netlink_message_is_error(m))
|
||||
return netlink_message_parse_error(m);
|
||||
|
||||
if (type == NETLINK_TYPE_NESTED) {
|
||||
const NLTypeSystem *type_system;
|
||||
|
||||
type_get_type_system(nl_type, &type_system);
|
||||
|
||||
m->containers[0].type_system = type_system;
|
||||
|
||||
if (sd_netlink_message_is_error(m))
|
||||
r = netlink_message_parse_error(m);
|
||||
else
|
||||
r = netlink_container_parse(m,
|
||||
&m->containers[m->n_containers],
|
||||
(struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
|
||||
NLMSG_PAYLOAD(m->hdr, size));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return netlink_container_parse(m,
|
||||
&m->containers[0],
|
||||
(struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
|
||||
NLMSG_PAYLOAD(m->hdr, size));
|
||||
}
|
||||
|
||||
void rtnl_message_seal(sd_netlink_message *m) {
|
||||
void message_seal(sd_netlink_message *m) {
|
||||
assert(m);
|
||||
assert(!m->sealed);
|
||||
|
||||
m->sealed = true;
|
||||
}
|
||||
|
@ -70,25 +70,11 @@ void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref) {
|
||||
case NETLINK_MATCH_CALLBACK:
|
||||
LIST_REMOVE(match_callbacks, nl->match_callbacks, &slot->match_callback);
|
||||
|
||||
switch (slot->match_callback.type) {
|
||||
case RTM_NEWLINK:
|
||||
case RTM_DELLINK:
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_LINK);
|
||||
for (size_t i = 0; i < slot->match_callback.n_groups; i++)
|
||||
(void) socket_broadcast_group_unref(nl, slot->match_callback.groups[i]);
|
||||
|
||||
break;
|
||||
case RTM_NEWADDR:
|
||||
case RTM_DELADDR:
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_IFADDR);
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_IFADDR);
|
||||
|
||||
break;
|
||||
case RTM_NEWROUTE:
|
||||
case RTM_DELROUTE:
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_ROUTE);
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_ROUTE);
|
||||
|
||||
break;
|
||||
}
|
||||
slot->match_callback.n_groups = 0;
|
||||
slot->match_callback.groups = mfree(slot->match_callback.groups);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
@ -238,7 +238,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
|
||||
|
||||
n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
|
||||
if (n == -ENOBUFS)
|
||||
return log_debug_errno(n, "rtnl: kernel receive buffer overrun");
|
||||
return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
|
||||
if (IN_SET(n, -EAGAIN, -EINTR))
|
||||
return 0;
|
||||
if (n < 0)
|
||||
@ -246,7 +246,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
|
||||
|
||||
if (sender.nl.nl_pid != 0) {
|
||||
/* not from the kernel, ignore */
|
||||
log_debug("rtnl: ignoring message from PID %"PRIu32, sender.nl.nl_pid);
|
||||
log_debug("sd-netlink: ignoring message from PID %"PRIu32, sender.nl.nl_pid);
|
||||
|
||||
if (peek) {
|
||||
/* drop the message */
|
||||
@ -276,7 +276,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
|
||||
* If nothing useful was received 0 is returned.
|
||||
* On failure, a negative error code is returned.
|
||||
*/
|
||||
int socket_read_message(sd_netlink *rtnl) {
|
||||
int socket_read_message(sd_netlink *nl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL;
|
||||
bool multi_part = false, done = false;
|
||||
size_t len, allocated;
|
||||
@ -285,25 +285,25 @@ int socket_read_message(sd_netlink *rtnl) {
|
||||
unsigned i = 0;
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(rtnl->rbuffer);
|
||||
assert(nl);
|
||||
assert(nl->rbuffer);
|
||||
|
||||
/* read nothing, just get the pending message size */
|
||||
r = socket_recv_message(rtnl->fd, &iov, NULL, true);
|
||||
r = socket_recv_message(nl->fd, &iov, NULL, true);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
else
|
||||
len = (size_t) r;
|
||||
|
||||
/* make room for the pending message */
|
||||
if (!greedy_realloc((void **)&rtnl->rbuffer, len, sizeof(uint8_t)))
|
||||
if (!greedy_realloc((void**) &nl->rbuffer, len, sizeof(uint8_t)))
|
||||
return -ENOMEM;
|
||||
|
||||
allocated = MALLOC_SIZEOF_SAFE(rtnl->rbuffer);
|
||||
iov = IOVEC_MAKE(rtnl->rbuffer, allocated);
|
||||
allocated = MALLOC_SIZEOF_SAFE(nl->rbuffer);
|
||||
iov = IOVEC_MAKE(nl->rbuffer, allocated);
|
||||
|
||||
/* read the pending message */
|
||||
r = socket_recv_message(rtnl->fd, &iov, &group, false);
|
||||
r = socket_recv_message(nl->fd, &iov, &group, false);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
else
|
||||
@ -313,22 +313,22 @@ int socket_read_message(sd_netlink *rtnl) {
|
||||
/* message did not fit in read buffer */
|
||||
return -EIO;
|
||||
|
||||
if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
|
||||
if (NLMSG_OK(nl->rbuffer, len) && nl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
|
||||
multi_part = true;
|
||||
|
||||
for (i = 0; i < rtnl->rqueue_partial_size; i++)
|
||||
if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
|
||||
rtnl->rbuffer->nlmsg_seq) {
|
||||
first = rtnl->rqueue_partial[i];
|
||||
for (i = 0; i < nl->rqueue_partial_size; i++)
|
||||
if (message_get_serial(nl->rqueue_partial[i]) ==
|
||||
nl->rbuffer->nlmsg_seq) {
|
||||
first = nl->rqueue_partial[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct nlmsghdr *new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
||||
for (struct nlmsghdr *new_msg = nl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *nl_type;
|
||||
size_t size;
|
||||
|
||||
if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
|
||||
if (!group && new_msg->nlmsg_pid != nl->sockaddr.nl.nl_pid)
|
||||
/* not broadcast and not for us */
|
||||
continue;
|
||||
|
||||
@ -346,7 +346,7 @@ int socket_read_message(sd_netlink *rtnl) {
|
||||
}
|
||||
|
||||
/* check that we support this message type */
|
||||
r = type_system_root_get_type(rtnl, &nl_type, new_msg->nlmsg_type);
|
||||
r = type_system_root_get_type_system_and_header_size(nl, new_msg->nlmsg_type, NULL, &size);
|
||||
if (r < 0) {
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug("sd-netlink: ignored message with unknown type: %i",
|
||||
@ -356,12 +356,12 @@ int socket_read_message(sd_netlink *rtnl) {
|
||||
}
|
||||
|
||||
/* check that the size matches the message type */
|
||||
if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) {
|
||||
if (new_msg->nlmsg_len < NLMSG_LENGTH(size)) {
|
||||
log_debug("sd-netlink: message is shorter than expected, dropping");
|
||||
continue;
|
||||
}
|
||||
|
||||
r = message_new_empty(rtnl, &m);
|
||||
r = message_new_empty(nl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -372,7 +372,7 @@ int socket_read_message(sd_netlink *rtnl) {
|
||||
return -ENOMEM;
|
||||
|
||||
/* seal and parse the top-level message */
|
||||
r = sd_netlink_message_rewind(m, rtnl);
|
||||
r = sd_netlink_message_rewind(m, nl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -390,31 +390,31 @@ int socket_read_message(sd_netlink *rtnl) {
|
||||
|
||||
if (!multi_part || done) {
|
||||
/* we got a complete message, push it on the read queue */
|
||||
r = rtnl_rqueue_make_room(rtnl);
|
||||
r = netlink_rqueue_make_room(nl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rtnl->rqueue[rtnl->rqueue_size++] = TAKE_PTR(first);
|
||||
nl->rqueue[nl->rqueue_size++] = TAKE_PTR(first);
|
||||
|
||||
if (multi_part && (i < rtnl->rqueue_partial_size)) {
|
||||
if (multi_part && (i < nl->rqueue_partial_size)) {
|
||||
/* remove the message form the partial read queue */
|
||||
memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
|
||||
sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1));
|
||||
rtnl->rqueue_partial_size--;
|
||||
memmove(nl->rqueue_partial + i, nl->rqueue_partial + i + 1,
|
||||
sizeof(sd_netlink_message*) * (nl->rqueue_partial_size - i - 1));
|
||||
nl->rqueue_partial_size--;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
/* we only got a partial multi-part message, push it on the
|
||||
partial read queue */
|
||||
if (i < rtnl->rqueue_partial_size)
|
||||
rtnl->rqueue_partial[i] = TAKE_PTR(first);
|
||||
if (i < nl->rqueue_partial_size)
|
||||
nl->rqueue_partial[i] = TAKE_PTR(first);
|
||||
else {
|
||||
r = rtnl_rqueue_partial_make_room(rtnl);
|
||||
r = netlink_rqueue_partial_make_room(nl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = TAKE_PTR(first);
|
||||
nl->rqueue_partial[nl->rqueue_partial_size++] = TAKE_PTR(first);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
234
src/libsystemd/sd-netlink/netlink-types-genl.c
Normal file
234
src/libsystemd/sd-netlink/netlink-types-genl.c
Normal file
@ -0,0 +1,234 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/batman_adv.h>
|
||||
#include <linux/fou.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/wireguard.h>
|
||||
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-types-internal.h"
|
||||
|
||||
/***************** genl ctrl type systems *****************/
|
||||
static const NLType genl_ctrl_mcast_group_types[] = {
|
||||
[CTRL_ATTR_MCAST_GRP_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[CTRL_ATTR_MCAST_GRP_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_ctrl_mcast_group);
|
||||
|
||||
static const NLType genl_ctrl_ops_types[] = {
|
||||
[CTRL_ATTR_OP_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_OP_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_ctrl_ops);
|
||||
|
||||
static const NLType genl_ctrl_types[] = {
|
||||
[CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[CTRL_ATTR_VERSION] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_HDRSIZE] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_MAXATTR] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_OPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_ops_type_system },
|
||||
[CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_mcast_group_type_system },
|
||||
/*
|
||||
[CTRL_ATTR_POLICY] = { .type = NETLINK_TYPE_NESTED, },
|
||||
[CTRL_ATTR_OP_POLICY] = { .type = NETLINK_TYPE_NESTED, }
|
||||
*/
|
||||
[CTRL_ATTR_OP] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
/***************** genl batadv type systems *****************/
|
||||
static const NLType genl_batadv_types[] = {
|
||||
[BATADV_ATTR_VERSION] = { .type = NETLINK_TYPE_STRING },
|
||||
[BATADV_ATTR_ALGO_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[BATADV_ATTR_MESH_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_MESH_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
|
||||
[BATADV_ATTR_MESH_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_HARD_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_HARD_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
|
||||
[BATADV_ATTR_HARD_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_ORIG_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_TPMETER_RESULT] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_TPMETER_BYTES] = { .type = NETLINK_TYPE_U64 },
|
||||
[BATADV_ATTR_TPMETER_COOKIE] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_PAD] = { .type = NETLINK_TYPE_UNSPEC },
|
||||
[BATADV_ATTR_ACTIVE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[BATADV_ATTR_TT_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_TT_TTVN] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_TT_LAST_TTVN] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_TT_CRC32] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_TT_VID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_TT_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_FLAG_BEST] = { .type = NETLINK_TYPE_FLAG },
|
||||
[BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_NEIGH_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_TQ] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_THROUGHPUT] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_BANDWIDTH_UP] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_ROUTER] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_BLA_OWN] = { .type = NETLINK_TYPE_FLAG },
|
||||
[BATADV_ATTR_BLA_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_BLA_VID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_BLA_BACKBONE] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_BLA_CRC] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_DAT_CACHE_IP4ADDRESS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_DAT_CACHE_HWADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_DAT_CACHE_VID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_MCAST_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_VLANID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_AGGREGATED_OGMS_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_AP_ISOLATION_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_ISOLATION_MARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_ISOLATION_MASK] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_BONDING_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_FRAGMENTATION_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_GW_BANDWIDTH_DOWN] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_GW_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_GW_SEL_CLASS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_HOP_PENALTY] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_LOG_LEVEL] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_MULTICAST_FANOUT] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_NETWORK_CODING_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_ORIG_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_ELP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
/***************** genl fou type systems *****************/
|
||||
static const NLType genl_fou_types[] = {
|
||||
[FOU_ATTR_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[FOU_ATTR_AF] = { .type = NETLINK_TYPE_U8 },
|
||||
[FOU_ATTR_IPPROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[FOU_ATTR_TYPE] = { .type = NETLINK_TYPE_U8 },
|
||||
[FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
|
||||
[FOU_ATTR_LOCAL_V4] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FOU_ATTR_PEER_V4] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FOU_ATTR_LOCAL_V6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FOU_ATTR_PEER_V6] = { .type = NETLINK_TYPE_IN_ADDR},
|
||||
[FOU_ATTR_PEER_PORT] = { .type = NETLINK_TYPE_U16},
|
||||
[FOU_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32},
|
||||
};
|
||||
|
||||
/***************** genl l2tp type systems *****************/
|
||||
static const NLType genl_l2tp_types[] = {
|
||||
[L2TP_ATTR_PW_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_OFFSET] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_DATA_SEQ] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_L2SPEC_TYPE] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_L2SPEC_LEN] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_PROTO_VERSION] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_IFNAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[L2TP_ATTR_CONN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_PEER_CONN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_SESSION_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_PEER_SESSION_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_RECV_SEQ] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_SEND_SEQ] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_LNS_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_USING_IPSEC] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_FD] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_IP_SADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_IP_DADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_UDP_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_UDP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_IP6_SADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_IP6_DADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_FLAG },
|
||||
[L2TP_ATTR_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
/***************** genl macsec type systems *****************/
|
||||
static const NLType genl_macsec_rxsc_types[] = {
|
||||
[MACSEC_RXSC_ATTR_SCI] = { .type = NETLINK_TYPE_U64 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_macsec_rxsc);
|
||||
|
||||
static const NLType genl_macsec_sa_types[] = {
|
||||
[MACSEC_SA_ATTR_AN] = { .type = NETLINK_TYPE_U8 },
|
||||
[MACSEC_SA_ATTR_ACTIVE] = { .type = NETLINK_TYPE_U8 },
|
||||
[MACSEC_SA_ATTR_PN] = { .type = NETLINK_TYPE_U32 },
|
||||
[MACSEC_SA_ATTR_KEYID] = { .size = MACSEC_KEYID_LEN },
|
||||
[MACSEC_SA_ATTR_KEY] = { .size = MACSEC_MAX_KEY_LEN },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_macsec_sa);
|
||||
|
||||
static const NLType genl_macsec_types[] = {
|
||||
[MACSEC_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[MACSEC_ATTR_RXSC_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_rxsc_type_system },
|
||||
[MACSEC_ATTR_SA_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_type_system },
|
||||
};
|
||||
|
||||
/***************** genl nl80211 type systems *****************/
|
||||
static const NLType genl_nl80211_types[] = {
|
||||
[NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[NL80211_ATTR_SSID] = { .type = NETLINK_TYPE_STRING },
|
||||
[NL80211_ATTR_IFTYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
/***************** genl wireguard type systems *****************/
|
||||
static const NLType genl_wireguard_allowedip_types[] = {
|
||||
[WGALLOWEDIP_A_FAMILY] = { .type = NETLINK_TYPE_U16 },
|
||||
[WGALLOWEDIP_A_IPADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[WGALLOWEDIP_A_CIDR_MASK] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_wireguard_allowedip);
|
||||
|
||||
static const NLType genl_wireguard_peer_types[] = {
|
||||
[WGPEER_A_PUBLIC_KEY] = { .size = WG_KEY_LEN },
|
||||
[WGPEER_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGPEER_A_PRESHARED_KEY] = { .size = WG_KEY_LEN },
|
||||
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 },
|
||||
[WGPEER_A_ENDPOINT] = { .type = NETLINK_TYPE_SOCKADDR },
|
||||
[WGPEER_A_ALLOWEDIPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_wireguard_peer);
|
||||
|
||||
static const NLType genl_wireguard_types[] = {
|
||||
[WGDEVICE_A_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGDEVICE_A_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
|
||||
[WGDEVICE_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGDEVICE_A_PRIVATE_KEY] = { .size = WG_KEY_LEN },
|
||||
[WGDEVICE_A_LISTEN_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[WGDEVICE_A_FWMARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGDEVICE_A_PEERS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_peer_type_system },
|
||||
};
|
||||
|
||||
/***************** genl families *****************/
|
||||
static const NLTypeSystemUnionElement genl_type_systems[] = {
|
||||
{ .name = CTRL_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_ctrl), },
|
||||
{ .name = BATADV_NL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_batadv), },
|
||||
{ .name = FOU_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_fou), },
|
||||
{ .name = L2TP_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_l2tp), },
|
||||
{ .name = MACSEC_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_macsec), },
|
||||
{ .name = NL80211_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_nl80211), },
|
||||
{ .name = WG_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_wireguard), },
|
||||
};
|
||||
|
||||
/* This is the root type system union, so match_attribute is not necessary. */
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(genl, 0);
|
||||
|
||||
const NLTypeSystem *genl_get_type_system_by_name(const char *name) {
|
||||
return type_system_union_get_type_system_by_string(&genl_type_system_union, name);
|
||||
}
|
49
src/libsystemd/sd-netlink/netlink-types-internal.h
Normal file
49
src/libsystemd/sd-netlink/netlink-types-internal.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
#include "netlink-types.h"
|
||||
|
||||
struct NLType {
|
||||
uint16_t type;
|
||||
size_t size;
|
||||
const NLTypeSystem *type_system;
|
||||
const NLTypeSystemUnion *type_system_union;
|
||||
};
|
||||
|
||||
struct NLTypeSystem {
|
||||
uint16_t count;
|
||||
const NLType *types;
|
||||
};
|
||||
|
||||
typedef struct NLTypeSystemUnionElement {
|
||||
union {
|
||||
int protocol;
|
||||
const char *name;
|
||||
};
|
||||
NLTypeSystem type_system;
|
||||
} NLTypeSystemUnionElement;
|
||||
|
||||
struct NLTypeSystemUnion {
|
||||
size_t count;
|
||||
const NLTypeSystemUnionElement *elements;
|
||||
NLMatchType match_type;
|
||||
uint16_t match_attribute;
|
||||
};
|
||||
|
||||
#define TYPE_SYSTEM_FROM_TYPE(name) \
|
||||
{ .count = ELEMENTSOF(name##_types), .types = name##_types }
|
||||
#define DEFINE_TYPE_SYSTEM(name) \
|
||||
static const NLTypeSystem name##_type_system = TYPE_SYSTEM_FROM_TYPE(name)
|
||||
|
||||
#define _DEFINE_TYPE_SYSTEM_UNION(name, type, attr) \
|
||||
static const NLTypeSystemUnion name##_type_system_union = { \
|
||||
.count = ELEMENTSOF(name##_type_systems), \
|
||||
.elements = name##_type_systems, \
|
||||
.match_type = type, \
|
||||
.match_attribute = attr, \
|
||||
}
|
||||
#define DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(name) \
|
||||
_DEFINE_TYPE_SYSTEM_UNION(name, NL_MATCH_PROTOCOL, 0)
|
||||
#define DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(name, attr) \
|
||||
_DEFINE_TYPE_SYSTEM_UNION(name, NL_MATCH_SIBLING, attr)
|
197
src/libsystemd/sd-netlink/netlink-types-nfnl.c
Normal file
197
src/libsystemd/sd-netlink/netlink-types-nfnl.c
Normal file
@ -0,0 +1,197 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
|
||||
#include "netlink-types-internal.h"
|
||||
#include "string-table.h"
|
||||
|
||||
static const NLType nfnl_nft_table_types[] = {
|
||||
[NFTA_TABLE_NAME] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_TABLE_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_table);
|
||||
|
||||
static const NLType nfnl_nft_chain_hook_types[] = {
|
||||
[NFTA_HOOK_HOOKNUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_HOOK_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_HOOK_DEV] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_chain_hook);
|
||||
|
||||
static const NLType nfnl_nft_chain_types[] = {
|
||||
[NFTA_CHAIN_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_CHAIN_NAME] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_CHAIN_HOOK] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_hook_type_system },
|
||||
[NFTA_CHAIN_TYPE] = { .type = NETLINK_TYPE_STRING, .size = 16 },
|
||||
[NFTA_CHAIN_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_chain);
|
||||
|
||||
static const NLType nfnl_nft_expr_meta_types[] = {
|
||||
[NFTA_META_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_META_KEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_META_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_payload_types[] = {
|
||||
[NFTA_PAYLOAD_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_PAYLOAD_BASE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_PAYLOAD_OFFSET] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_PAYLOAD_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_nat_types[] = {
|
||||
[NFTA_NAT_TYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_FAMILY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_ADDR_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_ADDR_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_data_types[] = {
|
||||
[NFTA_DATA_VALUE] = { .type = NETLINK_TYPE_BINARY },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_data);
|
||||
|
||||
static const NLType nfnl_nft_expr_bitwise_types[] = {
|
||||
[NFTA_BITWISE_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_BITWISE_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_BITWISE_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_BITWISE_MASK] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
[NFTA_BITWISE_XOR] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_cmp_types[] = {
|
||||
[NFTA_CMP_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_CMP_OP] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_CMP_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_fib_types[] = {
|
||||
[NFTA_FIB_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_FIB_RESULT] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_FIB_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_lookup_types[] = {
|
||||
[NFTA_LOOKUP_SET] = { .type = NETLINK_TYPE_STRING },
|
||||
[NFTA_LOOKUP_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_LOOKUP_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_LOOKUP_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_masq_types[] = {
|
||||
[NFTA_MASQ_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement nfnl_expr_data_type_systems[] = {
|
||||
{ .name = "bitwise", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_bitwise), },
|
||||
{ .name = "cmp", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_cmp), },
|
||||
{ .name = "fib", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_fib), },
|
||||
{ .name = "lookup", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_lookup), },
|
||||
{ .name = "masq", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_masq), },
|
||||
{ .name = "meta", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_meta), },
|
||||
{ .name = "nat", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_nat), },
|
||||
{ .name = "payload", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_payload), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(nfnl_expr_data, NFTA_EXPR_NAME);
|
||||
|
||||
static const NLType nfnl_nft_rule_expr_types[] = {
|
||||
[NFTA_EXPR_NAME] = { .type = NETLINK_TYPE_STRING, .size = 16 },
|
||||
[NFTA_EXPR_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &nfnl_expr_data_type_system_union },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_rule_expr);
|
||||
|
||||
static const NLType nfnl_nft_rule_types[] = {
|
||||
[NFTA_RULE_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_RULE_CHAIN] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_RULE_EXPRESSIONS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_expr_type_system }
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_rule);
|
||||
|
||||
static const NLType nfnl_nft_set_types[] = {
|
||||
[NFTA_SET_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_NAME] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_KEY_TYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_KEY_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_DATA_TYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_DATA_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_POLICY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_set);
|
||||
|
||||
static const NLType nfnl_nft_setelem_types[] = {
|
||||
[NFTA_SET_ELEM_KEY] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
[NFTA_SET_ELEM_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
[NFTA_SET_ELEM_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_setelem);
|
||||
|
||||
static const NLType nfnl_nft_setelem_list_types[] = {
|
||||
[NFTA_SET_ELEM_LIST_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_ELEM_LIST_SET] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_setelem_list);
|
||||
|
||||
static const NLType nfnl_subsys_nft_types [] = {
|
||||
[NFT_MSG_DELTABLE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWTABLE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWCHAIN] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWSET] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_set_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_DELSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_subsys_nft);
|
||||
|
||||
static const NLType nfnl_msg_batch_types [] = {
|
||||
[NFNL_BATCH_GENID] = { .type = NETLINK_TYPE_U32 }
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_msg_batch);
|
||||
|
||||
static const NLType nfnl_subsys_none_types[] = {
|
||||
[NFNL_MSG_BATCH_BEGIN] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFNL_MSG_BATCH_END] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_subsys_none);
|
||||
|
||||
static const NLType nfnl_types[] = {
|
||||
[NFNL_SUBSYS_NONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_none_type_system },
|
||||
[NFNL_SUBSYS_NFTABLES] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_nft_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl);
|
||||
|
||||
const NLType *nfnl_get_type(uint16_t nlmsg_type) {
|
||||
const NLTypeSystem *subsys;
|
||||
|
||||
subsys = type_system_get_type_system(&nfnl_type_system, nlmsg_type >> 8);
|
||||
if (!subsys)
|
||||
return NULL;
|
||||
|
||||
return type_system_get_type(subsys, nlmsg_type & ((1U << 8) - 1));
|
||||
}
|
872
src/libsystemd/sd-netlink/netlink-types-rtnl.c
Normal file
872
src/libsystemd/sd-netlink/netlink-types-rtnl.c
Normal file
@ -0,0 +1,872 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/batman_adv.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/can/vxcan.h>
|
||||
#include <linux/fib_rules.h>
|
||||
#include <linux/fou.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/if_addrlabel.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/if_tunnel.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/nexthop.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/veth.h>
|
||||
#include <linux/wireguard.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "netlink-types-internal.h"
|
||||
#include "string-table.h"
|
||||
|
||||
/* Maximum ARP IP target defined in kernel */
|
||||
#define BOND_MAX_ARP_TARGETS 16
|
||||
|
||||
typedef enum {
|
||||
BOND_ARP_TARGETS_0,
|
||||
BOND_ARP_TARGETS_1,
|
||||
BOND_ARP_TARGETS_2,
|
||||
BOND_ARP_TARGETS_3,
|
||||
BOND_ARP_TARGETS_4,
|
||||
BOND_ARP_TARGETS_5,
|
||||
BOND_ARP_TARGETS_6,
|
||||
BOND_ARP_TARGETS_7,
|
||||
BOND_ARP_TARGETS_8,
|
||||
BOND_ARP_TARGETS_9,
|
||||
BOND_ARP_TARGETS_10,
|
||||
BOND_ARP_TARGETS_11,
|
||||
BOND_ARP_TARGETS_12,
|
||||
BOND_ARP_TARGETS_13,
|
||||
BOND_ARP_TARGETS_14,
|
||||
BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS,
|
||||
} BondArpTargets;
|
||||
|
||||
static const NLTypeSystem rtnl_link_type_system;
|
||||
|
||||
static const NLType rtnl_link_info_data_batadv_types[] = {
|
||||
[IFLA_BATADV_ALGO_NAME] = { .type = NETLINK_TYPE_STRING, .size = 20 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_veth_types[] = {
|
||||
[VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vxcan_types[] = {
|
||||
[VXCAN_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipvlan_types[] = {
|
||||
[IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_macvlan_macaddr_types[] = {
|
||||
[IFLA_MACVLAN_MACADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_macvlan_macaddr);
|
||||
|
||||
static const NLType rtnl_link_info_data_macvlan_types[] = {
|
||||
[IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_MACVLAN_MACADDR_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_MACADDR_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_macvlan_macaddr_type_system },
|
||||
[IFLA_MACVLAN_MACADDR_COUNT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NETLINK_TYPE_REJECT },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bridge_types[] = {
|
||||
[IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_AGEING_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_STP_STATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_VLAN_FILTERING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_ROOT_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_ROOT_PATH_COST] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_TOPOLOGY_CHANGE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_TOPOLOGY_CHANGE_DETECTED] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_HELLO_TIMER] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_TCN_TIMER] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_TOPOLOGY_CHANGE_TIMER] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_GC_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_GROUP_ADDR] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_FDB_FLUSH] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_ROUTER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_SNOOPING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_QUERY_USE_IFADDR] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_QUERIER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_HASH_ELASTICITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MCAST_HASH_MAX] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_LAST_MEMBER_CNT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MCAST_STARTUP_QUERY_CNT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_LAST_MEMBER_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_MEMBERSHIP_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_QUERIER_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_QUERY_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_NF_CALL_IPTABLES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_NF_CALL_IP6TABLES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_NF_CALL_ARPTABLES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_VLAN_DEFAULT_PVID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_IGMP_VERSION] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_vlan_qos_map_types[] = {
|
||||
[IFLA_VLAN_QOS_MAPPING] = { .size = sizeof(struct ifla_vlan_qos_mapping) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vlan_qos_map);
|
||||
|
||||
static const NLType rtnl_link_info_data_vlan_types[] = {
|
||||
[IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_VLAN_FLAGS] = { .size = sizeof(struct ifla_vlan_flags) },
|
||||
[IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vlan_qos_map_type_system },
|
||||
[IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vlan_qos_map_type_system },
|
||||
[IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vxlan_types[] = {
|
||||
[IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32},
|
||||
[IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_VXLAN_GROUP6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_LOCAL6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_REMCSUM_TX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_REMCSUM_RX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_GBP] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_COLLECT_METADATA] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_LABEL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_GPE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_TTL_INHERIT] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_DF] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_bond_arp_target_types[] = {
|
||||
[BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_bond_arp_target);
|
||||
|
||||
static const NLType rtnl_link_info_data_bond_types[] = {
|
||||
[IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_target_type_system },
|
||||
[IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED },
|
||||
[IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BOND_AD_USER_PORT_KEY] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_iptun_types[] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipgre_types[] = {
|
||||
[IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ERSPAN_INDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipvti_types[] = {
|
||||
[IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ip6tnl_types[] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vrf_types[] = {
|
||||
[IFLA_VRF_TABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_geneve_types[] = {
|
||||
[IFLA_GENEVE_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GENEVE_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GENEVE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GENEVE_REMOTE6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GENEVE_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_LABEL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GENEVE_TTL_INHERIT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_DF] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_can_types[] = {
|
||||
[IFLA_CAN_BITTIMING] = { .size = sizeof(struct can_bittiming) },
|
||||
[IFLA_CAN_RESTART_MS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_CAN_CTRLMODE] = { .size = sizeof(struct can_ctrlmode) },
|
||||
[IFLA_CAN_TERMINATION] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_macsec_types[] = {
|
||||
[IFLA_MACSEC_SCI] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_MACSEC_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_MACSEC_ICV_LEN] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_CIPHER_SUITE] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_MACSEC_WINDOW] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACSEC_ENCODING_SA] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_ENCRYPT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_PROTECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_INC_SCI] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_ES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_SCB] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_REPLAY_PROTECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_VALIDATION] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_xfrm_types[] = {
|
||||
[IFLA_XFRM_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_XFRM_IF_ID] = { .type = NETLINK_TYPE_U32 }
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bareudp_types[] = {
|
||||
[IFLA_BAREUDP_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BAREUDP_ETHERTYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BAREUDP_SRCPORT_MIN] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BAREUDP_MULTIPROTO_MODE] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_link_info_data_type_systems[] = {
|
||||
{ .name = "bareudp", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bareudp), },
|
||||
{ .name = "batadv", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_batadv), },
|
||||
{ .name = "bond", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bond), },
|
||||
{ .name = "bridge", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bridge), },
|
||||
{ .name = "can", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_can), },
|
||||
{ .name = "dummy", },
|
||||
{ .name = "erspan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "geneve", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_geneve), },
|
||||
{ .name = "gre", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "gretap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "ifb", },
|
||||
{ .name = "ip6gre", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "ip6gretap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "ip6tnl", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ip6tnl), },
|
||||
{ .name = "ipip", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_iptun), },
|
||||
{ .name = "ipvlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvlan), },
|
||||
{ .name = "ipvtap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvlan), },
|
||||
{ .name = "macsec", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macsec), },
|
||||
{ .name = "macvlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macvlan), },
|
||||
{ .name = "macvtap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macvlan), },
|
||||
{ .name = "netdevsim", },
|
||||
{ .name = "nlmon", },
|
||||
{ .name = "sit", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_iptun), },
|
||||
{ .name = "vcan", },
|
||||
{ .name = "veth", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_veth), },
|
||||
{ .name = "vlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vlan), },
|
||||
{ .name = "vrf", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vrf), },
|
||||
{ .name = "vti", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvti), },
|
||||
{ .name = "vti6", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvti), },
|
||||
{ .name = "vxcan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vxcan), },
|
||||
{ .name = "vxlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vxlan), },
|
||||
{ .name = "wireguard", },
|
||||
{ .name = "xfrm", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_xfrm), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_link_info_data, IFLA_INFO_KIND);
|
||||
|
||||
static const NLType rtnl_link_info_types[] = {
|
||||
[IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union },
|
||||
/*
|
||||
[IFLA_INFO_XSTATS],
|
||||
[IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED },
|
||||
*/
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_link_info);
|
||||
|
||||
static const struct NLType rtnl_prot_info_bridge_port_types[] = {
|
||||
[IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_ROOT_ID] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BRIDGE_ID] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_DESIGNATED_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_DESIGNATED_COST] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_NO] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_CONFIG_PENDING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MESSAGE_AGE_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_FORWARD_DELAY_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_HOLD_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_FLUSH] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PAD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_VLAN_TUNNEL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_ISOLATED] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BACKUP_PORT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_prot_info_type_systems[] = {
|
||||
{ .protocol = AF_BRIDGE, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_prot_info_bridge_port), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(rtnl_prot_info);
|
||||
|
||||
static const struct NLType rtnl_af_spec_inet6_types[] = {
|
||||
[IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
IFLA_INET6_CONF,
|
||||
IFLA_INET6_STATS,
|
||||
IFLA_INET6_MCAST,
|
||||
IFLA_INET6_CACHEINFO,
|
||||
IFLA_INET6_ICMP6STATS,
|
||||
*/
|
||||
[IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_af_spec_inet6);
|
||||
|
||||
static const NLType rtnl_af_spec_unspec_types[] = {
|
||||
[AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system },
|
||||
};
|
||||
|
||||
static const NLType rtnl_af_spec_bridge_types[] = {
|
||||
[IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRIDGE_VLAN_INFO] = { .size = sizeof(struct bridge_vlan_info) },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_af_spec_type_systems[] = {
|
||||
{ .protocol = AF_UNSPEC, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_af_spec_unspec), },
|
||||
{ .protocol = AF_BRIDGE, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_af_spec_bridge), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(rtnl_af_spec);
|
||||
|
||||
static const NLType rtnl_prop_list_types[] = {
|
||||
[IFLA_ALT_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_prop_list);
|
||||
|
||||
static const NLType rtnl_vf_vlan_list_types[] = {
|
||||
[IFLA_VF_VLAN_INFO] = { .size = sizeof(struct ifla_vf_vlan_info) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vf_vlan_list);
|
||||
|
||||
static const NLType rtnl_vf_info_types[] = {
|
||||
[IFLA_VF_MAC] = { .size = sizeof(struct ifla_vf_mac) },
|
||||
[IFLA_VF_VLAN] = { .size = sizeof(struct ifla_vf_vlan) },
|
||||
[IFLA_VF_VLAN_LIST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_vlan_list_type_system},
|
||||
[IFLA_VF_TX_RATE] = { .size = sizeof(struct ifla_vf_tx_rate) },
|
||||
[IFLA_VF_SPOOFCHK] = { .size = sizeof(struct ifla_vf_spoofchk) },
|
||||
[IFLA_VF_RATE] = { .size = sizeof(struct ifla_vf_rate) },
|
||||
[IFLA_VF_LINK_STATE] = { .size = sizeof(struct ifla_vf_link_state) },
|
||||
[IFLA_VF_RSS_QUERY_EN] = { .size = sizeof(struct ifla_vf_rss_query_en) },
|
||||
[IFLA_VF_TRUST] = { .size = sizeof(struct ifla_vf_trust) },
|
||||
[IFLA_VF_IB_NODE_GUID] = { .size = sizeof(struct ifla_vf_guid) },
|
||||
[IFLA_VF_IB_PORT_GUID] = { .size = sizeof(struct ifla_vf_guid) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vf_info);
|
||||
|
||||
static const NLType rtnl_vfinfo_list_types[] = {
|
||||
[IFLA_VF_INFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_info_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vfinfo_list);
|
||||
|
||||
static const NLType rtnl_link_types[] = {
|
||||
[IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
[IFLA_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_QDISC] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_STATS] = { .size = sizeof(struct rtnl_link_stats) },
|
||||
/*
|
||||
[IFLA_COST],
|
||||
[IFLA_PRIORITY],
|
||||
*/
|
||||
[IFLA_MASTER] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
[IFLA_WIRELESS],
|
||||
*/
|
||||
[IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union },
|
||||
[IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
|
||||
*/
|
||||
[IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system },
|
||||
[IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 },
|
||||
[IFLA_NUM_VF] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VFINFO_LIST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vfinfo_list_type_system },
|
||||
[IFLA_STATS64] = { .size = sizeof(struct rtnl_link_stats64) },
|
||||
/*
|
||||
[IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED },
|
||||
[IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED },
|
||||
*/
|
||||
[IFLA_AF_SPEC] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_af_spec_type_system_union },
|
||||
/*
|
||||
[IFLA_VF_PORTS],
|
||||
[IFLA_PORT_SELF],
|
||||
*/
|
||||
[IFLA_GROUP] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GSO_MAX_SEGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GSO_MAX_SIZE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 },
|
||||
/*
|
||||
[IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
|
||||
*/
|
||||
[IFLA_MIN_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MAX_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_PROP_LIST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_prop_list_type_system },
|
||||
[IFLA_ALT_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_link);
|
||||
|
||||
/* IFA_FLAGS was defined in kernel 3.14, but we still support older
|
||||
* kernels where IFA_MAX is lower. */
|
||||
static const NLType rtnl_address_types[] = {
|
||||
[IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
[IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_ANYCAST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
|
||||
[IFA_MULTICAST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFA_RT_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFA_TARGET_NETNSID] = { .type = NETLINK_TYPE_S32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_address);
|
||||
|
||||
/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
|
||||
|
||||
static const NLType rtnl_route_metrics_types[] = {
|
||||
[RTAX_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_WINDOW] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_RTT] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_RTTVAR] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_SSTHRESH] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_CWND] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_ADVMSS] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_REORDERING] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_HOPLIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_INITCWND] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_FEATURES] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_RTO_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_INITRWND] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_QUICKACK] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_CC_ALGO] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_FASTOPEN_NO_COOKIE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_route_metrics);
|
||||
|
||||
static const NLType rtnl_route_types[] = {
|
||||
[RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_IIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_OIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_METRICS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system},
|
||||
[RTA_MULTIPATH] = { .size = sizeof(struct rtnexthop) },
|
||||
[RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */
|
||||
[RTA_CACHEINFO] = { .size = sizeof(struct rta_cacheinfo) },
|
||||
[RTA_TABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_MARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_MFC_STATS] = { .type = NETLINK_TYPE_U64 },
|
||||
[RTA_VIA] = { /* See struct rtvia */ },
|
||||
[RTA_NEWDST] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_ENCAP] = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
|
||||
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_UID] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_TTL_PROPAGATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_NH_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_route);
|
||||
|
||||
static const NLType rtnl_neigh_types[] = {
|
||||
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NDA_LLADDR] = { /* struct ether_addr, struct in_addr, or struct in6_addr */ },
|
||||
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
|
||||
[NDA_PROBES] = { .type = NETLINK_TYPE_U32 },
|
||||
[NDA_VLAN] = { .type = NETLINK_TYPE_U16 },
|
||||
[NDA_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[NDA_VNI] = { .type = NETLINK_TYPE_U32 },
|
||||
[NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_neigh);
|
||||
|
||||
static const NLType rtnl_addrlabel_types[] = {
|
||||
[IFAL_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
|
||||
[IFAL_LABEL] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_addrlabel);
|
||||
|
||||
static const NLType rtnl_routing_policy_rule_types[] = {
|
||||
[FRA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FRA_SRC] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FRA_IIFNAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[FRA_GOTO] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_FWMARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_FLOW] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_TUN_ID] = { .type = NETLINK_TYPE_U64 },
|
||||
[FRA_SUPPRESS_IFGROUP] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_SUPPRESS_PREFIXLEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_TABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_FWMASK] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_OIFNAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[FRA_PAD] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_L3MDEV] = { .type = NETLINK_TYPE_U8 },
|
||||
[FRA_UID_RANGE] = { .size = sizeof(struct fib_rule_uid_range) },
|
||||
[FRA_PROTOCOL] = { .type = NETLINK_TYPE_U8 },
|
||||
[FRA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[FRA_SPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) },
|
||||
[FRA_DPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_routing_policy_rule);
|
||||
|
||||
static const NLType rtnl_nexthop_types[] = {
|
||||
[NHA_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_GROUP] = { /* array of struct nexthop_grp */ },
|
||||
[NHA_GROUP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NHA_BLACKHOLE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[NHA_OIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NHA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NHA_ENCAP] = { .type = NETLINK_TYPE_NESTED },
|
||||
[NHA_GROUPS] = { .type = NETLINK_TYPE_FLAG },
|
||||
[NHA_MASTER] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_FDB] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_nexthop);
|
||||
|
||||
static const NLType rtnl_tca_option_data_cake_types[] = {
|
||||
[TCA_CAKE_BASE_RATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_CAKE_OVERHEAD] = { .type = NETLINK_TYPE_S32 },
|
||||
[TCA_CAKE_MPU] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_codel_types[] = {
|
||||
[TCA_CODEL_TARGET] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_ECN] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_drr_types[] = {
|
||||
[TCA_DRR_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_ets_quanta_types[] = {
|
||||
[TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32, },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_tca_option_data_ets_quanta);
|
||||
|
||||
static const NLType rtnl_tca_option_data_ets_prio_types[] = {
|
||||
[TCA_ETS_PRIOMAP_BAND] = { .type = NETLINK_TYPE_U8, },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_tca_option_data_ets_prio);
|
||||
|
||||
static const NLType rtnl_tca_option_data_ets_types[] = {
|
||||
[TCA_ETS_NBANDS] = { .type = NETLINK_TYPE_U8 },
|
||||
[TCA_ETS_NSTRICT] = { .type = NETLINK_TYPE_U8 },
|
||||
[TCA_ETS_QUANTA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_quanta_type_system },
|
||||
[TCA_ETS_PRIOMAP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_prio_type_system },
|
||||
[TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_fq_types[] = {
|
||||
[TCA_FQ_PLIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_PLIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_INITIAL_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_RATE_ENABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_DEFAULT_RATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_MAX_RATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_BUCKETS_LOG] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_REFILL_DELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_ORPHAN_MASK] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_fq_codel_types[] = {
|
||||
[TCA_FQ_CODEL_TARGET] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_ECN] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_FLOWS] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_DROP_BATCH_SIZE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_MEMORY_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_fq_pie_types[] = {
|
||||
[TCA_FQ_PIE_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_gred_types[] = {
|
||||
[TCA_GRED_DPS] = { .size = sizeof(struct tc_gred_sopt) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_hhf_types[] = {
|
||||
[TCA_HHF_BACKLOG_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_htb_types[] = {
|
||||
[TCA_HTB_PARMS] = { .size = sizeof(struct tc_htb_opt) },
|
||||
[TCA_HTB_INIT] = { .size = sizeof(struct tc_htb_glob) },
|
||||
[TCA_HTB_CTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_HTB_RTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_HTB_RATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_HTB_CEIL64] = { .type = NETLINK_TYPE_U64 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_pie_types[] = {
|
||||
[TCA_PIE_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_qfq_types[] = {
|
||||
[TCA_QFQ_WEIGHT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_QFQ_LMAX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_sfb_types[] = {
|
||||
[TCA_SFB_PARMS] = { .size = sizeof(struct tc_sfb_qopt) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_tbf_types[] = {
|
||||
[TCA_TBF_PARMS] = { .size = sizeof(struct tc_tbf_qopt) },
|
||||
[TCA_TBF_RTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_TBF_PTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_TBF_RATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_TBF_PRATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_TBF_BURST] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_TBF_PBURST] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_tca_option_data_type_systems[] = {
|
||||
{ .name = "cake", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_cake), },
|
||||
{ .name = "codel", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_codel), },
|
||||
{ .name = "drr", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_drr), },
|
||||
{ .name = "ets", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_ets), },
|
||||
{ .name = "fq", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq), },
|
||||
{ .name = "fq_codel", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq_codel), },
|
||||
{ .name = "fq_pie", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq_pie), },
|
||||
{ .name = "gred", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_gred), },
|
||||
{ .name = "hhf", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_hhf), },
|
||||
{ .name = "htb", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_htb), },
|
||||
{ .name = "pie", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_pie), },
|
||||
{ .name = "qfq", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_qfq), },
|
||||
{ .name = "sfb", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_sfb), },
|
||||
{ .name = "tbf", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_tbf), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_tca_option_data, TCA_KIND);
|
||||
|
||||
static const NLType rtnl_tca_types[] = {
|
||||
[TCA_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[TCA_OPTIONS] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_tca_option_data_type_system_union },
|
||||
[TCA_INGRESS_BLOCK] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_EGRESS_BLOCK] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_tca);
|
||||
|
||||
static const NLType rtnl_mdb_types[] = {
|
||||
[MDBA_SET_ENTRY] = { .size = sizeof(struct br_port_msg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_mdb);
|
||||
|
||||
static const NLType rtnl_types[] = {
|
||||
[RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_NEWLINKPROP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_DELLINKPROP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_GETLINKPROP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
|
||||
[RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
|
||||
[RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
|
||||
[RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
|
||||
[RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
|
||||
[RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
|
||||
[RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
|
||||
[RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
|
||||
[RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
|
||||
[RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
|
||||
[RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
|
||||
[RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
|
||||
[RTM_NEWRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
|
||||
[RTM_DELRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
|
||||
[RTM_GETRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
|
||||
[RTM_NEWNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) },
|
||||
[RTM_DELNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) },
|
||||
[RTM_GETNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) },
|
||||
[RTM_NEWQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_DELQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_GETQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_NEWTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_DELTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_GETTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_NEWMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) },
|
||||
[RTM_DELMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) },
|
||||
[RTM_GETMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl);
|
||||
|
||||
const NLType *rtnl_get_type(uint16_t nlmsg_type) {
|
||||
return type_system_get_type(&rtnl_type_system, nlmsg_type);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
#include "sd-netlink.h"
|
||||
|
||||
enum {
|
||||
NETLINK_TYPE_UNSPEC,
|
||||
@ -35,105 +35,30 @@ typedef struct NLTypeSystemUnion NLTypeSystemUnion;
|
||||
typedef struct NLTypeSystem NLTypeSystem;
|
||||
typedef struct NLType NLType;
|
||||
|
||||
struct NLTypeSystemUnion {
|
||||
int num;
|
||||
NLMatchType match_type;
|
||||
uint16_t match;
|
||||
int (*lookup)(const char *);
|
||||
const NLTypeSystem *type_systems;
|
||||
};
|
||||
|
||||
extern const NLTypeSystem genl_family_type_system_root;
|
||||
const NLType *rtnl_get_type(uint16_t nlmsg_type);
|
||||
const NLType *nfnl_get_type(uint16_t nlmsg_type);
|
||||
const NLTypeSystem *genl_get_type_system_by_name(const char *name);
|
||||
int genl_get_type_system_and_header_size(
|
||||
sd_netlink *nl,
|
||||
uint16_t id,
|
||||
const NLTypeSystem **ret_type_system,
|
||||
size_t *ret_header_size);
|
||||
|
||||
uint16_t type_get_type(const NLType *type);
|
||||
size_t type_get_size(const NLType *type);
|
||||
void type_get_type_system(const NLType *type, const NLTypeSystem **ret);
|
||||
void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **ret);
|
||||
const NLTypeSystem *type_get_type_system(const NLType *type);
|
||||
const NLTypeSystemUnion *type_get_type_system_union(const NLType *type);
|
||||
|
||||
const NLTypeSystem* type_system_get_root(int protocol);
|
||||
uint16_t type_system_get_count(const NLTypeSystem *type_system);
|
||||
int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type);
|
||||
int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type);
|
||||
int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type);
|
||||
int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type);
|
||||
int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key);
|
||||
int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol);
|
||||
int type_system_root_get_type_system_and_header_size(
|
||||
sd_netlink *nl,
|
||||
uint16_t type,
|
||||
const NLTypeSystem **ret_type_system,
|
||||
size_t *ret_header_size);
|
||||
|
||||
typedef enum NLUnionLinkInfoData {
|
||||
NL_UNION_LINK_INFO_DATA_BOND,
|
||||
NL_UNION_LINK_INFO_DATA_BRIDGE,
|
||||
NL_UNION_LINK_INFO_DATA_VLAN,
|
||||
NL_UNION_LINK_INFO_DATA_VETH,
|
||||
NL_UNION_LINK_INFO_DATA_DUMMY,
|
||||
NL_UNION_LINK_INFO_DATA_MACVLAN,
|
||||
NL_UNION_LINK_INFO_DATA_MACVTAP,
|
||||
NL_UNION_LINK_INFO_DATA_IPVLAN,
|
||||
NL_UNION_LINK_INFO_DATA_IPVTAP,
|
||||
NL_UNION_LINK_INFO_DATA_VXLAN,
|
||||
NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_ERSPAN,
|
||||
NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_SIT_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_VTI_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_VRF,
|
||||
NL_UNION_LINK_INFO_DATA_VCAN,
|
||||
NL_UNION_LINK_INFO_DATA_GENEVE,
|
||||
NL_UNION_LINK_INFO_DATA_VXCAN,
|
||||
NL_UNION_LINK_INFO_DATA_WIREGUARD,
|
||||
NL_UNION_LINK_INFO_DATA_NETDEVSIM,
|
||||
NL_UNION_LINK_INFO_DATA_CAN,
|
||||
NL_UNION_LINK_INFO_DATA_MACSEC,
|
||||
NL_UNION_LINK_INFO_DATA_NLMON,
|
||||
NL_UNION_LINK_INFO_DATA_XFRM,
|
||||
NL_UNION_LINK_INFO_DATA_IFB,
|
||||
NL_UNION_LINK_INFO_DATA_BAREUDP,
|
||||
NL_UNION_LINK_INFO_DATA_BATADV,
|
||||
_NL_UNION_LINK_INFO_DATA_MAX,
|
||||
_NL_UNION_LINK_INFO_DATA_INVALID = -EINVAL,
|
||||
} NLUnionLinkInfoData;
|
||||
|
||||
const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_;
|
||||
NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_;
|
||||
|
||||
typedef enum NLUnionTCAOptionData {
|
||||
NL_UNION_TCA_OPTION_DATA_CAKE,
|
||||
NL_UNION_TCA_OPTION_DATA_CODEL,
|
||||
NL_UNION_TCA_OPTION_DATA_DRR,
|
||||
NL_UNION_TCA_OPTION_DATA_ETS,
|
||||
NL_UNION_TCA_OPTION_DATA_FQ,
|
||||
NL_UNION_TCA_OPTION_DATA_FQ_CODEL,
|
||||
NL_UNION_TCA_OPTION_DATA_FQ_PIE,
|
||||
NL_UNION_TCA_OPTION_DATA_GRED,
|
||||
NL_UNION_TCA_OPTION_DATA_HHF,
|
||||
NL_UNION_TCA_OPTION_DATA_HTB,
|
||||
NL_UNION_TCA_OPTION_DATA_PIE,
|
||||
NL_UNION_TCA_OPTION_DATA_QFQ,
|
||||
NL_UNION_TCA_OPTION_DATA_SFB,
|
||||
NL_UNION_TCA_OPTION_DATA_TBF,
|
||||
_NL_UNION_TCA_OPTION_DATA_MAX,
|
||||
_NL_UNION_TCA_OPTION_DATA_INVALID = -EINVAL,
|
||||
} NLUnionTCAOptionData;
|
||||
|
||||
const char *nl_union_tca_option_data_to_string(NLUnionTCAOptionData p) _const_;
|
||||
NLUnionTCAOptionData nl_union_tca_option_data_from_string(const char *p) _pure_;
|
||||
|
||||
typedef enum NLUnionNFTExprData {
|
||||
NL_UNION_NFT_EXPR_DATA_BITWISE,
|
||||
NL_UNION_NFT_EXPR_DATA_CMP,
|
||||
NL_UNION_NFT_EXPR_DATA_FIB,
|
||||
NL_UNION_NFT_EXPR_DATA_LOOKUP,
|
||||
NL_UNION_NFT_EXPR_DATA_PAYLOAD,
|
||||
NL_UNION_NFT_EXPR_DATA_MASQ,
|
||||
NL_UNION_NFT_EXPR_DATA_META,
|
||||
NL_UNION_NFT_EXPR_DATA_NAT,
|
||||
_NL_UNION_NFT_EXPR_DATA_MAX,
|
||||
_NL_UNION_NFT_EXPR_DATA_INVALID = -EINVAL,
|
||||
} NLUnionNFTExprData;
|
||||
|
||||
const char *nl_union_nft_expr_data_to_string(NLUnionNFTExprData p) _const_;
|
||||
NLUnionNFTExprData nl_union_nft_expr_data_from_string(const char *p) _pure_;
|
||||
const NLType *type_system_get_type(const NLTypeSystem *type_system, uint16_t type);
|
||||
const NLTypeSystem *type_system_get_type_system(const NLTypeSystem *type_system, uint16_t type);
|
||||
const NLTypeSystemUnion *type_system_get_type_system_union(const NLTypeSystem *type_system, uint16_t type);
|
||||
NLMatchType type_system_union_get_match_type(const NLTypeSystemUnion *type_system_union);
|
||||
uint16_t type_system_union_get_match_attribute(const NLTypeSystemUnion *type_system_union);
|
||||
const NLTypeSystem *type_system_union_get_type_system_by_string(const NLTypeSystemUnion *type_system_union, const char *key);
|
||||
const NLTypeSystem *type_system_union_get_type_system_by_protocol(const NLTypeSystemUnion *type_system_union, uint16_t protocol);
|
||||
|
@ -400,25 +400,6 @@ int rtnl_get_link_info(sd_netlink **rtnl, int ifindex, unsigned short *ret_iftyp
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret) {
|
||||
struct nlmsgerr *err;
|
||||
int r;
|
||||
|
||||
assert(error <= 0);
|
||||
|
||||
r = message_new(rtnl, ret, NLMSG_ERROR);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rtnl_message_seal(*ret);
|
||||
(*ret)->hdr->nlmsg_seq = serial;
|
||||
|
||||
err = NLMSG_DATA((*ret)->hdr);
|
||||
err->error = error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_log_parse_error(int r) {
|
||||
return log_error_errno(r, "Failed to parse netlink message: %m");
|
||||
}
|
||||
|
@ -29,10 +29,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free);
|
||||
|
||||
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret);
|
||||
|
||||
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret);
|
||||
uint32_t rtnl_message_get_serial(sd_netlink_message *m);
|
||||
void rtnl_message_seal(sd_netlink_message *m);
|
||||
|
||||
static inline bool rtnl_message_type_is_neigh(uint16_t type) {
|
||||
return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,31 +2,40 @@
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/fou.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "macro.h"
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "util.h"
|
||||
#include "tests.h"
|
||||
|
||||
static void test_message_link_bridge(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
uint32_t cost;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
|
||||
assert_se(sd_rtnl_message_link_set_family(message, AF_BRIDGE) >= 0);
|
||||
assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0);
|
||||
assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(message) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_rewind(message, NULL) >= 0);
|
||||
assert_se(sd_netlink_message_rewind(message, rtnl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0);
|
||||
assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
|
||||
@ -40,6 +49,8 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
|
||||
const char *name_out;
|
||||
struct ether_addr mac_out;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
/* we'd really like to test NEWLINK, but let's not mess with the running kernel */
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
|
||||
|
||||
@ -57,6 +68,8 @@ static void test_link_get(sd_netlink *rtnl, int ifindex) {
|
||||
uint32_t u32_data;
|
||||
struct ether_addr eth_data;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
|
||||
assert_se(m);
|
||||
|
||||
@ -83,6 +96,8 @@ static void test_address_get(sd_netlink *rtnl, int ifindex) {
|
||||
struct ifa_cacheinfo cache;
|
||||
const char *label;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
|
||||
assert_se(m);
|
||||
assert_se(sd_netlink_message_request_dump(m, true) >= 0);
|
||||
@ -100,6 +115,8 @@ static void test_route(sd_netlink *rtnl) {
|
||||
uint32_t index = 2, u32_data;
|
||||
int r;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
r = sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
|
||||
@ -120,7 +137,7 @@ static void test_route(sd_netlink *rtnl) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(sd_netlink_message_rewind(req, NULL) >= 0);
|
||||
assert_se(sd_netlink_message_rewind(req, rtnl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
|
||||
assert_se(addr_data.s_addr == addr.s_addr);
|
||||
@ -134,6 +151,8 @@ static void test_route(sd_netlink *rtnl) {
|
||||
static void test_multiple(void) {
|
||||
sd_netlink *rtnl1, *rtnl2;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl1) >= 0);
|
||||
assert_se(sd_netlink_open(&rtnl2) >= 0);
|
||||
|
||||
@ -164,6 +183,8 @@ static void test_event_loop(int ifindex) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
ifname = strdup("lo2");
|
||||
assert_se(ifname);
|
||||
|
||||
@ -194,6 +215,8 @@ static void test_async(int ifindex) {
|
||||
const char *description;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
ifname = strdup("lo");
|
||||
assert_se(ifname);
|
||||
|
||||
@ -225,6 +248,8 @@ static void test_slot_set(int ifindex) {
|
||||
const char *description;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
ifname = strdup("lo");
|
||||
assert_se(ifname);
|
||||
|
||||
@ -303,6 +328,8 @@ static void test_async_destroy_callback(int ifindex) {
|
||||
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(t = new(struct test_async_object, 1));
|
||||
assert_se(ifname = strdup("lo"));
|
||||
*t = (struct test_async_object) {
|
||||
@ -371,6 +398,8 @@ static void test_pipe(int ifindex) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
|
||||
int counter = 0;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl) >= 0);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
|
||||
@ -396,6 +425,8 @@ static void test_container(sd_netlink *rtnl) {
|
||||
uint32_t u32_data;
|
||||
const char *string_data;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0);
|
||||
@ -406,7 +437,7 @@ static void test_container(sd_netlink *rtnl) {
|
||||
assert_se(sd_netlink_message_close_container(m) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(m) == -EINVAL);
|
||||
|
||||
assert_se(sd_netlink_message_rewind(m, NULL) >= 0);
|
||||
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0);
|
||||
assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
|
||||
@ -429,6 +460,8 @@ static void test_match(void) {
|
||||
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
|
||||
@ -445,6 +478,8 @@ static void test_get_addresses(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
sd_netlink_message *m;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
|
||||
assert_se(sd_netlink_message_request_dump(req, true) >= 0);
|
||||
assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
|
||||
@ -472,7 +507,9 @@ static void test_get_addresses(sd_netlink *rtnl) {
|
||||
static void test_message(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
|
||||
assert_se(rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
|
||||
assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
|
||||
}
|
||||
|
||||
@ -480,8 +517,10 @@ static void test_array(void) {
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_genl_socket_open(&genl) >= 0);
|
||||
assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0);
|
||||
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
@ -496,7 +535,7 @@ static void test_array(void) {
|
||||
}
|
||||
assert_se(sd_netlink_message_close_container(m) >= 0);
|
||||
|
||||
rtnl_message_seal(m);
|
||||
message_seal(m);
|
||||
assert_se(sd_netlink_message_rewind(m, genl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
|
||||
@ -522,6 +561,8 @@ static void test_strv(sd_netlink *rtnl) {
|
||||
_cleanup_strv_free_ char **names_in = NULL, **names_out;
|
||||
const char *p;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1) >= 0);
|
||||
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
@ -535,8 +576,8 @@ static void test_strv(sd_netlink *rtnl) {
|
||||
assert_se(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, names_in) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(m) >= 0);
|
||||
|
||||
rtnl_message_seal(m);
|
||||
assert_se(sd_netlink_message_rewind(m, NULL) >= 0);
|
||||
message_seal(m);
|
||||
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names_out) >= 0);
|
||||
assert_se(strv_equal(names_in, names_out));
|
||||
@ -547,6 +588,84 @@ static void test_strv(sd_netlink *rtnl) {
|
||||
assert_se(sd_netlink_message_exit_container(m) >= 0);
|
||||
}
|
||||
|
||||
static int genl_ctrl_match_callback(sd_netlink *genl, sd_netlink_message *m, void *userdata) {
|
||||
const char *name;
|
||||
uint16_t id;
|
||||
uint8_t cmd;
|
||||
|
||||
assert(genl);
|
||||
assert(m);
|
||||
|
||||
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
|
||||
assert_se(streq(name, CTRL_GENL_NAME));
|
||||
|
||||
assert_se(sd_genl_message_get_command(genl, m, &cmd) >= 0);
|
||||
|
||||
switch (cmd) {
|
||||
case CTRL_CMD_NEWFAMILY:
|
||||
case CTRL_CMD_DELFAMILY:
|
||||
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name) >= 0);
|
||||
assert_se(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id) >= 0);
|
||||
log_debug("%s: %s (id=%"PRIu16") family is %s.",
|
||||
__func__, name, id, cmd == CTRL_CMD_NEWFAMILY ? "added" : "removed");
|
||||
break;
|
||||
case CTRL_CMD_NEWMCAST_GRP:
|
||||
case CTRL_CMD_DELMCAST_GRP:
|
||||
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name) >= 0);
|
||||
assert_se(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id) >= 0);
|
||||
log_debug("%s: multicast group for %s (id=%"PRIu16") family is %s.",
|
||||
__func__, name, id, cmd == CTRL_CMD_NEWMCAST_GRP ? "added" : "removed");
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: received nlctrl message with unknown command '%"PRIu8"'.", __func__, cmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_genl(void) {
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const char *name;
|
||||
uint8_t cmd;
|
||||
int r;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_genl_socket_open(&genl) >= 0);
|
||||
assert_se(sd_event_default(&event) >= 0);
|
||||
assert_se(sd_netlink_attach_event(genl, event, 0) >= 0);
|
||||
|
||||
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
|
||||
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
|
||||
assert_se(streq(name, CTRL_GENL_NAME));
|
||||
assert_se(sd_genl_message_get_command(genl, m, &cmd) >= 0);
|
||||
assert_se(cmd == CTRL_CMD_GETFAMILY);
|
||||
|
||||
assert_se(sd_genl_add_match(genl, NULL, CTRL_GENL_NAME, "notify", 0, genl_ctrl_match_callback, NULL, NULL, "genl-ctrl-notify") >= 0);
|
||||
|
||||
m = sd_netlink_message_unref(m);
|
||||
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) < 0);
|
||||
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) == -EOPNOTSUPP);
|
||||
|
||||
/* These families may not be supported by kernel. Hence, ignore results. */
|
||||
(void) sd_genl_message_new(genl, FOU_GENL_NAME, 0, &m);
|
||||
m = sd_netlink_message_unref(m);
|
||||
(void) sd_genl_message_new(genl, L2TP_GENL_NAME, 0, &m);
|
||||
m = sd_netlink_message_unref(m);
|
||||
(void) sd_genl_message_new(genl, MACSEC_GENL_NAME, 0, &m);
|
||||
m = sd_netlink_message_unref(m);
|
||||
(void) sd_genl_message_new(genl, NL80211_GENL_NAME, 0, &m);
|
||||
|
||||
for (;;) {
|
||||
r = sd_event_run(event, 500 * USEC_PER_MSEC);
|
||||
assert_se(r >= 0);
|
||||
if (r == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
sd_netlink *rtnl;
|
||||
sd_netlink_message *m;
|
||||
@ -555,6 +674,8 @@ int main(void) {
|
||||
int if_loopback;
|
||||
uint16_t type;
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_match();
|
||||
test_multiple();
|
||||
|
||||
@ -605,5 +726,7 @@ int main(void) {
|
||||
assert_se((r = sd_netlink_message_unref(r)) == NULL);
|
||||
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
|
||||
|
||||
test_genl();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ static int netdev_batadv_post_create(NetDev *netdev, Link *link, sd_netlink_mess
|
||||
b = BATADV(netdev);
|
||||
assert(b);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_BATADV, BATADV_CMD_SET_MESH, &message);
|
||||
r = sd_genl_message_new(netdev->manager->genl, BATADV_NL_NAME, BATADV_CMD_SET_MESH, &message);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
|
||||
|
||||
|
@ -36,7 +36,7 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
|
||||
|
||||
assert(t);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_FOU, FOU_CMD_ADD, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, FOU_GENL_NAME, FOU_CMD_ADD, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
|
||||
|
||||
|
@ -104,7 +104,7 @@ static int netdev_l2tp_fill_message_tunnel(NetDev *netdev, union in_addr_union *
|
||||
|
||||
assert(t);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_TUNNEL_CREATE, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, L2TP_GENL_NAME, L2TP_CMD_TUNNEL_CREATE, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
@ -195,7 +195,7 @@ static int netdev_l2tp_fill_message_session(NetDev *netdev, L2tpSession *session
|
||||
assert(session);
|
||||
assert(session->tunnel);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_SESSION_CREATE, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, L2TP_GENL_NAME, L2TP_CMD_SESSION_CREATE, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
|
@ -224,7 +224,7 @@ static int netdev_macsec_fill_message(NetDev *netdev, int command, sd_netlink_me
|
||||
assert(netdev);
|
||||
assert(netdev->ifindex > 0);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_MACSEC, command, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, MACSEC_GENL_NAME, command, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
|
@ -229,7 +229,7 @@ static int wireguard_set_interface(NetDev *netdev) {
|
||||
|
||||
message = sd_netlink_message_unref(message);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_WIREGUARD, WG_CMD_SET_DEVICE, &message);
|
||||
r = sd_genl_message_new(netdev->manager->genl, WG_GENL_NAME, WG_CMD_SET_DEVICE, &message);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "lldp-internal.h"
|
||||
#include "macvlan.h"
|
||||
#include "ndisc-internal.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-util.h"
|
||||
@ -35,7 +34,6 @@ int main(int argc, char **argv) {
|
||||
/* test_table(link_state, LINK_STATE); — not a reversible mapping */
|
||||
test_table(lldp_mode, LLDP_MODE);
|
||||
test_table(netdev_kind, NETDEV_KIND);
|
||||
test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA);
|
||||
test_table(radv_prefix_delegation, RADV_PREFIX_DELEGATION);
|
||||
test_table(lldp_event, SD_LLDP_EVENT);
|
||||
test_table(ndisc_event, SD_NDISC_EVENT);
|
||||
@ -48,7 +46,6 @@ int main(int argc, char **argv) {
|
||||
assert_cc(sizeof(sd_lldp_event_t) == sizeof(int64_t));
|
||||
assert_cc(sizeof(sd_ndisc_event_t) == sizeof(int64_t));
|
||||
assert_cc(sizeof(sd_dhcp_lease_server_type_t) == sizeof(int64_t));
|
||||
assert_cc(sizeof(sd_genl_family_t) == sizeof(int64_t));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -649,7 +649,7 @@ static int fw_nftables_init_family(sd_netlink *nfnl, int family) {
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
/* Set F_EXCL so table add fails if the table already exists. */
|
||||
r = sd_nfnl_nft_message_new_table(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME, NLM_F_EXCL | NLM_F_ACK);
|
||||
r = sd_nfnl_nft_message_new_table(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "log.h"
|
||||
#include "string-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
sd_genl_family_t family;
|
||||
const char *family;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(ifindex > 0);
|
||||
|
||||
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
|
||||
r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_INTERFACE, &m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create generic netlink message: %m");
|
||||
|
||||
@ -38,11 +39,11 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get information about wifi interface %d: %m", ifindex);
|
||||
|
||||
r = sd_genl_message_get_family(genl, reply, &family);
|
||||
r = sd_genl_message_get_family_name(genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine genl family: %m");
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_debug("Received message of unexpected genl family %" PRIi64 ", ignoring.", family);
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("Received message of unexpected genl family '%s', ignoring.", family);
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
@ -75,14 +76,14 @@ nodata:
|
||||
|
||||
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
sd_genl_family_t family;
|
||||
const char *family;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(ifindex > 0);
|
||||
assert(bssid);
|
||||
|
||||
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
|
||||
r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_STATION, &m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create generic netlink message: %m");
|
||||
|
||||
@ -106,11 +107,11 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get information about wifi station: %m");
|
||||
|
||||
r = sd_genl_message_get_family(genl, reply, &family);
|
||||
r = sd_genl_message_get_family_name(genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine genl family: %m");
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_debug("Received message of unexpected genl family %" PRIi64 ", ignoring.", family);
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("Received message of unexpected genl family '%s', ignoring.", family);
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
|
@ -31,32 +31,15 @@
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
typedef struct sd_netlink sd_netlink;
|
||||
typedef struct sd_genl_socket sd_genl_socket;
|
||||
typedef struct sd_netlink_message sd_netlink_message;
|
||||
typedef struct sd_netlink_slot sd_netlink_slot;
|
||||
|
||||
typedef enum sd_genl_family_t {
|
||||
SD_GENL_ERROR,
|
||||
SD_GENL_DONE,
|
||||
SD_GENL_ID_CTRL,
|
||||
SD_GENL_WIREGUARD,
|
||||
SD_GENL_FOU,
|
||||
SD_GENL_L2TP,
|
||||
SD_GENL_MACSEC,
|
||||
SD_GENL_NL80211,
|
||||
SD_GENL_BATADV,
|
||||
_SD_GENL_FAMILY_MAX,
|
||||
_SD_GENL_FAMILY_INVALID = -EINVAL,
|
||||
_SD_ENUM_FORCE_S64(GENL_FAMILY)
|
||||
} sd_genl_family_t;
|
||||
|
||||
/* callback */
|
||||
|
||||
typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message *m, void *userdata);
|
||||
typedef _sd_destroy_t sd_netlink_destroy_t;
|
||||
|
||||
/* bus */
|
||||
int sd_netlink_new_from_netlink(sd_netlink **nl, int fd);
|
||||
int sd_netlink_new_from_fd(sd_netlink **nl, int fd);
|
||||
int sd_netlink_open(sd_netlink **nl);
|
||||
int sd_netlink_open_fd(sd_netlink **nl, int fd);
|
||||
int sd_netlink_inc_rcvbuf(sd_netlink *nl, const size_t size);
|
||||
@ -86,6 +69,7 @@ int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t ma
|
||||
int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
|
||||
int sd_netlink_detach_event(sd_netlink *nl);
|
||||
|
||||
/* message */
|
||||
int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data);
|
||||
int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data);
|
||||
int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type);
|
||||
@ -129,7 +113,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m);
|
||||
int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type);
|
||||
int sd_netlink_message_cancel_array(sd_netlink_message *m);
|
||||
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl);
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl);
|
||||
|
||||
sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m);
|
||||
|
||||
@ -182,12 +166,12 @@ int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char
|
||||
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);
|
||||
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type);
|
||||
|
||||
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol);
|
||||
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int nh_family, unsigned char nh_protocol);
|
||||
int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags);
|
||||
int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family);
|
||||
int sd_rtnl_message_nexthop_get_protocol(sd_netlink_message *m, uint8_t *protocol);
|
||||
|
||||
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family);
|
||||
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int nda_family);
|
||||
int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
|
||||
int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);
|
||||
int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family);
|
||||
@ -224,13 +208,13 @@ int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle);
|
||||
int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex);
|
||||
|
||||
/* nfnl */
|
||||
int sd_nfnl_socket_open(sd_netlink **nl);
|
||||
int sd_nfnl_socket_open(sd_netlink **ret);
|
||||
int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret);
|
||||
int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret);
|
||||
int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table);
|
||||
int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, uint16_t nl_flags);
|
||||
int family, const char *table);
|
||||
int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *chain,
|
||||
const char *type, uint8_t hook, int prio);
|
||||
@ -250,13 +234,19 @@ int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m,
|
||||
int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message *m);
|
||||
|
||||
/* genl */
|
||||
int sd_genl_socket_open(sd_netlink **nl);
|
||||
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret);
|
||||
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret);
|
||||
int sd_genl_socket_open(sd_netlink **ret);
|
||||
int sd_genl_message_new(sd_netlink *genl, const char *family_name, uint8_t cmd, sd_netlink_message **ret);
|
||||
int sd_genl_message_get_family_name(sd_netlink *genl, sd_netlink_message *m, const char **ret);
|
||||
int sd_genl_message_get_command(sd_netlink *genl, sd_netlink_message *m, uint8_t *ret);
|
||||
int sd_genl_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, const char *family_name,
|
||||
const char *multicast_group_name, uint8_t command,
|
||||
sd_netlink_message_handler_t callback,
|
||||
sd_netlink_destroy_t destroy_callback,
|
||||
void *userdata, const char *description);
|
||||
|
||||
/* slot */
|
||||
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl);
|
||||
sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *nl);
|
||||
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *slot);
|
||||
sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *slot);
|
||||
|
||||
sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot);
|
||||
void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot);
|
||||
|
Loading…
Reference in New Issue
Block a user