network, udev: introduce PermanentMACAddress= setting in [Match] section

Closes #13983.
This commit is contained in:
Yu Watanabe 2019-01-07 20:16:19 +09:00
parent 79b4428a7d
commit 4bb7cc8287
15 changed files with 77 additions and 15 deletions

View file

@ -80,6 +80,17 @@
<programlisting>MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PermanentMACAddress=</varname></term>
<listitem>
<para>A whitespace-separated list of hardware's permanent addresses. While
<varname>MACAddress=</varname> matches the device's current MAC address, this matches the
device's permanent MAC address, which may be different from the current one. Use full
colon-, hyphen- or dot-delimited hexadecimal. This option may appear more than once, in
which case the lists are merged. If the empty string is assigned to this option, the list
of hardware addresses defined prior to this is reset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>OriginalName=</varname></term>
<listitem>

View file

@ -97,6 +97,17 @@
<programlisting>MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PermanentMACAddress=</varname></term>
<listitem>
<para>A whitespace-separated list of hardware's permanent addresses. While
<varname>MACAddress=</varname> matches the device's current MAC address, this matches the
device's permanent MAC address, which may be different from the current one. Use full
colon-, hyphen- or dot-delimited hexadecimal. This option may appear more than once, in
which case the lists are merged. If the empty string is assigned to this option, the list
of hardware addresses defined prior to this is reset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Path=</varname></term>
<listitem>

View file

@ -167,6 +167,7 @@ static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype);
bool net_match_config(Set *match_mac,
Set *match_permanent_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_types,
@ -177,6 +178,7 @@ bool net_match_config(Set *match_mac,
Set *match_bssid,
sd_device *device,
const struct ether_addr *dev_mac,
const struct ether_addr *dev_permanent_mac,
const char *dev_name,
char * const *alternative_names,
enum nl80211_iftype wifi_iftype,
@ -200,6 +202,12 @@ bool net_match_config(Set *match_mac,
if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
return false;
if (match_permanent_mac &&
(!dev_permanent_mac ||
ether_addr_is_null(dev_permanent_mac) ||
!set_contains(match_permanent_mac, dev_permanent_mac)))
return false;
if (!net_condition_test_strv(match_paths, dev_path))
return false;

View file

@ -16,6 +16,7 @@
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
bool net_match_config(Set *match_mac,
Set *match_permanent_mac,
char * const *match_path,
char * const *match_driver,
char * const *match_type,
@ -26,6 +27,7 @@ bool net_match_config(Set *match_mac,
Set *match_bssid,
sd_device *device,
const struct ether_addr *dev_mac,
const struct ether_addr *dev_permanent_mac,
const char *dev_name,
char * const *alternative_names,
enum nl80211_iftype wifi_iftype,

View file

@ -12,6 +12,7 @@
#include "dhcp-identifier.h"
#include "dhcp-lease-internal.h"
#include "env-file.h"
#include "ethtool-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "ipvlan.h"
@ -617,6 +618,11 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
if (r < 0)
log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
_cleanup_close_ int fd = -1;
r = ethtool_get_permanent_macaddr(&fd, link->ifname, &link->permanent_mac);
if (r < 0)
log_link_debug_errno(link, r, "Permanent MAC address not found for new device, continuing without: %m");
r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &link->alternative_names);
if (r < 0 && r != -ENODATA)
return r;
@ -2961,7 +2967,7 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
}
r = network_get(link->manager, link->sd_device, link->ifname, link->alternative_names,
&link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
&link->mac, &link->permanent_mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 0;
@ -3093,7 +3099,7 @@ static int link_initialized_and_synced(Link *link) {
return r;
r = network_get(link->manager, link->sd_device, link->ifname, link->alternative_names,
&link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
&link->mac, &link->permanent_mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 0;

View file

@ -53,6 +53,7 @@ typedef struct Link {
unsigned short iftype;
char *state_file;
struct ether_addr mac;
struct ether_addr permanent_mac;
struct in6_addr ipv6ll_address;
uint32_t mtu;
sd_device *sd_device;

View file

@ -28,6 +28,7 @@ struct ConfigPerfItem;
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_mac)
Match.PermanentMACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_permanent_mac)
Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path)
Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver)
Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type)

View file

@ -160,10 +160,10 @@ int network_verify(Network *network) {
assert(network);
assert(network->filename);
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_name) && strv_isempty(network->match_property) &&
strv_isempty(network->match_ssid) && !network->conditions)
if (set_isempty(network->match_mac) && set_isempty(network->match_permanent_mac) &&
strv_isempty(network->match_path) && strv_isempty(network->match_driver) &&
strv_isempty(network->match_type) && strv_isempty(network->match_name) &&
strv_isempty(network->match_property) && strv_isempty(network->match_ssid) && !network->conditions)
log_warning("%s: No valid settings found in the [Match] section. "
"The file will match all interfaces. "
"If that is intended, please add Name=* in the [Match] section.",
@ -601,6 +601,7 @@ static Network *network_free(Network *network) {
free(network->filename);
set_free_free(network->match_mac);
set_free_free(network->match_permanent_mac);
strv_free(network->match_path);
strv_free(network->match_driver);
strv_free(network->match_type);
@ -721,7 +722,8 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
}
int network_get(Manager *manager, sd_device *device,
const char *ifname, char * const *alternative_names, const struct ether_addr *address,
const char *ifname, char * const *alternative_names,
const struct ether_addr *address, const struct ether_addr *permanent_address,
enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
Network **ret) {
Network *network;
@ -731,10 +733,12 @@ int network_get(Manager *manager, sd_device *device,
assert(ret);
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_permanent_mac,
network->match_path, network->match_driver,
network->match_type, network->match_name, network->match_property,
network->match_wlan_iftype, network->match_ssid, network->match_bssid,
device, address, ifname, alternative_names, wlan_iftype, ssid, bssid)) {
device, address, permanent_address,
ifname, alternative_names, wlan_iftype, ssid, bssid)) {
if (network->match_name && device) {
const char *attr;
uint8_t name_assign_type = NET_NAME_UNKNOWN;

View file

@ -64,6 +64,7 @@ struct Network {
unsigned n_ref;
Set *match_mac;
Set *match_permanent_mac;
char **match_path;
char **match_driver;
char **match_type;
@ -302,7 +303,8 @@ 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, char * const *alternative_names,
const struct ether_addr *mac, enum nl80211_iftype wlan_iftype, const char *ssid,
const struct ether_addr *mac, const struct ether_addr *permanent_mac,
enum nl80211_iftype wlan_iftype, 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);

View file

@ -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", NULL, &mac, 0, NULL, NULL, &network) == -ENOENT);
assert_se(network_get(manager, loopback, "lo", NULL, &mac, &mac, 0, NULL, NULL, &network) == -ENOENT);
assert_se(!network);
}

View file

@ -20,6 +20,7 @@ struct ConfigPerfItem;
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
Match.PermanentMACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_permanent_mac)
Match.OriginalName, config_parse_match_ifnames, 0, offsetof(link_config, match_name)
Match.Path, config_parse_match_strv, 0, offsetof(link_config, match_path)
Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match_driver)

