[![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)<br/>
-[![Build Status](https://dev.azure.com/evvers/systemd-systemd/_apis/build/status/systemd.systemd?branchName=master)](https://dev.azure.com/evvers/systemd-systemd/_build/latest?definitionId=1&branchName=master)
+[![Build Status](https://dev.azure.com/evvers/systemd-systemd/_apis/build/status/systemd.systemd?branchName=master)](https://dev.azure.com/evvers/systemd-systemd/_build/latest?definitionId=1&branchName=master)<br/>
+[![Packaging status](https://repology.org/badge/tiny-repos/systemd.svg)](https://repology.org/project/systemd/versions)
## Details
--- /dev/null
+---
+title: Desktop Environment Integration
+category: Concepts
+layout: default
+---
+
+# Desktop Environments
+
+NOTE: This document is a work-in-progress.
+
+## Single Graphical Session
+
+systemd only supports running one graphical session per user at a time.
+While this might not have always been the case historically, having multiple
+sessions for one user running at the same time is problematic.
+The DBus session bus is shared between all the logins, and services that are
+started must be implicitly assigned to the user's current graphical session.
+
+In principle it is possible to run a single graphical session across multiple
+logind seats, and this could be a way to use more than one display per user.
+When a user logs in to a second seat, the seat resources could be assigned
+to the existing session, allowing the graphical environment to present it
+is a single seat.
+Currently nothing like this is supported or even planned.
+
+## Pre-defined systemd units
+
+[`systemd.special(7)`](https://www.freedesktop.org/software/systemd/man/systemd.special.html)
+defines the `graphical-session.target` and `graphical-session-pre.target` to
+allow cross-desktop integration. Furthermore, systemd defines the three base
+slices `background`, `apps` and `session`.
+All units should be placed into one of these slices depending on their purposes:
+
+ * `session.slice`: Contains only processes essential to run the user's graphical session
+ * `apps.slice`: Contains all normal applications that the user is running
+ * `background.slice`: Useful for low-priority background tasks
+
+The purpose of this grouping is to assign different priorities to the
+applications.
+This could e.g. mean reserving memory to session processes,
+preferentially killing background tasks in out-of-memory situations
+or assinging different memory/CPU/IO priorities to ensure that the session
+runs smoothly under load.
+
+TODO: Will there be a default to place units into e.g. `apps.slice` by default
+rather than the root slice?
+
+## XDG standardization for applications
+
+To ensure cross-desktop compatibility and encourage sharing of good practices,
+desktop environments should adhere to the following conventions:
+
+ * Application units should follow the scheme `apps-<launcher>-<ApplicationID>-<RANDOM>.service`,
+ e.g. `apps-gnome-org.gnome.Evince-12345.service`,
+ `apps-flatpak-org.telegram.desktop-12345.service` or `apps-KDE-org.kde.okular-12345.service`.
+ * Using `.service` units instead of `.scope` units, i.e. allowing systemd to
+ start the process on behalf of the caller,
+ instead of the caller starting the process and letting systemd know about it,
+ is encouraged.
+ * If no application ID is available, the launcher should generate a reasonable
+ name when possible (e.g. using `basename(argv[0])`). This name must not
+ contain a `-` character.
+
+This has the following advantages:
+ * Using the `apps-<launcher>-` prefix means that the unit defaults can be
+ adjusted using desktop environment specific drop-in files.
+ * The application ID can be retrieved by stripping the prefix and postfix.
+ This in turn should map to the corresponding `.desktop` file when available
+
+TODO: Define the name of slices that should be used.
+This could be `apps-<launcher>-<ApplicationID>-<RANDOM>.slice`.
+
+TODO: Does it really make sense to insert the `<launcher>`? In GNOME I am
+currently using a drop-in to configure `BindTo=graphical-session.target`,
+`CollectMode=inactive-or-failed` and `TimeoutSec=5s`. I feel that such a
+policy makes sense, but it may make much more sense to just define a
+global default for all (graphical) applications.
+
+ * Should application lifetime be bound to the session?
+ * May the user have applications that do not belong to the graphical session (e.g. launched from SSH)?
+ * Could we maybe add a default `apps-.service.d` drop-in configuration?
+
+## XDG autostart integration
+
+To allow XDG autostart integration, systemd will ship a cross-desktop generator
+to create appropriate units for the autostart directory.
+Desktop Environments will be able to make use of this simply by starting the
+appropriate XDG related targets (representing e.g. content of the
+`$XDG_CURRENT_DESKTOP` environment variable to handle `OnlyShowIn/NotShowIn`).
+The names and ordering rules for these targets are to be defined.
+
+This generator will likely never support certain desktop specific extensions.
+One such example is the GNOME specific feature to bind a service to a settings
+variable.
+
+## Startup and shutdown best practices
+
+Question here are:
+
+ * Are there strong opinions on how the session-leader process should watch the user's session units?
+ * Should systemd/logind/… provide an integrated way to define a session in terms of a running *user* unit?
+ * Is having `gnome-session-shutdown.target` that is run with `replace-irreversibly` considered a good practice?
EVDEV_ABS_35=::30
EVDEV_ABS_36=::29
+#########################################
+# Star Labs
+#########################################
+
+# Star LabTop Mk III
+evdev:name:ALPS0001:00 0911:5288 Touchpad:dmi:*svnStarLabs:pnLabTop*
+ EVDEV_ABS_00=0:2627:25
+ EVDEV_ABS_01=0:1331:20
+ EVDEV_ABS_35=0:2627:25
+ EVDEV_ABS_36=0:1331:20
+
+# Star Lite Mk II
+evdev:name:ALPS0001:00 0911:5288 Touchpad:dmi:*svnStarLabs:pnLite:*
+ EVDEV_ABS_00=55:1750:16
+ EVDEV_ABS_01=51:950:15
+ EVDEV_ABS_35=55:1750:16
+ EVDEV_ABS_36=51:950:15
+
#########################################
# System76
#########################################
sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnDell*:pnVostro5581:*
ACCEL_LOCATION=base
+# Dell Venue 8 Pro 3845
+sensor:modalias:acpi:INVN6500*:dmi:*svnDellInc.*:pnVenue8Pro3845*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
# Dell Venue 10 Pro 5055
sensor:modalias:acpi:INVN6500*:dmi:*svnDell*:pnVenue10Pro5055*
ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1
''],
['sd_bus_set_sender', '3', ['sd_bus_get_sender'], ''],
['sd_bus_set_watch_bind', '3', ['sd_bus_get_watch_bind'], ''],
- ['sd_bus_slot_ref',
+ ['sd_bus_slot_get_bus',
'3',
- ['sd_bus_slot_get_bus', 'sd_bus_slot_unref', 'sd_bus_slot_unrefp'],
+ ['sd_bus_slot_get_current_handler',
+ 'sd_bus_slot_get_current_message',
+ 'sd_bus_slot_get_current_userdata'],
''],
+ ['sd_bus_slot_ref', '3', ['sd_bus_slot_unref', 'sd_bus_slot_unrefp'], ''],
['sd_bus_slot_set_description', '3', ['sd_bus_slot_get_description'], ''],
['sd_bus_slot_set_destroy_callback',
'3',
<citerefentry><refentrytitle>sd_bus_set_method_call_timeout</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_set_watch_bind</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-<citerefentry><refentrytitle>sd_bus_set_close_on_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+<citerefentry><refentrytitle>sd_bus_set_close_on_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>sd_bus_slot_get_current_handler</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>sd_bus_slot_get_current_message</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>sd_bus_slot_get_current_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_slot_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_slot_set_destroy_callback</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
--- /dev/null
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_bus_slot_get_bus" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>sd_bus_slot_get_bus</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_slot_get_bus</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_slot_get_bus</refname>
+ <refname>sd_bus_slot_get_current_handler</refname>
+ <refname>sd_bus_slot_get_current_message</refname>
+ <refname>sd_bus_slot_get_current_userdata</refname>
+
+ <refpurpose>Query information attached to a bus slot object</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>sd_bus *<function>sd_bus_slot_get_bus</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>sd_bus_message_handler_t <function>sd_bus_slot_get_current_handler</function>
+ </funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>sd_bus_message *<function>sd_bus_slot_get_current_message</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void *<function>sd_bus_slot_get_current_userdata</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_slot_get_bus()</function> returns the bus object that message
+ <parameter>slot</parameter> is attached to.</para>
+
+ <para><function>sd_bus_slot_get_current_handler()</function>,
+ <function>sd_bus_slot_get_current_message()</function> and
+ <function>sd_bus_slot_get_current_userdata()</function> return the current handler, message and
+ userdata respectively of the bus <parameter>slot</parameter> is attached to if we're currently
+ executing the callback associated with <parameter>slot</parameter>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para><function>sd_bus_slot_get_bus()</function> always returns the bus object.</para>
+
+ <para>On success, <function>sd_bus_slot_get_current_handler()</function>,
+ <function>sd_bus_slot_get_current_message()</function> and
+ <function>sd_bus_slot_get_current_userdata()</function> return the requested object. On failure,
+ they return <constant>NULL</constant>.</para>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ </para>
+ </refsect1>
+
+</refentry>
<refname>sd_bus_slot_ref</refname>
<refname>sd_bus_slot_unref</refname>
<refname>sd_bus_slot_unrefp</refname>
- <refname>sd_bus_slot_get_bus</refname>
<refpurpose>Create and destroy references to a bus slot object</refpurpose>
</refnamediv>
<funcdef>void <function>sd_bus_slot_unrefp</function></funcdef>
<paramdef>sd_bus_slot **<parameter>slotp</parameter></paramdef>
</funcprototype>
-
- <funcprototype>
- <funcdef>sd_bus *<function>sd_bus_slot_get_bus</function></funcdef>
- <paramdef>sd_bus_slot *<parameter>m</parameter></paramdef>
- </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
execute no operation if the passed in bus object address is
<constant>NULL</constant>. <function>sd_bus_slot_unrefp()</function> will first dereference
its argument, which must not be <constant>NULL</constant>, and will execute no operation if
- <emphasis>that</emphasis> is <constant>NULL</constant>.
- </para>
-
- <para><function>sd_bus_slot_get_bus()</function> returns the bus object that message
- <parameter>slot</parameter> is attached to.</para>
+ <emphasis>that</emphasis> is <constant>NULL</constant>.</para>
</refsect1>
<refsect1>
<para><function>sd_bus_slot_ref()</function> always returns the argument.</para>
<para><function>sd_bus_slot_unref()</function> always returns <constant>NULL</constant>.</para>
-
- <para><function>sd_bus_slot_get_bus()</function> always returns the bus object.</para>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
read via <function>sd_network_link_get_sip_servers()</function> function.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term><varname>UseMTU=</varname></term>
<listitem>
<varname>DNS=</varname>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>POP3Servers=</varname></term>
+
+ <listitem><para>Similar to the <varname>DNS=</varname> settings described above, these
+ settings configure whether and what POP3 server information shall be emitted as part of
+ the DHCP lease. The same syntax, propagation semantics and defaults apply as for
+ <varname>DNS=</varname>.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>EmitRouter=</varname></term>
unsigned long i;
int r;
+ /* Check that we can use PR_CAP_AMBIENT or quit early. */
+ if (!ambient_capabilities_supported())
+ return 0;
+
/* Add the capabilities to the ambient set. */
if (also_inherit) {
bool mac_selinux_use(void) {
#if HAVE_SELINUX
- if (cached_use < 0)
+ if (_unlikely_(cached_use < 0)) {
cached_use = is_selinux_enabled() > 0;
+ log_debug("SELinux enabled state cached to: %s", cached_use ? "enabled" : "disabled");
+ }
return cached_use;
#else
bool mac_selinux_enforcing(void) {
#if HAVE_SELINUX
- if (cached_enforcing < 0) {
+ if (_unlikely_(cached_enforcing < 0)) {
cached_enforcing = security_getenforce();
- if (cached_enforcing == -1) {
- log_error_errno(errno, "Failed to get SELinux enforced status: %m");
- }
+ if (cached_enforcing == -1)
+ log_error_errno(errno, "Failed to get SELinux enforced status, continue in enforcing mode: %m");
+ else
+ log_debug("SELinux enforcing state cached to: %s", cached_enforcing ? "enforcing" : "permissive");
}
- /* treat failure as enforced mode */
+ /* treat failure as enforcing mode */
return (cached_enforcing != 0);
#else
return false;
static int setenforce_callback(int enforcing) {
cached_enforcing = enforcing;
+ log_debug("SELinux enforcing state updated to: %s", cached_enforcing ? "enforcing" : "permissive");
+
return 0;
}
#endif
}
d->sysfs = TAKE_PTR(copy);
+ unit_add_to_dbus_queue(UNIT(d));
+
return 0;
}
if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
device_upgrade_mount_deps(u);
- /* Note that this won't dispatch the load queue, the caller has to do that if needed and appropriate */
- unit_add_to_dbus_queue(u);
-
return 0;
fail:
sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
}
- log_debug_errno(r, "SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %m",
- scon, fcon, tclass, permission, path, cl);
+ log_debug_errno(r, "SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s path=%s cmdline=%s: %m",
+ scon, fcon, tclass, permission, enforce ? "enforcing" : "permissive", path, cl);
return enforce ? r : 0;
}
Get rid of the deleted files now so they don't stay around indefinitely. */
ORDERED_HASHMAP_FOREACH(f, j->files, i) {
r = journal_file_fstat(f);
- if (r < 0) {
+ if (r == -EIDRM)
+ remove_file_real(j, f);
+ else if (r < 0) {
log_debug_errno(r,"Failed to fstat() journal file '%s' : %m", f->path);
continue;
}
-
- if (f->last_stat.st_nlink <= 0)
- remove_file_real(j, f);
}
/* The journal might have changed since the context
struct in_addr *sip;
size_t sip_size;
+ struct in_addr *pop3_server;
+ size_t pop3_server_size;
+
struct sd_dhcp_route *static_route;
size_t static_route_size, static_route_allocated;
char *timezone;
- struct in_addr *ntp, *dns, *sip;
- unsigned n_ntp, n_dns, n_sip;
+ struct in_addr *ntp, *dns, *sip, *pop3_server;
+ unsigned n_ntp, n_dns, n_sip, n_pop3_server;
OrderedHashmap *extra_options;
OrderedHashmap *vendor_options;
return (int) lease->sip_size;
}
+int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr) {
+ assert_return(lease, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ if (lease->pop3_server_size <= 0)
+ return -ENODATA;
+
+ *addr = lease->pop3_server;
+ return (int) lease->pop3_server_size;
+}
+
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL);
free(lease->dns);
free(lease->ntp);
free(lease->sip);
+ free(lease->pop3_server);
free(lease->static_route);
free(lease->client_id);
free(lease->vendor_specific);
log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
break;
+ case SD_DHCP_OPTION_POP3_SERVER:
+ r = lease_parse_in_addrs(option, len, &lease->pop3_server, &lease->pop3_server_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m");
+ break;
+
case SD_DHCP_OPTION_STATIC_ROUTE:
r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0)
*dns = NULL,
*ntp = NULL,
*sip = NULL,
+ *pop3_server = NULL,
*mtu = NULL,
*routes = NULL,
*domains = NULL,
"DNS", &dns,
"NTP", &ntp,
"SIP", &sip,
+ "POP3_SERVERS", &pop3_server,
"MTU", &mtu,
"DOMAINNAME", &lease->domainname,
"HOSTNAME", &lease->hostname,
lease->sip_size = r;
}
+ if (pop3_server) {
+ r = deserialize_in_addrs(&lease->pop3_server, pop3_server);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3_server);
+ else
+ lease->pop3_server_size = r;
+ }
+
if (mtu) {
r = safe_atou16(mtu, &lease->mtu);
if (r < 0)
free(server->dns);
free(server->ntp);
free(server->sip);
+ free(server->pop3_server);
hashmap_free(server->leases_by_client_id);
return r;
}
+ if (server->n_pop3_server > 0) {
+ r = dhcp_option_append(
+ &packet->dhcp, req->max_optlen, &offset, 0,
+ SD_DHCP_OPTION_POP3_SERVER,
+ sizeof(struct in_addr) * server->n_pop3_server, server->pop3_server);
+ if (r < 0)
+ return r;
+ }
+
if (server->timezone) {
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
return 1;
}
+int sd_dhcp_server_set_pop3_server(sd_dhcp_server *server, const struct in_addr pop3_server[], unsigned n) {
+ assert_return(server, -EINVAL);
+ assert_return(pop3_server || n <= 0, -EINVAL);
+
+ if (server->n_pop3_server == n &&
+ memcmp(server->pop3_server, pop3_server, sizeof(struct in_addr) * n) == 0)
+ return 0;
+
+ if (n <= 0) {
+ server->pop3_server = mfree(server->pop3_server);
+ server->n_pop3_server = 0;
+ } else {
+ struct in_addr *c;
+
+ c = newdup(struct in_addr, pop3_server, n);
+ if (!c)
+ return -ENOMEM;
+
+ free_and_replace(server->pop3_server, c);
+ server->n_pop3_server = n;
+ }
+
+ return 1;
+}
+
int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
assert_return(server, -EINVAL);
return network_link_get_strv(ifindex, "SIP", ret);
}
+_public_ int sd_network_link_get_pop3_servers(int ifindex, char ***pop3) {
+ return network_link_get_strv(ifindex, "POP3_SERVERS", pop3);
+}
+
_public_ int sd_network_link_get_dns_default_route(int ifindex) {
char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
_cleanup_free_ char *s = NULL;
sd_hwdb *hwdb,
const LinkInfo *info) {
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL;
+ _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL,
+ **pop3_server = NULL;
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
_cleanup_free_ char *t = NULL, *network = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
(void) sd_network_link_get_route_domains(info->ifindex, &route_domains);
(void) sd_network_link_get_ntp(info->ifindex, &ntp);
(void) sd_network_link_get_sip(info->ifindex, &sip);
+ (void) sd_network_link_get_pop3_servers(info->ifindex, &pop3_server);
if (info->sd_device) {
(void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link);
if (r < 0)
return r;
r = dump_list(table, "SIP:", sip);
+ if (r < 0)
+ return r;
+ r = dump_list(table, "POP3 servers:", pop3_server);
if (r < 0)
return r;
r = dump_ifindexes(table, "Carrier Bound To:", carrier_bound_to);
return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
}
+static int link_push_uplink_pop3_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+ _cleanup_free_ struct in_addr *addresses = NULL;
+ size_t n_addresses = 0, n_allocated = 0;
+ char **a;
+
+ if (!link->network)
+ return 0;
+
+ log_link_debug(link, "Copying POP3 server information from link");
+
+ STRV_FOREACH(a, link->network->pop3) {
+ union in_addr_union ia;
+
+ /* Only look for IPv4 addresses */
+ if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
+ continue;
+
+ /* Never propagate obviously borked data */
+ if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
+
+ addresses[n_addresses++] = ia.in;
+ }
+
+ if (link->dhcp_lease) {
+ const struct in_addr *da = NULL;
+ int j, n;
+
+ n = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &da);
+ if (n > 0) {
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ return log_oom();
+
+ for (j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
+ }
+ }
+
+ if (n_addresses <= 0)
+ return 0;
+
+ return sd_dhcp_server_set_pop3_server(s, addresses, n_addresses);
+}
+
static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) {
_cleanup_free_ struct in_addr *addresses = NULL;
size_t n_addresses = 0, n_allocated = 0;
log_link_warning_errno(link, r, "Failed to set SIP server for DHCP server, ignoring: %m");
}
+ if (link->network->n_dhcp_server_pop3 > 0)
+ r = sd_dhcp_server_set_pop3_server(link->dhcp_server, link->network->dhcp_server_pop3, link->network->n_dhcp_server_pop3);
+ else {
+ if (!acquired_uplink)
+ uplink = manager_find_uplink(link->manager, link);
+
+ if (!uplink) {
+ log_link_debug(link, "Not emitting POP3 server information on link, couldn't find suitable uplink.");
+ r = 0;
+ } else
+ r = link_push_uplink_pop3_to_dhcp_server(uplink, link->dhcp_server);
+
+ }
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set POP3 server for DHCP server, ignoring: %m");
+
r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set router emission for DHCP server: %m");
n->dhcp_server_sip = m;
}
}
+
+int config_parse_dhcp_server_pop3_servers(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ union in_addr_union a;
+ struct in_addr *m;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ r = in_addr_from_string(AF_INET, w, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse POP3 server address '%s', ignoring: %m", w);
+ continue;
+ }
+
+ m = reallocarray(n->dhcp_server_pop3, n->n_dhcp_server_pop3 + 1, sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
+
+ m[n->n_dhcp_server_pop3++] = a.in;
+ n->dhcp_server_pop3 = m;
+ }
+}
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_pop3_servers);
space = true;
}
+ fputc('\n', f);
+
+ fputs("POP3_SERVERS=", f);
+ space = false;
+ fputstrv(f, link->network->pop3, NULL, &space);
+
+ if (link->dhcp_lease) {
+ const struct in_addr *addresses;
+
+ r = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &addresses);
+ if (r > 0)
+ if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0)
+ space = true;
+ }
+
if (link->network->dhcp6_use_ntp && dhcp6_lease) {
struct in6_addr *in6_addrs;
char **hosts;
}
static int manager_save(Manager *m) {
- _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
+ _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *pop3 = NULL,
+ *search_domains = NULL, *route_domains = NULL;
const char *operstate_str, *carrier_state_str, *address_state_str;
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
_cleanup_free_ char *temp_path = NULL;
_cleanup_strv_free_ char **p = NULL;
_cleanup_fclose_ FILE *f = NULL;
+ const struct in_addr *addresses;
Link *link;
Iterator i;
int r;
if (!ntp)
return -ENOMEM;
- sip = ordered_set_new(&string_hash_ops);
- if (!sip)
+ sip = ordered_set_new(&string_hash_ops);
+ if (!sip)
return -ENOMEM;
+ pop3 = ordered_set_new(&string_hash_ops);
+ if (!pop3)
+ return -ENOMEM;
+
search_domains = ordered_set_new(&dns_name_hash_ops);
if (!search_domains)
return -ENOMEM;
/* Secondly, add the entries acquired via DHCP */
if (link->network->dhcp_use_dns) {
- const struct in_addr *addresses;
-
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
if (r > 0) {
r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
}
if (link->network->dhcp_use_ntp) {
- const struct in_addr *addresses;
-
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
if (r > 0) {
r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
}
if (link->network->dhcp_use_sip) {
- const struct in_addr *addresses;
-
r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
if (r > 0) {
r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
return r;
}
+
+ r = sd_dhcp_lease_get_pop3_server(link->dhcp_lease, &addresses);
+ if (r > 0) {
+ r = ordered_set_put_in4_addrv(pop3, addresses, r, in4_addr_is_non_local);
+ if (r < 0)
+ return r;
+ } else if (r < 0 && r != -ENODATA)
+ return r;
+
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
const char *domainname;
char **domains = NULL;
ordered_set_print(f, "DNS=", dns);
ordered_set_print(f, "NTP=", ntp);
ordered_set_print(f, "SIP=", sip);
+ ordered_set_print(f, "POP3_SERVERS=", pop3);
ordered_set_print(f, "DOMAINS=", search_domains);
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0
DHCPServer.EmitSIP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_sip)
DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0
+DHCPServer.POP3Servers, config_parse_dhcp_server_pop3_servers, 0, 0
DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router)
DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone)
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)
struct in_addr *dhcp_server_sip;
unsigned n_dhcp_server_sip;
+ struct in_addr *dhcp_server_pop3;
+ unsigned n_dhcp_server_pop3;
+
bool dhcp_server_emit_router;
bool dhcp_server_emit_timezone;
char *dhcp_server_timezone;
char **ntp;
char **sip;
+ char **pop3;
char **bind_carrier;
};
} sd_bus_error;
typedef struct {
- const char* name;
+ const char *name;
int code;
} sd_bus_error_map;
int sd_bus_try_close(sd_bus *bus) _sd_deprecated_; /* deprecated */
void sd_bus_close(sd_bus *bus);
-sd_bus *sd_bus_ref(sd_bus *bus);
-sd_bus *sd_bus_unref(sd_bus *bus);
-sd_bus *sd_bus_close_unref(sd_bus *bus);
-sd_bus *sd_bus_flush_close_unref(sd_bus *bus);
+sd_bus* sd_bus_ref(sd_bus *bus);
+sd_bus* sd_bus_unref(sd_bus *bus);
+sd_bus* sd_bus_close_unref(sd_bus *bus);
+sd_bus* sd_bus_flush_close_unref(sd_bus *bus);
void sd_bus_default_flush_close(void);
int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority);
int sd_bus_detach_event(sd_bus *bus);
-sd_event *sd_bus_get_event(sd_bus *bus);
+sd_event* sd_bus_get_event(sd_bus *bus);
int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret);
int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret);
sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot);
sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot);
-void *sd_bus_slot_get_userdata(sd_bus_slot *slot);
-void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
+void* sd_bus_slot_get_userdata(sd_bus_slot *slot);
+void* sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description);
int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description);
int sd_bus_slot_get_floating(sd_bus_slot *slot);
sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot);
sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot);
-void *sd_bus_slot_get_current_userdata(sd_bus_slot *slot);
+void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot);
/* Message object */
int sd_bus_message_get_auto_start(sd_bus_message *m);
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m);
-const char *sd_bus_message_get_signature(sd_bus_message *m, int complete);
-const char *sd_bus_message_get_path(sd_bus_message *m);
-const char *sd_bus_message_get_interface(sd_bus_message *m);
-const char *sd_bus_message_get_member(sd_bus_message *m);
-const char *sd_bus_message_get_destination(sd_bus_message *m);
-const char *sd_bus_message_get_sender(sd_bus_message *m);
-const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m);
+const char* sd_bus_message_get_signature(sd_bus_message *m, int complete);
+const char* sd_bus_message_get_path(sd_bus_message *m);
+const char* sd_bus_message_get_interface(sd_bus_message *m);
+const char* sd_bus_message_get_member(sd_bus_message *m);
+const char* sd_bus_message_get_destination(sd_bus_message *m);
+const char* sd_bus_message_get_sender(sd_bus_message *m);
+const sd_bus_error* sd_bus_message_get_error(sd_bus_message *m);
int sd_bus_message_get_errno(sd_bus_message *m);
int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec);
int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec);
-int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t* seqnum);
+int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum);
sd_bus* sd_bus_message_get_bus(sd_bus_message *m);
-sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m); /* do not unref the result */
+sd_bus_creds* sd_bus_message_get_creds(sd_bus_message *m); /* do not unref the result */
int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member);
int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member);
/* Credential handling */
int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask);
-sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c);
-sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c);
+sd_bus_creds* sd_bus_creds_ref(sd_bus_creds *c);
+sd_bus_creds* sd_bus_creds_unref(sd_bus_creds *c);
uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c);
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c);
sd_bus_track* sd_bus_track_unref(sd_bus_track *track);
sd_bus* sd_bus_track_get_bus(sd_bus_track *track);
-void *sd_bus_track_get_userdata(sd_bus_track *track);
-void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata);
+void* sd_bus_track_get_userdata(sd_bus_track *track);
+void* sd_bus_track_set_userdata(sd_bus_track *track, void *userdata);
int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m);
int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m);
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ SD_DHCP_OPTION_POP3_SERVER = 70,
SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n);
int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n);
int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n);
+int sd_dhcp_server_set_pop3_server(sd_dhcp_server *server, const struct in_addr pop3_server[], unsigned n);
int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled);
int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
/* Get the sip servers for a given link. */
int sd_network_link_get_sip_servers(int ifindex, char ***sip);
+/* Get the pop3 servers for a given link. */
+int sd_network_link_get_pop3_servers(int ifindex, char ***pop3);
+
/* Get whether this link shall be used as 'default route' for DNS queries */
int sd_network_link_get_dns_default_route(int ifindex);
NTP=
EmitSIP=
SIP=
+POP3Servers=
EmitRouter=
MaxLeaseTimeSec=
DefaultLeaseTimeSec=