mirror of
https://github.com/systemd/systemd.git
synced 2025-02-23 13:57:33 +03:00
wait-online: wait for address family
This introduce -4 and -6 commandline options.
This commit is contained in:
parent
bbea881312
commit
6dc4531d16
@ -85,6 +85,34 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-4</option></term>
|
||||
<term><option>--ipv4</option></term>
|
||||
|
||||
<listitem><para>Waiting for an IPv4 address of each network interface to be configured. If this
|
||||
option is specified with <option>--any</option>, then
|
||||
<command>systemd-networkd-wait-online</command> exits with success when at least one interface
|
||||
becomes online and has an IPv4 address. The option is applied only for the operational state
|
||||
<literal>degraded</literal> or above. If neither <option>--ipv4</option> nor
|
||||
<option>--ipv6</option> is specified, then the value from
|
||||
<varname>RequiredFamilyForOnline=</varname> in the corresponding <filename>.network</filename>
|
||||
file is used if present.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-6</option></term>
|
||||
<term><option>--ipv6</option></term>
|
||||
|
||||
<listitem><para>Waiting for an IPv6 address of each network interface to be configured. If this
|
||||
option is specified with <option>--any</option>, then
|
||||
<command>systemd-networkd-wait-online</command> exits with success when at least one interface
|
||||
becomes online and has an IPv6 address. The option is applied only for the operational state
|
||||
<literal>degraded</literal> or above. If neither <option>--ipv4</option> nor
|
||||
<option>--ipv6</option> is specified, then the value from
|
||||
<varname>RequiredFamilyForOnline=</varname> in the corresponding <filename>.network</filename>
|
||||
file is used if present.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--any</option></term>
|
||||
|
||||
|
@ -97,7 +97,8 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
|
||||
}
|
||||
|
||||
int link_update_monitor(Link *l) {
|
||||
_cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL;
|
||||
_cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *required_family = NULL,
|
||||
*ipv4_address_state = NULL, *ipv6_address_state = NULL, *state = NULL;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(l);
|
||||
@ -135,6 +136,47 @@ int link_update_monitor(Link *l) {
|
||||
l->operational_state = s;
|
||||
}
|
||||
|
||||
r = sd_network_link_get_required_family_for_online(l->ifindex, &required_family);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, r, "Failed to get required address family, ignoring: %m");
|
||||
else if (isempty(required_family))
|
||||
l->required_family = ADDRESS_FAMILY_NO;
|
||||
else {
|
||||
AddressFamily f;
|
||||
|
||||
f = link_required_address_family_from_string(required_family);
|
||||
if (f < 0)
|
||||
ret = log_link_debug_errno(l, f, "Failed to parse required address family, ignoring: %m");
|
||||
else
|
||||
l->required_family = f;
|
||||
}
|
||||
|
||||
r = sd_network_link_get_ipv4_address_state(l->ifindex, &ipv4_address_state);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, r, "Failed to get IPv4 address state, ignoring: %m");
|
||||
else {
|
||||
LinkAddressState s;
|
||||
|
||||
s = link_address_state_from_string(ipv4_address_state);
|
||||
if (s < 0)
|
||||
ret = log_link_debug_errno(l, s, "Failed to parse IPv4 address state, ignoring: %m");
|
||||
else
|
||||
l->ipv4_address_state = s;
|
||||
}
|
||||
|
||||
r = sd_network_link_get_ipv6_address_state(l->ifindex, &ipv6_address_state);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, r, "Failed to get IPv6 address state, ignoring: %m");
|
||||
else {
|
||||
LinkAddressState s;
|
||||
|
||||
s = link_address_state_from_string(ipv6_address_state);
|
||||
if (s < 0)
|
||||
ret = log_link_debug_errno(l, s, "Failed to parse IPv6 address state, ignoring: %m");
|
||||
else
|
||||
l->ipv6_address_state = s;
|
||||
}
|
||||
|
||||
r = sd_network_link_get_setup_state(l->ifindex, &state);
|
||||
if (r < 0)
|
||||
ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m");
|
||||
|
@ -19,6 +19,9 @@ struct Link {
|
||||
bool required_for_online;
|
||||
LinkOperationalStateRange required_operstate;
|
||||
LinkOperationalState operational_state;
|
||||
AddressFamily required_family;
|
||||
LinkAddressState ipv4_address_state;
|
||||
LinkAddressState ipv6_address_state;
|
||||
char *state;
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,13 @@ static bool manager_ignore_link(Manager *m, Link *link) {
|
||||
}
|
||||
|
||||
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange s) {
|
||||
AddressFamily required_family;
|
||||
bool needs_ipv4;
|
||||
bool needs_ipv6;
|
||||
|
||||
assert(m);
|
||||
assert(l);
|
||||
|
||||
/* This returns the following:
|
||||
* -EAGAIN: not processed by udev or networkd
|
||||
* 0: operstate is not enough
|
||||
@ -60,7 +67,35 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
|
||||
return 0;
|
||||
}
|
||||
|
||||
required_family = m->required_family > 0 ? m->required_family : l->required_family;
|
||||
needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
|
||||
needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
|
||||
|
||||
if (s.min >= LINK_OPERSTATE_DEGRADED) {
|
||||
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED)
|
||||
goto ipv4_not_ready;
|
||||
|
||||
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED)
|
||||
goto ipv6_not_ready;
|
||||
}
|
||||
|
||||
if (s.min >= LINK_OPERSTATE_ROUTABLE) {
|
||||
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE)
|
||||
goto ipv4_not_ready;
|
||||
|
||||
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE)
|
||||
goto ipv6_not_ready;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
ipv4_not_ready:
|
||||
log_link_debug(l, "No routable or link-local IPv4 address is configured.");
|
||||
return 0;
|
||||
|
||||
ipv6_not_ready:
|
||||
log_link_debug(l, "No routable or link-local IPv6 address is configured.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool manager_configured(Manager *m) {
|
||||
@ -298,6 +333,7 @@ static int manager_network_monitor_listen(Manager *m) {
|
||||
|
||||
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
LinkOperationalStateRange required_operstate,
|
||||
AddressFamily required_family,
|
||||
bool any, usec_t timeout) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int r;
|
||||
@ -312,6 +348,7 @@ int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
.interfaces = interfaces,
|
||||
.ignore = ignore,
|
||||
.required_operstate = required_operstate,
|
||||
.required_family = required_family,
|
||||
.any = any,
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@ struct Manager {
|
||||
char **ignore;
|
||||
|
||||
LinkOperationalStateRange required_operstate;
|
||||
AddressFamily required_family;
|
||||
bool any;
|
||||
|
||||
sd_netlink *rtnl;
|
||||
@ -35,6 +36,7 @@ struct Manager {
|
||||
Manager* manager_free(Manager *m);
|
||||
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
LinkOperationalStateRange required_operstate,
|
||||
AddressFamily required_family,
|
||||
bool any, usec_t timeout);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
|
@ -19,6 +19,7 @@ static usec_t arg_timeout = 120 * USEC_PER_SEC;
|
||||
static Hashmap *arg_interfaces = NULL;
|
||||
static char **arg_ignore = NULL;
|
||||
static LinkOperationalStateRange arg_required_operstate = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
|
||||
static AddressFamily arg_required_family = ADDRESS_FAMILY_NO;
|
||||
static bool arg_any = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_freep);
|
||||
@ -42,6 +43,8 @@ static int help(void) {
|
||||
" --ignore=INTERFACE Don't take these interfaces into account\n"
|
||||
" -o --operational-state=MIN_OPERSTATE[:MAX_OPERSTATE]\n"
|
||||
" Required operational state\n"
|
||||
" -4 --ipv4 Requires at least one IPv4 address\n"
|
||||
" -6 --ipv6 Requires at least one IPv6 address\n"
|
||||
" --any Wait until at least one of the interfaces is online\n"
|
||||
" --timeout=SECS Maximum time to wait for network connectivity\n"
|
||||
"\nSee the %s for details.\n",
|
||||
@ -111,6 +114,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "ignore", required_argument, NULL, ARG_IGNORE },
|
||||
{ "operational-state", required_argument, NULL, 'o' },
|
||||
{ "ipv4", no_argument, NULL, '4' },
|
||||
{ "ipv6", no_argument, NULL, '6' },
|
||||
{ "any", no_argument, NULL, ARG_ANY },
|
||||
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
|
||||
{}
|
||||
@ -121,7 +126,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hi:qo:", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "hi:qo:46", options, NULL)) >= 0)
|
||||
|
||||
switch (c) {
|
||||
|
||||
@ -159,6 +164,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '4':
|
||||
arg_required_family |= ADDRESS_FAMILY_IPV4;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
arg_required_family |= ADDRESS_FAMILY_IPV6;
|
||||
break;
|
||||
|
||||
case ARG_ANY:
|
||||
arg_any = true;
|
||||
break;
|
||||
@ -197,7 +211,7 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
|
||||
|
||||
r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_any, arg_timeout);
|
||||
r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_required_family, arg_any, arg_timeout);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not create manager: %m");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user