#include <netinet/in.h>
#include <linux/if.h>
+#include <linux/if_arp.h>
#include <unistd.h>
#include "alloc-util.h"
if (link->network->bond)
return false;
- if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+ if (link->iftype == ARPHRD_CAN)
return false;
if (link_sysctl_ipv6_enabled(link) == 0)
if (link->network->bond)
return false;
- if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+ if (link->iftype == ARPHRD_CAN)
return false;
return link->network->dhcp & ADDRESS_FAMILY_IPV4;
if (link->network->bond)
return false;
- if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+ if (link->iftype == ARPHRD_CAN)
return false;
return link->network->dhcp_server;
}
-bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
+bool link_ipv4ll_enabled(Link *link, AddressFamily mask) {
assert(link);
assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0);
if (!link->network)
return false;
+ if (link->iftype == ARPHRD_CAN)
+ return false;
+
if (STRPTR_IN_SET(link->kind,
"vrf", "wireguard", "ipip", "gre", "ip6gre","ip6tnl", "sit", "vti",
- "vti6", "can", "vcan", "vxcan", "nlmon", "xfrm"))
+ "vti6", "nlmon", "xfrm"))
return false;
/* L3 or L3S mode do not support ARP. */
if (!link->network)
return false;
- if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan", "nlmon"))
+ if (link->iftype == ARPHRD_CAN)
+ return false;
+
+ if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "nlmon"))
return false;
if (link->network->bond)
if (link_sysctl_ipv6_enabled(link) == 0)
return false;
- if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+ if (link->iftype == ARPHRD_CAN)
return false;
/* DHCPv6 client will not be started if no IPv6 link-local address is configured. */
if (!link->network)
return false;
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID)
return false;
return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
if (!link->network)
return false;
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID)
return false;
if (link_sysctl_ipv6_enabled(link) == 0)
link->routes = set_free_with_destructor(link->routes, route_free);
link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free);
+ link->neighbors = set_free_with_destructor(link->neighbors, neighbor_free);
+ link->neighbors_foreign = set_free_with_destructor(link->neighbors_foreign, neighbor_free);
+
link->addresses = set_free_with_destructor(link->addresses, address_free);
link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free);
r = set_put(master->slaves, link);
if (r < 0)
return r;
+ if (r == 0)
+ return 0;
link_ref(link);
return 0;
return false;
}
+static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) {
+ Neighbor *net_neighbor;
+
+ assert(link);
+ assert(neighbor);
+
+ if (!link->network)
+ return false;
+
+ LIST_FOREACH(neighbors, net_neighbor, link->network->neighbors)
+ if (neighbor_equal(net_neighbor, neighbor))
+ return true;
+
+ return false;
+}
+
static bool link_is_static_route_configured(Link *link, Route *route) {
Route *net_route;
static int link_drop_foreign_config(Link *link) {
Address *address;
+ Neighbor *neighbor;
Route *route;
Iterator i;
int r;
}
}
+ SET_FOREACH(neighbor, link->neighbors_foreign, i) {
+ if (link_is_neighbor_configured(link, neighbor)) {
+ r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL);
+ if (r < 0)
+ return r;
+ } else {
+ r = neighbor_remove(neighbor, link, NULL);
+ if (r < 0)
+ return r;
+ }
+ }
+
SET_FOREACH(route, link->routes_foreign, i) {
/* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
continue;
if (link_is_static_route_configured(link, route)) {
- r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL);
+ r = route_add(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, NULL);
if (r < 0)
return r;
} else {
static int link_drop_config(Link *link) {
Address *address, *pool_address;
+ Neighbor *neighbor;
Route *route;
Iterator i;
int r;
}
}
+ SET_FOREACH(neighbor, link->neighbors, i) {
+ r = neighbor_remove(neighbor, link, NULL);
+ if (r < 0)
+ return r;
+ }
+
SET_FOREACH(route, link->routes, i) {
/* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
assert(link->network);
assert(link->state == LINK_STATE_INITIALIZED);
- if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+ if (link->iftype == ARPHRD_CAN)
return link_configure_can(link);
/* Drop foreign config, but ignore loopback or critical devices.
configure:
while ((link = set_steal_first(manager->links_requesting_uuid))) {
+ link_unref(link);
+
r = link_configure(link);
if (r < 0)
link_enter_failed(link);
r = set_put(m->duids_requesting_uuid, duid);
if (r < 0)
return log_oom();
+
+ link_ref(link);
}
return 0;
continue;
}
- r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route);
+ r = route_add(link, family, &route_dst, prefixlen, NULL, tos, priority, table, &route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add route: %m");