Skip to content

Commit

Permalink
sysrepo-plugin-interfaces: implement interface store API
Browse files Browse the repository at this point in the history
  • Loading branch information
jkuless committed Oct 25, 2022
1 parent b9ebaf3 commit 073ecc4
Showing 1 changed file with 129 additions and 7 deletions.
136 changes: 129 additions & 7 deletions src/interfaces/src/plugin/api/interfaces/store.c
Original file line number Diff line number Diff line change
@@ -1,46 +1,168 @@
#include "store.h"
#include "netlink/addr.h"
#include "netlink/cache.h"
#include "netlink/object.h"
#include "netlink/route/addr.h"
#include "netlink/socket.h"
#include "plugin/data/interfaces/interface/ipv4/address.h"
#include "srpc/common.h"
#include "utlist.h"
#include "uthash.h"
#include "types.h"
#include "plugin/types.h"
#include <sysrepo.h>
#include "sysrepo/xpath.h"
#include "plugin/common.h"
#include "plugin/context.h"
#include <errno.h>
#include "sysrepo/xpath.h"
#include "netlink/errno.h"
#include "netlink/route/link.h"
#include "/usr/include/linux/if.h"

int interfaces_store_interface(interfaces_ctx_t* ctx, const interfaces_interface_hash_element_t* if_hash)
{
int error = 0;
interfaces_interface_hash_element_t *i = NULL, *tmp = NULL;
uint8_t if_status, prefix_length;
uint32_t mtu;
char *if_type = NULL;
char *if_type_libnl = NULL;
const interfaces_interface_hash_element_t *i = NULL, *tmp = NULL;
struct nl_sock *sk = NULL;
struct nl_addr* local_addr = NULL;
struct nl_cache* link_cache = NULL;
struct rtnl_link* new_link = NULL;
struct rtnl_addr *link_ipv4_addr = NULL;
struct rtnl_addr *link_ipv6_addr = NULL;

// setup nl socket

SRPC_SAFE_CALL_PTR(sk, nl_socket_alloc(), error_out);

// connect
SRPC_SAFE_CALL_ERR(error, nl_connect(sk, NETLINK_ROUTE), error_out);

// allocate link cache
SRPC_SAFE_CALL_ERR(error, rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache), error_out);

HASH_ITER (hh, if_hash, i, tmp) {
if_type = i->interface.type;
if_status = i->interface.enabled;
mtu = i->interface.ipv4.mtu < i->interface.ipv6.mtu ? i->interface.ipv4.mtu : i->interface.ipv6.mtu;

// create a new link
SRPC_SAFE_CALL_PTR(new_link, rtnl_link_alloc(), error_out);

//determine link type
if (strcmp(if_type, "iana-if-type:ethernetCsmacd") == 0) {
if_type_libnl = "veth";
// !! ADS 2 INTERFACES (one without ip addresses)
} else if (strcmp(if_type, "iana-if-type:softwareLoopback") == 0) {
if_type_libnl = "vcan";
//!! vcan INSTEAD OF lo
} else if (strcmp(if_type, "iana-if-type:l2vlan") == 0) {
if_type_libnl = "vlan";
//!! doesn't work
} else if (strcmp(if_type, "iana-if-type:other") == 0) {
if_type_libnl = "dummy";
}

// set link type
SRPC_SAFE_CALL_ERR(error, rtnl_link_set_type(new_link, if_type_libnl), error_out);

// setup link and add it to the system
// setup link name
rtnl_link_set_name(new_link, i->interface.name);
SRPC_SAFE_CALL_ERR(error, rtnl_link_set_type(new_link, i->interface.type), error_out);

// initialize desired link status
if (if_status) {
rtnl_link_set_flags(new_link, IFF_UP);
} else {
rtnl_link_unset_flags(new_link, IFF_UP);
}
rtnl_link_set_operstate(new_link, if_status ? IF_OPER_UP : IF_OPER_DOWN);

// set MTU
if (mtu) {
rtnl_link_set_mtu(new_link, mtu);
}

// add link
SRPC_SAFE_CALL_ERR(error, rtnl_link_add(sk, new_link, NLM_F_CREATE), error_out);

// update link cache
SRPC_SAFE_CALL_ERR(error, nl_cache_refill(sk, link_cache), error_out);

// get updated new_link
SRPC_SAFE_CALL_PTR(new_link, rtnl_link_get_by_name(link_cache, i->interface.name), error_out);

for(interfaces_interface_ipv4_address_element_t *addr_ptr = i->interface.ipv4.address; addr_ptr != NULL; addr_ptr = addr_ptr->next) {
link_ipv4_addr = rtnl_addr_alloc();

//parse local ipv4 address
SRPC_SAFE_CALL_ERR(error, nl_addr_parse(addr_ptr->address.ip, AF_INET, &local_addr), error_out);

// get ipv4 prefix length by using prefix-length or netmask
switch (addr_ptr->address.subnet_type) {
case interfaces_interface_ipv4_address_subnet_none:
SRPLG_LOG_ERR(PLUGIN_NAME, "Unable to get prefix-length/netmask for address %s", addr_ptr->address.ip);
break;
case interfaces_interface_ipv4_address_subnet_prefix_length:
prefix_length = addr_ptr->address.subnet.prefix_length;
break;
case interfaces_interface_ipv4_address_subnet_netmask:
interfaces_interface_ipv4_address_netmask2prefix(addr_ptr->address.subnet.netmask, &prefix_length);
break;
default:
SRPLG_LOG_ERR(PLUGIN_NAME, "Unable to get prefix-length/netmask for address %s", addr_ptr->address.ip);
}

// set ipv4 prefix length
nl_addr_set_prefixlen(local_addr, prefix_length);

//set to route address
SRPC_SAFE_CALL_ERR(error, rtnl_addr_set_local(link_ipv4_addr, local_addr), error_out);

// set interface
rtnl_addr_set_ifindex(link_ipv4_addr, rtnl_link_get_ifindex(new_link));

// add ipv4 address
SRPC_SAFE_CALL_ERR(error, rtnl_addr_add(sk, link_ipv4_addr, 0), error_out);

nl_addr_put(local_addr);
rtnl_addr_put(link_ipv4_addr);
}


for(interfaces_interface_ipv6_address_element_t *addr_ptr = i->interface.ipv6.address; addr_ptr != NULL; addr_ptr = addr_ptr->next) {
link_ipv6_addr = rtnl_addr_alloc();

// parse local ipv6 address
SRPC_SAFE_CALL_ERR(error, nl_addr_parse(addr_ptr->address.ip, AF_INET6, &local_addr), error_out);

// set ipv6 prefix length
nl_addr_set_prefixlen(local_addr, addr_ptr->address.prefix_length);

//set to route address
SRPC_SAFE_CALL_ERR(error, rtnl_addr_set_local(link_ipv6_addr, local_addr), error_out);

// set interface
rtnl_addr_set_ifindex(link_ipv6_addr, rtnl_link_get_ifindex(new_link));

//add ipv6 address
SRPC_SAFE_CALL_ERR(error, rtnl_addr_add(sk, link_ipv6_addr, 0), error_out);

nl_addr_put(local_addr);
rtnl_addr_put(link_ipv6_addr);
}

}

goto out;

error_out:
if (error < 0) {
SRPLG_LOG_ERR(PLUGIN_NAME, "nl_geterror(): %d = %s", error, nl_geterror(error));
}
error = -1;

error:
out:
nl_socket_free(sk);
return error;
}

0 comments on commit 073ecc4

Please sign in to comment.