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 bool arg_any
= false;
24 STATIC_DESTRUCTOR_REGISTER(arg_interfaces
, hashmap_free_free_freep
);
25 STATIC_DESTRUCTOR_REGISTER(arg_ignore
, strv_freep
);
27 static int help(void) {
28 _cleanup_free_
char *link
= NULL
;
31 r
= terminal_urlify_man("systemd-networkd-wait-online.service", "8", &link
);
35 printf("%s [OPTIONS...]\n\n"
36 "Block until network is configured.\n\n"
37 " -h --help Show this help\n"
38 " --version Print version string\n"
39 " -q --quiet Do not show status information\n"
40 " -i --interface=INTERFACE[:MIN_OPERSTATE[:MAX_OPERSTATE]]\n"
41 " Block until at least these interfaces have appeared\n"
42 " --ignore=INTERFACE Don't take these interfaces into account\n"
43 " -o --operational-state=MIN_OPERSTATE[:MAX_OPERSTATE]\n"
44 " Required operational state\n"
45 " --any Wait until at least one of the interfaces is online\n"
46 " --timeout=SECS Maximum time to wait for network connectivity\n"
47 "\nSee the %s for details.\n"
48 , program_invocation_short_name
55 static int parse_interface_with_operstate_range(const char *str
) {
56 _cleanup_free_
char *ifname
= NULL
;
57 _cleanup_free_ LinkOperationalStateRange
*range
;
63 range
= new(LinkOperationalStateRange
, 1);
69 r
= parse_operational_state_range(p
+ 1, range
);
71 log_error_errno(r
, "Invalid operational state range '%s'", p
+ 1);
73 ifname
= strndup(optarg
, p
- optarg
);
75 range
->min
= _LINK_OPERSTATE_INVALID
;
76 range
->max
= _LINK_OPERSTATE_INVALID
;
82 if (!ifname_valid(ifname
))
83 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
84 "Invalid interface name '%s'", ifname
);
86 r
= hashmap_ensure_allocated(&arg_interfaces
, &string_hash_ops
);
90 r
= hashmap_put(arg_interfaces
, 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 { "any", no_argument
, NULL
, ARG_ANY
},
118 { "timeout", required_argument
, NULL
, ARG_TIMEOUT
},
127 while ((c
= getopt_long(argc
, argv
, "hi:qo:", options
, NULL
)) >= 0)
143 r
= parse_interface_with_operstate_range(optarg
);
149 if (strv_extend(&arg_ignore
, optarg
) < 0)
155 LinkOperationalStateRange range
;
157 r
= parse_operational_state_range(optarg
, &range
);
159 return log_error_errno(r
, "Invalid operational state range '%s'", optarg
);
161 arg_required_operstate
= range
;
170 r
= parse_sec(optarg
, &arg_timeout
);
179 assert_not_reached("Unhandled option");
185 static int run(int argc
, char *argv
[]) {
186 _cleanup_(manager_freep
) Manager
*m
= NULL
;
187 _cleanup_(notify_on_cleanup
) const char *notify_message
= NULL
;
194 r
= parse_argv(argc
, argv
);
199 log_set_max_level(LOG_ERR
);
201 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
203 r
= manager_new(&m
, arg_interfaces
, arg_ignore
, arg_required_operstate
, arg_any
, arg_timeout
);
205 return log_error_errno(r
, "Could not create manager: %m");
207 if (manager_configured(m
))
210 notify_message
= notify_start("READY=1\n"
211 "STATUS=Waiting for network connections...",
212 "STATUS=Failed to wait for network connectivity...");
214 r
= sd_event_loop(m
->event
);
216 return log_error_errno(r
, "Event loop failed: %m");
219 notify_message
= "STATUS=All interfaces configured...";
224 DEFINE_MAIN_FUNCTION(run
);