View file

@ -47,6 +47,7 @@ static void link_config_free(link_config *link) {
free(link->filename);
set_free_free(link->match_mac);
set_free_free(link->match_permanent_mac);
strv_free(link->match_path);
strv_free(link->match_driver);
strv_free(link->match_type);
@ -162,8 +163,8 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
if (link->speed > UINT_MAX)
return -ERANGE;
if (set_isempty(link->match_mac) && strv_isempty(link->match_path) &&
strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
if (set_isempty(link->match_mac) && set_isempty(link->match_permanent_mac) &&
strv_isempty(link->match_path) && strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions)
log_warning("%s: No valid settings found in the [Match] section. "
"The file will match all interfaces. "
@ -236,16 +237,27 @@ bool link_config_should_reload(link_config_ctx *ctx) {
}
int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) {
struct ether_addr permanent_mac = {};
link_config *link;
const char *name;
int r;
assert(ctx);
assert(device);
assert(ret);
r = sd_device_get_sysname(device, &name);
if (r < 0)
return r;
r = ethtool_get_permanent_macaddr(&ctx->ethtool_fd, name, &permanent_mac);
if (r < 0)
log_device_debug_errno(device, r, "Failed to get permanent MAC address, ignoring: %m");
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_permanent_mac, link->match_path, link->match_driver,
link->match_type, link->match_name, link->match_property, NULL, NULL, NULL,
device, NULL, NULL, NULL, 0, NULL, NULL)) {
device, NULL, &permanent_mac, NULL, NULL, 0, NULL, NULL)) {
if (link->match_name && !strv_contains(link->match_name, "*")) {
unsigned name_assign_type = NET_NAME_UNKNOWN;

View file

@ -36,6 +36,7 @@ struct link_config {
char *filename;
Set *match_mac;
Set *match_permanent_mac;
char **match_path;
char **match_driver;
char **match_type;

View file

@ -1,5 +1,6 @@
[Match]
MACAddress=
PermanentMACAddress=
OriginalName=
Path=
Driver=

View file

@ -28,6 +28,7 @@ Virtualization=
KernelCommandLine=
Host=
MACAddress=
PermanentMACAddress=
[Link]
RequiredForOnline=
ARP=