diff options
author | Thomas Haller <thaller@redhat.com> | 2019-09-01 12:39:55 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-09-01 12:40:08 (GMT) |
commit | 2154891180bbae40af2f1abab5f6c4f7040de81a (patch) | |
tree | 58a6d3a96a27c43cf0df827d8256843159436119 | |
parent | f3d5c44d21243d5eb59bfc2878d4977df2fd1369 (diff) | |
parent | 9af32928c1d03ba3a134dc457adf917ec65d35b8 (diff) | |
download | libnl-2154891180bbae40af2f1abab5f6c4f7040de81a.zip libnl-2154891180bbae40af2f1abab5f6c4f7040de81a.tar.gz libnl-2154891180bbae40af2f1abab5f6c4f7040de81a.tar.bz2 |
route/xfrmi: merge branch 'ebirger/add-xfrmi-support'
Rebased original pull request #214 on master. One commit ("xfrmi: add
IFLA_XFRM_* definitions to if_link.h") was thereby dropped as it
is no longer necessary. Otherwise, the two remaining patches applied
cleanly. Then, add two more patches to the branch before merging.
https://github.com/thom311/libnl/pull/214
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | doc/route.txt | 51 | ||||
-rw-r--r-- | include/netlink/route/link/xfrmi.h | 37 | ||||
-rw-r--r-- | lib/route/link/xfrmi.c | 319 | ||||
-rw-r--r-- | libnl-route-3.sym | 6 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/test-create-xfrmi.c | 49 |
7 files changed, 464 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am index 88830be..b2e8737 100644 --- a/Makefile.am +++ b/Makefile.am @@ -166,6 +166,7 @@ libnlinclude_netlink_route_link_HEADERS = \ include/netlink/route/link/vlan.h \ include/netlink/route/link/vrf.h \ include/netlink/route/link/vxlan.h \ + include/netlink/route/link/xfrmi.h \ $(NULL) libnlinclude_netlink_route_qdiscdir = $(libnlincludedir)/netlink/route/qdisc libnlinclude_netlink_route_qdisc_HEADERS = \ @@ -412,6 +413,7 @@ lib_libnl_route_3_la_SOURCES = \ lib/route/link/vlan.c \ lib/route/link/vrf.c \ lib/route/link/vxlan.c \ + lib/route/link/xfrmi.c \ lib/route/neigh.c \ lib/route/neightbl.c \ lib/route/netconf.c \ @@ -852,6 +854,7 @@ check_PROGRAMS += \ tests/test-create-vlan \ tests/test-create-vrf \ tests/test-create-vxlan \ + tests/test-create-xfrmi \ tests/test-delete-link \ tests/test-loopback-up-down \ tests/test-socket-creation \ @@ -896,6 +899,8 @@ tests_test_create_vrf_CPPFLAGS = $(tests_cppflags) tests_test_create_vrf_LDADD = $(tests_ldadd) tests_test_create_vxlan_CPPFLAGS = $(tests_cppflags) tests_test_create_vxlan_LDADD = $(tests_ldadd) +tests_test_create_xfrmi_CPPFLAGS = $(tests_cppflags) +tests_test_create_xfrmi_LDADD = $(tests_ldadd) tests_test_delete_link_CPPFLAGS = $(tests_cppflags) tests_test_delete_link_LDADD = $(tests_ldadd) tests_test_loopback_up_down_CPPFLAGS = $(tests_cppflags) diff --git a/doc/route.txt b/doc/route.txt index fece917..9d4c23a 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -949,7 +949,7 @@ extern uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link); struct rtnl_link *link struct in_addr addr -/* allocate new link object of type vxlan */ +/* allocate new link object of type ipip */ if(!(link = rtnl_link_ipip_alloc())) /* error */ @@ -1027,7 +1027,7 @@ extern uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link); struct rtnl_link *link struct in_addr addr -/* allocate new link object of type vxlan */ +/* allocate new link object of type ipgre */ if(!(link = rtnl_link_ipgre_alloc())) /* error */ @@ -1105,7 +1105,7 @@ extern uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link); struct rtnl_link *link struct in_addr addr -/* allocate new link object of type vxlan */ +/* allocate new link object of type sit */ if(!(link = rtnl_link_sit_alloc())) /* error */ @@ -1169,7 +1169,7 @@ extern uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link); struct rtnl_link *link struct in_addr addr -/* allocate new link object of type vxlan */ +/* allocate new link object of type ipvti */ if(!(link = rtnl_link_ipvti_alloc())) /* error */ @@ -1257,6 +1257,49 @@ rtnl_link_put(link); ----- +[[link_xfrmi]] +==== XFRMI + +[source,c] +----- +extern struct rtnl_link *rtnl_link_xfrmi_alloc(void); + +extern int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index); +extern uint32_t rtnl_link_xfrmi_get_link(struct rtnl_link *link); + +extern int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id); +extern uint32_t rtnl_link_xfrmi_get_if_id(struct rtnl_link *link); + +----- + +.Example: Add a xfrmi device +[source,c] +----- +struct rtnl_link *link +struct in_addr addr + +/* allocate new link object of type xfrmi */ +if(!(link = rtnl_link_xfrmi_alloc())) + /* error */ + +/* set xfrmi name */ +if ((err = rtnl_link_set_name(link, "ipsec0")) < 0) + /* error */ + +/* set link index */ +if ((err = rtnl_link_xfrmi_set_link(link, if_index)) < 0) + /* error */ + +/* set if_id */ +if ((err = rtnl_link_xfrmi_set_if_id(link, 16)) < 0) + /* error */ + +if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) + /* error */ + +rtnl_link_put(link); +----- + == Neighbouring == Routing diff --git a/include/netlink/route/link/xfrmi.h b/include/netlink/route/link/xfrmi.h new file mode 100644 index 0000000..6e4cda7 --- /dev/null +++ b/include/netlink/route/link/xfrmi.h @@ -0,0 +1,37 @@ +/* + * netlink/route/link/xfrmi.h XFRMI interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2019 Eyal Birger <eyal.birger@gmail.com> + * + * Based on netlink/route/link/ipvti.h + */ + +#ifndef NETLINK_LINK_XFRMI_H_ +#define NETLINK_LINK_XFRMI_H_ + +#include <netlink/netlink.h> +#include <netlink/route/link.h> + +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_link *rtnl_link_xfrmi_alloc(void); + + extern int rtnl_link_is_xfrmi(struct rtnl_link *link); + + extern int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index); + extern int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link); + + extern int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id); + extern int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/route/link/xfrmi.c b/lib/route/link/xfrmi.c new file mode 100644 index 0000000..5a4a563 --- /dev/null +++ b/lib/route/link/xfrmi.c @@ -0,0 +1,319 @@ +/* + * lib/route/link/xfrmi.c XFRMI Link Info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2019 Eyal Birger <eyal.birger@gmail.com> + * + * Based on lib/route/link/ipvti.c + */ + +/** + * @ingroup link + * @defgroup xfrmi XFRMI + * xfrmi link module + * + * @details + * \b Link Type Name: "xfrmi" + * + * @route_doc{link_xfrmi, XFRMI Documentation} + * + * @{ + */ + +#include <netlink-private/netlink.h> +#include <netlink/netlink.h> +#include <netlink/attr.h> +#include <netlink/utils.h> +#include <netlink/object.h> +#include <netlink/route/rtnl.h> +#include <netlink/route/link/xfrmi.h> +#include <netlink-private/route/link/api.h> + +#define XFRMI_ATTR_LINK (1 << 0) +#define XFRMI_ATTR_IF_ID (1 << 1) + +#define XFRMI_LINK_TYPE_NAME "xfrm" + +struct xfrmi_info { + uint32_t link; + uint32_t if_id; + uint32_t xfrmi_mask; +}; + +static struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = { + [IFLA_XFRM_LINK] = { .type = NLA_U32 }, + [IFLA_XFRM_IF_ID] = { .type = NLA_U32 }, +}; + +static int xfrmi_alloc(struct rtnl_link *link) +{ + struct xfrmi_info *xfrmi; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*xfrmi)); + else { + xfrmi = calloc(1, sizeof(*xfrmi)); + if (!xfrmi) + return -NLE_NOMEM; + + link->l_info = xfrmi; + } + + return 0; +} + +static int xfrmi_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_XFRM_MAX + 1]; + struct xfrmi_info *xfrmi; + int err; + + NL_DBG(3, "Parsing XFRMI link info\n"); + + err = nla_parse_nested(tb, IFLA_XFRM_MAX, data, xfrmi_policy); + if (err < 0) + return err; + + err = xfrmi_alloc(link); + if (err < 0) + return err; + + xfrmi = link->l_info; + + if (tb[IFLA_XFRM_LINK]) { + xfrmi->link = nla_get_u32(tb[IFLA_XFRM_LINK]); + xfrmi->xfrmi_mask |= XFRMI_ATTR_LINK; + } + + if (tb[IFLA_XFRM_IF_ID]) { + xfrmi->if_id = nla_get_u32(tb[IFLA_XFRM_IF_ID]); + xfrmi->xfrmi_mask |= XFRMI_ATTR_IF_ID; + } + + return 0; +} + +static int xfrmi_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct xfrmi_info *xfrmi = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_XFRM_LINK, xfrmi->link); + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID) + NLA_PUT_U32(msg, IFLA_XFRM_IF_ID, xfrmi->if_id); + + nla_nest_end(msg, data); + +nla_put_failure: + return 0; +} + +static void xfrmi_free(struct rtnl_link *link) +{ + struct xfrmi_info *xfrmi = link->l_info; + + free(xfrmi); + link->l_info = NULL; +} + +static void xfrmi_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "xfrmi : %s", link->l_name); +} + +static void xfrmi_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct xfrmi_info *xfrmi = link->l_info; + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_LINK) { + struct rtnl_link *parent; + char *name; + + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, xfrmi->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", xfrmi->link); + } + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID) { + nl_dump(p, " if_id "); + nl_dump_line(p, "%x\n", xfrmi->if_id); + } +} + +static int xfrmi_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct xfrmi_info *xfrmi_dst, *xfrmi_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, XFRMI_LINK_TYPE_NAME); + if (err < 0) + return err; + + xfrmi_dst = dst->l_info; + + if (!xfrmi_dst || !xfrmi_src) + BUG(); + + memcpy(xfrmi_dst, xfrmi_src, sizeof(struct xfrmi_info)); + + return 0; +} + +static struct rtnl_link_info_ops xfrmi_info_ops = { + .io_name = XFRMI_LINK_TYPE_NAME, + .io_alloc = xfrmi_alloc, + .io_parse = xfrmi_parse, + .io_dump = { + [NL_DUMP_LINE] = xfrmi_dump_line, + [NL_DUMP_DETAILS] = xfrmi_dump_details, + }, + .io_clone = xfrmi_clone, + .io_put_attrs = xfrmi_put_attrs, + .io_free = xfrmi_free, +}; + +#define IS_XFRMI_LINK_ASSERT(link) do { \ + if ((link)->l_info_ops != &xfrmi_info_ops) { \ + APPBUG("Link is not a xfrmi link. set type \"xfrmi\" first."); \ + return -NLE_OPNOTSUPP; \ + } \ + } while(0) + +struct rtnl_link *rtnl_link_xfrmi_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, XFRMI_LINK_TYPE_NAME); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a XFRMI link + * @arg link Link object + * + * @return True if link is a IXFRMI link, otherwise 0 is returned. + */ +int rtnl_link_is_xfrmi(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, + XFRMI_LINK_TYPE_NAME); +} + +/** + * Set XFRMI link interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + xfrmi->link = index; + xfrmi->xfrmi_mask |= XFRMI_ATTR_LINK; + + return 0; +} + +/** + * Get XFRMI link interface index + * @arg link Link object + * @arg out_link The output value on success + * + * @return 0 on sucess or a negative error code + */ +int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + if (!(xfrmi->xfrmi_mask & XFRMI_ATTR_LINK)) + return -NLE_NOATTR; + + *out_link = xfrmi->link; + return 0; +} + +/** + * Set XFRMI if_id + * @arg link Link object + * @arg if_id xfrm if_id + * + * @return 0 on success or a negative error code + */ +int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + xfrmi->if_id = if_id; + xfrmi->xfrmi_mask |= XFRMI_ATTR_IF_ID; + + return 0; +} + +/** + * Get XFRMI if_id + * @arg link Link object + * @arg out_if_id The output value on success + * + * @return 0 on sucess or a negative error code + */ +int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + if (!(xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID)) + return -NLE_NOATTR; + + *out_if_id = xfrmi->if_id; + return 0; +} + +static void __init xfrmi_init(void) +{ + rtnl_link_register_info(&xfrmi_info_ops); +} + +static void __exit xfrmi_exit(void) +{ + rtnl_link_unregister_info(&xfrmi_info_ops); +} diff --git a/libnl-route-3.sym b/libnl-route-3.sym index 5a82d85..67334ab 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1089,7 +1089,13 @@ global: rtnl_link_geneve_set_udp_zero_csum6_tx; rtnl_link_get_slave_type; rtnl_link_is_geneve; + rtnl_link_is_xfrmi; rtnl_link_set_slave_type; + rtnl_link_xfrmi_alloc; + rtnl_link_xfrmi_get_if_id; + rtnl_link_xfrmi_get_link; + rtnl_link_xfrmi_set_if_id; + rtnl_link_xfrmi_set_link; rtnl_mall_append_action; rtnl_mall_del_action; rtnl_mall_get_classid; diff --git a/tests/.gitignore b/tests/.gitignore index 425a7c4..90af67a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -23,6 +23,7 @@ /test-create-vlan /test-create-vrf /test-create-vxlan +/test-create-xfrmi /test-delete-link /test-genl /test-loopback-up-down diff --git a/tests/test-create-xfrmi.c b/tests/test-create-xfrmi.c new file mode 100644 index 0000000..3a01a4f --- /dev/null +++ b/tests/test-create-xfrmi.c @@ -0,0 +1,49 @@ +#include <netlink/route/link/xfrmi.h> +#include <netlink-private/netlink.h> + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if (err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "eth0"); + if (!if_index) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + link = rtnl_link_xfrmi_alloc(); + if (!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + + rtnl_link_set_name(link, "ipsec0"); + rtnl_link_xfrmi_set_link(link, if_index); + rtnl_link_xfrmi_set_if_id(link, 16); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + return 0; +} |