mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-08-25 13:50:12 +03:00
Merge pull request #18773 from yuwata/network-move-several-functions
network: move several functions
This commit is contained in:
@ -869,7 +869,7 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {
|
||||
}
|
||||
|
||||
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
struct sd_dhcp_raw_option *option;
|
||||
struct in_addr address;
|
||||
@ -889,7 +889,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
||||
|
||||
r = fopen_temporary(lease_file, &f, &temp_path);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
@ -992,10 +992,8 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
||||
_cleanup_free_ char *client_id_hex = NULL;
|
||||
|
||||
client_id_hex = hexmem(client_id, client_id_len);
|
||||
if (!client_id_hex) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (!client_id_hex)
|
||||
return -ENOMEM;
|
||||
fprintf(f, "CLIENTID=%s\n", client_id_hex);
|
||||
}
|
||||
|
||||
@ -1004,10 +1002,8 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
||||
_cleanup_free_ char *option_hex = NULL;
|
||||
|
||||
option_hex = hexmem(data, data_len);
|
||||
if (!option_hex) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (!option_hex)
|
||||
return -ENOMEM;
|
||||
fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex);
|
||||
}
|
||||
|
||||
@ -1017,28 +1013,23 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
||||
xsprintf(key, "OPTION_%" PRIu8, option->tag);
|
||||
r = serialize_dhcp_option(f, key, option->data, option->length);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
r = conservative_rename(temp_path, lease_file);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
temp_path = mfree(temp_path);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (temp_path)
|
||||
(void) unlink(temp_path);
|
||||
|
||||
return log_error_errno(r, "Failed to save lease data %s: %m", lease_file);
|
||||
}
|
||||
|
||||
int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
|
||||
|
||||
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
|
||||
_cleanup_free_ char
|
||||
*address = NULL,
|
||||
|
@ -113,6 +113,8 @@ sources = files('''
|
||||
networkd-speed-meter.h
|
||||
networkd-sriov.c
|
||||
networkd-sriov.h
|
||||
networkd-state-file.c
|
||||
networkd-state-file.h
|
||||
networkd-sysctl.c
|
||||
networkd-sysctl.h
|
||||
networkd-util.c
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "networkd-link-bus.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "parse-util.h"
|
||||
#include "resolve-util.h"
|
||||
#include "socket-netlink.h"
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "bond.h"
|
||||
#include "bridge.h"
|
||||
#include "bus-util.h"
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
#include "dhcp-identifier.h"
|
||||
#include "dhcp-lease-internal.h"
|
||||
#include "env-file.h"
|
||||
@ -42,6 +44,7 @@
|
||||
#include "networkd-sysctl.h"
|
||||
#include "networkd-radv.h"
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
@ -543,8 +546,6 @@ static Link *link_free(Link *link) {
|
||||
link->ndisc_addresses = set_free(link->ndisc_addresses);
|
||||
|
||||
link_free_engines(link);
|
||||
free(link->lease_file);
|
||||
free(link->lldp_file);
|
||||
|
||||
free(link->ifname);
|
||||
strv_free(link->alternative_names);
|
||||
@ -552,8 +553,9 @@ static Link *link_free(Link *link) {
|
||||
free(link->ssid);
|
||||
free(link->driver);
|
||||
|
||||
(void) unlink(link->state_file);
|
||||
free(link->state_file);
|
||||
unlink_and_free(link->lease_file);
|
||||
unlink_and_free(link->lldp_file);
|
||||
unlink_and_free(link->state_file);
|
||||
|
||||
sd_device_unref(link->sd_device);
|
||||
|
||||
@ -1733,7 +1735,7 @@ static void link_detach_from_manager(Link *link) {
|
||||
link_unref(link);
|
||||
}
|
||||
|
||||
void link_drop(Link *link) {
|
||||
static void link_drop(Link *link) {
|
||||
if (!link || link->state == LINK_STATE_LINGER)
|
||||
return;
|
||||
|
||||
@ -2380,7 +2382,7 @@ static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin
|
||||
return 1;
|
||||
}
|
||||
|
||||
int link_initialized(Link *link, sd_device *device) {
|
||||
static int link_initialized(Link *link, sd_device *device) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
@ -2420,7 +2422,7 @@ int link_initialized(Link *link, sd_device *device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
|
||||
static int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
|
||||
Link *link;
|
||||
@ -2505,6 +2507,57 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata) {
|
||||
sd_device_action_t action;
|
||||
Manager *m = userdata;
|
||||
Link *link = NULL;
|
||||
int r, ifindex;
|
||||
|
||||
assert(m);
|
||||
assert(device);
|
||||
|
||||
r = sd_device_get_action(device, &action);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(device, r, "Failed to get udev action, ignoring device: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ignore the "remove" uevent — let's remove a device only if rtnetlink says so. All other uevents
|
||||
* are "positive" events in some form, i.e. inform us about a changed or new network interface, that
|
||||
* still exists — and we are interested in that. */
|
||||
if (action == SD_DEVICE_REMOVE)
|
||||
return 0;
|
||||
|
||||
r = sd_device_get_ifindex(device, &ifindex);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(device, r, "Ignoring udev %s event for device without ifindex or with invalid ifindex: %m",
|
||||
device_action_to_string(action));
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = device_is_renaming(device);
|
||||
if (r < 0) {
|
||||
log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m",
|
||||
device_action_to_string(action));
|
||||
return 0;
|
||||
}
|
||||
if (r > 0) {
|
||||
log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_get(m, ifindex, &link);
|
||||
if (r < 0) {
|
||||
if (r != -ENODEV)
|
||||
log_debug_errno(r, "Failed to get link from ifindex %i, ignoring: %m", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) link_initialized(link, device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_carrier_gained(Link *link) {
|
||||
int r;
|
||||
|
||||
@ -2618,13 +2671,14 @@ int link_carrier_reset(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is called every time an interface admin state changes to up;
|
||||
* specifically, when IFF_UP flag changes from unset to set */
|
||||
static int link_admin_state_up(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
/* This is called every time an interface admin state changes to up;
|
||||
* specifically, when IFF_UP flag changes from unset to set. */
|
||||
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
@ -2648,7 +2702,6 @@ static int link_admin_state_up(Link *link) {
|
||||
}
|
||||
|
||||
static int link_admin_state_down(Link *link) {
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->network)
|
||||
@ -2662,7 +2715,7 @@ static int link_admin_state_down(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_update(Link *link, sd_netlink_message *m) {
|
||||
static int link_update(Link *link, sd_netlink_message *m) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
hw_addr_data hw_addr;
|
||||
const char *ifname;
|
||||
@ -2806,388 +2859,91 @@ int link_update(Link *link, sd_netlink_message *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) {
|
||||
bool space = false;
|
||||
Link *link;
|
||||
int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||
Link *link = NULL;
|
||||
NetDev *netdev = NULL;
|
||||
uint16_t type;
|
||||
const char *name;
|
||||
int r, ifindex;
|
||||
|
||||
assert(f);
|
||||
assert(prefix);
|
||||
assert(rtnl);
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
if (hashmap_isempty(h))
|
||||
return;
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring");
|
||||
|
||||
fputs(prefix, f);
|
||||
HASHMAP_FOREACH(link, h) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
|
||||
fprintf(f, "%i", link->ifindex);
|
||||
space = true;
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
static void link_save_dns(Link *link, FILE *f, struct in_addr_full **dns, unsigned n_dns, bool *space) {
|
||||
for (unsigned j = 0; j < n_dns; j++) {
|
||||
const char *str;
|
||||
|
||||
if (dns[j]->ifindex != 0 && dns[j]->ifindex != link->ifindex)
|
||||
continue;
|
||||
|
||||
str = in_addr_full_to_string(dns[j]);
|
||||
if (!str)
|
||||
continue;
|
||||
|
||||
if (*space)
|
||||
fputc(' ', f);
|
||||
fputs(str, f);
|
||||
*space = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void serialize_addresses(
|
||||
FILE *f,
|
||||
const char *lvalue,
|
||||
bool *space,
|
||||
char **addresses,
|
||||
sd_dhcp_lease *lease,
|
||||
bool conditional,
|
||||
sd_dhcp_lease_server_type_t what,
|
||||
sd_dhcp6_lease *lease6,
|
||||
bool conditional6,
|
||||
int (*lease6_get_addr)(sd_dhcp6_lease*, const struct in6_addr**),
|
||||
int (*lease6_get_fqdn)(sd_dhcp6_lease*, char ***)) {
|
||||
int r;
|
||||
|
||||
bool _space = false;
|
||||
if (!space)
|
||||
space = &_space;
|
||||
|
||||
if (lvalue)
|
||||
fprintf(f, "%s=", lvalue);
|
||||
fputstrv(f, addresses, NULL, space);
|
||||
|
||||
if (lease && conditional) {
|
||||
const struct in_addr *lease_addresses;
|
||||
|
||||
r = sd_dhcp_lease_get_servers(lease, what, &lease_addresses);
|
||||
if (r > 0)
|
||||
serialize_in_addrs(f, lease_addresses, r, space, in4_addr_is_non_local);
|
||||
}
|
||||
|
||||
if (lease6 && conditional6 && lease6_get_addr) {
|
||||
const struct in6_addr *in6_addrs;
|
||||
|
||||
r = lease6_get_addr(lease6, &in6_addrs);
|
||||
if (r > 0)
|
||||
serialize_in6_addrs(f, in6_addrs, r, space);
|
||||
}
|
||||
|
||||
if (lease6 && conditional6 && lease6_get_fqdn) {
|
||||
char **in6_hosts;
|
||||
|
||||
r = lease6_get_fqdn(lease6, &in6_hosts);
|
||||
if (r > 0)
|
||||
fputstrv(f, in6_hosts, NULL, space);
|
||||
}
|
||||
|
||||
if (lvalue)
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
int link_save(Link *link) {
|
||||
const char *admin_state, *oper_state, *carrier_state, *address_state;
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->state_file);
|
||||
assert(link->lease_file);
|
||||
assert(link->manager);
|
||||
|
||||
if (link->state == LINK_STATE_LINGER) {
|
||||
(void) unlink(link->state_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
link_lldp_save(link);
|
||||
|
||||
admin_state = link_state_to_string(link->state);
|
||||
assert(admin_state);
|
||||
|
||||
oper_state = link_operstate_to_string(link->operstate);
|
||||
assert(oper_state);
|
||||
|
||||
carrier_state = link_carrier_state_to_string(link->carrier_state);
|
||||
assert(carrier_state);
|
||||
|
||||
address_state = link_address_state_to_string(link->address_state);
|
||||
assert(address_state);
|
||||
|
||||
r = fopen_temporary(link->state_file, &f, &temp_path);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n"
|
||||
"ADMIN_STATE=%s\n"
|
||||
"OPER_STATE=%s\n"
|
||||
"CARRIER_STATE=%s\n"
|
||||
"ADDRESS_STATE=%s\n",
|
||||
admin_state, oper_state, carrier_state, address_state);
|
||||
|
||||
if (link->network) {
|
||||
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
|
||||
const char *dhcp_domainname = NULL, *p;
|
||||
bool space;
|
||||
|
||||
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
|
||||
yes_no(link->network->required_for_online));
|
||||
|
||||
LinkOperationalStateRange st = link->network->required_operstate_for_online;
|
||||
fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s%s%s\n",
|
||||
strempty(link_operstate_to_string(st.min)),
|
||||
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "",
|
||||
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : "");
|
||||
|
||||
fprintf(f, "ACTIVATION_POLICY=%s\n",
|
||||
activation_policy_to_string(link->network->activation_policy));
|
||||
|
||||
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fputs("DNS=", f);
|
||||
space = false;
|
||||
if (link->n_dns != (unsigned) -1)
|
||||
link_save_dns(link, f, link->dns, link->n_dns, &space);
|
||||
else
|
||||
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
|
||||
|
||||
serialize_addresses(f, NULL, &space,
|
||||
NULL,
|
||||
link->dhcp_lease,
|
||||
link->network->dhcp_use_dns,
|
||||
SD_DHCP_LEASE_DNS,
|
||||
link->dhcp6_lease,
|
||||
link->network->dhcp6_use_dns,
|
||||
sd_dhcp6_lease_get_dns,
|
||||
NULL);
|
||||
|
||||
/* Make sure to flush out old entries before we use the NDisc data */
|
||||
ndisc_vacuum(link);
|
||||
|
||||
if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) {
|
||||
NDiscRDNSS *dd;
|
||||
|
||||
SET_FOREACH(dd, link->ndisc_rdnss)
|
||||
serialize_in6_addrs(f, &dd->address, 1, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
serialize_addresses(f, "NTP", NULL,
|
||||
link->ntp ?: link->network->ntp,
|
||||
link->dhcp_lease,
|
||||
link->network->dhcp_use_ntp,
|
||||
SD_DHCP_LEASE_NTP,
|
||||
link->dhcp6_lease,
|
||||
link->network->dhcp6_use_ntp,
|
||||
sd_dhcp6_lease_get_ntp_addrs,
|
||||
sd_dhcp6_lease_get_ntp_fqdn);
|
||||
|
||||
serialize_addresses(f, "SIP", NULL,
|
||||
NULL,
|
||||
link->dhcp_lease,
|
||||
link->network->dhcp_use_sip,
|
||||
SD_DHCP_LEASE_SIP,
|
||||
NULL, false, NULL, NULL);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
if (link->dhcp_lease) {
|
||||
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
|
||||
(void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
|
||||
}
|
||||
if (link->dhcp6_lease)
|
||||
(void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
|
||||
}
|
||||
|
||||
fputs("DOMAINS=", f);
|
||||
space = false;
|
||||
ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains)
|
||||
fputs_with_space(f, p, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
|
||||
if (dhcp_domainname)
|
||||
fputs_with_space(f, dhcp_domainname, NULL, &space);
|
||||
if (dhcp_domains)
|
||||
fputstrv(f, dhcp_domains, NULL, &space);
|
||||
if (dhcp6_domains)
|
||||
fputstrv(f, dhcp6_domains, NULL, &space);
|
||||
}
|
||||
|
||||
if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_YES) {
|
||||
NDiscDNSSL *dd;
|
||||
|
||||
SET_FOREACH(dd, link->ndisc_dnssl)
|
||||
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fputs("ROUTE_DOMAINS=", f);
|
||||
space = false;
|
||||
ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains)
|
||||
fputs_with_space(f, p, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
|
||||
if (dhcp_domainname)
|
||||
fputs_with_space(f, dhcp_domainname, NULL, &space);
|
||||
if (dhcp_domains)
|
||||
fputstrv(f, dhcp_domains, NULL, &space);
|
||||
if (dhcp6_domains)
|
||||
fputstrv(f, dhcp6_domains, NULL, &space);
|
||||
}
|
||||
|
||||
if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_ROUTE) {
|
||||
NDiscDNSSL *dd;
|
||||
|
||||
SET_FOREACH(dd, link->ndisc_dnssl)
|
||||
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fprintf(f, "LLMNR=%s\n",
|
||||
resolve_support_to_string(link->llmnr >= 0 ? link->llmnr : link->network->llmnr));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fprintf(f, "MDNS=%s\n",
|
||||
resolve_support_to_string(link->mdns >= 0 ? link->mdns : link->network->mdns));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
int dns_default_route =
|
||||
link->dns_default_route >= 0 ? link->dns_default_route :
|
||||
link->network->dns_default_route;
|
||||
if (dns_default_route >= 0)
|
||||
fprintf(f, "DNS_DEFAULT_ROUTE=%s\n", yes_no(dns_default_route));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
DnsOverTlsMode dns_over_tls_mode =
|
||||
link->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID ? link->dns_over_tls_mode :
|
||||
link->network->dns_over_tls_mode;
|
||||
if (dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
|
||||
fprintf(f, "DNS_OVER_TLS=%s\n", dns_over_tls_mode_to_string(dns_over_tls_mode));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
DnssecMode dnssec_mode =
|
||||
link->dnssec_mode != _DNSSEC_MODE_INVALID ? link->dnssec_mode :
|
||||
link->network->dnssec_mode;
|
||||
if (dnssec_mode != _DNSSEC_MODE_INVALID)
|
||||
fprintf(f, "DNSSEC=%s\n", dnssec_mode_to_string(dnssec_mode));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
Set *nta_anchors = link->dnssec_negative_trust_anchors;
|
||||
if (set_isempty(nta_anchors))
|
||||
nta_anchors = link->network->dnssec_negative_trust_anchors;
|
||||
|
||||
if (!set_isempty(nta_anchors)) {
|
||||
const char *n;
|
||||
|
||||
fputs("DNSSEC_NTA=", f);
|
||||
space = false;
|
||||
SET_FOREACH(n, nta_anchors)
|
||||
fputs_with_space(f, n, NULL, &space);
|
||||
fputc('\n', f);
|
||||
}
|
||||
r = sd_netlink_message_get_type(message, &type);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m");
|
||||
return 0;
|
||||
} else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) {
|
||||
log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links);
|
||||
print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links);
|
||||
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m");
|
||||
return 0;
|
||||
} else if (ifindex <= 0) {
|
||||
log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (link->dhcp_lease) {
|
||||
r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"DHCP_LEASE=%s\n",
|
||||
link->lease_file);
|
||||
} else
|
||||
(void) unlink(link->lease_file);
|
||||
(void) link_get(m, ifindex, &link);
|
||||
(void) netdev_get(m, name, &netdev);
|
||||
|
||||
r = link_serialize_dhcp6_client(link, f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
switch (type) {
|
||||
case RTM_NEWLINK:
|
||||
if (!link) {
|
||||
/* link is new, so add it */
|
||||
r = link_add(m, message, &link);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not process new link message, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
if (netdev) {
|
||||
/* netdev exists, so make sure the ifindex matches */
|
||||
r = netdev_set_ifindex(netdev, message);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = conservative_rename(temp_path, link->state_file);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
r = link_update(link, message);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not process link message, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
break;
|
||||
|
||||
fail:
|
||||
(void) unlink(link->state_file);
|
||||
if (temp_path)
|
||||
(void) unlink(temp_path);
|
||||
case RTM_DELLINK:
|
||||
link_drop(link);
|
||||
netdev_drop(netdev);
|
||||
|
||||
return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
|
||||
}
|
||||
break;
|
||||
|
||||
/* The serialized state in /run is no longer up-to-date. */
|
||||
void link_dirty(Link *link) {
|
||||
int r;
|
||||
default:
|
||||
assert_not_reached("Received link message with invalid RTNL message type.");
|
||||
}
|
||||
|
||||
assert(link);
|
||||
|
||||
/* mark manager dirty as link is dirty */
|
||||
manager_dirty(link->manager);
|
||||
|
||||
r = set_ensure_put(&link->manager->dirty_links, NULL, link);
|
||||
if (r <= 0)
|
||||
/* Ignore allocation errors and don't take another ref if the link was already dirty */
|
||||
return;
|
||||
link_ref(link);
|
||||
}
|
||||
|
||||
/* The serialized state in /run is up-to-date */
|
||||
void link_clean(Link *link) {
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
link_unref(set_remove(link->manager->dirty_links, link));
|
||||
}
|
||||
|
||||
int link_save_and_clean(Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_save(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_clean(link);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char* const link_state_table[_LINK_STATE_MAX] = {
|
||||
|
@ -203,24 +203,15 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
|
||||
DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref);
|
||||
|
||||
int link_get(Manager *m, int ifindex, Link **ret);
|
||||
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
|
||||
void link_drop(Link *link);
|
||||
|
||||
int link_down(Link *link, link_netlink_message_handler_t callback);
|
||||
|
||||
void link_enter_failed(Link *link);
|
||||
int link_initialized(Link *link, sd_device *device);
|
||||
|
||||
void link_set_state(Link *link, LinkState state);
|
||||
void link_check_ready(Link *link);
|
||||
|
||||
void link_update_operstate(Link *link, bool also_update_bond_master);
|
||||
int link_update(Link *link, sd_netlink_message *message);
|
||||
|
||||
void link_dirty(Link *link);
|
||||
void link_clean(Link *link);
|
||||
int link_save(Link *link);
|
||||
int link_save_and_clean(Link *link);
|
||||
|
||||
int link_carrier_reset(Link *link);
|
||||
bool link_has_carrier(Link *link);
|
||||
@ -241,6 +232,9 @@ LinkState link_state_from_string(const char *s) _pure_;
|
||||
int link_configure(Link *link);
|
||||
int link_reconfigure(Link *link, bool force);
|
||||
|
||||
int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata);
|
||||
int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
|
||||
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
|
||||
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-lldp-rx.h"
|
||||
#include "networkd-lldp-tx.h"
|
||||
@ -134,7 +135,7 @@ int link_update_lldp(Link *link) {
|
||||
}
|
||||
|
||||
int link_lldp_save(Link *link) {
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
sd_lldp_neighbor **l = NULL;
|
||||
int n = 0, r, i;
|
||||
@ -149,10 +150,10 @@ int link_lldp_save(Link *link) {
|
||||
|
||||
r = sd_lldp_get_neighbors(link->lldp, &l);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
return r;
|
||||
if (r == 0) {
|
||||
(void) unlink(link->lldp_file);
|
||||
goto finish;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = r;
|
||||
@ -181,19 +182,13 @@ int link_lldp_save(Link *link) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (rename(temp_path, link->lldp_file) < 0) {
|
||||
r = -errno;
|
||||
r = conservative_rename(temp_path, link->lldp_file);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
finish:
|
||||
if (r < 0) {
|
||||
(void) unlink(link->lldp_file);
|
||||
if (temp_path)
|
||||
(void) unlink(temp_path);
|
||||
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
|
||||
}
|
||||
|
||||
if (l) {
|
||||
for (i = 0; i < n; i++)
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include "bus-util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "def.h"
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -38,6 +36,7 @@
|
||||
#include "networkd-nexthop.h"
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-speed-meter.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "ordered-set.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
@ -48,7 +47,6 @@
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "udev-util.h"
|
||||
|
||||
/* use 128 MB for receive socket kernel queue. */
|
||||
#define RCVBUF_SIZE (128*1024*1024)
|
||||
@ -181,57 +179,6 @@ int manager_connect_bus(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata) {
|
||||
sd_device_action_t action;
|
||||
Manager *m = userdata;
|
||||
Link *link = NULL;
|
||||
int r, ifindex;
|
||||
|
||||
assert(m);
|
||||
assert(device);
|
||||
|
||||
r = sd_device_get_action(device, &action);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(device, r, "Failed to get udev action, ignoring device: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ignore the "remove" uevent — let's remove a device only if rtnetlink says so. All other uevents
|
||||
* are "positive" events in some form, i.e. inform us about a changed or new network interface, that
|
||||
* still exists — and we are interested in that. */
|
||||
if (action == SD_DEVICE_REMOVE)
|
||||
return 0;
|
||||
|
||||
r = sd_device_get_ifindex(device, &ifindex);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(device, r, "Ignoring udev %s event for device without ifindex or with invalid ifindex: %m",
|
||||
device_action_to_string(action));
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = device_is_renaming(device);
|
||||
if (r < 0) {
|
||||
log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m",
|
||||
device_action_to_string(action));
|
||||
return 0;
|
||||
}
|
||||
if (r > 0) {
|
||||
log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_get(m, ifindex, &link);
|
||||
if (r < 0) {
|
||||
if (r != -ENODEV)
|
||||
log_debug_errno(r, "Failed to get link from ifindex %i, ignoring: %m", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) link_initialized(link, device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_connect_udev(Manager *m) {
|
||||
int r;
|
||||
|
||||
@ -263,93 +210,6 @@ static int manager_connect_udev(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||
Link *link = NULL;
|
||||
NetDev *netdev = NULL;
|
||||
uint16_t type;
|
||||
const char *name;
|
||||
int r, ifindex;
|
||||
|
||||
assert(rtnl);
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_get_type(message, &type);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m");
|
||||
return 0;
|
||||
} else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) {
|
||||
log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m");
|
||||
return 0;
|
||||
} else if (ifindex <= 0) {
|
||||
log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) link_get(m, ifindex, &link);
|
||||
(void) netdev_get(m, name, &netdev);
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWLINK:
|
||||
if (!link) {
|
||||
/* link is new, so add it */
|
||||
r = link_add(m, message, &link);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not process new link message, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (netdev) {
|
||||
/* netdev exists, so make sure the ifindex matches */
|
||||
r = netdev_set_ifindex(netdev, message);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = link_update(link, message);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not process link message, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTM_DELLINK:
|
||||
link_drop(link);
|
||||
netdev_drop(netdev);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Received link message with invalid RTNL message type.");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int systemd_netlink_fd(void) {
|
||||
int n, fd, rtnl_fd = -EINVAL;
|
||||
|
||||
@ -357,14 +217,13 @@ static int systemd_netlink_fd(void) {
|
||||
if (n <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
|
||||
for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
|
||||
if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
|
||||
if (rtnl_fd >= 0)
|
||||
return -EINVAL;
|
||||
|
||||
rtnl_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
return rtnl_fd;
|
||||
}
|
||||
@ -466,300 +325,24 @@ static int manager_connect_rtnl(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ordered_set_put_dns_server(OrderedSet *s, int ifindex, struct in_addr_full *dns) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(dns);
|
||||
|
||||
if (dns->ifindex != 0 && dns->ifindex != ifindex)
|
||||
return 0;
|
||||
|
||||
p = in_addr_full_to_string(dns);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
r = ordered_set_put_strdup(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_dns_servers(OrderedSet *s, int ifindex, struct in_addr_full **dns, unsigned n) {
|
||||
int r, c = 0;
|
||||
|
||||
assert(s);
|
||||
assert(dns || n == 0);
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
r = ordered_set_put_dns_server(s, ifindex, dns[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += r;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
||||
r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_consume(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in4_addrv(OrderedSet *s,
|
||||
const struct in_addr *addresses,
|
||||
size_t n,
|
||||
bool (*predicate)(const struct in_addr *addr)) {
|
||||
int r, c = 0;
|
||||
|
||||
assert(s);
|
||||
assert(n == 0 || addresses);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (predicate && !predicate(&addresses[i]))
|
||||
continue;
|
||||
r = ordered_set_put_in4_addr(s, addresses+i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += r;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int manager_save(Manager *m) {
|
||||
_cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
|
||||
const char *operstate_str, *carrier_state_str, *address_state_str;
|
||||
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
|
||||
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
|
||||
LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_strv_free_ char **p = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->state_file);
|
||||
|
||||
/* We add all NTP and DNS server to a set, to filter out duplicates */
|
||||
dns = ordered_set_new(&string_hash_ops);
|
||||
if (!dns)
|
||||
return -ENOMEM;
|
||||
|
||||
ntp = ordered_set_new(&string_hash_ops);
|
||||
if (!ntp)
|
||||
return -ENOMEM;
|
||||
|
||||
sip = ordered_set_new(&string_hash_ops);
|
||||
if (!sip)
|
||||
return -ENOMEM;
|
||||
|
||||
search_domains = ordered_set_new(&dns_name_hash_ops);
|
||||
if (!search_domains)
|
||||
return -ENOMEM;
|
||||
|
||||
route_domains = ordered_set_new(&dns_name_hash_ops);
|
||||
if (!route_domains)
|
||||
return -ENOMEM;
|
||||
|
||||
HASHMAP_FOREACH(link, m->links) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
continue;
|
||||
|
||||
if (link->operstate > operstate)
|
||||
operstate = link->operstate;
|
||||
|
||||
if (link->carrier_state > carrier_state)
|
||||
carrier_state = link->carrier_state;
|
||||
|
||||
if (link->address_state > address_state)
|
||||
address_state = link->address_state;
|
||||
|
||||
if (!link->network)
|
||||
continue;
|
||||
|
||||
/* First add the static configured entries */
|
||||
if (link->n_dns != (unsigned) -1)
|
||||
r = ordered_set_put_dns_servers(dns, link->ifindex, link->dns, link->n_dns);
|
||||
else
|
||||
r = ordered_set_put_dns_servers(dns, link->ifindex, link->network->dns, link->network->n_dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_strdupv(ntp, link->ntp ?: link->network->ntp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_string_set(search_domains, link->search_domains ?: link->network->search_domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_string_set(route_domains, link->route_domains ?: link->network->route_domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!link->dhcp_lease)
|
||||
continue;
|
||||
|
||||
/* Secondly, add the entries acquired via DHCP */
|
||||
if (link->network->dhcp_use_dns) {
|
||||
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_ntp) {
|
||||
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_sip) {
|
||||
r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
const char *domainname;
|
||||
char **domains = NULL;
|
||||
|
||||
OrderedSet *target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? search_domains : route_domains;
|
||||
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
|
||||
if (r >= 0) {
|
||||
r = ordered_set_put_strdup(target_domains, domainname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r != -ENODATA)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains);
|
||||
if (r >= 0) {
|
||||
r = ordered_set_put_strdupv(target_domains, domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED)
|
||||
carrier_state = LINK_CARRIER_STATE_CARRIER;
|
||||
|
||||
operstate_str = link_operstate_to_string(operstate);
|
||||
assert(operstate_str);
|
||||
|
||||
carrier_state_str = link_carrier_state_to_string(carrier_state);
|
||||
assert(carrier_state_str);
|
||||
|
||||
address_state_str = link_address_state_to_string(address_state);
|
||||
assert(address_state_str);
|
||||
|
||||
r = fopen_temporary(m->state_file, &f, &temp_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n"
|
||||
"OPER_STATE=%s\n"
|
||||
"CARRIER_STATE=%s\n"
|
||||
"ADDRESS_STATE=%s\n",
|
||||
operstate_str, carrier_state_str, address_state_str);
|
||||
|
||||
ordered_set_print(f, "DNS=", dns);
|
||||
ordered_set_print(f, "NTP=", ntp);
|
||||
ordered_set_print(f, "SIP=", sip);
|
||||
ordered_set_print(f, "DOMAINS=", search_domains);
|
||||
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = conservative_rename(temp_path, m->state_file);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (m->operational_state != operstate) {
|
||||
m->operational_state = operstate;
|
||||
if (strv_extend(&p, "OperationalState") < 0)
|
||||
log_oom();
|
||||
}
|
||||
|
||||
if (m->carrier_state != carrier_state) {
|
||||
m->carrier_state = carrier_state;
|
||||
if (strv_extend(&p, "CarrierState") < 0)
|
||||
log_oom();
|
||||
}
|
||||
|
||||
if (m->address_state != address_state) {
|
||||
m->address_state = address_state;
|
||||
if (strv_extend(&p, "AddressState") < 0)
|
||||
log_oom();
|
||||
}
|
||||
|
||||
if (p) {
|
||||
r = manager_send_changed_strv(m, p);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Could not emit changed properties: %m");
|
||||
}
|
||||
|
||||
m->dirty = false;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
(void) unlink(m->state_file);
|
||||
(void) unlink(temp_path);
|
||||
|
||||
return log_error_errno(r, "Failed to save network state to %s: %m", m->state_file);
|
||||
}
|
||||
|
||||
static int manager_dirty_handler(sd_event_source *s, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->dirty)
|
||||
manager_save(m);
|
||||
if (m->dirty) {
|
||||
r = manager_save(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to update state file %s, ignoring: %m", m->state_file);
|
||||
}
|
||||
|
||||
SET_FOREACH(link, m->dirty_links)
|
||||
(void) link_save_and_clean(link);
|
||||
SET_FOREACH(link, m->dirty_links) {
|
||||
r = link_save_and_clean(link);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to update link state file %s, ignoring: %m", link->state_file);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -929,10 +512,15 @@ int manager_start(Manager *m) {
|
||||
/* The dirty handler will deal with future serialization, but the first one
|
||||
must be done explicitly. */
|
||||
|
||||
manager_save(m);
|
||||
r = manager_save(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to update state file %s, ignoring: %m", m->state_file);
|
||||
|
||||
HASHMAP_FOREACH(link, m->links)
|
||||
(void) link_save(link);
|
||||
HASHMAP_FOREACH(link, m->links) {
|
||||
r = link_save(link);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to update link state file %s, ignoring: %m", link->state_file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1155,13 +743,6 @@ Link* manager_find_uplink(Manager *m, Link *exclude) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void manager_dirty(Manager *manager) {
|
||||
assert(manager);
|
||||
|
||||
/* the serialized state in /run is no longer up-to-date */
|
||||
manager->dirty = true;
|
||||
}
|
||||
|
||||
static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
const sd_bus_error *e;
|
||||
int r;
|
||||
|
@ -100,8 +100,6 @@ bool manager_should_reload(Manager *m);
|
||||
|
||||
int manager_enumerate(Manager *m);
|
||||
|
||||
void manager_dirty(Manager *m);
|
||||
|
||||
Link* manager_find_uplink(Manager *m, Link *exclude);
|
||||
|
||||
int manager_set_hostname(Manager *m, const char *hostname);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "networkd-dhcp6.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
682
src/network/networkd-state-file.c
Normal file
682
src/network/networkd-state-file.c
Normal file
@ -0,0 +1,682 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "network-internal.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager-bus.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "ordered-set.h"
|
||||
#include "set.h"
|
||||
#include "strv.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
static int ordered_set_put_dns_server(OrderedSet *s, int ifindex, struct in_addr_full *dns) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(dns);
|
||||
|
||||
if (dns->ifindex != 0 && dns->ifindex != ifindex)
|
||||
return 0;
|
||||
|
||||
p = in_addr_full_to_string(dns);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
r = ordered_set_put_strdup(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_dns_servers(OrderedSet *s, int ifindex, struct in_addr_full **dns, unsigned n) {
|
||||
int r, c = 0;
|
||||
|
||||
assert(s);
|
||||
assert(dns || n == 0);
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
r = ordered_set_put_dns_server(s, ifindex, dns[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += r;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
||||
r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_consume(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in4_addrv(
|
||||
OrderedSet *s,
|
||||
const struct in_addr *addresses,
|
||||
size_t n,
|
||||
bool (*predicate)(const struct in_addr *addr)) {
|
||||
|
||||
int r, c = 0;
|
||||
|
||||
assert(s);
|
||||
assert(n == 0 || addresses);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (predicate && !predicate(&addresses[i]))
|
||||
continue;
|
||||
r = ordered_set_put_in4_addr(s, addresses+i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += r;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int manager_save(Manager *m) {
|
||||
_cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
|
||||
const char *operstate_str, *carrier_state_str, *address_state_str;
|
||||
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
|
||||
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
|
||||
LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
|
||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||
_cleanup_strv_free_ char **p = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->state_file);
|
||||
|
||||
/* We add all NTP and DNS server to a set, to filter out duplicates */
|
||||
dns = ordered_set_new(&string_hash_ops);
|
||||
if (!dns)
|
||||
return -ENOMEM;
|
||||
|
||||
ntp = ordered_set_new(&string_hash_ops);
|
||||
if (!ntp)
|
||||
return -ENOMEM;
|
||||
|
||||
sip = ordered_set_new(&string_hash_ops);
|
||||
if (!sip)
|
||||
return -ENOMEM;
|
||||
|
||||
search_domains = ordered_set_new(&dns_name_hash_ops);
|
||||
if (!search_domains)
|
||||
return -ENOMEM;
|
||||
|
||||
route_domains = ordered_set_new(&dns_name_hash_ops);
|
||||
if (!route_domains)
|
||||
return -ENOMEM;
|
||||
|
||||
HASHMAP_FOREACH(link, m->links) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
continue;
|
||||
|
||||
if (link->operstate > operstate)
|
||||
operstate = link->operstate;
|
||||
|
||||
if (link->carrier_state > carrier_state)
|
||||
carrier_state = link->carrier_state;
|
||||
|
||||
if (link->address_state > address_state)
|
||||
address_state = link->address_state;
|
||||
|
||||
if (!link->network)
|
||||
continue;
|
||||
|
||||
/* First add the static configured entries */
|
||||
if (link->n_dns != (unsigned) -1)
|
||||
r = ordered_set_put_dns_servers(dns, link->ifindex, link->dns, link->n_dns);
|
||||
else
|
||||
r = ordered_set_put_dns_servers(dns, link->ifindex, link->network->dns, link->network->n_dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_strdupv(ntp, link->ntp ?: link->network->ntp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_string_set(search_domains, link->search_domains ?: link->network->search_domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_string_set(route_domains, link->route_domains ?: link->network->route_domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!link->dhcp_lease)
|
||||
continue;
|
||||
|
||||
/* Secondly, add the entries acquired via DHCP */
|
||||
if (link->network->dhcp_use_dns) {
|
||||
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_ntp) {
|
||||
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_sip) {
|
||||
r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
const char *domainname;
|
||||
char **domains = NULL;
|
||||
|
||||
OrderedSet *target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? search_domains : route_domains;
|
||||
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
|
||||
if (r >= 0) {
|
||||
r = ordered_set_put_strdup(target_domains, domainname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r != -ENODATA)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains);
|
||||
if (r >= 0) {
|
||||
r = ordered_set_put_strdupv(target_domains, domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED)
|
||||
carrier_state = LINK_CARRIER_STATE_CARRIER;
|
||||
|
||||
operstate_str = link_operstate_to_string(operstate);
|
||||
assert(operstate_str);
|
||||
|
||||
carrier_state_str = link_carrier_state_to_string(carrier_state);
|
||||
assert(carrier_state_str);
|
||||
|
||||
address_state_str = link_address_state_to_string(address_state);
|
||||
assert(address_state_str);
|
||||
|
||||
r = fopen_temporary(m->state_file, &f, &temp_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n"
|
||||
"OPER_STATE=%s\n"
|
||||
"CARRIER_STATE=%s\n"
|
||||
"ADDRESS_STATE=%s\n",
|
||||
operstate_str, carrier_state_str, address_state_str);
|
||||
|
||||
ordered_set_print(f, "DNS=", dns);
|
||||
ordered_set_print(f, "NTP=", ntp);
|
||||
ordered_set_print(f, "SIP=", sip);
|
||||
ordered_set_print(f, "DOMAINS=", search_domains);
|
||||
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conservative_rename(temp_path, m->state_file);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
temp_path = mfree(temp_path);
|
||||
|
||||
if (m->operational_state != operstate) {
|
||||
m->operational_state = operstate;
|
||||
if (strv_extend(&p, "OperationalState") < 0)
|
||||
log_oom();
|
||||
}
|
||||
|
||||
if (m->carrier_state != carrier_state) {
|
||||
m->carrier_state = carrier_state;
|
||||
if (strv_extend(&p, "CarrierState") < 0)
|
||||
log_oom();
|
||||
}
|
||||
|
||||
if (m->address_state != address_state) {
|
||||
m->address_state = address_state;
|
||||
if (strv_extend(&p, "AddressState") < 0)
|
||||
log_oom();
|
||||
}
|
||||
|
||||
if (p) {
|
||||
r = manager_send_changed_strv(m, p);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Could not emit changed properties, ignoring: %m");
|
||||
}
|
||||
|
||||
m->dirty = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) {
|
||||
bool space = false;
|
||||
Link *link;
|
||||
|
||||
assert(f);
|
||||
assert(prefix);
|
||||
|
||||
if (hashmap_isempty(h))
|
||||
return;
|
||||
|
||||
fputs(prefix, f);
|
||||
HASHMAP_FOREACH(link, h) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
|
||||
fprintf(f, "%i", link->ifindex);
|
||||
space = true;
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
static void link_save_dns(Link *link, FILE *f, struct in_addr_full **dns, unsigned n_dns, bool *space) {
|
||||
for (unsigned j = 0; j < n_dns; j++) {
|
||||
const char *str;
|
||||
|
||||
if (dns[j]->ifindex != 0 && dns[j]->ifindex != link->ifindex)
|
||||
continue;
|
||||
|
||||
str = in_addr_full_to_string(dns[j]);
|
||||
if (!str)
|
||||
continue;
|
||||
|
||||
if (*space)
|
||||
fputc(' ', f);
|
||||
fputs(str, f);
|
||||
*space = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void serialize_addresses(
|
||||
FILE *f,
|
||||
const char *lvalue,
|
||||
bool *space,
|
||||
char **addresses,
|
||||
sd_dhcp_lease *lease,
|
||||
bool conditional,
|
||||
sd_dhcp_lease_server_type_t what,
|
||||
sd_dhcp6_lease *lease6,
|
||||
bool conditional6,
|
||||
int (*lease6_get_addr)(sd_dhcp6_lease*, const struct in6_addr**),
|
||||
int (*lease6_get_fqdn)(sd_dhcp6_lease*, char ***)) {
|
||||
|
||||
bool _space = false;
|
||||
int r;
|
||||
|
||||
if (!space)
|
||||
space = &_space;
|
||||
|
||||
if (lvalue)
|
||||
fprintf(f, "%s=", lvalue);
|
||||
fputstrv(f, addresses, NULL, space);
|
||||
|
||||
if (lease && conditional) {
|
||||
const struct in_addr *lease_addresses;
|
||||
|
||||
r = sd_dhcp_lease_get_servers(lease, what, &lease_addresses);
|
||||
if (r > 0)
|
||||
serialize_in_addrs(f, lease_addresses, r, space, in4_addr_is_non_local);
|
||||
}
|
||||
|
||||
if (lease6 && conditional6 && lease6_get_addr) {
|
||||
const struct in6_addr *in6_addrs;
|
||||
|
||||
r = lease6_get_addr(lease6, &in6_addrs);
|
||||
if (r > 0)
|
||||
serialize_in6_addrs(f, in6_addrs, r, space);
|
||||
}
|
||||
|
||||
if (lease6 && conditional6 && lease6_get_fqdn) {
|
||||
char **in6_hosts;
|
||||
|
||||
r = lease6_get_fqdn(lease6, &in6_hosts);
|
||||
if (r > 0)
|
||||
fputstrv(f, in6_hosts, NULL, space);
|
||||
}
|
||||
|
||||
if (lvalue)
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
int link_save(Link *link) {
|
||||
const char *admin_state, *oper_state, *carrier_state, *address_state;
|
||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->state_file);
|
||||
assert(link->lease_file);
|
||||
assert(link->manager);
|
||||
|
||||
if (link->state == LINK_STATE_LINGER)
|
||||
return 0;
|
||||
|
||||
link_lldp_save(link);
|
||||
|
||||
admin_state = link_state_to_string(link->state);
|
||||
assert(admin_state);
|
||||
|
||||
oper_state = link_operstate_to_string(link->operstate);
|
||||
assert(oper_state);
|
||||
|
||||
carrier_state = link_carrier_state_to_string(link->carrier_state);
|
||||
assert(carrier_state);
|
||||
|
||||
address_state = link_address_state_to_string(link->address_state);
|
||||
assert(address_state);
|
||||
|
||||
r = fopen_temporary(link->state_file, &f, &temp_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n"
|
||||
"ADMIN_STATE=%s\n"
|
||||
"OPER_STATE=%s\n"
|
||||
"CARRIER_STATE=%s\n"
|
||||
"ADDRESS_STATE=%s\n",
|
||||
admin_state, oper_state, carrier_state, address_state);
|
||||
|
||||
if (link->network) {
|
||||
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
|
||||
const char *dhcp_domainname = NULL, *p;
|
||||
bool space;
|
||||
|
||||
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
|
||||
yes_no(link->network->required_for_online));
|
||||
|
||||
LinkOperationalStateRange st = link->network->required_operstate_for_online;
|
||||
fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s%s%s\n",
|
||||
strempty(link_operstate_to_string(st.min)),
|
||||
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "",
|
||||
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : "");
|
||||
|
||||
fprintf(f, "ACTIVATION_POLICY=%s\n",
|
||||
activation_policy_to_string(link->network->activation_policy));
|
||||
|
||||
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fputs("DNS=", f);
|
||||
space = false;
|
||||
if (link->n_dns != (unsigned) -1)
|
||||
link_save_dns(link, f, link->dns, link->n_dns, &space);
|
||||
else
|
||||
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
|
||||
|
||||
serialize_addresses(f, NULL, &space,
|
||||
NULL,
|
||||
link->dhcp_lease,
|
||||
link->network->dhcp_use_dns,
|
||||
SD_DHCP_LEASE_DNS,
|
||||
link->dhcp6_lease,
|
||||
link->network->dhcp6_use_dns,
|
||||
sd_dhcp6_lease_get_dns,
|
||||
NULL);
|
||||
|
||||
/* Make sure to flush out old entries before we use the NDisc data */
|
||||
ndisc_vacuum(link);
|
||||
|
||||
if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) {
|
||||
NDiscRDNSS *dd;
|
||||
|
||||
SET_FOREACH(dd, link->ndisc_rdnss)
|
||||
serialize_in6_addrs(f, &dd->address, 1, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
serialize_addresses(f, "NTP", NULL,
|
||||
link->ntp ?: link->network->ntp,
|
||||
link->dhcp_lease,
|
||||
link->network->dhcp_use_ntp,
|
||||
SD_DHCP_LEASE_NTP,
|
||||
link->dhcp6_lease,
|
||||
link->network->dhcp6_use_ntp,
|
||||
sd_dhcp6_lease_get_ntp_addrs,
|
||||
sd_dhcp6_lease_get_ntp_fqdn);
|
||||
|
||||
serialize_addresses(f, "SIP", NULL,
|
||||
NULL,
|
||||
link->dhcp_lease,
|
||||
link->network->dhcp_use_sip,
|
||||
SD_DHCP_LEASE_SIP,
|
||||
NULL, false, NULL, NULL);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
if (link->dhcp_lease) {
|
||||
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
|
||||
(void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
|
||||
}
|
||||
if (link->dhcp6_lease)
|
||||
(void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
|
||||
}
|
||||
|
||||
fputs("DOMAINS=", f);
|
||||
space = false;
|
||||
ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains)
|
||||
fputs_with_space(f, p, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
|
||||
if (dhcp_domainname)
|
||||
fputs_with_space(f, dhcp_domainname, NULL, &space);
|
||||
if (dhcp_domains)
|
||||
fputstrv(f, dhcp_domains, NULL, &space);
|
||||
if (dhcp6_domains)
|
||||
fputstrv(f, dhcp6_domains, NULL, &space);
|
||||
}
|
||||
|
||||
if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_YES) {
|
||||
NDiscDNSSL *dd;
|
||||
|
||||
SET_FOREACH(dd, link->ndisc_dnssl)
|
||||
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fputs("ROUTE_DOMAINS=", f);
|
||||
space = false;
|
||||
ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains)
|
||||
fputs_with_space(f, p, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
|
||||
if (dhcp_domainname)
|
||||
fputs_with_space(f, dhcp_domainname, NULL, &space);
|
||||
if (dhcp_domains)
|
||||
fputstrv(f, dhcp_domains, NULL, &space);
|
||||
if (dhcp6_domains)
|
||||
fputstrv(f, dhcp6_domains, NULL, &space);
|
||||
}
|
||||
|
||||
if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_ROUTE) {
|
||||
NDiscDNSSL *dd;
|
||||
|
||||
SET_FOREACH(dd, link->ndisc_dnssl)
|
||||
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fprintf(f, "LLMNR=%s\n",
|
||||
resolve_support_to_string(link->llmnr >= 0 ? link->llmnr : link->network->llmnr));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
fprintf(f, "MDNS=%s\n",
|
||||
resolve_support_to_string(link->mdns >= 0 ? link->mdns : link->network->mdns));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
int dns_default_route =
|
||||
link->dns_default_route >= 0 ? link->dns_default_route :
|
||||
link->network->dns_default_route;
|
||||
if (dns_default_route >= 0)
|
||||
fprintf(f, "DNS_DEFAULT_ROUTE=%s\n", yes_no(dns_default_route));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
DnsOverTlsMode dns_over_tls_mode =
|
||||
link->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID ? link->dns_over_tls_mode :
|
||||
link->network->dns_over_tls_mode;
|
||||
if (dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
|
||||
fprintf(f, "DNS_OVER_TLS=%s\n", dns_over_tls_mode_to_string(dns_over_tls_mode));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
DnssecMode dnssec_mode =
|
||||
link->dnssec_mode != _DNSSEC_MODE_INVALID ? link->dnssec_mode :
|
||||
link->network->dnssec_mode;
|
||||
if (dnssec_mode != _DNSSEC_MODE_INVALID)
|
||||
fprintf(f, "DNSSEC=%s\n", dnssec_mode_to_string(dnssec_mode));
|
||||
|
||||
/************************************************************/
|
||||
|
||||
Set *nta_anchors = link->dnssec_negative_trust_anchors;
|
||||
if (set_isempty(nta_anchors))
|
||||
nta_anchors = link->network->dnssec_negative_trust_anchors;
|
||||
|
||||
if (!set_isempty(nta_anchors)) {
|
||||
const char *n;
|
||||
|
||||
fputs("DNSSEC_NTA=", f);
|
||||
space = false;
|
||||
SET_FOREACH(n, nta_anchors)
|
||||
fputs_with_space(f, n, NULL, &space);
|
||||
fputc('\n', f);
|
||||
}
|
||||
}
|
||||
|
||||
print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links);
|
||||
print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links);
|
||||
|
||||
if (link->dhcp_lease) {
|
||||
r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fprintf(f,
|
||||
"DHCP_LEASE=%s\n",
|
||||
link->lease_file);
|
||||
} else
|
||||
(void) unlink(link->lease_file);
|
||||
|
||||
r = link_serialize_dhcp6_client(link, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conservative_rename(temp_path, link->state_file);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
temp_path = mfree(temp_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void link_dirty(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
/* The serialized state in /run is no longer up-to-date. */
|
||||
|
||||
/* Also mark manager dirty as link is dirty */
|
||||
link->manager->dirty = true;
|
||||
|
||||
r = set_ensure_put(&link->manager->dirty_links, NULL, link);
|
||||
if (r <= 0)
|
||||
/* Ignore allocation errors and don't take another ref if the link was already dirty */
|
||||
return;
|
||||
link_ref(link);
|
||||
}
|
||||
|
||||
void link_clean(Link *link) {
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
/* The serialized state in /run is up-to-date */
|
||||
|
||||
link_unref(set_remove(link->manager->dirty_links, link));
|
||||
}
|
||||
|
||||
int link_save_and_clean(Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_save(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_clean(link);
|
||||
return 0;
|
||||
}
|
12
src/network/networkd-state-file.h
Normal file
12
src/network/networkd-state-file.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
|
||||
void link_dirty(Link *link);
|
||||
void link_clean(Link *link);
|
||||
int link_save(Link *link);
|
||||
int link_save_and_clean(Link *link);
|
||||
|
||||
int manager_save(Manager *m);
|
Reference in New Issue
Block a user