summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-07-11 19:23:29 +0200
committerGitHub <noreply@github.com>2019-07-11 19:23:29 +0200
commitbe9d8212a52fd1af8c169566d2092fcd70220d94 (patch)
tree276632ff6ad9d95f0d30388c2b27e875f5669599
parenttests: turn on the "object-size" UBSan check on Fuzzit (diff)
parenttest-network: add testcase that Neighbor.LinkLayerAddress= is IP address (diff)
downloadsystemd-be9d8212a52fd1af8c169566d2092fcd70220d94.tar.xz
systemd-be9d8212a52fd1af8c169566d2092fcd70220d94.zip
Merge pull request #13017 from yuwata/network-neighbor-lladdr-13015
network: rename Neighbor.MACAddress= and also support IPv4 address
-rw-r--r--man/systemd.network.xml4
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c2
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c2
-rw-r--r--src/network/networkctl.c2
-rw-r--r--src/network/networkd-fdb.c24
-rw-r--r--src/network/networkd-fdb.h2
-rw-r--r--src/network/networkd-neighbor.c121
-rw-r--r--src/network/networkd-neighbor.h17
-rw-r--r--src/network/networkd-network-gperf.gperf3
-rw-r--r--src/network/networkd-network.c2
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network1
-rw-r--r--test/test-network/conf/25-neighbor-ip-dummy.network6
-rw-r--r--test/test-network/conf/25-neighbor-ip.network10
-rw-r--r--test/test-network/conf/25-neighbor-section.network4
-rwxr-xr-xtest/test-network/systemd-networkd-tests.py19
15 files changed, 156 insertions, 63 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index c544315601..612450dbd8 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1016,9 +1016,9 @@
</listitem>
</varlistentry>
<varlistentry>
- <term><varname>MACAddress=</varname></term>
+ <term><varname>LinkLayerAddress=</varname></term>
<listitem>
- <para>The hardware address of the neighbor.</para>
+ <para>The link layer address (MAC address or IP address) of the neighbor.</para>
</listitem>
</varlistentry>
</variablelist>
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 7850406323..5323844c08 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -611,7 +611,7 @@ int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t s
if (data)
memcpy(data, attr_data, size);
- return 0;
+ return r;
}
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 450e298f2c..5e4d8a94a0 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -663,7 +663,7 @@ static const NLTypeSystem rtnl_route_type_system = {
static const NLType rtnl_neigh_types[] = {
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
- [NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
+ [NDA_LLADDR] = { /* struct ether_addr or struct in_addr */ },
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
[NDA_PROBES] = { .type = NETLINK_TYPE_U32 },
[NDA_VLAN] = { .type = NETLINK_TYPE_U16 },
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 2a748b8599..9d755c96d6 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -519,7 +519,7 @@ static int get_gateway_description(
if (!in_addr_equal(fam, &gw, gateway))
continue;
- r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac);
+ r = sd_netlink_message_read(m, NDA_LLADDR, sizeof(mac), &mac);
if (r < 0)
continue;
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index e3333698f8..5b7468c103 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -39,7 +39,6 @@ static int fdb_entry_new_static(
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
- _cleanup_free_ struct ether_addr *mac_addr = NULL;
int r;
assert(network);
@@ -63,11 +62,6 @@ static int fdb_entry_new_static(
if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX)
return -E2BIG;
- /* allocate space for MAC address. */
- mac_addr = new0(struct ether_addr, 1);
- if (!mac_addr)
- return -ENOMEM;
-
/* allocate space for and FDB entry. */
fdb_entry = new(FdbEntry, 1);
if (!fdb_entry)
@@ -76,7 +70,6 @@ static int fdb_entry_new_static(
/* init FDB structure. */
*fdb_entry = (FdbEntry) {
.network = network,
- .mac_addr = TAKE_PTR(mac_addr),
.vni = VXLAN_VID_MAX + 1,
.fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
};
@@ -143,7 +136,7 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
if (r < 0)
return rtnl_log_create_error(r);
- r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr);
+ r = sd_netlink_message_append_data(req, NDA_LLADDR, &fdb_entry->mac_addr, sizeof(fdb_entry->mac_addr));
if (r < 0)
return rtnl_log_create_error(r);
@@ -192,7 +185,6 @@ void fdb_entry_free(FdbEntry *fdb_entry) {
}
network_config_section_free(fdb_entry->section);
- free(fdb_entry->mac_addr);
free(fdb_entry);
}
@@ -223,17 +215,9 @@ int config_parse_fdb_hwaddr(
if (r < 0)
return log_oom();
- /* read in the MAC address for the FDB table. */
- r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
- &fdb_entry->mac_addr->ether_addr_octet[0],
- &fdb_entry->mac_addr->ether_addr_octet[1],
- &fdb_entry->mac_addr->ether_addr_octet[2],
- &fdb_entry->mac_addr->ether_addr_octet[3],
- &fdb_entry->mac_addr->ether_addr_octet[4],
- &fdb_entry->mac_addr->ether_addr_octet[5]);
-
- if (r != ETHER_ADDR_LEN) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
+ r = ether_addr_from_string(rvalue, &fdb_entry->mac_addr);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
return 0;
}
diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h
index bcdd8ce3cb..5e24ad6aee 100644
--- a/src/network/networkd-fdb.h
+++ b/src/network/networkd-fdb.h
@@ -35,7 +35,7 @@ struct FdbEntry {
int family;
uint16_t vlan_id;
- struct ether_addr *mac_addr;
+ struct ether_addr mac_addr;
union in_addr_union destination_addr;
NeighborCacheEntryFlags fdb_ntf_flags;
diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c
index d0275fdd3e..47839df13c 100644
--- a/src/network/networkd-neighbor.c
+++ b/src/network/networkd-neighbor.c
@@ -59,6 +59,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
*neighbor = (Neighbor) {
.network = network,
.family = AF_UNSPEC,
+ .lladdr_type = _NEIGHBOR_LLADDR_INVALID,
};
LIST_APPEND(neighbors, network->neighbors, neighbor);
@@ -115,11 +116,6 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
assert(link->manager);
assert(link->manager->rtnl);
- if (neighbor->family == AF_UNSPEC)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without Address= configured");
- if (!neighbor->mac_configured)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without MACAddress= configured");
-
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
link->ifindex, neighbor->family);
if (r < 0)
@@ -133,7 +129,10 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
if (r < 0)
return log_error_errno(r, "Could not set flags: %m");
- r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, &neighbor->mac);
+ if (neighbor->lladdr_type == NEIGHBOR_LLADDR_MAC)
+ r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr.mac, sizeof(neighbor->lladdr.mac));
+ else
+ r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr.ip.in, sizeof(neighbor->lladdr.ip.in));
if (r < 0)
return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m");
@@ -152,16 +151,36 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
return 0;
}
-int config_parse_neighbor_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) {
+int neighbor_section_verify(Neighbor *neighbor) {
+ if (section_is_invalid(neighbor->section))
+ return -EINVAL;
+
+ if (neighbor->family == AF_UNSPEC)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: Neighbor section without Address= configured. "
+ "Ignoring [Neighbor] section from line %u.",
+ neighbor->section->filename, neighbor->section->line);
+
+ if (neighbor->lladdr_type < 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: Neighbor section without LinkLayerAddress= configured. "
+ "Ignoring [Neighbor] section from line %u.",
+ neighbor->section->filename, neighbor->section->line);
+
+ return 0;
+}
+
+int config_parse_neighbor_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) {
Network *network = userdata;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
@@ -188,16 +207,60 @@ int config_parse_neighbor_address(const char *unit,
return 0;
}
-int config_parse_neighbor_hwaddr(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) {
+int config_parse_neighbor_lladdr(
+ 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) {
+
+ Network *network = userdata;
+ _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = neighbor_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = ether_addr_from_string(rvalue, &n->lladdr.mac);
+ if (r >= 0)
+ n->lladdr_type = NEIGHBOR_LLADDR_MAC;
+ else {
+ r = in_addr_from_string(AF_INET, rvalue, &n->lladdr.ip);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor LinkLayerAddress= is invalid, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+ n->lladdr_type = NEIGHBOR_LLADDR_IP;
+ }
+
+ TAKE_PTR(n);
+
+ return 0;
+}
+
+int config_parse_neighbor_hwaddr(
+ 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) {
Network *network = userdata;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
@@ -213,13 +276,13 @@ int config_parse_neighbor_hwaddr(const char *unit,
if (r < 0)
return r;
- r = ether_addr_from_string(rvalue, &n->mac);
+ r = ether_addr_from_string(rvalue, &n->lladdr.mac);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress is invalid, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress= is invalid, ignoring assignment: %s", rvalue);
return 0;
}
- n->mac_configured = true;
+ n->lladdr_type = NEIGHBOR_LLADDR_MAC;
TAKE_PTR(n);
return 0;
diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h
index f591f0b03f..1405ac25e2 100644
--- a/src/network/networkd-neighbor.h
+++ b/src/network/networkd-neighbor.h
@@ -15,6 +15,13 @@ typedef struct Neighbor Neighbor;
#include "networkd-network.h"
#include "networkd-util.h"
+typedef enum {
+ NEIGHBOR_LLADDR_MAC,
+ NEIGHBOR_LLADDR_IP,
+ _NEIGHBOR_LLADDR_MAX,
+ _NEIGHBOR_LLADDR_INVALID = -1,
+} NeighborLLAddressType;
+
struct Neighbor {
Network *network;
Link *link;
@@ -22,8 +29,11 @@ struct Neighbor {
int family;
union in_addr_union in_addr;
- bool mac_configured;
- struct ether_addr mac;
+ union {
+ struct ether_addr mac;
+ union in_addr_union ip;
+ } lladdr;
+ NeighborLLAddressType lladdr_type;
LIST_FIELDS(Neighbor, neighbors);
};
@@ -34,5 +44,8 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
+int neighbor_section_verify(Neighbor *neighbor);
+
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
+CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index ed8c061efb..3501ffdd10 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -108,7 +108,8 @@ Address.Scope, config_parse_address_scope,
IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0
IPv6AddressLabel.Label, config_parse_address_label, 0, 0
Neighbor.Address, config_parse_neighbor_address, 0, 0
-Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0
+Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0
+Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0 /* deprecated */
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule_tos, 0, 0
RoutingPolicyRule.Priority, config_parse_routing_policy_rule_priority, 0, 0
RoutingPolicyRule.Table, config_parse_routing_policy_rule_table, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 097938057b..9d3c383378 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -269,7 +269,7 @@ int network_verify(Network *network) {
fdb_entry_free(fdb);
LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
- if (section_is_invalid(neighbor->section))
+ if (neighbor_section_verify(neighbor) < 0)
neighbor_free(neighbor);
LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index b895e09d53..69a4281542 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -223,6 +223,7 @@ Managed=
OtherInformation=
[Neighbor]
Address=
+LinkLayerAddress=
MACAddress=
[IPv6AddressLabel]
Label=
diff --git a/test/test-network/conf/25-neighbor-ip-dummy.network b/test/test-network/conf/25-neighbor-ip-dummy.network
new file mode 100644
index 0000000000..d99d97298a
--- /dev/null
+++ b/test/test-network/conf/25-neighbor-ip-dummy.network
@@ -0,0 +1,6 @@
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Tunnel=gretun97
diff --git a/test/test-network/conf/25-neighbor-ip.network b/test/test-network/conf/25-neighbor-ip.network
new file mode 100644
index 0000000000..8865ccd972
--- /dev/null
+++ b/test/test-network/conf/25-neighbor-ip.network
@@ -0,0 +1,10 @@
+[Match]
+Name=gretun97
+
+[Network]
+IPv6AcceptRA=no
+Address=10.0.0.21
+
+[Neighbor]
+Address=10.0.0.22
+LinkLayerAddress=10.65.223.239
diff --git a/test/test-network/conf/25-neighbor-section.network b/test/test-network/conf/25-neighbor-section.network
index 02dbd3843b..94c04943b7 100644
--- a/test/test-network/conf/25-neighbor-section.network
+++ b/test/test-network/conf/25-neighbor-section.network
@@ -6,8 +6,8 @@ IPv6AcceptRA=no
[Neighbor]
Address=192.168.10.1
-MACAddress=00:00:5e:00:02:65
+LinkLayerAddress=00:00:5e:00:02:65
[Neighbor]
Address=2004:da8:1:0::1
-MACAddress=00:00:5e:00:02:66
+LinkLayerAddress=00:00:5e:00:02:66
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 6344b3d87e..272d5453fe 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -1376,7 +1376,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'bond199',
'dummy98',
'dummy99',
- 'test1']
+ 'gretun97',
+ 'test1'
+ ]
units = [
'11-dummy.netdev',
@@ -1391,8 +1393,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-bond-active-backup-slave.netdev',
'25-fibrule-invert.network',
'25-fibrule-port-range.network',
+ '25-gre-tunnel-remote-any.netdev',
'25-ipv6-address-label-section.network',
'25-neighbor-section.network',
+ '25-neighbor-ip-dummy.network',
+ '25-neighbor-ip.network',
'25-link-local-addressing-no.network',
'25-link-local-addressing-yes.network',
'25-link-section-unmanaged.network',
@@ -1620,7 +1625,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, '2004:da8:1::/64')
- def test_ipv6_neighbor(self):
+ def test_neighbor_section(self):
copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
start_networkd()
wait_online(['dummy98:degraded'], timeout='40s')
@@ -1630,6 +1635,16 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
+ def test_neighbor_gre(self):
+ copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ip-dummy.network',
+ '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev')
+ start_networkd()
+ wait_online(['dummy98:degraded', 'gretun97:routable'], timeout='40s')
+
+ output = check_output('ip neigh list dev gretun97')
+ print(output)
+ self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
+
def test_link_local_addressing(self):
copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
'25-link-local-addressing-no.network', '12-dummy.netdev')