1
0
mirror of https://github.com/systemd/systemd synced 2026-04-13 10:35:08 +02:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Yu Watanabe
9e3e592946
Merge pull request #22098 from DaanDeMeyer/journal-corrupt-2
journal: Fixes for handling of corrupt entry objects
2022-01-14 21:23:32 +09:00
Yu Watanabe
ba3440b9ab
Merge pull request #22096 from keszybz/networkctl-bus-once
Open the bus once in networkctl
2022-01-14 21:21:08 +09:00
Daan De Meyer
8d801e35cb journal: Fix entry array iteration corruption checks
Previously, we'd try to handle corruption by bumping the index even
if it was an entry array object that was corrupted (which we can't
deal with).

Now, we only try to deal with corrupted entry objects by moving the
corruption handling into generic_array_get().

On top, we also add an additional check for -EADDRNOTAVAIL which can
also be caused by corrupted journal data.
2022-01-14 11:33:32 +00:00
Evgeny Vereshchagin
9e360c6bf1 ci: switch to requirements.txt in the unit tests workflow 2022-01-14 10:29:23 +00:00
Zbigniew Jędrzejewski-Szmek
100433e05a networkctl: use xsprintf a bit more 2022-01-14 16:24:27 +09:00
Zbigniew Jędrzejewski-Szmek
d821e40ca9 networkctl: open the bus just once
We'd connect to the bus twice: the first time to check networkd namespace,
and then the second time to do the deed we were asked to do. It's nicer
to open the bus just once, for efficience and also to avoid the open call
in all functions.

An ASSERT_PTR helper is added:
- sd_bus *bus = userdata;
  ...
- assert(bus);
+ sd_bus *bus = ASSERT_PTR(userdata);
  ...

It can be used in other place too, but I'm leaving that for a later
refactoring.
2022-01-14 16:24:04 +09:00
Benjamin Berg
048d469999 man: Add more details about desktop file processing
In particular, mention the contract the generator has with external
ExecCondition= binaries that may be provided by desktop environments.

But, also mention all the other relevant keys. In particular
X-systemd-skip= is important to be documented.
2022-01-14 16:20:45 +09:00
Daan De Meyer
f2eceb5268 journal: Remove unused arguments from journal_file_next_entry_for_data() 2022-01-12 17:31:57 +00:00
8 changed files with 182 additions and 169 deletions

View File

@ -48,6 +48,7 @@ for phase in "${PHASES[@]}"; do
apt-get -y update apt-get -y update
apt-get -y build-dep systemd apt-get -y build-dep systemd
apt-get -y install "${ADDITIONAL_DEPS[@]}" apt-get -y install "${ADDITIONAL_DEPS[@]}"
pip3 install -r .github/workflows/requirements.txt --require-hashes
;; ;;
RUN|RUN_GCC|RUN_CLANG) RUN|RUN_GCC|RUN_CLANG)
if [[ "$phase" = "RUN_CLANG" ]]; then if [[ "$phase" = "RUN_CLANG" ]]; then

View File

@ -41,6 +41,55 @@
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry> <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for more details.</para> for more details.</para>
<para>XDG autostart may be conditionalized using both standardized and non-standardized keys.
In order to handle these, the generator may create one or more <varname>ExecCondition=</varname> entries.
For non-standardized keys, well-known helper binaries provided by Desktop Environments are used.
All external helpers <emphasis>must</emphasis> detect their corresponding desktop environment and
<emphasis>must</emphasis> return success when run in a different environment.
This is important as all <varname>ExecCondition=</varname> directives must succeed for an application to be started.</para>
<table>
<title>
Special XDG desktop file entries that are processed
</title>
<tgroup cols='2'>
<colspec colname='entry' />
<colspec colname='handling' />
<thead>
<row>
<entry>Entry</entry>
<entry>Handling</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>Hidden=</varname>, <varname>X-systemd-skip=</varname></entry>
<entry>No service will be generated if set to true</entry>
</row>
<row>
<entry><varname>OnlyShowIn=</varname>, <varname>NotShowIn=</varname></entry>
<entry><varname>ExecCondition=</varname> using <filename>systemd-xdg-autostart-condition</filename></entry>
</row>
<row>
<entry><varname>TryExec=</varname></entry>
<entry>No service will be generated if the binary does not exist or cannot be executed</entry>
</row>
<row>
<entry><varname>AutostartCondition=</varname> (GNOME extension)</entry>
<entry><varname>ExecCondition=</varname> using <filename>gnome-systemd-autostart-condition</filename></entry>
</row>
<row>
<entry><varname>X-GNOME-Autostart-Phase=</varname></entry>
<entry>No service will be generated if set to any value</entry>
</row>
<row>
<entry><varname>X-KDE-autostart-condition=</varname></entry>
<entry><varname>ExecCondition=</varname> using <filename>kde-systemd-start-condition</filename></entry>
</row>
</tbody>
</tgroup>
</table>
<para><filename>systemd-xdg-autostart-generator</filename> implements <para><filename>systemd-xdg-autostart-generator</filename> implements
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
</refsect1> </refsect1>

