1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "daemon-util.h"
10 #include "main-func.h"
12 #include "pretty-print.h"
13 #include "signal-util.h"
14 #include "socket-util.h"
17 static bool arg_quiet
= false;
18 static usec_t arg_timeout
= 120 * USEC_PER_SEC
;
19 static Hashmap
*arg_interfaces
= NULL
;
20 static char **arg_ignore
= NULL
;
21 static LinkOperationalStateRange arg_required_operstate
= { _LINK_OPERSTATE_INVALID
, _LINK_OPERSTATE_INVALID
};
22 static AddressFamily arg_required_family
= ADDRESS_FAMILY_NO
;
23 static bool arg_any
= false;
25 STATIC_DESTRUCTOR_REGISTER(arg_interfaces
, hashmap_free_free_freep
);
26 STATIC_DESTRUCTOR_REGISTER(arg_ignore
, strv_freep
);
28 static int help(void) {
29 _cleanup_free_
char *link
= NULL
;
32 r
= terminal_urlify_man("systemd-networkd-wait-online.service", "8", &link
);
36 printf("%s [OPTIONS...]\n\n"
37 "Block until network is configured.\n\n"
38 " -h --help Show this help\n"
39 " --version Print version string\n"
40 " -q --quiet Do not show status information\n"
41 " -i --interface=INTERFACE[:MIN_OPERSTATE[:MAX_OPERSTATE]]\n"
42 " Block until at least these interfaces have appeared\n"
43 " --ignore=INTERFACE Don't take these interfaces into account\n"
44 " -o --operational-state=MIN_OPERSTATE[:MAX_OPERSTATE]\n"
45 " Required operational state\n"
46 " -4 --ipv4 Requires at least one IPv4 address\n"
47 " -6 --ipv6 Requires at least one IPv6 address\n"
48 " --any Wait until at least one of the interfaces is online\n"
49 " --timeout=SECS Maximum time to wait for network connectivity\n"
50 "\nSee the %s for details.\n",
51 program_invocation_short_name
,
57 static int parse_interface_with_operstate_range(const char *str
) {
58 _cleanup_free_
char *ifname
= NULL
;
59 _cleanup_free_ LinkOperationalStateRange
*range
= NULL
;
65 range
= new(LinkOperationalStateRange
, 1);
71 r
= parse_operational_state_range(p
+ 1, range
);
73 log_error_errno(r
, "Invalid operational state range '%s'", p
+ 1);
75 ifname
= strndup(optarg
, p
- optarg
);
77 range
->min
= _LINK_OPERSTATE_INVALID
;
78 range
->max
= _LINK_OPERSTATE_INVALID
;
84 if (!ifname_valid(ifname
))
85 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
86 "Invalid interface name '%s'", ifname
);
88 r
= hashmap_ensure_put(&arg_interfaces
, &string_hash_ops
, ifname
, TAKE_PTR(range
));
92 return log_error_errno(r
, "Failed to store interface name: %m");
94 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
95 "Interface name %s is already specified", ifname
);
101 static int parse_argv(int argc
, char *argv
[]) {
110 static const struct option options
[] = {
111 { "help", no_argument
, NULL
, 'h' },
112 { "version", no_argument
, NULL
, ARG_VERSION
},
113 { "quiet", no_argument
, NULL
, 'q' },
114 { "interface", required_argument
, NULL
, 'i' },
115 { "ignore", required_argument
, NULL
, ARG_IGNORE
},
116 { "operational-state", required_argument
, NULL
, 'o' },
117 { "ipv4", no_argument
, NULL
, '4' },
118 { "ipv6", no_argument
, NULL
, '6' },
119 { "any", no_argument
, NULL
, ARG_ANY
},
120 { "timeout", required_argument
, NULL
, ARG_TIMEOUT
},
129 while ((c
= getopt_long(argc
, argv
, "hi:qo:46", options
, NULL
)) >= 0)
145 r
= parse_interface_with_operstate_range(optarg
);
151 if (strv_extend(&arg_ignore
, optarg
) < 0)
157 LinkOperationalStateRange range
;
159 r
= parse_operational_state_range(optarg
, &range
);
161 return log_error_errno(r
, "Invalid operational state range '%s'", optarg
);
163 arg_required_operstate
= range
;
169 arg_required_family
|= ADDRESS_FAMILY_IPV4
;
173 arg_required_family
|= ADDRESS_FAMILY_IPV6
;
181 r
= parse_sec(optarg
, &arg_timeout
);
190 assert_not_reached("Unhandled option");
196 static int run(int argc
, char *argv
[]) {
197 _cleanup_(manager_freep
) Manager
*m
= NULL
;
198 _cleanup_(notify_on_cleanup
) const char *notify_message
= NULL
;
205 r
= parse_argv(argc
, argv
);
210 log_set_max_level(LOG_ERR
);
212 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
214 r
= manager_new(&m
, arg_interfaces
, arg_ignore
, arg_required_operstate
, arg_required_family
, arg_any
, arg_timeout
);
216 return log_error_errno(r
, "Could not create manager: %m");
218 if (manager_configured(m
))
221 notify_message
= notify_start("READY=1\n"
222 "STATUS=Waiting for network connections...",
223 "STATUS=Failed to wait for network connectivity...");
225 r
= sd_event_loop(m
->event
);
227 return log_error_errno(r
, "Event loop failed: %m");
230 notify_message
= "STATUS=All interfaces configured...";
235 DEFINE_MAIN_FUNCTION(run
);