network: support matching based on wifi SSID
This commit is contained in:
parent
ad932b156c
commit
8d968fdd99
|
@ -153,6 +153,14 @@
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>SSID=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>A whitespace-separated list of shell-style globs matching the SSID of the currently
|
||||||
|
connected wireless LAN. If the list is prefixed with a "!", the test is inverted.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Host=</varname></term>
|
<term><varname>Host=</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -142,9 +142,11 @@ bool net_match_config(Set *match_mac,
|
||||||
char * const *match_types,
|
char * const *match_types,
|
||||||
char * const *match_names,
|
char * const *match_names,
|
||||||
char * const *match_property,
|
char * const *match_property,
|
||||||
|
char * const *match_ssid,
|
||||||
sd_device *device,
|
sd_device *device,
|
||||||
const struct ether_addr *dev_mac,
|
const struct ether_addr *dev_mac,
|
||||||
const char *dev_name) {
|
const char *dev_name,
|
||||||
|
const char *ssid) {
|
||||||
|
|
||||||
const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str;
|
const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str;
|
||||||
|
|
||||||
|
@ -178,6 +180,9 @@ bool net_match_config(Set *match_mac,
|
||||||
if (!net_condition_test_property(match_property, device))
|
if (!net_condition_test_property(match_property, device))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!net_condition_test_strv(match_ssid, ssid))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,11 @@ bool net_match_config(Set *match_mac,
|
||||||
char * const *match_type,
|
char * const *match_type,
|
||||||
char * const *match_name,
|
char * const *match_name,
|
||||||
char * const *match_property,
|
char * const *match_property,
|
||||||
|
char * const *match_ssid,
|
||||||
sd_device *device,
|
sd_device *device,
|
||||||
const struct ether_addr *dev_mac,
|
const struct ether_addr *dev_mac,
|
||||||
const char *dev_name);
|
const char *dev_name,
|
||||||
|
const char *ssid);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
|
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
|
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
|
||||||
|
|
|
@ -103,6 +103,8 @@ sources = files('''
|
||||||
networkd-speed-meter.h
|
networkd-speed-meter.h
|
||||||
networkd-util.c
|
networkd-util.c
|
||||||
networkd-util.h
|
networkd-util.h
|
||||||
|
networkd-wifi.c
|
||||||
|
networkd-wifi.h
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
systemd_networkd_sources = files('networkd.c')
|
systemd_networkd_sources = files('networkd.c')
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "networkd-neighbor.h"
|
#include "networkd-neighbor.h"
|
||||||
#include "networkd-radv.h"
|
#include "networkd-radv.h"
|
||||||
#include "networkd-routing-policy-rule.h"
|
#include "networkd-routing-policy-rule.h"
|
||||||
|
#include "networkd-wifi.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
|
@ -712,6 +713,7 @@ static Link *link_free(Link *link) {
|
||||||
|
|
||||||
free(link->ifname);
|
free(link->ifname);
|
||||||
free(link->kind);
|
free(link->kind);
|
||||||
|
free(link->ssid);
|
||||||
|
|
||||||
(void) unlink(link->state_file);
|
(void) unlink(link->state_file);
|
||||||
free(link->state_file);
|
free(link->state_file);
|
||||||
|
@ -2863,7 +2865,7 @@ int link_reconfigure(Link *link) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = network_get(link->manager, link->sd_device, link->ifname,
|
r = network_get(link->manager, link->sd_device, link->ifname,
|
||||||
&link->mac, &network);
|
&link->mac, link->ssid, &network);
|
||||||
if (r == -ENOENT) {
|
if (r == -ENOENT) {
|
||||||
link_enter_unmanaged(link);
|
link_enter_unmanaged(link);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2952,8 +2954,12 @@ static int link_initialized_and_synced(Link *link) {
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!link->network) {
|
if (!link->network) {
|
||||||
|
r = wifi_get_ssid(link);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = network_get(link->manager, link->sd_device, link->ifname,
|
r = network_get(link->manager, link->sd_device, link->ifname,
|
||||||
&link->mac, &network);
|
&link->mac, link->ssid, &network);
|
||||||
if (r == -ENOENT) {
|
if (r == -ENOENT) {
|
||||||
link_enter_unmanaged(link);
|
link_enter_unmanaged(link);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3327,6 +3333,15 @@ static int link_carrier_gained(Link *link) {
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
|
||||||
|
r = wifi_get_ssid(link);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r > 0) {
|
||||||
|
r = link_reconfigure(link);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
|
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
|
||||||
r = link_acquire_conf(link);
|
r = link_acquire_conf(link);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
|
|
@ -55,6 +55,9 @@ typedef struct Link {
|
||||||
uint32_t mtu;
|
uint32_t mtu;
|
||||||
sd_device *sd_device;
|
sd_device *sd_device;
|
||||||
|
|
||||||
|
/* wlan */
|
||||||
|
char *ssid;
|
||||||
|
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
uint8_t kernel_operstate;
|
uint8_t kernel_operstate;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ Match.MACAddress, config_parse_hwaddrs,
|
||||||
Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path)
|
Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path)
|
||||||
Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver)
|
Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver)
|
||||||
Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type)
|
Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type)
|
||||||
|
Match.SSID, config_parse_match_strv, 0, offsetof(Network, match_ssid)
|
||||||
Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name)
|
Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name)
|
||||||
Match.Property, config_parse_match_property, 0, offsetof(Network, match_property)
|
Match.Property, config_parse_match_property, 0, offsetof(Network, match_property)
|
||||||
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
|
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
|
||||||
|
|
|
@ -159,7 +159,7 @@ int network_verify(Network *network) {
|
||||||
if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
|
if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
|
||||||
strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
|
strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
|
||||||
strv_isempty(network->match_name) && strv_isempty(network->match_property) &&
|
strv_isempty(network->match_name) && strv_isempty(network->match_property) &&
|
||||||
!network->conditions)
|
strv_isempty(network->match_ssid) && !network->conditions)
|
||||||
log_warning("%s: No valid settings found in the [Match] section. "
|
log_warning("%s: No valid settings found in the [Match] section. "
|
||||||
"The file will match all interfaces. "
|
"The file will match all interfaces. "
|
||||||
"If that is intended, please add Name=* in the [Match] section.",
|
"If that is intended, please add Name=* in the [Match] section.",
|
||||||
|
@ -547,6 +547,7 @@ static Network *network_free(Network *network) {
|
||||||
strv_free(network->match_type);
|
strv_free(network->match_type);
|
||||||
strv_free(network->match_name);
|
strv_free(network->match_name);
|
||||||
strv_free(network->match_property);
|
strv_free(network->match_property);
|
||||||
|
strv_free(network->match_ssid);
|
||||||
condition_free_list(network->conditions);
|
condition_free_list(network->conditions);
|
||||||
|
|
||||||
free(network->description);
|
free(network->description);
|
||||||
|
@ -653,7 +654,7 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
|
||||||
|
|
||||||
int network_get(Manager *manager, sd_device *device,
|
int network_get(Manager *manager, sd_device *device,
|
||||||
const char *ifname, const struct ether_addr *address,
|
const char *ifname, const struct ether_addr *address,
|
||||||
Network **ret) {
|
const char *ssid, Network **ret) {
|
||||||
Network *network;
|
Network *network;
|
||||||
Iterator i;
|
Iterator i;
|
||||||
|
|
||||||
|
@ -663,7 +664,8 @@ int network_get(Manager *manager, sd_device *device,
|
||||||
ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
|
ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
|
||||||
if (net_match_config(network->match_mac, network->match_path, network->match_driver,
|
if (net_match_config(network->match_mac, network->match_path, network->match_driver,
|
||||||
network->match_type, network->match_name, network->match_property,
|
network->match_type, network->match_name, network->match_property,
|
||||||
device, address, ifname)) {
|
network->match_ssid,
|
||||||
|
device, address, ifname, ssid)) {
|
||||||
if (network->match_name && device) {
|
if (network->match_name && device) {
|
||||||
const char *attr;
|
const char *attr;
|
||||||
uint8_t name_assign_type = NET_NAME_UNKNOWN;
|
uint8_t name_assign_type = NET_NAME_UNKNOWN;
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct Network {
|
||||||
char **match_type;
|
char **match_type;
|
||||||
char **match_name;
|
char **match_name;
|
||||||
char **match_property;
|
char **match_property;
|
||||||
|
char **match_ssid;
|
||||||
LIST_HEAD(Condition, conditions);
|
LIST_HEAD(Condition, conditions);
|
||||||
|
|
||||||
char *description;
|
char *description;
|
||||||
|
@ -285,7 +286,7 @@ int network_load_one(Manager *manager, const char *filename);
|
||||||
int network_verify(Network *network);
|
int network_verify(Network *network);
|
||||||
|
|
||||||
int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
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, 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_apply(Network *network, Link *link);
|
int network_apply(Network *network, Link *link);
|
||||||
void network_apply_anonymize_if_set(Network *network);
|
void network_apply_anonymize_if_set(Network *network);
|
||||||
|
|
||||||
|
|
70
src/network/networkd-wifi.c
Normal file
70
src/network/networkd-wifi.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
#include <linux/nl80211.h>
|
||||||
|
|
||||||
|
#include "sd-bus.h"
|
||||||
|
|
||||||
|
#include "bus-util.h"
|
||||||
|
#include "netlink-internal.h"
|
||||||
|
#include "netlink-util.h"
|
||||||
|
#include "networkd-link.h"
|
||||||
|
#include "networkd-manager.h"
|
||||||
|
#include "networkd-wifi.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
|
||||||
|
int wifi_get_ssid(Link *link) {
|
||||||
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||||
|
_cleanup_free_ char *ssid = NULL;
|
||||||
|
sd_genl_family family;
|
||||||
|
const char *type;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!link->sd_device)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = sd_device_get_devtype(link->sd_device, &type);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
return 0;
|
||||||
|
else if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (!streq(type, "wlan"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = sd_genl_message_new(link->manager->genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Failed to create generic netlink message: %m");
|
||||||
|
|
||||||
|
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, link->ifindex);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
|
||||||
|
|
||||||
|
r = sd_netlink_call(link->manager->genl, m, 0, &reply);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Failed to request information about wifi interface: %m");
|
||||||
|
if (!reply)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = sd_netlink_message_get_errno(reply);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_warning_errno(link, r, "Failed to get information about wifi interface: %m");
|
||||||
|
|
||||||
|
r = sd_genl_message_get_family(link->manager->genl, reply, &family);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_warning_errno(link, r, "Failed to determine genl family: %m");
|
||||||
|
if (family != SD_GENL_NL80211) {
|
||||||
|
log_link_debug(link, "Received message of unexpected genl family %u, ignoring.", family);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, &ssid);
|
||||||
|
if (r < 0 && r != -ENODATA)
|
||||||
|
return log_link_warning_errno(link, r, "Failed to get NL80211_ATTR_SSID attribute: %m");
|
||||||
|
|
||||||
|
free_and_replace(link->ssid, ssid);
|
||||||
|
if (link->ssid)
|
||||||
|
log_link_info(link, "Connected SSID: %s", link->ssid);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
8
src/network/networkd-wifi.h
Normal file
8
src/network/networkd-wifi.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sd-bus.h"
|
||||||
|
|
||||||
|
typedef struct Link Link;
|
||||||
|
|
||||||
|
int wifi_get_ssid(Link *link);
|
|
@ -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
|
/* let's assume that the test machine does not have a .network file
|
||||||
that applies to the loopback device... */
|
that applies to the loopback device... */
|
||||||
assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT);
|
assert_se(network_get(manager, loopback, "lo", &mac, NULL, &network) == -ENOENT);
|
||||||
assert_se(!network);
|
assert_se(!network);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,8 +242,8 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
|
||||||
|
|
||||||
LIST_FOREACH(links, link, ctx->links) {
|
LIST_FOREACH(links, link, ctx->links) {
|
||||||
if (net_match_config(link->match_mac, link->match_path, link->match_driver,
|
if (net_match_config(link->match_mac, link->match_path, link->match_driver,
|
||||||
link->match_type, link->match_name, link->match_property,
|
link->match_type, link->match_name, link->match_property, NULL,
|
||||||
device, NULL, NULL)) {
|
device, NULL, NULL, NULL)) {
|
||||||
if (link->match_name && !strv_contains(link->match_name, "*")) {
|
if (link->match_name && !strv_contains(link->match_name, "*")) {
|
||||||
unsigned name_assign_type = NET_NAME_UNKNOWN;
|
unsigned name_assign_type = NET_NAME_UNKNOWN;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ Type=
|
||||||
Driver=
|
Driver=
|
||||||
Architecture=
|
Architecture=
|
||||||
Path=
|
Path=
|
||||||
|
SSID=
|
||||||
Name=
|
Name=
|
||||||
Property=
|
Property=
|
||||||
Virtualization=
|
Virtualization=
|
||||||
|
|
Loading…
Reference in a new issue