From 77e9be1ee4692612dc5672c961dc06237c8db7a0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 25 Feb 2022 12:59:58 +0900 Subject: [PATCH 1/6] network: address: introduce manager_get_address() And make manager_has_address() return true only when the link which has the address is ready. --- src/network/networkd-address.c | 28 ++++++++++++++++++++++------ src/network/networkd-address.h | 3 ++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index f9d8e9bb6cf..f883c79a9ee 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -602,19 +602,35 @@ int link_get_address(Link *link, int family, const union in_addr_union *address, return -ENOENT; } -int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready) { - Address *a; +int manager_get_address(Manager *manager, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret) { Link *link; assert(manager); assert(IN_SET(family, AF_INET, AF_INET6)); assert(address); - HASHMAP_FOREACH(link, manager->links_by_index) - if (link_get_address(link, family, address, 0, &a) >= 0) - return check_ready ? address_is_ready(a) : address_exists(a); + HASHMAP_FOREACH(link, manager->links_by_index) { + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + continue; - return false; + if (link_get_address(link, family, address, prefixlen, ret) >= 0) + return 0; + } + + return -ENOENT; +} + +bool manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready) { + Address *a; + + assert(manager); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(address); + + if (manager_get_address(manager, family, address, 0, &a) < 0) + return false; + + return check_ready ? address_is_ready(a) : address_exists(a); } const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) { diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 0b1f3192a2d..b116237638b 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -88,7 +88,8 @@ static inline int link_get_ipv4_address(Link *link, const struct in_addr *addres assert(address); return link_get_address(link, AF_INET, &(union in_addr_union) { .in = *address }, prefixlen, ret); } -int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready); +int manager_get_address(Manager *manager, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret); +bool manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready); void address_cancel_request(Address *address); int link_request_address( From c45cbc2394ddaf8b239f1c9e35e46125e2e50286 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 25 Feb 2022 16:29:26 +0900 Subject: [PATCH 2/6] network: merge gateway_is_ready() and link_address_is_reachable() As link_address_is_reachable() is used only by gateway_is_ready(). --- src/network/networkd-route-util.c | 33 +++++++++++-------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/network/networkd-route-util.c b/src/network/networkd-route-util.c index c202078f07d..e07dbb213cf 100644 --- a/src/network/networkd-route-util.c +++ b/src/network/networkd-route-util.c @@ -102,14 +102,21 @@ int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret) { return 0; } -static bool link_address_is_reachable(Link *link, int family, const union in_addr_union *address) { +bool gateway_is_ready(Link *link, bool onlink, int family, const union in_addr_union *gw) { Route *route; Address *a; assert(link); assert(link->manager); - assert(IN_SET(family, AF_INET, AF_INET6)); - assert(address); + + if (onlink) + return true; + + if (!gw || !in_addr_is_set(family, gw)) + return true; + + if (family == AF_INET6 && in6_addr_is_link_local(&gw->in6)) + return true; SET_FOREACH(route, link->routes) { if (!route_exists(route)) @@ -118,7 +125,7 @@ static bool link_address_is_reachable(Link *link, int family, const union in_add continue; if (!in_addr_is_set(route->family, &route->dst) && route->dst_prefixlen == 0) continue; - if (in_addr_prefix_covers(family, &route->dst, route->dst_prefixlen, address) > 0) + if (in_addr_prefix_covers(family, &route->dst, route->dst_prefixlen, gw) > 0) return true; } @@ -136,29 +143,13 @@ static bool link_address_is_reachable(Link *link, int family, const union in_add continue; if (in_addr_is_set(a->family, &a->in_addr_peer)) continue; - if (in_addr_prefix_covers(family, &a->in_addr, a->prefixlen, address) > 0) + if (in_addr_prefix_covers(family, &a->in_addr, a->prefixlen, gw) > 0) return true; } return false; } -bool gateway_is_ready(Link *link, bool onlink, int family, const union in_addr_union *gw) { - assert(link); - assert(gw); - - if (onlink) - return true; - - if (!in_addr_is_set(family, gw)) - return true; - - if (family == AF_INET6 && in6_addr_is_link_local(&gw->in6)) - return true; - - return link_address_is_reachable(link, family, gw); -} - static const char * const route_type_table[__RTN_MAX] = { [RTN_UNICAST] = "unicast", [RTN_LOCAL] = "local", From 8b7615f9b97766dd119650c11063033f89ebb8e0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 25 Feb 2022 16:47:47 +0900 Subject: [PATCH 3/6] network: introduce {manager,link}_address_is_reachable() --- src/network/networkd-route-util.c | 137 ++++++++++++++++++++++++++++++ src/network/networkd-route-util.h | 15 ++++ 2 files changed, 152 insertions(+) diff --git a/src/network/networkd-route-util.c b/src/network/networkd-route-util.c index e07dbb213cf..4c9920b6090 100644 --- a/src/network/networkd-route-util.c +++ b/src/network/networkd-route-util.c @@ -150,6 +150,143 @@ bool gateway_is_ready(Link *link, bool onlink, int family, const union in_addr_u return false; } +static int link_address_is_reachable_internal( + Link *link, + int family, + const union in_addr_union *address, + const union in_addr_union *prefsrc, /* optional */ + Route **ret) { + + Route *route, *found = NULL; + + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(address); + + SET_FOREACH(route, link->routes) { + if (!route_exists(route)) + continue; + + if (route->type != RTN_UNICAST) + continue; + + if (route->family != family) + continue; + + if (in_addr_prefix_covers(family, &route->dst, route->dst_prefixlen, address) <= 0) + continue; + + if (prefsrc && + in_addr_is_set(family, prefsrc) && + in_addr_is_set(family, &route->prefsrc) && + !in_addr_equal(family, prefsrc, &route->prefsrc)) + continue; + + if (found && found->priority <= route->priority) + continue; + + found = route; + } + + if (!found) + return -ENOENT; + + if (ret) + *ret = found; + + return 0; +} + +int link_address_is_reachable( + Link *link, + int family, + const union in_addr_union *address, + const union in_addr_union *prefsrc, /* optional */ + Address **ret) { + + Route *route; + Address *a; + int r; + + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(address); + + /* This checks if the address is reachable, and optionally return the Address object of the + * preferred source to access the address. */ + + r = link_address_is_reachable_internal(link, family, address, prefsrc, &route); + if (r < 0) + return r; + + if (!in_addr_is_set(route->family, &route->prefsrc)) { + if (ret) + *ret = NULL; + return 0; + } + + r = link_get_address(link, route->family, &route->prefsrc, 0, &a); + if (r < 0) + return r; + + if (!address_is_ready(a)) + return -EBUSY; + + if (ret) + *ret = a; + + return 0; +} + +int manager_address_is_reachable( + Manager *manager, + int family, + const union in_addr_union *address, + const union in_addr_union *prefsrc, /* optional */ + Address **ret) { + + Route *route, *found = NULL; + Address *a; + Link *link; + int r; + + assert(manager); + + HASHMAP_FOREACH(link, manager->links_by_index) { + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + continue; + + if (link_address_is_reachable_internal(link, family, address, prefsrc, &route) < 0) + continue; + + if (found && found->priority <= route->priority) + continue; + + found = route; + } + + if (!found) + return -ENOENT; + + if (!in_addr_is_set(found->family, &found->prefsrc)) { + if (ret) + *ret = NULL; + return 0; + } + + r = link_get_address(found->link, found->family, &found->prefsrc, 0, &a); + if (r < 0) + return r; + + if (!address_is_ready(a)) + return -EBUSY; + + if (ret) + *ret = a; + + return 0; +} + static const char * const route_type_table[__RTN_MAX] = { [RTN_UNICAST] = "unicast", [RTN_LOCAL] = "local", diff --git a/src/network/networkd-route-util.h b/src/network/networkd-route-util.h index 3dd3d3ace8e..b862cd67744 100644 --- a/src/network/networkd-route-util.h +++ b/src/network/networkd-route-util.h @@ -8,6 +8,7 @@ typedef struct Link Link; typedef struct Manager Manager; +typedef struct Address Address; unsigned routes_max(void); @@ -15,6 +16,20 @@ int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret); bool gateway_is_ready(Link *link, bool onlink, int family, const union in_addr_union *gw); +int link_address_is_reachable( + Link *link, + int family, + const union in_addr_union *address, + const union in_addr_union *prefsrc, /* optional */ + Address **ret); + +int manager_address_is_reachable( + Manager *manager, + int family, + const union in_addr_union *address, + const union in_addr_union *prefsrc, /* optional */ + Address **ret); + int route_type_from_string(const char *s) _pure_; const char *route_type_to_string(int t) _const_; From 8b49ee2dcda04f8147650f7d9fb93662caf3ea2e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 25 Feb 2022 17:12:18 +0900 Subject: [PATCH 4/6] network: l2tp: make Local= optionally take interface name --- man/systemd.netdev.xml | 15 +- src/network/netdev/l2tp-tunnel.c | 254 +++++++++++++++++----- src/network/netdev/l2tp-tunnel.h | 4 +- src/network/netdev/netdev-gperf.gperf | 4 +- test/test-network/conf/25-l2tp-ip.netdev | 2 +- test/test-network/conf/25-l2tp-udp.netdev | 2 +- 6 files changed, 218 insertions(+), 63 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 1f94e3d599f..e23146f3ca8 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -881,12 +881,15 @@ Local= - Specifies the IP address of the local interface. Takes an IP address, or the special values - auto, static, or dynamic. When an address - is set, then the local interface must have the address. If auto, then one of the - addresses on the local interface is used. Similarly, if static or - dynamic is set, then one of the static or dynamic addresses on the local - interface is used. Defaults to auto. + Specifies the IP address of a local interface. Takes an IP address, or the special + values auto, static, or dynamic. + Optionally a name of a local interface can be specified after @, e.g. + 192.168.0.1@eth0 or auto@eth0. When an address is + specified, then a local or specified interface must have the address, and the remote address + must be accessible through the local address. If auto, then one of the + addresses on a local or specified interface which is accessible to the remote address will be + used. Similarly, if static or dynamic is set, then one + of the static or dynamic addresses will be used. Defaults to auto. diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index 50f52f5d9b7..e94ca204079 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -10,6 +10,7 @@ #include "netlink-util.h" #include "networkd-address.h" #include "networkd-manager.h" +#include "networkd-route-util.h" #include "parse-util.h" #include "socket-util.h" #include "string-table.h" @@ -245,44 +246,114 @@ static int netdev_l2tp_create_message_session(NetDev *netdev, L2tpSession *sessi return 0; } -static int l2tp_acquire_local_address_one(L2tpTunnel *t, Address *a, union in_addr_union *ret) { - if (a->family != t->family) - return -EINVAL; - - if (in_addr_is_set(a->family, &a->in_addr_peer)) - return -EINVAL; - - if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC && - !FLAGS_SET(a->flags, IFA_F_PERMANENT)) - return -EINVAL; - - if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC && - FLAGS_SET(a->flags, IFA_F_PERMANENT)) - return -EINVAL; - - *ret = a->in_addr; - return 0; -} - -static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_union *ret) { +static int link_get_l2tp_local_address(Link *link, L2tpTunnel *t, union in_addr_union *ret) { Address *a; - assert(t); assert(link); - assert(ret); - assert(IN_SET(t->family, AF_INET, AF_INET6)); + assert(t); + + SET_FOREACH(a, link->addresses) { + if (!address_is_ready(a)) + continue; + + if (a->family != t->family) + continue; + + if (in_addr_is_set(a->family, &a->in_addr_peer)) + continue; + + if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC && + !FLAGS_SET(a->flags, IFA_F_PERMANENT)) + continue; + + if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC && + FLAGS_SET(a->flags, IFA_F_PERMANENT)) + continue; + + if (ret) + *ret = a->in_addr; + } + + return -ENOENT; +} + +static int l2tp_get_local_address(NetDev *netdev, union in_addr_union *ret) { + Link *link = NULL; + L2tpTunnel *t; + Address *a; + int r; + + assert(netdev); + assert(netdev->manager); + assert_se(t = L2TP(netdev)); + + if (t->local_ifname) { + r = link_get_by_name(netdev->manager, t->local_ifname, &link); + if (r < 0) + return r; + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return -EBUSY; + } + + if (netdev->manager->manage_foreign_routes) { + /* First, check if the remote address is accessible. */ + if (link) + r = link_address_is_reachable(link, t->family, &t->remote, &t->local, &a); + else + r = manager_address_is_reachable(netdev->manager, t->family, &t->remote, &t->local, &a); + if (r < 0) + return r; + } if (in_addr_is_set(t->family, &t->local)) { /* local address is explicitly specified. */ - *ret = t->local; + + if (!a) { + if (link) + r = link_get_address(link, t->family, &t->local, 0, &a); + else + r = manager_get_address(netdev->manager, t->family, &t->local, 0, &a); + if (r < 0) + return r; + + if (!address_is_ready(a)) + return -EBUSY; + } + + if (ret) + *ret = a->in_addr; + return 0; } - SET_FOREACH(a, link->addresses) - if (l2tp_acquire_local_address_one(t, a, ret) >= 0) - return 1; + if (a) { + if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC && + !FLAGS_SET(a->flags, IFA_F_PERMANENT)) + return -EINVAL; - return -ENODATA; + if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC && + FLAGS_SET(a->flags, IFA_F_PERMANENT)) + return -EINVAL; + + if (ret) + *ret = a->in_addr; + + return 0; + } + + if (link) + return link_get_l2tp_local_address(link, t, ret); + + HASHMAP_FOREACH(link, netdev->manager->links_by_index) { + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + continue; + + if (link_get_l2tp_local_address(link, t, ret) >= 0) + return 0; + } + + return -ENOENT; } static void l2tp_session_destroy_callback(L2tpSession *session) { @@ -370,11 +441,11 @@ static int l2tp_create_tunnel(NetDev *netdev, Link *link) { assert(netdev); assert_se(t = L2TP(netdev)); - r = l2tp_acquire_local_address(t, link, &local_address); + r = l2tp_get_local_address(netdev, &local_address); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not find local address."); - if (r > 0 && DEBUG_LOGGING) { + if (t->local_address_type >= 0 && DEBUG_LOGGING) { _cleanup_free_ char *str = NULL; (void) in_addr_to_string(t->family, &local_address, &str); @@ -395,7 +466,95 @@ static int l2tp_create_tunnel(NetDev *netdev, Link *link) { return 0; } -int config_parse_l2tp_tunnel_address( +static int netdev_l2tp_is_ready_to_create(NetDev *netdev, Link *link) { + return l2tp_get_local_address(netdev, NULL) >= 0; +} + +int config_parse_l2tp_tunnel_local_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *addr_or_type = NULL, *ifname = NULL; + L2tpLocalAddressType type; + L2tpTunnel *t = userdata; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(t); + + if (isempty(rvalue)) { + t->local_ifname = mfree(t->local_ifname); + t->local_address_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO; + t->local = IN_ADDR_NULL; + + if (!in_addr_is_set(t->family, &t->remote)) + /* If Remote= is not specified yet, then also clear family. */ + t->family = AF_UNSPEC; + + return 0; + } + + r = extract_first_word(&p, &addr_or_type, "@", 0); + if (r < 0) + return log_oom(); + if (r == 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid L2TP Tunnel address specified in %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + if (!isempty(p)) { + if (!ifname_valid_full(p, IFNAME_VALID_ALTERNATIVE)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid interface name specified in %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + ifname = strdup(p); + if (!ifname) + return log_oom(); + } + + type = l2tp_local_address_type_from_string(rvalue); + if (type >= 0) { + free_and_replace(t->local_ifname, ifname); + t->local_address_type = type; + t->local = IN_ADDR_NULL; + + if (!in_addr_is_set(t->family, &t->remote)) + /* If Remote= is not specified yet, then also clear family. */ + t->family = AF_UNSPEC; + + return 0; + } + + if (t->family == AF_UNSPEC) + r = in_addr_from_string_auto(rvalue, &t->family, &t->local); + else + r = in_addr_from_string(t->family, rvalue, &t->local); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid L2TP Tunnel address specified in %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + free_and_replace(t->local_ifname, ifname); + t->local_address_type = _NETDEV_L2TP_LOCAL_ADDRESS_INVALID; + return 0; +} + +int config_parse_l2tp_tunnel_remote_address( const char *unit, const char *filename, unsigned line, @@ -408,41 +567,30 @@ int config_parse_l2tp_tunnel_address( void *userdata) { L2tpTunnel *t = userdata; - union in_addr_union *addr = data; int r; assert(filename); assert(lvalue); assert(rvalue); - assert(data); + assert(t); - if (streq(lvalue, "Local")) { - L2tpLocalAddressType addr_type; + if (isempty(rvalue)) { + t->remote = IN_ADDR_NULL; - if (isempty(rvalue)) - addr_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO; - else - addr_type = l2tp_local_address_type_from_string(rvalue); + if (!in_addr_is_set(t->family, &t->local)) + /* If Local= is not specified yet, then also clear family. */ + t->family = AF_UNSPEC; - if (addr_type >= 0) { - if (!in_addr_is_set(t->family, &t->remote)) - /* If Remote= is not specified yet, then also clear family. */ - t->family = AF_UNSPEC; - - t->local = IN_ADDR_NULL; - t->local_address_type = addr_type; - - return 0; - } + return 0; } if (t->family == AF_UNSPEC) - r = in_addr_from_string_auto(rvalue, &t->family, addr); + r = in_addr_from_string_auto(rvalue, &t->family, &t->remote); else - r = in_addr_from_string(t->family, rvalue, addr); + r = in_addr_from_string(t->family, rvalue, &t->remote); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "Invalid L2TP Tunnel address specified in %s='%s', ignoring assignment: %m", lvalue, rvalue); + "Invalid L2TP Tunnel address specified in %s=, ignoring assignment: %s", lvalue, rvalue); return 0; } @@ -699,6 +847,7 @@ static void l2tp_tunnel_done(NetDev *netdev) { assert(t); ordered_hashmap_free_with_destructor(t->sessions_by_section, l2tp_session_free); + free(t->local_ifname); } const NetDevVTable l2tptnl_vtable = { @@ -708,5 +857,6 @@ const NetDevVTable l2tptnl_vtable = { .create_after_configured = l2tp_create_tunnel, .done = l2tp_tunnel_done, .create_type = NETDEV_CREATE_AFTER_CONFIGURED, + .is_ready_to_create = netdev_l2tp_is_ready_to_create, .config_verify = netdev_l2tp_tunnel_verify, }; diff --git a/src/network/netdev/l2tp-tunnel.h b/src/network/netdev/l2tp-tunnel.h index 236b78ce4b9..6028b352057 100644 --- a/src/network/netdev/l2tp-tunnel.h +++ b/src/network/netdev/l2tp-tunnel.h @@ -58,6 +58,7 @@ struct L2tpTunnel { bool udp6_csum_rx; bool udp6_csum_tx; + char *local_ifname; L2tpLocalAddressType local_address_type; union in_addr_union local; union in_addr_union remote; @@ -70,7 +71,8 @@ struct L2tpTunnel { DEFINE_NETDEV_CAST(L2TP, L2tpTunnel); extern const NetDevVTable l2tptnl_vtable; -CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_tunnel_address); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_tunnel_local_address); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_tunnel_remote_address); CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_tunnel_id); CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_encap_type); CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_session_l2spec); diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 2fec1da06bd..6dcc5a804f5 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -103,8 +103,8 @@ L2TP.TunnelId, config_parse_l2tp_tunnel_id, L2TP.PeerTunnelId, config_parse_l2tp_tunnel_id, 0, offsetof(L2tpTunnel, peer_tunnel_id) L2TP.UDPSourcePort, config_parse_ip_port, 0, offsetof(L2tpTunnel, l2tp_udp_sport) L2TP.UDPDestinationPort, config_parse_ip_port, 0, offsetof(L2tpTunnel, l2tp_udp_dport) -L2TP.Local, config_parse_l2tp_tunnel_address, 0, offsetof(L2tpTunnel, local) -L2TP.Remote, config_parse_l2tp_tunnel_address, 0, offsetof(L2tpTunnel, remote) +L2TP.Local, config_parse_l2tp_tunnel_local_address, 0, 0 +L2TP.Remote, config_parse_l2tp_tunnel_remote_address, 0, 0 L2TP.EncapsulationType, config_parse_l2tp_encap_type, 0, offsetof(L2tpTunnel, l2tp_encap_type) L2TP.UDPCheckSum, config_parse_bool, 0, offsetof(L2tpTunnel, udp_csum) L2TP.UDP6CheckSumRx, config_parse_bool, 0, offsetof(L2tpTunnel, udp6_csum_rx) diff --git a/test/test-network/conf/25-l2tp-ip.netdev b/test/test-network/conf/25-l2tp-ip.netdev index 1dd061894fd..882c83ac045 100644 --- a/test/test-network/conf/25-l2tp-ip.netdev +++ b/test/test-network/conf/25-l2tp-ip.netdev @@ -6,7 +6,7 @@ Name=l2tp99 [L2TP] TunnelId=10 PeerTunnelId=12 -Local=static +Local=static@test1 Remote=192.168.30.101 EncapsulationType=ip diff --git a/test/test-network/conf/25-l2tp-udp.netdev b/test/test-network/conf/25-l2tp-udp.netdev index 81d9ef51fcd..79824df5d47 100644 --- a/test/test-network/conf/25-l2tp-udp.netdev +++ b/test/test-network/conf/25-l2tp-udp.netdev @@ -8,7 +8,7 @@ TunnelId=10 PeerTunnelId=11 UDPSourcePort=3000 UDPDestinationPort=4000 -Local=static +Local=static@test1 Remote=192.168.30.101 EncapsulationType=udp UDPCheckSum=true From 0c91c7a24135620e543c006ab6ab5c4f974dbb10 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 25 Feb 2022 13:56:49 +0900 Subject: [PATCH 5/6] network: l2tp: change create type to independent L2TP tunnel does not have underlying interface. Let's change its type to independent. --- man/systemd.network.xml | 3 +-- src/network/netdev/l2tp-tunnel.c | 6 +++--- src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.c | 1 - test/test-network/conf/25-l2tp-dummy.network | 1 - 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 3f5a22e801b..9d4a4b3e1fc 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -869,7 +869,6 @@ Table=1234 IPoIB= IPVLAN= IPVTAP= - L2TP= MACsec= MACVLAN= MACVTAP= @@ -878,7 +877,7 @@ Table=1234 VXLAN= Xfrm= - The name of an IPoIB, IPVLAN, IPVTAP, L2TP, MACsec, MACVLAN, MACVTAP, tunnel, VLAN, + The name of an IPoIB, IPVLAN, IPVTAP, MACsec, MACVLAN, MACVTAP, tunnel, VLAN, VXLAN, or Xfrm to be created on the link. See systemd.netdev5. This option may be specified more than once. diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index e94ca204079..9724e7760ed 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -432,7 +432,7 @@ static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, N return 1; } -static int l2tp_create_tunnel(NetDev *netdev, Link *link) { +static int l2tp_create_tunnel(NetDev *netdev) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; union in_addr_union local_address; L2tpTunnel *t; @@ -854,9 +854,9 @@ const NetDevVTable l2tptnl_vtable = { .object_size = sizeof(L2tpTunnel), .init = l2tp_tunnel_init, .sections = NETDEV_COMMON_SECTIONS "L2TP\0L2TPSession\0", - .create_after_configured = l2tp_create_tunnel, + .create = l2tp_create_tunnel, .done = l2tp_tunnel_done, - .create_type = NETDEV_CREATE_AFTER_CONFIGURED, + .create_type = NETDEV_CREATE_INDEPENDENT, .is_ready_to_create = netdev_l2tp_is_ready_to_create, .config_verify = netdev_l2tp_tunnel_verify, }; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5d83a25c701..b639714d970 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -93,7 +93,7 @@ Network.VRF, config_parse_ifname, Network.IPoIB, config_parse_stacked_netdev, NETDEV_KIND_IPOIB, offsetof(Network, stacked_netdev_names) Network.IPVLAN, config_parse_stacked_netdev, NETDEV_KIND_IPVLAN, offsetof(Network, stacked_netdev_names) Network.IPVTAP, config_parse_stacked_netdev, NETDEV_KIND_IPVTAP, offsetof(Network, stacked_netdev_names) -Network.L2TP, config_parse_stacked_netdev, NETDEV_KIND_L2TP, offsetof(Network, stacked_netdev_names) +Network.L2TP, config_parse_warn_compat, DISABLED_LEGACY, 0 Network.MACsec, config_parse_stacked_netdev, NETDEV_KIND_MACSEC, offsetof(Network, stacked_netdev_names) Network.MACVLAN, config_parse_stacked_netdev, NETDEV_KIND_MACVLAN, offsetof(Network, stacked_netdev_names) Network.MACVTAP, config_parse_stacked_netdev, NETDEV_KIND_MACVTAP, offsetof(Network, stacked_netdev_names) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c6dceef1e95..5dae7b4de11 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -871,7 +871,6 @@ int config_parse_stacked_netdev( NETDEV_KIND_IPOIB, NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, - NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP, diff --git a/test/test-network/conf/25-l2tp-dummy.network b/test/test-network/conf/25-l2tp-dummy.network index d00a50daf6f..507ccd309e7 100644 --- a/test/test-network/conf/25-l2tp-dummy.network +++ b/test/test-network/conf/25-l2tp-dummy.network @@ -5,4 +5,3 @@ Name=test1 [Network] Address=192.168.30.100/24 IPv6AcceptRA=false -L2TP=l2tp99 From 3d24b0ddd80c0b5025bfb68ccd728db21511b43a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 25 Feb 2022 14:02:10 +0900 Subject: [PATCH 6/6] network: netdev: drop unused creation type NETDEV_CREATE_AFTER_CONFIGURED --- src/network/netdev/netdev.c | 55 ++++++++----------------------------- src/network/netdev/netdev.h | 4 --- 2 files changed, 12 insertions(+), 47 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index e1c85d97ab3..c3cdb4f6214 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -144,7 +144,7 @@ bool netdev_is_managed(NetDev *netdev) { static bool netdev_is_stacked_and_independent(NetDev *netdev) { assert(netdev); - if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED)) + if (netdev_get_create_type(netdev) != NETDEV_CREATE_STACKED) return false; switch (netdev->kind) { @@ -180,7 +180,7 @@ static bool netdev_is_stacked_and_independent(NetDev *netdev) { static bool netdev_is_stacked(NetDev *netdev) { assert(netdev); - if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED)) + if (netdev_get_create_type(netdev) != NETDEV_CREATE_STACKED) return false; if (netdev_is_stacked_and_independent(netdev)) @@ -617,10 +617,6 @@ static int netdev_is_ready_to_create(NetDev *netdev, Link *link) { if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return false; - if (netdev_get_create_type(netdev) == NETDEV_CREATE_AFTER_CONFIGURED && - link->state != LINK_STATE_CONFIGURED) - return false; - if (link->set_link_messages > 0) return false; @@ -652,28 +648,21 @@ int request_process_stacked_netdev(Request *req) { if (r <= 0) return r; - switch (netdev_get_create_type(netdev)) { - case NETDEV_CREATE_STACKED: - r = stacked_netdev_create(netdev, link, req->netlink_handler); - break; - case NETDEV_CREATE_AFTER_CONFIGURED: - assert(NETDEV_VTABLE(netdev)->create_after_configured); - r = NETDEV_VTABLE(netdev)->create_after_configured(netdev, link); - break; - default: - assert_not_reached(); - } + r = stacked_netdev_create(netdev, link, req->netlink_handler); if (r < 0) return log_netdev_warning_errno(netdev, r, "Failed to create netdev: %m"); return 1; } -static int link_create_stacked_netdev_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(m); assert(link); + assert(link->create_stacked_netdev_messages > 0); + + link->create_stacked_netdev_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 0; @@ -685,18 +674,6 @@ static int link_create_stacked_netdev_handler_internal(sd_netlink *rtnl, sd_netl return 0; } - return 1; -} - -static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - assert(link); - assert(link->create_stacked_netdev_messages > 0); - - link->create_stacked_netdev_messages--; - - if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0) - return 0; - if (link->create_stacked_netdev_messages == 0) { link->stacked_netdevs_created = true; log_link_debug(link, "Stacked netdevs created."); @@ -706,10 +683,6 @@ static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_messa return 0; } -static int link_create_stacked_netdev_after_configured_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return 0; -} - int link_request_stacked_netdev(Link *link, NetDev *netdev) { int r; @@ -722,15 +695,11 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { if (!IN_SET(netdev->state, NETDEV_STATE_LOADING, NETDEV_STATE_FAILED) || netdev->ifindex > 0) return 0; /* Already created. */ - if (netdev_get_create_type(netdev) == NETDEV_CREATE_STACKED) { - link->stacked_netdevs_created = false; - r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true, - &link->create_stacked_netdev_messages, - link_create_stacked_netdev_handler, - NULL); - } else - r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true, - NULL, link_create_stacked_netdev_after_configured_handler, NULL); + link->stacked_netdevs_created = false; + r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true, + &link->create_stacked_netdev_messages, + link_create_stacked_netdev_handler, + NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m", netdev->ifname); diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 66ee77fd805..ccf58f7ccb4 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -103,7 +103,6 @@ typedef enum NetDevState { typedef enum NetDevCreateType { NETDEV_CREATE_INDEPENDENT, NETDEV_CREATE_STACKED, - NETDEV_CREATE_AFTER_CONFIGURED, _NETDEV_CREATE_MAX, _NETDEV_CREATE_INVALID = -EINVAL, } NetDevCreateType; @@ -160,9 +159,6 @@ typedef struct NetDevVTable { /* create netdev, if not done via rtnl */ int (*create)(NetDev *netdev); - /* create netdev after link is fully configured */ - int (*create_after_configured)(NetDev *netdev, Link *link); - /* perform additional configuration after netdev has been createad */ int (*post_create)(NetDev *netdev, Link *link);