Merge pull request #17478 from yuwata/split-network-internal

libsystemd-network: split network-internal.c
This commit is contained in:
Yu Watanabe 2020-11-27 09:04:19 +09:00 committed by GitHub
commit 0d5eb02134
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 869 additions and 851 deletions

View File

@ -3194,7 +3194,6 @@ public_programs += executable(
c_args : '-DLOG_REALM=LOG_REALM_UDEV',
include_directories : includes,
link_with : [libudev_core,
libsystemd_network,
libudev_static],
dependencies : [versiondep,
threads,

View File

@ -108,7 +108,6 @@ fuzzers += [
[['src/fuzz/fuzz-udev-rules.c'],
[libudev_core,
libudev_static,
libsystemd_network,
libshared],
[threads,
libacl]],

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/if_infiniband.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include "sd-device.h"
@ -8,7 +9,7 @@
#include "dhcp-identifier.h"
#include "dhcp6-protocol.h"
#include "network-internal.h"
#include "network-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
#include "stdio-util.h"

View File

@ -17,6 +17,7 @@ sources = files('''
arp-util.h
arp-util.c
network-internal.c
network-internal.h
sd-ndisc.c
ndisc-internal.h
ndisc-router.h
@ -42,10 +43,7 @@ sources = files('''
sd-lldp.c
'''.split())
network_internal_h = files('network-internal.h')
libsystemd_network = static_library(
'systemd-network',
sources,
network_internal_h,
include_directories : includes)

View File

@ -4,658 +4,15 @@
#include <linux/if.h>
#include <netinet/ether.h>
#include "sd-id128.h"
#include "sd-ndisc.h"
#include "alloc-util.h"
#include "arphrd-list.h"
#include "condition.h"
#include "conf-parser.h"
#include "device-util.h"
#include "dhcp-lease-internal.h"
#include "env-util.h"
#include "ether-addr-util.h"
#include "extract-word.h"
#include "hexdecoct.h"
#include "log.h"
#include "network-internal.h"
#include "parse-util.h"
#include "siphash24.h"
#include "socket-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
#include "util.h"
const char *net_get_name_persistent(sd_device *device) {
const char *name, *field;
assert(device);
/* fetch some persistent data unique (on this machine) to this device */
FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC")
if (sd_device_get_property_value(device, field, &name) >= 0)
return name;
return NULL;
}
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result) {
size_t l, sz = 0;
const char *name;
int r;
uint8_t *v;
assert(device);
/* net_get_name_persistent() will return one of the device names based on stable information about
* the device. If this is not available, we fall back to using the actual device name. */
name = net_get_name_persistent(device);
if (!name && use_sysname)
(void) sd_device_get_sysname(device, &name);
if (!name)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENODATA),
"No stable identifying information found");
log_device_debug(device, "Using \"%s\" as stable identifying information", name);
l = strlen(name);
sz = sizeof(sd_id128_t) + l;
v = newa(uint8_t, sz);
/* Fetch some persistent data unique to this machine */
r = sd_id128_get_machine((sd_id128_t*) v);
if (r < 0)
return r;
memcpy(v + sizeof(sd_id128_t), name, l);
/* Let's hash the machine ID plus the device name. We use
* a fixed, but originally randomly created hash key here. */
*result = htole64(siphash24(v, sz, HASH_KEY.bytes));
return 0;
}
static bool net_condition_test_strv(char * const *patterns, const char *string) {
char * const *p;
bool match = false, has_positive_rule = false;
if (strv_isempty(patterns))
return true;
STRV_FOREACH(p, patterns) {
const char *q = *p;
bool invert;
invert = *q == '!';
q += invert;
if (!invert)
has_positive_rule = true;
if (string && fnmatch(q, string, 0) == 0) {
if (invert)
return false;
else
match = true;
}
}
return has_positive_rule ? match : true;
}
static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
if (net_condition_test_strv(patterns, ifname))
return true;
char * const *p;
STRV_FOREACH(p, alternative_names)
if (net_condition_test_strv(patterns, *p))
return true;
return false;
}
static int net_condition_test_property(char * const *match_property, sd_device *device) {
char * const *p;
if (strv_isempty(match_property))
return true;
STRV_FOREACH(p, match_property) {
_cleanup_free_ char *key = NULL;
const char *val, *dev_val;
bool invert, v;
invert = **p == '!';
val = strchr(*p + invert, '=');
if (!val)
return -EINVAL;
key = strndup(*p + invert, val - *p - invert);
if (!key)
return -ENOMEM;
val++;
v = device &&
sd_device_get_property_value(device, key, &dev_val) >= 0 &&
fnmatch(val, dev_val, 0) == 0;
if (invert ? v : !v)
return false;
}
return true;
}
static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = {
[NL80211_IFTYPE_ADHOC] = "ad-hoc",
[NL80211_IFTYPE_STATION] = "station",
[NL80211_IFTYPE_AP] = "ap",
[NL80211_IFTYPE_AP_VLAN] = "ap-vlan",
[NL80211_IFTYPE_WDS] = "wds",
[NL80211_IFTYPE_MONITOR] = "monitor",
[NL80211_IFTYPE_MESH_POINT] = "mesh-point",
[NL80211_IFTYPE_P2P_CLIENT] = "p2p-client",
[NL80211_IFTYPE_P2P_GO] = "p2p-go",
[NL80211_IFTYPE_P2P_DEVICE] = "p2p-device",
[NL80211_IFTYPE_OCB] = "ocb",
[NL80211_IFTYPE_NAN] = "nan",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype);
char *link_get_type_string(unsigned short iftype, sd_device *device) {
const char *t, *devtype;
char *p;
if (device &&
sd_device_get_devtype(device, &devtype) >= 0 &&
!isempty(devtype))
return strdup(devtype);
t = arphrd_to_name(iftype);
if (!t)
return NULL;
p = strdup(t);
if (!p)
return NULL;
ascii_strlower(p);
return p;
}
bool net_match_config(Set *match_mac,
Set *match_permanent_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_iftypes,
char * const *match_names,
char * const *match_property,
char * const *match_wifi_iftype,
char * const *match_ssid,
Set *match_bssid,
sd_device *device,
const struct ether_addr *dev_mac,
const struct ether_addr *dev_permanent_mac,
const char *dev_driver,
unsigned short dev_iftype,
const char *dev_name,
char * const *alternative_names,
enum nl80211_iftype dev_wifi_iftype,
const char *dev_ssid,
const struct ether_addr *dev_bssid) {
_cleanup_free_ char *dev_iftype_str;
const char *dev_path = NULL;
dev_iftype_str = link_get_type_string(dev_iftype, device);
if (device) {
const char *mac_str;
(void) sd_device_get_property_value(device, "ID_PATH", &dev_path);
if (!dev_driver)
(void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver);
if (!dev_name)
(void) sd_device_get_sysname(device, &dev_name);
if (!dev_mac &&
sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
dev_mac = ether_aton(mac_str);
}
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;
if (!net_condition_test_strv(match_drivers, dev_driver))
return false;
if (!net_condition_test_strv(match_iftypes, dev_iftype_str))
return false;
if (!net_condition_test_ifname(match_names, dev_name, alternative_names))
return false;
if (!net_condition_test_property(match_property, device))
return false;
if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(dev_wifi_iftype)))
return false;
if (!net_condition_test_strv(match_ssid, dev_ssid))
return false;
if (match_bssid && (!dev_bssid || !set_contains(match_bssid, dev_bssid)))
return false;
return true;
}
int config_parse_net_condition(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) {
ConditionType cond = ltype;
Condition **list = data, *c;
bool negate;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*list = condition_free_list_type(*list, cond);
return 0;
}
negate = rvalue[0] == '!';
if (negate)
rvalue++;
c = condition_new(cond, rvalue, false, negate);
if (!c)
return log_oom();
/* Drop previous assignment. */
*list = condition_free_list_type(*list, cond);
LIST_PREPEND(conditions, *list, c);
return 0;
}
int config_parse_match_strv(
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) {
const char *p = rvalue;
char ***sv = data;
bool invert;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*sv = strv_free(*sv);
return 0;
}
invert = *p == '!';
p += invert;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (invert) {
k = strjoin("!", word);
if (!k)
return log_oom();
} else
k = TAKE_PTR(word);
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
}
int config_parse_match_ifnames(
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) {
const char *p = rvalue;
char ***sv = data;
bool invert;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
invert = *p == '!';
p += invert;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Failed to parse interface name list: %s", rvalue);
return 0;
}
if (!ifname_valid_full(word, ltype)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Interface name is not valid or too long, ignoring assignment: %s", word);
continue;
}
if (invert) {
k = strjoin("!", word);
if (!k)
return log_oom();
} else
k = TAKE_PTR(word);
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
}
int config_parse_match_property(
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) {
const char *p = rvalue;
char ***sv = data;
bool invert;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
invert = *p == '!';
p += invert;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (!env_assignment_is_valid(word)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid property or value, ignoring assignment: %s", word);
continue;
}
if (invert) {
k = strjoin("!", word);
if (!k)
return log_oom();
} else
k = TAKE_PTR(word);
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
}
int config_parse_ifalias(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) {
char **s = data;
_cleanup_free_ char *n = NULL;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
n = strdup(rvalue);
if (!n)
return log_oom();
if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
return 0;
}
if (isempty(n))
*s = mfree(*s);
else
free_and_replace(*s, n);
return 0;
}
int config_parse_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) {
_cleanup_free_ struct ether_addr *n = NULL;
struct ether_addr **hwaddr = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
n = new0(struct ether_addr, 1);
if (!n)
return log_oom();
r = ether_addr_from_string(rvalue, n);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
return 0;
}
free_and_replace(*hwaddr, n);
return 0;
}
int config_parse_hwaddrs(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_set_free_free_ Set *s = NULL;
const char *p = rvalue;
Set **hwaddrs = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
*hwaddrs = set_free_free(*hwaddrs);
return 0;
}
s = set_new(&ether_addr_hash_ops);
if (!s)
return log_oom();
for (;;) {
_cleanup_free_ char *word = NULL;
_cleanup_free_ struct ether_addr *n = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
n = new(struct ether_addr, 1);
if (!n)
return log_oom();
r = ether_addr_from_string(word, n);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word);
continue;
}
r = set_put(s, n);
if (r < 0)
return log_oom();
if (r > 0)
n = NULL; /* avoid cleanup */
}
r = set_ensure_allocated(hwaddrs, &ether_addr_hash_ops);
if (r < 0)
return log_oom();
r = set_move(*hwaddrs, s);
if (r < 0)
return log_oom();
return 0;
}
int config_parse_bridge_port_priority(
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) {
uint16_t i;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = safe_atou16(rvalue, &i);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse bridge port priority, ignoring: %s", rvalue);
return 0;
}
if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue);
return 0;
}
*((uint16_t *)data) = i;
return 0;
}
size_t serialize_in_addrs(FILE *f,
const struct in_addr *addresses,

View File

@ -1,53 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <linux/nl80211.h>
#include <stdbool.h>
#include <stdio.h>
#include "sd-device.h"
#include "sd-dhcp-lease.h"
#include "conf-parser.h"
#include "set.h"
#include "strv.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
char *link_get_type_string(unsigned short iftype, sd_device *device);
bool net_match_config(Set *match_mac,
Set *match_permanent_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_iftypes,
char * const *match_names,
char * const *match_property,
char * const *match_wifi_iftype,
char * const *match_ssid,
Set *match_bssid,
sd_device *device,
const struct ether_addr *dev_mac,
const struct ether_addr *dev_permanent_mac,
const char *dev_driver,
unsigned short dev_iftype,
const char *dev_name,
char * const *alternative_names,
enum nl80211_iftype dev_wifi_iftype,
const char *dev_ssid,
const struct ether_addr *dev_bssid);
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result);
const char *net_get_name_persistent(sd_device *device);
size_t serialize_in_addrs(FILE *f,
const struct in_addr *addresses,
size_t size,

View File

@ -21,10 +21,10 @@
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
#include "network-internal.h"
#include "random-util.h"
#include "socket-util.h"
#include "string-table.h"
#include "strv.h"
#include "util.h"
#include "web-util.h"

View File

@ -1,8 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-id128.h"
#include "alloc-util.h"
#include "arphrd-list.h"
#include "device-util.h"
#include "fd-util.h"
#include "network-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
#include "string-table.h"
#include "strv.h"
@ -103,3 +109,72 @@ int parse_operational_state_range(const char *str, LinkOperationalStateRange *ou
return 0;
}
char *link_get_type_string(sd_device *device, unsigned short iftype) {
const char *t;
char *p;
if (device &&
sd_device_get_devtype(device, &t) >= 0 &&
!isempty(t))
return strdup(t);
t = arphrd_to_name(iftype);
if (!t)
return NULL;
p = strdup(t);
if (!p)
return NULL;
return ascii_strlower(p);
}
const char *net_get_name_persistent(sd_device *device) {
const char *name, *field;
assert(device);
/* fetch some persistent data unique (on this machine) to this device */
FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC")
if (sd_device_get_property_value(device, field, &name) >= 0)
return name;
return NULL;
}
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result) {
size_t l, sz = 0;
const char *name;
int r;
uint8_t *v;
assert(device);
/* net_get_name_persistent() will return one of the device names based on stable information about
* the device. If this is not available, we fall back to using the actual device name. */
name = net_get_name_persistent(device);
if (!name && use_sysname)
(void) sd_device_get_sysname(device, &name);
if (!name)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENODATA),
"No stable identifying information found");
log_device_debug(device, "Using \"%s\" as stable identifying information", name);
l = strlen(name);
sz = sizeof(sd_id128_t) + l;
v = newa(uint8_t, sz);
/* Fetch some persistent data unique to this machine */
r = sd_id128_get_machine((sd_id128_t*) v);
if (r < 0)
return r;
memcpy(v + sizeof(sd_id128_t), name, l);
/* Let's hash the machine ID plus the device name. We use
* a fixed, but originally randomly created hash key here. */
*result = htole64(siphash24(v, sz, HASH_KEY.bytes));
return 0;
}

View File

@ -1,6 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <inttypes.h>
#include <stdbool.h>
#include "sd-device.h"
#include "sd-network.h"
#include "macro.h"
@ -58,3 +62,7 @@ typedef struct LinkOperationalStateRange {
LINK_OPERSTATE_ROUTABLE }
int parse_operational_state_range(const char *str, LinkOperationalStateRange *out);
char *link_get_type_string(sd_device *device, unsigned short iftype);
int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result);
const char *net_get_name_persistent(sd_device *device);

View File

@ -171,7 +171,7 @@ systemd_networkd_wait_online_sources = files('''
wait-online/manager.c
wait-online/manager.h
wait-online/wait-online.c
'''.split()) + network_internal_h
'''.split())
networkctl_sources = files('networkctl.c')
@ -214,7 +214,6 @@ if conf.get('ENABLE_NETWORKD') == 1
libnetworkd_core = static_library(
'networkd-core',
sources,
network_internal_h,
networkd_gperf_c,
networkd_network_gperf_c,
netdev_gperf_c,

View File

@ -4,7 +4,6 @@
#include "bridge.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-manager.h"
#include "string-table.h"
#include "vlan-util.h"
@ -342,6 +341,47 @@ int config_parse_bridge_igmp_version(
return 0;
}
int config_parse_bridge_port_priority(
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) {
uint16_t i;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
/* This is used in networkd-network-gperf.gperf. */
r = safe_atou16(rvalue, &i);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse bridge port priority, ignoring: %s", rvalue);
return 0;
}
if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Bridge port priority is larger than maximum %u, ignoring: %s",
LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue);
return 0;
}
*((uint16_t *)data) = i;
return 0;
}
static void bridge_init(NetDev *n) {
Bridge *b;

View File

@ -7,6 +7,9 @@
#include "conf-parser.h"
#include "netdev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
typedef struct Bridge {
NetDev meta;
@ -45,3 +48,4 @@ MulticastRouter multicast_router_from_string(const char *s) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_multicast_router);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_igmp_version);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);

