diff --git a/home/nipa/nipa_out/1017472/ynl/new-code/wireguard-user.c b/home/nipa/nipa_out/1017472/ynl/new-code/wireguard-user.c new file mode 100644 index 000000000000..7403004c5e9a --- /dev/null +++ b/home/nipa/nipa_out/1017472/ynl/new-code/wireguard-user.c @@ -0,0 +1,555 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/wireguard.yaml */ +/* YNL-GEN user source */ + +#include +#include +#include "wireguard-user.h" +#include "ynl.h" +#include +#include + +#include + +/* Enums */ +static const char * const wireguard_op_strmap[] = { + [WG_CMD_SET_DEVICE] = "set-device", +}; + +const char *wireguard_op_str(int op) +{ + if (op < 0 || op >= (int)YNL_ARRAY_SIZE(wireguard_op_strmap)) + return NULL; + return wireguard_op_strmap[op]; +} + +static const char * const wireguard_wgdevice_flags_strmap[] = { + [0] = "replace-peers", +}; + +const char *wireguard_wgdevice_flags_str(enum wgdevice_flag value) +{ + value = ffs(value) - 1; + if (value < 0 || value >= (int)YNL_ARRAY_SIZE(wireguard_wgdevice_flags_strmap)) + return NULL; + return wireguard_wgdevice_flags_strmap[value]; +} + +static const char * const wireguard_wgpeer_flags_strmap[] = { + [0] = "remove-me", + [1] = "replace-allowedips", + [2] = "update-only", +}; + +const char *wireguard_wgpeer_flags_str(enum wgpeer_flag value) +{ + value = ffs(value) - 1; + if (value < 0 || value >= (int)YNL_ARRAY_SIZE(wireguard_wgpeer_flags_strmap)) + return NULL; + return wireguard_wgpeer_flags_strmap[value]; +} + +static const char * const wireguard_wgallowedip_flags_strmap[] = { + [0] = "remove-me", +}; + +const char *wireguard_wgallowedip_flags_str(enum wgallowedip_flag value) +{ + value = ffs(value) - 1; + if (value < 0 || value >= (int)YNL_ARRAY_SIZE(wireguard_wgallowedip_flags_strmap)) + return NULL; + return wireguard_wgallowedip_flags_strmap[value]; +} + +/* Policies */ +const struct ynl_policy_attr wireguard_wgallowedip_policy[WGALLOWEDIP_A_MAX + 1] = { + [WGALLOWEDIP_A_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, + [WGALLOWEDIP_A_FAMILY] = { .name = "family", .type = YNL_PT_U16, }, + [WGALLOWEDIP_A_IPADDR] = { .name = "ipaddr", .type = YNL_PT_BINARY,}, + [WGALLOWEDIP_A_CIDR_MASK] = { .name = "cidr-mask", .type = YNL_PT_U8, }, + [WGALLOWEDIP_A_FLAGS] = { .name = "flags", .type = YNL_PT_U32, }, +}; + +const struct ynl_policy_nest wireguard_wgallowedip_nest = { + .max_attr = WGALLOWEDIP_A_MAX, + .table = wireguard_wgallowedip_policy, +}; + +const struct ynl_policy_attr wireguard_wgpeer_policy[WGPEER_A_MAX + 1] = { + [WGPEER_A_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, + [WGPEER_A_PUBLIC_KEY] = { .name = "public-key", .type = YNL_PT_BINARY,}, + [WGPEER_A_PRESHARED_KEY] = { .name = "preshared-key", .type = YNL_PT_BINARY,}, + [WGPEER_A_FLAGS] = { .name = "flags", .type = YNL_PT_U32, }, + [WGPEER_A_ENDPOINT] = { .name = "endpoint", .type = YNL_PT_BINARY,}, + [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .name = "persistent-keepalive-interval", .type = YNL_PT_U16, }, + [WGPEER_A_LAST_HANDSHAKE_TIME] = { .name = "last-handshake-time", .type = YNL_PT_BINARY,}, + [WGPEER_A_RX_BYTES] = { .name = "rx-bytes", .type = YNL_PT_U64, }, + [WGPEER_A_TX_BYTES] = { .name = "tx-bytes", .type = YNL_PT_U64, }, + [WGPEER_A_ALLOWEDIPS] = { .name = "allowedips", .type = YNL_PT_NEST, .nest = &wireguard_wgallowedip_nest, }, + [WGPEER_A_PROTOCOL_VERSION] = { .name = "protocol-version", .type = YNL_PT_U32, }, +}; + +const struct ynl_policy_nest wireguard_wgpeer_nest = { + .max_attr = WGPEER_A_MAX, + .table = wireguard_wgpeer_policy, +}; + +const struct ynl_policy_attr wireguard_wgdevice_policy[WGDEVICE_A_MAX + 1] = { + [WGDEVICE_A_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, + [WGDEVICE_A_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, }, + [WGDEVICE_A_IFNAME] = { .name = "ifname", .type = YNL_PT_NUL_STR, }, + [WGDEVICE_A_PRIVATE_KEY] = { .name = "private-key", .type = YNL_PT_BINARY,}, + [WGDEVICE_A_PUBLIC_KEY] = { .name = "public-key", .type = YNL_PT_BINARY,}, + [WGDEVICE_A_FLAGS] = { .name = "flags", .type = YNL_PT_U32, }, + [WGDEVICE_A_LISTEN_PORT] = { .name = "listen-port", .type = YNL_PT_U16, }, + [WGDEVICE_A_FWMARK] = { .name = "fwmark", .type = YNL_PT_U32, }, + [WGDEVICE_A_PEERS] = { .name = "peers", .type = YNL_PT_NEST, .nest = &wireguard_wgpeer_nest, }, +}; + +const struct ynl_policy_nest wireguard_wgdevice_nest = { + .max_attr = WGDEVICE_A_MAX, + .table = wireguard_wgdevice_policy, +}; + +/* Common nested types */ +void wireguard_wgallowedip_free(struct wireguard_wgallowedip *obj) +{ + free(obj->ipaddr); +} + +int wireguard_wgallowedip_put(struct nlmsghdr *nlh, unsigned int attr_type, + struct wireguard_wgallowedip *obj) +{ + struct nlattr *nest; + + nest = ynl_attr_nest_start(nlh, attr_type); + if (obj->_present.family) + ynl_attr_put_u16(nlh, WGALLOWEDIP_A_FAMILY, obj->family); + if (obj->_len.ipaddr) + ynl_attr_put(nlh, WGALLOWEDIP_A_IPADDR, obj->ipaddr, obj->_len.ipaddr); + if (obj->_present.cidr_mask) + ynl_attr_put_u8(nlh, WGALLOWEDIP_A_CIDR_MASK, obj->cidr_mask); + if (obj->_present.flags) + ynl_attr_put_u32(nlh, WGALLOWEDIP_A_FLAGS, obj->flags); + ynl_attr_nest_end(nlh, nest); + + return 0; +} + +int wireguard_wgallowedip_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested, __u32 idx) +{ + struct wireguard_wgallowedip *dst = yarg->data; + const struct nlattr *attr; + unsigned int len; + + dst->idx = idx; + + ynl_attr_for_each_nested(attr, nested) { + unsigned int type = ynl_attr_type(attr); + + if (type == WGALLOWEDIP_A_FAMILY) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.family = 1; + dst->family = ynl_attr_get_u16(attr); + } else if (type == WGALLOWEDIP_A_IPADDR) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.ipaddr = len; + dst->ipaddr = malloc(len); + memcpy(dst->ipaddr, ynl_attr_data(attr), len); + } else if (type == WGALLOWEDIP_A_CIDR_MASK) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.cidr_mask = 1; + dst->cidr_mask = ynl_attr_get_u8(attr); + } else if (type == WGALLOWEDIP_A_FLAGS) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.flags = 1; + dst->flags = ynl_attr_get_u32(attr); + } + } + + return 0; +} + +void wireguard_wgpeer_free(struct wireguard_wgpeer *obj) +{ + free(obj->public_key); + free(obj->preshared_key); + free(obj->endpoint); + free(obj->last_handshake_time); + free(obj->allowedips); +} + +int wireguard_wgpeer_put(struct nlmsghdr *nlh, unsigned int attr_type, + struct wireguard_wgpeer *obj) +{ + struct nlattr *array; + struct nlattr *nest; + unsigned int i; + + nest = ynl_attr_nest_start(nlh, attr_type); + if (obj->_len.public_key) + ynl_attr_put(nlh, WGPEER_A_PUBLIC_KEY, obj->public_key, obj->_len.public_key); + if (obj->_len.preshared_key) + ynl_attr_put(nlh, WGPEER_A_PRESHARED_KEY, obj->preshared_key, obj->_len.preshared_key); + if (obj->_present.flags) + ynl_attr_put_u32(nlh, WGPEER_A_FLAGS, obj->flags); + if (obj->_len.endpoint) + ynl_attr_put(nlh, WGPEER_A_ENDPOINT, obj->endpoint, obj->_len.endpoint); + if (obj->_present.persistent_keepalive_interval) + ynl_attr_put_u16(nlh, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, obj->persistent_keepalive_interval); + if (obj->_len.last_handshake_time) + ynl_attr_put(nlh, WGPEER_A_LAST_HANDSHAKE_TIME, obj->last_handshake_time, obj->_len.last_handshake_time); + if (obj->_present.rx_bytes) + ynl_attr_put_u64(nlh, WGPEER_A_RX_BYTES, obj->rx_bytes); + if (obj->_present.tx_bytes) + ynl_attr_put_u64(nlh, WGPEER_A_TX_BYTES, obj->tx_bytes); + array = ynl_attr_nest_start(nlh, WGPEER_A_ALLOWEDIPS); + for (i = 0; i < obj->_count.allowedips; i++) + wireguard_wgallowedip_put(nlh, i, &obj->allowedips[i]); + ynl_attr_nest_end(nlh, array); + if (obj->_present.protocol_version) + ynl_attr_put_u32(nlh, WGPEER_A_PROTOCOL_VERSION, obj->protocol_version); + ynl_attr_nest_end(nlh, nest); + + return 0; +} + +int wireguard_wgpeer_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested, __u32 idx) +{ + const struct nlattr *attr_allowedips = NULL; + struct wireguard_wgpeer *dst = yarg->data; + unsigned int n_allowedips = 0; + const struct nlattr *attr2; + const struct nlattr *attr; + struct ynl_parse_arg parg; + unsigned int len; + int i; + + parg.ys = yarg->ys; + + dst->idx = idx; + if (dst->allowedips) + return ynl_error_parse(yarg, "attribute already present (wgpeer.allowedips)"); + + ynl_attr_for_each_nested(attr, nested) { + unsigned int type = ynl_attr_type(attr); + + if (type == WGPEER_A_PUBLIC_KEY) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.public_key = len; + dst->public_key = malloc(len); + memcpy(dst->public_key, ynl_attr_data(attr), len); + } else if (type == WGPEER_A_PRESHARED_KEY) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.preshared_key = len; + dst->preshared_key = malloc(len); + memcpy(dst->preshared_key, ynl_attr_data(attr), len); + } else if (type == WGPEER_A_FLAGS) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.flags = 1; + dst->flags = ynl_attr_get_u32(attr); + } else if (type == WGPEER_A_ENDPOINT) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.endpoint = len; + dst->endpoint = malloc(len); + memcpy(dst->endpoint, ynl_attr_data(attr), len); + } else if (type == WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.persistent_keepalive_interval = 1; + dst->persistent_keepalive_interval = ynl_attr_get_u16(attr); + } else if (type == WGPEER_A_LAST_HANDSHAKE_TIME) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.last_handshake_time = len; + if (len < sizeof(struct __kernel_timespec)) + dst->last_handshake_time = calloc(1, sizeof(struct __kernel_timespec)); + else + dst->last_handshake_time = malloc(len); + memcpy(dst->last_handshake_time, ynl_attr_data(attr), len); + } else if (type == WGPEER_A_RX_BYTES) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.rx_bytes = 1; + dst->rx_bytes = ynl_attr_get_u64(attr); + } else if (type == WGPEER_A_TX_BYTES) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.tx_bytes = 1; + dst->tx_bytes = ynl_attr_get_u64(attr); + } else if (type == WGPEER_A_ALLOWEDIPS) { + attr_allowedips = attr; + ynl_attr_for_each_nested(attr2, attr) { + if (__ynl_attr_validate(yarg, attr2, type)) + return YNL_PARSE_CB_ERROR; + n_allowedips++; + } + } else if (type == WGPEER_A_PROTOCOL_VERSION) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.protocol_version = 1; + dst->protocol_version = ynl_attr_get_u32(attr); + } + } + + if (n_allowedips) { + dst->allowedips = calloc(n_allowedips, sizeof(*dst->allowedips)); + dst->_count.allowedips = n_allowedips; + i = 0; + parg.rsp_policy = &wireguard_wgallowedip_nest; + ynl_attr_for_each_nested(attr, attr_allowedips) { + parg.data = &dst->allowedips[i]; + if (wireguard_wgallowedip_parse(&parg, attr, ynl_attr_type(attr))) + return YNL_PARSE_CB_ERROR; + i++; + } + } + + return 0; +} + +/* ============== WG_CMD_GET_DEVICE ============== */ +/* WG_CMD_GET_DEVICE - dump */ +int wireguard_get_device_rsp_parse(const struct nlmsghdr *nlh, + struct ynl_parse_arg *yarg) +{ + const struct nlattr *attr_peers = NULL; + struct wireguard_get_device_rsp *dst; + const struct nlattr *attr2; + const struct nlattr *attr; + struct ynl_parse_arg parg; + unsigned int n_peers = 0; + unsigned int len; + int i; + + dst = yarg->data; + parg.ys = yarg->ys; + + if (dst->peers) + return ynl_error_parse(yarg, "attribute already present (wgdevice.peers)"); + + ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len) { + unsigned int type = ynl_attr_type(attr); + + if (type == WGDEVICE_A_IFINDEX) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.ifindex = 1; + dst->ifindex = ynl_attr_get_u32(attr); + } else if (type == WGDEVICE_A_IFNAME) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = strnlen(ynl_attr_get_str(attr), ynl_attr_data_len(attr)); + dst->_len.ifname = len; + dst->ifname = malloc(len + 1); + memcpy(dst->ifname, ynl_attr_get_str(attr), len); + dst->ifname[len] = 0; + } else if (type == WGDEVICE_A_PRIVATE_KEY) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.private_key = len; + dst->private_key = malloc(len); + memcpy(dst->private_key, ynl_attr_data(attr), len); + } else if (type == WGDEVICE_A_PUBLIC_KEY) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = ynl_attr_data_len(attr); + dst->_len.public_key = len; + dst->public_key = malloc(len); + memcpy(dst->public_key, ynl_attr_data(attr), len); + } else if (type == WGDEVICE_A_FLAGS) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.flags = 1; + dst->flags = ynl_attr_get_u32(attr); + } else if (type == WGDEVICE_A_LISTEN_PORT) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.listen_port = 1; + dst->listen_port = ynl_attr_get_u16(attr); + } else if (type == WGDEVICE_A_FWMARK) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.fwmark = 1; + dst->fwmark = ynl_attr_get_u32(attr); + } else if (type == WGDEVICE_A_PEERS) { + attr_peers = attr; + ynl_attr_for_each_nested(attr2, attr) { + if (__ynl_attr_validate(yarg, attr2, type)) + return YNL_PARSE_CB_ERROR; + n_peers++; + } + } + } + + if (n_peers) { + dst->peers = calloc(n_peers, sizeof(*dst->peers)); + dst->_count.peers = n_peers; + i = 0; + parg.rsp_policy = &wireguard_wgpeer_nest; + ynl_attr_for_each_nested(attr, attr_peers) { + parg.data = &dst->peers[i]; + if (wireguard_wgpeer_parse(&parg, attr, ynl_attr_type(attr))) + return YNL_PARSE_CB_ERROR; + i++; + } + } + + return YNL_PARSE_CB_OK; +} + +void wireguard_get_device_req_free(struct wireguard_get_device_req *req) +{ + free(req->ifname); + free(req->private_key); + free(req->public_key); + free(req->peers); + free(req); +} + +void wireguard_get_device_list_free(struct wireguard_get_device_list *rsp) +{ + struct wireguard_get_device_list *next = rsp; + + while ((void *)next != YNL_LIST_END) { + rsp = next; + next = rsp->next; + + free(rsp->obj.ifname); + free(rsp->obj.private_key); + free(rsp->obj.public_key); + free(rsp->obj.peers); + free(rsp); + } +} + +struct wireguard_get_device_list * +wireguard_get_device_dump(struct ynl_sock *ys, + struct wireguard_get_device_req *req) +{ + struct ynl_dump_state yds = {}; + struct nlmsghdr *nlh; + struct nlattr *array; + unsigned int i; + int err; + + yds.yarg.ys = ys; + yds.yarg.rsp_policy = &wireguard_wgdevice_nest; + yds.yarg.data = NULL; + yds.alloc_sz = sizeof(struct wireguard_get_device_list); + yds.cb = wireguard_get_device_rsp_parse; + yds.rsp_cmd = WG_CMD_GET_DEVICE; + + nlh = ynl_gemsg_start_dump(ys, ys->family_id, WG_CMD_GET_DEVICE, 1); + ys->req_policy = &wireguard_wgdevice_nest; + ys->req_hdr_len = ys->family->hdr_len; + + if (req->_present.ifindex) + ynl_attr_put_u32(nlh, WGDEVICE_A_IFINDEX, req->ifindex); + if (req->_len.ifname) + ynl_attr_put_str(nlh, WGDEVICE_A_IFNAME, req->ifname); + if (req->_len.private_key) + ynl_attr_put(nlh, WGDEVICE_A_PRIVATE_KEY, req->private_key, req->_len.private_key); + if (req->_len.public_key) + ynl_attr_put(nlh, WGDEVICE_A_PUBLIC_KEY, req->public_key, req->_len.public_key); + if (req->_present.flags) + ynl_attr_put_u32(nlh, WGDEVICE_A_FLAGS, req->flags); + if (req->_present.listen_port) + ynl_attr_put_u16(nlh, WGDEVICE_A_LISTEN_PORT, req->listen_port); + if (req->_present.fwmark) + ynl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, req->fwmark); + array = ynl_attr_nest_start(nlh, WGDEVICE_A_PEERS); + for (i = 0; i < req->_count.peers; i++) + wireguard_wgpeer_put(nlh, i, &req->peers[i]); + ynl_attr_nest_end(nlh, array); + + err = ynl_exec_dump(ys, nlh, &yds); + if (err < 0) + goto free_list; + + return yds.first; + +free_list: + wireguard_get_device_list_free(yds.first); + return NULL; +} + +/* ============== WG_CMD_SET_DEVICE ============== */ +/* WG_CMD_SET_DEVICE - do */ +void wireguard_set_device_req_free(struct wireguard_set_device_req *req) +{ + free(req->ifname); + free(req->private_key); + free(req->public_key); + free(req->peers); + free(req); +} + +int wireguard_set_device(struct ynl_sock *ys, + struct wireguard_set_device_req *req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + struct nlattr *array; + unsigned int i; + int err; + + nlh = ynl_gemsg_start_req(ys, ys->family_id, WG_CMD_SET_DEVICE, 1); + ys->req_policy = &wireguard_wgdevice_nest; + ys->req_hdr_len = ys->family->hdr_len; + + if (req->_present.ifindex) + ynl_attr_put_u32(nlh, WGDEVICE_A_IFINDEX, req->ifindex); + if (req->_len.ifname) + ynl_attr_put_str(nlh, WGDEVICE_A_IFNAME, req->ifname); + if (req->_len.private_key) + ynl_attr_put(nlh, WGDEVICE_A_PRIVATE_KEY, req->private_key, req->_len.private_key); + if (req->_len.public_key) + ynl_attr_put(nlh, WGDEVICE_A_PUBLIC_KEY, req->public_key, req->_len.public_key); + if (req->_present.flags) + ynl_attr_put_u32(nlh, WGDEVICE_A_FLAGS, req->flags); + if (req->_present.listen_port) + ynl_attr_put_u16(nlh, WGDEVICE_A_LISTEN_PORT, req->listen_port); + if (req->_present.fwmark) + ynl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, req->fwmark); + array = ynl_attr_nest_start(nlh, WGDEVICE_A_PEERS); + for (i = 0; i < req->_count.peers; i++) + wireguard_wgpeer_put(nlh, i, &req->peers[i]); + ynl_attr_nest_end(nlh, array); + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) + return -1; + + return 0; +} + +const struct ynl_family ynl_wireguard_family = { + .name = "wireguard", + .hdr_len = sizeof(struct genlmsghdr), +}; diff --git a/home/nipa/nipa_out/1017472/ynl/new-code/wireguard-user.h b/home/nipa/nipa_out/1017472/ynl/new-code/wireguard-user.h new file mode 100644 index 000000000000..e42252db88e2 --- /dev/null +++ b/home/nipa/nipa_out/1017472/ynl/new-code/wireguard-user.h @@ -0,0 +1,463 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/wireguard.yaml */ +/* YNL-GEN user header */ + +#ifndef _LINUX_WIREGUARD_GEN_H +#define _LINUX_WIREGUARD_GEN_H + +#include +#include +#include +#include +#include + +struct ynl_sock; + +extern const struct ynl_family ynl_wireguard_family; + +/* Enums */ +const char *wireguard_op_str(int op); +const char *wireguard_wgdevice_flags_str(enum wgdevice_flag value); +const char *wireguard_wgpeer_flags_str(enum wgpeer_flag value); +const char *wireguard_wgallowedip_flags_str(enum wgallowedip_flag value); + +/* Common nested types */ +struct wireguard_wgallowedip { + struct { + __u32 family:1; + __u32 cidr_mask:1; + __u32 flags:1; + } _present; + struct { + __u32 ipaddr; + } _len; + + __u32 idx; + __u16 family; + void *ipaddr; + __u8 cidr_mask; + __u32 flags; +}; + +static inline struct wireguard_wgallowedip * +wireguard_wgallowedip_alloc(unsigned int n) +{ + return calloc(n, sizeof(struct wireguard_wgallowedip)); +} + +void wireguard_wgallowedip_free(struct wireguard_wgallowedip *obj); + +static inline void +wireguard_wgallowedip_set_family(struct wireguard_wgallowedip *obj, + __u16 family) +{ + obj->_present.family = 1; + obj->family = family; +} +static inline void +wireguard_wgallowedip_set_ipaddr(struct wireguard_wgallowedip *obj, + const void *ipaddr, size_t len) +{ + free(obj->ipaddr); + obj->_len.ipaddr = len; + obj->ipaddr = malloc(obj->_len.ipaddr); + memcpy(obj->ipaddr, ipaddr, obj->_len.ipaddr); +} +static inline void +wireguard_wgallowedip_set_cidr_mask(struct wireguard_wgallowedip *obj, + __u8 cidr_mask) +{ + obj->_present.cidr_mask = 1; + obj->cidr_mask = cidr_mask; +} +static inline void +wireguard_wgallowedip_set_flags(struct wireguard_wgallowedip *obj, __u32 flags) +{ + obj->_present.flags = 1; + obj->flags = flags; +} + +struct wireguard_wgpeer { + struct { + __u32 flags:1; + __u32 persistent_keepalive_interval:1; + __u32 rx_bytes:1; + __u32 tx_bytes:1; + __u32 protocol_version:1; + } _present; + struct { + __u32 public_key; + __u32 preshared_key; + __u32 endpoint; + __u32 last_handshake_time; + } _len; + struct { + __u32 allowedips; + } _count; + + __u32 idx; + void *public_key; + void *preshared_key; + __u32 flags; + void *endpoint; + __u16 persistent_keepalive_interval; + struct __kernel_timespec *last_handshake_time; + __u64 rx_bytes; + __u64 tx_bytes; + struct wireguard_wgallowedip *allowedips; + __u32 protocol_version; +}; + +static inline struct wireguard_wgpeer *wireguard_wgpeer_alloc(unsigned int n) +{ + return calloc(n, sizeof(struct wireguard_wgpeer)); +} + +void wireguard_wgpeer_free(struct wireguard_wgpeer *obj); + +static inline void +wireguard_wgpeer_set_public_key(struct wireguard_wgpeer *obj, + const void *public_key, size_t len) +{ + free(obj->public_key); + obj->_len.public_key = len; + obj->public_key = malloc(obj->_len.public_key); + memcpy(obj->public_key, public_key, obj->_len.public_key); +} +static inline void +wireguard_wgpeer_set_preshared_key(struct wireguard_wgpeer *obj, + const void *preshared_key, size_t len) +{ + free(obj->preshared_key); + obj->_len.preshared_key = len; + obj->preshared_key = malloc(obj->_len.preshared_key); + memcpy(obj->preshared_key, preshared_key, obj->_len.preshared_key); +} +static inline void +wireguard_wgpeer_set_flags(struct wireguard_wgpeer *obj, __u32 flags) +{ + obj->_present.flags = 1; + obj->flags = flags; +} +static inline void +wireguard_wgpeer_set_endpoint(struct wireguard_wgpeer *obj, + const void *endpoint, size_t len) +{ + free(obj->endpoint); + obj->_len.endpoint = len; + obj->endpoint = malloc(obj->_len.endpoint); + memcpy(obj->endpoint, endpoint, obj->_len.endpoint); +} +static inline void +wireguard_wgpeer_set_persistent_keepalive_interval(struct wireguard_wgpeer *obj, + __u16 persistent_keepalive_interval) +{ + obj->_present.persistent_keepalive_interval = 1; + obj->persistent_keepalive_interval = persistent_keepalive_interval; +} +static inline void +wireguard_wgpeer_set_last_handshake_time(struct wireguard_wgpeer *obj, + const void *last_handshake_time, + size_t len) +{ + free(obj->last_handshake_time); + obj->_len.last_handshake_time = len; + obj->last_handshake_time = malloc(obj->_len.last_handshake_time); + memcpy(obj->last_handshake_time, last_handshake_time, obj->_len.last_handshake_time); +} +static inline void +wireguard_wgpeer_set_rx_bytes(struct wireguard_wgpeer *obj, __u64 rx_bytes) +{ + obj->_present.rx_bytes = 1; + obj->rx_bytes = rx_bytes; +} +static inline void +wireguard_wgpeer_set_tx_bytes(struct wireguard_wgpeer *obj, __u64 tx_bytes) +{ + obj->_present.tx_bytes = 1; + obj->tx_bytes = tx_bytes; +} +static inline void +__wireguard_wgpeer_set_allowedips(struct wireguard_wgpeer *obj, + struct wireguard_wgallowedip *allowedips, + unsigned int n_allowedips) +{ + free(obj->allowedips); + obj->allowedips = allowedips; + obj->_count.allowedips = n_allowedips; +} +static inline void +wireguard_wgpeer_set_protocol_version(struct wireguard_wgpeer *obj, + __u32 protocol_version) +{ + obj->_present.protocol_version = 1; + obj->protocol_version = protocol_version; +} + +/* ============== WG_CMD_GET_DEVICE ============== */ +/* WG_CMD_GET_DEVICE - dump */ +struct wireguard_get_device_req { + struct { + __u32 ifindex:1; + __u32 flags:1; + __u32 listen_port:1; + __u32 fwmark:1; + } _present; + struct { + __u32 ifname; + __u32 private_key; + __u32 public_key; + } _len; + struct { + __u32 peers; + } _count; + + __u32 ifindex; + char *ifname; + void *private_key; + void *public_key; + __u32 flags; + __u16 listen_port; + __u32 fwmark; + struct wireguard_wgpeer *peers; +}; + +static inline struct wireguard_get_device_req * +wireguard_get_device_req_alloc(void) +{ + return calloc(1, sizeof(struct wireguard_get_device_req)); +} +void wireguard_get_device_req_free(struct wireguard_get_device_req *req); + +static inline void +wireguard_get_device_req_set_ifindex(struct wireguard_get_device_req *req, + __u32 ifindex) +{ + req->_present.ifindex = 1; + req->ifindex = ifindex; +} +static inline void +wireguard_get_device_req_set_ifname(struct wireguard_get_device_req *req, + const char *ifname) +{ + free(req->ifname); + req->_len.ifname = strlen(ifname); + req->ifname = malloc(req->_len.ifname + 1); + memcpy(req->ifname, ifname, req->_len.ifname); + req->ifname[req->_len.ifname] = 0; +} +static inline void +wireguard_get_device_req_set_private_key(struct wireguard_get_device_req *req, + const void *private_key, size_t len) +{ + free(req->private_key); + req->_len.private_key = len; + req->private_key = malloc(req->_len.private_key); + memcpy(req->private_key, private_key, req->_len.private_key); +} +static inline void +wireguard_get_device_req_set_public_key(struct wireguard_get_device_req *req, + const void *public_key, size_t len) +{ + free(req->public_key); + req->_len.public_key = len; + req->public_key = malloc(req->_len.public_key); + memcpy(req->public_key, public_key, req->_len.public_key); +} +static inline void +wireguard_get_device_req_set_flags(struct wireguard_get_device_req *req, + __u32 flags) +{ + req->_present.flags = 1; + req->flags = flags; +} +static inline void +wireguard_get_device_req_set_listen_port(struct wireguard_get_device_req *req, + __u16 listen_port) +{ + req->_present.listen_port = 1; + req->listen_port = listen_port; +} +static inline void +wireguard_get_device_req_set_fwmark(struct wireguard_get_device_req *req, + __u32 fwmark) +{ + req->_present.fwmark = 1; + req->fwmark = fwmark; +} +static inline void +__wireguard_get_device_req_set_peers(struct wireguard_get_device_req *req, + struct wireguard_wgpeer *peers, + unsigned int n_peers) +{ + free(req->peers); + req->peers = peers; + req->_count.peers = n_peers; +} + +struct wireguard_get_device_rsp { + struct { + __u32 ifindex:1; + __u32 flags:1; + __u32 listen_port:1; + __u32 fwmark:1; + } _present; + struct { + __u32 ifname; + __u32 private_key; + __u32 public_key; + } _len; + struct { + __u32 peers; + } _count; + + __u32 ifindex; + char *ifname; + void *private_key; + void *public_key; + __u32 flags; + __u16 listen_port; + __u32 fwmark; + struct wireguard_wgpeer *peers; +}; + +struct wireguard_get_device_list { + struct wireguard_get_device_list *next; + struct wireguard_get_device_rsp obj __attribute__((aligned(8))); +}; + +void wireguard_get_device_list_free(struct wireguard_get_device_list *rsp); + +struct wireguard_get_device_list * +wireguard_get_device_dump(struct ynl_sock *ys, + struct wireguard_get_device_req *req); + +/* ============== WG_CMD_SET_DEVICE ============== */ +/* WG_CMD_SET_DEVICE - do */ +struct wireguard_set_device_req { + struct { + __u32 ifindex:1; + __u32 flags:1; + __u32 listen_port:1; + __u32 fwmark:1; + } _present; + struct { + __u32 ifname; + __u32 private_key; + __u32 public_key; + } _len; + struct { + __u32 peers; + } _count; + + __u32 ifindex; + char *ifname; + void *private_key; + void *public_key; + __u32 flags; + __u16 listen_port; + __u32 fwmark; + struct wireguard_wgpeer *peers; +}; + +static inline struct wireguard_set_device_req * +wireguard_set_device_req_alloc(void) +{ + return calloc(1, sizeof(struct wireguard_set_device_req)); +} +void wireguard_set_device_req_free(struct wireguard_set_device_req *req); + +static inline void +wireguard_set_device_req_set_ifindex(struct wireguard_set_device_req *req, + __u32 ifindex) +{ + req->_present.ifindex = 1; + req->ifindex = ifindex; +} +static inline void +wireguard_set_device_req_set_ifname(struct wireguard_set_device_req *req, + const char *ifname) +{ + free(req->ifname); + req->_len.ifname = strlen(ifname); + req->ifname = malloc(req->_len.ifname + 1); + memcpy(req->ifname, ifname, req->_len.ifname); + req->ifname[req->_len.ifname] = 0; +} +static inline void +wireguard_set_device_req_set_private_key(struct wireguard_set_device_req *req, + const void *private_key, size_t len) +{ + free(req->private_key); + req->_len.private_key = len; + req->private_key = malloc(req->_len.private_key); + memcpy(req->private_key, private_key, req->_len.private_key); +} +static inline void +wireguard_set_device_req_set_public_key(struct wireguard_set_device_req *req, + const void *public_key, size_t len) +{ + free(req->public_key); + req->_len.public_key = len; + req->public_key = malloc(req->_len.public_key); + memcpy(req->public_key, public_key, req->_len.public_key); +} +static inline void +wireguard_set_device_req_set_flags(struct wireguard_set_device_req *req, + __u32 flags) +{ + req->_present.flags = 1; + req->flags = flags; +} +static inline void +wireguard_set_device_req_set_listen_port(struct wireguard_set_device_req *req, + __u16 listen_port) +{ + req->_present.listen_port = 1; + req->listen_port = listen_port; +} +static inline void +wireguard_set_device_req_set_fwmark(struct wireguard_set_device_req *req, + __u32 fwmark) +{ + req->_present.fwmark = 1; + req->fwmark = fwmark; +} +static inline void +__wireguard_set_device_req_set_peers(struct wireguard_set_device_req *req, + struct wireguard_wgpeer *peers, + unsigned int n_peers) +{ + free(req->peers); + req->peers = peers; + req->_count.peers = n_peers; +} + +/* + * Set WireGuard device +~~~~~~~~~~~~~~~~~~~~ + +This command should be called with a wgdevice set, containing one +but not both of ``WGDEVICE_A_IFINDEX`` and ``WGDEVICE_A_IFNAME``. + +It is possible that the amount of configuration data exceeds that +of the maximum message length accepted by the kernel. +In that case, several messages should be sent one after another, +with each successive one filling in information not contained in +the prior. +Note that if ``WGDEVICE_F_REPLACE_PEERS`` is specified in the first +message, it probably should not be specified in fragments that come +after, so that the list of peers is only cleared the first time but +appended after. +Likewise for peers, if ``WGPEER_F_REPLACE_ALLOWEDIPS`` is specified +in the first message of a peer, it likely should not be specified +in subsequent fragments. + +If an error occurs, ``NLMSG_ERROR`` will reply containing an errno. + + */ +int wireguard_set_device(struct ynl_sock *ys, + struct wireguard_set_device_req *req); + +#endif /* _LINUX_WIREGUARD_GEN_H */