#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;
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);
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;
}
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(link->dhcp4_6rd_tunnel_name);
assert(callback);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return r;
- r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, 0);
+ 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;
return r;
link_ref(link);
-
return 0;
}
}
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;
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 log_link_warning_errno(uplink, r, "Failed to create 6rd SIT tunnel: %m");
- }
+ 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) {