View File

@ -12,7 +12,6 @@
#include "macsec.h"
#include "memory-util.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-manager.h"
#include "path-util.h"
#include "socket-util.h"

View File

@ -7,23 +7,23 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "bond.h"
#include "bridge.h"
#include "conf-parser.h"
#include "fou-tunnel.h"
#include "geneve.h"
#include "ipvlan.h"
#include "l2tp-tunnel.h"
#include "macsec.h"
#include "macvlan.h"
#include "net-condition.h"
#include "netdev.h"
#include "tunnel.h"
#include "tuntap.h"
#include "veth.h"
#include "vlan-util.h"
#include "vlan.h"
#include "vxlan.h"
#include "vrf.h"
#include "netdev.h"
#include "network-internal.h"
#include "vxcan.h"
#include "vxlan.h"
#include "wireguard.h"
#include "fou-tunnel.h"
#include "l2tp-tunnel.h"
#include "xfrm.h"
%}
struct ConfigPerfItem;

View File

@ -23,7 +23,6 @@
#include "netdev.h"
#include "netdevsim.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-manager.h"
#include "nlmon.h"
#include "path-lookup.h"

View File

@ -44,6 +44,7 @@
#include "main-func.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "network-util.h"
#include "pager.h"
#include "parse-util.h"
#include "pretty-print.h"
@ -704,7 +705,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
setup_state = strdup("unmanaged");
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
t = link_get_type_string(links[i].iftype, links[i].sd_device);
t = link_get_type_string(links[i].sd_device, links[i].iftype);
r = table_add_many(table,
TABLE_INT, links[i].ifindex,
@ -1428,7 +1429,7 @@ static int link_status_one(
(void) sd_device_get_property_value(info->sd_device, "ID_MODEL", &model);
}
t = link_get_type_string(info->iftype, info->sd_device);
t = link_get_type_string(info->sd_device, info->iftype);
(void) sd_network_link_get_network_file(info->ifindex, &network);

View File

@ -17,7 +17,7 @@
#include "networkd-manager.h"
#include "networkd-network.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "sysctl-util.h"
#include "web-util.h"

View File

@ -13,7 +13,6 @@
#include "hashmap.h"
#include "hostname-util.h"
#include "missing_network.h"
#include "network-internal.h"
#include "networkd-address.h"
#include "networkd-dhcp6.h"
#include "networkd-link.h"

View File

@ -45,11 +45,11 @@ const sd_bus_vtable network_vtable[] = {
SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match.mac), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match.path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match.driver), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match.iftype), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match.ifname), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
};

