mirror of
https://github.com/systemd/systemd
synced 2025-12-27 11:24:46 +01:00
Compare commits
16 Commits
0f82a2ab5c
...
4cbd28af60
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cbd28af60 | ||
|
|
7e8a93b77c | ||
|
|
9c2c6692f3 | ||
|
|
efbbdf2923 | ||
|
|
2d453f3597 | ||
|
|
59c31eba49 | ||
|
|
f63e09ef75 | ||
|
|
5f016e326d | ||
|
|
240e41372e | ||
|
|
878c035a48 | ||
|
|
3f2c0d8520 | ||
|
|
1f1d4d42c1 | ||
|
|
99b06a2f5c | ||
|
|
f3e1f00d03 | ||
|
|
1098142436 | ||
|
|
b1b657c48f |
@ -450,6 +450,13 @@
|
||||
This setting is compulsory.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Protocol=</varname></term>
|
||||
<listitem>
|
||||
<para>Allows setting the protocol used for the VLAN interface. Takes <literal>802.1q</literal> or,
|
||||
<literal>802.1ad</literal>, and defaults to unset and kernel's default is used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>GVRP=</varname></term>
|
||||
<listitem>
|
||||
|
||||
@ -1047,18 +1047,29 @@ int copy_file_full(
|
||||
copy_progress_bytes_t progress_bytes,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_close_ int fdf = -1;
|
||||
struct stat st;
|
||||
int fdt = -1, r;
|
||||
|
||||
assert(from);
|
||||
assert(to);
|
||||
|
||||
fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fdf < 0)
|
||||
return -errno;
|
||||
|
||||
if (mode == (mode_t) -1)
|
||||
if (fstat(fdf, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
RUN_WITH_UMASK(0000) {
|
||||
if (copy_flags & COPY_MAC_CREATE) {
|
||||
r = mac_selinux_create_file_prepare(to, S_IFREG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode);
|
||||
fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
|
||||
mode != (mode_t) -1 ? mode : st.st_mode);
|
||||
if (copy_flags & COPY_MAC_CREATE)
|
||||
mac_selinux_create_file_clear();
|
||||
if (fdt < 0)
|
||||
@ -1068,13 +1079,16 @@ int copy_file_full(
|
||||
if (chattr_mask != 0)
|
||||
(void) chattr_fd(fdt, chattr_flags, chattr_mask & CHATTR_EARLY_FL, NULL);
|
||||
|
||||
r = copy_file_fd_full(from, fdt, copy_flags, progress_bytes, userdata);
|
||||
r = copy_bytes_full(fdf, fdt, (uint64_t) -1, copy_flags, NULL, NULL, progress_bytes, userdata);
|
||||
if (r < 0) {
|
||||
close(fdt);
|
||||
(void) unlink(to);
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) copy_times(fdf, fdt, copy_flags);
|
||||
(void) copy_xattr(fdf, fdt);
|
||||
|
||||
if (chattr_mask != 0)
|
||||
(void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL);
|
||||
|
||||
|
||||
@ -1613,3 +1613,80 @@ int path_is_encrypted(const char *path) {
|
||||
|
||||
return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
|
||||
}
|
||||
|
||||
int conservative_rename(
|
||||
int olddirfd, const char *oldpath,
|
||||
int newdirfd, const char *newpath) {
|
||||
|
||||
_cleanup_close_ int old_fd = -1, new_fd = -1;
|
||||
struct stat old_stat, new_stat;
|
||||
|
||||
/* Renames the old path to thew new path, much like renameat() — except if both are regular files and
|
||||
* have the exact same contents and basic file attributes already. In that case remove the new file
|
||||
* instead. This call is useful for reducing inotify wakeups on files that are updated but don't
|
||||
* actually change. This function is written in a style that we rather rename too often than suppress
|
||||
* too much. i.e. whenever we are in doubt we rather rename than fail. After all reducing inotify
|
||||
* events is an optimization only, not more. */
|
||||
|
||||
old_fd = openat(olddirfd, oldpath, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_NOFOLLOW);
|
||||
if (old_fd < 0)
|
||||
goto do_rename;
|
||||
|
||||
new_fd = openat(newdirfd, newpath, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_NOFOLLOW);
|
||||
if (new_fd < 0)
|
||||
goto do_rename;
|
||||
|
||||
if (fstat(old_fd, &old_stat) < 0)
|
||||
goto do_rename;
|
||||
|
||||
if (!S_ISREG(old_stat.st_mode))
|
||||
goto do_rename;
|
||||
|
||||
if (fstat(new_fd, &new_stat) < 0)
|
||||
goto do_rename;
|
||||
|
||||
if (new_stat.st_ino == old_stat.st_ino &&
|
||||
new_stat.st_dev == old_stat.st_dev)
|
||||
goto is_same;
|
||||
|
||||
if (old_stat.st_mode != new_stat.st_mode ||
|
||||
old_stat.st_size != new_stat.st_size ||
|
||||
old_stat.st_uid != new_stat.st_uid ||
|
||||
old_stat.st_gid != new_stat.st_gid)
|
||||
goto do_rename;
|
||||
|
||||
for (;;) {
|
||||
char buf1[16*1024];
|
||||
char buf2[sizeof(buf1) + 1];
|
||||
ssize_t l1, l2;
|
||||
|
||||
l1 = read(old_fd, buf1, sizeof(buf1));
|
||||
if (l1 < 0)
|
||||
goto do_rename;
|
||||
|
||||
l2 = read(new_fd, buf2, l1 + 1);
|
||||
if (l1 != l2)
|
||||
goto do_rename;
|
||||
|
||||
if (l1 == 0) /* EOF on both! And everything's the same so far, yay! */
|
||||
break;
|
||||
|
||||
if (memcmp(buf1, buf2, l1) != 0)
|
||||
goto do_rename;
|
||||
}
|
||||
|
||||
is_same:
|
||||
/* Everything matches? Then don't rename, instead remove the source file, and leave the existing
|
||||
* destination in place */
|
||||
|
||||
if (unlinkat(olddirfd, oldpath, 0) < 0)
|
||||
goto do_rename;
|
||||
|
||||
return 0;
|
||||
|
||||
do_rename:
|
||||
if (renameat(olddirfd, oldpath, newdirfd, newpath) < 0)
|
||||
return -errno;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -132,3 +132,5 @@ int syncfs_path(int atfd, const char *path);
|
||||
int open_parent(const char *path, int flags, mode_t mode);
|
||||
|
||||
int path_is_encrypted(const char *path);
|
||||
|
||||
int conservative_rename(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
|
||||
|
||||
@ -16,10 +16,12 @@
|
||||
#include "ether-addr-util.h"
|
||||
#include "event-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
#include "log-link.h"
|
||||
#include "random-util.h"
|
||||
#include "siphash24.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
@ -54,6 +56,7 @@ struct sd_ipv4acd {
|
||||
int ifindex;
|
||||
int fd;
|
||||
|
||||
char ifname[IF_NAMESIZE + 1];
|
||||
unsigned n_iteration;
|
||||
unsigned n_conflict;
|
||||
|
||||
@ -72,13 +75,30 @@ struct sd_ipv4acd {
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__)
|
||||
#define log_ipv4acd(acd, fmt, ...) log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__)
|
||||
#define log_ipv4acd_errno(acd, error, fmt, ...) \
|
||||
log_interface_full_errno(sd_ipv4acd_get_ifname(acd), LOG_DEBUG, error, "IPV4ACD: " fmt, ##__VA_ARGS__)
|
||||
#define log_ipv4acd(acd, fmt, ...) \
|
||||
log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__)
|
||||
|
||||
static const char * const ipv4acd_state_table[_IPV4ACD_STATE_MAX] = {
|
||||
[IPV4ACD_STATE_INIT] = "init",
|
||||
[IPV4ACD_STATE_STARTED] = "started",
|
||||
[IPV4ACD_STATE_WAITING_PROBE] = "waiting-probe",
|
||||
[IPV4ACD_STATE_PROBING] = "probing",
|
||||
[IPV4ACD_STATE_WAITING_ANNOUNCE] = "waiting-announce",
|
||||
[IPV4ACD_STATE_ANNOUNCING] = "announcing",
|
||||
[IPV4ACD_STATE_RUNNING] = "running",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ipv4acd_state, IPv4ACDState);
|
||||
|
||||
static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) {
|
||||
assert(acd);
|
||||
assert(st < _IPV4ACD_STATE_MAX);
|
||||
|
||||
if (st != acd->state)
|
||||
log_ipv4acd(acd, "%s -> %s", ipv4acd_state_to_string(acd->state), ipv4acd_state_to_string(st));
|
||||
|
||||
if (st == acd->state && !reset_counter)
|
||||
acd->n_iteration++;
|
||||
else {
|
||||
@ -378,15 +398,35 @@ fail:
|
||||
}
|
||||
|
||||
int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) {
|
||||
char ifname[IF_NAMESIZE + 1];
|
||||
|
||||
assert_return(acd, -EINVAL);
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
|
||||
|
||||
if (!format_ifname(ifindex, ifname))
|
||||
return -ENODEV;
|
||||
|
||||
strcpy(acd->ifname, ifname);
|
||||
acd->ifindex = ifindex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) {
|
||||
if (!acd)
|
||||
return -EINVAL;
|
||||
|
||||
return acd->ifindex;
|
||||
}
|
||||
|
||||
const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd) {
|
||||
if (!acd)
|
||||
return NULL;
|
||||
|
||||
return empty_to_null(acd->ifname);
|
||||
}
|
||||
|
||||
int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) {
|
||||
assert_return(acd, -EINVAL);
|
||||
assert_return(addr, -EINVAL);
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
#include "log-link.h"
|
||||
#include "random-util.h"
|
||||
#include "siphash24.h"
|
||||
#include "sparse-endian.h"
|
||||
@ -49,8 +49,10 @@ struct sd_ipv4ll {
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__)
|
||||
#define log_ipv4ll(ll, fmt, ...) log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__)
|
||||
#define log_ipv4ll_errno(ll, error, fmt, ...) \
|
||||
log_interface_full_errno(sd_ipv4ll_get_ifname(ll), LOG_DEBUG, error, "IPV4LL: " fmt, ##__VA_ARGS__)
|
||||
#define log_ipv4ll(ll, fmt, ...) \
|
||||
log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__)
|
||||
|
||||
static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
|
||||
|
||||
@ -103,6 +105,20 @@ int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) {
|
||||
return sd_ipv4acd_set_ifindex(ll->acd, ifindex);
|
||||
}
|
||||
|
||||
int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll) {
|
||||
if (!ll)
|
||||
return -EINVAL;
|
||||
|
||||
return sd_ipv4acd_get_ifindex(ll->acd);
|
||||
}
|
||||
|
||||
const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll) {
|
||||
if (!ll)
|
||||
return NULL;
|
||||
|
||||
return sd_ipv4acd_get_ifname(ll->acd);
|
||||
}
|
||||
|
||||
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
|
||||
int r;
|
||||
|
||||
|
||||
@ -126,7 +126,6 @@ static void test_public_api_setters(sd_event *e) {
|
||||
assert_se(sd_ipv4ll_set_ifindex(ll, -1) == -EINVAL);
|
||||
assert_se(sd_ipv4ll_set_ifindex(ll, -99) == -EINVAL);
|
||||
assert_se(sd_ipv4ll_set_ifindex(ll, 1) == 0);
|
||||
assert_se(sd_ipv4ll_set_ifindex(ll, 99) == 0);
|
||||
|
||||
assert_se(sd_ipv4ll_ref(ll) == ll);
|
||||
assert_se(sd_ipv4ll_unref(ll) == NULL);
|
||||
|
||||
@ -48,6 +48,7 @@ NetDev.Kind, config_parse_netdev_kind,
|
||||
NetDev.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(NetDev, mtu)
|
||||
NetDev.MACAddress, config_parse_hwaddr, 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)
|
||||
VLAN.MVRP, config_parse_tristate, 0, offsetof(VLan, mvrp)
|
||||
VLAN.LooseBinding, config_parse_tristate, 0, offsetof(VLan, loose_binding)
|
||||
|
||||
@ -24,6 +24,12 @@ static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlin
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m");
|
||||
|
||||
if (v->protocol >= 0) {
|
||||
r = sd_netlink_message_append_u16(req, IFLA_VLAN_PROTOCOL, htobe16(v->protocol));
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_PROTOCOL attribute: %m");
|
||||
}
|
||||
|
||||
if (v->gvrp != -1) {
|
||||
flags.mask |= VLAN_FLAG_GVRP;
|
||||
SET_FLAG(flags.flags, VLAN_FLAG_GVRP, v->gvrp);
|
||||
@ -76,6 +82,7 @@ static void vlan_init(NetDev *netdev) {
|
||||
assert(v);
|
||||
|
||||
v->id = VLANID_INVALID;
|
||||
v->protocol = -1;
|
||||
v->gvrp = -1;
|
||||
v->mvrp = -1;
|
||||
v->loose_binding = -1;
|
||||
|
||||
@ -9,6 +9,7 @@ struct VLan {
|
||||
NetDev meta;
|
||||
|
||||
uint16_t id;
|
||||
int protocol;
|
||||
|
||||
int gvrp;
|
||||
int mvrp;
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include "bus-error.h"
|
||||
#include "dhcp-internal.h"
|
||||
#include "dhcp6-internal.h"
|
||||
#include "escape.h"
|
||||
@ -99,18 +100,20 @@ static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_er
|
||||
|
||||
e = sd_bus_message_get_error(m);
|
||||
if (e) {
|
||||
log_error_errno(sd_bus_error_get_errno(e),
|
||||
"Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s",
|
||||
e->message);
|
||||
r = sd_bus_error_get_errno(e);
|
||||
log_warning_errno(r, "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s",
|
||||
bus_error_message(e, r));
|
||||
goto configure;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read_array(m, 'y', &a, &sz);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m");
|
||||
goto configure;
|
||||
}
|
||||
|
||||
if (sz != sizeof(sd_id128_t)) {
|
||||
log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID.");
|
||||
log_warning("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID.");
|
||||
goto configure;
|
||||
}
|
||||
|
||||
|
||||
@ -1277,6 +1277,8 @@ static int dhcp4_set_request_address(Link *link) {
|
||||
if (!a)
|
||||
return 0;
|
||||
|
||||
log_link_debug(link, "DHCP4 CLIENT: requesting " IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(a->in_addr.in));
|
||||
|
||||
return sd_dhcp_client_set_request_address(link->dhcp_client, &a->in_addr.in);
|
||||
}
|
||||
|
||||
|
||||
@ -2172,6 +2172,7 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
|
||||
link_free_carrier_maps(link);
|
||||
link_free_engines(link);
|
||||
link->network = network_unref(link->network);
|
||||
link_unref(set_remove(link->manager->links_requesting_uuid, link));
|
||||
|
||||
/* Then, apply new .network file */
|
||||
r = network_apply(network, link);
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-error.h"
|
||||
#include "bus-log-control-api.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "bus-util.h"
|
||||
@ -1157,15 +1158,16 @@ void manager_dirty(Manager *manager) {
|
||||
}
|
||||
|
||||
static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
_unused_ Manager *manager = userdata;
|
||||
const sd_bus_error *e;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(manager);
|
||||
|
||||
e = sd_bus_message_get_error(m);
|
||||
if (e)
|
||||
log_warning_errno(sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
|
||||
if (e) {
|
||||
r = sd_bus_error_get_errno(e);
|
||||
log_warning_errno(r, "Could not set hostname: %s", bus_error_message(e, r));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1203,15 +1205,16 @@ int manager_set_hostname(Manager *m, const char *hostname) {
|
||||
}
|
||||
|
||||
static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
_unused_ Manager *manager = userdata;
|
||||
const sd_bus_error *e;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(manager);
|
||||
|
||||
e = sd_bus_message_get_error(m);
|
||||
if (e)
|
||||
log_warning_errno(sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
|
||||
if (e) {
|
||||
r = sd_bus_error_get_errno(e);
|
||||
log_warning_errno(r, "Could not set timezone: %s", bus_error_message(e, r));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1887,7 +1887,7 @@ static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const
|
||||
if (!t->scope->link)
|
||||
return 0;
|
||||
|
||||
return set_contains(t->scope->link->dnssec_negative_trust_anchors, name);
|
||||
return link_negative_trust_anchor_lookup(t->scope->link, name);
|
||||
}
|
||||
|
||||
static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
|
||||
|
||||
@ -1407,3 +1407,26 @@ void link_remove_user(Link *l) {
|
||||
|
||||
(void) unlink(l->state_file);
|
||||
}
|
||||
|
||||
bool link_negative_trust_anchor_lookup(Link *l, const char *name) {
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(name);
|
||||
|
||||
/* Checks whether the specified domain (or any of its parent domains) are listed as per-link NTA. */
|
||||
|
||||
for (;;) {
|
||||
if (set_contains(l->dnssec_negative_trust_anchors, name))
|
||||
return true;
|
||||
|
||||
/* And now, let's look at the parent, and check that too */
|
||||
r = dns_name_parent(&name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -108,4 +108,6 @@ int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m);
|
||||
bool link_address_relevant(LinkAddress *l, bool local_multicast);
|
||||
void link_address_add_rrs(LinkAddress *a, bool force_remove);
|
||||
|
||||
bool link_negative_trust_anchor_lookup(Link *l, const char *name);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
|
||||
|
||||
@ -359,8 +359,9 @@ int manager_write_resolv_conf(Manager *m) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF) < 0)
|
||||
r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF);
|
||||
r = conservative_rename(AT_FDCWD, temp_path_stub, AT_FDCWD, PRIVATE_STUB_RESOLV_CONF);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF);
|
||||
|
||||
} else {
|
||||
r = symlink_atomic(basename(PRIVATE_UPLINK_RESOLV_CONF), PRIVATE_STUB_RESOLV_CONF);
|
||||
@ -368,8 +369,9 @@ int manager_write_resolv_conf(Manager *m) {
|
||||
log_error_errno(r, "Failed to symlink %s: %m", PRIVATE_STUB_RESOLV_CONF);
|
||||
}
|
||||
|
||||
if (rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF) < 0)
|
||||
r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_UPLINK_RESOLV_CONF);
|
||||
r = conservative_rename(AT_FDCWD, temp_path_uplink, AT_FDCWD, PRIVATE_UPLINK_RESOLV_CONF);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to move new %s into place: %m", PRIVATE_UPLINK_RESOLV_CONF);
|
||||
|
||||
fail:
|
||||
if (r < 0) {
|
||||
|
||||
@ -3,6 +3,13 @@
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#define log_interface_full_errno(ifname, level, error, ...) \
|
||||
({ \
|
||||
const char *_ifname = (ifname); \
|
||||
_ifname ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _ifname, NULL, NULL, ##__VA_ARGS__) : \
|
||||
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
/*
|
||||
* The following macros append INTERFACE= to the message.
|
||||
* The macros require a struct named 'Link' which contains 'char *ifname':
|
||||
@ -17,9 +24,8 @@
|
||||
#define log_link_full_errno(link, level, error, ...) \
|
||||
({ \
|
||||
const Link *_l = (link); \
|
||||
(_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \
|
||||
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
|
||||
}) \
|
||||
log_interface_full_errno(_l ? _l->ifname : NULL, level, error, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 0, __VA_ARGS__)
|
||||
|
||||
|
||||
@ -43,6 +43,8 @@ int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address);
|
||||
int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata);
|
||||
int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr);
|
||||
int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index);
|
||||
int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd);
|
||||
const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd);
|
||||
int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address);
|
||||
int sd_ipv4acd_is_running(sd_ipv4acd *acd);
|
||||
int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts);
|
||||
|
||||
@ -43,6 +43,8 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
|
||||
int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata);
|
||||
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
|
||||
int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index);
|
||||
int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll);
|
||||
const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll);
|
||||
int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
|
||||
int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed);
|
||||
int sd_ipv4ll_is_running(sd_ipv4ll *ll);
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "copy.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "macro.h"
|
||||
@ -834,6 +836,51 @@ static void test_path_is_encrypted(void) {
|
||||
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
|
||||
}
|
||||
|
||||
static void test_conservative_rename(void) {
|
||||
_cleanup_(unlink_and_freep) char *p = NULL;
|
||||
_cleanup_free_ char *q = NULL;
|
||||
|
||||
assert_se(tempfn_random_child(NULL, NULL, &p) >= 0);
|
||||
assert_se(write_string_file(p, "this is a test", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
|
||||
assert_se(tempfn_random_child(NULL, NULL, &q) >= 0);
|
||||
|
||||
/* Check that the hardlinked "copy" is detected */
|
||||
assert_se(link(p, q) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
/* Check that a manual copy is detected */
|
||||
assert_se(copy_file(p, q, 0, (mode_t) -1, 0, 0, COPY_REFLINK) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
/* Check that a manual new writeout is also detected */
|
||||
assert_se(write_string_file(q, "this is a test", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
/* Check that a minimally changed version is detected */
|
||||
assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
/* Check that this really is new updated version */
|
||||
assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
/* Make sure we detect extended files */
|
||||
assert_se(write_string_file(q, "this is a_testx", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
/* Make sure we detect truncated files */
|
||||
assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0);
|
||||
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
@ -852,6 +899,7 @@ int main(int argc, char *argv[]) {
|
||||
test_rename_noreplace();
|
||||
test_chmod_and_chown();
|
||||
test_path_is_encrypted();
|
||||
test_conservative_rename();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ LooseBinding=
|
||||
ReorderHeader=
|
||||
Id=
|
||||
GVRP=
|
||||
Protocol=
|
||||
[MACVLAN]
|
||||
Mode=
|
||||
SourceMACAddress=
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
[Match]
|
||||
Name=veth99
|
||||
|
||||
[Network]
|
||||
DHCP=ipv4
|
||||
LinkLocalAddressing=yes
|
||||
IPv6AcceptRA=no
|
||||
|
||||
[DHCPv4]
|
||||
MaxAttempts=1
|
||||
@ -589,9 +589,19 @@ class Utilities():
|
||||
output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
|
||||
if re.search(address_regex, output) and 'tentative' not in output:
|
||||
break
|
||||
else:
|
||||
|
||||
self.assertRegex(output, address_regex)
|
||||
|
||||
def wait_address_dropped(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
|
||||
for i in range(timeout_sec):
|
||||
if i > 0:
|
||||
time.sleep(1)
|
||||
output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
|
||||
if not re.search(address_regex, output):
|
||||
break
|
||||
|
||||
self.assertNotRegex(output, address_regex)
|
||||
|
||||
class NetworkctlTests(unittest.TestCase, Utilities):
|
||||
|
||||
links = [
|
||||
@ -3428,8 +3438,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
'dhcp-client-use-dns-yes.network',
|
||||
'dhcp-client-use-domains.network',
|
||||
'dhcp-client-vrf.network',
|
||||
'dhcp-client-with-ipv4ll-with-dhcp-server.network',
|
||||
'dhcp-client-with-ipv4ll-without-dhcp-server.network',
|
||||
'dhcp-client-with-ipv4ll.network',
|
||||
'dhcp-client-with-static-address.network',
|
||||
'dhcp-client.network',
|
||||
'dhcp-server-decline.network',
|
||||
@ -3994,7 +4003,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
|
||||
def test_dhcp_client_with_ipv4ll_with_dhcp_server(self):
|
||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
|
||||
'dhcp-client-with-ipv4ll-with-dhcp-server.network')
|
||||
'dhcp-client-with-ipv4ll.network')
|
||||
start_networkd()
|
||||
self.wait_online(['veth-peer:carrier'])
|
||||
start_dnsmasq(lease_time='2m')
|
||||
@ -4004,13 +4013,13 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
|
||||
output = check_output('ip -6 address show dev veth99 scope global dynamic')
|
||||
self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
|
||||
self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
|
||||
output = check_output('ip -6 address show dev veth99 scope link')
|
||||
self.assertRegex(output, 'inet6 .* scope link')
|
||||
self.assertRegex(output, r'inet6 .* scope link')
|
||||
output = check_output('ip -4 address show dev veth99 scope global dynamic')
|
||||
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
|
||||
self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
|
||||
output = check_output('ip -4 address show dev veth99 scope link')
|
||||
self.assertNotRegex(output, 'inet .* scope link')
|
||||
self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
|
||||
|
||||
print('Wait for the dynamic address to be expired')
|
||||
time.sleep(130)
|
||||
@ -4019,19 +4028,19 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
|
||||
output = check_output('ip -6 address show dev veth99 scope global dynamic')
|
||||
self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
|
||||
self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
|
||||
output = check_output('ip -6 address show dev veth99 scope link')
|
||||
self.assertRegex(output, 'inet6 .* scope link')
|
||||
self.assertRegex(output, r'inet6 .* scope link')
|
||||
output = check_output('ip -4 address show dev veth99 scope global dynamic')
|
||||
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
|
||||
self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
|
||||
output = check_output('ip -4 address show dev veth99 scope link')
|
||||
self.assertNotRegex(output, 'inet .* scope link')
|
||||
self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
|
||||
|
||||
search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
|
||||
|
||||
def test_dhcp_client_with_ipv4ll_without_dhcp_server(self):
|
||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
|
||||
'dhcp-client-with-ipv4ll-without-dhcp-server.network')
|
||||
'dhcp-client-with-ipv4ll.network')
|
||||
start_networkd()
|
||||
self.wait_online(['veth99:degraded', 'veth-peer:routable'])
|
||||
|
||||
@ -4039,13 +4048,17 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
|
||||
output = check_output('ip -6 address show dev veth99 scope global dynamic')
|
||||
self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
|
||||
self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
|
||||
output = check_output('ip -6 address show dev veth99 scope link')
|
||||
self.assertRegex(output, 'inet6 .* scope link')
|
||||
self.assertRegex(output, r'inet6 .* scope link')
|
||||
output = check_output('ip -4 address show dev veth99 scope global dynamic')
|
||||
self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
|
||||
self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
|
||||
output = check_output('ip -4 address show dev veth99 scope link')
|
||||
self.assertRegex(output, 'inet .* scope link')
|
||||
self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
|
||||
|
||||
start_dnsmasq(lease_time='2m')
|
||||
self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
|
||||
self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4')
|
||||
|
||||
def test_dhcp_client_route_remove_on_renew(self):
|
||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user