1
0
mirror of https://github.com/systemd/systemd synced 2026-04-03 21:54:58 +02:00

Compare commits

...

22 Commits

Author SHA1 Message Date
Yu Watanabe
5ff3c71af8
Merge pull request #21276 from yuwata/ether-addr-util
ether-addr-util: introduce parse_hw_addr() and related conf parsers
2021-11-10 09:22:01 +09:00
Yu Watanabe
3f6a18633f
Merge pull request #21281 from poettering/repart-align-fixes
repart: fixes when operating on unaligned partitions
2021-11-10 09:21:24 +09:00
Lennart Poettering
4a77b47ed8
Merge pull request #21283 from poettering/nspawn-idempotent-empty-settings
nspawn: make empty settings files true NOPs
2021-11-09 22:20:22 +01:00
Albert Brox
437346c96b analyze: basename -> path_extract_filename and other minor fixes 2021-11-09 22:19:34 +01:00
Lennart Poettering
9baa294c12 nspawn: don't muck with caps if no network setting is used in settings file
Our goal here (as in the previous commits) is to ensure that a settings
file loaded in --settings=override mode is truly a NOP. Previously this
was not the case as we'd drop CAP_NET_ADMIN from the caps if the
settings file didn't enable networking.

With this change we'll drop it only if explicitly turned off in the
settings file, and otherwise let the built-in defaults and cmdline
params reign supreme as documented.

Fixes: #20055
2021-11-09 18:32:30 +01:00
Lennart Poettering
2d09ea44fc nspawn: only copy syscall filters from settings if actually configured
As in the previous commit, let's not copy settings that aren#t
configured, so that --settings=override with an empty .nspawn file is
truly a NOP.
2021-11-09 18:32:25 +01:00
Lennart Poettering
0cc3c9f997 nspawn: copy BindUser= setting from settings only if set
Let's only pick this up from the settings if actually set.

As in the previous commit this makes sure that an empty settings file in
--settings=override mode is really a NOP.
2021-11-09 18:32:20 +01:00
Lennart Poettering
d3689b9435 nspawn: use three boolean fields from settings file when actually set
Let's turn these three fields into tristates, so that we can distinguish
whether they are not configured at all from explicitly turned off.

Let#s then use this to ensure that we only copy the settings fields into
our execution environment if they are actually configured.

We already do this for some of the boolean settings, this adds it for
the missing ones.

The goal here is to ensure that an empty settings file used in
--settings=override mode (i.e. the default mode used in the
systemd-nspawn@.service unit) is truly a NOP.
2021-11-09 18:32:15 +01:00
Lennart Poettering
a1dfd585c4 nspawn: add helper settings_network_configured()
The new helper returns whether the settings file had *any* networking
setting configured at all. We already have a similar helper
settings_private_network() which returns a similar result. The
difference is that the new helper will return true when the private
network was explicitly turned off, while the old one will only return
true if configured and enabled.

We'll reuse the helper a 2nd time later on, but even without it it makes
things a bit more readable.
2021-11-09 18:32:10 +01:00
Lennart Poettering
8c1e088ac9 nspawn: drop two entirely redundant lines 2021-11-09 18:31:24 +01:00
Lennart Poettering
15c5977644 test: extend repart test suite to test for unaligned partitions 2021-11-09 16:53:11 +01:00
Lennart Poettering
1052a1142d repart: fix free area calculations for unaligned partitions
To properly detect how much space we have to distribute we need to take
into account that both the partition offset and the partition size
aren't aligned.
2021-11-09 16:31:48 +01:00
Lennart Poettering
0b7f574f72 repart: don't distribute space after unaligned partitions
If we operate on a disk that has a pre-existing unaligned partition
(i.e. one that doesn't start on multiple of 4K, or doesn't have a size
of multiple 4K), then the amount of space after it to distribute among
partitions isn't a multiple of 4K either.  So far we might end up
passing the remaining fraction to any partition that wanted it, which
was usually the first one after it that is newly defined. This then
confused the later placement algorithm, since it assumed all partitions
we newly allocate were properly aligned but by being extended by the
fractional space they wouldn't be anymore.

Let's hence fix that by ensuring we never pass space to later partitions
so that things wouldn't be aligned anymore.

Anything that is left-over then at the very end (i.e. typically exactly
the remaining fraction) is added as padding to the existing, unaligned
partition, so that it can't confuse anyone.

Fixes: #20622
2021-11-09 16:25:24 +01:00
Lennart Poettering
ae0613c6c4 repart: simplify stat machine we mostly go through linearly 2021-11-09 16:25:00 +01:00
Lennart Poettering
184cf99a35 repart: use LESS_BY() more 2021-11-09 16:24:22 +01:00
Yu Watanabe
99628f363b conf-parser: introduce config_parse_hw_addr() and config_parse_hw_addrs() 2021-11-09 21:39:09 +09:00
Yu Watanabe
c6df73ca72 ether-addr-util: introduce {hw,ether}_addr_hash_ops_free 2021-11-09 21:39:09 +09:00
Yu Watanabe
aa4f765326 conf-parser: rename config_parse_hwaddr() -> config_parse_ether_addr() 2021-11-09 21:39:09 +09:00
Yu Watanabe
227e9ce255 ether-addr-util: replace ether_addr_from_string() with parse_ether_addr() 2021-11-09 21:39:09 +09:00
Yu Watanabe
02160bc909 ether-addr-util: introduce parse_ether_addr() 2021-11-09 21:39:09 +09:00
Yu Watanabe
fb4e524180 test: add tests for parse_hw_addr() 2021-11-09 21:39:09 +09:00
Yu Watanabe
76a5d3dee2 ether-addr-util: introduce parse_hw_addr() 2021-11-09 21:39:05 +09:00
26 changed files with 576 additions and 235 deletions

View File

