mirror of
https://github.com/systemd/systemd
synced 2025-10-01 01:34:47 +02:00
Compare commits
53 Commits
ccb4072e21
...
b1b4e9204c
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b1b4e9204c | ||
![]() |
bb1296b55a | ||
![]() |
356b7a58f3 | ||
![]() |
3b4e3ebb51 | ||
![]() |
0a5393ad68 | ||
![]() |
9a9ca40803 | ||
![]() |
696e5a8a73 | ||
![]() |
a9a43d8aa2 | ||
![]() |
23220d8a00 | ||
![]() |
0addd9ba9c | ||
![]() |
7820a56ccb | ||
![]() |
b8f762f2fe | ||
![]() |
42b23010b9 | ||
![]() |
955b11ffd3 | ||
![]() |
9147b591a1 | ||
![]() |
7ef863a76a | ||
![]() |
fba3e94df5 | ||
![]() |
d8592a4e2f | ||
![]() |
2c42a217a2 | ||
![]() |
8900c05e6e | ||
![]() |
fc80ed5f97 | ||
![]() |
735a3d73b7 | ||
![]() |
4684ec5e3d | ||
![]() |
f5b7deb969 | ||
![]() |
15567b3a73 | ||
![]() |
cfb1a0e555 | ||
![]() |
425ac7a253 | ||
![]() |
36556f6e51 | ||
![]() |
fd421c4adc | ||
![]() |
75db809ae5 | ||
![]() |
13734c75b5 | ||
![]() |
b230baaeb7 | ||
![]() |
73c8cc7164 | ||
![]() |
99bfce1080 | ||
![]() |
f08231fe07 | ||
![]() |
6f8f8688e1 | ||
![]() |
ab4ab13c74 | ||
![]() |
809ceb8217 | ||
![]() |
b850a9b29f | ||
![]() |
5d160a2304 | ||
![]() |
1f38830153 | ||
![]() |
d3b56a0cad | ||
![]() |
450918d111 | ||
![]() |
a779cf30d2 | ||
![]() |
6aa601c56c | ||
![]() |
a16d732a51 | ||
![]() |
b70935ac65 | ||
![]() |
aaf057c4bb | ||
![]() |
79dd224093 | ||
![]() |
f4fca22ad4 | ||
![]() |
48ed276647 | ||
![]() |
deff68e718 | ||
![]() |
0e544221c9 |
@ -151,18 +151,18 @@ else {
|
||||
<function>poll()</function> and
|
||||
<function>sd_journal_process()</function> into one.</para>
|
||||
|
||||
<para><function>sd_journal_reliable_fd()</function> may be used to
|
||||
check whether the wakeup events from the file descriptor returned
|
||||
by <function>sd_journal_get_fd()</function> are known to be
|
||||
immediately triggered. On certain file systems where file change
|
||||
events from the OS are not available (such as NFS) changes need to
|
||||
be polled for repeatedly, and hence are detected only with a
|
||||
certain latency. This call will return a positive value if the
|
||||
journal changes are detected immediately and zero when they need
|
||||
to be polled for and hence might be noticed only with a certain
|
||||
latency. Note that there is usually no need to invoke this function
|
||||
directly as <function>sd_journal_get_timeout()</function> on these
|
||||
file systems will ask for timeouts explicitly anyway.</para>
|
||||
<para><function>sd_journal_reliable_fd()</function> may be used to check whether the wake-up events from
|
||||
the file descriptor returned by <function>sd_journal_get_fd()</function> are known to be quickly
|
||||
triggered. On certain file systems where file change events from the OS are not available (such as NFS)
|
||||
changes need to be polled for repeatedly, and hence are detected only with a considerable latency. This
|
||||
call will return a positive value if the journal changes are detected quickly and zero when they need to
|
||||
be polled for. Note that there is usually no need to invoke this function directly as
|
||||
<function>sd_journal_get_timeout()</function> will request appropriate timeouts anyway.</para>
|
||||
|
||||
<para>Note that all of the above change notification interfaces do not report changes
|
||||
instantly. Latencies are introduced for multiple reasons: as mentioned certain storage backends require
|
||||
time-based polling, in other cases wake-ups are optimized by coalescing events, and the OS introduces
|
||||
additional IO/CPU scheduling latencies.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -744,9 +744,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
<listitem><para>Configures IP masquerading for the network
|
||||
interface. If enabled, packets forwarded from the network
|
||||
interface will be appear as coming from the local host.
|
||||
Takes a boolean argument. Implies
|
||||
<varname>IPForward=ipv4</varname>. Defaults to
|
||||
<literal>no</literal>.</para></listitem>
|
||||
Takes one of <literal>ipv4</literal>, <literal>ipv6</literal>,
|
||||
<literal>both</literal>, <literal>no</literal>.
|
||||
The setting <literal>yes</literal> is the same as <literal>ipv4</literal> and not as
|
||||
<literal>both</literal>!
|
||||
Defaults to <literal>no</literal>.
|
||||
If enabled, this automatically sets <varname>IPForward</varname> to one of
|
||||
<literal>ipv4</literal>, <literal>ipv6</literal> or <literal>both</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>IPv6PrivacyExtensions=</varname></term>
|
||||
|
@ -92,7 +92,7 @@ static usec_t arg_base_time = USEC_INFINITY;
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
|
||||
|
||||
struct boot_times {
|
||||
typedef struct BootTimes {
|
||||
usec_t firmware_time;
|
||||
usec_t loader_time;
|
||||
usec_t kernel_time;
|
||||
@ -124,9 +124,9 @@ struct boot_times {
|
||||
* (so it is stored here for reference).
|
||||
*/
|
||||
usec_t reverse_offset;
|
||||
};
|
||||
} BootTimes;
|
||||
|
||||
struct unit_times {
|
||||
typedef struct UnitTimes {
|
||||
bool has_data;
|
||||
char *name;
|
||||
usec_t activating;
|
||||
@ -134,9 +134,9 @@ struct unit_times {
|
||||
usec_t deactivated;
|
||||
usec_t deactivating;
|
||||
usec_t time;
|
||||
};
|
||||
} UnitTimes;
|
||||
|
||||
struct host_info {
|
||||
typedef struct HostInfo {
|
||||
char *hostname;
|
||||
char *kernel_name;
|
||||
char *kernel_release;
|
||||
@ -144,7 +144,7 @@ struct host_info {
|
||||
char *os_pretty_name;
|
||||
char *virtualization;
|
||||
char *architecture;
|
||||
};
|
||||
} HostInfo;
|
||||
|
||||
static int acquire_bus(sd_bus **bus, bool *use_full_bus) {
|
||||
bool user = arg_scope != UNIT_FILE_SYSTEM;
|
||||
@ -209,19 +209,16 @@ static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_unit_start(const struct unit_times *a, const struct unit_times *b) {
|
||||
static int compare_unit_start(const UnitTimes *a, const UnitTimes *b) {
|
||||
return CMP(a->activating, b->activating);
|
||||
}
|
||||
|
||||
static void unit_times_free(struct unit_times *t) {
|
||||
struct unit_times *p;
|
||||
|
||||
for (p = t; p->has_data; p++)
|
||||
static UnitTimes* unit_times_free_array(UnitTimes *t) {
|
||||
for (UnitTimes *p = t; p && p->has_data; p++)
|
||||
free(p->name);
|
||||
free(t);
|
||||
return mfree(t);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct unit_times *, unit_times_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(UnitTimes*, unit_times_free_array);
|
||||
|
||||
static void subtract_timestamp(usec_t *a, usec_t b) {
|
||||
assert(a);
|
||||
@ -232,30 +229,30 @@ static void subtract_timestamp(usec_t *a, usec_t b) {
|
||||
}
|
||||
}
|
||||
|
||||
static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
|
||||
static int acquire_boot_times(sd_bus *bus, BootTimes **bt) {
|
||||
static const struct bus_properties_map property_map[] = {
|
||||
{ "FirmwareTimestampMonotonic", "t", NULL, offsetof(struct boot_times, firmware_time) },
|
||||
{ "LoaderTimestampMonotonic", "t", NULL, offsetof(struct boot_times, loader_time) },
|
||||
{ "KernelTimestamp", "t", NULL, offsetof(struct boot_times, kernel_time) },
|
||||
{ "InitRDTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_time) },
|
||||
{ "UserspaceTimestampMonotonic", "t", NULL, offsetof(struct boot_times, userspace_time) },
|
||||
{ "FinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, finish_time) },
|
||||
{ "SecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_start_time) },
|
||||
{ "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_finish_time) },
|
||||
{ "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_start_time) },
|
||||
{ "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_finish_time) },
|
||||
{ "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_start_time) },
|
||||
{ "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_finish_time) },
|
||||
{ "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_start_time) },
|
||||
{ "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_finish_time) },
|
||||
{ "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_start_time) },
|
||||
{ "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_finish_time) },
|
||||
{ "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_start_time) },
|
||||
{ "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_finish_time) },
|
||||
{ "FirmwareTimestampMonotonic", "t", NULL, offsetof(BootTimes, firmware_time) },
|
||||
{ "LoaderTimestampMonotonic", "t", NULL, offsetof(BootTimes, loader_time) },
|
||||
{ "KernelTimestamp", "t", NULL, offsetof(BootTimes, kernel_time) },
|
||||
{ "InitRDTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_time) },
|
||||
{ "UserspaceTimestampMonotonic", "t", NULL, offsetof(BootTimes, userspace_time) },
|
||||
{ "FinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, finish_time) },
|
||||
{ "SecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_start_time) },
|
||||
{ "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_finish_time) },
|
||||
{ "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_start_time) },
|
||||
{ "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_finish_time) },
|
||||
{ "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_start_time) },
|
||||
{ "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_finish_time) },
|
||||
{ "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_start_time) },
|
||||
{ "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_finish_time) },
|
||||
{ "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_start_time) },
|
||||
{ "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_finish_time) },
|
||||
{ "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_start_time) },
|
||||
{ "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_finish_time) },
|
||||
{},
|
||||
};
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
static struct boot_times times;
|
||||
static BootTimes times;
|
||||
static bool cached = false;
|
||||
int r;
|
||||
|
||||
@ -293,7 +290,7 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
|
||||
} else {
|
||||
/*
|
||||
* User-instance-specific or container-system-specific timestamps processing
|
||||
* (see comment to reverse_offset in struct boot_times).
|
||||
* (see comment to reverse_offset in BootTimes).
|
||||
*/
|
||||
times.reverse_offset = times.userspace_time;
|
||||
|
||||
@ -316,9 +313,9 @@ finish:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_host_info(struct host_info *hi) {
|
||||
static HostInfo* free_host_info(HostInfo *hi) {
|
||||
if (!hi)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
free(hi->hostname);
|
||||
free(hi->kernel_name);
|
||||
@ -327,23 +324,23 @@ static void free_host_info(struct host_info *hi) {
|
||||
free(hi->os_pretty_name);
|
||||
free(hi->virtualization);
|
||||
free(hi->architecture);
|
||||
free(hi);
|
||||
return mfree(hi);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info *, free_host_info);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(HostInfo *, free_host_info);
|
||||
|
||||
static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
static int acquire_time_data(sd_bus *bus, UnitTimes **out) {
|
||||
static const struct bus_properties_map property_map[] = {
|
||||
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activating) },
|
||||
{ "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activated) },
|
||||
{ "ActiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivating) },
|
||||
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivated) },
|
||||
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activating) },
|
||||
{ "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activated) },
|
||||
{ "ActiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivating) },
|
||||
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivated) },
|
||||
{},
|
||||
};
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(unit_times_freep) struct unit_times *unit_times = NULL;
|
||||
struct boot_times *boot_times = NULL;
|
||||
_cleanup_(unit_times_free_arrayp) UnitTimes *unit_times = NULL;
|
||||
BootTimes *boot_times = NULL;
|
||||
size_t allocated = 0, c = 0;
|
||||
UnitInfo u;
|
||||
int r;
|
||||
@ -361,7 +358,7 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
while ((r = bus_parse_unit_info(reply, &u)) > 0) {
|
||||
struct unit_times *t;
|
||||
UnitTimes *t;
|
||||
|
||||
if (!GREEDY_REALLOC(unit_times, allocated, c + 2))
|
||||
return log_oom();
|
||||
@ -414,28 +411,28 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
return c;
|
||||
}
|
||||
|
||||
static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
|
||||
static int acquire_host_info(sd_bus *bus, HostInfo **hi) {
|
||||
static const struct bus_properties_map hostname_map[] = {
|
||||
{ "Hostname", "s", NULL, offsetof(struct host_info, hostname) },
|
||||
{ "KernelName", "s", NULL, offsetof(struct host_info, kernel_name) },
|
||||
{ "KernelRelease", "s", NULL, offsetof(struct host_info, kernel_release) },
|
||||
{ "KernelVersion", "s", NULL, offsetof(struct host_info, kernel_version) },
|
||||
{ "OperatingSystemPrettyName", "s", NULL, offsetof(struct host_info, os_pretty_name) },
|
||||
{ "Hostname", "s", NULL, offsetof(HostInfo, hostname) },
|
||||
{ "KernelName", "s", NULL, offsetof(HostInfo, kernel_name) },
|
||||
{ "KernelRelease", "s", NULL, offsetof(HostInfo, kernel_release) },
|
||||
{ "KernelVersion", "s", NULL, offsetof(HostInfo, kernel_version) },
|
||||
{ "OperatingSystemPrettyName", "s", NULL, offsetof(HostInfo, os_pretty_name) },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct bus_properties_map manager_map[] = {
|
||||
{ "Virtualization", "s", NULL, offsetof(struct host_info, virtualization) },
|
||||
{ "Architecture", "s", NULL, offsetof(struct host_info, architecture) },
|
||||
{ "Virtualization", "s", NULL, offsetof(HostInfo, virtualization) },
|
||||
{ "Architecture", "s", NULL, offsetof(HostInfo, architecture) },
|
||||
{}
|
||||
};
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *system_bus = NULL;
|
||||
_cleanup_(free_host_infop) struct host_info *host;
|
||||
_cleanup_(free_host_infop) HostInfo *host = NULL;
|
||||
int r;
|
||||
|
||||
host = new0(struct host_info, 1);
|
||||
host = new0(HostInfo, 1);
|
||||
if (!host)
|
||||
return log_oom();
|
||||
|
||||
@ -482,7 +479,7 @@ manager:
|
||||
|
||||
static int pretty_boot_time(sd_bus *bus, char **_buf) {
|
||||
char ts[FORMAT_TIMESPAN_MAX];
|
||||
struct boot_times *t;
|
||||
BootTimes *t;
|
||||
static char buf[4096];
|
||||
size_t size;
|
||||
char *ptr;
|
||||
@ -559,14 +556,12 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
|
||||
}
|
||||
|
||||
static void svg_graph_box(double height, double begin, double end) {
|
||||
long long i;
|
||||
|
||||
/* outside box, fill */
|
||||
svg("<rect class=\"box\" x=\"0\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
|
||||
SCALE_X * (end - begin),
|
||||
SCALE_Y * height);
|
||||
|
||||
for (i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) {
|
||||
for (long long i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) {
|
||||
/* lines for each second */
|
||||
if (i % 5000000 == 0)
|
||||
svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
|
||||
@ -594,7 +589,7 @@ static void svg_graph_box(double height, double begin, double end) {
|
||||
}
|
||||
}
|
||||
|
||||
static int plot_unit_times(struct unit_times *u, double width, int y) {
|
||||
static int plot_unit_times(UnitTimes *u, double width, int y) {
|
||||
char ts[FORMAT_TIMESPAN_MAX];
|
||||
bool b;
|
||||
|
||||
@ -617,13 +612,13 @@ static int plot_unit_times(struct unit_times *u, double width, int y) {
|
||||
}
|
||||
|
||||
static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(free_host_infop) struct host_info *host = NULL;
|
||||
_cleanup_(free_host_infop) HostInfo *host = NULL;
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(unit_times_freep) struct unit_times *times = NULL;
|
||||
_cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
|
||||
_cleanup_free_ char *pretty_times = NULL;
|
||||
bool use_full_bus = arg_scope == UNIT_FILE_SYSTEM;
|
||||
struct boot_times *boot;
|
||||
struct unit_times *u;
|
||||
BootTimes *boot;
|
||||
UnitTimes *u;
|
||||
int n, m = 1, y = 0, r;
|
||||
double width;
|
||||
|
||||
@ -837,13 +832,12 @@ static int list_dependencies_print(
|
||||
unsigned level,
|
||||
unsigned branches,
|
||||
bool last,
|
||||
struct unit_times *times,
|
||||
struct boot_times *boot) {
|
||||
UnitTimes *times,
|
||||
BootTimes *boot) {
|
||||
|
||||
unsigned i;
|
||||
char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX];
|
||||
|
||||
for (i = level; i != 0; i--)
|
||||
for (unsigned i = level; i != 0; i--)
|
||||
printf("%s", special_glyph(branches & (1 << (i-1)) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
|
||||
|
||||
printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
|
||||
@ -882,7 +876,7 @@ static Hashmap *unit_times_hashmap;
|
||||
|
||||
static int list_dependencies_compare(char *const *a, char *const *b) {
|
||||
usec_t usa = 0, usb = 0;
|
||||
struct unit_times *times;
|
||||
UnitTimes *times;
|
||||
|
||||
times = hashmap_get(unit_times_hashmap, *a);
|
||||
if (times)
|
||||
@ -894,7 +888,7 @@ static int list_dependencies_compare(char *const *a, char *const *b) {
|
||||
return CMP(usb, usa);
|
||||
}
|
||||
|
||||
static bool times_in_range(const struct unit_times *times, const struct boot_times *boot) {
|
||||
static bool times_in_range(const UnitTimes *times, const BootTimes *boot) {
|
||||
return times && times->activated > 0 && times->activated <= boot->finish_time;
|
||||
}
|
||||
|
||||
@ -904,8 +898,8 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
|
||||
int r;
|
||||
usec_t service_longest = 0;
|
||||
int to_print = 0;
|
||||
struct unit_times *times;
|
||||
struct boot_times *boot;
|
||||
UnitTimes *times;
|
||||
BootTimes *boot;
|
||||
|
||||
if (strv_extend(units, name))
|
||||
return log_oom();
|
||||
@ -970,13 +964,13 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
|
||||
static int list_dependencies(sd_bus *bus, const char *name) {
|
||||
_cleanup_strv_free_ char **units = NULL;
|
||||
char ts[FORMAT_TIMESPAN_MAX];
|
||||
struct unit_times *times;
|
||||
UnitTimes *times;
|
||||
int r;
|
||||
const char *id;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
struct boot_times *boot;
|
||||
BootTimes *boot;
|
||||
|
||||
assert(bus);
|
||||
|
||||
@ -1021,7 +1015,7 @@ static int list_dependencies(sd_bus *bus, const char *name) {
|
||||
|
||||
static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(unit_times_freep) struct unit_times *times = NULL;
|
||||
_cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
|
||||
Hashmap *h;
|
||||
int n, r;
|
||||
|
||||
@ -1037,7 +1031,7 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
|
||||
if (!h)
|
||||
return log_oom();
|
||||
|
||||
for (struct unit_times *u = times; u->has_data; u++) {
|
||||
for (UnitTimes *u = times; u->has_data; u++) {
|
||||
r = hashmap_put(h, u->name, u);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add entry to hashmap: %m");
|
||||
@ -1062,7 +1056,7 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
|
||||
|
||||
static int analyze_blame(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(unit_times_freep) struct unit_times *times = NULL;
|
||||
_cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
TableCell *cell;
|
||||
int n, r;
|
||||
@ -1103,7 +1097,7 @@ static int analyze_blame(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (struct unit_times *u = times; u->has_data; u++) {
|
||||
for (UnitTimes *u = times; u->has_data; u++) {
|
||||
if (u->time <= 0)
|
||||
continue;
|
||||
|
||||
@ -1716,7 +1710,7 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
|
||||
if (strv_isempty(strv_skip(argv, 1))) {
|
||||
_cleanup_set_free_ Set *kernel = NULL, *known = NULL;
|
||||
const char *sys;
|
||||
int i, k;
|
||||
int k;
|
||||
|
||||
NULSTR_FOREACH(sys, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value)
|
||||
if (set_put_strdup(&known, sys) < 0)
|
||||
@ -1724,7 +1718,7 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
|
||||
|
||||
k = load_kernel_syscalls(&kernel);
|
||||
|
||||
for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
|
||||
for (int i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
|
||||
const SyscallFilterSet *set = syscall_filter_sets + i;
|
||||
if (!first)
|
||||
puts("");
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "util.h"
|
||||
|
||||
int have_effective_cap(int value) {
|
||||
_cleanup_cap_free_ cap_t cap;
|
||||
_cleanup_cap_free_ cap_t cap = NULL;
|
||||
cap_flag_value_t fv;
|
||||
|
||||
cap = cap_get_proc();
|
||||
|
@ -25,7 +25,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
|
||||
|
||||
int drop_capability(cap_value_t cv);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(cap_t, cap_free, NULL);
|
||||
#define _cleanup_cap_free_ _cleanup_(cap_freep)
|
||||
|
||||
static inline void cap_free_charpp(char **p) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
|
||||
|
||||
int dlsym_many_and_warn(void *dl, int level, ...);
|
||||
|
||||
|
@ -385,11 +385,9 @@ static int load_env_file_push(
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = strv_env_replace(m, p);
|
||||
if (r < 0) {
|
||||
free(p);
|
||||
r = strv_env_replace_consume(m, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (n_pushed)
|
||||
(*n_pushed)++;
|
||||
|
@ -363,20 +363,23 @@ char **strv_env_unset_many(char **l, ...) {
|
||||
return l;
|
||||
}
|
||||
|
||||
int strv_env_replace(char ***l, char *p) {
|
||||
int strv_env_replace_consume(char ***l, char *p) {
|
||||
const char *t, *name;
|
||||
char **f;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
|
||||
/* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits
|
||||
* in-place. Does not copy p. p must be a valid key=value assignment.
|
||||
*/
|
||||
/* Replace first occurrence of the env var or add a new one in the string list. Drop other
|
||||
* occurrences. Edits in-place. Does not copy p and CONSUMES p EVEN ON FAILURE.
|
||||
*
|
||||
* p must be a valid key=value assignment. */
|
||||
|
||||
t = strchr(p, '=');
|
||||
if (!t)
|
||||
if (!t) {
|
||||
free(p);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
name = strndupa(p, t - p);
|
||||
|
||||
@ -388,39 +391,39 @@ int strv_env_replace(char ***l, char *p) {
|
||||
}
|
||||
|
||||
/* We didn't find a match, we need to append p or create a new strv */
|
||||
r = strv_push(l, p);
|
||||
r = strv_consume(l, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char **strv_env_set(char **x, const char *p) {
|
||||
_cleanup_strv_free_ char **ret = NULL;
|
||||
size_t n, m;
|
||||
char **k;
|
||||
int strv_env_replace_strdup(char ***l, const char *assignment) {
|
||||
/* Like strv_env_replace_consume(), but copies the argument. */
|
||||
|
||||
/* Overrides the env var setting of p, returns a new copy */
|
||||
char *p = strdup(assignment);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
n = strv_length(x);
|
||||
m = n + 2;
|
||||
if (m < n) /* overflow? */
|
||||
return NULL;
|
||||
return strv_env_replace_consume(l, p);
|
||||
}
|
||||
|
||||
ret = new(char*, m);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
int strv_env_assign(char ***l, const char *key, const char *value) {
|
||||
if (!env_name_is_valid(key))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = NULL;
|
||||
k = ret;
|
||||
/* NULL removes assignment, "" creates an empty assignment. */
|
||||
|
||||
if (env_append(ret, &k, x) < 0)
|
||||
return NULL;
|
||||
if (!value) {
|
||||
strv_env_unset(*l, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (env_append(ret, &k, STRV_MAKE(p)) < 0)
|
||||
return NULL;
|
||||
char *p = strjoin(key, "=", value);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
return TAKE_PTR(ret);
|
||||
return strv_env_replace_consume(l, p);
|
||||
}
|
||||
|
||||
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
|
||||
|
@ -42,10 +42,11 @@ bool strv_env_name_or_assignment_is_valid(char **l);
|
||||
char **strv_env_merge(size_t n_lists, ...);
|
||||
char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
|
||||
|
||||
char **strv_env_set(char **x, const char *p); /* New copy ... */
|
||||
char **strv_env_unset(char **l, const char *p); /* In place ... */
|
||||
char **strv_env_unset_many(char **l, ...) _sentinel_;
|
||||
int strv_env_replace(char ***l, char *p); /* In place ... */
|
||||
int strv_env_replace_consume(char ***l, char *p); /* In place ... */
|
||||
int strv_env_replace_strdup(char ***l, const char *assignment);
|
||||
int strv_env_assign(char ***l, const char *key, const char *value);
|
||||
|
||||
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_;
|
||||
char *strv_env_get(char **x, const char *n) _pure_;
|
||||
|
@ -41,8 +41,8 @@ static inline void fclosep(FILE **f) {
|
||||
safe_fclose(*f);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, pclose, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
|
||||
|
||||
#define _cleanup_close_ _cleanup_(closep)
|
||||
#define _cleanup_fclose_ _cleanup_(fclosep)
|
||||
|
@ -1146,7 +1146,7 @@ static EndOfLineMarker categorize_eol(char c, ReadLineFlags flags) {
|
||||
return EOL_NONE;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, funlockfile, NULL);
|
||||
|
||||
int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
|
||||
size_t n = 0, allocated = 0, count = 0;
|
||||
|
@ -14,7 +14,7 @@
|
||||
void initialize_libgcrypt(bool secmem);
|
||||
int string_hashsum(const char *s, size_t len, int md_algorithm, char **out);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(gcry_md_hd_t, gcry_md_close);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gcry_md_hd_t, gcry_md_close, NULL);
|
||||
#endif
|
||||
|
||||
static inline int string_hashsum_sha224(const char *s, size_t len, char **out) {
|
||||
|
@ -405,10 +405,20 @@ static inline int __coverity_check_and_return__(int condition) {
|
||||
func(p); \
|
||||
}
|
||||
|
||||
/* When func() returns the void value (NULL, -1, …) of the appropriate type */
|
||||
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
|
||||
static inline void func##p(type *p) { \
|
||||
if (*p) \
|
||||
*p = func(*p); \
|
||||
}
|
||||
|
||||
/* When func() doesn't return the appropriate type, set variable to empty afterwards */
|
||||
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \
|
||||
static inline void func##p(type *p) { \
|
||||
if (*p != (empty)) { \
|
||||
func(*p); \
|
||||
*p = (empty); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _DEFINE_TRIVIAL_REF_FUNC(type, name, scope) \
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "time-util.h"
|
||||
|
||||
#if HAVE_SELINUX
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(context_t, context_free, NULL);
|
||||
#define _cleanup_context_free_ _cleanup_(context_freep)
|
||||
|
||||
static int mac_selinux_reload(int seqno);
|
||||
|
@ -11,7 +11,7 @@
|
||||
#if HAVE_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, freecon, NULL);
|
||||
#define _cleanup_freecon_ _cleanup_(freeconp)
|
||||
#endif
|
||||
|
||||
|
@ -72,12 +72,17 @@ int dir_is_empty_at(int dir_fd, const char *path) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
|
||||
if (path)
|
||||
if (path) {
|
||||
fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
else
|
||||
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
} else {
|
||||
/* Note that DUPing is not enough, as the internal pointer
|
||||
* would still be shared and moved by FOREACH_DIRENT. */
|
||||
fd = fd_reopen(dir_fd, O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
}
|
||||
|
||||
d = take_fdopendir(&fd);
|
||||
if (!d)
|
||||
|
@ -26,7 +26,7 @@
|
||||
* ...
|
||||
*/
|
||||
|
||||
struct strbuf *strbuf_new(void) {
|
||||
struct strbuf* strbuf_new(void) {
|
||||
struct strbuf *str;
|
||||
|
||||
str = new(struct strbuf, 1);
|
||||
@ -65,13 +65,13 @@ void strbuf_complete(struct strbuf *str) {
|
||||
}
|
||||
|
||||
/* clean up everything */
|
||||
void strbuf_cleanup(struct strbuf *str) {
|
||||
struct strbuf* strbuf_free(struct strbuf *str) {
|
||||
if (!str)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
strbuf_complete(str);
|
||||
free(str->buf);
|
||||
free(str);
|
||||
return mfree(str);
|
||||
}
|
||||
|
||||
static int strbuf_children_cmp(const struct strbuf_child_entry *n1,
|
||||
|
@ -32,8 +32,8 @@ struct strbuf_child_entry {
|
||||
struct strbuf_node *child;
|
||||
};
|
||||
|
||||
struct strbuf *strbuf_new(void);
|
||||
struct strbuf* strbuf_new(void);
|
||||
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
|
||||
void strbuf_complete(struct strbuf *str);
|
||||
void strbuf_cleanup(struct strbuf *str);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_cleanup);
|
||||
struct strbuf* strbuf_free(struct strbuf *str);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_free);
|
||||
|
@ -780,24 +780,22 @@ static int member_compare_funcp(Member * const *a, Member * const *b) {
|
||||
return member_compare_func(*a, *b);
|
||||
}
|
||||
|
||||
static void member_free(Member *m) {
|
||||
static Member* member_free(Member *m) {
|
||||
if (!m)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
free(m->interface);
|
||||
free(m->name);
|
||||
free(m->signature);
|
||||
free(m->result);
|
||||
free(m->value);
|
||||
free(m);
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
|
||||
|
||||
static void member_set_free(Set *s) {
|
||||
set_free_with_destructor(s, member_free);
|
||||
static Set* member_set_free(Set *s) {
|
||||
return set_free_with_destructor(s, member_free);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
|
||||
|
||||
static int on_interface(const char *interface, uint64_t flags, void *userdata) {
|
||||
|
@ -16,17 +16,17 @@
|
||||
#include "strv.h"
|
||||
|
||||
#if HAVE_APPARMOR
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(aa_policy_cache *, aa_policy_cache_unref);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(aa_features *, aa_features_unref);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(aa_policy_cache *, aa_policy_cache_unref, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(aa_features *, aa_features_unref, NULL);
|
||||
#endif
|
||||
|
||||
int mac_apparmor_setup(void) {
|
||||
#if HAVE_APPARMOR
|
||||
int r;
|
||||
_cleanup_(aa_policy_cache_unrefp) aa_policy_cache *policy_cache = NULL;
|
||||
_cleanup_(aa_features_unrefp) aa_features *features = NULL;
|
||||
const char *current_file;
|
||||
_cleanup_free_ char *current_profile = NULL, *cache_dir_path = NULL;
|
||||
int r;
|
||||
|
||||
if (!mac_apparmor_use()) {
|
||||
log_debug("AppArmor either not supported by the kernel or disabled.");
|
||||
|
@ -48,13 +48,13 @@ struct expire_data {
|
||||
int ioctl_fd;
|
||||
};
|
||||
|
||||
static void expire_data_free(struct expire_data *data) {
|
||||
static struct expire_data* expire_data_free(struct expire_data *data) {
|
||||
if (!data)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
safe_close(data->dev_autofs_fd);
|
||||
safe_close(data->ioctl_fd);
|
||||
free(data);
|
||||
return mfree(data);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
|
||||
|
@ -2636,7 +2636,7 @@ int config_parse_environ(
|
||||
}
|
||||
|
||||
for (const char *p = rvalue;; ) {
|
||||
_cleanup_free_ char *word = NULL, *k = NULL;
|
||||
_cleanup_free_ char *word = NULL, *resolved = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
|
||||
if (r == 0)
|
||||
@ -2650,26 +2650,24 @@ int config_parse_environ(
|
||||
}
|
||||
|
||||
if (u) {
|
||||
r = unit_full_printf(u, word, &k);
|
||||
r = unit_full_printf(u, word, &resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to resolve unit specifiers in %s, ignoring: %m", word);
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
k = TAKE_PTR(word);
|
||||
resolved = TAKE_PTR(word);
|
||||
|
||||
if (!env_assignment_is_valid(k)) {
|
||||
if (!env_assignment_is_valid(resolved)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Invalid environment assignment, ignoring: %s", k);
|
||||
"Invalid environment assignment, ignoring: %s", resolved);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_env_replace(env, k);
|
||||
r = strv_env_replace_consume(env, TAKE_PTR(resolved));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
k = NULL;
|
||||
return log_error_errno(r, "Failed to update environment: %m");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,16 +453,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
if (env_assignment_is_valid(value)) {
|
||||
char **env;
|
||||
|
||||
env = strv_env_set(arg_default_environment, value);
|
||||
if (!env)
|
||||
if (!env_assignment_is_valid(value))
|
||||
log_warning("Environment variable assignment '%s' is not valid. Ignoring.", value);
|
||||
else {
|
||||
r = strv_env_replace_strdup(&arg_default_environment, value);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
arg_default_environment = env;
|
||||
} else
|
||||
log_warning("Environment variable name '%s' is not valid. Ignoring.", value);
|
||||
}
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.machine_id")) {
|
||||
|
||||
@ -821,6 +818,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
};
|
||||
|
||||
int c, r;
|
||||
bool user_arg_seen = false;
|
||||
|
||||
assert(argc >= 1);
|
||||
assert(argv);
|
||||
@ -910,6 +908,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
case ARG_USER:
|
||||
arg_system = false;
|
||||
user_arg_seen = true;
|
||||
break;
|
||||
|
||||
case ARG_TEST:
|
||||
@ -1066,10 +1065,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (optind < argc && getpid_cached() != 1)
|
||||
/* Hmm, when we aren't run as init system
|
||||
* let's complain about excess arguments */
|
||||
/* Hmm, when we aren't run as init system let's complain about excess arguments */
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Excess arguments.");
|
||||
|
||||
if (arg_action == ACTION_RUN && !arg_system && !user_arg_seen)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Excess arguments.");
|
||||
"Explicit --user argument required to run as user manager.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -642,22 +642,14 @@ int manager_default_environment(Manager *m) {
|
||||
/* Import locale variables LC_*= from configuration */
|
||||
(void) locale_setup(&m->transient_environment);
|
||||
} else {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
/* The user manager passes its own environment
|
||||
* along to its children, except for $PATH. */
|
||||
/* The user manager passes its own environment along to its children, except for $PATH. */
|
||||
m->transient_environment = strv_copy(environ);
|
||||
if (!m->transient_environment)
|
||||
return log_oom();
|
||||
|
||||
k = strdup("PATH=" DEFAULT_USER_PATH);
|
||||
if (!k)
|
||||
return log_oom();
|
||||
|
||||
r = strv_env_replace(&m->transient_environment, k);
|
||||
r = strv_env_replace_strdup(&m->transient_environment, "PATH=" DEFAULT_USER_PATH);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
TAKE_PTR(k);
|
||||
}
|
||||
|
||||
sanitize_environment(m->transient_environment);
|
||||
|
@ -72,6 +72,8 @@ typedef struct MountEntry {
|
||||
bool exec:1; /* Shall clear MS_NOEXEC on the mount itself */
|
||||
bool applied:1; /* Already applied */
|
||||
char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */
|
||||
const char *unprefixed_path_const; /* If the path was amended with a prefix, these will save the original */
|
||||
char *unprefixed_path_malloc;
|
||||
const char *source_const; /* The source path, for bind mounts or images */
|
||||
char *source_malloc;
|
||||
const char *options_const;/* Mount options for tmpfs */
|
||||
@ -231,6 +233,29 @@ static const char *mount_entry_path(const MountEntry *p) {
|
||||
return p->path_malloc ?: p->path_const;
|
||||
}
|
||||
|
||||
static const char *mount_entry_unprefixed_path(const MountEntry *p) {
|
||||
assert(p);
|
||||
|
||||
/* Returns the unprefixed path (ie: before prefix_where_needed() ran), if any */
|
||||
|
||||
return p->unprefixed_path_malloc ?: p->unprefixed_path_const ?: mount_entry_path(p);
|
||||
}
|
||||
|
||||
static void mount_entry_consume_prefix(MountEntry *p, char *new_path) {
|
||||
assert(p);
|
||||
assert(p->path_malloc || p->path_const);
|
||||
assert(new_path);
|
||||
|
||||
/* Saves current path in unprefixed_ variable, and takes over new_path */
|
||||
|
||||
free_and_replace(p->unprefixed_path_malloc, p->path_malloc);
|
||||
/* If we didn't have a path on the heap, then it's a static one */
|
||||
if (!p->unprefixed_path_malloc)
|
||||
p->unprefixed_path_const = p->path_const;
|
||||
p->path_malloc = new_path;
|
||||
p->has_prefix = true;
|
||||
}
|
||||
|
||||
static bool mount_entry_read_only(const MountEntry *p) {
|
||||
assert(p);
|
||||
|
||||
@ -265,6 +290,7 @@ static void mount_entry_done(MountEntry *p) {
|
||||
assert(p);
|
||||
|
||||
p->path_malloc = mfree(p->path_malloc);
|
||||
p->unprefixed_path_malloc = mfree(p->unprefixed_path_malloc);
|
||||
p->source_malloc = mfree(p->source_malloc);
|
||||
p->options_malloc = mfree(p->options_malloc);
|
||||
p->image_options = mount_options_free_all(p->image_options);
|
||||
@ -492,8 +518,7 @@ static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directo
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(m[i].path_malloc, s);
|
||||
m[i].has_prefix = true;
|
||||
mount_entry_consume_prefix(&m[i], s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -946,7 +971,7 @@ static int mount_tmpfs(const MountEntry *m) {
|
||||
assert(m);
|
||||
|
||||
entry_path = mount_entry_path(m);
|
||||
inner_path = m->path_const;
|
||||
inner_path = mount_entry_unprefixed_path(m);
|
||||
|
||||
/* First, get rid of everything that is below if there is anything. Then, overmount with our new tmpfs */
|
||||
|
||||
@ -984,6 +1009,8 @@ static int mount_images(const MountEntry *m) {
|
||||
assert(m);
|
||||
|
||||
r = verity_dissect_and_mount(mount_entry_source(m), mount_entry_path(m), m->image_options);
|
||||
if (r == -ENOENT && m->ignore)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to mount image %s on %s: %m", mount_entry_source(m), mount_entry_path(m));
|
||||
|
||||
@ -1015,8 +1042,7 @@ static int follow_symlink(
|
||||
|
||||
log_debug("Followed mount entry path symlink %s → %s.", mount_entry_path(m), target);
|
||||
|
||||
free_and_replace(m->path_malloc, target);
|
||||
m->has_prefix = true;
|
||||
mount_entry_consume_prefix(m, TAKE_PTR(target));
|
||||
|
||||
m->n_followed ++;
|
||||
|
||||
|
@ -137,11 +137,11 @@ int setup_namespace(
|
||||
|
||||
#define RUN_SYSTEMD_EMPTY "/run/systemd/empty"
|
||||
|
||||
static inline void namespace_cleanup_tmpdir(char *p) {
|
||||
static inline char* namespace_cleanup_tmpdir(char *p) {
|
||||
PROTECT_ERRNO;
|
||||
if (!streq_ptr(p, RUN_SYSTEMD_EMPTY))
|
||||
(void) rmdir(p);
|
||||
free(p);
|
||||
return mfree(p);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, namespace_cleanup_tmpdir);
|
||||
|
||||
|
@ -969,6 +969,8 @@ static void socket_close_fds(Socket *s) {
|
||||
if (s->remove_on_stop)
|
||||
STRV_FOREACH(i, s->symlinks)
|
||||
(void) unlink(*i);
|
||||
|
||||
/* Note that we don't return NULL here, since s has not been freed. */
|
||||
}
|
||||
|
||||
static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
|
||||
@ -1609,10 +1611,10 @@ static int socket_address_listen_in_cgroup(
|
||||
return fd;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Socket *, socket_close_fds);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(Socket *, socket_close_fds, NULL);
|
||||
|
||||
static int socket_open_fds(Socket *_s) {
|
||||
_cleanup_(socket_close_fdsp) Socket *s = _s;
|
||||
static int socket_open_fds(Socket *orig_s) {
|
||||
_cleanup_(socket_close_fdsp) Socket *s = orig_s;
|
||||
_cleanup_(mac_selinux_freep) char *label = NULL;
|
||||
bool know_label = false;
|
||||
SocketPort *p;
|
||||
|
@ -82,7 +82,7 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
|
||||
|
||||
static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency);
|
||||
|
||||
Unit *unit_new(Manager *m, size_t size) {
|
||||
Unit* unit_new(Manager *m, size_t size) {
|
||||
Unit *u;
|
||||
|
||||
assert(m);
|
||||
@ -607,11 +607,11 @@ static void unit_done(Unit *u) {
|
||||
cgroup_context_done(cc);
|
||||
}
|
||||
|
||||
void unit_free(Unit *u) {
|
||||
Unit* unit_free(Unit *u) {
|
||||
char *t;
|
||||
|
||||
if (!u)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
u->transient_file = safe_fclose(u->transient_file);
|
||||
|
||||
@ -741,7 +741,7 @@ void unit_free(Unit *u) {
|
||||
set_free_free(u->aliases);
|
||||
free(u->id);
|
||||
|
||||
free(u);
|
||||
return mfree(u);
|
||||
}
|
||||
|
||||
FreezerState unit_freezer_state(Unit *u) {
|
||||
|
@ -674,8 +674,8 @@ static inline Unit* UNIT_TRIGGER(Unit *u) {
|
||||
return hashmap_first_key(u->dependencies[UNIT_TRIGGERS]);
|
||||
}
|
||||
|
||||
Unit *unit_new(Manager *m, size_t size);
|
||||
void unit_free(Unit *u);
|
||||
Unit* unit_new(Manager *m, size_t size);
|
||||
Unit* unit_free(Unit *u);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free);
|
||||
|
||||
int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret);
|
||||
|
@ -22,24 +22,23 @@
|
||||
#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
|
||||
#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL) /* 1 MB */
|
||||
|
||||
struct vacuum_candidate {
|
||||
typedef struct VacuumCandidate {
|
||||
unsigned n_files;
|
||||
char *oldest_file;
|
||||
usec_t oldest_mtime;
|
||||
};
|
||||
} VacuumCandidate;
|
||||
|
||||
static void vacuum_candidate_free(struct vacuum_candidate *c) {
|
||||
static VacuumCandidate* vacuum_candidate_free(VacuumCandidate *c) {
|
||||
if (!c)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
free(c->oldest_file);
|
||||
free(c);
|
||||
return mfree(c);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(VacuumCandidate*, vacuum_candidate_free);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free);
|
||||
|
||||
static void vacuum_candidate_hashmap_free(Hashmap *h) {
|
||||
hashmap_free_with_destructor(h, vacuum_candidate_free);
|
||||
static Hashmap* vacuum_candidate_hashmap_free(Hashmap *h) {
|
||||
return hashmap_free_with_destructor(h, vacuum_candidate_free);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hashmap_free);
|
||||
@ -142,14 +141,14 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(vacuum_candidate_hashmap_freep) Hashmap *h = NULL;
|
||||
struct vacuum_candidate *worst = NULL;
|
||||
VacuumCandidate *worst = NULL;
|
||||
struct dirent *de;
|
||||
uint64_t sum = 0;
|
||||
|
||||
rewinddir(d);
|
||||
|
||||
FOREACH_DIRENT(de, d, goto fail) {
|
||||
struct vacuum_candidate *c;
|
||||
VacuumCandidate *c;
|
||||
struct stat st;
|
||||
uid_t uid;
|
||||
usec_t t;
|
||||
@ -196,9 +195,9 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
||||
}
|
||||
|
||||
} else {
|
||||
_cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL;
|
||||
_cleanup_(vacuum_candidate_freep) VacuumCandidate *n = NULL;
|
||||
|
||||
n = new0(struct vacuum_candidate, 1);
|
||||
n = new0(VacuumCandidate, 1);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
|
@ -2512,7 +2512,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_SETENV: {
|
||||
_cleanup_free_ char **l = NULL, **k = NULL;
|
||||
_cleanup_free_ char **l = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *ne = NULL;
|
||||
JsonVariant *e;
|
||||
|
||||
@ -2525,7 +2525,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (!env_assignment_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Environment assignment '%s' not valid.", optarg);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Environment assignment '%s' not valid.", optarg);
|
||||
|
||||
e = json_variant_by_key(arg_identity_extra, "environment");
|
||||
if (e) {
|
||||
@ -2534,13 +2535,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(r, "Failed to parse JSON environment field: %m");
|
||||
}
|
||||
|
||||
k = strv_env_set(l, optarg);
|
||||
if (!k)
|
||||
return log_oom();
|
||||
r = strv_env_replace_strdup(&l, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to replace JSON environment field: %m");
|
||||
|
||||
strv_sort(k);
|
||||
strv_sort(l);
|
||||
|
||||
r = json_variant_new_array_strv(&ne, k);
|
||||
r = json_variant_new_array_strv(&ne, l);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate environment list JSON: %m");
|
||||
|
||||
|
@ -1343,7 +1343,7 @@ static int manager_load_key_pair(Manager *m) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY_CTX*, EVP_PKEY_CTX_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL);
|
||||
|
||||
static int manager_generate_key_pair(Manager *m) {
|
||||
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
|
||||
@ -1454,7 +1454,7 @@ int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, EVP_PKEY_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY*, EVP_PKEY_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL);
|
||||
|
||||
static int manager_load_public_key_one(Manager *m, const char *path) {
|
||||
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
|
||||
|
@ -1592,10 +1592,10 @@ static int luks_format(
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
|
||||
|
||||
static int make_partition_table(
|
||||
int fd,
|
||||
|
@ -27,7 +27,7 @@ static int user_record_signable_json(UserRecord *ur, char **ret) {
|
||||
return json_variant_format(j, 0, ret);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_MD_CTX*, EVP_MD_CTX_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
|
||||
|
||||
int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *encoded = NULL, *v = NULL;
|
||||
|
@ -423,25 +423,11 @@ static int context_write_data_machine_info(Context *c) {
|
||||
return r;
|
||||
|
||||
for (int p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
char **u;
|
||||
|
||||
assert(name[p]);
|
||||
|
||||
if (isempty(c->data[p])) {
|
||||
strv_env_unset(l, name[p]);
|
||||
continue;
|
||||
}
|
||||
|
||||
t = strjoin(name[p], "=", c->data[p]);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
u = strv_env_set(l, t);
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
strv_free_and_replace(l, u);
|
||||
r = strv_env_assign(&l, name[p], empty_to_null(c->data[p]));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (strv_isempty(l)) {
|
||||
|
@ -34,6 +34,6 @@ struct curl_slist *curl_slist_new(const char *first, ...) _sentinel_;
|
||||
int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value);
|
||||
int curl_parse_http_time(const char *t, usec_t *ret);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_easy_cleanup);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(CURLM*, curl_multi_cleanup);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct curl_slist*, curl_slist_free_all);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CURL*, curl_easy_cleanup, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CURLM*, curl_multi_cleanup, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct curl_slist*, curl_slist_free_all, NULL);
|
||||
|
@ -210,8 +210,9 @@ static int fifo_process(Fifo *f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fifo_free(Fifo *f) {
|
||||
assert(f);
|
||||
static Fifo* fifo_free(Fifo *f) {
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
if (f->server) {
|
||||
assert(f->server->n_fifos > 0);
|
||||
@ -226,7 +227,7 @@ static void fifo_free(Fifo *f) {
|
||||
safe_close(f->fd);
|
||||
}
|
||||
|
||||
free(f);
|
||||
return mfree(f);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Fifo*, fifo_free);
|
||||
|
||||
|
@ -80,5 +80,5 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
|
||||
*/
|
||||
int setup_gnutls_logger(char **categories);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Response*, MHD_destroy_response);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Daemon*, MHD_stop_daemon, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Response*, MHD_destroy_response, NULL);
|
||||
|
@ -166,8 +166,8 @@ typedef struct BootId {
|
||||
} BootId;
|
||||
|
||||
#if HAVE_PCRE2
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, sym_pcre2_match_data_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, sym_pcre2_code_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pcre2_match_data*, sym_pcre2_match_data_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pcre2_code*, sym_pcre2_code_free, NULL);
|
||||
|
||||
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
|
||||
int errorcode, r;
|
||||
|
@ -98,9 +98,9 @@ struct StdoutStream {
|
||||
char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX];
|
||||
};
|
||||
|
||||
void stdout_stream_free(StdoutStream *s) {
|
||||
StdoutStream* stdout_stream_free(StdoutStream *s) {
|
||||
if (!s)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (s->server) {
|
||||
|
||||
@ -129,7 +129,7 @@ void stdout_stream_free(StdoutStream *s) {
|
||||
free(s->state_file);
|
||||
free(s->buffer);
|
||||
|
||||
free(s);
|
||||
return mfree(s);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
|
||||
|
@ -9,7 +9,7 @@ typedef struct StdoutStream StdoutStream;
|
||||
int server_open_stdout_socket(Server *s, const char *stdout_socket);
|
||||
int server_restore_streams(Server *s, FDSet *fds);
|
||||
|
||||
void stdout_stream_free(StdoutStream *s);
|
||||
StdoutStream* stdout_stream_free(StdoutStream *s);
|
||||
int stdout_stream_install(Server *s, int fd, StdoutStream **ret);
|
||||
void stdout_stream_destroy(StdoutStream *s);
|
||||
void stdout_stream_send_notify(StdoutStream *s);
|
||||
|
@ -649,12 +649,12 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dhcp_request_free(DHCPRequest *req) {
|
||||
static DHCPRequest* dhcp_request_free(DHCPRequest *req) {
|
||||
if (!req)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
free(req->client_id.data);
|
||||
free(req);
|
||||
return mfree(req);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
|
||||
|
@ -939,7 +939,7 @@ static void source_disconnect(sd_event_source *s) {
|
||||
sd_event_unref(event);
|
||||
}
|
||||
|
||||
static void source_free(sd_event_source *s) {
|
||||
static sd_event_source* source_free(sd_event_source *s) {
|
||||
assert(s);
|
||||
|
||||
source_disconnect(s);
|
||||
@ -989,7 +989,7 @@ static void source_free(sd_event_source *s) {
|
||||
s->destroy_callback(s->userdata);
|
||||
|
||||
free(s->description);
|
||||
free(s);
|
||||
return mfree(s);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, source_free);
|
||||
|
||||
|
@ -115,13 +115,13 @@ static void trie_node_cleanup(struct trie_node *node) {
|
||||
free(node);
|
||||
}
|
||||
|
||||
static void trie_free(struct trie *trie) {
|
||||
static struct trie* trie_free(struct trie *trie) {
|
||||
if (!trie)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
trie_node_cleanup(trie->root);
|
||||
strbuf_cleanup(trie->strings);
|
||||
free(trie);
|
||||
strbuf_free(trie->strings);
|
||||
return mfree(trie);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free);
|
||||
|
@ -444,7 +444,7 @@ error:
|
||||
int catalog_update(const char* database, const char* root, const char* const* dirs) {
|
||||
_cleanup_strv_free_ char **files = NULL;
|
||||
char **f;
|
||||
_cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL;
|
||||
_cleanup_(strbuf_freep) struct strbuf *sb = NULL;
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
_cleanup_free_ CatalogItem *items = NULL;
|
||||
ssize_t offset;
|
||||
|
@ -34,13 +34,13 @@
|
||||
#include "util.h"
|
||||
|
||||
#if HAVE_LZ4
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionContext);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(LZ4F_compressionContext_t, LZ4F_freeCompressionContext, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext, NULL);
|
||||
#endif
|
||||
|
||||
#if HAVE_ZSTD
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_CCtx *, ZSTD_freeCCtx);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_DCtx *, ZSTD_freeDCtx);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ZSTD_CCtx*, ZSTD_freeCCtx, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ZSTD_DCtx*, ZSTD_freeDCtx, NULL);
|
||||
|
||||
static int zstd_ret_to_errno(size_t ret) {
|
||||
switch (ZSTD_getErrorCode(ret)) {
|
||||
|
@ -208,6 +208,7 @@ static bool journal_file_set_offline_try_restart(JournalFile *f) {
|
||||
* context without involving another thread.
|
||||
*/
|
||||
int journal_file_set_offline(JournalFile *f, bool wait) {
|
||||
int target_state;
|
||||
bool restarted;
|
||||
int r;
|
||||
|
||||
@ -219,9 +220,13 @@ int journal_file_set_offline(JournalFile *f, bool wait) {
|
||||
if (f->fd < 0 || !f->header)
|
||||
return -EINVAL;
|
||||
|
||||
target_state = f->archive ? STATE_ARCHIVED : STATE_OFFLINE;
|
||||
|
||||
/* An offlining journal is implicitly online and may modify f->header->state,
|
||||
* we must also join any potentially lingering offline thread when not online. */
|
||||
if (!journal_file_is_offlining(f) && f->header->state != STATE_ONLINE)
|
||||
* we must also join any potentially lingering offline thread when already in
|
||||
* the desired offline state.
|
||||
*/
|
||||
if (!journal_file_is_offlining(f) && f->header->state == target_state)
|
||||
return journal_file_set_offline_thread_join(f);
|
||||
|
||||
/* Restart an in-flight offline thread and wait if needed, or join a lingering done one. */
|
||||
|
@ -663,13 +663,17 @@ int sd_netlink_message_cancel_array(sd_netlink_message *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) {
|
||||
static int netlink_message_read_internal(
|
||||
sd_netlink_message *m,
|
||||
unsigned short type,
|
||||
void **ret_data,
|
||||
bool *ret_net_byteorder) {
|
||||
|
||||
struct netlink_attribute *attribute;
|
||||
struct rtattr *rta;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->sealed, -EPERM);
|
||||
assert_return(data, -EINVAL);
|
||||
|
||||
assert(m->n_containers < RTNL_CONTAINER_DEPTH);
|
||||
|
||||
@ -686,10 +690,11 @@ static int netlink_message_read_internal(sd_netlink_message *m, unsigned short t
|
||||
|
||||
rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
|
||||
|
||||
*data = RTA_DATA(rta);
|
||||
if (ret_data)
|
||||
*ret_data = RTA_DATA(rta);
|
||||
|
||||
if (net_byteorder)
|
||||
*net_byteorder = attribute->net_byteorder;
|
||||
if (ret_net_byteorder)
|
||||
*ret_net_byteorder = attribute->net_byteorder;
|
||||
|
||||
return RTA_PAYLOAD(rta);
|
||||
}
|
||||
@ -974,6 +979,27 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type) {
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
/* This returns 1 when the flag is set, 0 when not set, negative errno on error. */
|
||||
|
||||
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_FLAG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r == -ENODATA)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
const NLTypeSystem *type_system;
|
||||
|
@ -733,14 +733,15 @@ static const NLType rtnl_route_types[] = {
|
||||
[RTA_VIA] = { /* See struct rtvia */ },
|
||||
[RTA_NEWDST] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_ENCAP] = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
|
||||
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_UID] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_TTL_PROPAGATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_NH_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_route_type_system = {
|
||||
@ -804,8 +805,16 @@ static const NLTypeSystem rtnl_routing_policy_rule_type_system = {
|
||||
|
||||
static const NLType rtnl_nexthop_types[] = {
|
||||
[NHA_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_GROUP] = { /* array of struct nexthop_grp */ },
|
||||
[NHA_GROUP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NHA_BLACKHOLE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[NHA_OIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NHA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NHA_ENCAP] = { .type = NETLINK_TYPE_NESTED },
|
||||
[NHA_GROUPS] = { .type = NETLINK_TYPE_FLAG },
|
||||
[NHA_MASTER] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_FDB] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_nexthop_type_system = {
|
||||
|
@ -125,20 +125,6 @@ int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) {
|
||||
struct rtmsg *rtm;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
|
||||
|
||||
rtm = NLMSG_DATA(m->hdr);
|
||||
|
||||
rtm->rtm_family = family;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type) {
|
||||
struct rtmsg *rtm;
|
||||
|
||||
@ -294,8 +280,19 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
int r;
|
||||
|
||||
assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
|
||||
assert_return((nhmsg_type == RTM_GETNEXTHOP && nh_family == AF_UNSPEC) ||
|
||||
IN_SET(nh_family, AF_INET, AF_INET6), -EINVAL);
|
||||
switch(nhmsg_type) {
|
||||
case RTM_DELNEXTHOP:
|
||||
assert_return(nh_family == AF_UNSPEC, -EINVAL);
|
||||
_fallthrough_;
|
||||
case RTM_GETNEXTHOP:
|
||||
assert_return(nh_protocol == RTPROT_UNSPEC, -EINVAL);
|
||||
break;
|
||||
case RTM_NEWNEXTHOP:
|
||||
assert_return(IN_SET(nh_family, AF_UNSPEC, AF_INET, AF_INET6), -EINVAL);
|
||||
break;
|
||||
default:
|
||||
assert_not_reached("Invalid message type.");
|
||||
}
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = message_new(rtnl, ret, nhmsg_type);
|
||||
@ -319,7 +316,7 @@ int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) {
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL);
|
||||
assert_return(m->hdr->nlmsg_type == RTM_NEWNEXTHOP, -EINVAL);
|
||||
|
||||
nhm = NLMSG_DATA(m->hdr);
|
||||
nhm->nh_flags |= flags;
|
||||
@ -327,18 +324,6 @@ int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family) {
|
||||
struct nhmsg *nhm;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
|
||||
nhm = NLMSG_DATA(m->hdr);
|
||||
nhm->nh_family = family;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family) {
|
||||
struct nhmsg *nhm;
|
||||
|
||||
@ -346,7 +331,7 @@ int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *fam
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
|
||||
nhm = NLMSG_DATA(m->hdr);
|
||||
*family = nhm->nh_family ;
|
||||
*family = nhm->nh_family;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -66,9 +66,7 @@ static void context_free_vconsole(Context *c) {
|
||||
}
|
||||
|
||||
static void context_free_locale(Context *c) {
|
||||
int p;
|
||||
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
c->locale[p] = mfree(c->locale[p]);
|
||||
}
|
||||
|
||||
@ -85,9 +83,7 @@ void context_clear(Context *c) {
|
||||
};
|
||||
|
||||
void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
|
||||
int p;
|
||||
|
||||
for (p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
|
||||
for (LocaleVariable p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
|
||||
if (isempty(locale[p]) || streq_ptr(locale[VARIABLE_LANG], locale[p]))
|
||||
locale[p] = mfree(locale[p]);
|
||||
}
|
||||
@ -138,13 +134,11 @@ int locale_read_data(Context *c, sd_bus_message *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
int p;
|
||||
|
||||
c->locale_mtime = USEC_INFINITY;
|
||||
context_free_locale(c);
|
||||
|
||||
/* Fill in what we got passed from systemd. */
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
const char *name;
|
||||
|
||||
name = locale_variable_to_string(p);
|
||||
@ -294,30 +288,16 @@ int x11_read_data(Context *c, sd_bus_message *m) {
|
||||
int locale_write_data(Context *c, char ***settings) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
struct stat st;
|
||||
int r, p;
|
||||
int r;
|
||||
|
||||
/* Set values will be returned as strv in *settings on success. */
|
||||
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
char **u;
|
||||
const char *name;
|
||||
|
||||
name = locale_variable_to_string(p);
|
||||
assert(name);
|
||||
|
||||
if (isempty(c->locale[p]))
|
||||
continue;
|
||||
|
||||
if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
u = strv_env_set(l, t);
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
strv_free_and_replace(l, u);
|
||||
}
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
if (!isempty(c->locale[p])) {
|
||||
r = strv_env_assign(&l, locale_variable_to_string(p), c->locale[p]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (strv_isempty(l)) {
|
||||
if (unlink("/etc/locale.conf") < 0)
|
||||
@ -348,39 +328,13 @@ int vconsole_write_data(Context *c) {
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
if (isempty(c->vc_keymap))
|
||||
l = strv_env_unset(l, "KEYMAP");
|
||||
else {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
char **u;
|
||||
r = strv_env_assign(&l, "KEYMAP", empty_to_null(c->vc_keymap));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
s = strjoin("KEYMAP=", c->vc_keymap);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
u = strv_env_set(l, s);
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
strv_free_and_replace(l, u);
|
||||
}
|
||||
|
||||
if (isempty(c->vc_keymap_toggle))
|
||||
l = strv_env_unset(l, "KEYMAP_TOGGLE");
|
||||
else {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
char **u;
|
||||
|
||||
s = strjoin("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
u = strv_env_set(l, s);
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
strv_free_and_replace(l, u);
|
||||
}
|
||||
r = strv_env_assign(&l, "KEYMAP_TOGGLE", empty_to_null(c->vc_keymap_toggle));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (strv_isempty(l)) {
|
||||
if (unlink("/etc/vconsole.conf") < 0)
|
||||
|
@ -55,7 +55,6 @@ static void status_info_clear(StatusInfo *info) {
|
||||
static void print_overridden_variables(void) {
|
||||
_cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
|
||||
bool print_warning = true;
|
||||
LocaleVariable j;
|
||||
int r;
|
||||
|
||||
if (arg_transport != BUS_TRANSPORT_LOCAL)
|
||||
@ -82,7 +81,7 @@ static void print_overridden_variables(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < _VARIABLE_LC_MAX; j++)
|
||||
for (LocaleVariable j = 0; j < _VARIABLE_LC_MAX; j++)
|
||||
if (variables[j]) {
|
||||
if (print_warning) {
|
||||
log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
|
||||
|
@ -37,8 +37,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) {
|
||||
_cleanup_strv_free_ char **l_set = NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
size_t c_set, c_unset;
|
||||
LocaleVariable p;
|
||||
size_t c_set = 0, c_unset = 0;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@ -51,7 +50,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) {
|
||||
if (!l_set)
|
||||
return log_oom();
|
||||
|
||||
for (p = 0, c_set = 0, c_unset = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
const char *name;
|
||||
|
||||
name = locale_variable_to_string(p);
|
||||
@ -178,7 +177,7 @@ static int property_get_locale(
|
||||
|
||||
Context *c = userdata;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int p, q, r;
|
||||
int r;
|
||||
|
||||
r = locale_read_data(c, reply);
|
||||
if (r < 0)
|
||||
@ -188,7 +187,7 @@ static int property_get_locale(
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
for (p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
for (LocaleVariable p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
char *t;
|
||||
const char *name;
|
||||
|
||||
|
@ -44,9 +44,9 @@ typedef struct BrightnessWriter {
|
||||
sd_event_source* child_event_source;
|
||||
} BrightnessWriter;
|
||||
|
||||
static void brightness_writer_free(BrightnessWriter *w) {
|
||||
static BrightnessWriter* brightness_writer_free(BrightnessWriter *w) {
|
||||
if (!w)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (w->manager && w->path)
|
||||
(void) hashmap_remove_value(w->manager->brightness_writers, w->path, w);
|
||||
@ -59,7 +59,7 @@ static void brightness_writer_free(BrightnessWriter *w) {
|
||||
|
||||
w->child_event_source = sd_event_source_unref(w->child_event_source);
|
||||
|
||||
free(w);
|
||||
return mfree(w);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(BrightnessWriter*, brightness_writer_free);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "logind-dbus.h"
|
||||
#include "logind-polkit.h"
|
||||
#include "logind-seat-dbus.h"
|
||||
#include "logind-session-dbus.h"
|
||||
#include "logind-user-dbus.h"
|
||||
@ -1047,15 +1048,7 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda
|
||||
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT,
|
||||
"Session %s not on seat %s", session_name, seat_name);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
r = check_polkit_chvt(message, m, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
|
24
src/login/logind-polkit.c
Normal file
24
src/login/logind-polkit.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "bus-polkit.h"
|
||||
#include "logind-polkit.h"
|
||||
#include "missing_capability.h"
|
||||
#include "user-util.h"
|
||||
|
||||
int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error) {
|
||||
#if ENABLE_POLKIT
|
||||
return bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&manager->polkit_registry,
|
||||
error);
|
||||
#else
|
||||
/* Allow chvt when polkit is not present. This allows a service to start a graphical session as a
|
||||
* non-root user when polkit is not compiled in, more closely matching the default polkit policy */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
9
src/login/logind-polkit.h
Normal file
9
src/login/logind-polkit.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "bus-object.h"
|
||||
#include "logind.h"
|
||||
|
||||
int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error);
|
@ -9,6 +9,7 @@
|
||||
#include "bus-polkit.h"
|
||||
#include "bus-util.h"
|
||||
#include "logind-dbus.h"
|
||||
#include "logind-polkit.h"
|
||||
#include "logind-seat-dbus.h"
|
||||
#include "logind-seat.h"
|
||||
#include "logind-session-dbus.h"
|
||||
@ -179,15 +180,7 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b
|
||||
if (session->seat != s)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&s->manager->polkit_registry,
|
||||
error);
|
||||
r = check_polkit_chvt(message, s->manager, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
@ -215,15 +208,7 @@ static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
if (to <= 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&s->manager->polkit_registry,
|
||||
error);
|
||||
r = check_polkit_chvt(message, s->manager, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
@ -243,15 +228,7 @@ static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus
|
||||
assert(message);
|
||||
assert(s);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&s->manager->polkit_registry,
|
||||
error);
|
||||
r = check_polkit_chvt(message, s->manager, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
@ -271,15 +248,7 @@ static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd
|
||||
assert(message);
|
||||
assert(s);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&s->manager->polkit_registry,
|
||||
error);
|
||||
r = check_polkit_chvt(message, s->manager, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "logind-brightness.h"
|
||||
#include "logind-dbus.h"
|
||||
#include "logind-polkit.h"
|
||||
#include "logind-seat-dbus.h"
|
||||
#include "logind-session-dbus.h"
|
||||
#include "logind-session-device.h"
|
||||
@ -192,15 +193,7 @@ int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_
|
||||
assert(message);
|
||||
assert(s);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.chvt",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&s->manager->polkit_registry,
|
||||
error);
|
||||
r = check_polkit_chvt(message, s->manager, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
|
@ -25,6 +25,8 @@ liblogind_core_sources = files('''
|
||||
logind-device.h
|
||||
logind-inhibit.c
|
||||
logind-inhibit.h
|
||||
logind-polkit.c
|
||||
logind-polkit.h
|
||||
logind-seat-dbus.c
|
||||
logind-seat-dbus.h
|
||||
logind-seat.c
|
||||
|
@ -39,18 +39,16 @@ static const char* const l2tp_local_address_type_table[_NETDEV_L2TP_LOCAL_ADDRES
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
|
||||
|
||||
static void l2tp_session_free(L2tpSession *s) {
|
||||
static L2tpSession* l2tp_session_free(L2tpSession *s) {
|
||||
if (!s)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (s->tunnel && s->section)
|
||||
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
|
||||
|
||||
network_config_section_free(s->section);
|
||||
|
||||
free(s->name);
|
||||
|
||||
free(s);
|
||||
return mfree(s);
|
||||
}
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
|
||||
|
@ -35,9 +35,9 @@ static void security_association_init(SecurityAssociation *sa) {
|
||||
sa->use_for_encoding = -1;
|
||||
}
|
||||
|
||||
static void macsec_receive_association_free(ReceiveAssociation *c) {
|
||||
static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c) {
|
||||
if (!c)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (c->macsec && c->section)
|
||||
ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
|
||||
@ -45,7 +45,7 @@ static void macsec_receive_association_free(ReceiveAssociation *c) {
|
||||
network_config_section_free(c->section);
|
||||
security_association_clear(&c->sa);
|
||||
|
||||
free(c);
|
||||
return mfree(c);
|
||||
}
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
|
||||
@ -90,9 +90,9 @@ static int macsec_receive_association_new_static(MACsec *s, const char *filename
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void macsec_receive_channel_free(ReceiveChannel *c) {
|
||||
static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
|
||||
if (!c)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (c->macsec) {
|
||||
if (c->sci.as_uint64 > 0)
|
||||
@ -104,7 +104,7 @@ static void macsec_receive_channel_free(ReceiveChannel *c) {
|
||||
|
||||
network_config_section_free(c->section);
|
||||
|
||||
free(c);
|
||||
return mfree(c);
|
||||
}
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
|
||||
@ -162,9 +162,9 @@ static int macsec_receive_channel_new_static(MACsec *s, const char *filename, un
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void macsec_transmit_association_free(TransmitAssociation *a) {
|
||||
static TransmitAssociation* macsec_transmit_association_free(TransmitAssociation *a) {
|
||||
if (!a)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (a->macsec && a->section)
|
||||
ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
|
||||
@ -172,7 +172,7 @@ static void macsec_transmit_association_free(TransmitAssociation *a) {
|
||||
network_config_section_free(a->section);
|
||||
security_association_clear(&a->sa);
|
||||
|
||||
free(a);
|
||||
return mfree(a);
|
||||
}
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
|
||||
|
@ -26,11 +26,11 @@
|
||||
|
||||
static void resolve_endpoints(NetDev *netdev);
|
||||
|
||||
static void wireguard_peer_free(WireguardPeer *peer) {
|
||||
static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
|
||||
WireguardIPmask *mask;
|
||||
|
||||
if (!peer)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (peer->wireguard) {
|
||||
LIST_REMOVE(peers, peer->wireguard->peers, peer);
|
||||
@ -54,7 +54,7 @@ static void wireguard_peer_free(WireguardPeer *peer) {
|
||||
free(peer->preshared_key_file);
|
||||
explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN);
|
||||
|
||||
free(peer);
|
||||
return mfree(peer);
|
||||
}
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer, wireguard_peer_free);
|
||||
|
@ -230,7 +230,7 @@ static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
|
||||
return CMP(a->ifindex, b->ifindex);
|
||||
}
|
||||
|
||||
static const LinkInfo* link_info_array_free(LinkInfo *array) {
|
||||
static LinkInfo* link_info_array_free(LinkInfo *array) {
|
||||
for (unsigned i = 0; array && array[i].needs_freeing; i++) {
|
||||
sd_device_unref(array[i].sd_device);
|
||||
free(array[i].ssid);
|
||||
|
@ -262,16 +262,23 @@ static int address_set_masquerade(Address *address, bool add) {
|
||||
if (!address->link->network)
|
||||
return 0;
|
||||
|
||||
if (!address->link->network->ip_masquerade)
|
||||
if (address->family == AF_INET &&
|
||||
!FLAGS_SET(address->link->network->ip_masquerade, ADDRESS_FAMILY_IPV4))
|
||||
return 0;
|
||||
|
||||
if (address->family != AF_INET)
|
||||
if (address->family == AF_INET6 &&
|
||||
!FLAGS_SET(address->link->network->ip_masquerade, ADDRESS_FAMILY_IPV6))
|
||||
return 0;
|
||||
|
||||
if (address->scope >= RT_SCOPE_LINK)
|
||||
return 0;
|
||||
|
||||
if (address->ip_masquerade_done == add)
|
||||
if (address->family == AF_INET &&
|
||||
address->ip_masquerade_done == add)
|
||||
return 0;
|
||||
|
||||
if (address->family == AF_INET6 &&
|
||||
address->ipv6_masquerade_done == add)
|
||||
return 0;
|
||||
|
||||
masked = address->in_addr;
|
||||
@ -279,11 +286,14 @@ static int address_set_masquerade(Address *address, bool add) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fw_add_masquerade(&address->link->manager->fw_ctx, add, AF_INET, &masked, address->prefixlen);
|
||||
r = fw_add_masquerade(&address->link->manager->fw_ctx, add, address->family, &masked, address->prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
address->ip_masquerade_done = add;
|
||||
if (address->family == AF_INET)
|
||||
address->ip_masquerade_done = add;
|
||||
else if (address->family == AF_INET6)
|
||||
address->ipv6_masquerade_done = add;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ typedef struct Address {
|
||||
|
||||
bool scope_set:1;
|
||||
bool ip_masquerade_done:1;
|
||||
bool ipv6_masquerade_done:1;
|
||||
AddressFamily duplicate_address_detection;
|
||||
|
||||
/* Called when address become ready */
|
||||
|
@ -850,11 +850,11 @@ int manager_new(Manager **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void manager_free(Manager *m) {
|
||||
Manager* manager_free(Manager *m) {
|
||||
Link *link;
|
||||
|
||||
if (!m)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
free(m->state_file);
|
||||
|
||||
@ -909,7 +909,7 @@ void manager_free(Manager *m) {
|
||||
|
||||
m->fw_ctx = fw_ctx_free(m->fw_ctx);
|
||||
|
||||
free(m);
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
int manager_start(Manager *m) {
|
||||
|
@ -83,7 +83,7 @@ struct Manager {
|
||||
};
|
||||
|
||||
int manager_new(Manager **ret);
|
||||
void manager_free(Manager *m);
|
||||
Manager* manager_free(Manager *m);
|
||||
|
||||
int manager_connect_bus(Manager *m);
|
||||
int manager_start(Manager *m);
|
||||
|
@ -63,7 +63,6 @@ struct IPv6Token {
|
||||
};
|
||||
|
||||
int ipv6token_new(IPv6Token **ret);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6Token *, freep);
|
||||
|
||||
static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
|
||||
return ((char*) n) + ALIGN(sizeof(NDiscDNSSL));
|
||||
|
@ -111,7 +111,7 @@ Network.DNSSEC, config_parse_dnssec_mode,
|
||||
Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
|
||||
Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp)
|
||||
Network.IPForward, config_parse_address_family_with_kernel, 0, offsetof(Network, ip_forward)
|
||||
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
|
||||
Network.IPMasquerade, config_parse_address_family_compat, 0, offsetof(Network, ip_masquerade)
|
||||
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
|
||||
Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
|
||||
Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
|
||||
|
@ -208,9 +208,8 @@ int network_verify(Network *network) {
|
||||
if (network->link_local < 0)
|
||||
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
|
||||
|
||||
/* IPMasquerade=yes implies IPForward=yes */
|
||||
if (network->ip_masquerade)
|
||||
network->ip_forward |= ADDRESS_FAMILY_IPV4;
|
||||
/* IPMasquerade implies IPForward */
|
||||
network->ip_forward |= network->ip_masquerade;
|
||||
|
||||
network_adjust_ipv6_accept_ra(network);
|
||||
network_adjust_dhcp(network);
|
||||
|
@ -110,7 +110,7 @@ struct Network {
|
||||
KeepConfiguration keep_configuration;
|
||||
char **bind_carrier;
|
||||
bool default_route_on_device;
|
||||
bool ip_masquerade;
|
||||
AddressFamily ip_masquerade;
|
||||
|
||||
/* DHCP Client Support */
|
||||
AddressFamily dhcp;
|
||||
|
@ -281,10 +281,6 @@ static int nexthop_configure(NextHop *nexthop, Link *link) {
|
||||
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m");
|
||||
|
||||
r = sd_rtnl_message_nexthop_set_family(req, nexthop->family);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set nexthop family: %m");
|
||||
}
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler,
|
||||
|
@ -61,6 +61,16 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_addr
|
||||
DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFamily);
|
||||
DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type);
|
||||
|
||||
static AddressFamily address_family_compat_from_string(const char *s) {
|
||||
if (streq_ptr(s, "yes")) /* compat name */
|
||||
return ADDRESS_FAMILY_IPV4;
|
||||
if (streq_ptr(s, "both"))
|
||||
return ADDRESS_FAMILY_YES;
|
||||
return address_family_from_string(s);
|
||||
}
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_compat, address_family_compat,
|
||||
AddressFamily, "Failed to parse option");
|
||||
|
||||
int config_parse_address_family_with_kernel(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
@ -155,10 +165,6 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi
|
||||
return 0;
|
||||
}
|
||||
|
||||
void network_config_section_free(NetworkConfigSection *cs) {
|
||||
free(cs);
|
||||
}
|
||||
|
||||
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
|
||||
NetworkConfigSection *cs;
|
||||
unsigned n = 0;
|
||||
|
@ -28,6 +28,7 @@ typedef struct NetworkConfigSection {
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_family_compat);
|
||||
|
||||
const char *address_family_to_string(AddressFamily b) _const_;
|
||||
AddressFamily address_family_from_string(const char *s) _pure_;
|
||||
@ -47,9 +48,12 @@ sd_dhcp_lease_server_type dhcp_lease_server_type_from_string(const char *s) _pur
|
||||
|
||||
int kernel_route_expiration_supported(void);
|
||||
|
||||
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
|
||||
void network_config_section_free(NetworkConfigSection *network);
|
||||
static inline NetworkConfigSection* network_config_section_free(NetworkConfigSection *cs) {
|
||||
return mfree(cs);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
|
||||
|
||||
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
|
||||
extern const struct hash_ops network_config_hash_ops;
|
||||
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
|
||||
|
||||
@ -63,13 +67,14 @@ static inline bool section_is_invalid(NetworkConfigSection *section) {
|
||||
}
|
||||
|
||||
#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \
|
||||
static inline void free_func##_or_set_invalid(type *p) { \
|
||||
static inline type* free_func##_or_set_invalid(type *p) { \
|
||||
assert(p); \
|
||||
\
|
||||
if (p->section) \
|
||||
p->section->invalid = true; \
|
||||
else \
|
||||
free_func(p); \
|
||||
return NULL; \
|
||||
} \
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
|
||||
|
@ -134,9 +134,9 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qdisc_free(QDisc *qdisc) {
|
||||
QDisc* qdisc_free(QDisc *qdisc) {
|
||||
if (!qdisc)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (qdisc->network && qdisc->section)
|
||||
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
|
||||
@ -144,7 +144,7 @@ void qdisc_free(QDisc *qdisc) {
|
||||
network_config_section_free(qdisc->section);
|
||||
|
||||
free(qdisc->tca_kind);
|
||||
free(qdisc);
|
||||
return mfree(qdisc);
|
||||
}
|
||||
|
||||
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
|
@ -74,7 +74,7 @@ extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
|
||||
/* For casting the various qdisc kinds into a qdisc */
|
||||
#define QDISC(q) (&(q)->meta)
|
||||
|
||||
void qdisc_free(QDisc *qdisc);
|
||||
QDisc* qdisc_free(QDisc *qdisc);
|
||||
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
|
||||
|
||||
int qdisc_configure(Link *link, QDisc *qdisc);
|
||||
|
@ -90,16 +90,16 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tclass_free(TClass *tclass) {
|
||||
TClass* tclass_free(TClass *tclass) {
|
||||
if (!tclass)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (tclass->network && tclass->section)
|
||||
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
|
||||
|
||||
network_config_section_free(tclass->section);
|
||||
|
||||
free(tclass);
|
||||
return mfree(tclass);
|
||||
}
|
||||
|
||||
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
|
@ -53,7 +53,7 @@ extern const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX];
|
||||
/* For casting the various tclass kinds into a tclass */
|
||||
#define TCLASS(t) (&(t)->meta)
|
||||
|
||||
void tclass_free(TClass *tclass);
|
||||
TClass* tclass_free(TClass *tclass);
|
||||
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
|
||||
|
||||
int tclass_configure(Link *link, TClass *tclass);
|
||||
|
@ -347,21 +347,18 @@ int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void manager_free(Manager *m) {
|
||||
Manager* manager_free(Manager *m) {
|
||||
if (!m)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
hashmap_free_with_destructor(m->links, link_free);
|
||||
hashmap_free(m->links_by_name);
|
||||
|
||||
sd_event_source_unref(m->network_monitor_event_source);
|
||||
sd_network_monitor_unref(m->network_monitor);
|
||||
|
||||
sd_event_source_unref(m->rtnl_event_source);
|
||||
sd_netlink_unref(m->rtnl);
|
||||
|
||||
sd_event_unref(m->event);
|
||||
free(m);
|
||||
|
||||
return;
|
||||
return mfree(m);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ struct Manager {
|
||||
sd_event *event;
|
||||
};
|
||||
|
||||
void manager_free(Manager *m);
|
||||
Manager* manager_free(Manager *m);
|
||||
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
|
||||
LinkOperationalStateRange required_operstate,
|
||||
bool any, usec_t timeout);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "firewall-util.h"
|
||||
@ -82,9 +83,9 @@ void expose_port_free_all(ExposePort *p) {
|
||||
}
|
||||
}
|
||||
|
||||
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_union *exposed) {
|
||||
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, int af, union in_addr_union *exposed) {
|
||||
ExposePort *p;
|
||||
int r, af = AF_INET;
|
||||
int r;
|
||||
|
||||
assert(exposed);
|
||||
|
||||
@ -106,19 +107,19 @@ int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_uni
|
||||
p->container_port,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to modify firewall: %m");
|
||||
log_warning_errno(r, "Failed to modify %s firewall: %m", af_to_name(af));
|
||||
}
|
||||
|
||||
*exposed = IN_ADDR_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, union in_addr_union *exposed) {
|
||||
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, int af, union in_addr_union *exposed) {
|
||||
_cleanup_free_ struct local_address *addresses = NULL;
|
||||
union in_addr_union new_exposed;
|
||||
ExposePort *p;
|
||||
bool add;
|
||||
int af = AF_INET, r;
|
||||
int r;
|
||||
|
||||
assert(exposed);
|
||||
|
||||
@ -137,7 +138,7 @@ int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *
|
||||
addresses[0].scope < RT_SCOPE_LINK;
|
||||
|
||||
if (!add)
|
||||
return expose_port_flush(fw_ctx, l, exposed);
|
||||
return expose_port_flush(fw_ctx, l, af, exposed);
|
||||
|
||||
new_exposed = addresses[0].address;
|
||||
if (in_addr_equal(af, exposed, &new_exposed))
|
||||
@ -160,7 +161,7 @@ int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *
|
||||
p->container_port,
|
||||
in_addr_is_null(af, exposed) ? NULL : exposed);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to modify firewall: %m");
|
||||
log_warning_errno(r, "Failed to modify %s firewall: %m", af_to_name(af));
|
||||
}
|
||||
|
||||
*exposed = new_exposed;
|
||||
|
@ -23,5 +23,5 @@ int expose_port_parse(ExposePort **l, const char *s);
|
||||
int expose_port_watch_rtnl(sd_event *event, int recv_fd, sd_netlink_message_handler_t handler, void *userdata, sd_netlink **ret);
|
||||
int expose_port_send_rtnl(int send_fd);
|
||||
|
||||
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, union in_addr_union *exposed);
|
||||
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_union *exposed);
|
||||
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, int af, union in_addr_union *exposed);
|
||||
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, int af, union in_addr_union *exposed);
|
||||
|
@ -1110,17 +1110,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'E': {
|
||||
char **n;
|
||||
|
||||
if (!env_assignment_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Environment variable assignment '%s' is not valid.", optarg);
|
||||
r = strv_env_replace_strdup(&arg_setenv, optarg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n = strv_env_set(arg_setenv, optarg);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
strv_free_and_replace(arg_setenv, n);
|
||||
arg_settings_mask |= SETTING_ENVIRONMENT;
|
||||
break;
|
||||
}
|
||||
@ -2471,7 +2467,8 @@ static int setup_kmsg(int kmsg_socket) {
|
||||
}
|
||||
|
||||
struct ExposeArgs {
|
||||
union in_addr_union address;
|
||||
union in_addr_union address4;
|
||||
union in_addr_union address6;
|
||||
struct FirewallContext *fw_ctx;
|
||||
};
|
||||
|
||||
@ -2482,7 +2479,8 @@ static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *user
|
||||
assert(m);
|
||||
assert(args);
|
||||
|
||||
expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, &args->address);
|
||||
expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, AF_INET, &args->address4);
|
||||
expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, AF_INET6, &args->address6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4904,7 +4902,8 @@ static int run_container(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, &expose_args->address);
|
||||
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, AF_INET, &expose_args->address4);
|
||||
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, AF_INET6, &expose_args->address6);
|
||||
}
|
||||
|
||||
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
|
||||
@ -5031,7 +5030,8 @@ static int run_container(
|
||||
return 0; /* finito */
|
||||
}
|
||||
|
||||
expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, &expose_args->address);
|
||||
expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, AF_INET, &expose_args->address4);
|
||||
expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, AF_INET6, &expose_args->address6);
|
||||
|
||||
(void) remove_veth_links(veth_name, arg_network_veth_extra);
|
||||
*veth_created = false;
|
||||
@ -5586,7 +5586,8 @@ finish:
|
||||
(void) rm_rf(p, REMOVE_ROOT);
|
||||
}
|
||||
|
||||
expose_port_flush(&fw_ctx, arg_expose_ports, &expose_args.address);
|
||||
expose_port_flush(&fw_ctx, arg_expose_ports, AF_INET, &expose_args.address4);
|
||||
expose_port_flush(&fw_ctx, arg_expose_ports, AF_INET6, &expose_args.address6);
|
||||
|
||||
if (veth_created)
|
||||
(void) remove_veth_links(veth_name, arg_network_veth_extra);
|
||||
|
@ -397,7 +397,7 @@ static int monitor_cgroup_contexts(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void manager_free(Manager *m) {
|
||||
Manager* manager_free(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
varlink_close_unref(m->varlink);
|
||||
@ -410,7 +410,7 @@ void manager_free(Manager *m) {
|
||||
hashmap_free(m->monitored_swap_cgroup_contexts);
|
||||
hashmap_free(m->monitored_mem_pressure_cgroup_contexts);
|
||||
|
||||
free(m);
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret) {
|
||||
|
@ -51,7 +51,7 @@ struct Manager {
|
||||
Varlink *varlink;
|
||||
};
|
||||
|
||||
void manager_free(Manager *m);
|
||||
Manager* manager_free(Manager *m);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
|
||||
int manager_new(Manager **ret);
|
||||
|
@ -1268,10 +1268,10 @@ static int context_read_definitions(
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
|
||||
|
||||
static int determine_current_padding(
|
||||
struct fdisk_context *c,
|
||||
|
@ -82,17 +82,16 @@ static const char *dns_cache_item_type_to_string(DnsCacheItem *item) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dns_cache_item_free(DnsCacheItem *i) {
|
||||
static DnsCacheItem* dns_cache_item_free(DnsCacheItem *i) {
|
||||
if (!i)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
dns_resource_record_unref(i->rr);
|
||||
dns_resource_key_unref(i->key);
|
||||
dns_answer_unref(i->answer);
|
||||
dns_packet_unref(i->full_packet);
|
||||
free(i);
|
||||
return mfree(i);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free);
|
||||
|
||||
static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) {
|
||||
|
@ -240,6 +240,7 @@ static void dns_server_reset_counters(DnsServer *s) {
|
||||
s->n_failed_tcp = 0;
|
||||
s->n_failed_tls = 0;
|
||||
s->packet_truncated = false;
|
||||
s->packet_invalid = false;
|
||||
s->verified_usec = 0;
|
||||
|
||||
/* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the
|
||||
@ -366,6 +367,17 @@ void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level
|
||||
log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
|
||||
}
|
||||
|
||||
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {
|
||||
assert(s);
|
||||
|
||||
/* Invoked whenever we got a packet we couldn't parse at all */
|
||||
|
||||
if (s->possible_feature_level != level)
|
||||
return;
|
||||
|
||||
s->packet_invalid = true;
|
||||
}
|
||||
|
||||
static bool dns_server_grace_period_expired(DnsServer *s) {
|
||||
usec_t ts;
|
||||
|
||||
@ -434,21 +446,46 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
|
||||
* work. Upgrade back to UDP again. */
|
||||
log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
|
||||
|
||||
} else if (s->n_failed_tls > 0 &&
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) && dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) &&
|
||||
dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
|
||||
|
||||
/* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
|
||||
* if we don't require DNS-over-TLS */
|
||||
|
||||
log_debug("Server doesn't support DNS-over-TLS, downgrading protocol...");
|
||||
s->possible_feature_level--;
|
||||
} else if (s->packet_bad_opt &&
|
||||
s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
|
||||
|
||||
/* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below
|
||||
* EDNS0 levels. After all, some records generate different responses with and without OPT RR
|
||||
* in the request. Example:
|
||||
* https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
|
||||
} else if (s->packet_invalid &&
|
||||
s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
|
||||
s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN) {
|
||||
|
||||
/* Downgrade from DO to EDNS0 + from EDNS0 to UDP, from TLS+DO to plain TLS. Or in
|
||||
* other words, if we receive a packet we cannot parse jump to the next lower feature
|
||||
* level that actually has an influence on the packet layout (and not just the
|
||||
* transport). */
|
||||
|
||||
log_debug("Got invalid packet from server, downgrading protocol...");
|
||||
s->possible_feature_level =
|
||||
s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TLS_DO ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_EDNS0 :
|
||||
DNS_SERVER_FEATURE_LEVEL_UDP;
|
||||
|
||||
} else if (s->packet_bad_opt &&
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(s->possible_feature_level) &&
|
||||
dns_server_get_dnssec_mode(s) != DNSSEC_YES &&
|
||||
dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
|
||||
|
||||
/* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to
|
||||
* below EDNS0 levels. After all, some servers generate different responses with and
|
||||
* without OPT RR in the request. Example:
|
||||
*
|
||||
* https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html
|
||||
*
|
||||
* If we are in strict DNSSEC or DoT mode, we don't do this kind of downgrade
|
||||
* however, as both modes imply EDNS0 to work (DNSSEC strictly requires it, and DoT
|
||||
* only in our implementation). */
|
||||
|
||||
log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
|
||||
@ -458,42 +495,57 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
|
||||
log_level = LOG_NOTICE;
|
||||
|
||||
} else if (s->packet_rrsig_missing &&
|
||||
s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) {
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
|
||||
dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
|
||||
|
||||
/* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't
|
||||
* augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore,
|
||||
* after all some servers generate different replies depending if an OPT RR is in the query or
|
||||
* not. */
|
||||
/* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server
|
||||
* doesn't augment responses with DNSSEC RRs. If so, let's better not ask the server
|
||||
* for it anymore, after all some servers generate different replies depending if an
|
||||
* OPT RR is in the query or not. If we are in strict DNSSEC mode, don't allow such
|
||||
* downgrades however, since a DNSSEC feature level is a requirement for strict
|
||||
* DNSSEC mode. */
|
||||
|
||||
log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
|
||||
DNS_SERVER_FEATURE_LEVEL_EDNS0;
|
||||
|
||||
} else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
|
||||
s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
|
||||
((s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_DO) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
|
||||
|
||||
/* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the
|
||||
* packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good
|
||||
* idea. We might downgrade all the way down to TCP this way.
|
||||
/* We lost too many UDP packets in a row, and are on an UDP feature level. If the
|
||||
* packets are lost, maybe the server cannot parse them, hence downgrading sounds
|
||||
* like a good idea. We might downgrade all the way down to TCP this way.
|
||||
*
|
||||
* If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss
|
||||
* might have many reasons, a broken DNSSEC implementation being only one reason. And if the
|
||||
* user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */
|
||||
|
||||
log_debug("Lost too many UDP packets, downgrading feature level...");
|
||||
s->possible_feature_level--;
|
||||
if (s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_DO) /* skip over TLS_PLAIN */
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
|
||||
else
|
||||
s->possible_feature_level--;
|
||||
|
||||
} else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
|
||||
s->packet_truncated &&
|
||||
s->possible_feature_level > (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
|
||||
s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
|
||||
DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
|
||||
(!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
|
||||
|
||||
/* We got too many TCP connection failures in a row, we had at least one truncated packet, and
|
||||
* are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0
|
||||
* data we hope to make the packet smaller, so that it still works via UDP given that TCP
|
||||
* appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't
|
||||
* go further down, since that's TCP, and TCP failed too often after all. */
|
||||
/* We got too many TCP connection failures in a row, we had at least one truncated
|
||||
* packet, and are on feature level above UDP. By downgrading things and getting rid
|
||||
* of DNSSEC or EDNS0 data we hope to make the packet smaller, so that it still
|
||||
* works via UDP given that TCP appears not to be a fallback. Note that if we are
|
||||
* already at the lowest UDP level, we don't go further down, since that's TCP, and
|
||||
* TCP failed too often after all. */
|
||||
|
||||
log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
|
||||
s->possible_feature_level--;
|
||||
|
||||
if (DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level))
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0; /* Go DNSSEC → EDNS0 */
|
||||
else
|
||||
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; /* Go EDNS0 → UDP */
|
||||
}
|
||||
|
||||
if (p != s->possible_feature_level) {
|
||||
@ -589,7 +641,10 @@ bool dns_server_dnssec_supported(DnsServer *server) {
|
||||
|
||||
/* Returns whether the server supports DNSSEC according to what we know about it */
|
||||
|
||||
if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO)
|
||||
if (dns_server_get_dnssec_mode(server) == DNSSEC_YES) /* If strict DNSSEC mode is enabled, always assume DNSSEC mode is supported. */
|
||||
return true;
|
||||
|
||||
if (!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(server->possible_feature_level))
|
||||
return false;
|
||||
|
||||
if (server->packet_bad_opt)
|
||||
@ -903,13 +958,15 @@ void dns_server_dump(DnsServer *s, FILE *f) {
|
||||
"\tFailed TCP attempts: %u\n"
|
||||
"\tSeen truncated packet: %s\n"
|
||||
"\tSeen OPT RR getting lost: %s\n"
|
||||
"\tSeen RRSIG RR missing: %s\n",
|
||||
"\tSeen RRSIG RR missing: %s\n"
|
||||
"\tSeen invalid packet: %s\n",
|
||||
s->received_udp_packet_max,
|
||||
s->n_failed_udp,
|
||||
s->n_failed_tcp,
|
||||
yes_no(s->packet_truncated),
|
||||
yes_no(s->packet_bad_opt),
|
||||
yes_no(s->packet_rrsig_missing));
|
||||
yes_no(s->packet_rrsig_missing),
|
||||
yes_no(s->packet_invalid));
|
||||
}
|
||||
|
||||
void dns_server_unref_stream(DnsServer *s) {
|
||||
|
@ -40,7 +40,10 @@ typedef enum DnsServerFeatureLevel {
|
||||
|
||||
#define DNS_SERVER_FEATURE_LEVEL_WORST 0
|
||||
#define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1)
|
||||
#define DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(x) ((x) >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
|
||||
#define DNS_SERVER_FEATURE_LEVEL_IS_TLS(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN, DNS_SERVER_FEATURE_LEVEL_TLS_DO)
|
||||
#define DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(x) ((x) >= DNS_SERVER_FEATURE_LEVEL_DO)
|
||||
#define DNS_SERVER_FEATURE_LEVEL_IS_UDP(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_UDP, DNS_SERVER_FEATURE_LEVEL_EDNS0, DNS_SERVER_FEATURE_LEVEL_DO, DNS_SERVER_FEATURE_LEVEL_LARGE)
|
||||
|
||||
const char* dns_server_feature_level_to_string(int i) _const_;
|
||||
int dns_server_feature_level_from_string(const char *s) _pure_;
|
||||
@ -78,9 +81,10 @@ struct DnsServer {
|
||||
unsigned n_failed_tcp;
|
||||
unsigned n_failed_tls;
|
||||
|
||||
bool packet_truncated:1;
|
||||
bool packet_bad_opt:1;
|
||||
bool packet_rrsig_missing:1;
|
||||
bool packet_truncated:1; /* Set when TC bit was set on reply */
|
||||
bool packet_bad_opt:1; /* Set when OPT was missing or otherwise bad on reply */
|
||||
bool packet_rrsig_missing:1; /* Set when RRSIG was missing */
|
||||
bool packet_invalid:1; /* Set when we failed to parse a reply */
|
||||
|
||||
usec_t verified_usec;
|
||||
usec_t features_grace_period_usec;
|
||||
@ -119,6 +123,7 @@ void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level);
|
||||
void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level);
|
||||
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
|
||||
void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level);
|
||||
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level);
|
||||
|
||||
DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);
|
||||
|
||||
|
@ -162,23 +162,23 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
|
||||
|
||||
bool dns_transaction_gc(DnsTransaction *t) {
|
||||
DnsTransaction* dns_transaction_gc(DnsTransaction *t) {
|
||||
assert(t);
|
||||
|
||||
/* Returns !NULL if we can't gc yet. */
|
||||
|
||||
if (t->block_gc > 0)
|
||||
return true;
|
||||
return t;
|
||||
|
||||
if (set_isempty(t->notify_query_candidates) &&
|
||||
set_isempty(t->notify_query_candidates_done) &&
|
||||
set_isempty(t->notify_zone_items) &&
|
||||
set_isempty(t->notify_zone_items_done) &&
|
||||
set_isempty(t->notify_transactions) &&
|
||||
set_isempty(t->notify_transactions_done)) {
|
||||
dns_transaction_free(t);
|
||||
return false;
|
||||
}
|
||||
set_isempty(t->notify_transactions_done))
|
||||
return dns_transaction_free(t);
|
||||
|
||||
return true;
|
||||
return t;
|
||||
}
|
||||
|
||||
static uint16_t pick_new_id(Manager *m) {
|
||||
@ -502,7 +502,12 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
|
||||
|
||||
assert(t);
|
||||
|
||||
log_debug("Retrying transaction %" PRIu16 ".", t->id);
|
||||
/* Retries the transaction as it is, possibly on a different server */
|
||||
|
||||
if (next_server)
|
||||
log_debug("Retrying transaction %" PRIu16 ", after switching servers.", t->id);
|
||||
else
|
||||
log_debug("Retrying transaction %" PRIu16 ".", t->id);
|
||||
|
||||
/* Before we try again, switch to a new server. */
|
||||
if (next_server)
|
||||
@ -513,12 +518,25 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
|
||||
dns_transaction_complete_errno(t, r);
|
||||
}
|
||||
|
||||
static bool dns_transaction_limited_retry(DnsTransaction *t) {
|
||||
assert(t);
|
||||
|
||||
/* If we haven't tried all different servers yet, let's try again with a different server */
|
||||
|
||||
if (t->n_picked_servers >= dns_scope_get_n_dns_servers(t->scope))
|
||||
return false;
|
||||
|
||||
dns_transaction_retry(t, /* next_server= */ true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dns_transaction_maybe_restart(DnsTransaction *t) {
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
/* Returns > 0 if the transaction was restarted, 0 if not */
|
||||
/* Restarts the transaction, under a new ID if the feature level of the server changed since we first
|
||||
* tried, without changing DNS server. Returns > 0 if the transaction was restarted, 0 if not. */
|
||||
|
||||
if (!t->server)
|
||||
return 0;
|
||||
@ -911,11 +929,8 @@ static void dns_transaction_process_dnssec(DnsTransaction *t) {
|
||||
/* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe
|
||||
* that works. */
|
||||
|
||||
if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
|
||||
/* We tried fewer servers on this transaction than we know, let's try another one then */
|
||||
dns_transaction_retry(t, true);
|
||||
if (dns_transaction_limited_retry(t))
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK, let's give up, apparently all servers we tried didn't work. */
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
|
||||
@ -1098,11 +1113,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
||||
* packet loss, but is not going to give us better rcodes should we actually have
|
||||
* managed to get them already at UDP level. */
|
||||
|
||||
if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
|
||||
/* We tried fewer servers on this transaction than we know, let's try another one then */
|
||||
dns_transaction_retry(t, true);
|
||||
if (dns_transaction_limited_retry(t))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Give up, accept the rcode */
|
||||
log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
|
||||
@ -1133,8 +1145,11 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
||||
if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) {
|
||||
/* This server refused our request? If so, try again, use a different server */
|
||||
log_debug("Server returned REFUSED, switching servers, and retrying.");
|
||||
dns_transaction_retry(t, true /* pick a new server */);
|
||||
return;
|
||||
|
||||
if (dns_transaction_limited_retry(t))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (DNS_PACKET_TC(p))
|
||||
@ -1180,7 +1195,11 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
||||
goto fail;
|
||||
|
||||
/* On DNS, couldn't send? Try immediately again, with a new server */
|
||||
dns_transaction_retry(t, true);
|
||||
if (dns_transaction_limited_retry(t))
|
||||
return;
|
||||
|
||||
/* No new server to try, give up */
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -1189,6 +1208,16 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
||||
/* After the superficial checks, actually parse the message. */
|
||||
r = dns_packet_extract(p);
|
||||
if (r < 0) {
|
||||
if (t->server) {
|
||||
dns_server_packet_invalid(t->server, t->current_feature_level);
|
||||
|
||||
r = dns_transaction_maybe_restart(t);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
if (r > 0) /* Transaction got restarted... */
|
||||
return;
|
||||
}
|
||||
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
|
||||
return;
|
||||
}
|
||||
@ -1296,7 +1325,10 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
|
||||
|
||||
dns_transaction_close_connection(t, /* use_graveyard = */ false);
|
||||
|
||||
dns_transaction_retry(t, true);
|
||||
if (dns_transaction_limited_retry(t)) /* Try a different server */
|
||||
return 0;
|
||||
|
||||
dns_transaction_complete_errno(t, r);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0) {
|
||||
@ -1415,7 +1447,8 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat
|
||||
|
||||
log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
|
||||
|
||||
dns_transaction_retry(t, true);
|
||||
dns_transaction_retry(t, true); /* try a different server, but given this means packet loss, let's do
|
||||
* so even if we already tried a bunch */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ struct DnsTransaction {
|
||||
int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key, DnsPacket *bypass, uint64_t flags);
|
||||
DnsTransaction* dns_transaction_free(DnsTransaction *t);
|
||||
|
||||
bool dns_transaction_gc(DnsTransaction *t);
|
||||
DnsTransaction* dns_transaction_gc(DnsTransaction *t);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_gc);
|
||||
|
||||
int dns_transaction_go(DnsTransaction *t);
|
||||
|
@ -26,16 +26,15 @@ void dns_zone_item_probe_stop(DnsZoneItem *i) {
|
||||
dns_transaction_gc(t);
|
||||
}
|
||||
|
||||
static void dns_zone_item_free(DnsZoneItem *i) {
|
||||
static DnsZoneItem* dns_zone_item_free(DnsZoneItem *i) {
|
||||
if (!i)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
dns_zone_item_probe_stop(i);
|
||||
dns_resource_record_unref(i->rr);
|
||||
|
||||
free(i);
|
||||
return mfree(i);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free);
|
||||
|
||||
static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "resolved-manager.h"
|
||||
|
||||
#define TLS_PROTOCOL_PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gnutls_session_t, gnutls_deinit, NULL);
|
||||
|
||||
static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) {
|
||||
int r;
|
||||
|
@ -21,13 +21,13 @@ int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask);
|
||||
|
||||
/* acl_free takes multiple argument types.
|
||||
* Multiple cleanup functions are necessary. */
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(acl_t, acl_free, NULL);
|
||||
#define acl_free_charp acl_free
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, acl_free_charp, NULL);
|
||||
#define acl_free_uid_tp acl_free
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(uid_t*, acl_free_uid_tp, NULL);
|
||||
#define acl_free_gid_tp acl_free
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gid_t*, acl_free_gid_tp, NULL);
|
||||
|
||||
#else
|
||||
#define ACL_READ 0x04
|
||||
|
@ -123,14 +123,15 @@ int barrier_create(Barrier *b) {
|
||||
*
|
||||
* If @b is NULL, this is a no-op.
|
||||
*/
|
||||
void barrier_destroy(Barrier *b) {
|
||||
Barrier* barrier_destroy(Barrier *b) {
|
||||
if (!b)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
b->me = safe_close(b->me);
|
||||
b->them = safe_close(b->them);
|
||||
safe_close_pair(b->pipe);
|
||||
b->barriers = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,7 +37,7 @@ struct Barrier {
|
||||
#define BARRIER_NULL {-1, -1, {-1, -1}, 0}
|
||||
|
||||
int barrier_create(Barrier *obj);
|
||||
void barrier_destroy(Barrier *b);
|
||||
Barrier* barrier_destroy(Barrier *b);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy);
|
||||
|
||||
|
@ -24,11 +24,11 @@
|
||||
#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
|
||||
#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
|
||||
|
||||
Bitmap *bitmap_new(void) {
|
||||
Bitmap* bitmap_new(void) {
|
||||
return new0(Bitmap, 1);
|
||||
}
|
||||
|
||||
Bitmap *bitmap_copy(Bitmap *b) {
|
||||
Bitmap* bitmap_copy(Bitmap *b) {
|
||||
Bitmap *ret;
|
||||
|
||||
ret = bitmap_new();
|
||||
@ -43,12 +43,12 @@ Bitmap *bitmap_copy(Bitmap *b) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bitmap_free(Bitmap *b) {
|
||||
Bitmap* bitmap_free(Bitmap *b) {
|
||||
if (!b)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
free(b->bitmaps);
|
||||
free(b);
|
||||
return mfree(b);
|
||||
}
|
||||
|
||||
int bitmap_ensure_allocated(Bitmap **b) {
|
||||
|
@ -12,10 +12,10 @@ typedef struct Bitmap {
|
||||
size_t bitmaps_allocated;
|
||||
} Bitmap;
|
||||
|
||||
Bitmap *bitmap_new(void);
|
||||
Bitmap *bitmap_copy(Bitmap *b);
|
||||
Bitmap* bitmap_new(void);
|
||||
Bitmap* bitmap_copy(Bitmap *b);
|
||||
int bitmap_ensure_allocated(Bitmap **b);
|
||||
void bitmap_free(Bitmap *b);
|
||||
Bitmap* bitmap_free(Bitmap *b);
|
||||
|
||||
int bitmap_set(Bitmap *b, unsigned n);
|
||||
void bitmap_unset(Bitmap *b, unsigned n);
|
||||
|
@ -6,5 +6,5 @@
|
||||
|
||||
# include "macro.h"
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(blkid_probe, blkid_free_probe, NULL);
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user