View File

@ -66,6 +66,14 @@
#define free(a) FreePool(a) #define free(a) FreePool(a)
#endif #endif
/* This passes the argument through after (if asserts are enabled) checking that it is not null. */
#define ASSERT_PTR(expr) \
({ \
typeof(expr) _expr_ = (expr); \
assert(_expr_); \
_expr_; \
})
#if defined(static_assert) #if defined(static_assert)
#define assert_cc(expr) \ #define assert_cc(expr) \
static_assert(expr, #expr) static_assert(expr, #expr)

View File

@ -76,17 +76,17 @@ static void test_non_empty(void) {
assert_se(le64toh(o->entry.seqnum) == 1); assert_se(le64toh(o->entry.seqnum) == 1);
assert_se(journal_file_find_data_object(f->file, test, strlen(test), NULL, &p) == 1); assert_se(journal_file_find_data_object(f->file, test, strlen(test), NULL, &p) == 1);
assert_se(journal_file_next_entry_for_data(f->file, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); assert_se(journal_file_next_entry_for_data(f->file, p, DIRECTION_DOWN, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 1); assert_se(le64toh(o->entry.seqnum) == 1);
assert_se(journal_file_next_entry_for_data(f->file, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); assert_se(journal_file_next_entry_for_data(f->file, p, DIRECTION_UP, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 3); assert_se(le64toh(o->entry.seqnum) == 3);
assert_se(journal_file_find_data_object(f->file, test2, strlen(test2), NULL, &p) == 1); assert_se(journal_file_find_data_object(f->file, test2, strlen(test2), NULL, &p) == 1);
assert_se(journal_file_next_entry_for_data(f->file, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); assert_se(journal_file_next_entry_for_data(f->file, p, DIRECTION_UP, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 2); assert_se(le64toh(o->entry.seqnum) == 2);
assert_se(journal_file_next_entry_for_data(f->file, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); assert_se(journal_file_next_entry_for_data(f->file, p, DIRECTION_DOWN, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 2); assert_se(le64toh(o->entry.seqnum) == 2);
assert_se(journal_file_find_data_object(f->file, "quux", 4, NULL, &p) == 0); assert_se(journal_file_find_data_object(f->file, "quux", 4, NULL, &p) == 0);

View File

@ -2099,14 +2099,35 @@ static void chain_cache_put(
ci->last_index = last_index; ci->last_index = last_index;
} }
static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
assert(i);
/* Increase or decrease the specified index, in the right direction. */
if (direction == DIRECTION_DOWN) {
if (*i >= n - 1)
return 0;
(*i)++;
} else {
if (*i <= 0)
return 0;
(*i)--;
}
return 1;
}
static int generic_array_get( static int generic_array_get(
JournalFile *f, JournalFile *f,
uint64_t first, uint64_t first,
uint64_t i, uint64_t i,
direction_t direction,
Object **ret, uint64_t *ret_offset) { Object **ret, uint64_t *ret_offset) {
Object *o; Object *o, *e;
uint64_t p = 0, a, t = 0; uint64_t p = 0, a, t = 0, k;
int r; int r;
ChainCacheItem *ci; ChainCacheItem *ci;
@ -2123,35 +2144,64 @@ static int generic_array_get(
} }
while (a > 0) { while (a > 0) {
uint64_t k;
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
if (r < 0) if (r < 0)
return r; return r;
k = journal_file_entry_array_n_items(o); k = journal_file_entry_array_n_items(o);
if (i < k) { if (i < k)
p = le64toh(o->entry_array.items[i]); break;
goto found;
}
i -= k; i -= k;
t += k; t += k;
a = le64toh(o->entry_array.next_entry_array_offset); a = le64toh(o->entry_array.next_entry_array_offset);
} }
/* If we've found the right location, now look for the first non-corrupt entry object (in the right
* direction). */
while (a > 0) {
/* In the first iteration of the while loop, we reuse i, k and o from the previous while
* loop. */
if (i == UINT64_MAX) {
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
if (r < 0)
return r;
k = journal_file_entry_array_n_items(o);
if (k == 0)
break;
i = direction == DIRECTION_DOWN ? 0 : k - 1;
}
do {
p = le64toh(o->entry_array.items[i]);
r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &e);
if (r >= 0)
goto found;
if (!IN_SET(r, -EADDRNOTAVAIL, -EBADMSG))
return r;
/* OK, so this entry is borked. Most likely some entry didn't get synced to
* disk properly, let's see if the next one might work for us instead. */
log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i);
} while (bump_array_index(&i, direction, k) > 0);
t += k;
a = le64toh(o->entry_array.next_entry_array_offset);
i = UINT64_MAX;
}
return 0; return 0;
found: found:
/* Let's cache this item for the next invocation */ /* Let's cache this item for the next invocation */
chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i); chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i);
r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
if (r < 0)
return r;
if (ret) if (ret)
*ret = o; *ret = e;
if (ret_offset) if (ret_offset)
*ret_offset = p; *ret_offset = p;
@ -2164,16 +2214,18 @@ static int generic_array_get_plus_one(
uint64_t extra, uint64_t extra,
uint64_t first, uint64_t first,
uint64_t i, uint64_t i,
direction_t direction,
Object **ret, uint64_t *ret_offset) { Object **ret, uint64_t *ret_offset) {
Object *o; Object *o;
int r;
assert(f); assert(f);
if (i == 0) { if (i == 0) {
int r;
r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG))
return generic_array_get(f, first, 0, direction, ret, ret_offset);
if (r < 0) if (r < 0)
return r; return r;
@ -2186,7 +2238,7 @@ static int generic_array_get_plus_one(
return 1; return 1;
} }
return generic_array_get(f, first, i-1, ret, ret_offset); return generic_array_get(f, first, i - 1, direction, ret, ret_offset);
} }
enum { enum {
@ -2710,25 +2762,6 @@ int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
return CMP(af->current_xor_hash, bf->current_xor_hash); return CMP(af->current_xor_hash, bf->current_xor_hash);
} }
static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
/* Increase or decrease the specified index, in the right direction. */
if (direction == DIRECTION_DOWN) {
if (*i >= n - 1)
return 0;
(*i) ++;
} else {
if (*i <= 0)
return 0;
(*i) --;
}
return 1;
}
static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) { static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) {
/* Consider it an error if any of the two offsets is uninitialized */ /* Consider it an error if any of the two offsets is uninitialized */
@ -2777,24 +2810,9 @@ int journal_file_next_entry(
} }
/* And jump to it */ /* And jump to it */
for (;;) { r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret, &ofs);
r = generic_array_get(f,
le64toh(f->header->entry_array_offset),
i,
ret, &ofs);
if (r > 0)
break;
if (r != -EBADMSG)
return r;
/* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if
* the next one might work for us instead. */
log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i);
r = bump_array_index(&i, direction, n);
if (r <= 0) if (r <= 0)
return r; return r;
}
/* Ensure our array is properly ordered. */ /* Ensure our array is properly ordered. */
if (p > 0 && !check_properly_ordered(ofs, p, direction)) if (p > 0 && !check_properly_ordered(ofs, p, direction))
@ -2810,7 +2828,6 @@ int journal_file_next_entry(
int journal_file_next_entry_for_data( int journal_file_next_entry_for_data(
JournalFile *f, JournalFile *f,
Object *o, uint64_t p,
uint64_t data_offset, uint64_t data_offset,
direction_t direction, direction_t direction,
Object **ret, uint64_t *ret_offset) { Object **ret, uint64_t *ret_offset) {
@ -2820,7 +2837,6 @@ int journal_file_next_entry_for_data(
int r; int r;
assert(f); assert(f);
assert(p > 0 || !o);
r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
if (r < 0) if (r < 0)
@ -2830,53 +2846,16 @@ int journal_file_next_entry_for_data(
if (n <= 0) if (n <= 0)
return n; return n;
if (!o)
i = direction == DIRECTION_DOWN ? 0 : n - 1; i = direction == DIRECTION_DOWN ? 0 : n - 1;
else {
if (o->object.type != OBJECT_ENTRY)
return -EINVAL;
r = generic_array_bisect_plus_one(f,
le64toh(d->data.entry_offset),
le64toh(d->data.entry_array_offset),
le64toh(d->data.n_entries),
p,
test_object_offset,
DIRECTION_DOWN,
NULL, NULL,
&i);
if (r <= 0)
return r;
r = bump_array_index(&i, direction, n);
if (r <= 0)
return r;
}
for (;;) {
r = generic_array_get_plus_one(f, r = generic_array_get_plus_one(f,
le64toh(d->data.entry_offset), le64toh(d->data.entry_offset),
le64toh(d->data.entry_array_offset), le64toh(d->data.entry_array_offset),
i, i,
direction,
ret, &ofs); ret, &ofs);
if (r > 0)
break;
if (r != -EBADMSG)
return r;
log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i);
r = bump_array_index(&i, direction, n);
if (r <= 0) if (r <= 0)
return r; return r;
}
/* Ensure our array is properly ordered. */
if (p > 0 && check_properly_ordered(ofs, p, direction))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"%s data entry array not properly ordered at entry %" PRIu64,
f->path, i);
if (ret_offset) if (ret_offset)
*ret_offset = ofs; *ret_offset = ofs;
@ -3820,6 +3799,7 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u
le64toh(o->data.entry_offset), le64toh(o->data.entry_offset),
le64toh(o->data.entry_array_offset), le64toh(o->data.entry_array_offset),
le64toh(o->data.n_entries) - 1, le64toh(o->data.n_entries) - 1,
DIRECTION_UP,
&o, NULL); &o, NULL);
if (r <= 0) if (r <= 0)
return r; return r;

View File

@ -214,7 +214,7 @@ void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
int journal_file_compare_locations(JournalFile *af, JournalFile *bf); int journal_file_compare_locations(JournalFile *af, JournalFile *bf);
int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset); int journal_file_next_entry_for_data(JournalFile *f, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);