@ -243,27 +243,27 @@ static int process_aliases(char *argv[], char *tempdir, char ***ret) {
assert(ret);
STRV_FOREACH(filename, strv_skip(argv, 1)) {
_cleanup_free_ char *src = NULL, *dst = NULL, *arg = NULL;
char *parse_arg;
_cleanup_free_ char *src = NULL, *dst = NULL, *base = NULL;
const char *parse_arg;
arg = strdup(*filename);
if (!arg)
return -ENOMEM;
parse_arg = arg;
r = extract_first_word((const char **) &parse_arg, &src, ":", 0);
parse_arg = *filename;
r = extract_first_word(&parse_arg, &src, ":", EXTRACT_DONT_COALESCE_SEPARATORS|EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
if (!parse_arg) {
r = strv_extend(&filenames, src);
r = strv_consume(&filenames, TAKE_PTR(src));
if (r < 0)
return -ENOMEM;
return r;
continue;
}
dst = path_join(tempdir, basename(parse_arg));
r = path_extract_filename(parse_arg, &base);
if (r < 0)
return r;
dst = path_join(tempdir, base);
if (!dst)
return -ENOMEM;
@ -273,7 +273,7 @@ static int process_aliases(char *argv[], char *tempdir, char ***ret) {
r = strv_consume(&filenames, TAKE_PTR(dst));
if (r < 0)
return -ENOMEM;
return r;
}
*ret = TAKE_PTR(filenames);

View File

@ -48,6 +48,7 @@ static void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *stat
}
DEFINE_HASH_OPS(hw_addr_hash_ops, struct hw_addr_data, hw_addr_hash_func, hw_addr_compare);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(hw_addr_hash_ops_free, struct hw_addr_data, hw_addr_hash_func, hw_addr_compare, free);
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
assert(addr);
@ -93,75 +94,163 @@ static void ether_addr_hash_func(const struct ether_addr *p, struct siphash *sta
}
DEFINE_HASH_OPS(ether_addr_hash_ops, struct ether_addr, ether_addr_hash_func, ether_addr_compare);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(ether_addr_hash_ops_free, struct ether_addr, ether_addr_hash_func, ether_addr_compare, free);
int ether_addr_from_string(const char *s, struct ether_addr *ret) {
size_t pos = 0, n, field;
char sep = '\0';
const char *hex = HEXDIGITS, *hexoff;
size_t x;
bool touched;
static int parse_hw_addr_one_field(const char **s, char sep, size_t len, uint8_t *buf) {
const char *hex = HEXDIGITS, *p;
uint16_t data = 0;
bool cont;
#define parse_fields(v) \
for (field = 0; field < ELEMENTSOF(v); field++) { \
touched = false; \
for (n = 0; n < (2 * sizeof(v[0])); n++) { \
if (s[pos] == '\0') \
break; \
hexoff = strchr(hex, s[pos]); \
if (!hexoff) \
break; \
assert(hexoff >= hex); \
x = hexoff - hex; \
if (x >= 16) \
x -= 6; /* A-F */ \
assert(x < 16); \
touched = true; \
v[field] <<= 4; \
v[field] += x; \
pos++; \
} \
if (!touched) \
return -EINVAL; \
if (field < (ELEMENTSOF(v)-1)) { \
if (s[pos] != sep) \
return -EINVAL; \
else \
pos++; \
} \
assert(s);
assert(*s);
assert(IN_SET(len, 1, 2));
assert(buf);
p = *s;
for (size_t i = 0; i < len * 2; i++) {
const char *hexoff;
size_t x;
if (*p == '\0' || *p == sep) {
if (i == 0)
return -EINVAL;
break;
}
hexoff = strchr(hex, *p);
if (!hexoff)
return -EINVAL;
assert(hexoff >= hex);
x = hexoff - hex;
if (x >= 16)
x -= 6; /* A-F */
assert(x < 16);
data <<= 4;
data += x;
p++;
}
if (*p != '\0' && *p != sep)
return -EINVAL;
switch (len) {
case 1:
buf[0] = data;
break;
case 2:
buf[0] = (data & 0xff00) >> 8;
buf[1] = data & 0xff;
break;
default:
assert_not_reached();
}
cont = *p == sep;
*s = p + cont;
return cont;
}
int parse_hw_addr_full(const char *s, size_t expected_len, struct hw_addr_data *ret) {
size_t field_size, max_len, len = 0;
uint8_t bytes[HW_ADDR_MAX_SIZE];
char sep;
int r;
assert(s);
assert(expected_len <= HW_ADDR_MAX_SIZE || expected_len == SIZE_MAX);
assert(ret);
/* This accepts the following formats:
*
* Dot separated 2 bytes format: xxyy.zzaa.bbcc
* Colon separated 1 bytes format: xx:yy:zz:aa:bb:cc
* Hyphen separated 1 bytes format: xx-yy-zz-aa-bb-cc
*
* Moreover, if expected_len == 0, 4, or 16, this also accepts:
*
* IPv4 format: used by IPv4 tunnel, e.g. ipgre
* IPv6 format: used by IPv6 tunnel, e.g. ip6gre
*
* The expected_len argument controls the length of acceptable addresses:
*
* 0: accepts 4 (AF_INET), 16 (AF_INET6), 6 (ETH_ALEN), or 20 (INFINIBAND_ALEN).
* SIZE_MAX: accepts arbitrary length, but at least one separator must be included.
* Otherwise: accepts addresses with matching length.
*/
if (IN_SET(expected_len, 0, sizeof(struct in_addr), sizeof(struct in6_addr))) {
union in_addr_union a;
int family;
if (expected_len == 0)
r = in_addr_from_string_auto(s, &family, &a);
else {
family = expected_len == sizeof(struct in_addr) ? AF_INET : AF_INET6;
r = in_addr_from_string(family, s, &a);
}
if (r >= 0) {
ret->length = FAMILY_ADDRESS_SIZE(family);
memcpy(ret->bytes, a.bytes, ret->length);
return 0;
}
}
max_len =
expected_len == 0 ? INFINIBAND_ALEN :
expected_len == SIZE_MAX ? HW_ADDR_MAX_SIZE : expected_len;
sep = s[strspn(s, HEXDIGITS)];
if (sep == '.')
field_size = 2;
else if (IN_SET(sep, ':', '-'))
field_size = 1;
else
return -EINVAL;
if (max_len % field_size != 0)
return -EINVAL;
for (size_t i = 0; i < max_len / field_size; i++) {
r = parse_hw_addr_one_field(&s, sep, field_size, bytes + i * field_size);
if (r < 0)
return r;
if (r == 0) {
len = (i + 1) * field_size;
break;
}
}
if (len == 0)
return -EINVAL;
if (expected_len == 0) {
if (!IN_SET(len, 4, 16, ETH_ALEN, INFINIBAND_ALEN))
return -EINVAL;
} else if (expected_len != SIZE_MAX) {
if (len != expected_len)
return -EINVAL;
}
ret->length = len;
memcpy(ret->bytes, bytes, ret->length);
return 0;
}
int parse_ether_addr(const char *s, struct ether_addr *ret) {
struct hw_addr_data a;
int r;
assert(s);
assert(ret);
s += strspn(s, WHITESPACE);
sep = s[strspn(s, hex)];
if (sep == '.') {
uint16_t shorts[3] = { 0 };
parse_fields(shorts);
if (s[pos] != '\0')
return -EINVAL;
for (n = 0; n < ELEMENTSOF(shorts); n++) {
ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
}
} else if (IN_SET(sep, ':', '-')) {
struct ether_addr out = ETHER_ADDR_NULL;
parse_fields(out.ether_addr_octet);
if (s[pos] != '\0')
return -EINVAL;
for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
ret->ether_addr_octet[n] = out.ether_addr_octet[n];
} else
return -EINVAL;
r = parse_hw_addr_full(s, ETH_ALEN, &a);
if (r < 0)
return r;
*ret = a.ether;
return 0;
}

View File

@ -6,6 +6,7 @@
#include <stdbool.h>
#include "hash-funcs.h"
#include "in-addr-util.h"
#include "macro.h"
#include "memory-util.h"
@ -18,10 +19,18 @@ struct hw_addr_data {
union {
struct ether_addr ether;
uint8_t infiniband[INFINIBAND_ALEN];
struct in_addr in;
struct in6_addr in6;
uint8_t bytes[HW_ADDR_MAX_SIZE];
};
};
int parse_hw_addr_full(const char *s, size_t expected_len, struct hw_addr_data *ret);
static inline int parse_hw_addr(const char *s, struct hw_addr_data *ret) {
return parse_hw_addr_full(s, 0, ret);
}
int parse_ether_addr(const char *s, struct ether_addr *ret);
#define HW_ADDR_TO_STRING_MAX (3*HW_ADDR_MAX_SIZE)
char* hw_addr_to_string(const struct hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]);
@ -42,6 +51,7 @@ static inline bool hw_addr_is_null(const struct hw_addr_data *addr) {
}
extern const struct hash_ops hw_addr_hash_ops;
extern const struct hash_ops hw_addr_hash_ops_free;
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
@ -83,6 +93,5 @@ static inline bool ether_addr_is_local(const struct ether_addr *addr) {
return !FLAGS_SET(addr->ether_addr_octet[0], 0x02);
}
int ether_addr_from_string(const char *s, struct ether_addr *ret);
extern const struct hash_ops ether_addr_hash_ops;
extern const struct hash_ops ether_addr_hash_ops_free;

View File

@ -353,7 +353,7 @@ static int network_set_mac_address(Context *context, const char *ifname, const c
if (!network)
return -ENODEV;
return ether_addr_from_string(mac, &network->mac);
return parse_ether_addr(mac, &network->mac);
}
static int network_set_address(Context *context, const char *ifname, int family, unsigned char prefixlen,
@ -909,7 +909,7 @@ static int parse_cmdline_ifname(Context *context, const char *key, const char *v
name = strndupa_safe(value, p - value);
r = ether_addr_from_string(p + 1, &mac);
r = parse_ether_addr(p + 1, &mac);
if (r < 0)
return r;

View File

@ -386,7 +386,7 @@ int config_parse_ad_actor_system(
assert(rvalue);
assert(data);
r = ether_addr_from_string(rvalue, &n);
r = parse_ether_addr(rvalue, &n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Not a valid MAC address %s. Ignoring assignment: %m",

View File

@ -620,7 +620,7 @@ int config_parse_macsec_hw_address(
if (r < 0)
return log_oom();
r = ether_addr_from_string(rvalue, b ? &b->sci.mac : &c->sci.mac);
r = parse_ether_addr(rvalue, b ? &b->sci.mac : &c->sci.mac);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse MAC address for secure channel identifier. "

View File

@ -127,7 +127,7 @@ static void macvlan_done(NetDev *n) {
assert(m);
set_free_free(m->match_source_mac);
set_free(m->match_source_mac);
}
static void macvlan_init(NetDev *n) {

View File

@ -49,7 +49,7 @@ NetDev.Description, config_parse_string,
NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname)
NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind)
NetDev.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(NetDev, mtu)
NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac)
NetDev.MACAddress, config_parse_ether_addr, 0, offsetof(NetDev, mac)
VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id)
VLAN.Protocol, config_parse_vlanprotocol, 0, offsetof(VLan, protocol)
VLAN.GVRP, config_parse_tristate, 0, offsetof(VLan, gvrp)
@ -59,10 +59,10 @@ VLAN.ReorderHeader, config_parse_tristate,
VLAN.EgressQOSMaps, config_parse_vlan_qos_maps, 0, offsetof(VLan, egress_qos_maps)
VLAN.IngressQOSMaps, config_parse_vlan_qos_maps, 0, offsetof(VLan, ingress_qos_maps)
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
MACVLAN.SourceMACAddress, config_parse_hwaddrs, 0, offsetof(MacVlan, match_source_mac)
MACVLAN.SourceMACAddress, config_parse_ether_addrs, 0, offsetof(MacVlan, match_source_mac)
MACVLAN.BroadcastMulticastQueueLength, config_parse_macvlan_broadcast_queue_size, 0, offsetof(MacVlan, bc_queue_length)
MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
MACVTAP.SourceMACAddress, config_parse_hwaddrs, 0, offsetof(MacVlan, match_source_mac)
MACVTAP.SourceMACAddress, config_parse_ether_addrs, 0, offsetof(MacVlan, match_source_mac)
IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
@ -111,7 +111,7 @@ L2TPSession.PeerSessionId, config_parse_l2tp_session_id,
L2TPSession.Layer2SpecificHeader, config_parse_l2tp_session_l2spec, 0, 0
L2TPSession.Name, config_parse_l2tp_session_name, 0, 0
Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer)
Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer)
Peer.MACAddress, config_parse_ether_addr, 0, offsetof(Veth, mac_peer)
VXCAN.Peer, config_parse_ifname, 0, offsetof(VxCan, ifname_peer)
VXLAN.VNI, config_parse_uint32, 0, offsetof(VxLan, vni)
VXLAN.Id, config_parse_uint32, 0, offsetof(VxLan, vni) /* deprecated */

View File

@ -286,7 +286,7 @@ int config_parse_fdb_hwaddr(
if (r < 0)
return log_oom();
r = ether_addr_from_string(rvalue, &fdb->mac_addr);
r = parse_ether_addr(rvalue, &fdb->mac_addr);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
return 0;

View File

@ -184,7 +184,7 @@ int config_parse_dhcp_static_lease_hwaddr(
return 0;
}
r = ether_addr_from_string(rvalue, &hwaddr);
r = parse_ether_addr(rvalue, &hwaddr);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse MAC address for DHCPv4 static lease, ignoring assignment: %s", rvalue);

View File

@ -680,7 +680,7 @@ int config_parse_neighbor_lladdr(
if (r < 0)
return log_oom();
r = ether_addr_from_string(rvalue, &n->lladdr.mac);
r = parse_ether_addr(rvalue, &n->lladdr.mac);
if (r >= 0)
n->lladdr_size = sizeof(n->lladdr.mac);
else {
@ -725,7 +725,7 @@ int config_parse_neighbor_hwaddr(
if (r < 0)
return log_oom();
r = ether_addr_from_string(rvalue, &n->lladdr.mac);
r = parse_ether_addr(rvalue, &n->lladdr.mac);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Neighbor MACAddress= is invalid, ignoring assignment: %s", rvalue);

View File

@ -45,14 +45,14 @@ 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.MACAddress, config_parse_ether_addrs, 0, offsetof(Network, match.mac)
Match.PermanentMACAddress, config_parse_ether_addrs, 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.wlan_iftype)
Match.SSID, config_parse_match_strv, 0, offsetof(Network, match.ssid)
Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match.bssid)
Match.BSSID, config_parse_ether_addrs, 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)
@ -61,7 +61,7 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, conditions)
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, conditions)
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(Network, conditions)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MACAddress, config_parse_ether_addr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu)
Link.Group, config_parse_link_group, 0, 0
Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)

