diff --git a/generated/Makefile b/generated/Makefile index 85fad4f..baf24e6 100644 --- a/generated/Makefile +++ b/generated/Makefile @@ -15,8 +15,9 @@ TOOL:=../ynl-gen-cpp.py GENS_PATHS=$(shell grep -nrI --files-without-match \ 'protocol: netlink' ../Documentation/netlink/specs/) +GENS_PATHS+=$(wildcard ../Documentation/netlink/specs/rt-*.yaml) GENS_ALL=$(patsubst ../Documentation/netlink/specs/%.yaml,%,${GENS_PATHS}) -GENS=rt-addr rt-link $(filter-out devlink ovs_datapath ovs_flow ovs_vport nlctrl,${GENS_ALL}) +GENS=$(filter-out devlink ovs_datapath ovs_flow ovs_vport nlctrl,${GENS_ALL}) SRCS=$(patsubst %,%-user.cpp,${GENS}) HDRS=$(patsubst %,%-user.hpp,${GENS}) OBJS=$(patsubst %,%-user.cpp.o,${GENS}) diff --git a/generated/rt-neigh-user.cpp b/generated/rt-neigh-user.cpp new file mode 100644 index 0000000..f76e9d1 --- /dev/null +++ b/generated/rt-neigh-user.cpp @@ -0,0 +1,847 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* */ +/* YNL-GEN user source */ + +#include "rt-neigh-user.hpp" + +#include + +#include + +#include + +namespace ynl_cpp { + +/* Enums */ +static constexpr std::array rt_neigh_op_strmap = []() { + std::array arr{}; + arr[29] = "delneigh-ntf"; + arr[28] = "newneigh-ntf"; + arr[64] = "getneightbl"; + return arr; +} (); + +std::string_view rt_neigh_op_str(int op) +{ + if (op < 0 || op >= (int)(rt_neigh_op_strmap.size())) { + return ""; + } + return rt_neigh_op_strmap[op]; +} + +static constexpr std::array rt_neigh_nud_state_strmap = []() { + std::array arr{}; + arr[0] = "incomplete"; + arr[1] = "reachable"; + arr[2] = "stale"; + arr[3] = "delay"; + arr[4] = "probe"; + arr[5] = "failed"; + arr[6] = "noarp"; + arr[7] = "permanent"; + return arr; +} (); + +std::string_view rt_neigh_nud_state_str(int value) +{ + value = (int)(ffs(value) - 1); + if (value < 0 || value >= (int)(rt_neigh_nud_state_strmap.size())) { + return ""; + } + return rt_neigh_nud_state_strmap[value]; +} + +static constexpr std::array rt_neigh_ntf_flags_strmap = []() { + std::array arr{}; + arr[0] = "use"; + arr[1] = "self"; + arr[2] = "master"; + arr[3] = "proxy"; + arr[4] = "ext-learned"; + arr[5] = "offloaded"; + arr[6] = "sticky"; + arr[7] = "router"; + return arr; +} (); + +std::string_view rt_neigh_ntf_flags_str(int value) +{ + value = (int)(ffs(value) - 1); + if (value < 0 || value >= (int)(rt_neigh_ntf_flags_strmap.size())) { + return ""; + } + return rt_neigh_ntf_flags_strmap[value]; +} + +static constexpr std::array rt_neigh_ntf_ext_flags_strmap = []() { + std::array arr{}; + arr[0] = "managed"; + arr[1] = "locked"; + arr[2] = "ext-validated"; + return arr; +} (); + +std::string_view rt_neigh_ntf_ext_flags_str(int value) +{ + value = (int)(ffs(value) - 1); + if (value < 0 || value >= (int)(rt_neigh_ntf_ext_flags_strmap.size())) { + return ""; + } + return rt_neigh_ntf_ext_flags_strmap[value]; +} + +static constexpr std::array rt_neigh_rtm_type_strmap = []() { + std::array arr{}; + arr[0] = "unspec"; + arr[1] = "unicast"; + arr[2] = "local"; + arr[3] = "broadcast"; + arr[4] = "anycast"; + arr[5] = "multicast"; + arr[6] = "blackhole"; + arr[7] = "unreachable"; + arr[8] = "prohibit"; + arr[9] = "throw"; + arr[10] = "nat"; + arr[11] = "xresolve"; + return arr; +} (); + +std::string_view rt_neigh_rtm_type_str(int value) +{ + if (value < 0 || value >= (int)(rt_neigh_rtm_type_strmap.size())) { + return ""; + } + return rt_neigh_rtm_type_strmap[value]; +} + +/* Policies */ +static std::array rt_neigh_ndtpa_attrs_policy = []() { + std::array arr{}; + arr[NDTPA_IFINDEX].name = "ifindex"; + arr[NDTPA_IFINDEX].type = YNL_PT_U32; + arr[NDTPA_REFCNT].name = "refcnt"; + arr[NDTPA_REFCNT].type = YNL_PT_U32; + arr[NDTPA_REACHABLE_TIME].name = "reachable-time"; + arr[NDTPA_REACHABLE_TIME].type = YNL_PT_U64; + arr[NDTPA_BASE_REACHABLE_TIME].name = "base-reachable-time"; + arr[NDTPA_BASE_REACHABLE_TIME].type = YNL_PT_U64; + arr[NDTPA_RETRANS_TIME].name = "retrans-time"; + arr[NDTPA_RETRANS_TIME].type = YNL_PT_U64; + arr[NDTPA_GC_STALETIME].name = "gc-staletime"; + arr[NDTPA_GC_STALETIME].type = YNL_PT_U64; + arr[NDTPA_DELAY_PROBE_TIME].name = "delay-probe-time"; + arr[NDTPA_DELAY_PROBE_TIME].type = YNL_PT_U64; + arr[NDTPA_QUEUE_LEN].name = "queue-len"; + arr[NDTPA_QUEUE_LEN].type = YNL_PT_U32; + arr[NDTPA_APP_PROBES].name = "app-probes"; + arr[NDTPA_APP_PROBES].type = YNL_PT_U32; + arr[NDTPA_UCAST_PROBES].name = "ucast-probes"; + arr[NDTPA_UCAST_PROBES].type = YNL_PT_U32; + arr[NDTPA_MCAST_PROBES].name = "mcast-probes"; + arr[NDTPA_MCAST_PROBES].type = YNL_PT_U32; + arr[NDTPA_ANYCAST_DELAY].name = "anycast-delay"; + arr[NDTPA_ANYCAST_DELAY].type = YNL_PT_U64; + arr[NDTPA_PROXY_DELAY].name = "proxy-delay"; + arr[NDTPA_PROXY_DELAY].type = YNL_PT_U64; + arr[NDTPA_PROXY_QLEN].name = "proxy-qlen"; + arr[NDTPA_PROXY_QLEN].type = YNL_PT_U32; + arr[NDTPA_LOCKTIME].name = "locktime"; + arr[NDTPA_LOCKTIME].type = YNL_PT_U64; + arr[NDTPA_QUEUE_LENBYTES].name = "queue-lenbytes"; + arr[NDTPA_QUEUE_LENBYTES].type = YNL_PT_U32; + arr[NDTPA_MCAST_REPROBES].name = "mcast-reprobes"; + arr[NDTPA_MCAST_REPROBES].type = YNL_PT_U32; + arr[NDTPA_PAD].name = "pad"; + arr[NDTPA_PAD].type = YNL_PT_IGNORE; + arr[NDTPA_INTERVAL_PROBE_TIME_MS].name = "interval-probe-time-ms"; + arr[NDTPA_INTERVAL_PROBE_TIME_MS].type = YNL_PT_U64; + return arr; +} (); + +struct ynl_policy_nest rt_neigh_ndtpa_attrs_nest = { + .max_attr = static_cast(NDTPA_MAX), + .table = rt_neigh_ndtpa_attrs_policy.data(), +}; + +static std::array rt_neigh_neighbour_attrs_policy = []() { + std::array arr{}; + arr[NDA_UNSPEC].name = "unspec"; + arr[NDA_UNSPEC].type = YNL_PT_BINARY; + arr[NDA_DST].name = "dst"; + arr[NDA_DST].type = YNL_PT_BINARY; + arr[NDA_LLADDR].name = "lladdr"; + arr[NDA_LLADDR].type = YNL_PT_BINARY; + arr[NDA_CACHEINFO].name = "cacheinfo"; + arr[NDA_CACHEINFO].type = YNL_PT_BINARY; + arr[NDA_PROBES].name = "probes"; + arr[NDA_PROBES].type = YNL_PT_U32; + arr[NDA_VLAN].name = "vlan"; + arr[NDA_VLAN].type = YNL_PT_U16; + arr[NDA_PORT].name = "port"; + arr[NDA_PORT].type = YNL_PT_U16; + arr[NDA_VNI].name = "vni"; + arr[NDA_VNI].type = YNL_PT_U32; + arr[NDA_IFINDEX].name = "ifindex"; + arr[NDA_IFINDEX].type = YNL_PT_U32; + arr[NDA_MASTER].name = "master"; + arr[NDA_MASTER].type = YNL_PT_U32; + arr[NDA_LINK_NETNSID].name = "link-netnsid"; + arr[NDA_LINK_NETNSID].type = YNL_PT_U32; + arr[NDA_SRC_VNI].name = "src-vni"; + arr[NDA_SRC_VNI].type = YNL_PT_U32; + arr[NDA_PROTOCOL].name = "protocol"; + arr[NDA_PROTOCOL].type = YNL_PT_U8; + arr[NDA_NH_ID].name = "nh-id"; + arr[NDA_NH_ID].type = YNL_PT_U32; + arr[NDA_FDB_EXT_ATTRS].name = "fdb-ext-attrs"; + arr[NDA_FDB_EXT_ATTRS].type = YNL_PT_BINARY; + arr[NDA_FLAGS_EXT].name = "flags-ext"; + arr[NDA_FLAGS_EXT].type = YNL_PT_U32; + arr[NDA_NDM_STATE_MASK].name = "ndm-state-mask"; + arr[NDA_NDM_STATE_MASK].type = YNL_PT_U16; + arr[NDA_NDM_FLAGS_MASK].name = "ndm-flags-mask"; + arr[NDA_NDM_FLAGS_MASK].type = YNL_PT_U8; + return arr; +} (); + +struct ynl_policy_nest rt_neigh_neighbour_attrs_nest = { + .max_attr = static_cast(NDA_MAX), + .table = rt_neigh_neighbour_attrs_policy.data(), +}; + +static std::array rt_neigh_ndt_attrs_policy = []() { + std::array arr{}; + arr[NDTA_NAME].name = "name"; + arr[NDTA_NAME].type = YNL_PT_NUL_STR; + arr[NDTA_THRESH1].name = "thresh1"; + arr[NDTA_THRESH1].type = YNL_PT_U32; + arr[NDTA_THRESH2].name = "thresh2"; + arr[NDTA_THRESH2].type = YNL_PT_U32; + arr[NDTA_THRESH3].name = "thresh3"; + arr[NDTA_THRESH3].type = YNL_PT_U32; + arr[NDTA_CONFIG].name = "config"; + arr[NDTA_CONFIG].type = YNL_PT_BINARY; + arr[NDTA_PARMS].name = "parms"; + arr[NDTA_PARMS].type = YNL_PT_NEST; + arr[NDTA_PARMS].nest = &rt_neigh_ndtpa_attrs_nest; + arr[NDTA_STATS].name = "stats"; + arr[NDTA_STATS].type = YNL_PT_BINARY; + arr[NDTA_GC_INTERVAL].name = "gc-interval"; + arr[NDTA_GC_INTERVAL].type = YNL_PT_U64; + arr[NDTA_PAD].name = "pad"; + arr[NDTA_PAD].type = YNL_PT_IGNORE; + return arr; +} (); + +struct ynl_policy_nest rt_neigh_ndt_attrs_nest = { + .max_attr = static_cast(NDTA_MAX), + .table = rt_neigh_ndt_attrs_policy.data(), +}; + +/* Common nested types */ +int rt_neigh_ndtpa_attrs_put(struct nlmsghdr *nlh, unsigned int attr_type, + const rt_neigh_ndtpa_attrs& obj) +{ + struct nlattr *nest; + + nest = ynl_attr_nest_start(nlh, attr_type); + if (obj.ifindex.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_IFINDEX, obj.ifindex.value()); + } + if (obj.refcnt.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_REFCNT, obj.refcnt.value()); + } + if (obj.reachable_time.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_REACHABLE_TIME, obj.reachable_time.value()); + } + if (obj.base_reachable_time.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_BASE_REACHABLE_TIME, obj.base_reachable_time.value()); + } + if (obj.retrans_time.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_RETRANS_TIME, obj.retrans_time.value()); + } + if (obj.gc_staletime.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_GC_STALETIME, obj.gc_staletime.value()); + } + if (obj.delay_probe_time.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_DELAY_PROBE_TIME, obj.delay_probe_time.value()); + } + if (obj.queue_len.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_QUEUE_LEN, obj.queue_len.value()); + } + if (obj.app_probes.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_APP_PROBES, obj.app_probes.value()); + } + if (obj.ucast_probes.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_UCAST_PROBES, obj.ucast_probes.value()); + } + if (obj.mcast_probes.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_MCAST_PROBES, obj.mcast_probes.value()); + } + if (obj.anycast_delay.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_ANYCAST_DELAY, obj.anycast_delay.value()); + } + if (obj.proxy_delay.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_PROXY_DELAY, obj.proxy_delay.value()); + } + if (obj.proxy_qlen.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_PROXY_QLEN, obj.proxy_qlen.value()); + } + if (obj.locktime.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_LOCKTIME, obj.locktime.value()); + } + if (obj.queue_lenbytes.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_QUEUE_LENBYTES, obj.queue_lenbytes.value()); + } + if (obj.mcast_reprobes.has_value()) { + ynl_attr_put_u32(nlh, NDTPA_MCAST_REPROBES, obj.mcast_reprobes.value()); + } + if (obj.interval_probe_time_ms.has_value()) { + ynl_attr_put_u64(nlh, NDTPA_INTERVAL_PROBE_TIME_MS, obj.interval_probe_time_ms.value()); + } + ynl_attr_nest_end(nlh, nest); + + return 0; +} + +int rt_neigh_ndtpa_attrs_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested) +{ + rt_neigh_ndtpa_attrs *dst = (rt_neigh_ndtpa_attrs *)yarg->data; + const struct nlattr *attr; + + ynl_attr_for_each_nested(attr, nested) { + unsigned int type = ynl_attr_type(attr); + + if (type == NDTPA_IFINDEX) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ifindex = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_REFCNT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->refcnt = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_REACHABLE_TIME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->reachable_time = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_BASE_REACHABLE_TIME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->base_reachable_time = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_RETRANS_TIME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->retrans_time = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_GC_STALETIME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->gc_staletime = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_DELAY_PROBE_TIME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->delay_probe_time = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_QUEUE_LEN) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->queue_len = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_APP_PROBES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->app_probes = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_UCAST_PROBES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ucast_probes = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_MCAST_PROBES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->mcast_probes = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_ANYCAST_DELAY) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->anycast_delay = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_PROXY_DELAY) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->proxy_delay = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_PROXY_QLEN) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->proxy_qlen = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_LOCKTIME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->locktime = (__u64)ynl_attr_get_u64(attr); + } else if (type == NDTPA_QUEUE_LENBYTES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->queue_lenbytes = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_MCAST_REPROBES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->mcast_reprobes = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTPA_INTERVAL_PROBE_TIME_MS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->interval_probe_time_ms = (__u64)ynl_attr_get_u64(attr); + } + } + + return 0; +} + +/* ============== RTM_NEWNEIGH ============== */ +/* RTM_NEWNEIGH - do */ +int rt_neigh_newneigh(ynl_cpp::ynl_socket& ys, rt_neigh_newneigh_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_NEWNEIGH, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_neigh_neighbour_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.dst.size() > 0) { + ynl_attr_put(nlh, NDA_DST, req.dst.data(), req.dst.size()); + } + if (req.lladdr.size() > 0) { + ynl_attr_put(nlh, NDA_LLADDR, req.lladdr.data(), req.lladdr.size()); + } + if (req.probes.has_value()) { + ynl_attr_put_u32(nlh, NDA_PROBES, req.probes.value()); + } + if (req.vlan.has_value()) { + ynl_attr_put_u16(nlh, NDA_VLAN, req.vlan.value()); + } + if (req.port.has_value()) { + ynl_attr_put_u16(nlh, NDA_PORT, req.port.value()); + } + if (req.vni.has_value()) { + ynl_attr_put_u32(nlh, NDA_VNI, req.vni.value()); + } + if (req.ifindex.has_value()) { + ynl_attr_put_u32(nlh, NDA_IFINDEX, req.ifindex.value()); + } + if (req.master.has_value()) { + ynl_attr_put_u32(nlh, NDA_MASTER, req.master.value()); + } + if (req.protocol.has_value()) { + ynl_attr_put_u8(nlh, NDA_PROTOCOL, req.protocol.value()); + } + if (req.nh_id.has_value()) { + ynl_attr_put_u32(nlh, NDA_NH_ID, req.nh_id.value()); + } + if (req.flags_ext.has_value()) { + ynl_attr_put_u32(nlh, NDA_FLAGS_EXT, req.flags_ext.value()); + } + if (req.fdb_ext_attrs.size() > 0) { + ynl_attr_put(nlh, NDA_FDB_EXT_ATTRS, req.fdb_ext_attrs.data(), req.fdb_ext_attrs.size()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +/* ============== RTM_DELNEIGH ============== */ +/* RTM_DELNEIGH - do */ +int rt_neigh_delneigh(ynl_cpp::ynl_socket& ys, rt_neigh_delneigh_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_DELNEIGH, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_neigh_neighbour_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.dst.size() > 0) { + ynl_attr_put(nlh, NDA_DST, req.dst.data(), req.dst.size()); + } + if (req.ifindex.has_value()) { + ynl_attr_put_u32(nlh, NDA_IFINDEX, req.ifindex.value()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +/* ============== RTM_GETNEIGH ============== */ +/* RTM_GETNEIGH - do */ +int rt_neigh_getneigh_rsp_parse(const struct nlmsghdr *nlh, + struct ynl_parse_arg *yarg) +{ + rt_neigh_getneigh_rsp *dst; + const struct nlattr *attr; + void *hdr; + + dst = (rt_neigh_getneigh_rsp*)yarg->data; + + hdr = ynl_nlmsg_data(nlh); + memcpy(&dst->_hdr, hdr, sizeof(struct ndmsg)); + + ynl_attr_for_each(attr, nlh, sizeof(struct ndmsg)) { + unsigned int type = ynl_attr_type(attr); + + if (type == NDA_DST) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->dst.assign(data, data + len); + } else if (type == NDA_LLADDR) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->lladdr.assign(data, data + len); + } else if (type == NDA_PROBES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->probes = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDA_VLAN) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->vlan = (__u16)ynl_attr_get_u16(attr); + } else if (type == NDA_PORT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->port = (__u16)ynl_attr_get_u16(attr); + } else if (type == NDA_VNI) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->vni = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDA_IFINDEX) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ifindex = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDA_MASTER) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->master = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDA_PROTOCOL) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->protocol = (__u8)ynl_attr_get_u8(attr); + } else if (type == NDA_NH_ID) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->nh_id = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDA_FLAGS_EXT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->flags_ext = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDA_FDB_EXT_ATTRS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->fdb_ext_attrs.assign(data, data + len); + } + } + + return YNL_PARSE_CB_OK; +} + +std::unique_ptr +rt_neigh_getneigh(ynl_cpp::ynl_socket& ys, rt_neigh_getneigh_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + std::unique_ptr rsp; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_GETNEIGH, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_neigh_neighbour_attrs_nest; + yrs.yarg.rsp_policy = &rt_neigh_neighbour_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.dst.size() > 0) { + ynl_attr_put(nlh, NDA_DST, req.dst.data(), req.dst.size()); + } + + rsp.reset(new rt_neigh_getneigh_rsp()); + yrs.yarg.data = rsp.get(); + yrs.cb = rt_neigh_getneigh_rsp_parse; + yrs.rsp_cmd = 28; + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return nullptr; + } + + return rsp; +} + +/* RTM_GETNEIGH - dump */ +std::unique_ptr +rt_neigh_getneigh_dump(ynl_cpp::ynl_socket& ys, + rt_neigh_getneigh_req_dump& req) +{ + struct ynl_dump_no_alloc_state yds = {}; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + auto ret = std::make_unique(); + yds.yarg.ys = ys; + yds.yarg.rsp_policy = &rt_neigh_neighbour_attrs_nest; + yds.yarg.data = ret.get(); + yds.alloc_cb = [](void* arg)->void* {return &(static_cast(arg)->objs.emplace_back());}; + yds.cb = rt_neigh_getneigh_rsp_parse; + yds.rsp_cmd = 28; + + nlh = ynl_msg_start_dump(ys, RTM_GETNEIGH); + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + ((struct ynl_sock*)ys)->req_policy = &rt_neigh_neighbour_attrs_nest; + + if (req.ifindex.has_value()) { + ynl_attr_put_u32(nlh, NDA_IFINDEX, req.ifindex.value()); + } + if (req.master.has_value()) { + ynl_attr_put_u32(nlh, NDA_MASTER, req.master.value()); + } + + err = ynl_exec_dump_no_alloc(ys, nlh, &yds); + if (err < 0) { + return nullptr; + } + + return ret; +} + +/* RTM_GETNEIGH - notify */ +/* ============== RTM_GETNEIGHTBL ============== */ +/* RTM_GETNEIGHTBL - dump */ +int rt_neigh_getneightbl_rsp_parse(const struct nlmsghdr *nlh, + struct ynl_parse_arg *yarg) +{ + rt_neigh_getneightbl_rsp *dst; + const struct nlattr *attr; + struct ynl_parse_arg parg; + void *hdr; + + dst = (rt_neigh_getneightbl_rsp*)yarg->data; + parg.ys = yarg->ys; + + hdr = ynl_nlmsg_data(nlh); + memcpy(&dst->_hdr, hdr, sizeof(struct ndtmsg)); + + ynl_attr_for_each(attr, nlh, sizeof(struct ndtmsg)) { + unsigned int type = ynl_attr_type(attr); + + if (type == NDTA_NAME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->name.assign(ynl_attr_get_str(attr)); + } else if (type == NDTA_THRESH1) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->thresh1 = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTA_THRESH2) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->thresh2 = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTA_THRESH3) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->thresh3 = (__u32)ynl_attr_get_u32(attr); + } else if (type == NDTA_CONFIG) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + unsigned int struct_sz = sizeof(struct ndt_config); + dst->config.emplace(); + memcpy(&*dst->config, ynl_attr_data(attr), std::min(struct_sz, len)); + } else if (type == NDTA_PARMS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + + parg.rsp_policy = &rt_neigh_ndtpa_attrs_nest; + parg.data = &dst->parms.emplace(); + if (rt_neigh_ndtpa_attrs_parse(&parg, attr)) { + return YNL_PARSE_CB_ERROR; + } + } else if (type == NDTA_STATS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + unsigned int struct_sz = sizeof(struct ndt_stats); + dst->stats.emplace(); + memcpy(&*dst->stats, ynl_attr_data(attr), std::min(struct_sz, len)); + } else if (type == NDTA_GC_INTERVAL) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->gc_interval = (__u64)ynl_attr_get_u64(attr); + } + } + + return YNL_PARSE_CB_OK; +} + +std::unique_ptr +rt_neigh_getneightbl_dump(ynl_cpp::ynl_socket& ys, + rt_neigh_getneightbl_req& req) +{ + struct ynl_dump_no_alloc_state yds = {}; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + auto ret = std::make_unique(); + yds.yarg.ys = ys; + yds.yarg.rsp_policy = &rt_neigh_ndt_attrs_nest; + yds.yarg.data = ret.get(); + yds.alloc_cb = [](void* arg)->void* {return &(static_cast(arg)->objs.emplace_back());}; + yds.cb = rt_neigh_getneightbl_rsp_parse; + yds.rsp_cmd = 64; + + nlh = ynl_msg_start_dump(ys, RTM_GETNEIGHTBL); + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + ((struct ynl_sock*)ys)->req_policy = &rt_neigh_ndt_attrs_nest; + + err = ynl_exec_dump_no_alloc(ys, nlh, &yds); + if (err < 0) { + return nullptr; + } + + return ret; +} + +/* ============== RTM_SETNEIGHTBL ============== */ +/* RTM_SETNEIGHTBL - do */ +int rt_neigh_setneightbl(ynl_cpp::ynl_socket& ys, + rt_neigh_setneightbl_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_SETNEIGHTBL, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_neigh_ndt_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.name.size() > 0) { + ynl_attr_put_str(nlh, NDTA_NAME, req.name.data()); + } + if (req.thresh1.has_value()) { + ynl_attr_put_u32(nlh, NDTA_THRESH1, req.thresh1.value()); + } + if (req.thresh2.has_value()) { + ynl_attr_put_u32(nlh, NDTA_THRESH2, req.thresh2.value()); + } + if (req.thresh3.has_value()) { + ynl_attr_put_u32(nlh, NDTA_THRESH3, req.thresh3.value()); + } + if (req.parms.has_value()) { + rt_neigh_ndtpa_attrs_put(nlh, NDTA_PARMS, req.parms.value()); + } + if (req.gc_interval.has_value()) { + ynl_attr_put_u64(nlh, NDTA_GC_INTERVAL, req.gc_interval.value()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +static constexpr std::array rt_neigh_ntf_info = []() { + std::array arr{}; + arr[RTM_DELNEIGH].policy = &rt_neigh_neighbour_attrs_nest; + arr[RTM_DELNEIGH].cb = rt_neigh_getneigh_rsp_parse; + arr[RTM_NEWNEIGH].policy = &rt_neigh_neighbour_attrs_nest; + arr[RTM_NEWNEIGH].cb = rt_neigh_getneigh_rsp_parse; + return arr; +} (); + +const struct ynl_family ynl_rt_neigh_family = { + .name = "rt_neigh", + .is_classic = true, + .classic_id = 0, + .ntf_info = rt_neigh_ntf_info.data(), + .ntf_info_size = rt_neigh_ntf_info.size(), +}; +const struct ynl_family& get_ynl_rt_neigh_family() { + return ynl_rt_neigh_family; +}; +} //namespace ynl_cpp diff --git a/generated/rt-neigh-user.hpp b/generated/rt-neigh-user.hpp new file mode 100644 index 0000000..3c42e0f --- /dev/null +++ b/generated/rt-neigh-user.hpp @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* */ +/* YNL-GEN user header */ + +#ifndef _LINUX_RT_NEIGH_GEN_H +#define _LINUX_RT_NEIGH_GEN_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ynl.hpp" + +#include + +namespace ynl_cpp { +const struct ynl_family& get_ynl_rt_neigh_family(); + +/* Enums */ +std::string_view rt_neigh_op_str(int op); +std::string_view rt_neigh_nud_state_str(int value); +std::string_view rt_neigh_ntf_flags_str(int value); +std::string_view rt_neigh_ntf_ext_flags_str(int value); +std::string_view rt_neigh_rtm_type_str(int value); + +/* Common nested types */ +struct rt_neigh_ndtpa_attrs { + std::optional<__u32> ifindex; + std::optional<__u32> refcnt; + std::optional<__u64> reachable_time; + std::optional<__u64> base_reachable_time; + std::optional<__u64> retrans_time; + std::optional<__u64> gc_staletime; + std::optional<__u64> delay_probe_time; + std::optional<__u32> queue_len; + std::optional<__u32> app_probes; + std::optional<__u32> ucast_probes; + std::optional<__u32> mcast_probes; + std::optional<__u64> anycast_delay; + std::optional<__u64> proxy_delay; + std::optional<__u32> proxy_qlen; + std::optional<__u64> locktime; + std::optional<__u32> queue_lenbytes; + std::optional<__u32> mcast_reprobes; + std::optional<__u64> interval_probe_time_ms; +}; + +/* ============== RTM_NEWNEIGH ============== */ +/* RTM_NEWNEIGH - do */ +struct rt_neigh_newneigh_req { + __u16 _nlmsg_flags; + + struct ndmsg _hdr; + + std::vector<__u8> dst; + std::vector<__u8> lladdr; + std::optional<__u32> probes; + std::optional<__u16> vlan; + std::optional<__u16> port; + std::optional<__u32> vni; + std::optional<__u32> ifindex; + std::optional<__u32> master; + std::optional<__u8> protocol; + std::optional<__u32> nh_id; + std::optional<__u32> flags_ext; + std::vector<__u8> fdb_ext_attrs; +}; + +/* + * Add new neighbour entry + */ +int rt_neigh_newneigh(ynl_cpp::ynl_socket& ys, rt_neigh_newneigh_req& req); + +/* ============== RTM_DELNEIGH ============== */ +/* RTM_DELNEIGH - do */ +struct rt_neigh_delneigh_req { + __u16 _nlmsg_flags; + + struct ndmsg _hdr; + + std::vector<__u8> dst; + std::optional<__u32> ifindex; +}; + +/* + * Remove an existing neighbour entry + */ +int rt_neigh_delneigh(ynl_cpp::ynl_socket& ys, rt_neigh_delneigh_req& req); + +/* ============== RTM_GETNEIGH ============== */ +/* RTM_GETNEIGH - do */ +struct rt_neigh_getneigh_req { + __u16 _nlmsg_flags; + + struct ndmsg _hdr; + + std::vector<__u8> dst; +}; + +struct rt_neigh_getneigh_rsp { + struct ndmsg _hdr; + + std::vector<__u8> dst; + std::vector<__u8> lladdr; + std::optional<__u32> probes; + std::optional<__u16> vlan; + std::optional<__u16> port; + std::optional<__u32> vni; + std::optional<__u32> ifindex; + std::optional<__u32> master; + std::optional<__u8> protocol; + std::optional<__u32> nh_id; + std::optional<__u32> flags_ext; + std::vector<__u8> fdb_ext_attrs; +}; + +/* + * Get or dump neighbour entries + */ +std::unique_ptr +rt_neigh_getneigh(ynl_cpp::ynl_socket& ys, rt_neigh_getneigh_req& req); + +/* RTM_GETNEIGH - dump */ +struct rt_neigh_getneigh_req_dump { + struct ndmsg _hdr; + + std::optional<__u32> ifindex; + std::optional<__u32> master; +}; + +struct rt_neigh_getneigh_list { + std::list objs; +}; + +std::unique_ptr +rt_neigh_getneigh_dump(ynl_cpp::ynl_socket& ys, + rt_neigh_getneigh_req_dump& req); + +/* RTM_GETNEIGH - notify */ +struct rt_neigh_getneigh_ntf { +}; + +/* ============== RTM_GETNEIGHTBL ============== */ +/* RTM_GETNEIGHTBL - dump */ +struct rt_neigh_getneightbl_req { + struct ndtmsg _hdr; +}; + +struct rt_neigh_getneightbl_rsp { + struct ndtmsg _hdr; + + std::string name; + std::optional<__u32> thresh1; + std::optional<__u32> thresh2; + std::optional<__u32> thresh3; + std::optional config; + std::optional parms; + std::optional stats; + std::optional<__u64> gc_interval; +}; + +struct rt_neigh_getneightbl_list { + std::list objs; +}; + +std::unique_ptr +rt_neigh_getneightbl_dump(ynl_cpp::ynl_socket& ys, + rt_neigh_getneightbl_req& req); + +/* ============== RTM_SETNEIGHTBL ============== */ +/* RTM_SETNEIGHTBL - do */ +struct rt_neigh_setneightbl_req { + __u16 _nlmsg_flags; + + struct ndtmsg _hdr; + + std::string name; + std::optional<__u32> thresh1; + std::optional<__u32> thresh2; + std::optional<__u32> thresh3; + std::optional parms; + std::optional<__u64> gc_interval; +}; + +/* + * Set neighbour tables + */ +int rt_neigh_setneightbl(ynl_cpp::ynl_socket& ys, + rt_neigh_setneightbl_req& req); + +} //namespace ynl_cpp +#endif /* _LINUX_RT_NEIGH_GEN_H */ diff --git a/generated/rt-route-user.cpp b/generated/rt-route-user.cpp new file mode 100644 index 0000000..68b2fba --- /dev/null +++ b/generated/rt-route-user.cpp @@ -0,0 +1,857 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* */ +/* YNL-GEN user source */ + +#include "rt-route-user.hpp" + +#include + +#include + +#include + +namespace ynl_cpp { + +/* Enums */ +static constexpr std::array rt_route_op_strmap = []() { + std::array arr{}; + arr[24] = "getroute"; + return arr; +} (); + +std::string_view rt_route_op_str(int op) +{ + if (op < 0 || op >= (int)(rt_route_op_strmap.size())) { + return ""; + } + return rt_route_op_strmap[op]; +} + +static constexpr std::array rt_route_rtm_type_strmap = []() { + std::array arr{}; + arr[0] = "unspec"; + arr[1] = "unicast"; + arr[2] = "local"; + arr[3] = "broadcast"; + arr[4] = "anycast"; + arr[5] = "multicast"; + arr[6] = "blackhole"; + arr[7] = "unreachable"; + arr[8] = "prohibit"; + arr[9] = "throw"; + arr[10] = "nat"; + arr[11] = "xresolve"; + return arr; +} (); + +std::string_view rt_route_rtm_type_str(int value) +{ + if (value < 0 || value >= (int)(rt_route_rtm_type_strmap.size())) { + return ""; + } + return rt_route_rtm_type_strmap[value]; +} + +/* Policies */ +static std::array rt_route_metrics_policy = []() { + std::array arr{}; + arr[RTAX_UNSPEC].name = "unspec"; + arr[RTAX_UNSPEC].type = YNL_PT_REJECT; + arr[RTAX_LOCK].name = "lock"; + arr[RTAX_LOCK].type = YNL_PT_U32; + arr[RTAX_MTU].name = "mtu"; + arr[RTAX_MTU].type = YNL_PT_U32; + arr[RTAX_WINDOW].name = "window"; + arr[RTAX_WINDOW].type = YNL_PT_U32; + arr[RTAX_RTT].name = "rtt"; + arr[RTAX_RTT].type = YNL_PT_U32; + arr[RTAX_RTTVAR].name = "rttvar"; + arr[RTAX_RTTVAR].type = YNL_PT_U32; + arr[RTAX_SSTHRESH].name = "ssthresh"; + arr[RTAX_SSTHRESH].type = YNL_PT_U32; + arr[RTAX_CWND].name = "cwnd"; + arr[RTAX_CWND].type = YNL_PT_U32; + arr[RTAX_ADVMSS].name = "advmss"; + arr[RTAX_ADVMSS].type = YNL_PT_U32; + arr[RTAX_REORDERING].name = "reordering"; + arr[RTAX_REORDERING].type = YNL_PT_U32; + arr[RTAX_HOPLIMIT].name = "hoplimit"; + arr[RTAX_HOPLIMIT].type = YNL_PT_U32; + arr[RTAX_INITCWND].name = "initcwnd"; + arr[RTAX_INITCWND].type = YNL_PT_U32; + arr[RTAX_FEATURES].name = "features"; + arr[RTAX_FEATURES].type = YNL_PT_U32; + arr[RTAX_RTO_MIN].name = "rto-min"; + arr[RTAX_RTO_MIN].type = YNL_PT_U32; + arr[RTAX_INITRWND].name = "initrwnd"; + arr[RTAX_INITRWND].type = YNL_PT_U32; + arr[RTAX_QUICKACK].name = "quickack"; + arr[RTAX_QUICKACK].type = YNL_PT_U32; + arr[RTAX_CC_ALGO].name = "cc-algo"; + arr[RTAX_CC_ALGO].type = YNL_PT_NUL_STR; + arr[RTAX_FASTOPEN_NO_COOKIE].name = "fastopen-no-cookie"; + arr[RTAX_FASTOPEN_NO_COOKIE].type = YNL_PT_U32; + return arr; +} (); + +struct ynl_policy_nest rt_route_metrics_nest = { + .max_attr = static_cast(RTAX_MAX), + .table = rt_route_metrics_policy.data(), +}; + +static std::array rt_route_route_attrs_policy = []() { + std::array arr{}; + arr[RTA_DST].name = "dst"; + arr[RTA_DST].type = YNL_PT_BINARY; + arr[RTA_SRC].name = "src"; + arr[RTA_SRC].type = YNL_PT_BINARY; + arr[RTA_IIF].name = "iif"; + arr[RTA_IIF].type = YNL_PT_U32; + arr[RTA_OIF].name = "oif"; + arr[RTA_OIF].type = YNL_PT_U32; + arr[RTA_GATEWAY].name = "gateway"; + arr[RTA_GATEWAY].type = YNL_PT_BINARY; + arr[RTA_PRIORITY].name = "priority"; + arr[RTA_PRIORITY].type = YNL_PT_U32; + arr[RTA_PREFSRC].name = "prefsrc"; + arr[RTA_PREFSRC].type = YNL_PT_BINARY; + arr[RTA_METRICS].name = "metrics"; + arr[RTA_METRICS].type = YNL_PT_NEST; + arr[RTA_METRICS].nest = &rt_route_metrics_nest; + arr[RTA_MULTIPATH].name = "multipath"; + arr[RTA_MULTIPATH].type = YNL_PT_BINARY; + arr[RTA_PROTOINFO].name = "protoinfo"; + arr[RTA_PROTOINFO].type = YNL_PT_BINARY; + arr[RTA_FLOW].name = "flow"; + arr[RTA_FLOW].type = YNL_PT_U32; + arr[RTA_CACHEINFO].name = "cacheinfo"; + arr[RTA_CACHEINFO].type = YNL_PT_BINARY; + arr[RTA_SESSION].name = "session"; + arr[RTA_SESSION].type = YNL_PT_BINARY; + arr[RTA_MP_ALGO].name = "mp-algo"; + arr[RTA_MP_ALGO].type = YNL_PT_BINARY; + arr[RTA_TABLE].name = "table"; + arr[RTA_TABLE].type = YNL_PT_U32; + arr[RTA_MARK].name = "mark"; + arr[RTA_MARK].type = YNL_PT_U32; + arr[RTA_MFC_STATS].name = "mfc-stats"; + arr[RTA_MFC_STATS].type = YNL_PT_BINARY; + arr[RTA_VIA].name = "via"; + arr[RTA_VIA].type = YNL_PT_BINARY; + arr[RTA_NEWDST].name = "newdst"; + arr[RTA_NEWDST].type = YNL_PT_BINARY; + arr[RTA_PREF].name = "pref"; + arr[RTA_PREF].type = YNL_PT_U8; + arr[RTA_ENCAP_TYPE].name = "encap-type"; + arr[RTA_ENCAP_TYPE].type = YNL_PT_U16; + arr[RTA_ENCAP].name = "encap"; + arr[RTA_ENCAP].type = YNL_PT_BINARY; + arr[RTA_EXPIRES].name = "expires"; + arr[RTA_EXPIRES].type = YNL_PT_U32; + arr[RTA_PAD].name = "pad"; + arr[RTA_PAD].type = YNL_PT_BINARY; + arr[RTA_UID].name = "uid"; + arr[RTA_UID].type = YNL_PT_U32; + arr[RTA_TTL_PROPAGATE].name = "ttl-propagate"; + arr[RTA_TTL_PROPAGATE].type = YNL_PT_U8; + arr[RTA_IP_PROTO].name = "ip-proto"; + arr[RTA_IP_PROTO].type = YNL_PT_U8; + arr[RTA_SPORT].name = "sport"; + arr[RTA_SPORT].type = YNL_PT_U16; + arr[RTA_DPORT].name = "dport"; + arr[RTA_DPORT].type = YNL_PT_U16; + arr[RTA_NH_ID].name = "nh-id"; + arr[RTA_NH_ID].type = YNL_PT_U32; + arr[RTA_FLOWLABEL].name = "flowlabel"; + arr[RTA_FLOWLABEL].type = YNL_PT_U32; + return arr; +} (); + +struct ynl_policy_nest rt_route_route_attrs_nest = { + .max_attr = static_cast(RTA_MAX), + .table = rt_route_route_attrs_policy.data(), +}; + +/* Common nested types */ +int rt_route_metrics_put(struct nlmsghdr *nlh, unsigned int attr_type, + const rt_route_metrics& obj) +{ + struct nlattr *nest; + + nest = ynl_attr_nest_start(nlh, attr_type); + if (obj.lock.has_value()) { + ynl_attr_put_u32(nlh, RTAX_LOCK, obj.lock.value()); + } + if (obj.mtu.has_value()) { + ynl_attr_put_u32(nlh, RTAX_MTU, obj.mtu.value()); + } + if (obj.window.has_value()) { + ynl_attr_put_u32(nlh, RTAX_WINDOW, obj.window.value()); + } + if (obj.rtt.has_value()) { + ynl_attr_put_u32(nlh, RTAX_RTT, obj.rtt.value()); + } + if (obj.rttvar.has_value()) { + ynl_attr_put_u32(nlh, RTAX_RTTVAR, obj.rttvar.value()); + } + if (obj.ssthresh.has_value()) { + ynl_attr_put_u32(nlh, RTAX_SSTHRESH, obj.ssthresh.value()); + } + if (obj.cwnd.has_value()) { + ynl_attr_put_u32(nlh, RTAX_CWND, obj.cwnd.value()); + } + if (obj.advmss.has_value()) { + ynl_attr_put_u32(nlh, RTAX_ADVMSS, obj.advmss.value()); + } + if (obj.reordering.has_value()) { + ynl_attr_put_u32(nlh, RTAX_REORDERING, obj.reordering.value()); + } + if (obj.hoplimit.has_value()) { + ynl_attr_put_u32(nlh, RTAX_HOPLIMIT, obj.hoplimit.value()); + } + if (obj.initcwnd.has_value()) { + ynl_attr_put_u32(nlh, RTAX_INITCWND, obj.initcwnd.value()); + } + if (obj.features.has_value()) { + ynl_attr_put_u32(nlh, RTAX_FEATURES, obj.features.value()); + } + if (obj.rto_min.has_value()) { + ynl_attr_put_u32(nlh, RTAX_RTO_MIN, obj.rto_min.value()); + } + if (obj.initrwnd.has_value()) { + ynl_attr_put_u32(nlh, RTAX_INITRWND, obj.initrwnd.value()); + } + if (obj.quickack.has_value()) { + ynl_attr_put_u32(nlh, RTAX_QUICKACK, obj.quickack.value()); + } + if (obj.cc_algo.size() > 0) { + ynl_attr_put_str(nlh, RTAX_CC_ALGO, obj.cc_algo.data()); + } + if (obj.fastopen_no_cookie.has_value()) { + ynl_attr_put_u32(nlh, RTAX_FASTOPEN_NO_COOKIE, obj.fastopen_no_cookie.value()); + } + ynl_attr_nest_end(nlh, nest); + + return 0; +} + +int rt_route_metrics_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested) +{ + rt_route_metrics *dst = (rt_route_metrics *)yarg->data; + const struct nlattr *attr; + + ynl_attr_for_each_nested(attr, nested) { + unsigned int type = ynl_attr_type(attr); + + if (type == RTAX_LOCK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->lock = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_MTU) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->mtu = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_WINDOW) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->window = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_RTT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->rtt = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_RTTVAR) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->rttvar = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_SSTHRESH) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ssthresh = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_CWND) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->cwnd = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_ADVMSS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->advmss = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_REORDERING) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->reordering = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_HOPLIMIT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->hoplimit = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_INITCWND) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->initcwnd = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_FEATURES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->features = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_RTO_MIN) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->rto_min = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_INITRWND) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->initrwnd = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_QUICKACK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->quickack = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTAX_CC_ALGO) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->cc_algo.assign(ynl_attr_get_str(attr)); + } else if (type == RTAX_FASTOPEN_NO_COOKIE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->fastopen_no_cookie = (__u32)ynl_attr_get_u32(attr); + } + } + + return 0; +} + +/* ============== RTM_GETROUTE ============== */ +/* RTM_GETROUTE - do */ +int rt_route_getroute_rsp_parse(const struct nlmsghdr *nlh, + struct ynl_parse_arg *yarg) +{ + rt_route_getroute_rsp *dst; + const struct nlattr *attr; + struct ynl_parse_arg parg; + void *hdr; + + dst = (rt_route_getroute_rsp*)yarg->data; + parg.ys = yarg->ys; + + hdr = ynl_nlmsg_data(nlh); + memcpy(&dst->_hdr, hdr, sizeof(struct rtmsg)); + + ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len) { + unsigned int type = ynl_attr_type(attr); + + if (type == RTA_DST) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->dst.assign(data, data + len); + } else if (type == RTA_SRC) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->src.assign(data, data + len); + } else if (type == RTA_IIF) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->iif = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_OIF) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->oif = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_GATEWAY) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->gateway.assign(data, data + len); + } else if (type == RTA_PRIORITY) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->priority = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_PREFSRC) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->prefsrc.assign(data, data + len); + } else if (type == RTA_METRICS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + + parg.rsp_policy = &rt_route_metrics_nest; + parg.data = &dst->metrics.emplace(); + if (rt_route_metrics_parse(&parg, attr)) { + return YNL_PARSE_CB_ERROR; + } + } else if (type == RTA_MULTIPATH) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->multipath.assign(data, data + len); + } else if (type == RTA_FLOW) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->flow = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_CACHEINFO) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + unsigned int struct_sz = sizeof(struct rta_cacheinfo); + dst->cacheinfo.emplace(); + memcpy(&*dst->cacheinfo, ynl_attr_data(attr), std::min(struct_sz, len)); + } else if (type == RTA_TABLE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->table = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_MARK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->mark = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_MFC_STATS) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->mfc_stats.assign(data, data + len); + } else if (type == RTA_VIA) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->via.assign(data, data + len); + } else if (type == RTA_NEWDST) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->newdst.assign(data, data + len); + } else if (type == RTA_PREF) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->pref = (__u8)ynl_attr_get_u8(attr); + } else if (type == RTA_ENCAP_TYPE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->encap_type = (__u16)ynl_attr_get_u16(attr); + } else if (type == RTA_ENCAP) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->encap.assign(data, data + len); + } else if (type == RTA_EXPIRES) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->expires = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_PAD) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + __u8 *data = (__u8*)ynl_attr_data(attr); + dst->pad.assign(data, data + len); + } else if (type == RTA_UID) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->uid = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_TTL_PROPAGATE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ttl_propagate = (__u8)ynl_attr_get_u8(attr); + } else if (type == RTA_IP_PROTO) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ip_proto = (__u8)ynl_attr_get_u8(attr); + } else if (type == RTA_SPORT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->sport = (__u16)ynl_attr_get_u16(attr); + } else if (type == RTA_DPORT) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->dport = (__u16)ynl_attr_get_u16(attr); + } else if (type == RTA_NH_ID) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->nh_id = (__u32)ynl_attr_get_u32(attr); + } else if (type == RTA_FLOWLABEL) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->flowlabel = (__u32)ynl_attr_get_u32(attr); + } + } + + return YNL_PARSE_CB_OK; +} + +std::unique_ptr +rt_route_getroute(ynl_cpp::ynl_socket& ys, rt_route_getroute_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + std::unique_ptr rsp; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_GETROUTE, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_route_route_attrs_nest; + yrs.yarg.rsp_policy = &rt_route_route_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.src.size() > 0) { + ynl_attr_put(nlh, RTA_SRC, req.src.data(), req.src.size()); + } + if (req.dst.size() > 0) { + ynl_attr_put(nlh, RTA_DST, req.dst.data(), req.dst.size()); + } + if (req.iif.has_value()) { + ynl_attr_put_u32(nlh, RTA_IIF, req.iif.value()); + } + if (req.oif.has_value()) { + ynl_attr_put_u32(nlh, RTA_OIF, req.oif.value()); + } + if (req.ip_proto.has_value()) { + ynl_attr_put_u8(nlh, RTA_IP_PROTO, req.ip_proto.value()); + } + if (req.sport.has_value()) { + ynl_attr_put_u16(nlh, RTA_SPORT, req.sport.value()); + } + if (req.dport.has_value()) { + ynl_attr_put_u16(nlh, RTA_DPORT, req.dport.value()); + } + if (req.mark.has_value()) { + ynl_attr_put_u32(nlh, RTA_MARK, req.mark.value()); + } + if (req.uid.has_value()) { + ynl_attr_put_u32(nlh, RTA_UID, req.uid.value()); + } + if (req.flowlabel.has_value()) { + ynl_attr_put_u32(nlh, RTA_FLOWLABEL, req.flowlabel.value()); + } + + rsp.reset(new rt_route_getroute_rsp()); + yrs.yarg.data = rsp.get(); + yrs.cb = rt_route_getroute_rsp_parse; + yrs.rsp_cmd = 24; + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return nullptr; + } + + return rsp; +} + +/* RTM_GETROUTE - dump */ +std::unique_ptr +rt_route_getroute_dump(ynl_cpp::ynl_socket& ys, + rt_route_getroute_req_dump& req) +{ + struct ynl_dump_no_alloc_state yds = {}; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + auto ret = std::make_unique(); + yds.yarg.ys = ys; + yds.yarg.rsp_policy = &rt_route_route_attrs_nest; + yds.yarg.data = ret.get(); + yds.alloc_cb = [](void* arg)->void* {return &(static_cast(arg)->objs.emplace_back());}; + yds.cb = rt_route_getroute_rsp_parse; + yds.rsp_cmd = 24; + + nlh = ynl_msg_start_dump(ys, RTM_GETROUTE); + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + ((struct ynl_sock*)ys)->req_policy = &rt_route_route_attrs_nest; + + err = ynl_exec_dump_no_alloc(ys, nlh, &yds); + if (err < 0) { + return nullptr; + } + + return ret; +} + +/* ============== RTM_NEWROUTE ============== */ +/* RTM_NEWROUTE - do */ +int rt_route_newroute(ynl_cpp::ynl_socket& ys, rt_route_newroute_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_NEWROUTE, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_route_route_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.dst.size() > 0) { + ynl_attr_put(nlh, RTA_DST, req.dst.data(), req.dst.size()); + } + if (req.src.size() > 0) { + ynl_attr_put(nlh, RTA_SRC, req.src.data(), req.src.size()); + } + if (req.iif.has_value()) { + ynl_attr_put_u32(nlh, RTA_IIF, req.iif.value()); + } + if (req.oif.has_value()) { + ynl_attr_put_u32(nlh, RTA_OIF, req.oif.value()); + } + if (req.gateway.size() > 0) { + ynl_attr_put(nlh, RTA_GATEWAY, req.gateway.data(), req.gateway.size()); + } + if (req.priority.has_value()) { + ynl_attr_put_u32(nlh, RTA_PRIORITY, req.priority.value()); + } + if (req.prefsrc.size() > 0) { + ynl_attr_put(nlh, RTA_PREFSRC, req.prefsrc.data(), req.prefsrc.size()); + } + if (req.metrics.has_value()) { + rt_route_metrics_put(nlh, RTA_METRICS, req.metrics.value()); + } + if (req.multipath.size() > 0) { + ynl_attr_put(nlh, RTA_MULTIPATH, req.multipath.data(), req.multipath.size()); + } + if (req.flow.has_value()) { + ynl_attr_put_u32(nlh, RTA_FLOW, req.flow.value()); + } + if (req.cacheinfo) { + ynl_attr_put(nlh, RTA_CACHEINFO, &*req.cacheinfo, sizeof(struct rta_cacheinfo)); + } + if (req.table.has_value()) { + ynl_attr_put_u32(nlh, RTA_TABLE, req.table.value()); + } + if (req.mark.has_value()) { + ynl_attr_put_u32(nlh, RTA_MARK, req.mark.value()); + } + if (req.mfc_stats.size() > 0) { + ynl_attr_put(nlh, RTA_MFC_STATS, req.mfc_stats.data(), req.mfc_stats.size()); + } + if (req.via.size() > 0) { + ynl_attr_put(nlh, RTA_VIA, req.via.data(), req.via.size()); + } + if (req.newdst.size() > 0) { + ynl_attr_put(nlh, RTA_NEWDST, req.newdst.data(), req.newdst.size()); + } + if (req.pref.has_value()) { + ynl_attr_put_u8(nlh, RTA_PREF, req.pref.value()); + } + if (req.encap_type.has_value()) { + ynl_attr_put_u16(nlh, RTA_ENCAP_TYPE, req.encap_type.value()); + } + if (req.encap.size() > 0) { + ynl_attr_put(nlh, RTA_ENCAP, req.encap.data(), req.encap.size()); + } + if (req.expires.has_value()) { + ynl_attr_put_u32(nlh, RTA_EXPIRES, req.expires.value()); + } + if (req.pad.size() > 0) { + ynl_attr_put(nlh, RTA_PAD, req.pad.data(), req.pad.size()); + } + if (req.uid.has_value()) { + ynl_attr_put_u32(nlh, RTA_UID, req.uid.value()); + } + if (req.ttl_propagate.has_value()) { + ynl_attr_put_u8(nlh, RTA_TTL_PROPAGATE, req.ttl_propagate.value()); + } + if (req.ip_proto.has_value()) { + ynl_attr_put_u8(nlh, RTA_IP_PROTO, req.ip_proto.value()); + } + if (req.sport.has_value()) { + ynl_attr_put_u16(nlh, RTA_SPORT, req.sport.value()); + } + if (req.dport.has_value()) { + ynl_attr_put_u16(nlh, RTA_DPORT, req.dport.value()); + } + if (req.nh_id.has_value()) { + ynl_attr_put_u32(nlh, RTA_NH_ID, req.nh_id.value()); + } + if (req.flowlabel.has_value()) { + ynl_attr_put_u32(nlh, RTA_FLOWLABEL, req.flowlabel.value()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +/* ============== RTM_DELROUTE ============== */ +/* RTM_DELROUTE - do */ +int rt_route_delroute(ynl_cpp::ynl_socket& ys, rt_route_delroute_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_DELROUTE, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_route_route_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.dst.size() > 0) { + ynl_attr_put(nlh, RTA_DST, req.dst.data(), req.dst.size()); + } + if (req.src.size() > 0) { + ynl_attr_put(nlh, RTA_SRC, req.src.data(), req.src.size()); + } + if (req.iif.has_value()) { + ynl_attr_put_u32(nlh, RTA_IIF, req.iif.value()); + } + if (req.oif.has_value()) { + ynl_attr_put_u32(nlh, RTA_OIF, req.oif.value()); + } + if (req.gateway.size() > 0) { + ynl_attr_put(nlh, RTA_GATEWAY, req.gateway.data(), req.gateway.size()); + } + if (req.priority.has_value()) { + ynl_attr_put_u32(nlh, RTA_PRIORITY, req.priority.value()); + } + if (req.prefsrc.size() > 0) { + ynl_attr_put(nlh, RTA_PREFSRC, req.prefsrc.data(), req.prefsrc.size()); + } + if (req.metrics.has_value()) { + rt_route_metrics_put(nlh, RTA_METRICS, req.metrics.value()); + } + if (req.multipath.size() > 0) { + ynl_attr_put(nlh, RTA_MULTIPATH, req.multipath.data(), req.multipath.size()); + } + if (req.flow.has_value()) { + ynl_attr_put_u32(nlh, RTA_FLOW, req.flow.value()); + } + if (req.cacheinfo) { + ynl_attr_put(nlh, RTA_CACHEINFO, &*req.cacheinfo, sizeof(struct rta_cacheinfo)); + } + if (req.table.has_value()) { + ynl_attr_put_u32(nlh, RTA_TABLE, req.table.value()); + } + if (req.mark.has_value()) { + ynl_attr_put_u32(nlh, RTA_MARK, req.mark.value()); + } + if (req.mfc_stats.size() > 0) { + ynl_attr_put(nlh, RTA_MFC_STATS, req.mfc_stats.data(), req.mfc_stats.size()); + } + if (req.via.size() > 0) { + ynl_attr_put(nlh, RTA_VIA, req.via.data(), req.via.size()); + } + if (req.newdst.size() > 0) { + ynl_attr_put(nlh, RTA_NEWDST, req.newdst.data(), req.newdst.size()); + } + if (req.pref.has_value()) { + ynl_attr_put_u8(nlh, RTA_PREF, req.pref.value()); + } + if (req.encap_type.has_value()) { + ynl_attr_put_u16(nlh, RTA_ENCAP_TYPE, req.encap_type.value()); + } + if (req.encap.size() > 0) { + ynl_attr_put(nlh, RTA_ENCAP, req.encap.data(), req.encap.size()); + } + if (req.expires.has_value()) { + ynl_attr_put_u32(nlh, RTA_EXPIRES, req.expires.value()); + } + if (req.pad.size() > 0) { + ynl_attr_put(nlh, RTA_PAD, req.pad.data(), req.pad.size()); + } + if (req.uid.has_value()) { + ynl_attr_put_u32(nlh, RTA_UID, req.uid.value()); + } + if (req.ttl_propagate.has_value()) { + ynl_attr_put_u8(nlh, RTA_TTL_PROPAGATE, req.ttl_propagate.value()); + } + if (req.ip_proto.has_value()) { + ynl_attr_put_u8(nlh, RTA_IP_PROTO, req.ip_proto.value()); + } + if (req.sport.has_value()) { + ynl_attr_put_u16(nlh, RTA_SPORT, req.sport.value()); + } + if (req.dport.has_value()) { + ynl_attr_put_u16(nlh, RTA_DPORT, req.dport.value()); + } + if (req.nh_id.has_value()) { + ynl_attr_put_u32(nlh, RTA_NH_ID, req.nh_id.value()); + } + if (req.flowlabel.has_value()) { + ynl_attr_put_u32(nlh, RTA_FLOWLABEL, req.flowlabel.value()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +const struct ynl_family ynl_rt_route_family = { + .name = "rt_route", + .is_classic = true, + .classic_id = 0, + .hdr_len = sizeof(struct rtmsg), +}; +const struct ynl_family& get_ynl_rt_route_family() { + return ynl_rt_route_family; +}; +} //namespace ynl_cpp diff --git a/generated/rt-route-user.hpp b/generated/rt-route-user.hpp new file mode 100644 index 0000000..e34bfa6 --- /dev/null +++ b/generated/rt-route-user.hpp @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* */ +/* YNL-GEN user header */ + +#ifndef _LINUX_RT_ROUTE_GEN_H +#define _LINUX_RT_ROUTE_GEN_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ynl.hpp" + +#include + +namespace ynl_cpp { +const struct ynl_family& get_ynl_rt_route_family(); + +/* Enums */ +std::string_view rt_route_op_str(int op); +std::string_view rt_route_rtm_type_str(int value); + +/* Common nested types */ +struct rt_route_metrics { + std::optional<__u32> lock; + std::optional<__u32> mtu; + std::optional<__u32> window; + std::optional<__u32> rtt; + std::optional<__u32> rttvar; + std::optional<__u32> ssthresh; + std::optional<__u32> cwnd; + std::optional<__u32> advmss; + std::optional<__u32> reordering; + std::optional<__u32> hoplimit; + std::optional<__u32> initcwnd; + std::optional<__u32> features; + std::optional<__u32> rto_min; + std::optional<__u32> initrwnd; + std::optional<__u32> quickack; + std::string cc_algo; + std::optional<__u32> fastopen_no_cookie; +}; + +/* ============== RTM_GETROUTE ============== */ +/* RTM_GETROUTE - do */ +struct rt_route_getroute_req { + __u16 _nlmsg_flags; + + struct rtmsg _hdr; + + std::vector<__u8> src; + std::vector<__u8> dst; + std::optional<__u32> iif; + std::optional<__u32> oif; + std::optional<__u8> ip_proto; + std::optional<__u16> sport; + std::optional<__u16> dport; + std::optional<__u32> mark; + std::optional<__u32> uid; + std::optional<__u32> flowlabel /* big-endian */; +}; + +struct rt_route_getroute_rsp { + struct rtmsg _hdr; + + std::vector<__u8> dst; + std::vector<__u8> src; + std::optional<__u32> iif; + std::optional<__u32> oif; + std::vector<__u8> gateway; + std::optional<__u32> priority; + std::vector<__u8> prefsrc; + std::optional metrics; + std::vector<__u8> multipath; + std::optional<__u32> flow; + std::optional cacheinfo; + std::optional<__u32> table; + std::optional<__u32> mark; + std::vector<__u8> mfc_stats; + std::vector<__u8> via; + std::vector<__u8> newdst; + std::optional<__u8> pref; + std::optional<__u16> encap_type; + std::vector<__u8> encap; + std::optional<__u32> expires; + std::vector<__u8> pad; + std::optional<__u32> uid; + std::optional<__u8> ttl_propagate; + std::optional<__u8> ip_proto; + std::optional<__u16> sport; + std::optional<__u16> dport; + std::optional<__u32> nh_id; + std::optional<__u32> flowlabel /* big-endian */; +}; + +/* + * Dump route information. + */ +std::unique_ptr +rt_route_getroute(ynl_cpp::ynl_socket& ys, rt_route_getroute_req& req); + +/* RTM_GETROUTE - dump */ +struct rt_route_getroute_req_dump { + struct rtmsg _hdr; +}; + +struct rt_route_getroute_list { + std::list objs; +}; + +std::unique_ptr +rt_route_getroute_dump(ynl_cpp::ynl_socket& ys, + rt_route_getroute_req_dump& req); + +/* ============== RTM_NEWROUTE ============== */ +/* RTM_NEWROUTE - do */ +struct rt_route_newroute_req { + __u16 _nlmsg_flags; + + struct rtmsg _hdr; + + std::vector<__u8> dst; + std::vector<__u8> src; + std::optional<__u32> iif; + std::optional<__u32> oif; + std::vector<__u8> gateway; + std::optional<__u32> priority; + std::vector<__u8> prefsrc; + std::optional metrics; + std::vector<__u8> multipath; + std::optional<__u32> flow; + std::optional cacheinfo; + std::optional<__u32> table; + std::optional<__u32> mark; + std::vector<__u8> mfc_stats; + std::vector<__u8> via; + std::vector<__u8> newdst; + std::optional<__u8> pref; + std::optional<__u16> encap_type; + std::vector<__u8> encap; + std::optional<__u32> expires; + std::vector<__u8> pad; + std::optional<__u32> uid; + std::optional<__u8> ttl_propagate; + std::optional<__u8> ip_proto; + std::optional<__u16> sport; + std::optional<__u16> dport; + std::optional<__u32> nh_id; + std::optional<__u32> flowlabel /* big-endian */; +}; + +/* + * Create a new route + */ +int rt_route_newroute(ynl_cpp::ynl_socket& ys, rt_route_newroute_req& req); + +/* ============== RTM_DELROUTE ============== */ +/* RTM_DELROUTE - do */ +struct rt_route_delroute_req { + __u16 _nlmsg_flags; + + struct rtmsg _hdr; + + std::vector<__u8> dst; + std::vector<__u8> src; + std::optional<__u32> iif; + std::optional<__u32> oif; + std::vector<__u8> gateway; + std::optional<__u32> priority; + std::vector<__u8> prefsrc; + std::optional metrics; + std::vector<__u8> multipath; + std::optional<__u32> flow; + std::optional cacheinfo; + std::optional<__u32> table; + std::optional<__u32> mark; + std::vector<__u8> mfc_stats; + std::vector<__u8> via; + std::vector<__u8> newdst; + std::optional<__u8> pref; + std::optional<__u16> encap_type; + std::vector<__u8> encap; + std::optional<__u32> expires; + std::vector<__u8> pad; + std::optional<__u32> uid; + std::optional<__u8> ttl_propagate; + std::optional<__u8> ip_proto; + std::optional<__u16> sport; + std::optional<__u16> dport; + std::optional<__u32> nh_id; + std::optional<__u32> flowlabel /* big-endian */; +}; + +/* + * Delete an existing route + */ +int rt_route_delroute(ynl_cpp::ynl_socket& ys, rt_route_delroute_req& req); + +} //namespace ynl_cpp +#endif /* _LINUX_RT_ROUTE_GEN_H */ diff --git a/generated/rt-rule-user.cpp b/generated/rt-rule-user.cpp new file mode 100644 index 0000000..fb12021 --- /dev/null +++ b/generated/rt-rule-user.cpp @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* */ +/* YNL-GEN user source */ + +#include "rt-rule-user.hpp" + +#include + +#include + +#include + +namespace ynl_cpp { + +/* Enums */ +static constexpr std::array rt_rule_op_strmap = []() { + std::array arr{}; + arr[33] = "delrule-ntf"; + arr[32] = "getrule"; + return arr; +} (); + +std::string_view rt_rule_op_str(int op) +{ + if (op < 0 || op >= (int)(rt_rule_op_strmap.size())) { + return ""; + } + return rt_rule_op_strmap[op]; +} + +static constexpr std::array rt_rule_fr_act_strmap = []() { + std::array arr{}; + arr[0] = "unspec"; + arr[1] = "to-tbl"; + arr[2] = "goto"; + arr[3] = "nop"; + arr[4] = "res3"; + arr[5] = "res4"; + arr[6] = "blackhole"; + arr[7] = "unreachable"; + arr[8] = "prohibit"; + return arr; +} (); + +std::string_view rt_rule_fr_act_str(int value) +{ + if (value < 0 || value >= (int)(rt_rule_fr_act_strmap.size())) { + return ""; + } + return rt_rule_fr_act_strmap[value]; +} + +/* Policies */ +static std::array rt_rule_fib_rule_attrs_policy = []() { + std::array arr{}; + arr[FRA_DST].name = "dst"; + arr[FRA_DST].type = YNL_PT_U32; + arr[FRA_SRC].name = "src"; + arr[FRA_SRC].type = YNL_PT_U32; + arr[FRA_IIFNAME].name = "iifname"; + arr[FRA_IIFNAME].type = YNL_PT_NUL_STR; + arr[FRA_GOTO].name = "goto"; + arr[FRA_GOTO].type = YNL_PT_U32; + arr[FRA_UNUSED2].name = "unused2"; + arr[FRA_UNUSED2].type = YNL_PT_IGNORE; + arr[FRA_PRIORITY].name = "priority"; + arr[FRA_PRIORITY].type = YNL_PT_U32; + arr[FRA_UNUSED3].name = "unused3"; + arr[FRA_UNUSED3].type = YNL_PT_IGNORE; + arr[FRA_UNUSED4].name = "unused4"; + arr[FRA_UNUSED4].type = YNL_PT_IGNORE; + arr[FRA_UNUSED5].name = "unused5"; + arr[FRA_UNUSED5].type = YNL_PT_IGNORE; + arr[FRA_FWMARK].name = "fwmark"; + arr[FRA_FWMARK].type = YNL_PT_U32; + arr[FRA_FLOW].name = "flow"; + arr[FRA_FLOW].type = YNL_PT_U32; + arr[FRA_TUN_ID].name = "tun-id"; + arr[FRA_TUN_ID].type = YNL_PT_U64; + arr[FRA_SUPPRESS_IFGROUP].name = "suppress-ifgroup"; + arr[FRA_SUPPRESS_IFGROUP].type = YNL_PT_U32; + arr[FRA_SUPPRESS_PREFIXLEN].name = "suppress-prefixlen"; + arr[FRA_SUPPRESS_PREFIXLEN].type = YNL_PT_U32; + arr[FRA_TABLE].name = "table"; + arr[FRA_TABLE].type = YNL_PT_U32; + arr[FRA_FWMASK].name = "fwmask"; + arr[FRA_FWMASK].type = YNL_PT_U32; + arr[FRA_OIFNAME].name = "oifname"; + arr[FRA_OIFNAME].type = YNL_PT_NUL_STR; + arr[FRA_PAD].name = "pad"; + arr[FRA_PAD].type = YNL_PT_IGNORE; + arr[FRA_L3MDEV].name = "l3mdev"; + arr[FRA_L3MDEV].type = YNL_PT_U8; + arr[FRA_UID_RANGE].name = "uid-range"; + arr[FRA_UID_RANGE].type = YNL_PT_BINARY; + arr[FRA_PROTOCOL].name = "protocol"; + arr[FRA_PROTOCOL].type = YNL_PT_U8; + arr[FRA_IP_PROTO].name = "ip-proto"; + arr[FRA_IP_PROTO].type = YNL_PT_U8; + arr[FRA_SPORT_RANGE].name = "sport-range"; + arr[FRA_SPORT_RANGE].type = YNL_PT_BINARY; + arr[FRA_DPORT_RANGE].name = "dport-range"; + arr[FRA_DPORT_RANGE].type = YNL_PT_BINARY; + arr[FRA_DSCP].name = "dscp"; + arr[FRA_DSCP].type = YNL_PT_U8; + arr[FRA_FLOWLABEL].name = "flowlabel"; + arr[FRA_FLOWLABEL].type = YNL_PT_U32; + arr[FRA_FLOWLABEL_MASK].name = "flowlabel-mask"; + arr[FRA_FLOWLABEL_MASK].type = YNL_PT_U32; + arr[FRA_SPORT_MASK].name = "sport-mask"; + arr[FRA_SPORT_MASK].type = YNL_PT_U16; + arr[FRA_DPORT_MASK].name = "dport-mask"; + arr[FRA_DPORT_MASK].type = YNL_PT_U16; + arr[FRA_DSCP_MASK].name = "dscp-mask"; + arr[FRA_DSCP_MASK].type = YNL_PT_U8; + return arr; +} (); + +struct ynl_policy_nest rt_rule_fib_rule_attrs_nest = { + .max_attr = static_cast(FRA_MAX), + .table = rt_rule_fib_rule_attrs_policy.data(), +}; + +/* Common nested types */ +/* ============== RTM_NEWRULE ============== */ +/* RTM_NEWRULE - do */ +int rt_rule_newrule(ynl_cpp::ynl_socket& ys, rt_rule_newrule_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_NEWRULE, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_rule_fib_rule_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.iifname.size() > 0) { + ynl_attr_put_str(nlh, FRA_IIFNAME, req.iifname.data()); + } + if (req.oifname.size() > 0) { + ynl_attr_put_str(nlh, FRA_OIFNAME, req.oifname.data()); + } + if (req.priority.has_value()) { + ynl_attr_put_u32(nlh, FRA_PRIORITY, req.priority.value()); + } + if (req.fwmark.has_value()) { + ynl_attr_put_u32(nlh, FRA_FWMARK, req.fwmark.value()); + } + if (req.flow.has_value()) { + ynl_attr_put_u32(nlh, FRA_FLOW, req.flow.value()); + } + if (req.tun_id.has_value()) { + ynl_attr_put_u64(nlh, FRA_TUN_ID, req.tun_id.value()); + } + if (req.fwmask.has_value()) { + ynl_attr_put_u32(nlh, FRA_FWMASK, req.fwmask.value()); + } + if (req.table.has_value()) { + ynl_attr_put_u32(nlh, FRA_TABLE, req.table.value()); + } + if (req.suppress_prefixlen.has_value()) { + ynl_attr_put_u32(nlh, FRA_SUPPRESS_PREFIXLEN, req.suppress_prefixlen.value()); + } + if (req.suppress_ifgroup.has_value()) { + ynl_attr_put_u32(nlh, FRA_SUPPRESS_IFGROUP, req.suppress_ifgroup.value()); + } + if (req.goto_.has_value()) { + ynl_attr_put_u32(nlh, FRA_GOTO, req.goto_.value()); + } + if (req.l3mdev.has_value()) { + ynl_attr_put_u8(nlh, FRA_L3MDEV, req.l3mdev.value()); + } + if (req.uid_range) { + ynl_attr_put(nlh, FRA_UID_RANGE, &*req.uid_range, sizeof(struct fib_rule_uid_range)); + } + if (req.protocol.has_value()) { + ynl_attr_put_u8(nlh, FRA_PROTOCOL, req.protocol.value()); + } + if (req.ip_proto.has_value()) { + ynl_attr_put_u8(nlh, FRA_IP_PROTO, req.ip_proto.value()); + } + if (req.sport_range) { + ynl_attr_put(nlh, FRA_SPORT_RANGE, &*req.sport_range, sizeof(struct fib_rule_port_range)); + } + if (req.dport_range) { + ynl_attr_put(nlh, FRA_DPORT_RANGE, &*req.dport_range, sizeof(struct fib_rule_port_range)); + } + if (req.dscp.has_value()) { + ynl_attr_put_u8(nlh, FRA_DSCP, req.dscp.value()); + } + if (req.flowlabel.has_value()) { + ynl_attr_put_u32(nlh, FRA_FLOWLABEL, req.flowlabel.value()); + } + if (req.flowlabel_mask.has_value()) { + ynl_attr_put_u32(nlh, FRA_FLOWLABEL_MASK, req.flowlabel_mask.value()); + } + if (req.sport_mask.has_value()) { + ynl_attr_put_u16(nlh, FRA_SPORT_MASK, req.sport_mask.value()); + } + if (req.dport_mask.has_value()) { + ynl_attr_put_u16(nlh, FRA_DPORT_MASK, req.dport_mask.value()); + } + if (req.dscp_mask.has_value()) { + ynl_attr_put_u8(nlh, FRA_DSCP_MASK, req.dscp_mask.value()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +/* ============== RTM_DELRULE ============== */ +/* RTM_DELRULE - do */ +int rt_rule_delrule(ynl_cpp::ynl_socket& ys, rt_rule_delrule_req& req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + nlh = ynl_msg_start_req(ys, RTM_DELRULE, req._nlmsg_flags); + ((struct ynl_sock*)ys)->req_policy = &rt_rule_fib_rule_attrs_nest; + + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + if (req.iifname.size() > 0) { + ynl_attr_put_str(nlh, FRA_IIFNAME, req.iifname.data()); + } + if (req.oifname.size() > 0) { + ynl_attr_put_str(nlh, FRA_OIFNAME, req.oifname.data()); + } + if (req.priority.has_value()) { + ynl_attr_put_u32(nlh, FRA_PRIORITY, req.priority.value()); + } + if (req.fwmark.has_value()) { + ynl_attr_put_u32(nlh, FRA_FWMARK, req.fwmark.value()); + } + if (req.flow.has_value()) { + ynl_attr_put_u32(nlh, FRA_FLOW, req.flow.value()); + } + if (req.tun_id.has_value()) { + ynl_attr_put_u64(nlh, FRA_TUN_ID, req.tun_id.value()); + } + if (req.fwmask.has_value()) { + ynl_attr_put_u32(nlh, FRA_FWMASK, req.fwmask.value()); + } + if (req.table.has_value()) { + ynl_attr_put_u32(nlh, FRA_TABLE, req.table.value()); + } + if (req.suppress_prefixlen.has_value()) { + ynl_attr_put_u32(nlh, FRA_SUPPRESS_PREFIXLEN, req.suppress_prefixlen.value()); + } + if (req.suppress_ifgroup.has_value()) { + ynl_attr_put_u32(nlh, FRA_SUPPRESS_IFGROUP, req.suppress_ifgroup.value()); + } + if (req.goto_.has_value()) { + ynl_attr_put_u32(nlh, FRA_GOTO, req.goto_.value()); + } + if (req.l3mdev.has_value()) { + ynl_attr_put_u8(nlh, FRA_L3MDEV, req.l3mdev.value()); + } + if (req.uid_range) { + ynl_attr_put(nlh, FRA_UID_RANGE, &*req.uid_range, sizeof(struct fib_rule_uid_range)); + } + if (req.protocol.has_value()) { + ynl_attr_put_u8(nlh, FRA_PROTOCOL, req.protocol.value()); + } + if (req.ip_proto.has_value()) { + ynl_attr_put_u8(nlh, FRA_IP_PROTO, req.ip_proto.value()); + } + if (req.sport_range) { + ynl_attr_put(nlh, FRA_SPORT_RANGE, &*req.sport_range, sizeof(struct fib_rule_port_range)); + } + if (req.dport_range) { + ynl_attr_put(nlh, FRA_DPORT_RANGE, &*req.dport_range, sizeof(struct fib_rule_port_range)); + } + if (req.dscp.has_value()) { + ynl_attr_put_u8(nlh, FRA_DSCP, req.dscp.value()); + } + if (req.flowlabel.has_value()) { + ynl_attr_put_u32(nlh, FRA_FLOWLABEL, req.flowlabel.value()); + } + if (req.flowlabel_mask.has_value()) { + ynl_attr_put_u32(nlh, FRA_FLOWLABEL_MASK, req.flowlabel_mask.value()); + } + if (req.sport_mask.has_value()) { + ynl_attr_put_u16(nlh, FRA_SPORT_MASK, req.sport_mask.value()); + } + if (req.dport_mask.has_value()) { + ynl_attr_put_u16(nlh, FRA_DPORT_MASK, req.dport_mask.value()); + } + if (req.dscp_mask.has_value()) { + ynl_attr_put_u8(nlh, FRA_DSCP_MASK, req.dscp_mask.value()); + } + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) { + return -1; + } + + return 0; +} + +/* ============== RTM_GETRULE ============== */ +/* RTM_GETRULE - dump */ +int rt_rule_getrule_rsp_parse(const struct nlmsghdr *nlh, + struct ynl_parse_arg *yarg) +{ + const struct nlattr *attr; + rt_rule_getrule_rsp *dst; + void *hdr; + + dst = (rt_rule_getrule_rsp*)yarg->data; + + hdr = ynl_nlmsg_data(nlh); + memcpy(&dst->_hdr, hdr, sizeof(struct fib_rule_hdr)); + + ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len) { + unsigned int type = ynl_attr_type(attr); + + if (type == FRA_IIFNAME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->iifname.assign(ynl_attr_get_str(attr)); + } else if (type == FRA_OIFNAME) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->oifname.assign(ynl_attr_get_str(attr)); + } else if (type == FRA_PRIORITY) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->priority = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_FWMARK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->fwmark = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_FLOW) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->flow = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_TUN_ID) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->tun_id = (__u64)ynl_attr_get_u64(attr); + } else if (type == FRA_FWMASK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->fwmask = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_TABLE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->table = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_SUPPRESS_PREFIXLEN) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->suppress_prefixlen = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_SUPPRESS_IFGROUP) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->suppress_ifgroup = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_GOTO) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->goto_ = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_L3MDEV) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->l3mdev = (__u8)ynl_attr_get_u8(attr); + } else if (type == FRA_UID_RANGE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + unsigned int struct_sz = sizeof(struct fib_rule_uid_range); + dst->uid_range.emplace(); + memcpy(&*dst->uid_range, ynl_attr_data(attr), std::min(struct_sz, len)); + } else if (type == FRA_PROTOCOL) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->protocol = (__u8)ynl_attr_get_u8(attr); + } else if (type == FRA_IP_PROTO) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->ip_proto = (__u8)ynl_attr_get_u8(attr); + } else if (type == FRA_SPORT_RANGE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + unsigned int struct_sz = sizeof(struct fib_rule_port_range); + dst->sport_range.emplace(); + memcpy(&*dst->sport_range, ynl_attr_data(attr), std::min(struct_sz, len)); + } else if (type == FRA_DPORT_RANGE) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + unsigned int len = ynl_attr_data_len(attr); + unsigned int struct_sz = sizeof(struct fib_rule_port_range); + dst->dport_range.emplace(); + memcpy(&*dst->dport_range, ynl_attr_data(attr), std::min(struct_sz, len)); + } else if (type == FRA_DSCP) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->dscp = (__u8)ynl_attr_get_u8(attr); + } else if (type == FRA_FLOWLABEL) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->flowlabel = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_FLOWLABEL_MASK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->flowlabel_mask = (__u32)ynl_attr_get_u32(attr); + } else if (type == FRA_SPORT_MASK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->sport_mask = (__u16)ynl_attr_get_u16(attr); + } else if (type == FRA_DPORT_MASK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->dport_mask = (__u16)ynl_attr_get_u16(attr); + } else if (type == FRA_DSCP_MASK) { + if (ynl_attr_validate(yarg, attr)) { + return YNL_PARSE_CB_ERROR; + } + dst->dscp_mask = (__u8)ynl_attr_get_u8(attr); + } + } + + return YNL_PARSE_CB_OK; +} + +std::unique_ptr +rt_rule_getrule_dump(ynl_cpp::ynl_socket& ys, rt_rule_getrule_req& req) +{ + struct ynl_dump_no_alloc_state yds = {}; + struct nlmsghdr *nlh; + size_t hdr_len; + void *hdr; + int err; + + auto ret = std::make_unique(); + yds.yarg.ys = ys; + yds.yarg.rsp_policy = &rt_rule_fib_rule_attrs_nest; + yds.yarg.data = ret.get(); + yds.alloc_cb = [](void* arg)->void* {return &(static_cast(arg)->objs.emplace_back());}; + yds.cb = rt_rule_getrule_rsp_parse; + yds.rsp_cmd = 32; + + nlh = ynl_msg_start_dump(ys, RTM_GETRULE); + hdr_len = sizeof(req._hdr); + hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len); + memcpy(hdr, &req._hdr, hdr_len); + + ((struct ynl_sock*)ys)->req_policy = &rt_rule_fib_rule_attrs_nest; + + err = ynl_exec_dump_no_alloc(ys, nlh, &yds); + if (err < 0) { + return nullptr; + } + + return ret; +} + +/* RTM_GETRULE - notify */ + +static constexpr std::array rt_rule_ntf_info = []() { + std::array arr{}; + arr[RTM_NEWRULE].policy = &rt_rule_fib_rule_attrs_nest; + arr[RTM_NEWRULE].cb = rt_rule_getrule_rsp_parse; + arr[RTM_DELRULE].policy = &rt_rule_fib_rule_attrs_nest; + arr[RTM_DELRULE].cb = rt_rule_getrule_rsp_parse; + return arr; +} (); + +const struct ynl_family ynl_rt_rule_family = { + .name = "rt_rule", + .is_classic = true, + .classic_id = 0, + .hdr_len = sizeof(struct fib_rule_hdr), + .ntf_info = rt_rule_ntf_info.data(), + .ntf_info_size = rt_rule_ntf_info.size(), +}; +const struct ynl_family& get_ynl_rt_rule_family() { + return ynl_rt_rule_family; +}; +} //namespace ynl_cpp diff --git a/generated/rt-rule-user.hpp b/generated/rt-rule-user.hpp new file mode 100644 index 0000000..ebe1665 --- /dev/null +++ b/generated/rt-rule-user.hpp @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* */ +/* YNL-GEN user header */ + +#ifndef _LINUX_RT_RULE_GEN_H +#define _LINUX_RT_RULE_GEN_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ynl.hpp" + +#include + +namespace ynl_cpp { +const struct ynl_family& get_ynl_rt_rule_family(); + +/* Enums */ +std::string_view rt_rule_op_str(int op); +std::string_view rt_rule_fr_act_str(int value); + +/* Common nested types */ +/* ============== RTM_NEWRULE ============== */ +/* RTM_NEWRULE - do */ +struct rt_rule_newrule_req { + __u16 _nlmsg_flags; + + struct fib_rule_hdr _hdr; + + std::string iifname; + std::string oifname; + std::optional<__u32> priority; + std::optional<__u32> fwmark; + std::optional<__u32> flow; + std::optional<__u64> tun_id; + std::optional<__u32> fwmask; + std::optional<__u32> table; + std::optional<__u32> suppress_prefixlen; + std::optional<__u32> suppress_ifgroup; + std::optional<__u32> goto_; + std::optional<__u8> l3mdev; + std::optional uid_range; + std::optional<__u8> protocol; + std::optional<__u8> ip_proto; + std::optional sport_range; + std::optional dport_range; + std::optional<__u8> dscp; + std::optional<__u32> flowlabel /* big-endian */; + std::optional<__u32> flowlabel_mask /* big-endian */; + std::optional<__u16> sport_mask; + std::optional<__u16> dport_mask; + std::optional<__u8> dscp_mask; +}; + +/* + * Add new FIB rule + */ +int rt_rule_newrule(ynl_cpp::ynl_socket& ys, rt_rule_newrule_req& req); + +/* ============== RTM_DELRULE ============== */ +/* RTM_DELRULE - do */ +struct rt_rule_delrule_req { + __u16 _nlmsg_flags; + + struct fib_rule_hdr _hdr; + + std::string iifname; + std::string oifname; + std::optional<__u32> priority; + std::optional<__u32> fwmark; + std::optional<__u32> flow; + std::optional<__u64> tun_id; + std::optional<__u32> fwmask; + std::optional<__u32> table; + std::optional<__u32> suppress_prefixlen; + std::optional<__u32> suppress_ifgroup; + std::optional<__u32> goto_; + std::optional<__u8> l3mdev; + std::optional uid_range; + std::optional<__u8> protocol; + std::optional<__u8> ip_proto; + std::optional sport_range; + std::optional dport_range; + std::optional<__u8> dscp; + std::optional<__u32> flowlabel /* big-endian */; + std::optional<__u32> flowlabel_mask /* big-endian */; + std::optional<__u16> sport_mask; + std::optional<__u16> dport_mask; + std::optional<__u8> dscp_mask; +}; + +/* + * Remove an existing FIB rule + */ +int rt_rule_delrule(ynl_cpp::ynl_socket& ys, rt_rule_delrule_req& req); + +/* ============== RTM_GETRULE ============== */ +/* RTM_GETRULE - dump */ +struct rt_rule_getrule_req { + struct fib_rule_hdr _hdr; +}; + +struct rt_rule_getrule_rsp { + struct fib_rule_hdr _hdr; + + std::string iifname; + std::string oifname; + std::optional<__u32> priority; + std::optional<__u32> fwmark; + std::optional<__u32> flow; + std::optional<__u64> tun_id; + std::optional<__u32> fwmask; + std::optional<__u32> table; + std::optional<__u32> suppress_prefixlen; + std::optional<__u32> suppress_ifgroup; + std::optional<__u32> goto_; + std::optional<__u8> l3mdev; + std::optional uid_range; + std::optional<__u8> protocol; + std::optional<__u8> ip_proto; + std::optional sport_range; + std::optional dport_range; + std::optional<__u8> dscp; + std::optional<__u32> flowlabel /* big-endian */; + std::optional<__u32> flowlabel_mask /* big-endian */; + std::optional<__u16> sport_mask; + std::optional<__u16> dport_mask; + std::optional<__u8> dscp_mask; +}; + +struct rt_rule_getrule_list { + std::list objs; +}; + +std::unique_ptr +rt_rule_getrule_dump(ynl_cpp::ynl_socket& ys, rt_rule_getrule_req& req); + +/* RTM_GETRULE - notify */ +struct rt_rule_getrule_ntf { +}; + +} //namespace ynl_cpp +#endif /* _LINUX_RT_RULE_GEN_H */ diff --git a/samples/.gitignore b/samples/.gitignore index 059dfa0..67bc2fd 100644 --- a/samples/.gitignore +++ b/samples/.gitignore @@ -2,3 +2,4 @@ ethtool netdev rt-addr rt-link +rt-route \ No newline at end of file diff --git a/samples/rt-route.cpp b/samples/rt-route.cpp new file mode 100644 index 0000000..b492f3a --- /dev/null +++ b/samples/rt-route.cpp @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +std::ostream &operator<<(std::ostream &os, + const ynl_cpp::rt_route_getroute_rsp &rsp) +{ + char ifname[IF_NAMESIZE]; + char route_str[64]; + + /* Ignore local */ + if (rsp._hdr.rtm_table == RT_TABLE_LOCAL) + return os; + + if (rsp.oif) + { + auto name = if_indextoname(*rsp.oif, ifname); + if (name) + os << "oif: " << std::setw(16) << name; + } + + if (rsp.dst.size()) + { + auto route = inet_ntop(rsp._hdr.rtm_family, rsp.dst.data(), + route_str, sizeof(route_str)); + os << " dst: " << route << "/" << (int)rsp._hdr.rtm_dst_len; + } + + if (rsp.gateway.size()) + { + auto route = inet_ntop(rsp._hdr.rtm_family, rsp.gateway.data(), + route_str, sizeof(route_str)); + os << " gateway: " << route; + } + + os << std::endl; + return os; +} + +int main(int argc, char **argv) +{ + ynl_error yerr; + ynl_cpp::ynl_socket ys(ynl_cpp::get_ynl_rt_route_family(), &yerr); + if (!ys) + { + std::cerr << yerr.msg << std::endl; + return -1; + } + + ynl_cpp::rt_route_getroute_req_dump req = {}; + std::unique_ptr rsp = + ynl_cpp::rt_route_getroute_dump(ys, req); + if (rsp == nullptr) + { + std::cerr << "Error: rt-route getroute dump fails" << std::endl; + return 2; + } + + if (ynl_dump_empty(rsp.get())) + std::cerr << "Error: no routeesses reported" << std::endl; + for (const auto &route : rsp->objs) + std::cout << route; + + return 0; +}