View File

@ -611,9 +611,9 @@ static int find_location_for_match(
/* FIXME: missing: find by monotonic */ /* FIXME: missing: find by monotonic */
if (j->current_location.type == LOCATION_HEAD) if (j->current_location.type == LOCATION_HEAD)
return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset); return journal_file_next_entry_for_data(f, dp, DIRECTION_DOWN, ret, offset);
if (j->current_location.type == LOCATION_TAIL) if (j->current_location.type == LOCATION_TAIL)
return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset); return journal_file_next_entry_for_data(f, dp, DIRECTION_UP, ret, offset);
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset); return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset);
if (j->current_location.monotonic_set) { if (j->current_location.monotonic_set) {
@ -624,7 +624,7 @@ static int find_location_for_match(
if (j->current_location.realtime_set) if (j->current_location.realtime_set)
return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset); return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset);
return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset); return journal_file_next_entry_for_data(f, dp, direction, ret, offset);
} else if (m->type == MATCH_OR_TERM) { } else if (m->type == MATCH_OR_TERM) {
uint64_t np = 0; uint64_t np = 0;

View File

@ -79,17 +79,12 @@ static bool arg_full = false;
static unsigned arg_lines = 10; static unsigned arg_lines = 10;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static int get_description(JsonVariant **ret) { static int get_description(sd_bus *bus, JsonVariant **ret) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *text = NULL; const char *text = NULL;
int r; int r;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
r = bus_call_method(bus, bus_network_mgr, "Describe", &error, &reply, NULL); r = bus_call_method(bus, bus_network_mgr, "Describe", &error, &reply, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to get description: %s", bus_error_message(&error, r)); return log_error_errno(r, "Failed to get description: %s", bus_error_message(&error, r));
@ -105,11 +100,11 @@ static int get_description(JsonVariant **ret) {
return 0; return 0;
} }
static int dump_manager_description(void) { static int dump_manager_description(sd_bus *bus) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL; _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
int r; int r;
r = get_description(&v); r = get_description(bus, &v);
if (r < 0) if (r < 0)
return r; return r;
@ -117,14 +112,14 @@ static int dump_manager_description(void) {
return 0; return 0;
} }
static int dump_link_description(char **patterns) { static int dump_link_description(sd_bus *bus, char **patterns) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL; _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
_cleanup_free_ bool *matched_patterns = NULL; _cleanup_free_ bool *matched_patterns = NULL;
JsonVariant *i; JsonVariant *i;
size_t c = 0; size_t c = 0;
int r; int r;
r = get_description(&v); r = get_description(bus, &v);
if (r < 0) if (r < 0)
return r; return r;
@ -618,11 +613,12 @@ static int link_get_property(
sd_bus_message **reply, sd_bus_message **reply,
const char *iface, const char *iface,
const char *propname) { const char *propname) {
_cleanup_free_ char *path = NULL, *ifindex_str = NULL;
char ifindex_str[DECIMAL_STR_MAX(int)];
_cleanup_free_ char *path = NULL;
int r; int r;
if (asprintf(&ifindex_str, "%i", link->ifindex) < 0) xsprintf(ifindex_str, "%i", link->ifindex);
return -ENOMEM;
r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex_str, &path); r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex_str, &path);
if (r < 0) if (r < 0)
@ -790,6 +786,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
} }
static int list_links(int argc, char *argv[], void *userdata) { static int list_links(int argc, char *argv[], void *userdata) {
sd_bus *bus = ASSERT_PTR(userdata);
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(link_info_array_freep) LinkInfo *links = NULL; _cleanup_(link_info_array_freep) LinkInfo *links = NULL;
_cleanup_(table_unrefp) Table *table = NULL; _cleanup_(table_unrefp) Table *table = NULL;
@ -798,9 +795,9 @@ static int list_links(int argc, char *argv[], void *userdata) {
if (arg_json_format_flags != JSON_FORMAT_OFF) { if (arg_json_format_flags != JSON_FORMAT_OFF) {
if (arg_all || argc <= 1) if (arg_all || argc <= 1)
return dump_manager_description(); return dump_manager_description(bus);
else else
return dump_link_description(strv_skip(argv, 1)); return dump_link_description(bus, strv_skip(argv, 1));
} }
r = sd_netlink_open(&rtnl); r = sd_netlink_open(&rtnl);
@ -1223,12 +1220,10 @@ static int list_address_labels(int argc, char *argv[], void *userdata) {
} }
static int open_lldp_neighbors(int ifindex, FILE **ret) { static int open_lldp_neighbors(int ifindex, FILE **ret) {
_cleanup_free_ char *p = NULL; char p[STRLEN("/run/systemd/netif/lldp/") + DECIMAL_STR_MAX(int)];
FILE *f; FILE *f;
if (asprintf(&p, "/run/systemd/netif/lldp/%i", ifindex) < 0) xsprintf(p, "/run/systemd/netif/lldp/%i", ifindex);
return -ENOMEM;
f = fopen(p, "re"); f = fopen(p, "re");
if (!f) if (!f)
return -errno; return -errno;
@ -1556,7 +1551,7 @@ static int link_status_one(
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL; _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL;
_cleanup_free_ char *t = NULL, *network = NULL, *iaid = NULL, *duid = NULL, _cleanup_free_ char *t = NULL, *network = NULL, *iaid = NULL, *duid = NULL,
*setup_state = NULL, *operational_state = NULL, *online_state = NULL, *lease_file = NULL, *activation_policy = NULL; *setup_state = NULL, *operational_state = NULL, *online_state = NULL, *activation_policy = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL, const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL,
*on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup, *on_color_online; *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup, *on_color_online;
_cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL; _cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
@ -1606,8 +1601,8 @@ static int link_status_one(
(void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to); (void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to);
(void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by); (void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by);
if (asprintf(&lease_file, "/run/systemd/netif/leases/%d", info->ifindex) < 0) char lease_file[STRLEN("/run/systemd/netif/leases/") + DECIMAL_STR_MAX(int)];
return log_oom(); xsprintf(lease_file, "/run/systemd/netif/leases/%i", info->ifindex);
(void) dhcp_lease_load(&lease, lease_file); (void) dhcp_lease_load(&lease, lease_file);
@ -2383,7 +2378,7 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
} }
static int link_status(int argc, char *argv[], void *userdata) { static int link_status(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; sd_bus *bus = ASSERT_PTR(userdata);
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
_cleanup_(link_info_array_freep) LinkInfo *links = NULL; _cleanup_(link_info_array_freep) LinkInfo *links = NULL;
@ -2391,17 +2386,13 @@ static int link_status(int argc, char *argv[], void *userdata) {
if (arg_json_format_flags != JSON_FORMAT_OFF) { if (arg_json_format_flags != JSON_FORMAT_OFF) {
if (arg_all || argc <= 1) if (arg_all || argc <= 1)
return dump_manager_description(); return dump_manager_description(bus);
else else
return dump_link_description(strv_skip(argv, 1)); return dump_link_description(bus, strv_skip(argv, 1));
} }
pager_open(arg_pager_flags); pager_open(arg_pager_flags);
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
r = sd_netlink_open(&rtnl); r = sd_netlink_open(&rtnl);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m"); return log_error_errno(r, "Failed to connect to netlink: %m");
@ -2738,14 +2729,10 @@ static int link_renew_one(sd_bus *bus, int index, const char *name) {
} }
static int link_renew(int argc, char *argv[], void *userdata) { static int link_renew(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; sd_bus *bus = ASSERT_PTR(userdata);
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int index, k = 0, r; int index, k = 0, r;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0) if (index < 0)
@ -2772,14 +2759,10 @@ static int link_force_renew_one(sd_bus *bus, int index, const char *name) {
} }
static int link_force_renew(int argc, char *argv[], void *userdata) { static int link_force_renew(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; sd_bus *bus = ASSERT_PTR(userdata);
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int k = 0, r; int k = 0, r;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
int index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); int index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0) if (index < 0)
@ -2794,14 +2777,10 @@ static int link_force_renew(int argc, char *argv[], void *userdata) {
} }
static int verb_reload(int argc, char *argv[], void *userdata) { static int verb_reload(int argc, char *argv[], void *userdata) {
sd_bus *bus = ASSERT_PTR(userdata);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r; int r;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
r = bus_call_method(bus, bus_network_mgr, "Reload", &error, NULL, NULL); r = bus_call_method(bus, bus_network_mgr, "Reload", &error, NULL, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to reload network settings: %m"); return log_error_errno(r, "Failed to reload network settings: %m");
@ -2810,17 +2789,13 @@ static int verb_reload(int argc, char *argv[], void *userdata) {
} }
static int verb_reconfigure(int argc, char *argv[], void *userdata) { static int verb_reconfigure(int argc, char *argv[], void *userdata) {
sd_bus *bus = ASSERT_PTR(userdata);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_set_free_ Set *indexes = NULL; _cleanup_set_free_ Set *indexes = NULL;
int index, r; int index, r;
void *p; void *p;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
indexes = set_new(NULL); indexes = set_new(NULL);
if (!indexes) if (!indexes)
return log_oom(); return log_oom();
@ -2968,7 +2943,7 @@ static int parse_argv(int argc, char *argv[]) {
return 1; return 1;
} }
static int networkctl_main(int argc, char *argv[]) { static int networkctl_main(sd_bus *bus, int argc, char *argv[]) {
static const Verb verbs[] = { static const Verb verbs[] = {
{ "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links }, { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
{ "status", VERB_ANY, VERB_ANY, 0, link_status }, { "status", VERB_ANY, VERB_ANY, 0, link_status },
@ -2984,20 +2959,15 @@ static int networkctl_main(int argc, char *argv[]) {
{} {}
}; };
return dispatch_verb(argc, argv, verbs, NULL); return dispatch_verb(argc, argv, verbs, bus);
} }
static int check_netns_match(void) { static int check_netns_match(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
struct stat st; struct stat st;
uint64_t id; uint64_t id;
int r; int r;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
r = sd_bus_get_property_trivial( r = sd_bus_get_property_trivial(
bus, bus,
"org.freedesktop.network1", "org.freedesktop.network1",
@ -3035,6 +3005,7 @@ static void warn_networkd_missing(void) {
} }
static int run(int argc, char* argv[]) { static int run(int argc, char* argv[]) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r; int r;
log_setup(); log_setup();
@ -3043,13 +3014,17 @@ static int run(int argc, char* argv[]) {
if (r <= 0) if (r <= 0)
return r; return r;
r = check_netns_match(); r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
r = check_netns_match(bus);
if (r < 0) if (r < 0)
return r; return r;
warn_networkd_missing(); warn_networkd_missing();
return networkctl_main(argc, argv); return networkctl_main(bus, argc, argv);
} }
DEFINE_MAIN_FUNCTION(run); DEFINE_MAIN_FUNCTION(run);