mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #1055 from poettering/dhcp-updates
Various networkd and dhcp updates
This commit is contained in:
commit
4a316c44aa
53
Makefile.am
53
Makefile.am
@ -5167,41 +5167,48 @@ libnetworkd_core_la_SOURCES = \
|
||||
src/libsystemd-network/network-internal.h \
|
||||
src/network/networkd.h \
|
||||
src/network/networkd-link.h \
|
||||
src/network/networkd-netdev.h \
|
||||
src/network/networkd-netdev-tunnel.h \
|
||||
src/network/networkd-netdev-veth.h \
|
||||
src/network/networkd-netdev-vxlan.h \
|
||||
src/network/networkd-netdev-vlan.h \
|
||||
src/network/networkd-netdev-macvlan.h \
|
||||
src/network/networkd-netdev-ipvlan.h \
|
||||
src/network/networkd-netdev-dummy.h \
|
||||
src/network/networkd-netdev-tuntap.h \
|
||||
src/network/networkd-netdev-bond.h \
|
||||
src/network/networkd-netdev-bridge.h \
|
||||
src/network/networkd-netdev.c \
|
||||
src/network/networkd-netdev-tunnel.c \
|
||||
src/network/networkd-netdev-veth.c \
|
||||
src/network/networkd-netdev-vxlan.c \
|
||||
src/network/networkd-netdev-vlan.c \
|
||||
src/network/networkd-netdev-macvlan.c \
|
||||
src/network/networkd-netdev-ipvlan.c \
|
||||
src/network/networkd-netdev-dummy.c \
|
||||
src/network/networkd-netdev-tuntap.c \
|
||||
src/network/networkd-netdev-bond.c \
|
||||
src/network/networkd-netdev-bridge.c \
|
||||
src/network/networkd-link.c \
|
||||
src/network/networkd-netdev.h \
|
||||
src/network/networkd-netdev.c \
|
||||
src/network/networkd-netdev-tunnel.h \
|
||||
src/network/networkd-netdev-tunnel.c \
|
||||
src/network/networkd-netdev-veth.h \
|
||||
src/network/networkd-netdev-veth.c \
|
||||
src/network/networkd-netdev-vxlan.h \
|
||||
src/network/networkd-netdev-vxlan.c \
|
||||
src/network/networkd-netdev-vlan.h \
|
||||
src/network/networkd-netdev-vlan.c \
|
||||
src/network/networkd-netdev-macvlan.h \
|
||||
src/network/networkd-netdev-macvlan.c \
|
||||
src/network/networkd-netdev-ipvlan.h \
|
||||
src/network/networkd-netdev-ipvlan.c \
|
||||
src/network/networkd-netdev-dummy.h \
|
||||
src/network/networkd-netdev-dummy.c \
|
||||
src/network/networkd-netdev-tuntap.h \
|
||||
src/network/networkd-netdev-tuntap.c \
|
||||
src/network/networkd-netdev-bond.h \
|
||||
src/network/networkd-netdev-bond.c \
|
||||
src/network/networkd-netdev-bridge.h \
|
||||
src/network/networkd-netdev-bridge.c \
|
||||
src/network/networkd-link-bus.c \
|
||||
src/network/networkd-ipv4ll.c \
|
||||
src/network/networkd-dhcp4.c \
|
||||
src/network/networkd-dhcp6.c \
|
||||
src/network/networkd-network.h \
|
||||
src/network/networkd-network.c \
|
||||
src/network/networkd-network-bus.c \
|
||||
src/network/networkd-address.h \
|
||||
src/network/networkd-address.c \
|
||||
src/network/networkd-route.h \
|
||||
src/network/networkd-route.c \
|
||||
src/network/networkd-manager.c \
|
||||
src/network/networkd-manager-bus.c \
|
||||
src/network/networkd-fdb.h \
|
||||
src/network/networkd-fdb.c \
|
||||
src/network/networkd-address-pool.c
|
||||
src/network/networkd-address-pool.h \
|
||||
src/network/networkd-address-pool.c \
|
||||
src/network/networkd-util.h \
|
||||
src/network/networkd-util.c
|
||||
|
||||
nodist_libnetworkd_core_la_SOURCES = \
|
||||
src/network/networkd-network-gperf.c \
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
@ -223,7 +223,7 @@
|
||||
<varlistentry>
|
||||
<term><varname>DHCP=</varname></term>
|
||||
<listitem>
|
||||
<para>Enables DHCPv4 and/or DHCPv6 support. Accepts
|
||||
<para>Enables DHCPv4 and/or DHCPv6 client support. Accepts
|
||||
<literal>yes</literal>, <literal>no</literal>,
|
||||
<literal>ipv4</literal>, or <literal>ipv6</literal>.</para>
|
||||
|
||||
@ -235,9 +235,10 @@
|
||||
<varlistentry>
|
||||
<term><varname>DHCPServer=</varname></term>
|
||||
<listitem>
|
||||
<para>A boolean. Enables a basic DHCPv4 server on the
|
||||
device. Mostly useful for handing out leases to container
|
||||
instances.</para>
|
||||
<para>A boolean. Enables DHCPv4 server support. Defaults
|
||||
to <literal>no</literal>. Further settings for the DHCP
|
||||
server may be set in the <literal>[DHCPServer]</literal>
|
||||
section described below.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@ -541,7 +542,9 @@
|
||||
|
||||
<refsect1>
|
||||
<title>[DHCP] Section Options</title>
|
||||
<para>The <literal>[DHCP]</literal> section accepts the following keys:</para>
|
||||
<para>The <literal>[DHCP]</literal> section configures the
|
||||
DHCPv4 and DHCP6 client, if it is enabled with the
|
||||
<varname>DHCP=</varname> setting described above:</para>
|
||||
|
||||
<variablelist class='network-directives'>
|
||||
<varlistentry>
|
||||
@ -552,7 +555,8 @@
|
||||
any statically configured ones.</para>
|
||||
|
||||
<para>This corresponds to the <option>nameserver</option>
|
||||
option in <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
option in <citerefentry
|
||||
project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@ -582,7 +586,7 @@
|
||||
<term><varname>UseHostname=</varname></term>
|
||||
<listitem>
|
||||
<para>When true (the default), the hostname received from
|
||||
the DHCP server will be used as the transient hostname.
|
||||
the DHCP server will be set as the transient hostname of the system
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -615,6 +619,15 @@
|
||||
table with metric of 1024.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>UseTimezone=</varname></term>
|
||||
|
||||
<listitem><para>When true, the timezone received from the
|
||||
DHCP server will be set as as timezone of the local
|
||||
system. Defaults to <literal>no</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>CriticalConnection=</varname></term>
|
||||
<listitem>
|
||||
@ -658,10 +671,96 @@
|
||||
DHCP server.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>[DHCPServer] Section Options</title>
|
||||
<para>The <literal>[DHCPServer]</literal> section contains
|
||||
settings for the DHCP server, if enabled via the
|
||||
<varname>DHCPServer=</varname> option described above:</para>
|
||||
|
||||
<variablelist class='network-directives'>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DefaultLeaseTimeSec=</varname></term>
|
||||
<term><varname>MaxLeaseTimeSec=</varname></term>
|
||||
|
||||
<listitem><para>Control the default and maximum DHCP lease
|
||||
time to pass to clients. These settings take time values in seconds or
|
||||
another common time unit, depending on the suffix. The default
|
||||
lease time is used for clients that did not ask for a specific
|
||||
lease time. If a client asks for a lease time longer than the
|
||||
maximum lease time it is automatically shortened to the
|
||||
specified time. The default lease time defaults to 1h, the
|
||||
maximum lease time to 12h. Shorter lease times are beneficial
|
||||
if the configuration data in DHCP leases changes frequently
|
||||
and clients shall learn the new settings with shorter
|
||||
latencies. Longer lease times reduce the generated DHCP
|
||||
network traffic.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>EmitDNS=</varname></term>
|
||||
<term><varname>DNS=</varname></term>
|
||||
|
||||
<listitem><para>Configures whether the DHCP leases handed out
|
||||
to clients shall contain DNS server information. The
|
||||
<varname>EmitDNS=</varname> setting takes a boolean argument
|
||||
and defaults to <literal>yes</literal>. The DNS servers to
|
||||
pass to clients may be configured with the
|
||||
<varname>DNS=</varname> option, which takes a list of IPv4
|
||||
addresses. If the <varname>EmitDNS=</varname> option is
|
||||
enabled but no servers configured the servers are
|
||||
automatically propagated from an "uplink" interface that has
|
||||
appropriate servers set. The "uplink" interface is determined
|
||||
by the default route of the system with the highest
|
||||
priority. Note that this information is acquired at the time
|
||||
the lease is handed out, and does not take uplink interfaces
|
||||
into account that acquire DNS or NTP server information at a
|
||||
later point. DNS server propagation does not take
|
||||
<filename>/etc/resolv.conf</filename> into account. Also, note
|
||||
that the leases are not refreshed if uplink network
|
||||
configuration changes. To ensure clients regularly acquire the
|
||||
most current uplink DNS server information it is thus
|
||||
advisable to shorten the DHCP lease time via
|
||||
<varname>MaxLeaseTimeSec=</varname> described
|
||||
above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>EmitNTP=</varname></term>
|
||||
<term><varname>NTP=</varname></term>
|
||||
|
||||
<listitem><para>Similar to the <varname>EmitDNS=</varname> and
|
||||
<varname>DNS=</varname> settings described above these
|
||||
settings configure whether and what NTP server information
|
||||
shall be emitted as part of the DHCP lease. The same syntax,
|
||||
propagation semantics and defaults apply as for
|
||||
<varname>EmitDNS=</varname> and
|
||||
<varname>DNS=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>EmitTimezone=</varname></term>
|
||||
<term><varname>Timezone=</varname></term>
|
||||
|
||||
<listitem><para>Configures whether the DHCP leases handed out
|
||||
to clients shall contain timezone information. The
|
||||
<varname>EmitTimezone=</varname> setting takes a boolean
|
||||
argument and defaults to <literal>yes</literal>. The
|
||||
<varname>Timezone=</varname> setting takes a timezone string
|
||||
(such as <literal>Europe/Berlin</literal> or
|
||||
<literal>UTC</literal>) to pass to clients. If no explicit
|
||||
timezone is set the system timezone of the local host is
|
||||
propagated, as determined by the
|
||||
<filename>/etc/localtime</filename> symlink.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>[Bridge] Section Options</title>
|
||||
<para>The <literal>[Bridge]</literal> section accepts the
|
||||
|
@ -12,3 +12,6 @@ Name=host0
|
||||
[Network]
|
||||
DHCP=yes
|
||||
LinkLocalAddressing=yes
|
||||
|
||||
[DHCP]
|
||||
UseTimezone=yes
|
||||
|
@ -21,7 +21,9 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
/* A type-safe atomic refcounter */
|
||||
/* A type-safe atomic refcounter.
|
||||
*
|
||||
* DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
|
||||
|
||||
typedef struct {
|
||||
volatile unsigned _value;
|
||||
|
@ -50,7 +50,6 @@ int ring_push(Ring *r, const void *u8, size_t size);
|
||||
void ring_pull(Ring *r, size_t size);
|
||||
|
||||
/* return size of occupied buffer in bytes */
|
||||
static inline size_t ring_get_size(Ring *r)
|
||||
{
|
||||
static inline size_t ring_get_size(Ring *r) {
|
||||
return r->used;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "time-util.h"
|
||||
#include "path-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
usec_t now(clockid_t clock_id) {
|
||||
@ -971,7 +972,10 @@ bool timezone_is_valid(const char *name) {
|
||||
const char *p, *t;
|
||||
struct stat st;
|
||||
|
||||
if (!name || *name == 0 || *name == '/')
|
||||
if (isempty(name))
|
||||
return false;
|
||||
|
||||
if (name[0] == '/')
|
||||
return false;
|
||||
|
||||
for (p = name; *p; p++) {
|
||||
@ -1021,3 +1025,30 @@ clockid_t clock_boottime_or_monotonic(void) {
|
||||
|
||||
return clock;
|
||||
}
|
||||
|
||||
int get_timezone(char **timezone) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
const char *e;
|
||||
char *z;
|
||||
int r;
|
||||
|
||||
r = readlink_malloc("/etc/localtime", &t);
|
||||
if (r < 0)
|
||||
return r; /* returns EINVAL if not a symlink */
|
||||
|
||||
e = path_startswith(t, "/usr/share/zoneinfo/");
|
||||
if (!e)
|
||||
e = path_startswith(t, "../usr/share/zoneinfo/");
|
||||
if (!e)
|
||||
return -EINVAL;
|
||||
|
||||
if (!timezone_is_valid(e))
|
||||
return -EINVAL;
|
||||
|
||||
z = strdup(e);
|
||||
if (!z)
|
||||
return -ENOMEM;
|
||||
|
||||
*timezone = z;
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,3 +110,5 @@ bool timezone_is_valid(const char *name);
|
||||
clockid_t clock_boottime_or_monotonic(void);
|
||||
|
||||
#define xstrftime(buf, fmt, tm) assert_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0)
|
||||
|
||||
int get_timezone(char **timezone);
|
||||
|
@ -70,16 +70,14 @@ typedef struct {
|
||||
BOOLEAN no_editor;
|
||||
} Config;
|
||||
|
||||
static VOID cursor_left(UINTN *cursor, UINTN *first)
|
||||
{
|
||||
static VOID cursor_left(UINTN *cursor, UINTN *first) {
|
||||
if ((*cursor) > 0)
|
||||
(*cursor)--;
|
||||
else if ((*first) > 0)
|
||||
(*first)--;
|
||||
}
|
||||
|
||||
static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len)
|
||||
{
|
||||
static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) {
|
||||
if ((*cursor)+1 < x_max)
|
||||
(*cursor)++;
|
||||
else if ((*first) + (*cursor) < len)
|
||||
@ -856,13 +854,11 @@ static VOID config_entry_free(ConfigEntry *entry) {
|
||||
FreePool(entry->options);
|
||||
}
|
||||
|
||||
static BOOLEAN is_digit(CHAR16 c)
|
||||
{
|
||||
static BOOLEAN is_digit(CHAR16 c) {
|
||||
return (c >= '0') && (c <= '9');
|
||||
}
|
||||
|
||||
static UINTN c_order(CHAR16 c)
|
||||
{
|
||||
static UINTN c_order(CHAR16 c) {
|
||||
if (c == '\0')
|
||||
return 0;
|
||||
if (is_digit(c))
|
||||
@ -873,8 +869,7 @@ static UINTN c_order(CHAR16 c)
|
||||
return c + 0x10000;
|
||||
}
|
||||
|
||||
static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2)
|
||||
{
|
||||
static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) {
|
||||
CHAR16 *os1 = s1;
|
||||
CHAR16 *os2 = s2;
|
||||
|
||||
|
@ -45,10 +45,10 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_
|
||||
uint8_t code, size_t optlen, const void *optval);
|
||||
|
||||
typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
|
||||
const uint8_t *option, void *user_data);
|
||||
const void *option, void *userdata);
|
||||
|
||||
int dhcp_option_parse(DHCPMessage *message, size_t len,
|
||||
dhcp_option_cb_t cb, void *user_data);
|
||||
dhcp_option_cb_t cb, void *userdata);
|
||||
|
||||
int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
|
||||
uint8_t type, uint16_t arp_type, size_t optlen,
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <stdint.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
#include "refcnt.h"
|
||||
#include "util.h"
|
||||
#include "list.h"
|
||||
|
||||
@ -48,54 +47,62 @@ struct sd_dhcp_raw_option {
|
||||
};
|
||||
|
||||
struct sd_dhcp_lease {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
int32_t time_offset;
|
||||
/* each 0 if unset */
|
||||
uint32_t t1;
|
||||
uint32_t t2;
|
||||
uint32_t lifetime;
|
||||
uint32_t mtu_aging_timeout;
|
||||
|
||||
/* each 0 if unset */
|
||||
be32_t address;
|
||||
be32_t server_address;
|
||||
be32_t subnet_mask;
|
||||
be32_t router;
|
||||
be32_t next_server;
|
||||
|
||||
bool have_subnet_mask;
|
||||
be32_t subnet_mask;
|
||||
|
||||
bool have_broadcast;
|
||||
be32_t broadcast;
|
||||
|
||||
struct in_addr *dns;
|
||||
size_t dns_size;
|
||||
|
||||
struct in_addr *ntp;
|
||||
size_t ntp_size;
|
||||
struct in_addr *policy_filter;
|
||||
size_t policy_filter_size;
|
||||
|
||||
struct sd_dhcp_route *static_route;
|
||||
size_t static_route_size;
|
||||
size_t static_route_allocated;
|
||||
uint16_t boot_file_size;
|
||||
uint16_t mdr;
|
||||
uint16_t mtu;
|
||||
uint8_t ttl;
|
||||
bool ip_forward;
|
||||
bool ip_forward_non_local;
|
||||
size_t static_route_size, static_route_allocated;
|
||||
|
||||
uint16_t mtu; /* 0 if unset */
|
||||
|
||||
char *domainname;
|
||||
char *hostname;
|
||||
char *root_path;
|
||||
uint8_t *client_id;
|
||||
|
||||
void *client_id;
|
||||
size_t client_id_len;
|
||||
uint8_t *vendor_specific;
|
||||
|
||||
void *vendor_specific;
|
||||
size_t vendor_specific_len;
|
||||
|
||||
char *timezone;
|
||||
|
||||
LIST_HEAD(struct sd_dhcp_raw_option, private_options);
|
||||
};
|
||||
|
||||
int dhcp_lease_new(sd_dhcp_lease **ret);
|
||||
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
void *user_data);
|
||||
int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag,
|
||||
const uint8_t *data, uint8_t len);
|
||||
|
||||
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata);
|
||||
int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len);
|
||||
|
||||
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
|
||||
|
||||
int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id,
|
||||
size_t client_id_len);
|
||||
int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len);
|
||||
|
||||
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
|
||||
int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
|
||||
#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
|
||||
|
@ -140,7 +140,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
|
||||
|
||||
static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,
|
||||
uint8_t *message_type, dhcp_option_cb_t cb,
|
||||
void *user_data) {
|
||||
void *userdata) {
|
||||
uint8_t code, len;
|
||||
size_t offset = 0;
|
||||
|
||||
@ -199,7 +199,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
|
||||
return -EINVAL;
|
||||
|
||||
if (cb)
|
||||
cb(code, len, &options[offset], user_data);
|
||||
cb(code, len, &options[offset], userdata);
|
||||
|
||||
offset += len;
|
||||
|
||||
@ -214,7 +214,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
|
||||
}
|
||||
|
||||
int dhcp_option_parse(DHCPMessage *message, size_t len,
|
||||
dhcp_option_cb_t cb, void *user_data) {
|
||||
dhcp_option_cb_t cb, void *userdata) {
|
||||
uint8_t overload = 0;
|
||||
uint8_t message_type = 0;
|
||||
int r;
|
||||
@ -228,20 +228,20 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
|
||||
len -= sizeof(DHCPMessage);
|
||||
|
||||
r = parse_options(message->options, len, &overload, &message_type,
|
||||
cb, user_data);
|
||||
cb, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (overload & DHCP_OVERLOAD_FILE) {
|
||||
r = parse_options(message->file, sizeof(message->file),
|
||||
NULL, &message_type, cb, user_data);
|
||||
NULL, &message_type, cb, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (overload & DHCP_OVERLOAD_SNAME) {
|
||||
r = parse_options(message->sname, sizeof(message->sname),
|
||||
NULL, &message_type, cb, user_data);
|
||||
NULL, &message_type, cb, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -137,6 +137,8 @@ enum {
|
||||
DHCP_OPTION_REBINDING_T2_TIME = 59,
|
||||
DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
|
||||
DHCP_OPTION_CLIENT_IDENTIFIER = 61,
|
||||
DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
|
||||
DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
|
||||
DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
|
||||
DHCP_OPTION_PRIVATE_BASE = 224,
|
||||
DHCP_OPTION_PRIVATE_LAST = 254,
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "sd-dhcp-server.h"
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "refcnt.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
@ -34,7 +33,7 @@
|
||||
|
||||
typedef struct DHCPClientId {
|
||||
size_t length;
|
||||
uint8_t *data;
|
||||
void *data;
|
||||
} DHCPClientId;
|
||||
|
||||
typedef struct DHCPLease {
|
||||
@ -47,7 +46,7 @@ typedef struct DHCPLease {
|
||||
} DHCPLease;
|
||||
|
||||
struct sd_dhcp_server {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
sd_event *event;
|
||||
int event_priority;
|
||||
@ -55,15 +54,22 @@ struct sd_dhcp_server {
|
||||
int fd;
|
||||
int fd_raw;
|
||||
|
||||
int index;
|
||||
int ifindex;
|
||||
be32_t address;
|
||||
be32_t netmask;
|
||||
be32_t pool_start;
|
||||
size_t pool_size;
|
||||
size_t next_offer;
|
||||
|
||||
char *timezone;
|
||||
|
||||
struct in_addr *ntp, *dns;
|
||||
unsigned n_ntp, n_dns;
|
||||
|
||||
Hashmap *leases_by_client_id;
|
||||
DHCPLease **bound_leases;
|
||||
|
||||
uint32_t max_lease_time, default_lease_time;
|
||||
};
|
||||
|
||||
typedef struct DHCPRequest {
|
||||
@ -75,7 +81,7 @@ typedef struct DHCPRequest {
|
||||
size_t max_optlen;
|
||||
be32_t server_id;
|
||||
be32_t requested_ip;
|
||||
int lifetime;
|
||||
uint32_t lifetime;
|
||||
} DHCPRequest;
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_server*, sd_dhcp_server_unref);
|
||||
|
@ -24,13 +24,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "refcnt.h"
|
||||
|
||||
#include "sd-dhcp6-lease.h"
|
||||
#include "dhcp6-internal.h"
|
||||
|
||||
struct sd_dhcp6_lease {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
uint8_t *serverid;
|
||||
size_t serverid_len;
|
||||
|
@ -41,8 +41,7 @@
|
||||
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
|
||||
|
||||
int dhcp_network_icmp6_bind_router_solicitation(int index)
|
||||
{
|
||||
int dhcp_network_icmp6_bind_router_solicitation(int index) {
|
||||
struct icmp6_filter filter = { };
|
||||
struct ipv6_mreq mreq = {
|
||||
.ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
|
||||
@ -92,8 +91,7 @@ int dhcp_network_icmp6_bind_router_solicitation(int index)
|
||||
return r;
|
||||
}
|
||||
|
||||
int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr)
|
||||
{
|
||||
int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
|
||||
struct sockaddr_in6 dst = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
|
||||
|
@ -338,9 +338,7 @@ int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
|
||||
return count;
|
||||
}
|
||||
|
||||
int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
|
||||
char ***str_arr)
|
||||
{
|
||||
int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) {
|
||||
size_t pos = 0, idx = 0;
|
||||
_cleanup_free_ char **names = NULL;
|
||||
int r;
|
||||
|
@ -374,9 +374,8 @@ int lldp_mib_add_objects(Prioq *by_expiry,
|
||||
}
|
||||
|
||||
/* Admission Control: Can this port attached to the existing chassis ? */
|
||||
if (REFCNT_GET(c->n_ref) >= LLDP_MIB_MAX_PORT_PER_CHASSIS) {
|
||||
log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...",
|
||||
REFCNT_GET(c->n_ref));
|
||||
if (c->n_ref >= LLDP_MIB_MAX_PORT_PER_CHASSIS) {
|
||||
log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...", c->n_ref);
|
||||
|
||||
c = NULL;
|
||||
goto drop;
|
||||
@ -394,7 +393,7 @@ int lldp_mib_add_objects(Prioq *by_expiry,
|
||||
|
||||
/* Attach new port to chassis */
|
||||
LIST_PREPEND(port, c->ports, p);
|
||||
REFCNT_INC(c->n_ref);
|
||||
c->n_ref ++;
|
||||
|
||||
p = NULL;
|
||||
c = NULL;
|
||||
@ -424,7 +423,8 @@ void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p) {
|
||||
lldp_neighbour_port_free(p);
|
||||
|
||||
/* Drop the Chassis if no port is attached */
|
||||
if (REFCNT_DEC(c->n_ref) <= 1) {
|
||||
c->n_ref --;
|
||||
if (c->n_ref <= 1) {
|
||||
hashmap_remove(c->neighbour_mib, &c->chassis_id);
|
||||
lldp_chassis_free(c);
|
||||
}
|
||||
@ -486,7 +486,7 @@ void lldp_chassis_free(lldp_chassis *c) {
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
if (REFCNT_GET(c->n_ref) > 1)
|
||||
if (c->n_ref > 1)
|
||||
return;
|
||||
|
||||
free(c->chassis_id.data);
|
||||
@ -513,7 +513,7 @@ int lldp_chassis_new(tlv_packet *tlv,
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
c->n_ref = REFCNT_INIT;
|
||||
c->n_ref = 1;
|
||||
c->chassis_id.type = type;
|
||||
c->chassis_id.length = length;
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "list.h"
|
||||
#include "refcnt.h"
|
||||
#include "lldp-tlv.h"
|
||||
#include "prioq.h"
|
||||
|
||||
@ -63,7 +62,7 @@ struct lldp_chassis_id {
|
||||
};
|
||||
|
||||
struct lldp_chassis {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
lldp_chassis_id chassis_id;
|
||||
|
||||
|
@ -525,7 +525,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size) {
|
||||
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {
|
||||
_cleanup_free_ char *hex_buf = NULL;
|
||||
|
||||
assert(f);
|
||||
@ -541,7 +541,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string) {
|
||||
int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
|
||||
assert(data);
|
||||
assert(data_len);
|
||||
assert(string);
|
||||
|
@ -77,5 +77,5 @@ struct sd_dhcp_route;
|
||||
void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size);
|
||||
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
|
||||
|
||||
int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size);
|
||||
int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string);
|
||||
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
|
||||
int deserialize_dhcp_option(void **data, size_t *data_len, const char *string);
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "refcnt.h"
|
||||
#include "random-util.h"
|
||||
#include "async.h"
|
||||
|
||||
@ -41,7 +40,7 @@
|
||||
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
|
||||
|
||||
struct sd_dhcp_client {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
DHCPState state;
|
||||
sd_event *event;
|
||||
@ -106,7 +105,6 @@ static const uint8_t default_req_opts[] = {
|
||||
DHCP_OPTION_HOST_NAME,
|
||||
DHCP_OPTION_DOMAIN_NAME,
|
||||
DHCP_OPTION_DOMAIN_NAME_SERVER,
|
||||
DHCP_OPTION_NTP_SERVER,
|
||||
};
|
||||
|
||||
static int client_receive_message_raw(sd_event_source *s, int fd,
|
||||
@ -377,8 +375,7 @@ static int client_initialize(sd_dhcp_client *client) {
|
||||
client->state = DHCP_STATE_INIT;
|
||||
client->xid = 0;
|
||||
|
||||
if (client->lease)
|
||||
client->lease = sd_dhcp_lease_unref(client->lease);
|
||||
client->lease = sd_dhcp_lease_unref(client->lease);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1055,18 +1052,16 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
||||
}
|
||||
|
||||
lease->next_server = offer->siaddr;
|
||||
|
||||
lease->address = offer->yiaddr;
|
||||
|
||||
if (lease->address == INADDR_ANY ||
|
||||
lease->server_address == INADDR_ANY ||
|
||||
if (lease->address == 0 ||
|
||||
lease->server_address == 0 ||
|
||||
lease->lifetime == 0) {
|
||||
log_dhcp_client(client, "received lease lacks address, server "
|
||||
"address or lease lifetime, ignoring");
|
||||
log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
if (lease->subnet_mask == INADDR_ANY) {
|
||||
if (!lease->have_subnet_mask) {
|
||||
r = dhcp_lease_set_default_subnet_mask(lease);
|
||||
if (r < 0) {
|
||||
log_dhcp_client(client, "received lease lacks subnet "
|
||||
@ -1168,13 +1163,17 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint64_t client_compute_timeout(sd_dhcp_client *client,
|
||||
uint32_t lifetime, double factor) {
|
||||
static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {
|
||||
assert(client);
|
||||
assert(client->request_sent);
|
||||
assert(lifetime);
|
||||
assert(lifetime > 0);
|
||||
|
||||
return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
|
||||
if (lifetime > 3)
|
||||
lifetime -= 3;
|
||||
else
|
||||
lifetime = 0;
|
||||
|
||||
return client->request_sent + (lifetime * USEC_PER_SEC * factor) +
|
||||
+ (random_u32() & 0x1fffff);
|
||||
}
|
||||
|
||||
@ -1206,7 +1205,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
||||
|
||||
/* convert the various timeouts from relative (secs) to absolute (usecs) */
|
||||
lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
|
||||
if (client->lease->t1 && client->lease->t2) {
|
||||
if (client->lease->t1 > 0 && client->lease->t2 > 0) {
|
||||
/* both T1 and T2 are given */
|
||||
if (client->lease->t1 < client->lease->t2 &&
|
||||
client->lease->t2 < client->lease->lifetime) {
|
||||
@ -1220,7 +1219,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
||||
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
|
||||
client->lease->t1 = client->lease->lifetime / 2;
|
||||
}
|
||||
} else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
|
||||
} else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {
|
||||
/* only T2 is given, and it is valid */
|
||||
t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
|
||||
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
|
||||
@ -1230,7 +1229,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
|
||||
client->lease->t2 = (client->lease->lifetime * 7) / 8;
|
||||
}
|
||||
} else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
|
||||
} else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {
|
||||
/* only T1 is given, and it is valid */
|
||||
t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
|
||||
@ -1676,30 +1675,41 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
|
||||
}
|
||||
|
||||
sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
|
||||
if (client)
|
||||
assert_se(REFCNT_INC(client->n_ref) >= 2);
|
||||
|
||||
if (!client)
|
||||
return NULL;
|
||||
|
||||
assert(client->n_ref >= 1);
|
||||
client->n_ref++;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
|
||||
if (client && REFCNT_DEC(client->n_ref) == 0) {
|
||||
log_dhcp_client(client, "FREE");
|
||||
|
||||
client_initialize(client);
|
||||
if (!client)
|
||||
return NULL;
|
||||
|
||||
client->receive_message =
|
||||
sd_event_source_unref(client->receive_message);
|
||||
assert(client->n_ref >= 1);
|
||||
client->n_ref--;
|
||||
|
||||
sd_dhcp_client_detach_event(client);
|
||||
if (client->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
sd_dhcp_lease_unref(client->lease);
|
||||
log_dhcp_client(client, "FREE");
|
||||
|
||||
free(client->req_opts);
|
||||
free(client->hostname);
|
||||
free(client->vendor_class_identifier);
|
||||
free(client);
|
||||
}
|
||||
client_initialize(client);
|
||||
|
||||
client->receive_message = sd_event_source_unref(client->receive_message);
|
||||
|
||||
sd_dhcp_client_detach_event(client);
|
||||
|
||||
sd_dhcp_lease_unref(client->lease);
|
||||
|
||||
free(client->req_opts);
|
||||
free(client->hostname);
|
||||
free(client->vendor_class_identifier);
|
||||
free(client);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -1713,7 +1723,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
client->n_ref = REFCNT_INIT;
|
||||
client->n_ref = 1;
|
||||
client->state = DHCP_STATE_INIT;
|
||||
client->index = -1;
|
||||
client->fd = -1;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,8 @@
|
||||
#include "dhcp-server-internal.h"
|
||||
#include "dhcp-internal.h"
|
||||
|
||||
#define DHCP_DEFAULT_LEASE_TIME 3600 /* one hour */
|
||||
#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
|
||||
#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
|
||||
|
||||
int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server,
|
||||
struct in_addr *address,
|
||||
@ -73,8 +74,12 @@ bool sd_dhcp_server_is_running(sd_dhcp_server *server) {
|
||||
}
|
||||
|
||||
sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) {
|
||||
if (server)
|
||||
assert_se(REFCNT_INC(server->n_ref) >= 2);
|
||||
|
||||
if (!server)
|
||||
return NULL;
|
||||
|
||||
assert(server->n_ref >= 1);
|
||||
server->n_ref++;
|
||||
|
||||
return server;
|
||||
}
|
||||
@ -127,7 +132,10 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
|
||||
if (!server)
|
||||
return NULL;
|
||||
|
||||
if (REFCNT_DEC(server->n_ref) > 0)
|
||||
assert(server->n_ref >= 1);
|
||||
server->n_ref--;
|
||||
|
||||
if (server->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
log_dhcp_server(server, "UNREF");
|
||||
@ -136,6 +144,10 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
|
||||
|
||||
sd_event_unref(server->event);
|
||||
|
||||
free(server->timezone);
|
||||
free(server->dns);
|
||||
free(server->ntp);
|
||||
|
||||
while ((lease = hashmap_steal_first(server->leases_by_client_id)))
|
||||
dhcp_lease_free(lease);
|
||||
hashmap_free(server->leases_by_client_id);
|
||||
@ -156,13 +168,15 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
|
||||
if (!server)
|
||||
return -ENOMEM;
|
||||
|
||||
server->n_ref = REFCNT_INIT;
|
||||
server->n_ref = 1;
|
||||
server->fd_raw = -1;
|
||||
server->fd = -1;
|
||||
server->address = htobe32(INADDR_ANY);
|
||||
server->netmask = htobe32(INADDR_ANY);
|
||||
server->index = ifindex;
|
||||
server->ifindex = ifindex;
|
||||
server->leases_by_client_id = hashmap_new(&client_id_hash_ops);
|
||||
server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC);
|
||||
server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC);
|
||||
|
||||
*ret = server;
|
||||
server = NULL;
|
||||
@ -223,13 +237,12 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,
|
||||
union sockaddr_union link = {
|
||||
.ll.sll_family = AF_PACKET,
|
||||
.ll.sll_protocol = htons(ETH_P_IP),
|
||||
.ll.sll_ifindex = server->index,
|
||||
.ll.sll_ifindex = server->ifindex,
|
||||
.ll.sll_halen = ETH_ALEN,
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(server);
|
||||
assert(server->index > 0);
|
||||
assert(server->ifindex > 0);
|
||||
assert(server->address);
|
||||
assert(packet);
|
||||
assert(len > sizeof(DHCPPacket));
|
||||
@ -240,11 +253,7 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,
|
||||
packet->dhcp.yiaddr,
|
||||
DHCP_PORT_CLIENT, len);
|
||||
|
||||
r = dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len);
|
||||
}
|
||||
|
||||
static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
|
||||
@ -290,7 +299,7 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
|
||||
pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
|
||||
assert(pktinfo);
|
||||
|
||||
pktinfo->ipi_ifindex = server->index;
|
||||
pktinfo->ipi_ifindex = server->ifindex;
|
||||
pktinfo->ipi_spec_dst.s_addr = server->address;
|
||||
|
||||
r = sendmsg(server->fd, &msg, 0);
|
||||
@ -474,6 +483,33 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (server->n_dns > 0) {
|
||||
r = dhcp_option_append(
|
||||
&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
DHCP_OPTION_DOMAIN_NAME_SERVER,
|
||||
sizeof(struct in_addr) * server->n_dns, server->dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (server->n_ntp > 0) {
|
||||
r = dhcp_option_append(
|
||||
&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
DHCP_OPTION_NTP_SERVER,
|
||||
sizeof(struct in_addr) * server->n_ntp, server->ntp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (server->timezone) {
|
||||
r = dhcp_option_append(
|
||||
&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
DHCP_OPTION_NEW_TZDB_TIMEZONE,
|
||||
strlen(server->timezone), server->timezone);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -490,11 +526,7 @@ static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
|
||||
}
|
||||
|
||||
static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
|
||||
@ -532,9 +564,8 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_request(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
void *user_data) {
|
||||
DHCPRequest *req = user_data;
|
||||
static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) {
|
||||
DHCPRequest *req = userdata;
|
||||
|
||||
assert(req);
|
||||
|
||||
@ -590,7 +621,7 @@ static void dhcp_request_free(DHCPRequest *req) {
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
|
||||
#define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
|
||||
|
||||
static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) {
|
||||
static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {
|
||||
assert(req);
|
||||
assert(message);
|
||||
|
||||
@ -599,23 +630,27 @@ static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) {
|
||||
/* set client id based on MAC address if client did not send an explicit
|
||||
one */
|
||||
if (!req->client_id.data) {
|
||||
uint8_t *data;
|
||||
void *data;
|
||||
|
||||
data = new0(uint8_t, ETH_ALEN + 1);
|
||||
data = malloc0(ETH_ALEN + 1);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
((uint8_t*) data)[0] = 0x01;
|
||||
memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN);
|
||||
|
||||
req->client_id.length = ETH_ALEN + 1;
|
||||
req->client_id.data = data;
|
||||
req->client_id.data[0] = 0x01;
|
||||
memcpy(&req->client_id.data[1], &message->chaddr, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)
|
||||
req->max_optlen = DHCP_MIN_OPTIONS_SIZE;
|
||||
|
||||
if (!req->lifetime)
|
||||
req->lifetime = DHCP_DEFAULT_LEASE_TIME;
|
||||
if (req->lifetime <= 0)
|
||||
req->lifetime = MAX(1ULL, server->default_lease_time);
|
||||
|
||||
if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time)
|
||||
req->lifetime = server->max_lease_time;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -656,7 +691,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
||||
if (type < 0)
|
||||
return 0;
|
||||
|
||||
r = ensure_sane_request(req, message);
|
||||
r = ensure_sane_request(server, req, message);
|
||||
if (r < 0)
|
||||
/* this only fails on critical errors */
|
||||
return r;
|
||||
@ -665,8 +700,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
||||
&req->client_id);
|
||||
|
||||
switch(type) {
|
||||
case DHCP_DISCOVER:
|
||||
{
|
||||
|
||||
case DHCP_DISCOVER: {
|
||||
be32_t address = INADDR_ANY;
|
||||
unsigned i;
|
||||
|
||||
@ -716,9 +751,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
||||
|
||||
return 1;
|
||||
|
||||
break;
|
||||
case DHCP_REQUEST:
|
||||
{
|
||||
case DHCP_REQUEST: {
|
||||
be32_t address;
|
||||
bool init_reboot = false;
|
||||
int pool_offset;
|
||||
@ -840,6 +873,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DHCP_RELEASE: {
|
||||
int pool_offset;
|
||||
|
||||
@ -883,13 +917,12 @@ static int server_receive_message(sd_event_source *s, int fd,
|
||||
.msg_controllen = sizeof(cmsgbuf),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
int buflen = 0, len, r;
|
||||
int buflen = 0, len;
|
||||
|
||||
assert(server);
|
||||
|
||||
r = ioctl(fd, FIONREAD, &buflen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (ioctl(fd, FIONREAD, &buflen) < 0)
|
||||
return -errno;
|
||||
if (buflen < 0)
|
||||
return -EIO;
|
||||
|
||||
@ -914,7 +947,7 @@ static int server_receive_message(sd_event_source *s, int fd,
|
||||
|
||||
/* TODO figure out if this can be done as a filter on
|
||||
* the socket, like for IPv6 */
|
||||
if (server->index != info->ipi_ifindex)
|
||||
if (server->ifindex != info->ipi_ifindex)
|
||||
return 0;
|
||||
|
||||
break;
|
||||
@ -993,3 +1026,91 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone) {
|
||||
int r;
|
||||
|
||||
assert_return(server, -EINVAL);
|
||||
assert_return(timezone_is_valid(timezone), -EINVAL);
|
||||
|
||||
if (streq_ptr(timezone, server->timezone))
|
||||
return 0;
|
||||
|
||||
r = free_and_strdup(&server->timezone, timezone);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) {
|
||||
assert_return(server, -EINVAL);
|
||||
|
||||
if (t == server->max_lease_time)
|
||||
return 0;
|
||||
|
||||
server->max_lease_time = t;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) {
|
||||
assert_return(server, -EINVAL);
|
||||
|
||||
if (t == server->default_lease_time)
|
||||
return 0;
|
||||
|
||||
server->default_lease_time = t;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) {
|
||||
assert_return(server, -EINVAL);
|
||||
assert_return(dns || n <= 0, -EINVAL);
|
||||
|
||||
if (server->n_dns == n &&
|
||||
memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0)
|
||||
return 0;
|
||||
|
||||
if (n <= 0) {
|
||||
server->dns = mfree(server->dns);
|
||||
server->n_dns = 0;
|
||||
} else {
|
||||
struct in_addr *c;
|
||||
|
||||
c = newdup(struct in_addr, dns, n);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
free(server->dns);
|
||||
server->dns = c;
|
||||
server->n_dns = n;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) {
|
||||
assert_return(server, -EINVAL);
|
||||
assert_return(ntp || n <= 0, -EINVAL);
|
||||
|
||||
if (server->n_ntp == n &&
|
||||
memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0)
|
||||
return 0;
|
||||
|
||||
if (n <= 0) {
|
||||
server->ntp = mfree(server->ntp);
|
||||
server->n_ntp = 0;
|
||||
} else {
|
||||
struct in_addr *c;
|
||||
|
||||
c = newdup(struct in_addr, ntp, n);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
free(server->ntp);
|
||||
server->ntp = c;
|
||||
server->n_ntp = n;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "udev.h"
|
||||
#include "udev-util.h"
|
||||
#include "util.h"
|
||||
#include "refcnt.h"
|
||||
#include "random-util.h"
|
||||
|
||||
#include "network-internal.h"
|
||||
@ -40,7 +39,7 @@
|
||||
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
|
||||
|
||||
struct sd_dhcp6_client {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
enum DHCP6State state;
|
||||
sd_event *event;
|
||||
@ -113,9 +112,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
|
||||
|
||||
static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
|
||||
|
||||
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
|
||||
sd_dhcp6_client_cb_t cb, void *userdata)
|
||||
{
|
||||
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client->cb = cb;
|
||||
@ -124,8 +121,7 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
|
||||
{
|
||||
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(interface_index >= -1, -EINVAL);
|
||||
|
||||
@ -134,9 +130,11 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type)
|
||||
{
|
||||
int sd_dhcp6_client_set_mac(
|
||||
sd_dhcp6_client *client,
|
||||
const uint8_t *addr, size_t addr_len,
|
||||
uint16_t arp_type) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(addr, -EINVAL);
|
||||
assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
|
||||
@ -160,16 +158,17 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_ensure_duid(sd_dhcp6_client *client)
|
||||
{
|
||||
static int client_ensure_duid(sd_dhcp6_client *client) {
|
||||
if (client->duid_len != 0)
|
||||
return 0;
|
||||
|
||||
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
|
||||
size_t duid_len)
|
||||
{
|
||||
int sd_dhcp6_client_set_duid(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t type,
|
||||
uint8_t *duid, size_t duid_len) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(duid, -EINVAL);
|
||||
assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
|
||||
@ -203,8 +202,7 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
|
||||
bool enabled) {
|
||||
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, bool enabled) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client->information_request = enabled;
|
||||
@ -212,8 +210,7 @@ int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
|
||||
bool *enabled) {
|
||||
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, bool *enabled) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(enabled, -EINVAL);
|
||||
|
||||
@ -222,8 +219,7 @@ int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
|
||||
uint16_t option) {
|
||||
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
|
||||
size_t t;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
@ -805,9 +801,7 @@ static int client_parse_message(sd_dhcp6_client *client,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
|
||||
size_t len)
|
||||
{
|
||||
static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
|
||||
int r;
|
||||
_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
|
||||
bool rapid_commit;
|
||||
@ -843,8 +837,7 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
|
||||
return DHCP6_STATE_BOUND;
|
||||
}
|
||||
|
||||
static int client_receive_advertise(sd_dhcp6_client *client,
|
||||
DHCP6Message *advertise, size_t len) {
|
||||
static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
|
||||
int r;
|
||||
_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
|
||||
uint8_t pref_advertise = 0, pref_lease = 0;
|
||||
@ -879,8 +872,7 @@ static int client_receive_advertise(sd_dhcp6_client *client,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
|
||||
void *userdata) {
|
||||
static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
sd_dhcp6_client *client = userdata;
|
||||
DHCP6_CLIENT_DONT_DESTROY(client);
|
||||
_cleanup_free_ DHCP6Message *message;
|
||||
@ -991,8 +983,7 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
|
||||
{
|
||||
static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
|
||||
int r;
|
||||
usec_t timeout, time_now;
|
||||
char time_string[FORMAT_TIMESPAN_MAX];
|
||||
@ -1121,15 +1112,13 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_stop(sd_dhcp6_client *client)
|
||||
{
|
||||
int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
|
||||
client_stop(client, DHCP6_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_start(sd_dhcp6_client *client)
|
||||
{
|
||||
int sd_dhcp6_client_start(sd_dhcp6_client *client) {
|
||||
int r = 0;
|
||||
enum DHCP6State state = DHCP6_STATE_SOLICITATION;
|
||||
|
||||
@ -1185,9 +1174,7 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
|
||||
int priority)
|
||||
{
|
||||
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) {
|
||||
int r;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
@ -1222,30 +1209,39 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
|
||||
}
|
||||
|
||||
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
|
||||
if (client)
|
||||
assert_se(REFCNT_INC(client->n_ref) >= 2);
|
||||
|
||||
if (!client)
|
||||
return NULL;
|
||||
|
||||
assert(client->n_ref >= 1);
|
||||
client->n_ref++;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
|
||||
if (client && REFCNT_DEC(client->n_ref) == 0) {
|
||||
client_reset(client);
|
||||
|
||||
sd_dhcp6_client_detach_event(client);
|
||||
sd_dhcp6_lease_unref(client->lease);
|
||||
|
||||
free(client->req_opts);
|
||||
free(client);
|
||||
|
||||
if (!client)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return client;
|
||||
assert(client->n_ref >= 1);
|
||||
client->n_ref--;
|
||||
|
||||
if (client->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
client_reset(client);
|
||||
|
||||
sd_dhcp6_client_detach_event(client);
|
||||
sd_dhcp6_lease_unref(client->lease);
|
||||
|
||||
free(client->req_opts);
|
||||
free(client);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_new(sd_dhcp6_client **ret)
|
||||
{
|
||||
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
|
||||
_cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
|
||||
size_t t;
|
||||
|
||||
@ -1255,7 +1251,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
client->n_ref = REFCNT_INIT;
|
||||
client->n_ref = 1;
|
||||
|
||||
client->ia_na.type = DHCP6_OPTION_IA_NA;
|
||||
|
||||
|
@ -247,8 +247,7 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen)
|
||||
{
|
||||
int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
|
||||
int r;
|
||||
uint16_t subopt;
|
||||
size_t sublen;
|
||||
@ -361,26 +360,38 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
|
||||
}
|
||||
|
||||
sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
|
||||
if (lease)
|
||||
assert_se(REFCNT_INC(lease->n_ref) >= 2);
|
||||
|
||||
if (!lease)
|
||||
return NULL;
|
||||
|
||||
assert(lease->n_ref >= 1);
|
||||
lease->n_ref++;
|
||||
|
||||
return lease;
|
||||
}
|
||||
|
||||
sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
|
||||
if (lease && REFCNT_DEC(lease->n_ref) == 0) {
|
||||
free(lease->serverid);
|
||||
dhcp6_lease_free_ia(&lease->ia);
|
||||
|
||||
free(lease->dns);
|
||||
if (!lease)
|
||||
return NULL;
|
||||
|
||||
lease->domains = strv_free(lease->domains);
|
||||
assert(lease->n_ref >= 1);
|
||||
lease->n_ref--;
|
||||
|
||||
free(lease->ntp);
|
||||
if (lease->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
|
||||
free(lease);
|
||||
}
|
||||
free(lease->serverid);
|
||||
dhcp6_lease_free_ia(&lease->ia);
|
||||
|
||||
free(lease->dns);
|
||||
|
||||
lease->domains = strv_free(lease->domains);
|
||||
|
||||
free(lease->ntp);
|
||||
|
||||
lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
|
||||
free(lease);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -392,7 +403,7 @@ int dhcp6_lease_new(sd_dhcp6_lease **ret) {
|
||||
if (!lease)
|
||||
return -ENOMEM;
|
||||
|
||||
lease->n_ref = REFCNT_INIT;
|
||||
lease->n_ref = 1;
|
||||
|
||||
LIST_HEAD_INIT(lease->ia.addresses);
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "socket-util.h"
|
||||
#include "refcnt.h"
|
||||
#include "async.h"
|
||||
|
||||
#include "dhcp6-internal.h"
|
||||
@ -47,7 +46,7 @@ enum icmp6_nd_state {
|
||||
typedef struct ICMP6Prefix ICMP6Prefix;
|
||||
|
||||
struct ICMP6Prefix {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
LIST_FIELDS(ICMP6Prefix, prefixes);
|
||||
|
||||
@ -57,7 +56,7 @@ struct ICMP6Prefix {
|
||||
};
|
||||
|
||||
struct sd_icmp6_nd {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
enum icmp6_nd_state state;
|
||||
sd_event *event;
|
||||
@ -78,13 +77,18 @@ struct sd_icmp6_nd {
|
||||
#define log_icmp6_nd(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "ICMPv6 CLIENT: " fmt, ##__VA_ARGS__)
|
||||
|
||||
static ICMP6Prefix *icmp6_prefix_unref(ICMP6Prefix *prefix) {
|
||||
if (prefix && REFCNT_DEC(prefix->n_ref) <= 0) {
|
||||
prefix->timeout_valid =
|
||||
sd_event_source_unref(prefix->timeout_valid);
|
||||
|
||||
free(prefix);
|
||||
}
|
||||
if (!prefix)
|
||||
return NULL;
|
||||
|
||||
assert(prefix->n_ref > 0);
|
||||
prefix->n_ref--;
|
||||
|
||||
if (prefix->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
prefix->timeout_valid = sd_event_source_unref(prefix->timeout_valid);
|
||||
free(prefix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -97,7 +101,7 @@ static int icmp6_prefix_new(ICMP6Prefix **ret) {
|
||||
if (!prefix)
|
||||
return -ENOMEM;
|
||||
|
||||
prefix->n_ref = REFCNT_INIT;
|
||||
prefix->n_ref = 1;
|
||||
LIST_INIT(prefixes, prefix);
|
||||
|
||||
*ret = prefix;
|
||||
@ -106,8 +110,7 @@ static int icmp6_prefix_new(ICMP6Prefix **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void icmp6_nd_notify(sd_icmp6_nd *nd, int event)
|
||||
{
|
||||
static void icmp6_nd_notify(sd_icmp6_nd *nd, int event) {
|
||||
if (nd->callback)
|
||||
nd->callback(nd, event, nd->userdata);
|
||||
}
|
||||
@ -177,9 +180,12 @@ sd_event *sd_icmp6_nd_get_event(sd_icmp6_nd *nd) {
|
||||
}
|
||||
|
||||
sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd) {
|
||||
assert (nd);
|
||||
|
||||
assert_se(REFCNT_INC(nd->n_ref) >= 2);
|
||||
if (!nd)
|
||||
return NULL;
|
||||
|
||||
assert(nd->n_ref > 0);
|
||||
nd->n_ref++;
|
||||
|
||||
return nd;
|
||||
}
|
||||
@ -195,21 +201,28 @@ static int icmp6_nd_init(sd_icmp6_nd *nd) {
|
||||
}
|
||||
|
||||
sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) {
|
||||
if (nd && REFCNT_DEC(nd->n_ref) == 0) {
|
||||
ICMP6Prefix *prefix, *p;
|
||||
ICMP6Prefix *prefix, *p;
|
||||
|
||||
icmp6_nd_init(nd);
|
||||
sd_icmp6_nd_detach_event(nd);
|
||||
if (!nd)
|
||||
return NULL;
|
||||
|
||||
LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
|
||||
LIST_REMOVE(prefixes, nd->prefixes, prefix);
|
||||
assert(nd->n_ref > 0);
|
||||
nd->n_ref--;
|
||||
|
||||
prefix = icmp6_prefix_unref(prefix);
|
||||
}
|
||||
if (nd->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
free(nd);
|
||||
icmp6_nd_init(nd);
|
||||
sd_icmp6_nd_detach_event(nd);
|
||||
|
||||
LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
|
||||
LIST_REMOVE(prefixes, nd->prefixes, prefix);
|
||||
|
||||
prefix = icmp6_prefix_unref(prefix);
|
||||
}
|
||||
|
||||
free(nd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -225,7 +238,7 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
|
||||
if (!nd)
|
||||
return -ENOMEM;
|
||||
|
||||
nd->n_ref = REFCNT_INIT;
|
||||
nd->n_ref = 1;
|
||||
|
||||
nd->index = -1;
|
||||
nd->fd = -1;
|
||||
@ -376,9 +389,7 @@ int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
|
||||
uint8_t *prefixlen)
|
||||
{
|
||||
int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr, uint8_t *prefixlen) {
|
||||
assert_return(nd, -EINVAL);
|
||||
assert_return(addr, -EINVAL);
|
||||
assert_return(prefixlen, -EINVAL);
|
||||
@ -525,9 +536,7 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata)
|
||||
{
|
||||
static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
sd_icmp6_nd *nd = userdata;
|
||||
int r, buflen = 0;
|
||||
ssize_t len;
|
||||
@ -586,9 +595,7 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
|
||||
void *userdata)
|
||||
{
|
||||
static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_icmp6_nd *nd = userdata;
|
||||
uint64_t time_now, next_timeout;
|
||||
struct ether_addr unset = { };
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "util.h"
|
||||
#include "siphash24.h"
|
||||
#include "list.h"
|
||||
#include "refcnt.h"
|
||||
#include "random-util.h"
|
||||
|
||||
#include "ipv4ll-internal.h"
|
||||
@ -68,7 +67,7 @@ typedef enum IPv4LLState {
|
||||
} IPv4LLState;
|
||||
|
||||
struct sd_ipv4ll {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
IPv4LLState state;
|
||||
int index;
|
||||
@ -598,30 +597,39 @@ int sd_ipv4ll_stop(sd_ipv4ll *ll) {
|
||||
}
|
||||
|
||||
sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
|
||||
if (ll)
|
||||
assert_se(REFCNT_INC(ll->n_ref) >= 2);
|
||||
|
||||
if (!ll)
|
||||
return NULL;
|
||||
|
||||
assert(ll->n_ref >= 1);
|
||||
ll->n_ref++;
|
||||
|
||||
return ll;
|
||||
}
|
||||
|
||||
sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
|
||||
if (ll && REFCNT_DEC(ll->n_ref) == 0) {
|
||||
ll->receive_message =
|
||||
sd_event_source_unref(ll->receive_message);
|
||||
ll->fd = safe_close(ll->fd);
|
||||
|
||||
ll->timer = sd_event_source_unref(ll->timer);
|
||||
|
||||
sd_ipv4ll_detach_event(ll);
|
||||
|
||||
free(ll->random_data);
|
||||
free(ll->random_data_state);
|
||||
free(ll);
|
||||
|
||||
if (!ll)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ll;
|
||||
assert(ll->n_ref >= 1);
|
||||
ll->n_ref--;
|
||||
|
||||
if (ll->n_ref > 0)
|
||||
return ll;
|
||||
|
||||
ll->receive_message = sd_event_source_unref(ll->receive_message);
|
||||
ll->fd = safe_close(ll->fd);
|
||||
|
||||
ll->timer = sd_event_source_unref(ll->timer);
|
||||
|
||||
sd_ipv4ll_detach_event(ll);
|
||||
|
||||
free(ll->random_data);
|
||||
free(ll->random_data_state);
|
||||
free(ll);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref);
|
||||
@ -636,7 +644,7 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {
|
||||
if (!ll)
|
||||
return -ENOMEM;
|
||||
|
||||
ll->n_ref = REFCNT_INIT;
|
||||
ll->n_ref = 1;
|
||||
ll->state = IPV4LL_STATE_INIT;
|
||||
ll->index = -1;
|
||||
ll->fd = -1;
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "random-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "async.h"
|
||||
#include "refcnt.h"
|
||||
#include "utf8.h"
|
||||
|
||||
#define PPPOE_MAX_PACKET_SIZE 1484
|
||||
@ -68,7 +67,7 @@ typedef struct PPPoETags {
|
||||
} PPPoETags;
|
||||
|
||||
struct sd_pppoe {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
PPPoEState state;
|
||||
uint64_t host_uniq;
|
||||
@ -202,23 +201,34 @@ int sd_pppoe_detach_event(sd_pppoe *ppp) {
|
||||
}
|
||||
|
||||
sd_pppoe *sd_pppoe_ref(sd_pppoe *ppp) {
|
||||
if (ppp)
|
||||
assert_se(REFCNT_INC(ppp->n_ref) >= 2);
|
||||
|
||||
if (!ppp)
|
||||
return NULL;
|
||||
|
||||
assert(ppp->n_ref > 0);
|
||||
ppp->n_ref++;
|
||||
|
||||
return ppp;
|
||||
}
|
||||
|
||||
sd_pppoe *sd_pppoe_unref(sd_pppoe *ppp) {
|
||||
if (ppp && REFCNT_DEC(ppp->n_ref) <= 0) {
|
||||
pppoe_tags_clear(&ppp->tags);
|
||||
free(ppp->ifname);
|
||||
free(ppp->service_name);
|
||||
sd_pppoe_stop(ppp);
|
||||
sd_pppoe_detach_event(ppp);
|
||||
|
||||
free(ppp);
|
||||
}
|
||||
if (!ppp)
|
||||
return NULL;
|
||||
|
||||
assert(ppp->n_ref > 0);
|
||||
ppp->n_ref--;
|
||||
|
||||
if (ppp->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
pppoe_tags_clear(&ppp->tags);
|
||||
free(ppp->ifname);
|
||||
free(ppp->service_name);
|
||||
sd_pppoe_stop(ppp);
|
||||
sd_pppoe_detach_event(ppp);
|
||||
|
||||
free(ppp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -231,7 +241,7 @@ int sd_pppoe_new (sd_pppoe **ret) {
|
||||
if (!ppp)
|
||||
return -ENOMEM;
|
||||
|
||||
ppp->n_ref = REFCNT_INIT;
|
||||
ppp->n_ref = 1;
|
||||
ppp->state = _PPPOE_STATE_INVALID;
|
||||
ppp->ifindex = -1;
|
||||
ppp->fd = -1;
|
||||
|
@ -43,16 +43,13 @@ static test_callback_recv_t callback_recv;
|
||||
static be32_t xid;
|
||||
static sd_event_source *test_hangcheck;
|
||||
|
||||
static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec,
|
||||
void *userdata)
|
||||
{
|
||||
static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
assert_not_reached("Test case should have completed in 2 seconds");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_request_basic(sd_event *e)
|
||||
{
|
||||
static void test_request_basic(sd_event *e) {
|
||||
int r;
|
||||
|
||||
sd_dhcp_client *client;
|
||||
@ -87,10 +84,7 @@ static void test_request_basic(sd_event *e)
|
||||
assert_se(sd_dhcp_client_set_request_option(client,
|
||||
DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
|
||||
assert_se(sd_dhcp_client_set_request_option(client,
|
||||
DHCP_OPTION_DOMAIN_NAME_SERVER)
|
||||
== -EEXIST);
|
||||
assert_se(sd_dhcp_client_set_request_option(client,
|
||||
DHCP_OPTION_NTP_SERVER) == -EEXIST);
|
||||
DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
|
||||
|
||||
assert_se(sd_dhcp_client_set_request_option(client,
|
||||
DHCP_OPTION_PAD) == -EINVAL);
|
||||
@ -112,8 +106,7 @@ static void test_request_basic(sd_event *e)
|
||||
sd_dhcp_client_unref(client);
|
||||
}
|
||||
|
||||
static void test_checksum(void)
|
||||
{
|
||||
static void test_checksum(void) {
|
||||
uint8_t buf[20] = {
|
||||
0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@ -126,9 +119,7 @@ static void test_checksum(void)
|
||||
assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
|
||||
}
|
||||
|
||||
static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
void *user_data)
|
||||
{
|
||||
static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
|
||||
switch(code) {
|
||||
case DHCP_OPTION_CLIENT_IDENTIFIER:
|
||||
{
|
||||
@ -141,10 +132,10 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
|
||||
assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
|
||||
assert_se(len == 19);
|
||||
assert_se(option[0] == 0xff);
|
||||
assert_se(((uint8_t*) option)[0] == 0xff);
|
||||
|
||||
assert_se(memcmp(&option[1], &iaid, sizeof(iaid)) == 0);
|
||||
assert_se(memcmp(&option[5], &duid, duid_len) == 0);
|
||||
assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0);
|
||||
assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -155,9 +146,7 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
|
||||
const void *packet, size_t len)
|
||||
{
|
||||
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) {
|
||||
size_t size;
|
||||
_cleanup_free_ DHCPPacket *discover;
|
||||
uint16_t ip_check, udp_check;
|
||||
@ -202,18 +191,20 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
|
||||
return 575;
|
||||
}
|
||||
|
||||
int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
|
||||
uint32_t id, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type)
|
||||
{
|
||||
int dhcp_network_bind_raw_socket(
|
||||
int index,
|
||||
union sockaddr_union *link,
|
||||
uint32_t id,
|
||||
const uint8_t *addr, size_t addr_len,
|
||||
uint16_t arp_type) {
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
|
||||
return -errno;
|
||||
|
||||
return test_fd[0];
|
||||
}
|
||||
|
||||
int dhcp_network_bind_udp_socket(be32_t address, uint16_t port)
|
||||
{
|
||||
int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
|
||||
@ -223,14 +214,11 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port)
|
||||
return fd;
|
||||
}
|
||||
|
||||
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
|
||||
const void *packet, size_t len)
|
||||
{
|
||||
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp)
|
||||
{
|
||||
static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
|
||||
int res;
|
||||
|
||||
res = dhcp_option_parse(dhcp, size, check_options, NULL);
|
||||
@ -242,8 +230,7 @@ static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_discover_message(sd_event *e)
|
||||
{
|
||||
static void test_discover_message(sd_event *e) {
|
||||
sd_dhcp_client *client;
|
||||
int res, r;
|
||||
|
||||
|
@ -145,8 +145,8 @@ static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) {
|
||||
}
|
||||
}
|
||||
|
||||
static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, void *user_data) {
|
||||
struct option_desc *desc = user_data;
|
||||
static int test_options_cb(uint8_t code, uint8_t len, const void *option, void *userdata) {
|
||||
struct option_desc *desc = userdata;
|
||||
uint8_t *descoption = NULL;
|
||||
int *desclen = NULL, *descpos = NULL;
|
||||
uint8_t optcode = 0;
|
||||
@ -207,10 +207,10 @@ static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, voi
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (verbose)
|
||||
printf("0x%02x(0x%02x) ", option[i],
|
||||
printf("0x%02x(0x%02x) ", ((uint8_t*) option)[i],
|
||||
descoption[*descpos + 2 + i]);
|
||||
|
||||
assert_se(option[i] == descoption[*descpos + 2 + i]);
|
||||
assert_se(((uint8_t*) option)[i] == descoption[*descpos + 2 + i]);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
|
@ -501,8 +501,7 @@ static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_client_send_advertise(DHCP6Message *solicit)
|
||||
{
|
||||
static int test_client_send_advertise(DHCP6Message *solicit) {
|
||||
DHCP6Message advertise;
|
||||
|
||||
advertise.transaction_id = solicit->transaction_id;
|
||||
|
@ -39,9 +39,9 @@ static int test_fd[2];
|
||||
|
||||
static int basic_request_handler_bind = 0;
|
||||
static int basic_request_handler_stop = 0;
|
||||
static void* basic_request_handler_user_data = (void*)0xCABCAB;
|
||||
static void* basic_request_handler_userdata = (void*)0xCABCAB;
|
||||
static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) {
|
||||
assert_se(userdata == basic_request_handler_user_data);
|
||||
assert_se(userdata == basic_request_handler_userdata);
|
||||
|
||||
switch(event) {
|
||||
case IPV4LL_EVENT_STOP:
|
||||
@ -175,7 +175,7 @@ static void test_basic_request(sd_event *e) {
|
||||
assert_se(sd_ipv4ll_start(ll) == -EINVAL);
|
||||
|
||||
assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler,
|
||||
basic_request_handler_user_data) == 0);
|
||||
basic_request_handler_userdata) == 0);
|
||||
assert_se(sd_ipv4ll_start(ll) == -EINVAL);
|
||||
|
||||
assert_se(sd_ipv4ll_set_index(ll, 1) == 0);
|
||||
|
@ -1024,7 +1024,9 @@ _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
|
||||
|
||||
_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
|
||||
assert_return(m, NULL);
|
||||
assert_return(sd_bus_error_is_set(&m->error), NULL);
|
||||
|
||||
if (!sd_bus_error_is_set(&m->error))
|
||||
return NULL;
|
||||
|
||||
return &m->error;
|
||||
}
|
||||
|
@ -79,8 +79,7 @@ static bool linebuf_add(struct linebuf *buf, const char *s, size_t len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool linebuf_add_char(struct linebuf *buf, char c)
|
||||
{
|
||||
static bool linebuf_add_char(struct linebuf *buf, char c) {
|
||||
if (buf->len + 1 >= sizeof(buf->bytes))
|
||||
return false;
|
||||
buf->bytes[buf->len++] = c;
|
||||
@ -269,13 +268,13 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
|
||||
}
|
||||
|
||||
static const char hwdb_bin_paths[] =
|
||||
"/etc/systemd/hwdb/hwdb.bin\0"
|
||||
"/etc/udev/hwdb.bin\0"
|
||||
"/usr/lib/systemd/hwdb/hwdb.bin\0"
|
||||
"/etc/systemd/hwdb/hwdb.bin\0"
|
||||
"/etc/udev/hwdb.bin\0"
|
||||
"/usr/lib/systemd/hwdb/hwdb.bin\0"
|
||||
#ifdef HAVE_SPLIT_USR
|
||||
"/lib/systemd/hwdb/hwdb.bin\0"
|
||||
"/lib/systemd/hwdb/hwdb.bin\0"
|
||||
#endif
|
||||
UDEVLIBEXECDIR "/hwdb.bin\0";
|
||||
UDEVLIBEXECDIR "/hwdb.bin\0";
|
||||
|
||||
_public_ int sd_hwdb_new(sd_hwdb **ret) {
|
||||
_cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
|
||||
|
@ -214,6 +214,28 @@ _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_network_link_get_timezone(int ifindex, char **ret) {
|
||||
_cleanup_free_ char *s = NULL, *p = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = parse_env_file(p, NEWLINE, "TIMEZONE", &s, NULL);
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (isempty(s))
|
||||
return -ENODATA;
|
||||
|
||||
*ret = s;
|
||||
s = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
|
@ -497,7 +497,7 @@ static int link_status_one(
|
||||
sd_hwdb *hwdb,
|
||||
const char *name) {
|
||||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
|
||||
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
|
||||
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *timezone = NULL;
|
||||
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
|
||||
_cleanup_device_unref_ sd_device *d = NULL;
|
||||
char devid[2 + DECIMAL_STR_MAX(int)];
|
||||
@ -570,7 +570,6 @@ static int link_status_one(
|
||||
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
|
||||
|
||||
sd_network_link_get_dns(ifindex, &dns);
|
||||
sd_network_link_get_ntp(ifindex, &ntp);
|
||||
sd_network_link_get_domains(ifindex, &domains);
|
||||
r = sd_network_link_get_wildcard_domain(ifindex);
|
||||
if (r > 0) {
|
||||
@ -652,6 +651,8 @@ static int link_status_one(
|
||||
dump_list(" DNS: ", dns);
|
||||
if (!strv_isempty(domains))
|
||||
dump_list(" Domain: ", domains);
|
||||
|
||||
(void) sd_network_link_get_ntp(ifindex, &ntp);
|
||||
if (!strv_isempty(ntp))
|
||||
dump_list(" NTP: ", ntp);
|
||||
|
||||
@ -661,6 +662,10 @@ static int link_status_one(
|
||||
if (!strv_isempty(carrier_bound_by))
|
||||
dump_list("Carrier Bound By: ", carrier_bound_by);
|
||||
|
||||
(void) sd_network_link_get_timezone(ifindex, &timezone);
|
||||
if (timezone)
|
||||
printf(" Time Zone: %s", timezone);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,8 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-address-pool.h"
|
||||
|
||||
int address_pool_new(
|
||||
Manager *m,
|
||||
|
43
src/network/networkd-address-pool.h
Normal file
43
src/network/networkd-address-pool.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
typedef struct AddressPool AddressPool;
|
||||
|
||||
#include "networkd.h"
|
||||
|
||||
struct AddressPool {
|
||||
Manager *manager;
|
||||
|
||||
int family;
|
||||
unsigned prefixlen;
|
||||
|
||||
union in_addr_union in_addr;
|
||||
|
||||
LIST_FIELDS(AddressPool, address_pools);
|
||||
};
|
||||
|
||||
int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen);
|
||||
int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen);
|
||||
void address_pool_free(AddressPool *p);
|
||||
|
||||
int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found);
|
@ -25,8 +25,10 @@
|
||||
#include "util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "firewall-util.h"
|
||||
#include "netlink-util.h"
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-address.h"
|
||||
|
||||
static void address_init(Address *address) {
|
||||
assert(address);
|
||||
|
73
src/network/networkd-address.h
Normal file
73
src/network/networkd-address.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Tom Gundersen <teg@jklm.no>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "in-addr-util.h"
|
||||
|
||||
typedef struct Address Address;
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-link.h"
|
||||
|
||||
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
|
||||
|
||||
struct Address {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
|
||||
int family;
|
||||
unsigned char prefixlen;
|
||||
unsigned char scope;
|
||||
uint32_t flags;
|
||||
char *label;
|
||||
|
||||
struct in_addr broadcast;
|
||||
struct ifa_cacheinfo cinfo;
|
||||
|
||||
union in_addr_union in_addr;
|
||||
union in_addr_union in_addr_peer;
|
||||
|
||||
bool ip_masquerade_done;
|
||||
|
||||
LIST_FIELDS(Address, addresses);
|
||||
};
|
||||
|
||||
int address_new_static(Network *network, unsigned section, Address **ret);
|
||||
int address_new_dynamic(Address **ret);
|
||||
void address_free(Address *address);
|
||||
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_establish(Address *address, Link *link);
|
||||
int address_release(Address *address, Link *link);
|
||||
bool address_equal(Address *a1, Address *a2);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
|
||||
#define _cleanup_address_free_ _cleanup_(address_freep)
|
||||
|
||||
int config_parse_address(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);
|
||||
int config_parse_broadcast(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);
|
||||
int config_parse_label(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);
|
@ -39,8 +39,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
log_link_error(link, "could not set DHCPv4 route: %s",
|
||||
strerror(-r));
|
||||
log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
|
||||
link_enter_failed(link);
|
||||
}
|
||||
|
||||
@ -61,40 +60,25 @@ static int link_set_dhcp_routes(Link *link) {
|
||||
assert(link->dhcp_lease);
|
||||
|
||||
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
|
||||
if (r < 0 && r != -ENOENT) {
|
||||
log_link_warning(link,
|
||||
"DHCP error: could not get gateway: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
|
||||
|
||||
if (r >= 0) {
|
||||
struct in_addr address;
|
||||
_cleanup_route_free_ Route *route = NULL;
|
||||
_cleanup_route_free_ Route *route_gw = NULL;
|
||||
|
||||
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
|
||||
if (r < 0) {
|
||||
log_link_warning(link,
|
||||
"DHCP error: could not get address: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
|
||||
|
||||
r = route_new_dynamic(&route, RTPROT_DHCP);
|
||||
if (r < 0) {
|
||||
log_link_error(link,
|
||||
"Could not allocate route: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate route: %m");
|
||||
|
||||
r = route_new_dynamic(&route_gw, RTPROT_DHCP);
|
||||
if (r < 0) {
|
||||
log_link_error(link,
|
||||
"Could not allocate route: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate route: %m");
|
||||
|
||||
/* The dhcp netmask may mask out the gateway. Add an explicit
|
||||
* route for the gw host so that we can route no matter the
|
||||
@ -107,12 +91,8 @@ static int link_set_dhcp_routes(Link *link) {
|
||||
route_gw->metrics = link->network->dhcp_route_metric;
|
||||
|
||||
r = route_configure(route_gw, link, &dhcp4_route_handler);
|
||||
if (r < 0) {
|
||||
log_link_warning(link,
|
||||
"could not set host route: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not set host route: %m");
|
||||
|
||||
link->dhcp4_messages ++;
|
||||
|
||||
@ -123,9 +103,7 @@ static int link_set_dhcp_routes(Link *link) {
|
||||
|
||||
r = route_configure(route, link, &dhcp4_route_handler);
|
||||
if (r < 0) {
|
||||
log_link_warning(link,
|
||||
"could not set routes: %s",
|
||||
strerror(-r));
|
||||
log_link_warning_errno(link, r, "Could not set routes: %m");
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
@ -136,23 +114,15 @@ static int link_set_dhcp_routes(Link *link) {
|
||||
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
|
||||
if (n == -ENOENT)
|
||||
return 0;
|
||||
if (n < 0) {
|
||||
log_link_warning(link,
|
||||
"DHCP error: could not get routes: %s",
|
||||
strerror(-n));
|
||||
|
||||
return n;
|
||||
}
|
||||
if (n < 0)
|
||||
return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m");
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
_cleanup_route_free_ Route *route = NULL;
|
||||
|
||||
r = route_new_dynamic(&route, RTPROT_DHCP);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not allocate route: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate route: %m");
|
||||
|
||||
route->family = AF_INET;
|
||||
route->in_addr.in = static_routes[i].gw_addr;
|
||||
@ -161,12 +131,8 @@ static int link_set_dhcp_routes(Link *link) {
|
||||
route->metrics = link->network->dhcp_route_metric;
|
||||
|
||||
r = route_configure(route, link, &dhcp4_route_handler);
|
||||
if (r < 0) {
|
||||
log_link_warning(link,
|
||||
"could not set host route: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not set host route: %m");
|
||||
|
||||
link->dhcp4_messages ++;
|
||||
}
|
||||
@ -270,18 +236,16 @@ static int dhcp_lease_lost(Link *link) {
|
||||
if (link->network->dhcp_hostname) {
|
||||
const char *hostname = NULL;
|
||||
|
||||
if (!link->network->hostname)
|
||||
r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
|
||||
else
|
||||
if (link->network->hostname)
|
||||
hostname = link->network->hostname;
|
||||
else
|
||||
(void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
|
||||
|
||||
if (r >= 0 || hostname) {
|
||||
r = link_set_hostname(link, hostname);
|
||||
if (hostname) {
|
||||
/* If a hostname was set due to the lease, then unset it now. */
|
||||
r = link_set_hostname(link, NULL);
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r,
|
||||
"Failed to set transient hostname to '%s': %m",
|
||||
hostname);
|
||||
|
||||
log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,8 +264,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
log_link_error(link, "could not set DHCPv4 address: %s",
|
||||
strerror(-r));
|
||||
log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
|
||||
link_enter_failed(link);
|
||||
} else if (r >= 0)
|
||||
link_rtnl_process_address(rtnl, m, link->manager);
|
||||
@ -357,45 +320,30 @@ static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
|
||||
assert(link->network);
|
||||
|
||||
r = sd_dhcp_client_get_lease(client, &lease);
|
||||
if (r < 0) {
|
||||
log_link_warning(link, "DHCP error: no lease %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
|
||||
|
||||
sd_dhcp_lease_unref(link->dhcp_lease);
|
||||
link->dhcp4_configured = false;
|
||||
link->dhcp_lease = sd_dhcp_lease_ref(lease);
|
||||
|
||||
r = sd_dhcp_lease_get_address(lease, &address);
|
||||
if (r < 0) {
|
||||
log_link_warning(link, "DHCP error: no address: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "DHCP error: no address: %m");
|
||||
|
||||
r = sd_dhcp_lease_get_netmask(lease, &netmask);
|
||||
if (r < 0) {
|
||||
log_link_warning(link, "DHCP error: no netmask: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
|
||||
|
||||
if (!link->network->dhcp_critical) {
|
||||
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease,
|
||||
&lifetime);
|
||||
if (r < 0) {
|
||||
log_link_warning(link,
|
||||
"DHCP error: no lifetime: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
|
||||
}
|
||||
|
||||
r = dhcp4_update_address(link, &address, &netmask, lifetime);
|
||||
if (r < 0) {
|
||||
log_link_warning(link, "could not update IP address: %s",
|
||||
strerror(-r));
|
||||
log_link_warning_errno(link, r, "Could not update IP address: %m");
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
@ -417,21 +365,21 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
|
||||
|
||||
r = sd_dhcp_client_get_lease(client, &lease);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP error: no lease: %m");
|
||||
return log_link_error_errno(link, r, "DHCP error: No lease: %m");
|
||||
|
||||
r = sd_dhcp_lease_get_address(lease, &address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP error: no address: %m");
|
||||
return log_link_error_errno(link, r, "DHCP error: No address: %m");
|
||||
|
||||
r = sd_dhcp_lease_get_netmask(lease, &netmask);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP error: no netmask: %m");
|
||||
return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
|
||||
|
||||
prefixlen = in_addr_netmask_to_prefixlen(&netmask);
|
||||
|
||||
r = sd_dhcp_lease_get_router(lease, &gateway);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
|
||||
return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
|
||||
|
||||
if (r >= 0)
|
||||
log_struct(LOG_INFO,
|
||||
@ -470,18 +418,30 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
|
||||
if (link->network->dhcp_hostname) {
|
||||
const char *hostname = NULL;
|
||||
|
||||
if (!link->network->hostname)
|
||||
r = sd_dhcp_lease_get_hostname(lease, &hostname);
|
||||
else
|
||||
if (link->network->hostname)
|
||||
hostname = link->network->hostname;
|
||||
else
|
||||
(void) sd_dhcp_lease_get_hostname(lease, &hostname);
|
||||
|
||||
if (r >= 0 || hostname) {
|
||||
if (hostname) {
|
||||
r = link_set_hostname(link, hostname);
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_timezone) {
|
||||
const char *tz = NULL;
|
||||
|
||||
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
|
||||
|
||||
if (tz) {
|
||||
r = link_set_timezone(link, tz);
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
|
||||
}
|
||||
}
|
||||
|
||||
if (!link->network->dhcp_critical) {
|
||||
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
|
||||
if (r < 0) {
|
||||
@ -515,8 +475,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
|
||||
case DHCP_EVENT_STOP:
|
||||
case DHCP_EVENT_IP_CHANGE:
|
||||
if (link->network->dhcp_critical) {
|
||||
log_link_error(link,
|
||||
"DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
|
||||
log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -553,13 +512,9 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
|
||||
break;
|
||||
default:
|
||||
if (event < 0)
|
||||
log_link_warning(link,
|
||||
"DHCP error: client failed: %s",
|
||||
strerror(-event));
|
||||
log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
|
||||
else
|
||||
log_link_warning(link,
|
||||
"DHCP unknown event: %d",
|
||||
event);
|
||||
log_link_warning(link, "DHCP unknown event: %i", event);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -607,10 +562,10 @@ int dhcp4_configure(Link *link) {
|
||||
}
|
||||
|
||||
if (link->network->dhcp_mtu) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
||||
DHCP_OPTION_INTERFACE_MTU);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
||||
DHCP_OPTION_INTERFACE_MTU);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_routes) {
|
||||
@ -624,6 +579,15 @@ int dhcp4_configure(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Always acquire the timezone and NTP*/
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NTP_SERVER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NEW_TZDB_TIMEZONE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network->dhcp_sendhost) {
|
||||
_cleanup_free_ char *hostname = NULL;
|
||||
const char *hn = NULL;
|
||||
|
@ -22,10 +22,12 @@
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-link.h"
|
||||
#include "conf-parser.h"
|
||||
#include "util.h"
|
||||
#include "netlink-util.h"
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-fdb.h"
|
||||
|
||||
/* create a new FDB entry or get an existing one. */
|
||||
int fdb_entry_new_static(Network *const network,
|
||||
|
47
src/network/networkd-fdb.h
Normal file
47
src/network/networkd-fdb.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright (C) 2014 Intel Corporation. All rights reserved.
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
typedef struct FdbEntry FdbEntry;
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-network.h"
|
||||
|
||||
struct FdbEntry {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
|
||||
struct ether_addr *mac_addr;
|
||||
uint16_t vlan_id;
|
||||
|
||||
LIST_FIELDS(FdbEntry, static_fdb_entries);
|
||||
};
|
||||
|
||||
int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret);
|
||||
void fdb_entry_free(FdbEntry *fdb_entry);
|
||||
int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free);
|
||||
#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep)
|
||||
|
||||
int config_parse_fdb_hwaddr(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);
|
||||
int config_parse_fdb_vlan_id(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);
|
@ -29,7 +29,10 @@
|
||||
#include "socket-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "netlink-util.h"
|
||||
#include "dhcp-lease-internal.h"
|
||||
#include "network-internal.h"
|
||||
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-netdev.h"
|
||||
|
||||
@ -613,6 +616,96 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_push_dns_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;
|
||||
|
||||
log_debug("Copying DNS server information from %s", link->ifname);
|
||||
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
STRV_FOREACH(a, link->network->dns) {
|
||||
struct in_addr ia;
|
||||
|
||||
/* Only look for IPv4 addresses */
|
||||
if (inet_pton(AF_INET, *a, &ia) <= 0)
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
|
||||
return log_oom();
|
||||
|
||||
addresses[n_addresses++] = ia;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_dns &&
|
||||
link->dhcp_lease) {
|
||||
const struct in_addr *da = NULL;
|
||||
int n;
|
||||
|
||||
n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
|
||||
if (n > 0) {
|
||||
|
||||
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
|
||||
return log_oom();
|
||||
|
||||
memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
|
||||
n_addresses += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_addresses <= 0)
|
||||
return 0;
|
||||
|
||||
return sd_dhcp_server_set_dns(s, addresses, n_addresses);
|
||||
}
|
||||
|
||||
static int link_push_ntp_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_debug("Copying NTP server information from %s", link->ifname);
|
||||
|
||||
STRV_FOREACH(a, link->network->ntp) {
|
||||
struct in_addr ia;
|
||||
|
||||
/* Only look for IPv4 addresses */
|
||||
if (inet_pton(AF_INET, *a, &ia) <= 0)
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
|
||||
return log_oom();
|
||||
|
||||
addresses[n_addresses++] = ia;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_ntp &&
|
||||
link->dhcp_lease) {
|
||||
const struct in_addr *da = NULL;
|
||||
int n;
|
||||
|
||||
n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
|
||||
if (n > 0) {
|
||||
|
||||
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
|
||||
return log_oom();
|
||||
|
||||
memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
|
||||
n_addresses += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_addresses <= 0)
|
||||
return 0;
|
||||
|
||||
return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
|
||||
}
|
||||
|
||||
static int link_enter_set_addresses(Link *link) {
|
||||
Address *ad;
|
||||
int r;
|
||||
@ -639,6 +732,8 @@ static int link_enter_set_addresses(Link *link) {
|
||||
if (link_dhcp4_server_enabled(link)) {
|
||||
struct in_addr pool_start;
|
||||
Address *address;
|
||||
Link *uplink = NULL;
|
||||
bool acquired_uplink = false;
|
||||
|
||||
address = link_find_dhcp_server_address(link);
|
||||
if (!address) {
|
||||
@ -672,6 +767,81 @@ static int link_enter_set_addresses(Link *link) {
|
||||
return r;
|
||||
*/
|
||||
|
||||
if (link->network->dhcp_server_max_lease_time_usec > 0) {
|
||||
r = sd_dhcp_server_set_max_lease_time(
|
||||
link->dhcp_server,
|
||||
DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_server_default_lease_time_usec > 0) {
|
||||
r = sd_dhcp_server_set_default_lease_time(
|
||||
link->dhcp_server,
|
||||
DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_server_emit_dns) {
|
||||
|
||||
if (link->network->n_dhcp_server_dns > 0)
|
||||
r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
|
||||
else {
|
||||
uplink = manager_find_uplink(link->manager, link);
|
||||
acquired_uplink = true;
|
||||
|
||||
if (!uplink) {
|
||||
log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
|
||||
r = 0;
|
||||
} else
|
||||
r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
|
||||
}
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
|
||||
}
|
||||
|
||||
|
||||
if (link->network->dhcp_server_emit_ntp) {
|
||||
|
||||
if (link->network->n_dhcp_server_ntp > 0)
|
||||
r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
|
||||
else {
|
||||
if (!acquired_uplink)
|
||||
uplink = manager_find_uplink(link->manager, link);
|
||||
|
||||
if (!uplink) {
|
||||
log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
|
||||
r = 0;
|
||||
} else
|
||||
r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
|
||||
|
||||
}
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
|
||||
}
|
||||
|
||||
if (link->network->dhcp_server_emit_timezone) {
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
const char *tz;
|
||||
|
||||
if (link->network->dhcp_server_timezone)
|
||||
tz = link->network->dhcp_server_timezone;
|
||||
else {
|
||||
r = get_timezone(&buffer);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine timezone: %m");
|
||||
else
|
||||
tz = buffer;
|
||||
}
|
||||
|
||||
if (tz) {
|
||||
r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_dhcp_server_start(link->dhcp_server);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
|
||||
@ -743,7 +913,7 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd
|
||||
|
||||
static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
_cleanup_link_unref_ Link *link = userdata;
|
||||
int r;
|
||||
const sd_bus_error *e;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
@ -751,21 +921,20 @@ static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_bus_message_get_errno(m);
|
||||
if (r > 0)
|
||||
log_link_warning_errno(link, r, "Could not set hostname: %m");
|
||||
e = sd_bus_message_get_error(m);
|
||||
if (e)
|
||||
log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int link_set_hostname(Link *link, const char *hostname) {
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(hostname);
|
||||
|
||||
log_link_debug(link, "Setting transient hostname: '%s'", hostname);
|
||||
log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
|
||||
|
||||
if (!link->manager->bus) {
|
||||
/* TODO: replace by assert when we can rely on kdbus */
|
||||
@ -794,6 +963,57 @@ int link_set_hostname(Link *link, const char *hostname) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
_cleanup_link_unref_ Link *link = userdata;
|
||||
const sd_bus_error *e;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
e = sd_bus_message_get_error(m);
|
||||
if (e)
|
||||
log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int link_set_timezone(Link *link, const char *timezone) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(timezone);
|
||||
|
||||
log_link_debug(link, "Setting system timezone: '%s'", timezone);
|
||||
|
||||
if (!link->manager->bus) {
|
||||
log_link_info(link, "Not connected to system bus, ignoring timezone.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_call_method_async(
|
||||
link->manager->bus,
|
||||
NULL,
|
||||
"org.freedesktop.timedate1",
|
||||
"/org/freedesktop/timedate1",
|
||||
"org.freedesktop.timedate1",
|
||||
"SetTimezone",
|
||||
set_timezone_handler,
|
||||
link,
|
||||
"sb",
|
||||
timezone,
|
||||
false);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set timezone: %m");
|
||||
|
||||
link_ref(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
|
||||
_cleanup_link_unref_ Link *link = userdata;
|
||||
int r;
|
||||
@ -2413,10 +2633,18 @@ int link_save(Link *link) {
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
if (link->dhcp_lease) {
|
||||
const char *tz = NULL;
|
||||
|
||||
r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
|
||||
if (r >= 0)
|
||||
fprintf(f, "TIMEZONE=%s\n", tz);
|
||||
}
|
||||
|
||||
if (link->dhcp_lease) {
|
||||
assert(link->network);
|
||||
|
||||
r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
|
||||
r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
@ -19,11 +21,16 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#include "networkd.h"
|
||||
#include "sd-dhcp-client.h"
|
||||
#include "sd-dhcp-server.h"
|
||||
#include "sd-ipv4ll.h"
|
||||
#include "sd-icmp6-nd.h"
|
||||
#include "sd-dhcp6-client.h"
|
||||
#include "sd-lldp.h"
|
||||
|
||||
typedef struct Link Link;
|
||||
|
||||
typedef enum LinkState {
|
||||
LINK_STATE_PENDING,
|
||||
@ -38,6 +45,21 @@ typedef enum LinkState {
|
||||
_LINK_STATE_INVALID = -1
|
||||
} LinkState;
|
||||
|
||||
typedef enum LinkOperationalState {
|
||||
LINK_OPERSTATE_OFF,
|
||||
LINK_OPERSTATE_NO_CARRIER,
|
||||
LINK_OPERSTATE_DORMANT,
|
||||
LINK_OPERSTATE_CARRIER,
|
||||
LINK_OPERSTATE_DEGRADED,
|
||||
LINK_OPERSTATE_ROUTABLE,
|
||||
_LINK_OPERSTATE_MAX,
|
||||
_LINK_OPERSTATE_INVALID = -1
|
||||
} LinkOperationalState;
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-address.h"
|
||||
|
||||
struct Link {
|
||||
Manager *manager;
|
||||
|
||||
@ -115,6 +137,7 @@ bool link_has_carrier(Link *link);
|
||||
|
||||
int link_set_mtu(Link *link, uint32_t mtu);
|
||||
int link_set_hostname(Link *link, const char *hostname);
|
||||
int link_set_timezone(Link *link, const char *timezone);
|
||||
|
||||
int ipv4ll_configure(Link *link);
|
||||
int dhcp4_configure(Link *link);
|
||||
@ -130,6 +153,9 @@ bool link_dhcp6_enabled(Link *link);
|
||||
const char* link_state_to_string(LinkState s) _const_;
|
||||
LinkState link_state_from_string(const char *s) _pure_;
|
||||
|
||||
const char* link_operstate_to_string(LinkOperationalState s) _const_;
|
||||
LinkOperationalState link_operstate_from_string(const char *s) _pure_;
|
||||
|
||||
extern const sd_bus_vtable link_vtable[];
|
||||
|
||||
int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
|
||||
|
@ -22,20 +22,21 @@
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-daemon.h"
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "path-util.h"
|
||||
#include "networkd.h"
|
||||
#include "networkd-netdev.h"
|
||||
#include "networkd-link.h"
|
||||
#include "libudev-private.h"
|
||||
#include "udev-util.h"
|
||||
#include "netlink-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "def.h"
|
||||
#include "virt.h"
|
||||
#include "set.h"
|
||||
#include "local-addresses.h"
|
||||
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-daemon.h"
|
||||
#include "networkd.h"
|
||||
|
||||
/* use 8 MB for receive socket kernel queue. */
|
||||
#define RCVBUF_SIZE (8*1024*1024)
|
||||
@ -99,7 +100,7 @@ static int manager_reset_all(Manager *m) {
|
||||
HASHMAP_FOREACH(link, m->links, i) {
|
||||
r = link_carrier_reset(link);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "could not reset carrier: %m");
|
||||
log_link_warning_errno(link, r, "Could not reset carrier: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -204,7 +205,7 @@ static int manager_udev_process_link(Manager *m, struct udev_device *device) {
|
||||
|
||||
ifindex = udev_device_get_ifindex(device);
|
||||
if (ifindex <= 0) {
|
||||
log_debug("ignoring udev ADD event for device with invalid ifindex");
|
||||
log_debug("Ignoring udev ADD event for device with invalid ifindex");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -291,23 +292,23 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "rtnl: could not receive link: %m");
|
||||
log_warning_errno(r, "rtnl: Could not receive link: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_get_type(message, &type);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: could not get message type: %m");
|
||||
log_warning_errno(r, "rtnl: Could not get message type: %m");
|
||||
return 0;
|
||||
} else if (type != RTM_NEWLINK && type != RTM_DELLINK) {
|
||||
log_warning("rtnl: received unexpected message type when processing link");
|
||||
log_warning("rtnl: Received unexpected message type when processing link");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: could not get ifindex from link: %m");
|
||||
log_warning_errno(r, "rtnl: Could not get ifindex from link: %m");
|
||||
return 0;
|
||||
} else if (ifindex <= 0) {
|
||||
log_warning("rtnl: received link message with invalid ifindex: %d", ifindex);
|
||||
@ -317,7 +318,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
|
||||
|
||||
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: received link message without ifname: %m");
|
||||
log_warning_errno(r, "rtnl: Received link message without ifname: %m");
|
||||
return 0;
|
||||
} else
|
||||
netdev_get(m, name, &netdev);
|
||||
@ -328,7 +329,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
|
||||
/* link is new, so add it */
|
||||
r = link_add(m, message, &link);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "could not add new link: %m");
|
||||
log_warning_errno(r, "Could not add new link: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -337,7 +338,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
|
||||
/* netdev exists, so make sure the ifindex matches */
|
||||
r = netdev_set_ifindex(netdev, message);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "could not set ifindex on netdev: %m");
|
||||
log_warning_errno(r, "Could not set ifindex on netdev: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -476,13 +477,13 @@ void manager_free(Manager *m) {
|
||||
|
||||
free(m->state_file);
|
||||
|
||||
sd_event_source_unref(m->udev_event_source);
|
||||
udev_monitor_unref(m->udev_monitor);
|
||||
udev_unref(m->udev);
|
||||
|
||||
sd_bus_unref(m->bus);
|
||||
sd_bus_slot_unref(m->prepare_for_sleep_slot);
|
||||
sd_event_source_unref(m->udev_event_source);
|
||||
sd_event_source_unref(m->bus_retry_event_source);
|
||||
sd_event_unref(m->event);
|
||||
|
||||
while ((link = hashmap_first(m->links)))
|
||||
link_unref(link);
|
||||
@ -501,6 +502,7 @@ void manager_free(Manager *m) {
|
||||
address_pool_free(pool);
|
||||
|
||||
sd_netlink_unref(m->rtnl);
|
||||
sd_event_unref(m->event);
|
||||
|
||||
free(m);
|
||||
}
|
||||
@ -846,36 +848,39 @@ int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, uni
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
|
||||
if (b == ADDRESS_FAMILY_YES ||
|
||||
b == ADDRESS_FAMILY_NO)
|
||||
return yes_no(b == ADDRESS_FAMILY_YES);
|
||||
Link* manager_find_uplink(Manager *m, Link *exclude) {
|
||||
_cleanup_free_ struct local_address *gateways = NULL;
|
||||
int n, i;
|
||||
|
||||
if (b == ADDRESS_FAMILY_IPV4)
|
||||
return "ipv4";
|
||||
if (b == ADDRESS_FAMILY_IPV6)
|
||||
return "ipv6";
|
||||
assert(m);
|
||||
|
||||
/* Looks for a suitable "uplink", via black magic: an
|
||||
* interface that is up and where the default route with the
|
||||
* highest priority points to. */
|
||||
|
||||
n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways);
|
||||
if (n < 0) {
|
||||
log_warning_errno(n, "Failed to determine list of default gateways: %m");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
Link *link;
|
||||
|
||||
link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex));
|
||||
if (!link) {
|
||||
log_debug("Weird, found a gateway for a link we don't know. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (link == exclude)
|
||||
continue;
|
||||
|
||||
if (link->operstate < LINK_OPERSTATE_ROUTABLE)
|
||||
continue;
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
|
||||
int r;
|
||||
|
||||
/* Make this a true superset of a boolean */
|
||||
|
||||
r = parse_boolean(s);
|
||||
if (r > 0)
|
||||
return ADDRESS_FAMILY_YES;
|
||||
if (r == 0)
|
||||
return ADDRESS_FAMILY_NO;
|
||||
|
||||
if (streq(s, "ipv4"))
|
||||
return ADDRESS_FAMILY_IPV4;
|
||||
if (streq(s, "ipv6"))
|
||||
return ADDRESS_FAMILY_IPV6;
|
||||
|
||||
return _ADDRESS_FAMILY_BOOLEAN_INVALID;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
|
||||
|
@ -1,5 +1,7 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
@ -19,7 +21,7 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#pragma once
|
||||
#include "in-addr-util.h"
|
||||
|
||||
typedef struct Bond Bond;
|
||||
|
||||
|
@ -21,15 +21,18 @@
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include "networkd-netdev.h"
|
||||
#include "networkd-link.h"
|
||||
#include "network-internal.h"
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "list.h"
|
||||
#include "siphash24.h"
|
||||
#include "netlink-util.h"
|
||||
#include "network-internal.h"
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-netdev.h"
|
||||
|
||||
const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
|
||||
|
||||
[NETDEV_KIND_BRIDGE] = &bridge_vtable,
|
||||
[NETDEV_KIND_BOND] = &bond_vtable,
|
||||
[NETDEV_KIND_VLAN] = &vlan_vtable,
|
||||
|
@ -21,11 +21,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "networkd.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef struct NetDev NetDev;
|
||||
typedef struct NetDevVTable NetDevVTable;
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-link.h"
|
||||
|
||||
typedef struct netdev_join_callback netdev_join_callback;
|
||||
|
||||
struct netdev_join_callback {
|
||||
|
@ -73,6 +73,15 @@ DHCP.RequestBroadcast, config_parse_bool, 0
|
||||
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
|
||||
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
|
||||
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone)
|
||||
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
|
||||
DHCPServer.DefaultLeaseTimeSec,config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
|
||||
DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns)
|
||||
DHCPServer.DNS, config_parse_dhcp_server_dns, 0, 0
|
||||
DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_ntp)
|
||||
DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0
|
||||
DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone)
|
||||
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)
|
||||
Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost)
|
||||
Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu)
|
||||
Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin)
|
||||
|
@ -26,11 +26,11 @@
|
||||
#include "conf-parser.h"
|
||||
#include "util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "networkd.h"
|
||||
#include "networkd-netdev.h"
|
||||
#include "networkd-link.h"
|
||||
#include "network-internal.h"
|
||||
#include "dns-domain.h"
|
||||
#include "network-internal.h"
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-network.h"
|
||||
|
||||
static int network_load_one(Manager *manager, const char *filename) {
|
||||
_cleanup_network_free_ Network *network = NULL;
|
||||
@ -107,6 +107,10 @@ static int network_load_one(Manager *manager, const char *filename) {
|
||||
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
|
||||
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
|
||||
|
||||
network->dhcp_server_emit_dns = true;
|
||||
network->dhcp_server_emit_ntp = true;
|
||||
network->dhcp_server_emit_timezone = true;
|
||||
|
||||
network->use_bpdu = true;
|
||||
network->allow_port_to_be_root = true;
|
||||
network->unicast_flood = true;
|
||||
@ -124,7 +128,8 @@ static int network_load_one(Manager *manager, const char *filename) {
|
||||
"Address\0"
|
||||
"Route\0"
|
||||
"DHCP\0"
|
||||
"DHCPv4\0"
|
||||
"DHCPv4\0" /* compat */
|
||||
"DHCPServer\0"
|
||||
"Bridge\0"
|
||||
"BridgeFDB\0",
|
||||
config_item_perf_lookup, network_network_gperf_lookup,
|
||||
@ -258,6 +263,10 @@ void network_free(Network *network) {
|
||||
condition_free_list(network->match_kernel);
|
||||
condition_free_list(network->match_arch);
|
||||
|
||||
free(network->dhcp_server_timezone);
|
||||
free(network->dhcp_server_dns);
|
||||
free(network->dhcp_server_ntp);
|
||||
|
||||
free(network);
|
||||
}
|
||||
|
||||
@ -632,57 +641,6 @@ static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type");
|
||||
|
||||
static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
|
||||
[RESOLVE_SUPPORT_NO] = "no",
|
||||
[RESOLVE_SUPPORT_YES] = "yes",
|
||||
[RESOLVE_SUPPORT_RESOLVE] = "resolve",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport);
|
||||
|
||||
int config_parse_resolve(
|
||||
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) {
|
||||
|
||||
ResolveSupport *resolve = data;
|
||||
int k;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(resolve);
|
||||
|
||||
/* Our enum shall be a superset of booleans, hence first try
|
||||
* to parse as boolean, and then as enum */
|
||||
|
||||
k = parse_boolean(rvalue);
|
||||
if (k > 0)
|
||||
*resolve = RESOLVE_SUPPORT_YES;
|
||||
else if (k == 0)
|
||||
*resolve = RESOLVE_SUPPORT_NO;
|
||||
else {
|
||||
ResolveSupport s;
|
||||
|
||||
s = resolve_support_from_string(rvalue);
|
||||
if (s < 0){
|
||||
log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse %s option, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*resolve = s;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ipv6token(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
@ -726,40 +684,6 @@ int config_parse_ipv6token(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_address_family_boolean_with_kernel(
|
||||
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) {
|
||||
|
||||
AddressFamilyBoolean *fwd = data, s;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
s = address_family_boolean_from_string(rvalue);
|
||||
if (s < 0) {
|
||||
if (streq(rvalue, "kernel"))
|
||||
s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
|
||||
else {
|
||||
log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPForwarding option, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*fwd = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
|
||||
[IPV6_PRIVACY_EXTENSIONS_NO] = "no",
|
||||
[IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
|
||||
@ -816,37 +740,165 @@ int config_parse_ipv6_privacy_extensions(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hostname(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) {
|
||||
char **hostname = data;
|
||||
char *hn = NULL;
|
||||
int config_parse_hostname(
|
||||
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) {
|
||||
|
||||
char **hostname = data, *hn = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
r = config_parse_string(unit, filename, line, section, section_line,
|
||||
lvalue, ltype, rvalue, &hn, userdata);
|
||||
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!hostname_is_valid(hn, true)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "hostname is not valid, ignoring assignment: %s", rvalue);
|
||||
|
||||
if (!hostname_is_valid(hn, false)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Hostname is not valid, ignoring assignment: %s", rvalue);
|
||||
free(hn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(*hostname);
|
||||
*hostname = hostname_cleanup(hn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_timezone(
|
||||
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) {
|
||||
|
||||
char **timezone = data, *tz = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!timezone_is_valid(tz)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Timezone is not valid, ignoring assignment: %s", rvalue);
|
||||
free(tz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(*timezone);
|
||||
*timezone = tz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_server_dns(
|
||||
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;
|
||||
struct in_addr a, *m;
|
||||
|
||||
r = extract_first_word(&p, &w, NULL, 0);
|
||||
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;
|
||||
|
||||
if (inet_pton(AF_INET, w, &a) <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server address, ignoring: %s", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr));
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
m[n->n_dhcp_server_dns++] = a;
|
||||
n->dhcp_server_dns = m;
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_dhcp_server_ntp(
|
||||
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;
|
||||
struct in_addr a, *m;
|
||||
|
||||
r = extract_first_word(&p, &w, NULL, 0);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, r, line, "Failed to extract word, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (inet_pton(AF_INET, w, &a) <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, r, line, "Failed to parse NTP server address, ignoring: %s", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr));
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
m[n->n_dhcp_server_ntp++] = a;
|
||||
n->dhcp_server_ntp = m;
|
||||
}
|
||||
}
|
||||
|
179
src/network/networkd-network.h
Normal file
179
src/network/networkd-network.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Tom Gundersen <teg@jklm.no>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "condition.h"
|
||||
|
||||
typedef struct Network Network;
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-netdev.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-fdb.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
#define DHCP_ROUTE_METRIC 1024
|
||||
#define IPV4LL_ROUTE_METRIC 2048
|
||||
|
||||
typedef enum DCHPClientIdentifier {
|
||||
DHCP_CLIENT_ID_MAC,
|
||||
DHCP_CLIENT_ID_DUID,
|
||||
_DHCP_CLIENT_ID_MAX,
|
||||
_DHCP_CLIENT_ID_INVALID = -1,
|
||||
} DCHPClientIdentifier;
|
||||
|
||||
typedef enum IPv6PrivacyExtensions {
|
||||
/* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
|
||||
IPV6_PRIVACY_EXTENSIONS_NO,
|
||||
IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
|
||||
IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
|
||||
_IPV6_PRIVACY_EXTENSIONS_MAX,
|
||||
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
|
||||
} IPv6PrivacyExtensions;
|
||||
|
||||
struct Network {
|
||||
Manager *manager;
|
||||
|
||||
char *filename;
|
||||
char *name;
|
||||
|
||||
struct ether_addr *match_mac;
|
||||
char **match_path;
|
||||
char **match_driver;
|
||||
char **match_type;
|
||||
char **match_name;
|
||||
|
||||
Condition *match_host;
|
||||
Condition *match_virt;
|
||||
Condition *match_kernel;
|
||||
Condition *match_arch;
|
||||
|
||||
char *description;
|
||||
|
||||
NetDev *bridge;
|
||||
NetDev *bond;
|
||||
Hashmap *stacked_netdevs;
|
||||
|
||||
/* DHCP Client Support */
|
||||
AddressFamilyBoolean dhcp;
|
||||
DCHPClientIdentifier dhcp_client_identifier;
|
||||
char *dhcp_vendor_class_identifier;
|
||||
char *hostname;
|
||||
bool dhcp_dns;
|
||||
bool dhcp_ntp;
|
||||
bool dhcp_mtu;
|
||||
bool dhcp_hostname;
|
||||
bool dhcp_domains;
|
||||
bool dhcp_sendhost;
|
||||
bool dhcp_broadcast;
|
||||
bool dhcp_critical;
|
||||
bool dhcp_routes;
|
||||
bool dhcp_timezone;
|
||||
unsigned dhcp_route_metric;
|
||||
|
||||
/* DHCP Server Support */
|
||||
bool dhcp_server;
|
||||
bool dhcp_server_emit_dns;
|
||||
struct in_addr *dhcp_server_dns;
|
||||
unsigned n_dhcp_server_dns;
|
||||
bool dhcp_server_emit_ntp;
|
||||
struct in_addr *dhcp_server_ntp;
|
||||
unsigned n_dhcp_server_ntp;
|
||||
bool dhcp_server_emit_timezone;
|
||||
char *dhcp_server_timezone;
|
||||
usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec;
|
||||
|
||||
/* IPV4LL Support */
|
||||
AddressFamilyBoolean link_local;
|
||||
bool ipv4ll_route;
|
||||
|
||||
/* Bridge Support */
|
||||
bool use_bpdu;
|
||||
bool hairpin;
|
||||
bool fast_leave;
|
||||
bool allow_port_to_be_root;
|
||||
bool unicast_flood;
|
||||
unsigned cost;
|
||||
|
||||
AddressFamilyBoolean ip_forward;
|
||||
bool ip_masquerade;
|
||||
|
||||
union in_addr_union ipv6_token;
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions;
|
||||
|
||||
struct ether_addr *mac;
|
||||
unsigned mtu;
|
||||
|
||||
bool lldp;
|
||||
|
||||
LIST_HEAD(Address, static_addresses);
|
||||
LIST_HEAD(Route, static_routes);
|
||||
LIST_HEAD(FdbEntry, static_fdb_entries);
|
||||
|
||||
Hashmap *addresses_by_section;
|
||||
Hashmap *routes_by_section;
|
||||
Hashmap *fdb_entries_by_section;
|
||||
|
||||
bool wildcard_domain;
|
||||
char **domains, **dns, **ntp, **bind_carrier;
|
||||
|
||||
ResolveSupport llmnr;
|
||||
|
||||
LIST_FIELDS(Network, networks);
|
||||
};
|
||||
|
||||
void network_free(Network *network);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
|
||||
#define _cleanup_network_free_ _cleanup_(network_freep)
|
||||
|
||||
int network_load(Manager *manager);
|
||||
|
||||
int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
||||
int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *mac, Network **ret);
|
||||
int network_apply(Manager *manager, Network *network, Link *link);
|
||||
|
||||
int config_parse_netdev(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);
|
||||
int config_parse_domains(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);
|
||||
int config_parse_tunnel(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);
|
||||
int config_parse_dhcp(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);
|
||||
int config_parse_dhcp_client_identifier(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);
|
||||
int config_parse_ipv6token(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);
|
||||
int config_parse_ipv6_privacy_extensions(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);
|
||||
int config_parse_hostname(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);
|
||||
int config_parse_timezone(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);
|
||||
int config_parse_dhcp_server_dns(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);
|
||||
int config_parse_dhcp_server_ntp(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);
|
||||
|
||||
/* Legacy IPv4LL support */
|
||||
int config_parse_ipv4ll(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);
|
||||
|
||||
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
|
||||
|
||||
extern const sd_bus_vtable network_vtable[];
|
||||
|
||||
int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
|
||||
int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
|
||||
|
||||
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
|
@ -19,12 +19,12 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-link.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "netlink-util.h"
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-route.h"
|
||||
|
||||
int route_new_static(Network *network, unsigned section, Route **ret) {
|
||||
_cleanup_route_free_ Route *route = NULL;
|
||||
|
60
src/network/networkd-route.h
Normal file
60
src/network/networkd-route.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Tom Gundersen <teg@jklm.no>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
typedef struct Route Route;
|
||||
|
||||
#include "networkd.h"
|
||||
#include "networkd-network.h"
|
||||
|
||||
struct Route {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
|
||||
int family;
|
||||
unsigned char dst_prefixlen;
|
||||
unsigned char src_prefixlen;
|
||||
unsigned char scope;
|
||||
uint32_t metrics;
|
||||
unsigned char protocol; /* RTPROT_* */
|
||||
|
||||
union in_addr_union in_addr;
|
||||
union in_addr_union dst_addr;
|
||||
union in_addr_union src_addr;
|
||||
union in_addr_union prefsrc_addr;
|
||||
|
||||
LIST_FIELDS(Route, routes);
|
||||
};
|
||||
|
||||
int route_new_static(Network *network, unsigned section, Route **ret);
|
||||
int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
|
||||
void route_free(Route *route);
|
||||
int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
|
||||
int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
|
||||
#define _cleanup_route_free_ _cleanup_(route_freep)
|
||||
|
||||
int config_parse_gateway(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);
|
||||
int config_parse_destination(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);
|
||||
int config_parse_route_priority(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);
|
||||
int config_parse_route_scope(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);
|
144
src/network/networkd-util.c
Normal file
144
src/network/networkd-util.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Tom Gundersen <teg@jklm.no>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "util.h"
|
||||
#include "conf-parser.h"
|
||||
|
||||
#include "networkd-util.h"
|
||||
|
||||
const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
|
||||
if (b == ADDRESS_FAMILY_YES ||
|
||||
b == ADDRESS_FAMILY_NO)
|
||||
return yes_no(b == ADDRESS_FAMILY_YES);
|
||||
|
||||
if (b == ADDRESS_FAMILY_IPV4)
|
||||
return "ipv4";
|
||||
if (b == ADDRESS_FAMILY_IPV6)
|
||||
return "ipv6";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
|
||||
int r;
|
||||
|
||||
/* Make this a true superset of a boolean */
|
||||
|
||||
r = parse_boolean(s);
|
||||
if (r > 0)
|
||||
return ADDRESS_FAMILY_YES;
|
||||
if (r == 0)
|
||||
return ADDRESS_FAMILY_NO;
|
||||
|
||||
if (streq(s, "ipv4"))
|
||||
return ADDRESS_FAMILY_IPV4;
|
||||
if (streq(s, "ipv6"))
|
||||
return ADDRESS_FAMILY_IPV6;
|
||||
|
||||
return _ADDRESS_FAMILY_BOOLEAN_INVALID;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
|
||||
|
||||
int config_parse_address_family_boolean_with_kernel(
|
||||
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) {
|
||||
|
||||
AddressFamilyBoolean *fwd = data, s;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
s = address_family_boolean_from_string(rvalue);
|
||||
if (s < 0) {
|
||||
if (streq(rvalue, "kernel"))
|
||||
s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
|
||||
else {
|
||||
log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPForwarding= option, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*fwd = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
|
||||
[RESOLVE_SUPPORT_NO] = "no",
|
||||
[RESOLVE_SUPPORT_YES] = "yes",
|
||||
[RESOLVE_SUPPORT_RESOLVE] = "resolve",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport);
|
||||
|
||||
int config_parse_resolve(
|
||||
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) {
|
||||
|
||||
ResolveSupport *resolve = data;
|
||||
int k;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(resolve);
|
||||
|
||||
/* Our enum shall be a superset of booleans, hence first try
|
||||
* to parse as boolean, and then as enum */
|
||||
|
||||
k = parse_boolean(rvalue);
|
||||
if (k > 0)
|
||||
*resolve = RESOLVE_SUPPORT_YES;
|
||||
else if (k == 0)
|
||||
*resolve = RESOLVE_SUPPORT_NO;
|
||||
else {
|
||||
ResolveSupport s;
|
||||
|
||||
s = resolve_support_from_string(rvalue);
|
||||
if (s < 0){
|
||||
log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse %s= option, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*resolve = s;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
52
src/network/networkd-util.h
Normal file
52
src/network/networkd-util.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Tom Gundersen <teg@jklm.no>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
typedef enum AddressFamilyBoolean {
|
||||
/* This is a bitmask, though it usually doesn't feel that way! */
|
||||
ADDRESS_FAMILY_NO = 0,
|
||||
ADDRESS_FAMILY_IPV4 = 1,
|
||||
ADDRESS_FAMILY_IPV6 = 2,
|
||||
ADDRESS_FAMILY_YES = 3,
|
||||
_ADDRESS_FAMILY_BOOLEAN_MAX,
|
||||
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
|
||||
} AddressFamilyBoolean;
|
||||
|
||||
typedef enum ResolveSupport {
|
||||
RESOLVE_SUPPORT_NO,
|
||||
RESOLVE_SUPPORT_YES,
|
||||
RESOLVE_SUPPORT_RESOLVE,
|
||||
_RESOLVE_SUPPORT_MAX,
|
||||
_RESOLVE_SUPPORT_INVALID = -1,
|
||||
} ResolveSupport;
|
||||
|
||||
int config_parse_resolve(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);
|
||||
int config_parse_address_family_boolean(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);
|
||||
int config_parse_address_family_boolean_with_kernel(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);
|
||||
|
||||
const char* resolve_support_to_string(ResolveSupport i) _const_;
|
||||
ResolveSupport resolve_support_from_string(const char *s) _pure_;
|
||||
|
||||
const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
|
||||
AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
|
@ -26,213 +26,17 @@
|
||||
#include "sd-event.h"
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-bus.h"
|
||||
#include "sd-dhcp-client.h"
|
||||
#include "sd-dhcp-server.h"
|
||||
#include "sd-ipv4ll.h"
|
||||
#include "sd-icmp6-nd.h"
|
||||
#include "sd-dhcp6-client.h"
|
||||
#include "udev.h"
|
||||
#include "sd-lldp.h"
|
||||
|
||||
#include "netlink-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "list.h"
|
||||
#include "set.h"
|
||||
#include "condition.h"
|
||||
#include "in-addr-util.h"
|
||||
|
||||
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
|
||||
#define DHCP_ROUTE_METRIC 1024
|
||||
#define IPV4LL_ROUTE_METRIC 2048
|
||||
|
||||
typedef struct NetDev NetDev;
|
||||
typedef struct Network Network;
|
||||
typedef struct Link Link;
|
||||
typedef struct Address Address;
|
||||
typedef struct Route Route;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct AddressPool AddressPool;
|
||||
typedef struct FdbEntry FdbEntry;
|
||||
|
||||
typedef enum AddressFamilyBoolean {
|
||||
/* This is a bitmask, though it usually doesn't feel that way! */
|
||||
ADDRESS_FAMILY_NO = 0,
|
||||
ADDRESS_FAMILY_IPV4 = 1,
|
||||
ADDRESS_FAMILY_IPV6 = 2,
|
||||
ADDRESS_FAMILY_YES = 3,
|
||||
_ADDRESS_FAMILY_BOOLEAN_MAX,
|
||||
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
|
||||
} AddressFamilyBoolean;
|
||||
|
||||
typedef enum ResolveSupport {
|
||||
RESOLVE_SUPPORT_NO,
|
||||
RESOLVE_SUPPORT_YES,
|
||||
RESOLVE_SUPPORT_RESOLVE,
|
||||
_RESOLVE_SUPPORT_MAX,
|
||||
_RESOLVE_SUPPORT_INVALID = -1,
|
||||
} ResolveSupport;
|
||||
|
||||
typedef enum LinkOperationalState {
|
||||
LINK_OPERSTATE_OFF,
|
||||
LINK_OPERSTATE_NO_CARRIER,
|
||||
LINK_OPERSTATE_DORMANT,
|
||||
LINK_OPERSTATE_CARRIER,
|
||||
LINK_OPERSTATE_DEGRADED,
|
||||
LINK_OPERSTATE_ROUTABLE,
|
||||
_LINK_OPERSTATE_MAX,
|
||||
_LINK_OPERSTATE_INVALID = -1
|
||||
} LinkOperationalState;
|
||||
|
||||
typedef enum DCHPClientIdentifier {
|
||||
DHCP_CLIENT_ID_MAC,
|
||||
DHCP_CLIENT_ID_DUID,
|
||||
_DHCP_CLIENT_ID_MAX,
|
||||
_DHCP_CLIENT_ID_INVALID = -1,
|
||||
} DCHPClientIdentifier;
|
||||
|
||||
typedef enum IPv6PrivacyExtensions {
|
||||
/* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
|
||||
IPV6_PRIVACY_EXTENSIONS_NO,
|
||||
IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
|
||||
IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
|
||||
_IPV6_PRIVACY_EXTENSIONS_MAX,
|
||||
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
|
||||
} IPv6PrivacyExtensions;
|
||||
|
||||
struct FdbEntry {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
|
||||
struct ether_addr *mac_addr;
|
||||
uint16_t vlan_id;
|
||||
|
||||
LIST_FIELDS(FdbEntry, static_fdb_entries);
|
||||
};
|
||||
|
||||
struct Network {
|
||||
Manager *manager;
|
||||
|
||||
char *filename;
|
||||
char *name;
|
||||
|
||||
struct ether_addr *match_mac;
|
||||
char **match_path;
|
||||
char **match_driver;
|
||||
char **match_type;
|
||||
char **match_name;
|
||||
|
||||
Condition *match_host;
|
||||
Condition *match_virt;
|
||||
Condition *match_kernel;
|
||||
Condition *match_arch;
|
||||
|
||||
char *description;
|
||||
NetDev *bridge;
|
||||
NetDev *bond;
|
||||
Hashmap *stacked_netdevs;
|
||||
AddressFamilyBoolean dhcp;
|
||||
DCHPClientIdentifier dhcp_client_identifier;
|
||||
char *dhcp_vendor_class_identifier;
|
||||
char *hostname;
|
||||
bool dhcp_dns;
|
||||
bool dhcp_ntp;
|
||||
bool dhcp_mtu;
|
||||
bool dhcp_hostname;
|
||||
bool dhcp_domains;
|
||||
bool dhcp_sendhost;
|
||||
bool dhcp_broadcast;
|
||||
bool dhcp_critical;
|
||||
bool dhcp_routes;
|
||||
unsigned dhcp_route_metric;
|
||||
AddressFamilyBoolean link_local;
|
||||
bool ipv4ll_route;
|
||||
union in_addr_union ipv6_token;
|
||||
|
||||
bool dhcp_server;
|
||||
|
||||
bool use_bpdu;
|
||||
bool hairpin;
|
||||
bool fast_leave;
|
||||
bool allow_port_to_be_root;
|
||||
bool unicast_flood;
|
||||
unsigned cost;
|
||||
|
||||
AddressFamilyBoolean ip_forward;
|
||||
bool ip_masquerade;
|
||||
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions;
|
||||
|
||||
struct ether_addr *mac;
|
||||
unsigned mtu;
|
||||
|
||||
bool lldp;
|
||||
|
||||
LIST_HEAD(Address, static_addresses);
|
||||
LIST_HEAD(Route, static_routes);
|
||||
LIST_HEAD(FdbEntry, static_fdb_entries);
|
||||
|
||||
Hashmap *addresses_by_section;
|
||||
Hashmap *routes_by_section;
|
||||
Hashmap *fdb_entries_by_section;
|
||||
|
||||
bool wildcard_domain;
|
||||
char **domains, **dns, **ntp, **bind_carrier;
|
||||
|
||||
ResolveSupport llmnr;
|
||||
|
||||
LIST_FIELDS(Network, networks);
|
||||
};
|
||||
|
||||
struct Address {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
|
||||
int family;
|
||||
unsigned char prefixlen;
|
||||
unsigned char scope;
|
||||
uint32_t flags;
|
||||
char *label;
|
||||
|
||||
struct in_addr broadcast;
|
||||
struct ifa_cacheinfo cinfo;
|
||||
|
||||
union in_addr_union in_addr;
|
||||
union in_addr_union in_addr_peer;
|
||||
|
||||
bool ip_masquerade_done;
|
||||
|
||||
LIST_FIELDS(Address, addresses);
|
||||
};
|
||||
|
||||
struct Route {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
|
||||
int family;
|
||||
unsigned char dst_prefixlen;
|
||||
unsigned char src_prefixlen;
|
||||
unsigned char scope;
|
||||
uint32_t metrics;
|
||||
unsigned char protocol; /* RTPROT_* */
|
||||
|
||||
union in_addr_union in_addr;
|
||||
union in_addr_union dst_addr;
|
||||
union in_addr_union src_addr;
|
||||
union in_addr_union prefsrc_addr;
|
||||
|
||||
LIST_FIELDS(Route, routes);
|
||||
};
|
||||
|
||||
struct AddressPool {
|
||||
Manager *manager;
|
||||
|
||||
int family;
|
||||
unsigned prefixlen;
|
||||
|
||||
union in_addr_union in_addr;
|
||||
|
||||
LIST_FIELDS(AddressPool, address_pools);
|
||||
};
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-address-pool.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
struct Manager {
|
||||
sd_netlink *rtnl;
|
||||
@ -281,183 +85,7 @@ int manager_save(Manager *m);
|
||||
|
||||
int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);
|
||||
|
||||
Link* manager_find_uplink(Manager *m, Link *exclude);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
#define _cleanup_manager_free_ _cleanup_(manager_freep)
|
||||
|
||||
/* Network */
|
||||
|
||||
int network_load(Manager *manager);
|
||||
|
||||
void network_free(Network *network);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
|
||||
#define _cleanup_network_free_ _cleanup_(network_freep)
|
||||
|
||||
int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
||||
int network_get(Manager *manager, struct udev_device *device,
|
||||
const char *ifname, const struct ether_addr *mac,
|
||||
Network **ret);
|
||||
int network_apply(Manager *manager, Network *network, Link *link);
|
||||
|
||||
int config_parse_netdev(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);
|
||||
|
||||
int config_parse_domains(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);
|
||||
|
||||
int config_parse_tunnel(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);
|
||||
|
||||
extern const sd_bus_vtable network_vtable[];
|
||||
|
||||
int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
|
||||
int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
|
||||
|
||||
/* gperf */
|
||||
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
|
||||
|
||||
/* Route */
|
||||
int route_new_static(Network *network, unsigned section, Route **ret);
|
||||
int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
|
||||
void route_free(Route *route);
|
||||
int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
|
||||
int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback);
|
||||
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
|
||||
#define _cleanup_route_free_ _cleanup_(route_freep)
|
||||
|
||||
int config_parse_gateway(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);
|
||||
|
||||
int config_parse_destination(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);
|
||||
|
||||
int config_parse_route_priority(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);
|
||||
|
||||
int config_parse_route_scope(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);
|
||||
/* Address */
|
||||
int address_new_static(Network *network, unsigned section, Address **ret);
|
||||
int address_new_dynamic(Address **ret);
|
||||
void address_free(Address *address);
|
||||
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_establish(Address *address, Link *link);
|
||||
int address_release(Address *address, Link *link);
|
||||
bool address_equal(Address *a1, Address *a2);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
|
||||
#define _cleanup_address_free_ _cleanup_(address_freep)
|
||||
|
||||
int config_parse_address(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);
|
||||
|
||||
int config_parse_broadcast(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);
|
||||
|
||||
int config_parse_label(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);
|
||||
|
||||
/* Forwarding database table. */
|
||||
int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry);
|
||||
void fdb_entry_free(FdbEntry *fdb_entry);
|
||||
int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free);
|
||||
#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep)
|
||||
|
||||
int config_parse_fdb_hwaddr(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);
|
||||
|
||||
int config_parse_fdb_vlan_id(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);
|
||||
|
||||
/* DHCP support */
|
||||
|
||||
int config_parse_dhcp(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);
|
||||
int config_parse_dhcp_client_identifier(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);
|
||||
|
||||
/* IPv4LL support (legacy) */
|
||||
|
||||
int config_parse_ipv4ll(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);
|
||||
|
||||
/* IPv6 support */
|
||||
int config_parse_ipv6token(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);
|
||||
|
||||
/* Resolve protocols support */
|
||||
|
||||
const char* resolve_support_to_string(ResolveSupport i) _const_;
|
||||
ResolveSupport resolve_support_from_string(const char *s) _pure_;
|
||||
|
||||
int config_parse_resolve(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);
|
||||
|
||||
/* Address Pool */
|
||||
|
||||
int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen);
|
||||
int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen);
|
||||
void address_pool_free(AddressPool *p);
|
||||
|
||||
int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found);
|
||||
|
||||
const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
|
||||
AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
|
||||
|
||||
int config_parse_address_family_boolean(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);
|
||||
|
||||
/* IPForwarding parser */
|
||||
int config_parse_address_family_boolean_with_kernel(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);
|
||||
|
||||
/* Operational State */
|
||||
|
||||
const char* link_operstate_to_string(LinkOperationalState s) _const_;
|
||||
LinkOperationalState link_operstate_from_string(const char *s) _pure_;
|
||||
|
||||
/* IPv6 privacy extensions support */
|
||||
|
||||
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
|
||||
|
||||
int config_parse_ipv6_privacy_extensions(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);
|
||||
|
||||
|
||||
/* Hostname */
|
||||
int config_parse_hostname(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);
|
||||
|
@ -34,6 +34,9 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);
|
||||
|
||||
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr);
|
||||
int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime);
|
||||
int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1);
|
||||
int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2);
|
||||
int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr);
|
||||
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr);
|
||||
int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr);
|
||||
int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
|
||||
@ -44,13 +47,9 @@ 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_hostname(sd_dhcp_lease *lease, const char **hostname);
|
||||
int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
|
||||
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn);
|
||||
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data,
|
||||
size_t *data_len);
|
||||
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
|
||||
size_t *client_id_len);
|
||||
|
||||
int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
|
||||
int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
|
||||
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes);
|
||||
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
|
||||
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
|
||||
int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
|
||||
|
||||
#endif
|
||||
|
@ -30,11 +30,11 @@
|
||||
|
||||
typedef struct sd_dhcp_server sd_dhcp_server;
|
||||
|
||||
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex);
|
||||
|
||||
sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server);
|
||||
sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server);
|
||||
|
||||
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex);
|
||||
|
||||
int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int priority);
|
||||
int sd_dhcp_server_detach_event(sd_dhcp_server *client);
|
||||
sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client);
|
||||
@ -47,5 +47,13 @@ int sd_dhcp_server_stop(sd_dhcp_server *server);
|
||||
int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen);
|
||||
int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *start, size_t size);
|
||||
|
||||
int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone);
|
||||
int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n);
|
||||
int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr dns[], unsigned n);
|
||||
|
||||
int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t);
|
||||
int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
|
||||
|
||||
int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
|
||||
|
||||
#endif
|
||||
|
@ -122,6 +122,9 @@ int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);
|
||||
/* Get the CARRIERS that are bound to current link. */
|
||||
int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
|
||||
|
||||
/* Get the timezone that was learnt on a specific link. */
|
||||
int sd_network_link_get_timezone(int ifindex, char **timezone);
|
||||
|
||||
/* Returns whether or not domains that don't match any link should be resolved
|
||||
* on this link. 1 for yes, 0 for no and negative value for error */
|
||||
int sd_network_link_get_wildcard_domain(int ifindex);
|
||||
|
@ -68,32 +68,15 @@ static int context_read_data(Context *c) {
|
||||
|
||||
assert(c);
|
||||
|
||||
r = readlink_malloc("/etc/localtime", &t);
|
||||
if (r < 0) {
|
||||
if (r == -EINVAL)
|
||||
log_warning("/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.");
|
||||
else
|
||||
log_warning_errno(r, "Failed to get target of /etc/localtime: %m");
|
||||
} else {
|
||||
const char *e;
|
||||
r = get_timezone(&t);
|
||||
if (r == -EINVAL)
|
||||
log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.");
|
||||
else if (r < 0)
|
||||
log_warning_errno(r, "Failed to get target of /etc/localtime: %m");
|
||||
|
||||
e = path_startswith(t, "/usr/share/zoneinfo/");
|
||||
if (!e)
|
||||
e = path_startswith(t, "../usr/share/zoneinfo/");
|
||||
|
||||
if (!e)
|
||||
log_warning("/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.");
|
||||
else {
|
||||
c->zone = strdup(e);
|
||||
if (!c->zone)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
if (isempty(c->zone)) {
|
||||
free(c->zone);
|
||||
c->zone = NULL;
|
||||
}
|
||||
free(c->zone);
|
||||
c->zone = t;
|
||||
t = NULL;
|
||||
|
||||
c->local_rtc = clock_is_localtime() > 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user