From 277ba8d1ab968f4c699c623a6bb17bd3b5fd17eb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 24 Jul 2019 15:32:24 +0900 Subject: network: add support matching based on BSSID= --- man/systemd.network.xml | 10 ++++++++++ src/libsystemd-network/network-internal.c | 7 ++++++- src/libsystemd-network/network-internal.h | 4 +++- src/network/networkd-link.c | 4 ++-- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 7 ++++--- src/network/networkd-network.h | 4 +++- src/network/test-network.c | 2 +- src/udev/net/link-config.c | 4 ++-- test/fuzz/fuzz-network-parser/directives.network | 1 + 10 files changed, 33 insertions(+), 11 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 03c488d7dc..3863f3d004 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -161,6 +161,16 @@ + + BSSID= + + A whitespace-separated list of hardware address of the currently connected wireless + LAN. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example in + MACAddress=. This option may appear more than one, in which case the + lists are merged. If the empty string is assigned to this option, the list of BSSID defined + prior to this is reset. + + Host= diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index 08c756788e..a8cb4ea286 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -143,10 +143,12 @@ bool net_match_config(Set *match_mac, char * const *match_names, char * const *match_property, char * const *match_ssid, + Set *match_bssid, sd_device *device, const struct ether_addr *dev_mac, const char *dev_name, - const char *ssid) { + const char *ssid, + const struct ether_addr *bssid) { const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str; @@ -183,6 +185,9 @@ bool net_match_config(Set *match_mac, if (!net_condition_test_strv(match_ssid, ssid)) return false; + if (match_bssid && (!bssid || !set_contains(match_bssid, bssid))) + return false; + return true; } diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index 71aec1a99b..f40ad6b1dd 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -21,10 +21,12 @@ bool net_match_config(Set *match_mac, char * const *match_name, char * const *match_property, char * const *match_ssid, + Set *match_bssid, sd_device *device, const struct ether_addr *dev_mac, const char *dev_name, - const char *ssid); + const char *ssid, + const struct ether_addr *bssid); CONFIG_PARSER_PROTOTYPE(config_parse_net_condition); CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1c0ae0184c..5fedd3765c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2865,7 +2865,7 @@ int link_reconfigure(Link *link) { return 0; r = network_get(link->manager, link->sd_device, link->ifname, - &link->mac, link->ssid, &network); + &link->mac, link->ssid, &link->bssid, &network); if (r == -ENOENT) { link_enter_unmanaged(link); return 0; @@ -2959,7 +2959,7 @@ static int link_initialized_and_synced(Link *link) { return r; r = network_get(link->manager, link->sd_device, link->ifname, - &link->mac, link->ssid, &network); + &link->mac, link->ssid, &link->bssid, &network); if (r == -ENOENT) { link_enter_unmanaged(link); return 0; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 95d3331222..832303aaa7 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -30,6 +30,7 @@ Match.Path, config_parse_match_strv, Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver) Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type) Match.SSID, config_parse_match_strv, 0, offsetof(Network, match_ssid) +Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match_bssid) Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name) Match.Property, config_parse_match_property, 0, offsetof(Network, match_property) Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index b3bc598c44..7a2ee5ff85 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -548,6 +548,7 @@ static Network *network_free(Network *network) { strv_free(network->match_name); strv_free(network->match_property); strv_free(network->match_ssid); + set_free_free(network->match_bssid); condition_free_list(network->conditions); free(network->description); @@ -654,7 +655,7 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) { int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *address, - const char *ssid, Network **ret) { + const char *ssid, const struct ether_addr *bssid, Network **ret) { Network *network; Iterator i; @@ -664,8 +665,8 @@ int network_get(Manager *manager, sd_device *device, ORDERED_HASHMAP_FOREACH(network, manager->networks, i) if (net_match_config(network->match_mac, network->match_path, network->match_driver, network->match_type, network->match_name, network->match_property, - network->match_ssid, - device, address, ifname, ssid)) { + network->match_ssid, network->match_bssid, + device, address, ifname, ssid, bssid)) { if (network->match_name && device) { const char *attr; uint8_t name_assign_type = NET_NAME_UNKNOWN; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 883f0fab6e..fd98d88d6a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -64,6 +64,7 @@ struct Network { char **match_name; char **match_property; char **match_ssid; + Set *match_bssid; LIST_HEAD(Condition, conditions); char *description; @@ -286,7 +287,8 @@ int network_load_one(Manager *manager, const char *filename); int network_verify(Network *network); int network_get_by_name(Manager *manager, const char *name, Network **ret); -int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac, const char *ssid, Network **ret); +int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac, + const char *ssid, const struct ether_addr *bssid, Network **ret); int network_apply(Network *network, Link *link); void network_apply_anonymize_if_set(Network *network); diff --git a/src/network/test-network.c b/src/network/test-network.c index 50b5cc047c..130adcbca8 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -125,7 +125,7 @@ static void test_network_get(Manager *manager, sd_device *loopback) { /* let's assume that the test machine does not have a .network file that applies to the loopback device... */ - assert_se(network_get(manager, loopback, "lo", &mac, NULL, &network) == -ENOENT); + assert_se(network_get(manager, loopback, "lo", &mac, NULL, NULL, &network) == -ENOENT); assert_se(!network); } diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 62974b7c95..b84caaf459 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -242,8 +242,8 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) LIST_FOREACH(links, link, ctx->links) { if (net_match_config(link->match_mac, link->match_path, link->match_driver, - link->match_type, link->match_name, link->match_property, NULL, - device, NULL, NULL, NULL)) { + link->match_type, link->match_name, link->match_property, NULL, NULL, + device, NULL, NULL, NULL, NULL)) { if (link->match_name && !strv_contains(link->match_name, "*")) { unsigned name_assign_type = NET_NAME_UNKNOWN; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 8f3153079b..22fe2b4e33 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -20,6 +20,7 @@ Driver= Architecture= Path= SSID= +BSSID= Name= Property= Virtualization= -- cgit v1.2.1