network/tunnel: reuse existing 6rd sit tunnel (#34938)
split-out of #34909.
This commit is contained in:
+42
-52
@@ -34,7 +34,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode);
|
||||
|
||||
#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) {
|
||||
static int dhcp4_pd_create_6rd_tunnel_name(Link *link) {
|
||||
_cleanup_free_ char *ifname_alloc = NULL;
|
||||
uint8_t ipv4masklen, sixrd_prefixlen, *buf, *p;
|
||||
struct in_addr ipv4address;
|
||||
@@ -47,13 +47,16 @@ int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
|
||||
assert(link);
|
||||
assert(link->dhcp_lease);
|
||||
|
||||
if (link->dhcp4_6rd_tunnel_name)
|
||||
return 0; /* Already set. Do not change even if the 6rd option is changed. */
|
||||
|
||||
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");
|
||||
return r;
|
||||
|
||||
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");
|
||||
return r;
|
||||
|
||||
sz = sizeof(uint8_t) * 2 + sizeof(struct in6_addr) + sizeof(struct in_addr);
|
||||
buf = newa(uint8_t, sz);
|
||||
@@ -80,21 +83,44 @@ int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
|
||||
|
||||
ifname_alloc = strdup(ifname);
|
||||
if (!ifname_alloc)
|
||||
return log_oom_debug();
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(ifname_alloc);
|
||||
link->dhcp4_6rd_tunnel_name = TAKE_PTR(ifname_alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp4_pd_create_6rd_tunnel_message(
|
||||
Link *link,
|
||||
sd_netlink_message *m,
|
||||
const struct in_addr *ipv4address,
|
||||
uint8_t ipv4masklen,
|
||||
const struct in6_addr *sixrd_prefix,
|
||||
uint8_t sixrd_prefixlen) {
|
||||
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;
|
||||
struct in6_addr sixrd_prefix;
|
||||
Link *sit = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->dhcp_lease);
|
||||
assert(callback);
|
||||
|
||||
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp4_pd_create_6rd_tunnel_name(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) link_get_by_name(link->manager, link->dhcp4_6rd_tunnel_name, &sit);
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, sit ? sit->ifindex : 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_string(m, IFLA_IFNAME, link->dhcp4_6rd_tunnel_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -107,7 +133,7 @@ static int dhcp4_pd_create_6rd_tunnel_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, ipv4address);
|
||||
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &ipv4address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -115,7 +141,7 @@ static int dhcp4_pd_create_6rd_tunnel_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, sixrd_prefix);
|
||||
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &sixrd_prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -123,7 +149,7 @@ static int dhcp4_pd_create_6rd_tunnel_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
struct in_addr relay_prefix = *ipv4address;
|
||||
struct in_addr 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)
|
||||
@@ -141,48 +167,12 @@ static int dhcp4_pd_create_6rd_tunnel_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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;
|
||||
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, "Failed to create netlink message: %m");
|
||||
|
||||
r = dhcp4_pd_create_6rd_tunnel_message(link, m,
|
||||
&ipv4address, ipv4masklen,
|
||||
&sixrd_prefix, sixrd_prefixlen);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to fill netlink message: %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 netlink message: %m");
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ 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);
|
||||
|
||||
@@ -961,7 +961,6 @@ static int dhcp4_pd_6rd_tunnel_create_handler(sd_netlink *rtnl, sd_netlink_messa
|
||||
}
|
||||
|
||||
int dhcp4_pd_prefix_acquired(Link *uplink) {
|
||||
_cleanup_free_ char *tunnel_name = NULL;
|
||||
uint8_t ipv4masklen, sixrd_prefixlen, pd_prefixlen;
|
||||
struct in6_addr sixrd_prefix, pd_prefix;
|
||||
struct in_addr ipv4address;
|
||||
@@ -1010,28 +1009,10 @@ int dhcp4_pd_prefix_acquired(Link *uplink) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Generate 6rd SIT tunnel device name. */
|
||||
r = dhcp4_pd_create_6rd_tunnel_name(uplink, &tunnel_name);
|
||||
/* Create or update 6rd SIT tunnel device. */
|
||||
r = dhcp4_pd_create_6rd_tunnel(uplink, dhcp4_pd_6rd_tunnel_create_handler);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Remove old tunnel device if exists. */
|
||||
if (!streq_ptr(uplink->dhcp4_6rd_tunnel_name, tunnel_name)) {
|
||||
Link *old_tunnel;
|
||||
|
||||
if (uplink->dhcp4_6rd_tunnel_name &&
|
||||
link_get_by_name(uplink->manager, uplink->dhcp4_6rd_tunnel_name, &old_tunnel) >= 0)
|
||||
(void) link_remove(old_tunnel);
|
||||
|
||||
free_and_replace(uplink->dhcp4_6rd_tunnel_name, tunnel_name);
|
||||
}
|
||||
|
||||
/* Create 6rd SIT tunnel device if it does not exist yet. */
|
||||
if (link_get_by_name(uplink->manager, uplink->dhcp4_6rd_tunnel_name, NULL) < 0) {
|
||||
r = dhcp4_pd_create_6rd_tunnel(uplink, dhcp4_pd_6rd_tunnel_create_handler);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
return log_link_warning_errno(uplink, r, "Failed to create or update 6rd SIT tunnel: %m");
|
||||
|
||||
/* Then, assign subnet prefixes to downstream interfaces. */
|
||||
HASHMAP_FOREACH(link, uplink->manager->links_by_index) {
|
||||
|
||||
Reference in New Issue
Block a user