network: dhcp-pd: add 6rd support

Closes #19152.
This commit is contained in:
Yu Watanabe
2021-12-07 20:33:16 +09:00
parent dbdcaca3ab
commit e49bad0179
13 changed files with 534 additions and 16 deletions
+143
View File
@@ -8,9 +8,12 @@
#include <linux/ip6_tunnel.h>
#include "conf-parser.h"
#include "hexdecoct.h"
#include "missing_network.h"
#include "netlink-util.h"
#include "networkd-manager.h"
#include "parse-util.h"
#include "siphash24.h"
#include "string-table.h"
#include "string-util.h"
#include "tunnel.h"
@@ -29,6 +32,146 @@ static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
#define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
_cleanup_free_ char *ifname_alloc = NULL;
uint8_t ipv4masklen, sixrd_prefixlen, *buf, *p;
struct in_addr ipv4address;
struct in6_addr sixrd_prefix;
char ifname[IFNAMSIZ];
uint64_t result;
size_t sz;
int r;
assert(link);
assert(link->dhcp_lease);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
sz = sizeof(uint8_t) * 2 + sizeof(struct in6_addr) + sizeof(struct in_addr);
buf = newa(uint8_t, sz);
p = buf;
p = mempcpy(p, &ipv4masklen, sizeof(uint8_t));
p = mempcpy(p, &ipv4address, sizeof(struct in_addr));
p = mempcpy(p, &sixrd_prefixlen, sizeof(uint8_t));
p = mempcpy(p, &sixrd_prefix, sizeof(struct in6_addr));
result = siphash24(buf, sz, HASH_KEY.bytes);
memcpy(ifname, "6rd-", STRLEN("6rd-"));
ifname[STRLEN("6rd-") ] = urlsafe_base64char(result >> 54);
ifname[STRLEN("6rd-") + 1] = urlsafe_base64char(result >> 48);
ifname[STRLEN("6rd-") + 2] = urlsafe_base64char(result >> 42);
ifname[STRLEN("6rd-") + 3] = urlsafe_base64char(result >> 36);
ifname[STRLEN("6rd-") + 4] = urlsafe_base64char(result >> 30);
ifname[STRLEN("6rd-") + 5] = urlsafe_base64char(result >> 24);
ifname[STRLEN("6rd-") + 6] = urlsafe_base64char(result >> 18);
ifname[STRLEN("6rd-") + 7] = urlsafe_base64char(result >> 12);
ifname[STRLEN("6rd-") + 8] = urlsafe_base64char(result >> 6);
ifname[STRLEN("6rd-") + 9] = urlsafe_base64char(result);
ifname[STRLEN("6rd-") + 10] = '\0';
assert_cc(STRLEN("6rd-") + 10 <= IFNAMSIZ);
ifname_alloc = strdup(ifname);
if (!ifname_alloc)
return log_oom_debug();
*ret = TAKE_PTR(ifname_alloc);
return 0;
}
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint8_t ipv4masklen, sixrd_prefixlen;
struct in_addr ipv4address, relay_prefix;
struct in6_addr sixrd_prefix;
int r;
assert(link);
assert(link->ifindex > 0);
assert(link->manager);
assert(link->dhcp_lease);
assert(link->dhcp4_6rd_tunnel_name);
assert(callback);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, 0);
if (r < 0)
return log_link_debug_errno(link, r, "Could not allocate RTM_NEWLINK message: %m");
r = sd_netlink_message_append_string(m, IFLA_IFNAME, link->dhcp4_6rd_tunnel_name);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IFNAME, attribute: %m");
r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "sit");
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, 64);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &sixrd_prefix);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, sixrd_prefixlen);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m");
relay_prefix = ipv4address;
(void) in4_addr_mask(&relay_prefix, ipv4masklen);
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_6RD_RELAY_PREFIX, relay_prefix.s_addr);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_RELAY_PREFIX attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ipv4masklen);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_RELAY_PREFIXLEN attribute: %m");
r = sd_netlink_message_close_container(m);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_message_close_container(m);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
return 0;
}
static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
Tunnel *t;
int r;
+4
View File
@@ -6,6 +6,7 @@
#include "conf-parser.h"
#include "fou-tunnel.h"
#include "netdev.h"
#include "networkd-link.h"
typedef enum Ip6TnlMode {
NETDEV_IP6_TNL_MODE_IP6IP6,
@@ -60,6 +61,9 @@ typedef struct Tunnel {
uint8_t sixrd_prefixlen;
} Tunnel;
int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret);
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback);
DEFINE_NETDEV_CAST(IPIP, Tunnel);
DEFINE_NETDEV_CAST(GRE, Tunnel);
DEFINE_NETDEV_CAST(GRETAP, Tunnel);