View File

@ -5,7 +5,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include <stddef.h>
#include "conf-parser.h"
#include "netem.h"
#include "network-internal.h"
#include "net-condition.h"
#include "networkd-address-label.h"
#include "networkd-address.h"
#include "networkd-can.h"
@ -41,16 +41,16 @@ struct ConfigPerfItem;
%struct-type
%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)
Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match_wlan_iftype)
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, IFNAME_VALID_ALTERNATIVE, offsetof(Network, match_name)
Match.Property, config_parse_match_property, 0, offsetof(Network, match_property)
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.iftype)
Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match.wifi_iftype)
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, IFNAME_VALID_ALTERNATIVE, offsetof(Network, match.ifname)
Match.Property, config_parse_match_property, 0, offsetof(Network, match.property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)

View File

@ -12,11 +12,11 @@
#include "fd-util.h"
#include "hostname-util.h"
#include "in-addr-util.h"
#include "networkd-dhcp-server.h"
#include "network-internal.h"
#include "net-condition.h"
#include "networkd-address-label.h"
#include "networkd-address.h"
#include "networkd-dhcp-common.h"
#include "networkd-dhcp-server.h"
#include "networkd-fdb.h"
#include "networkd-manager.h"
#include "networkd-mdb.h"
@ -161,11 +161,7 @@ int network_verify(Network *network) {
assert(network);
assert(network->filename);
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_wlan_iftype) &&
strv_isempty(network->match_ssid) && !network->conditions)
if (net_match_is_empty(&network->match) && !network->conditions)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: No valid settings found in the [Match] section, ignoring file. "
"To match all interfaces, add Name=* in the [Match] section.",
@ -589,16 +585,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);
strv_free(network->match_name);
strv_free(network->match_property);
strv_free(network->match_wlan_iftype);
strv_free(network->match_ssid);
set_free_free(network->match_bssid);
net_match_clear(&network->match);
condition_free_list(network->conditions);
free(network->description);
@ -705,13 +692,9 @@ int network_get(Manager *manager, unsigned short iftype, sd_device *device,
assert(ret);
ORDERED_HASHMAP_FOREACH(network, manager->networks)
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, mac, permanent_mac, driver, iftype,
if (net_match_config(&network->match, device, mac, permanent_mac, driver, iftype,
ifname, alternative_names, wlan_iftype, ssid, bssid)) {
if (network->match_name && device) {
if (network->match.ifname && device) {
const char *attr;
uint8_t name_assign_type = NET_NAME_UNKNOWN;

View File

@ -10,6 +10,7 @@
#include "condition.h"
#include "conf-parser.h"
#include "hashmap.h"
#include "net-condition.h"
#include "netdev.h"
#include "networkd-brvlan.h"
#include "networkd-dhcp-common.h"
@ -65,16 +66,7 @@ struct Network {
char *description;
/* [Match] section */
Set *match_mac;
Set *match_permanent_mac;
char **match_path;
char **match_driver;
char **match_type;
char **match_name;
char **match_property;
char **match_wlan_iftype;
char **match_ssid;
Set *match_bssid;
NetMatch match;
LIST_HEAD(Condition, conditions);
/* Master or stacked netdevs */

View File

@ -1,15 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "macro.h"
#include "set.h"
#include "string-util.h"
#include "network-internal.h"
#include "net-condition.h"
#include "networkd-conf.h"
#include "networkd-network.h"
#include "strv.h"
static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected, usec_t expected_time) {
DUID actual = {};
@ -174,7 +171,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign
assert_se(network = new0(Network, 1));
network->n_ref = 1;
assert_se(network->filename = strdup("hogehoge.network"));
assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match.ifname, network) == 0);
assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
assert_se(ordered_hashmap_size(network->addresses_by_section) == 1);
assert_se(network_verify(network) >= 0);

View File

@ -8,7 +8,6 @@
#include "link.h"
#include "manager.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "strv.h"
#include "time-util.h"
#include "util.h"

View File

@ -20,7 +20,6 @@
#include "io-util.h"
#include "missing_network.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "ordered-set.h"
#include "parse-util.h"
#include "random-util.h"

View File

@ -11,6 +11,7 @@
#include "conf-files.h"
#include "conf-parser.h"
#include "def.h"
#include "ether-addr-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
@ -24,6 +25,7 @@
#include "process-util.h"
#include "rlimit-util.h"
#include "sd-id128.h"
#include "set.h"
#include "signal-util.h"
#include "socket-util.h"
#include "string-util.h"
@ -251,15 +253,16 @@ static int parse_line(
}
/* Go through the file and parse each line */
int config_parse(const char *unit,
const char *filename,
FILE *f,
const char *sections,
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
void *userdata,
usec_t *ret_mtime) {
int config_parse(
const char *unit,
const char *filename,
FILE *f,
const char *sections,
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
void *userdata,
usec_t *ret_mtime) {
_cleanup_free_ char *section = NULL, *continuation = NULL;
_cleanup_fclose_ FILE *ours = NULL;
@ -522,16 +525,17 @@ DEFINE_PARSER(sec, usec_t, parse_sec);
DEFINE_PARSER(sec_def_infinity, usec_t, parse_sec_def_infinity);
DEFINE_PARSER(mode, mode_t, parse_mode);
int config_parse_iec_size(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_iec_size(
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) {
size_t *sz = data;
uint64_t v;
@ -608,16 +612,17 @@ int config_parse_iec_uint64(
return 0;
}
int config_parse_bool(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_bool(
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 k;
bool *b = data;
@ -1181,16 +1186,17 @@ int config_parse_rlimit(
return 0;
}
int config_parse_permille(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_permille(
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) {
unsigned *permille = data;
int r;
@ -1212,17 +1218,20 @@ int config_parse_permille(const char* unit,
return 0;
}
int config_parse_vlanprotocol(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_vlanprotocol(
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 *vlan_protocol = data;
assert(filename);
assert(lvalue);
@ -1244,4 +1253,106 @@ int config_parse_vlanprotocol(const char* unit,
return 0;
}
int config_parse_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) {
_cleanup_free_ struct ether_addr *n = NULL;
struct ether_addr **hwaddr = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*hwaddr = mfree(*hwaddr);
return 0;
}
n = new0(struct ether_addr, 1);
if (!n)
return log_oom();
r = ether_addr_from_string(rvalue, n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Not a valid MAC address, ignoring assignment: %s", rvalue);
return 0;
}
free_and_replace(*hwaddr, n);
return 0;
}
int config_parse_hwaddrs(
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) {
Set **hwaddrs = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
*hwaddrs = set_free_free(*hwaddrs);
return 0;
}
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL;
_cleanup_free_ struct ether_addr *n = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
n = new(struct ether_addr, 1);
if (!n)
return log_oom();
r = ether_addr_from_string(word, n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Not a valid MAC address, ignoring: %s", word);
continue;
}
r = set_ensure_put(hwaddrs, &ether_addr_hash_ops, n);
if (r < 0)
return log_oom();
if (r > 0)
TAKE_PTR(n); /* avoid cleanup */
}
}
DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value");

View File

@ -147,6 +147,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
CONFIG_PARSER_PROTOTYPE(config_parse_vlanprotocol);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
typedef enum Disabled {

View File

@ -169,6 +169,8 @@ shared_sources = files('''
module-util.h
mount-util.c
mount-util.h
net-condition.c
net-condition.h
netif-naming-scheme.c
netif-naming-scheme.h
nscd-flush.c

428
src/shared/net-condition.c Normal file
View File

@ -0,0 +1,428 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <netinet/ether.h>
#include "condition.h"
#include "env-util.h"
#include "log.h"
#include "net-condition.h"
#include "network-util.h"
#include "socket-util.h"
#include "string-table.h"
#include "strv.h"
void net_match_clear(NetMatch *match) {
if (!match)
return;
match->mac = set_free_free(match->mac);
match->permanent_mac = set_free_free(match->permanent_mac);
match->path = strv_free(match->path);
match->driver = strv_free(match->driver);
match->iftype = strv_free(match->iftype);
match->ifname = strv_free(match->ifname);
match->property = strv_free(match->property);
match->wifi_iftype = strv_free(match->wifi_iftype);
match->ssid = strv_free(match->ssid);
match->bssid = set_free_free(match->bssid);
}
bool net_match_is_empty(const NetMatch *match) {
assert(match);
return
set_isempty(match->mac) &&
set_isempty(match->permanent_mac) &&
strv_isempty(match->path) &&
strv_isempty(match->driver) &&
strv_isempty(match->iftype) &&
strv_isempty(match->ifname) &&
strv_isempty(match->property) &&
strv_isempty(match->wifi_iftype) &&
strv_isempty(match->ssid) &&
set_isempty(match->bssid);
}
static bool net_condition_test_strv(char * const *patterns, const char *string) {
char * const *p;
bool match = false, has_positive_rule = false;
if (strv_isempty(patterns))
return true;
STRV_FOREACH(p, patterns) {
const char *q = *p;
bool invert;
invert = *q == '!';
q += invert;
if (!invert)
has_positive_rule = true;
if (string && fnmatch(q, string, 0) == 0) {
if (invert)
return false;
else
match = true;
}
}
return has_positive_rule ? match : true;
}
static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
if (net_condition_test_strv(patterns, ifname))
return true;
char * const *p;
STRV_FOREACH(p, alternative_names)
if (net_condition_test_strv(patterns, *p))
return true;
return false;
}
static int net_condition_test_property(char * const *match_property, sd_device *device) {
char * const *p;
if (strv_isempty(match_property))
return true;
STRV_FOREACH(p, match_property) {
_cleanup_free_ char *key = NULL;
const char *val, *dev_val;
bool invert, v;
invert = **p == '!';
val = strchr(*p + invert, '=');
if (!val)
return -EINVAL;
key = strndup(*p + invert, val - *p - invert);
if (!key)
return -ENOMEM;
val++;
v = device &&
sd_device_get_property_value(device, key, &dev_val) >= 0 &&
fnmatch(val, dev_val, 0) == 0;
if (invert ? v : !v)
return false;
}
return true;
}
static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = {
[NL80211_IFTYPE_ADHOC] = "ad-hoc",
[NL80211_IFTYPE_STATION] = "station",
[NL80211_IFTYPE_AP] = "ap",
[NL80211_IFTYPE_AP_VLAN] = "ap-vlan",
[NL80211_IFTYPE_WDS] = "wds",
[NL80211_IFTYPE_MONITOR] = "monitor",
[NL80211_IFTYPE_MESH_POINT] = "mesh-point",
[NL80211_IFTYPE_P2P_CLIENT] = "p2p-client",
[NL80211_IFTYPE_P2P_GO] = "p2p-go",
[NL80211_IFTYPE_P2P_DEVICE] = "p2p-device",
[NL80211_IFTYPE_OCB] = "ocb",
[NL80211_IFTYPE_NAN] = "nan",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype);
bool net_match_config(
const NetMatch *match,
sd_device *device,
const struct ether_addr *mac,
const struct ether_addr *permanent_mac,
const char *driver,
unsigned short iftype,
const char *ifname,
char * const *alternative_names,
enum nl80211_iftype wifi_iftype,
const char *ssid,
const struct ether_addr *bssid) {
_cleanup_free_ char *iftype_str;
const char *path = NULL;
assert(match);
iftype_str = link_get_type_string(device, iftype);
if (device) {
const char *mac_str;
(void) sd_device_get_property_value(device, "ID_PATH", &path);
if (!driver)
(void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
if (!ifname)
(void) sd_device_get_sysname(device, &ifname);
if (!mac &&
sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
mac = ether_aton(mac_str);
}
if (match->mac && (!mac || !set_contains(match->mac, mac)))
return false;
if (match->permanent_mac &&
(!permanent_mac ||
ether_addr_is_null(permanent_mac) ||
!set_contains(match->permanent_mac, permanent_mac)))
return false;
if (!net_condition_test_strv(match->path, path))
return false;
if (!net_condition_test_strv(match->driver, driver))
return false;
if (!net_condition_test_strv(match->iftype, iftype_str))
return false;
if (!net_condition_test_ifname(match->ifname, ifname, alternative_names))
return false;
if (!net_condition_test_property(match->property, device))
return false;
if (!net_condition_test_strv(match->wifi_iftype, wifi_iftype_to_string(wifi_iftype)))
return false;
if (!net_condition_test_strv(match->ssid, ssid))
return false;
if (match->bssid && (!bssid || !set_contains(match->bssid, bssid)))
return false;
return true;
}
int config_parse_net_condition(
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) {
ConditionType cond = ltype;
Condition **list = data, *c;
bool negate;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*list = condition_free_list_type(*list, cond);
return 0;
}
negate = rvalue[0] == '!';
if (negate)
rvalue++;
c = condition_new(cond, rvalue, false, negate);
if (!c)
return log_oom();
/* Drop previous assignment. */
*list = condition_free_list_type(*list, cond);
LIST_PREPEND(conditions, *list, c);
return 0;
}
int config_parse_match_strv(
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) {
const char *p = rvalue;
char ***sv = data;
bool invert;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*sv = strv_free(*sv);
return 0;
}
invert = *p == '!';
p += invert;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (invert) {
k = strjoin("!", word);
if (!k)
return log_oom();
} else
k = TAKE_PTR(word);
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
}
int config_parse_match_ifnames(
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) {
const char *p = rvalue;
char ***sv = data;
bool invert;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*sv = strv_free(*sv);
return 0;
}
invert = *p == '!';
p += invert;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to parse interface name list, ignoring: %s", rvalue);
return 0;
}
if (!ifname_valid_full(word, ltype)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Interface name is not valid or too long, ignoring assignment: %s", word);
continue;
}
if (invert) {
k = strjoin("!", word);
if (!k)
return log_oom();
} else
k = TAKE_PTR(word);
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
}
int config_parse_match_property(
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) {
const char *p = rvalue;
char ***sv = data;
bool invert;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*sv = strv_free(*sv);
return 0;
}
invert = *p == '!';
p += invert;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (!env_assignment_is_valid(word)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid property or value, ignoring assignment: %s", word);
continue;
}
if (invert) {
k = strjoin("!", word);
if (!k)
return log_oom();
} else
k = TAKE_PTR(word);
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
}

View File

@ -0,0 +1,45 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <linux/nl80211.h>
#include <stdbool.h>
#include "sd-device.h"
#include "conf-parser.h"
#include "ether-addr-util.h"
#include "set.h"
typedef struct NetMatch {
Set *mac;
Set *permanent_mac;
char **path;
char **driver;
char **iftype;
char **ifname;
char **property;
char **wifi_iftype;
char **ssid;
Set *bssid;
} NetMatch;
void net_match_clear(NetMatch *match);
bool net_match_is_empty(const NetMatch *match);
bool net_match_config(
const NetMatch *match,
sd_device *device,
const struct ether_addr *mac,
const struct ether_addr *permanent_mac,
const char *driver,
unsigned short iftype,
const char *ifname,
char * const *alternative_names,
enum nl80211_iftype wifi_iftype,
const char *ssid,
const struct ether_addr *bssid);
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_match_property);

View File

@ -126,8 +126,7 @@ tests += [
[['src/test/test-dns-domain.c'],
[libcore,
libshared,
libsystemd_network],
libshared],
[]],
[['src/test/test-boot-timestamps.c'],
@ -530,7 +529,6 @@ tests += [
libjournal_core,
libudev_core,
libudev_static,
libsystemd_network,
libshared],
[threads,
libseccomp,
@ -766,7 +764,6 @@ tests += [
[['src/test/test-udev.c'],
[libudev_core,
libudev_static,
libsystemd_network,
libshared],
[threads,
librt,

View File

@ -206,7 +206,6 @@ fuzzers += [
'src/fuzz/fuzz.h'],
[libudev_core,
libudev_static,
libsystemd_network,
libshared],
[threads,
libacl]],

View File

@ -6,7 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "conf-parser.h"
#include "ethtool-util.h"
#include "link-config.h"
#include "network-internal.h"
#include "net-condition.h"
#include "socket-util.h"
%}
struct ConfigPerfItem;
@ -20,13 +20,13 @@ struct ConfigPerfItem;
%struct-type
%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)
Match.Type, config_parse_match_strv, 0, offsetof(link_config, match_type)
Match.Property, config_parse_match_property, 0, offsetof(link_config, match_property)
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.ifname)
Match.Path, config_parse_match_strv, 0, offsetof(link_config, match.path)
Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match.driver)
Match.Type, config_parse_match_strv, 0, offsetof(link_config, match.iftype)
Match.Property, config_parse_match_property, 0, offsetof(link_config, match.property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)

View File

@ -18,9 +18,10 @@
#include "link-config.h"
#include "log.h"
#include "memory-util.h"
#include "net-condition.h"
#include "netif-naming-scheme.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "network-util.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
@ -30,6 +31,7 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
struct link_config_ctx {
LIST_HEAD(link_config, links);
@ -49,13 +51,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);
strv_free(link->match_name);
strv_free(link->match_property);
net_match_clear(&link->match);
condition_free_list(link->conditions);
free(link->description);
@ -167,9 +163,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
if (r < 0)
return r;
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) {
if (net_match_is_empty(&link->match) && !link->conditions) {
log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
"To match all interfaces, add OriginalName=* in the [Match] section.",
filename);
@ -279,11 +273,8 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
(void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
LIST_FOREACH(links, link, ctx->links) {
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, &permanent_mac, NULL, iftype, NULL, NULL, 0, NULL, NULL)) {
if (link->match_name && !strv_contains(link->match_name, "*") && name_assign_type == NET_NAME_ENUM)
if (net_match_config(&link->match, device, NULL, &permanent_mac, NULL, iftype, NULL, NULL, 0, NULL, NULL)) {
if (link->match.ifname && !strv_contains(link->match.ifname, "*") && name_assign_type == NET_NAME_ENUM)
log_device_warning(device, "Config file %s is applied to device based on potentially unpredictable interface name.",
link->filename);
else
@ -668,6 +659,48 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
return 0;
}
int config_parse_ifalias(
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) {
char **s = data;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (!isempty(rvalue)) {
*s = mfree(*s);
return 0;
}
if (!ascii_is_valid(rvalue)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Interface alias is not ASCII clean, ignoring assignment: %s", rvalue);
return 0;
}
if (strlen(rvalue) >= IFALIASZ) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Interface alias is too long, ignoring assignment: %s", rvalue);
return 0;
}
if (free_and_strdup(s, rvalue) < 0)
return log_oom();
return 0;
}
static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
[MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
[MAC_ADDRESS_POLICY_RANDOM] = "random",

View File

@ -7,7 +7,7 @@
#include "conf-parser.h"
#include "ethtool-util.h"
#include "list.h"
#include "set.h"
#include "net-condition.h"
typedef struct link_config_ctx link_config_ctx;
typedef struct link_config link_config;
@ -35,13 +35,7 @@ typedef enum NamePolicy {
struct link_config {
char *filename;
Set *match_mac;
Set *match_permanent_mac;
char **match_path;
char **match_driver;
char **match_type;
char **match_name;
char **match_property;
NetMatch match;
LIST_HEAD(Condition, conditions);
char *description;
@ -93,6 +87,7 @@ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
/* gperf lookup function */
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_alternative_names_policy);