View File

@ -523,7 +523,7 @@ int config_parse_sr_iov_mac(
return 0;
}
r = ether_addr_from_string(rvalue, &sr_iov->mac);
r = parse_ether_addr(rvalue, &sr_iov->mac);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);

View File

@ -51,11 +51,11 @@ static void test_config_parse_duid_rawdata_one(const char *rvalue, int ret, cons
}
}
static void test_config_parse_hwaddr_one(const char *rvalue, int ret, const struct ether_addr* expected) {
static void test_config_parse_ether_addr_one(const char *rvalue, int ret, const struct ether_addr* expected) {
struct ether_addr *actual = NULL;
int r;
r = config_parse_hwaddr("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL);
r = config_parse_ether_addr("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL);
assert_se(ret == r);
if (expected) {
assert_se(actual);
@ -66,10 +66,10 @@ static void test_config_parse_hwaddr_one(const char *rvalue, int ret, const stru
free(actual);
}
static void test_config_parse_hwaddrs_one(const char *rvalue, const struct ether_addr* list, size_t n) {
static void test_config_parse_ether_addrs_one(const char *rvalue, const struct ether_addr* list, size_t n) {
_cleanup_set_free_free_ Set *s = NULL;
assert_se(config_parse_hwaddrs("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &s, NULL) == 0);
assert_se(config_parse_ether_addrs("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &s, NULL) == 0);
assert_se(set_size(s) == n);
for (size_t m = 0; m < n; m++) {
@ -101,68 +101,68 @@ static void test_config_parse_duid_rawdata(void) {
test_config_parse_duid_rawdata_one(&BYTES_0_128[2], 0, &(DUID){0, 128, BYTES_1_128});
}
static void test_config_parse_hwaddr(void) {
static void test_config_parse_ether_addr(void) {
const struct ether_addr t[] = {
{ .ether_addr_octet = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } },
{ .ether_addr_octet = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } },
};
test_config_parse_hwaddr_one("", 0, NULL);
test_config_parse_hwaddr_one("no:ta:ma:ca:dd:re", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:fx", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff", 0, &t[0]);
test_config_parse_hwaddr_one(" aa:bb:cc:dd:ee:ff", 0, &t[0]);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\nxxx", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc: dd:ee:ff", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:d d:ee:ff", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee", 0, NULL);
test_config_parse_hwaddr_one("9:aa:bb:cc:dd:ee:ff", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff:gg", 0, NULL);
test_config_parse_hwaddr_one("aa:Bb:CC:dd:ee:ff", 0, &t[0]);
test_config_parse_hwaddr_one("01:23:45:67:89:aB", 0, &t[1]);
test_config_parse_hwaddr_one("1:23:45:67:89:aB", 0, &t[1]);
test_config_parse_hwaddr_one("aa-bb-cc-dd-ee-ff", 0, &t[0]);
test_config_parse_hwaddr_one("AA-BB-CC-DD-EE-FF", 0, &t[0]);
test_config_parse_hwaddr_one("01-23-45-67-89-ab", 0, &t[1]);
test_config_parse_hwaddr_one("aabb.ccdd.eeff", 0, &t[0]);
test_config_parse_hwaddr_one("0123.4567.89ab", 0, &t[1]);
test_config_parse_hwaddr_one("123.4567.89ab.", 0, NULL);
test_config_parse_hwaddr_one("aabbcc.ddeeff", 0, NULL);
test_config_parse_hwaddr_one("aabbccddeeff", 0, NULL);
test_config_parse_hwaddr_one("aabbccddee:ff", 0, NULL);
test_config_parse_hwaddr_one("012345.6789ab", 0, NULL);
test_config_parse_hwaddr_one("123.4567.89ab", 0, &t[1]);
test_config_parse_ether_addr_one("", 0, NULL);
test_config_parse_ether_addr_one("no:ta:ma:ca:dd:re", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:dd:ee:fx", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:dd:ee:ff", 0, &t[0]);
test_config_parse_ether_addr_one(" aa:bb:cc:dd:ee:ff", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:dd:ee:ff \t\n", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:dd:ee:ff \t\nxxx", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc: dd:ee:ff", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:d d:ee:ff", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:dd:ee", 0, NULL);
test_config_parse_ether_addr_one("9:aa:bb:cc:dd:ee:ff", 0, NULL);
test_config_parse_ether_addr_one("aa:bb:cc:dd:ee:ff:gg", 0, NULL);
test_config_parse_ether_addr_one("aa:Bb:CC:dd:ee:ff", 0, &t[0]);
test_config_parse_ether_addr_one("01:23:45:67:89:aB", 0, &t[1]);
test_config_parse_ether_addr_one("1:23:45:67:89:aB", 0, &t[1]);
test_config_parse_ether_addr_one("aa-bb-cc-dd-ee-ff", 0, &t[0]);
test_config_parse_ether_addr_one("AA-BB-CC-DD-EE-FF", 0, &t[0]);
test_config_parse_ether_addr_one("01-23-45-67-89-ab", 0, &t[1]);
test_config_parse_ether_addr_one("aabb.ccdd.eeff", 0, &t[0]);
test_config_parse_ether_addr_one("0123.4567.89ab", 0, &t[1]);
test_config_parse_ether_addr_one("123.4567.89ab.", 0, NULL);
test_config_parse_ether_addr_one("aabbcc.ddeeff", 0, NULL);
test_config_parse_ether_addr_one("aabbccddeeff", 0, NULL);
test_config_parse_ether_addr_one("aabbccddee:ff", 0, NULL);
test_config_parse_ether_addr_one("012345.6789ab", 0, NULL);
test_config_parse_ether_addr_one("123.4567.89ab", 0, &t[1]);
test_config_parse_hwaddrs_one("", t, 0);
test_config_parse_hwaddrs_one("no:ta:ma:ca:dd:re", t, 0);
test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:fx", t, 0);
test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff", t, 1);
test_config_parse_hwaddrs_one(" aa:bb:cc:dd:ee:ff", t, 1);
test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\n", t, 1);
test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\nxxx", t, 1);
test_config_parse_hwaddrs_one("aa:bb:cc: dd:ee:ff", t, 0);
test_config_parse_hwaddrs_one("aa:bb:cc:d d:ee:ff", t, 0);
test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee", t, 0);
test_config_parse_hwaddrs_one("9:aa:bb:cc:dd:ee:ff", t, 0);
test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff:gg", t, 0);
test_config_parse_hwaddrs_one("aa:Bb:CC:dd:ee:ff", t, 1);
test_config_parse_hwaddrs_one("01:23:45:67:89:aB", &t[1], 1);
test_config_parse_hwaddrs_one("1:23:45:67:89:aB", &t[1], 1);
test_config_parse_hwaddrs_one("aa-bb-cc-dd-ee-ff", t, 1);
test_config_parse_hwaddrs_one("AA-BB-CC-DD-EE-FF", t, 1);
test_config_parse_hwaddrs_one("01-23-45-67-89-ab", &t[1], 1);
test_config_parse_hwaddrs_one("aabb.ccdd.eeff", t, 1);
test_config_parse_hwaddrs_one("0123.4567.89ab", &t[1], 1);
test_config_parse_hwaddrs_one("123.4567.89ab.", t, 0);
test_config_parse_hwaddrs_one("aabbcc.ddeeff", t, 0);
test_config_parse_hwaddrs_one("aabbccddeeff", t, 0);
test_config_parse_hwaddrs_one("aabbccddee:ff", t, 0);
test_config_parse_hwaddrs_one("012345.6789ab", t, 0);
test_config_parse_hwaddrs_one("123.4567.89ab", &t[1], 1);
test_config_parse_ether_addrs_one("", t, 0);
test_config_parse_ether_addrs_one("no:ta:ma:ca:dd:re", t, 0);
test_config_parse_ether_addrs_one("aa:bb:cc:dd:ee:fx", t, 0);
test_config_parse_ether_addrs_one("aa:bb:cc:dd:ee:ff", t, 1);
test_config_parse_ether_addrs_one(" aa:bb:cc:dd:ee:ff", t, 1);
test_config_parse_ether_addrs_one("aa:bb:cc:dd:ee:ff \t\n", t, 1);
test_config_parse_ether_addrs_one("aa:bb:cc:dd:ee:ff \t\nxxx", t, 1);
test_config_parse_ether_addrs_one("aa:bb:cc: dd:ee:ff", t, 0);
test_config_parse_ether_addrs_one("aa:bb:cc:d d:ee:ff", t, 0);
test_config_parse_ether_addrs_one("aa:bb:cc:dd:ee", t, 0);
test_config_parse_ether_addrs_one("9:aa:bb:cc:dd:ee:ff", t, 0);
test_config_parse_ether_addrs_one("aa:bb:cc:dd:ee:ff:gg", t, 0);
test_config_parse_ether_addrs_one("aa:Bb:CC:dd:ee:ff", t, 1);
test_config_parse_ether_addrs_one("01:23:45:67:89:aB", &t[1], 1);
test_config_parse_ether_addrs_one("1:23:45:67:89:aB", &t[1], 1);
test_config_parse_ether_addrs_one("aa-bb-cc-dd-ee-ff", t, 1);
test_config_parse_ether_addrs_one("AA-BB-CC-DD-EE-FF", t, 1);
test_config_parse_ether_addrs_one("01-23-45-67-89-ab", &t[1], 1);
test_config_parse_ether_addrs_one("aabb.ccdd.eeff", t, 1);
test_config_parse_ether_addrs_one("0123.4567.89ab", &t[1], 1);
test_config_parse_ether_addrs_one("123.4567.89ab.", t, 0);
test_config_parse_ether_addrs_one("aabbcc.ddeeff", t, 0);
test_config_parse_ether_addrs_one("aabbccddeeff", t, 0);
test_config_parse_ether_addrs_one("aabbccddee:ff", t, 0);
test_config_parse_ether_addrs_one("012345.6789ab", t, 0);
test_config_parse_ether_addrs_one("123.4567.89ab", &t[1], 1);
test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:ff 01-23-45-67-89-ab aa:Bb:CC:dd:ee:ff", t, 2);
test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:fx hogehoge 01-23-45-67-89-ab aaaa aa:Bb:CC:dd:ee:ff", t, 2);
test_config_parse_ether_addrs_one("123.4567.89ab aa:bb:cc:dd:ee:ff 01-23-45-67-89-ab aa:Bb:CC:dd:ee:ff", t, 2);
test_config_parse_ether_addrs_one("123.4567.89ab aa:bb:cc:dd:ee:fx hogehoge 01-23-45-67-89-ab aaaa aa:Bb:CC:dd:ee:ff", t, 2);
}
static void test_config_parse_address_one(const char *rvalue, int family, unsigned n_addresses, const union in_addr_union *u, unsigned char prefixlen) {
@ -248,7 +248,7 @@ int main(int argc, char **argv) {
test_config_parse_duid_type();
test_config_parse_duid_rawdata();
test_config_parse_hwaddr();
test_config_parse_ether_addr();
test_config_parse_address();
test_config_parse_match_ifnames();
test_config_parse_match_strv();

View File

@ -20,7 +20,7 @@ struct ConfigPerfItem;
%includes
%%
Exec.Boot, config_parse_boot, 0, 0
Exec.Ephemeral, config_parse_bool, 0, offsetof(Settings, ephemeral)
Exec.Ephemeral, config_parse_tristate, 0, offsetof(Settings, ephemeral)
Exec.ProcessTwo, config_parse_pid2, 0, 0
Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
@ -34,7 +34,7 @@ Exec.MachineID, config_parse_id128, 0, of
Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
Exec.PivotRoot, config_parse_pivot_root, 0, 0
Exec.PrivateUsers, config_parse_private_users, 0, 0
Exec.NotifyReady, config_parse_bool, 0, offsetof(Settings, notify_ready)
Exec.NotifyReady, config_parse_tristate, 0, offsetof(Settings, notify_ready)
Exec.SystemCallFilter, config_parse_syscall_filter, 0, 0,
Exec.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof(Settings, rlimit)
Exec.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof(Settings, rlimit)
@ -59,7 +59,7 @@ Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0
Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf)
Exec.LinkJournal, config_parse_link_journal, 0, 0
Exec.Timezone, config_parse_timezone, 0, offsetof(Settings, timezone)
Exec.SuppressSync, config_parse_bool, 0, offsetof(Settings, suppress_sync)
Exec.SuppressSync, config_parse_tristate, 0, offsetof(Settings, suppress_sync)
Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
Files.Bind, config_parse_bind, 0, 0

View File

@ -27,6 +27,7 @@ Settings *settings_new(void) {
*s = (Settings) {
.start_mode = _START_MODE_INVALID,
.ephemeral = -1,
.personality = PERSONALITY_INVALID,
.resolv_conf = _RESOLV_CONF_MODE_INVALID,
@ -57,6 +58,9 @@ Settings *settings_new(void) {
.clone_ns_flags = ULONG_MAX,
.use_cgns = -1,
.notify_ready = -1,
.suppress_sync = -1,
};
return s;
@ -170,6 +174,8 @@ Settings* settings_free(Settings *s) {
bool settings_private_network(Settings *s) {
assert(s);
/* Determines whether we shall open up our own private network */
return
s->private_network > 0 ||
s->network_veth > 0 ||
@ -190,6 +196,25 @@ bool settings_network_veth(Settings *s) {
s->network_zone;
}
bool settings_network_configured(Settings *s) {
assert(s);
/* Determines whether any network configuration setting was used. (i.e. in contrast to
* settings_private_network() above this might also indicate if private networking was explicitly
* turned off.) */
return
s->private_network >= 0 ||
s->network_veth >= 0 ||
s->network_bridge ||
s->network_zone ||
s->network_interfaces ||
s->network_macvlan ||
s->network_ipvlan ||
s->network_veth_extra ||
s->network_namespace_path;
}
int settings_allocate_properties(Settings *s) {
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int r;
@ -285,9 +310,6 @@ int config_parse_capability(
}
}
if (u == 0)
return 0;
*result |= u;
return 0;
}

View File

@ -162,7 +162,7 @@ typedef struct OciHook {
typedef struct Settings {
/* [Exec] */
StartMode start_mode;
bool ephemeral;
int ephemeral;
char **parameters;
char **environment;
char *user;
@ -177,7 +177,7 @@ typedef struct Settings {
char *pivot_root_old;
UserNamespaceMode userns_mode;
uid_t uid_shift, uid_range;
bool notify_ready;
int notify_ready;
char **syscall_allow_list;
char **syscall_deny_list;
struct rlimit *rlimit[_RLIMIT_MAX];
@ -190,7 +190,7 @@ typedef struct Settings {
LinkJournal link_journal;
bool link_journal_try;
TimezoneMode timezone;
bool suppress_sync;
int suppress_sync;
/* [Files] */
int read_only;
@ -242,6 +242,8 @@ Settings* settings_free(Settings *s);
bool settings_network_veth(Settings *s);
bool settings_private_network(Settings *s);
bool settings_network_configured(Settings *s);
int settings_allocate_properties(Settings *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(Settings*, settings_free);

View File

@ -4284,7 +4284,8 @@ static int merge_settings(Settings *settings, const char *path) {
strv_free_and_replace(arg_parameters, settings->parameters);
}
if ((arg_settings_mask & SETTING_EPHEMERAL) == 0)
if ((arg_settings_mask & SETTING_EPHEMERAL) == 0 &&
settings->ephemeral >= 0)
arg_ephemeral = settings->ephemeral;
if ((arg_settings_mask & SETTING_DIRECTORY) == 0 &&
@ -4336,7 +4337,8 @@ static int merge_settings(Settings *settings, const char *path) {
plus = settings->capability;
minus = settings->drop_capability;
if ((arg_settings_mask & SETTING_NETWORK) == 0) {
if ((arg_settings_mask & SETTING_NETWORK) == 0 &&
settings_network_configured(settings)) {
if (settings_private_network(settings))
plus |= UINT64_C(1) << CAP_NET_ADMIN;
else
@ -4407,15 +4409,7 @@ static int merge_settings(Settings *settings, const char *path) {
}
if ((arg_settings_mask & SETTING_NETWORK) == 0 &&
(settings->private_network >= 0 ||
settings->network_veth >= 0 ||
settings->network_bridge ||
settings->network_zone ||
settings->network_interfaces ||
settings->network_macvlan ||
settings->network_ipvlan ||
settings->network_veth_extra ||
settings->network_namespace_path)) {
settings_network_configured(settings)) {
if (!arg_settings_trusted)
log_warning("Ignoring network settings, file %s is not trusted.", path);
@ -4459,27 +4453,33 @@ static int merge_settings(Settings *settings, const char *path) {
}
}
if ((arg_settings_mask & SETTING_BIND_USER) == 0)
if ((arg_settings_mask & SETTING_BIND_USER) == 0 &&
!strv_isempty(settings->bind_user))
strv_free_and_replace(arg_bind_user, settings->bind_user);
if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0)
if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0 &&
settings->notify_ready >= 0)
arg_notify_ready = settings->notify_ready;
if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
if (!arg_settings_trusted && !strv_isempty(settings->syscall_allow_list))
log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path);
else {
strv_free_and_replace(arg_syscall_allow_list, settings->syscall_allow_list);
strv_free_and_replace(arg_syscall_deny_list, settings->syscall_deny_list);
if (!strv_isempty(settings->syscall_allow_list) || !strv_isempty(settings->syscall_deny_list)) {
if (!arg_settings_trusted && !strv_isempty(settings->syscall_allow_list))
log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path);
else {
strv_free_and_replace(arg_syscall_allow_list, settings->syscall_allow_list);
strv_free_and_replace(arg_syscall_deny_list, settings->syscall_deny_list);
}
}
#if HAVE_SECCOMP
if (!arg_settings_trusted && settings->seccomp)
log_warning("Ignoring SECCOMP filter, file %s is not trusted.", path);
else {
seccomp_release(arg_seccomp);
arg_seccomp = TAKE_PTR(settings->seccomp);
if (settings->seccomp) {
if (!arg_settings_trusted)
log_warning("Ignoring SECCOMP filter, file %s is not trusted.", path);
else {
seccomp_release(arg_seccomp);
arg_seccomp = TAKE_PTR(settings->seccomp);
}
}
#endif
}
@ -4585,7 +4585,8 @@ static int merge_settings(Settings *settings, const char *path) {
arg_console_mode = settings->console_mode;
}
if ((arg_settings_mask & SETTING_SUPPRESS_SYNC) == 0)
if ((arg_settings_mask & SETTING_SUPPRESS_SYNC) == 0 &&
settings->suppress_sync >= 0)
arg_suppress_sync = settings->suppress_sync;
/* The following properties can only be set through the OCI settings logic, not from the command line, hence we

View File

@ -505,18 +505,21 @@ static uint64_t free_area_available_for_new_partitions(const FreeArea *a) {
avail = free_area_available(a);
if (a->after) {
uint64_t need, space;
uint64_t need, space_end, new_end;
need = partition_min_size_with_padding(a->after);
assert(a->after->offset != UINT64_MAX);
assert(a->after->current_size != UINT64_MAX);
space = round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset + avail;
if (need >= space)
return 0;
/* Calculate where the free area ends, based on the offset of the partition preceding it */
space_end = round_up_size(a->after->offset + a->after->current_size, 4096) + avail;
return space - need;
/* Calculate where the partition would end when we give it as much as it needs */
new_end = round_up_size(a->after->offset + need, 4096);
/* Calculate saturated difference of the two: that's how much we have free for other partitions */
return LESS_BY(space_end, new_end);
}
return avail;
@ -528,16 +531,9 @@ static int free_area_compare(FreeArea *const *a, FreeArea *const*b) {
}
static uint64_t charge_size(uint64_t total, uint64_t amount) {
uint64_t rounded;
assert(amount <= total);
/* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */
rounded = round_up_size(amount, 4096);
if (rounded >= total)
return 0;
return total - rounded;
assert(amount <= total);
return LESS_BY(total, round_up_size(amount, 4096));
}
static uint64_t charge_weight(uint64_t total, uint64_t amount) {
@ -651,6 +647,8 @@ typedef enum GrowPartitionPhase {
/* The third phase: we distribute what remains among the remaining partitions, according to the weights */
PHASE_DISTRIBUTE,
_GROW_PARTITION_PHASE_MAX,
} GrowPartitionPhase;
static int context_grow_partitions_phase(
@ -786,20 +784,14 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
span += round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset;
}
GrowPartitionPhase phase = PHASE_OVERCHARGE;
for (;;) {
for (GrowPartitionPhase phase = 0; phase < _GROW_PARTITION_PHASE_MAX;) {
r = context_grow_partitions_phase(context, a, phase, &span, &weight_sum);
if (r < 0)
return r;
if (r == 0) /* not done yet, re-run this phase */
continue;
if (phase == PHASE_OVERCHARGE)
phase = PHASE_UNDERCHARGE;
else if (phase == PHASE_UNDERCHARGE)
phase = PHASE_DISTRIBUTE;
else if (phase == PHASE_DISTRIBUTE)
break;
phase++; /* got to next phase */
}
/* We still have space left over? Donate to preceding partition if we have one */
@ -807,7 +799,9 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
uint64_t m, xsz;
assert(a->after->new_size != UINT64_MAX);
m = a->after->new_size + span;
/* Calculate new size and align (but ensure this doesn't shrink the size) */
m = MAX(a->after->new_size, round_down_size(a->after->new_size + span, 4096));
xsz = partition_max_size(a->after);
if (xsz != UINT64_MAX && m > xsz)
@ -832,7 +826,7 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
continue;
assert(p->new_size != UINT64_MAX);
m = p->new_size + span;
m = MAX(p->new_size, round_down_size(p->new_size + span, 4096));
xsz = partition_max_size(p);
if (xsz != UINT64_MAX && m > xsz)
@ -1491,11 +1485,7 @@ static int determine_current_padding(
offset = round_up_size(offset, 4096);
next = round_down_size(next, 4096);
if (next >= offset) /* Check again, rounding might have fucked things up */
*ret = next - offset;
else
*ret = 0;
*ret = LESS_BY(next, offset); /* Saturated substraction, rounding might have fucked things up */
return 0;
}
@ -4988,7 +4978,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
/* Now calculate where each partition gets placed */
/* Now calculate where each new partition gets placed */
context_place_partitions(context);
/* Make sure each partition has a unique UUID and unique label */

View File

@ -1320,7 +1320,101 @@ int config_parse_vlanprotocol(
return 0;
}
int config_parse_hwaddr(
int config_parse_hw_addr(
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) {
struct hw_addr_data a, *hwaddr = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*hwaddr = HW_ADDR_NULL;
return 0;
}
r = parse_hw_addr_full(rvalue, ltype, &a);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Not a valid hardware address, ignoring assignment: %s", rvalue);
return 0;
}
*hwaddr = a;
return 0;
}
int config_parse_hw_addrs(
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(*hwaddrs);
return 0;
}
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL;
_cleanup_free_ struct hw_addr_data *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 hw_addr_data, 1);
if (!n)
return log_oom();
r = parse_hw_addr_full(word, ltype, n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Not a valid hardware address, ignoring: %s", word);
continue;
}
r = set_ensure_consume(hwaddrs, &hw_addr_hash_ops_free, TAKE_PTR(n));
if (r < 0)
return log_oom();
}
}
int config_parse_ether_addr(
const char *unit,
const char *filename,
unsigned line,
@ -1350,7 +1444,7 @@ int config_parse_hwaddr(
if (!n)
return log_oom();
r = ether_addr_from_string(rvalue, n);
r = parse_ether_addr(rvalue, n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Not a valid MAC address, ignoring assignment: %s", rvalue);
@ -1362,7 +1456,7 @@ int config_parse_hwaddr(
return 0;
}
int config_parse_hwaddrs(
int config_parse_ether_addrs(
const char *unit,
const char *filename,
unsigned line,
@ -1384,7 +1478,7 @@ int config_parse_hwaddrs(
if (isempty(rvalue)) {
/* Empty assignment resets the list */
*hwaddrs = set_free_free(*hwaddrs);
*hwaddrs = set_free(*hwaddrs);
return 0;
}
@ -1407,18 +1501,16 @@ int config_parse_hwaddrs(
if (!n)
return log_oom();
r = ether_addr_from_string(word, n);
r = parse_ether_addr(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);
r = set_ensure_consume(hwaddrs, &ether_addr_hash_ops_free, TAKE_PTR(n));
if (r < 0)
return log_oom();
if (r > 0)
TAKE_PTR(n); /* avoid cleanup */
}
}

View File

@ -149,8 +149,10 @@ 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_hw_addr);
CONFIG_PARSER_PROTOTYPE(config_parse_hw_addrs);
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addr);
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs);
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null);
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);

View File

@ -17,8 +17,8 @@ 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->mac = set_free(match->mac);
match->permanent_mac = set_free(match->permanent_mac);
match->path = strv_free(match->path);
match->driver = strv_free(match->driver);
match->iftype = strv_free(match->iftype);
@ -26,7 +26,7 @@ void net_match_clear(NetMatch *match) {
match->property = strv_free(match->property);
match->wlan_iftype = strv_free(match->wlan_iftype);
match->ssid = strv_free(match->ssid);
match->bssid = set_free_free(match->bssid);
match->bssid = set_free(match->bssid);
}
bool net_match_is_empty(const NetMatch *match) {

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ether-addr-util.h"
#include "string-util.h"
#include "tests.h"
#define INFINIBAD_ADDR_1 ((const struct hw_addr_data){ .length = 20, .infiniband = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} })
@ -34,9 +35,110 @@ static void test_HW_ADDR_TO_STRING(void) {
log_info("joint: %s, %s", s, p);
}
static void test_parse_hw_addr_full_one(const char *in, size_t expected_len, const char *expected) {
struct hw_addr_data h;
int r;
r = parse_hw_addr_full(in, expected_len, &h);
log_debug_errno(r, "parse_hw_addr(\"%s\", len=%zu) → \"%s\" (expected: \"%s\") : %d/%m",
in, expected_len, r >= 0 ? HW_ADDR_TO_STR(&h) : "n/a", strna(expected), r);
assert_se((r >= 0) == !!expected);
if (r >= 0) {
if (!IN_SET(expected_len, 0, SIZE_MAX))
assert_se(h.length == expected_len);
assert_se(streq(HW_ADDR_TO_STR(&h), expected));
}
}
static void test_parse_hw_addr(void) {
log_info("/* %s */", __func__);
/* IPv4 */
test_parse_hw_addr_full_one("10.0.0.1", 0, "0a:00:00:01");
test_parse_hw_addr_full_one("10.0.0.1", 4, "0a:00:00:01");
test_parse_hw_addr_full_one("192.168.0.1", 0, "c0:a8:00:01");
test_parse_hw_addr_full_one("192.168.0.1", 4, "c0:a8:00:01");
/* IPv6 */
test_parse_hw_addr_full_one("::", 0, "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00");
test_parse_hw_addr_full_one("::", 16, "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00");
test_parse_hw_addr_full_one("::1", 0, "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01");
test_parse_hw_addr_full_one("::1", 16, "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01");
test_parse_hw_addr_full_one("1234::", 0, "12:34:00:00:00:00:00:00:00:00:00:00:00:00:00:00");
test_parse_hw_addr_full_one("1234::", 16, "12:34:00:00:00:00:00:00:00:00:00:00:00:00:00:00");
test_parse_hw_addr_full_one("12:34::56", 0, "00:12:00:34:00:00:00:00:00:00:00:00:00:00:00:56");
test_parse_hw_addr_full_one("12:34::56", 16, "00:12:00:34:00:00:00:00:00:00:00:00:00:00:00:56");
test_parse_hw_addr_full_one("12aa:34::56", 0, "12:aa:00:34:00:00:00:00:00:00:00:00:00:00:00:56");
test_parse_hw_addr_full_one("12aa:34::56", 16, "12:aa:00:34:00:00:00:00:00:00:00:00:00:00:00:56");
test_parse_hw_addr_full_one("1234:5678:90ab:cdef:1234:5678:90ab:cdef", 0, "12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("1234:5678:90ab:cdef:1234:5678:90ab:cdef", 16, "12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef");
/* Dot */
test_parse_hw_addr_full_one("12.34", 0, "00:12:00:34");
test_parse_hw_addr_full_one("12.34", 4, "00:12:00:34");
test_parse_hw_addr_full_one("12.34", SIZE_MAX, "00:12:00:34");
test_parse_hw_addr_full_one("12.34.56", 0, "00:12:00:34:00:56");
test_parse_hw_addr_full_one("12.34.56", 6, "00:12:00:34:00:56");
test_parse_hw_addr_full_one("12.34.56", SIZE_MAX, "00:12:00:34:00:56");
test_parse_hw_addr_full_one("12.34.56.78", 0, "0c:22:38:4e"); /* IPv4 address */
test_parse_hw_addr_full_one("12.34.56.78", 4, "0c:22:38:4e"); /* IPv4 address */
test_parse_hw_addr_full_one("12.34.56.78", 8, "00:12:00:34:00:56:00:78");
test_parse_hw_addr_full_one("12.34.56.78", SIZE_MAX, "00:12:00:34:00:56:00:78");
test_parse_hw_addr_full_one("12.34.56.78.90", 0, NULL);
test_parse_hw_addr_full_one("12.34.56.78.90", 10, "00:12:00:34:00:56:00:78:00:90");
test_parse_hw_addr_full_one("12.34.56.78.90", SIZE_MAX, "00:12:00:34:00:56:00:78:00:90");
test_parse_hw_addr_full_one("aabb.ccdd", 0, "aa:bb:cc:dd");
test_parse_hw_addr_full_one("aabb.ccdd", 4, "aa:bb:cc:dd");
test_parse_hw_addr_full_one("aabb.ccdd", SIZE_MAX, "aa:bb:cc:dd");
test_parse_hw_addr_full_one("aabb.ccdd.eeff", 0, "aa:bb:cc:dd:ee:ff");
test_parse_hw_addr_full_one("aabb.ccdd.eeff", 6, "aa:bb:cc:dd:ee:ff");
test_parse_hw_addr_full_one("aabb.ccdd.eeff", SIZE_MAX, "aa:bb:cc:dd:ee:ff");
/* Colon */
test_parse_hw_addr_full_one("12:34", 0, NULL);
test_parse_hw_addr_full_one("12:34", 2, "12:34");
test_parse_hw_addr_full_one("12:34", SIZE_MAX, "12:34");
test_parse_hw_addr_full_one("12:34:56:78:90:ab", 0, "12:34:56:78:90:ab");
test_parse_hw_addr_full_one("12:34:56:78:90:ab", 6, "12:34:56:78:90:ab");
test_parse_hw_addr_full_one("12:34:56:78:90:ab", SIZE_MAX, "12:34:56:78:90:ab");
test_parse_hw_addr_full_one("12:34:56:78:90:ab:cd:ef", 0, "00:12:00:34:00:56:00:78:00:90:00:ab:00:cd:00:ef"); /* IPv6 */
test_parse_hw_addr_full_one("12:34:56:78:90:ab:cd:ef", 8, "12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("12:34:56:78:90:ab:cd:ef", 16, "00:12:00:34:00:56:00:78:00:90:00:ab:00:cd:00:ef"); /* IPv6 */
test_parse_hw_addr_full_one("12:34:56:78:90:ab:cd:ef", SIZE_MAX, "12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("12:34:56:78:90:AB:CD:EF", 0, "00:12:00:34:00:56:00:78:00:90:00:ab:00:cd:00:ef"); /* IPv6 */
test_parse_hw_addr_full_one("12:34:56:78:90:AB:CD:EF", 8, "12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("12:34:56:78:90:AB:CD:EF", 16, "00:12:00:34:00:56:00:78:00:90:00:ab:00:cd:00:ef"); /* IPv6 */
test_parse_hw_addr_full_one("12:34:56:78:90:AB:CD:EF", SIZE_MAX, "12:34:56:78:90:ab:cd:ef");
/* Hyphen */
test_parse_hw_addr_full_one("12-34", 0, NULL);
test_parse_hw_addr_full_one("12-34", 2, "12:34");
test_parse_hw_addr_full_one("12-34", SIZE_MAX, "12:34");
test_parse_hw_addr_full_one("12-34-56-78-90-ab-cd-ef", 0, NULL);
test_parse_hw_addr_full_one("12-34-56-78-90-ab-cd-ef", 8, "12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("12-34-56-78-90-ab-cd-ef", SIZE_MAX, "12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("12-34-56-78-90-AB-CD-EF", 0, NULL);
test_parse_hw_addr_full_one("12-34-56-78-90-AB-CD-EF", 8, "12:34:56:78:90:ab:cd:ef");
test_parse_hw_addr_full_one("12-34-56-78-90-AB-CD-EF", SIZE_MAX, "12:34:56:78:90:ab:cd:ef");
/* Invalid */
test_parse_hw_addr_full_one("", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("12", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("12.", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("12.34.", SIZE_MAX, NULL);
test_parse_hw_addr_full_one(".12", SIZE_MAX, NULL);
test_parse_hw_addr_full_one(".12.34", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("12.34:56", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("1234:56", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("1234:56", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("12:34:", SIZE_MAX, NULL);
test_parse_hw_addr_full_one(":12:34", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("::1", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("aa:bb-cc", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("aa:xx", SIZE_MAX, NULL);
test_parse_hw_addr_full_one("aa bb", SIZE_MAX, NULL);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_HW_ADDR_TO_STRING();
test_parse_hw_addr();
return 0;
}

View File

@ -21,8 +21,8 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(LinkConfig, match.mac)
Match.PermanentMACAddress, config_parse_hwaddrs, 0, offsetof(LinkConfig, match.permanent_mac)
Match.MACAddress, config_parse_ether_addrs, 0, offsetof(LinkConfig, match.mac)
Match.PermanentMACAddress, config_parse_ether_addrs, 0, offsetof(LinkConfig, match.permanent_mac)
Match.OriginalName, config_parse_match_ifnames, 0, offsetof(LinkConfig, match.ifname)
Match.Path, config_parse_match_strv, 0, offsetof(LinkConfig, match.path)
Match.Driver, config_parse_match_strv, 0, offsetof(LinkConfig, match.driver)
@ -35,7 +35,7 @@ Match.KernelVersion, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(LinkConfig, conditions)
Link.Description, config_parse_string, 0, offsetof(LinkConfig, description)
Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(LinkConfig, mac_address_policy)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(LinkConfig, mac)
Link.MACAddress, config_parse_ether_addr, 0, offsetof(LinkConfig, mac)
Link.NamePolicy, config_parse_name_policy, 0, offsetof(LinkConfig, name_policy)
Link.Name, config_parse_ifname, 0, offsetof(LinkConfig, name)
Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(LinkConfig, alternative_names)

View File

@ -118,8 +118,8 @@ static int link_parse_wol_password(LinkConfig *link, const char *str) {
if (!p)
return -ENOMEM;
/* Reuse ether_addr_from_string(), as their formats are equivalent. */
r = ether_addr_from_string(str, (struct ether_addr*) p);
/* Reuse parse_ether_addr(), as their formats are equivalent. */
r = parse_ether_addr(str, (struct ether_addr*) p);
if (r < 0)
return r;

View File

@ -84,6 +84,38 @@ cmp /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img
rm /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img /tmp/testsuite-58.dump
rm -r /tmp/testsuite-58-defs/
# Third part: operate on an an image with unaligned partition, to see if that works.
rm -f /var/tmp/testsuite-58.3.img /tmp/testsuite-58-3.dump
mkdir -p /tmp/testsuite-58.3-defs/
cat >/tmp/testsuite-58.3-defs/root.conf <<EOF
[Partition]
Type=root
EOF
truncate -s 10g /var/tmp/testsuite-58.3.img
sfdisk /var/tmp/testsuite-58.3.img <<EOF
label: gpt
start=2048, size=69044
start=71092, size=3591848
EOF
systemd-repart --definitions=/tmp/testsuite-58.3-defs/ \
--seed=750b6cd5c4ae4012a15e7be3c29e6a47 \
--dry-run=no \
/var/tmp/testsuite-58.3.img
sfdisk --dump /var/tmp/testsuite-58.3.img | tee /tmp/testsuite-58.3.dump
grep -qF '/var/tmp/testsuite-58.3.img1 : start= 2048, size= 69044,' /tmp/testsuite-58.3.dump
grep -qF '/var/tmp/testsuite-58.3.img2 : start= 71092, size= 3591848,' /tmp/testsuite-58.3.dump
grep -qxF '/var/tmp/testsuite-58.3.img3 : start= 3662944, size= 17308536, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0, name="root-x86-64", attrs="GUID:59"' /tmp/testsuite-58.3.dump
rm /var/tmp/testsuite-58.3.img /tmp/testsuite-58.3.dump
rm -r /tmp/testsuite-58.3-defs/
echo OK >/testok
exit 0