Merge pull request #3156 from keszybz/duid-settings

Rework DUID setting
This commit is contained in:
Lennart Poettering 2016-05-04 11:31:59 +02:00
commit 5119d304ff
46 changed files with 671 additions and 435 deletions

1
.gitignore vendored
View File

@ -235,6 +235,7 @@
/test-ndisc-rs /test-ndisc-rs
/test-netlink /test-netlink
/test-netlink-manual /test-netlink-manual
/test-netword-conf
/test-network /test-network
/test-network-tables /test-network-tables
/test-ns /test-ns

View File

@ -5515,6 +5515,12 @@ networkctl_LDADD = \
dist_bashcompletion_data += \ dist_bashcompletion_data += \
shell-completion/bash/networkctl shell-completion/bash/networkctl
test_networkd_conf_SOURCES = \
src/network/test-networkd-conf.c
test_networkd_conf_LDADD = \
libnetworkd-core.la
test_network_SOURCES = \ test_network_SOURCES = \
src/network/test-network.c src/network/test-network.c
@ -5540,6 +5546,7 @@ test_network_tables_LDADD += \
endif endif
tests += \ tests += \
test-networkd-conf \
test-network \ test-network \
test-network-tables test-network-tables

View File

@ -58,14 +58,14 @@
<title>Description</title> <title>Description</title>
<para>These configuration files control global network parameters. <para>These configuration files control global network parameters.
For e.g. DHCP Unique Identifier (DUID).</para> Currently the DHCP Unique Identifier (DUID).</para>
</refsect1> </refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" /> <xi:include href="standard-conf.xml" xpointer="main-conf" />
<refsect1> <refsect1>
<title>[DUID] Section Options</title> <title>[DHCP] Section Options</title>
<para>This section configures the DHCP Unique Identifier (DUID) value used by DHCP <para>This section configures the DHCP Unique Identifier (DUID) value used by DHCP
protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface
@ -73,28 +73,71 @@
address. DHCPv4 client protocol sends IAID and DUID to the DHCP server when acquiring address. DHCPv4 client protocol sends IAID and DUID to the DHCP server when acquiring
a dynamic IPv4 address if <option>ClientIdentifier=duid</option>. IAID and DUID allows a dynamic IPv4 address if <option>ClientIdentifier=duid</option>. IAID and DUID allows
a DHCP server to uniquely identify the machine and the interface requesting a DHCP IP. a DHCP server to uniquely identify the machine and the interface requesting a DHCP IP.
To configure IAID and ClientIdentifier, see <citerefentry><refentrytitle>systemd.network To configure IAID and ClientIdentifier, see
</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
<para>The DUID value specified here overrides the DUID that systemd-networkd <para>The following options are understood:</para>
generates using the machine-id from the <filename>/etc/machine-id</filename> file.
To configure DUID per-network, see <citerefentry><refentrytitle>systemd.network
</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>The configured DHCP DUID should conform to the specification in
<ulink url="http://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>,
<ulink url="http://tools.ietf.org/html/rfc6355">RFC 6355</ulink>. To configure IAID, see
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>.</para>
<para>The following options are available in <literal>[DUID]</literal> section:</para>
<variablelist class='network-directives'> <variablelist class='network-directives'>
<varlistentry>
<term><varname>DUIDType=</varname></term>
<listitem><para>Specifies how the DUID should be generated. See
<ulink url="https://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>
for a description of all the options.</para>
<para>The following values are understood:
<variablelist>
<varlistentry>
<term><option>vendor</option> </term>
<listitem><para>If <literal>DUIDType=vendor</literal>, then the DUID value will be generated using
<literal>43793</literal> as the vendor identifier (systemd) and hashed contents of
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
This is the default if <varname>DUIDType=</varname> is not specified.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>link-layer-time</option> </term>
<term><option>link-layer</option> </term>
<term><option>uuid</option> </term>
<listitem><para>Those values are parsed and can be used to set the DUID type
field, but DUID contents must be provided using <varname>DUIDRawData=</varname>.
</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>In all cases, <varname>DUIDRawData=</varname> can be used to override the
actual DUID value that is used.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>RawData=</varname></term> <term><varname>DUIDRawData=</varname></term>
<listitem><para>Specifies the DUID bytes as a single newline-terminated, hexadecimal <listitem><para>Specifies the DHCP DUID value as a single newline-terminated, hexadecimal string, with each
string, with each byte separated by a ':'.</para></listitem> byte separated by <literal>:</literal>. The DUID that is sent is composed of the DUID type specified by
<varname>DUIDType=</varname> and the value configured here.</para>
<para>The DUID value specified here overrides the DUID that systemd-networkd generates using the machine-id
from the <filename>/etc/machine-id</filename> file. To configure DUID per-network, see
<citerefentry><refentrytitle>systemd.network </refentrytitle><manvolnum>5</manvolnum></citerefentry>.
The configured DHCP DUID should conform to the specification in
<ulink url="http://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>,
<ulink url="http://tools.ietf.org/html/rfc6355">RFC 6355</ulink>. To configure IAID, see
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>.</para>
<example>
<title>A <option>DUIDType=vendor</option> with a custom value</title>
<programlisting>DUIDType=vendor
DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</programlisting>
<para>This specifies a 14 byte DUID, with the type DUID-EN (<literal>00:02</literal>), enterprise number
43793 (<literal>00:00:ab:11</literal>), and identifier value <literal>f9:2a:c2:77:29:f9:5c:00</literal>.
</para>
</example>
</listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -832,6 +832,7 @@
false.</para> false.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>ClientIdentifier=</varname></term> <term><varname>ClientIdentifier=</varname></term>
<listitem> <listitem>
@ -839,6 +840,7 @@
or <literal>duid</literal> (the default, see below) to use a RFC4361-compliant Client ID.</para> or <literal>duid</literal> (the default, see below) to use a RFC4361-compliant Client ID.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>VendorClassIdentifier=</varname></term> <term><varname>VendorClassIdentifier=</varname></term>
<listitem> <listitem>
@ -846,25 +848,25 @@
type and configuration.</para> type and configuration.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>DUIDRawData=</varname></term> <term><varname>DUIDType=</varname></term>
<listitem><para>Specifies the DHCP DUID bytes as a single newline-terminated, hexadecimal string, with each <listitem>
byte separated by a ':'. A DHCPv6 client sends the DHCP Unique Identifier (DUID) and the interface Identity <para>Override the global <varname>DUIDType</varname> setting for this network. See
Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6 address. Similar, DHCPv4 clients <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
send the IAID and DUID to the DHCP server when acquiring a dynamic IPv4 address if for a description of possible values.</para>
<option>ClientIdentifier=duid</option>. IAID and DUID allows a DHCP server to uniquely identify the machine
and the interface requesting a DHCP IP address.</para>
<para>The DUID value specified here takes precedence over the DUID that systemd-networkd generates
using the machine-id from the <filename>/etc/machine-id</filename> file, as well as the
global DUID that may be specified in <citerefentry><refentrytitle>networkd.conf
</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>The configured DHCP DUID should conform to the specification in
<ulink url="http://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>,
<ulink url="http://tools.ietf.org/html/rfc6355">RFC 6355</ulink>.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>DUIDRawData=</varname></term>
<listitem>
<para>Override the global <varname>DUIDRawData</varname> setting for this network. See
<citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for a description of possible values.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>RequestBroadcast=</varname></term> <term><varname>RequestBroadcast=</varname></term>
<listitem> <listitem>
@ -876,6 +878,7 @@
networks where broadcasts are filtered out.</para> networks where broadcasts are filtered out.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>RouteMetric=</varname></term> <term><varname>RouteMetric=</varname></term>
<listitem> <listitem>

View File

@ -31,6 +31,37 @@
#define SYSTEMD_PEN 43793 #define SYSTEMD_PEN 43793
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
struct duid d;
assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
if (duid_len > MAX_DUID_LEN)
return -EINVAL;
switch (duid_type) {
case DUID_TYPE_LLT:
if (duid_len <= sizeof(d.llt))
return -EINVAL;
break;
case DUID_TYPE_EN:
if (duid_len != sizeof(d.en))
return -EINVAL;
break;
case DUID_TYPE_LL:
if (duid_len <= sizeof(d.ll))
return -EINVAL;
break;
case DUID_TYPE_UUID:
if (duid_len != sizeof(d.uuid))
return -EINVAL;
break;
default:
/* accept unknown type in order to be forward compatible */
break;
}
return 0;
}
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
sd_id128_t machine_id; sd_id128_t machine_id;
uint64_t hash; uint64_t hash;

View File

@ -26,7 +26,6 @@
#include "unaligned.h" #include "unaligned.h"
typedef enum DUIDType { typedef enum DUIDType {
DUID_TYPE_RAW = 0,
DUID_TYPE_LLT = 1, DUID_TYPE_LLT = 1,
DUID_TYPE_EN = 2, DUID_TYPE_EN = 2,
DUID_TYPE_LL = 3, DUID_TYPE_LL = 3,
@ -40,27 +39,28 @@ typedef enum DUIDType {
*/ */
#define MAX_DUID_LEN 128 #define MAX_DUID_LEN 128
/* https://tools.ietf.org/html/rfc3315#section-9.1 */
struct duid { struct duid {
be16_t type; be16_t type;
union { union {
struct { struct {
/* DHCP6_DUID_LLT */ /* DUID_TYPE_LLT */
uint16_t htype; uint16_t htype;
uint32_t time; uint32_t time;
uint8_t haddr[0]; uint8_t haddr[0];
} _packed_ llt; } _packed_ llt;
struct { struct {
/* DHCP6_DUID_EN */ /* DUID_TYPE_EN */
uint32_t pen; uint32_t pen;
uint8_t id[8]; uint8_t id[8];
} _packed_ en; } _packed_ en;
struct { struct {
/* DHCP6_DUID_LL */ /* DUID_TYPE_LL */
int16_t htype; int16_t htype;
uint8_t haddr[0]; uint8_t haddr[0];
} _packed_ ll; } _packed_ ll;
struct { struct {
/* DHCP6_DUID_UUID */ /* DUID_TYPE_UUID */
sd_id128_t uuid; sd_id128_t uuid;
} _packed_ uuid; } _packed_ uuid;
struct { struct {
@ -69,36 +69,6 @@ struct duid {
}; };
} _packed_; } _packed_;
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id); int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
struct duid d;
assert(duid_len > 0);
switch (duid_type) {
case DUID_TYPE_LLT:
if (duid_len <= sizeof(d.llt))
return -EINVAL;
break;
case DUID_TYPE_EN:
if (duid_len != sizeof(d.en))
return -EINVAL;
break;
case DUID_TYPE_LL:
if (duid_len <= sizeof(d.ll))
return -EINVAL;
break;
case DUID_TYPE_UUID:
if (duid_len != sizeof(d.uuid))
return -EINVAL;
break;
default:
if (duid_len > sizeof(d.raw))
return -EINVAL;
/* accept unknown type in order to be forward compatible */
break;
}
return 0;
}

View File

@ -115,14 +115,22 @@ static const uint8_t default_req_opts[] = {
SD_DHCP_OPTION_DOMAIN_NAME_SERVER, SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
}; };
static int client_receive_message_raw(sd_event_source *s, int fd, static int client_receive_message_raw(
uint32_t revents, void *userdata); sd_event_source *s,
static int client_receive_message_udp(sd_event_source *s, int fd, int fd,
uint32_t revents, void *userdata); uint32_t revents,
void *userdata);
static int client_receive_message_udp(
sd_event_source *s,
int fd,
uint32_t revents,
void *userdata);
static void client_stop(sd_dhcp_client *client, int error); static void client_stop(sd_dhcp_client *client, int error);
int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb, int sd_dhcp_client_set_callback(
void *userdata) { sd_dhcp_client *client,
sd_dhcp_client_callback_t cb,
void *userdata) {
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
client->cb = cb; client->cb = cb;
@ -171,8 +179,9 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
return 0; return 0;
} }
int sd_dhcp_client_set_request_address(sd_dhcp_client *client, int sd_dhcp_client_set_request_address(
const struct in_addr *last_addr) { sd_dhcp_client *client,
const struct in_addr *last_addr) {
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return (IN_SET(client->state, DHCP_STATE_INIT, assert_return (IN_SET(client->state, DHCP_STATE_INIT,
DHCP_STATE_STOPPED), -EBUSY); DHCP_STATE_STOPPED), -EBUSY);
@ -196,8 +205,12 @@ int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
return 0; return 0;
} }
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, int sd_dhcp_client_set_mac(
size_t addr_len, uint16_t arp_type) { sd_dhcp_client *client,
const uint8_t *addr,
size_t addr_len,
uint16_t arp_type) {
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false; bool need_restart = false;
@ -234,8 +247,11 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
return 0; return 0;
} }
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, int sd_dhcp_client_get_client_id(
const uint8_t **data, size_t *data_len) { sd_dhcp_client *client,
uint8_t *type,
const uint8_t **data,
size_t *data_len) {
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(type, -EINVAL); assert_return(type, -EINVAL);
@ -254,8 +270,12 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
return 0; return 0;
} }
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, int sd_dhcp_client_set_client_id(
const uint8_t *data, size_t data_len) { sd_dhcp_client *client,
uint8_t type,
const uint8_t *data,
size_t data_len) {
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false; bool need_restart = false;
@ -298,13 +318,32 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
return 0; return 0;
} }
int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid, /**
uint16_t duid_type, uint8_t *duid, size_t duid_len) { * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
int sd_dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
uint32_t iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
int r; int r;
assert_return(client, -EINVAL); size_t len;
zero(client->client_id);
assert_return(client, -EINVAL);
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
if (duid != NULL) {
r = dhcp_validate_duid_len(duid_type, duid_len);
if (r < 0)
return r;
}
zero(client->client_id);
client->client_id.type = 255; client->client_id.type = 255;
/* If IAID is not configured, generate it. */ /* If IAID is not configured, generate it. */
@ -317,22 +356,18 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
} else } else
client->client_id.ns.iaid = htobe32(iaid); client->client_id.ns.iaid = htobe32(iaid);
/* If DUID is not configured, generate DUID-EN. */ if (duid != NULL) {
if (duid_len == 0) {
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
&duid_len);
if (r < 0)
return r;
} else {
r = dhcp_validate_duid_len(client->client_id.type, duid_len);
if (r < 0)
return r;
client->client_id.ns.duid.type = htobe16(duid_type); client->client_id.ns.duid.type = htobe16(duid_type);
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len); memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
duid_len += sizeof(client->client_id.ns.duid.type); len = sizeof(client->client_id.ns.duid.type) + duid_len;
} } else if (duid_type == DUID_TYPE_EN) {
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
if (r < 0)
return r;
} else
return -EOPNOTSUPP;
client->client_id_len = sizeof(client->client_id.type) + duid_len + client->client_id_len = sizeof(client->client_id.type) + len +
sizeof(client->client_id.ns.iaid); sizeof(client->client_id.ns.iaid);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
@ -344,8 +379,10 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
return 0; return 0;
} }
int sd_dhcp_client_set_hostname(sd_dhcp_client *client, int sd_dhcp_client_set_hostname(
const char *hostname) { sd_dhcp_client *client,
const char *hostname) {
char *new_hostname = NULL; char *new_hostname = NULL;
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
@ -368,8 +405,10 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
return 0; return 0;
} }
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, int sd_dhcp_client_set_vendor_class_identifier(
const char *vci) { sd_dhcp_client *client,
const char *vci) {
char *new_vci = NULL; char *new_vci = NULL;
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
@ -452,8 +491,13 @@ static void client_stop(sd_dhcp_client *client, int error) {
client_initialize(client); client_initialize(client);
} }
static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, static int client_message_init(
uint8_t type, size_t *_optlen, size_t *_optoffset) { sd_dhcp_client *client,
DHCPPacket **ret,
uint8_t type,
size_t *_optlen,
size_t *_optoffset) {
_cleanup_free_ DHCPPacket *packet = NULL; _cleanup_free_ DHCPPacket *packet = NULL;
size_t optlen, optoffset, size; size_t optlen, optoffset, size;
be16_t max_size; be16_t max_size;
@ -594,8 +638,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
return 0; return 0;
} }
static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset, static int client_append_fqdn_option(
const char *fqdn) { DHCPMessage *message,
size_t optlen,
size_t *optoffset,
const char *fqdn) {
uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
int r; int r;
@ -612,8 +660,11 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t
return r; return r;
} }
static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet, static int dhcp_client_send_raw(
size_t len) { sd_dhcp_client *client,
DHCPPacket *packet,
size_t len) {
dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT, dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
INADDR_BROADCAST, DHCP_PORT_SERVER, len); INADDR_BROADCAST, DHCP_PORT_SERVER, len);
@ -820,8 +871,11 @@ static int client_send_request(sd_dhcp_client *client) {
static int client_start(sd_dhcp_client *client); static int client_start(sd_dhcp_client *client);
static int client_timeout_resend(sd_event_source *s, uint64_t usec, static int client_timeout_resend(
void *userdata) { sd_event_source *s,
uint64_t usec,
void *userdata) {
sd_dhcp_client *client = userdata; sd_dhcp_client *client = userdata;
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
usec_t next_timeout = 0; usec_t next_timeout = 0;
@ -965,8 +1019,10 @@ error:
return 0; return 0;
} }
static int client_initialize_io_events(sd_dhcp_client *client, static int client_initialize_io_events(
sd_event_io_handler_t io_callback) { sd_dhcp_client *client,
sd_event_io_handler_t io_callback) {
int r; int r;
assert(client); assert(client);
@ -1033,8 +1089,7 @@ error:
} }
static int client_initialize_events(sd_dhcp_client *client, static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
sd_event_io_handler_t io_callback) {
client_initialize_io_events(client, io_callback); client_initialize_io_events(client, io_callback);
client_initialize_time_events(client); client_initialize_time_events(client);
@ -1074,8 +1129,7 @@ static int client_start(sd_dhcp_client *client) {
return client_start_delayed(client); return client_start_delayed(client);
} }
static int client_timeout_expire(sd_event_source *s, uint64_t usec, static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
void *userdata) {
sd_dhcp_client *client = userdata; sd_dhcp_client *client = userdata;
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
@ -1115,8 +1169,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
return client_initialize_events(client, client_receive_message_raw); return client_initialize_events(client, client_receive_message_raw);
} }
static int client_timeout_t1(sd_event_source *s, uint64_t usec, static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
void *userdata) {
sd_dhcp_client *client = userdata; sd_dhcp_client *client = userdata;
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
@ -1126,8 +1179,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
return client_initialize_time_events(client); return client_initialize_time_events(client);
} }
static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
size_t len) {
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
int r; int r;
@ -1178,8 +1230,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
return 0; return 0;
} }
static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
size_t len) {
int r; int r;
r = dhcp_option_parse(force, len, NULL, NULL, NULL); r = dhcp_option_parse(force, len, NULL, NULL, NULL);
@ -1191,8 +1242,7 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
return 0; return 0;
} }
static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) {
size_t len) {
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
_cleanup_free_ char *error_message = NULL; _cleanup_free_ char *error_message = NULL;
int r; int r;
@ -1420,8 +1470,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return 0; return 0;
} }
static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) {
int len) {
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
char time_string[FORMAT_TIMESPAN_MAX]; char time_string[FORMAT_TIMESPAN_MAX];
int r = 0, notify_event = 0; int r = 0, notify_event = 0;
@ -1567,8 +1616,12 @@ error:
return r; return r;
} }
static int client_receive_message_udp(sd_event_source *s, int fd, static int client_receive_message_udp(
uint32_t revents, void *userdata) { sd_event_source *s,
int fd,
uint32_t revents,
void *userdata) {
sd_dhcp_client *client = userdata; sd_dhcp_client *client = userdata;
_cleanup_free_ DHCPMessage *message = NULL; _cleanup_free_ DHCPMessage *message = NULL;
const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } }; const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
@ -1645,8 +1698,12 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
return client_handle_message(client, message, len); return client_handle_message(client, message, len);
} }
static int client_receive_message_raw(sd_event_source *s, int fd, static int client_receive_message_raw(
uint32_t revents, void *userdata) { sd_event_source *s,
int fd,
uint32_t revents,
void *userdata) {
sd_dhcp_client *client = userdata; sd_dhcp_client *client = userdata;
_cleanup_free_ DHCPPacket *packet = NULL; _cleanup_free_ DHCPPacket *packet = NULL;
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];

View File

@ -111,7 +111,10 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
static int client_start(sd_dhcp6_client *client, enum DHCP6State state); static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_callback_t cb, void *userdata) { int sd_dhcp6_client_set_callback(
sd_dhcp6_client *client,
sd_dhcp6_client_callback_t cb,
void *userdata) {
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
client->cb = cb; client->cb = cb;
@ -131,7 +134,10 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
return 0; return 0;
} }
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) { int sd_dhcp6_client_set_local_address(
sd_dhcp6_client *client,
const struct in6_addr *local_address) {
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(local_address, -EINVAL); assert_return(local_address, -EINVAL);
assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL); assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
@ -180,20 +186,38 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
} }
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type, /**
uint8_t *duid, size_t duid_len) { * Sets DUID. If duid is non-null, the DUID is set to duid_type + duid
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
int sd_dhcp6_client_set_duid(
sd_dhcp6_client *client,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
int r; int r;
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
if (duid_len > 0) { if (duid != NULL) {
r = dhcp_validate_duid_len(duid_type, duid_len); r = dhcp_validate_duid_len(duid_type, duid_len);
if (r < 0) if (r < 0)
return r; return r;
}
if (duid != NULL) {
client->duid.type = htobe16(duid_type); client->duid.type = htobe16(duid_type);
memcpy(&client->duid.raw.data, duid, duid_len); memcpy(&client->duid.raw.data, duid, duid_len);
client->duid_len = duid_len + sizeof(client->duid.type); client->duid_len = sizeof(client->duid.type) + duid_len;
} } else if (duid_type == DUID_TYPE_EN) {
r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
if (r < 0)
return r;
} else
return -EOPNOTSUPP;
return 0; return 0;
} }
@ -427,8 +451,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return 0; return 0;
} }
static int client_timeout_t2(sd_event_source *s, uint64_t usec, static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
void *userdata) {
sd_dhcp6_client *client = userdata; sd_dhcp6_client *client = userdata;
assert_return(s, -EINVAL); assert_return(s, -EINVAL);
@ -445,8 +468,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec,
return 0; return 0;
} }
static int client_timeout_t1(sd_event_source *s, uint64_t usec, static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
void *userdata) {
sd_dhcp6_client *client = userdata; sd_dhcp6_client *client = userdata;
assert_return(s, -EINVAL); assert_return(s, -EINVAL);
@ -463,8 +485,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
return 0; return 0;
} }
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) {
void *userdata) {
sd_dhcp6_client *client = userdata; sd_dhcp6_client *client = userdata;
DHCP6_CLIENT_DONT_DESTROY(client); DHCP6_CLIENT_DONT_DESTROY(client);
enum DHCP6State state; enum DHCP6State state;
@ -490,8 +511,7 @@ static usec_t client_timeout_compute_random(usec_t val) {
(random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC; (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
} }
static int client_timeout_resend(sd_event_source *s, uint64_t usec, static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) {
void *userdata) {
int r = 0; int r = 0;
sd_dhcp6_client *client = userdata; sd_dhcp6_client *client = userdata;
usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0; usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
@ -658,9 +678,11 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
return 0; return 0;
} }
static int client_parse_message(sd_dhcp6_client *client, static int client_parse_message(
DHCP6Message *message, size_t len, sd_dhcp6_client *client,
sd_dhcp6_lease *lease) { DHCP6Message *message,
size_t len,
sd_dhcp6_lease *lease) {
int r; int r;
uint8_t *optval, *option, *id = NULL; uint8_t *optval, *option, *id = NULL;
uint16_t optcode, status; uint16_t optcode, status;

View File

@ -22,7 +22,9 @@
typedef struct AddressPool AddressPool; typedef struct AddressPool AddressPool;
#include "in-addr-util.h" #include "in-addr-util.h"
#include "networkd.h" #include "list.h"
typedef struct Manager Manager;
struct AddressPool { struct AddressPool {
Manager *manager; Manager *manager;

View File

@ -28,10 +28,12 @@ typedef struct Address Address;
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd.h"
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
typedef struct Network Network;
typedef struct Link Link;
struct Address { struct Address {
Network *network; Network *network;
unsigned section; unsigned section;

View File

@ -37,11 +37,10 @@ int manager_parse_config_file(Manager *m) {
} }
static const char* const duid_type_table[_DUID_TYPE_MAX] = { static const char* const duid_type_table[_DUID_TYPE_MAX] = {
[DUID_TYPE_RAW] = "raw",
[DUID_TYPE_LLT] = "link-layer-time", [DUID_TYPE_LLT] = "link-layer-time",
[DUID_TYPE_EN] = "vendor", [DUID_TYPE_EN] = "vendor",
[DUID_TYPE_LL] = "link-layer", [DUID_TYPE_LL] = "link-layer",
[DUID_TYPE_UUID] = "uuid" [DUID_TYPE_UUID] = "uuid",
}; };
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType); DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type"); DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type");
@ -58,69 +57,29 @@ int config_parse_duid_rawdata(
void *data, void *data,
void *userdata) { void *userdata) {
int r; DUID *ret = data;
char *cbyte; uint8_t raw_data[MAX_DUID_LEN];
const char *pduid = rvalue; unsigned count = 0;
Manager *m = userdata;
Network *n = userdata;
DUIDType duidtype;
uint16_t dhcp_duid_type = 0;
uint8_t dhcp_duid[MAX_DUID_LEN];
size_t len, count = 0, duid_start_offset = 0, dhcp_duid_len = 0;
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(rvalue); assert(rvalue);
assert(userdata); assert(ret);
duidtype = (ltype == DUID_CONFIG_SOURCE_GLOBAL) ? m->duid_type : n->duid_type; /* RawData contains DUID in format "NN:NN:NN..." */
if (duidtype == _DUID_TYPE_INVALID)
duidtype = DUID_TYPE_RAW;
switch (duidtype) {
case DUID_TYPE_LLT:
/* RawData contains DUID-LLT link-layer address (offset 6) */
duid_start_offset = 6;
break;
case DUID_TYPE_EN:
/* RawData contains DUID-EN identifier (offset 4) */
duid_start_offset = 4;
break;
case DUID_TYPE_LL:
/* RawData contains DUID-LL link-layer address (offset 2) */
duid_start_offset = 2;
break;
case DUID_TYPE_UUID:
/* RawData specifies UUID (offset 0) - fall thru */
case DUID_TYPE_RAW:
/* First two bytes of RawData is DUID Type - fall thru */
default:
break;
}
if (duidtype != DUID_TYPE_RAW)
dhcp_duid_type = (uint16_t) duidtype;
/* RawData contains DUID in format " NN:NN:NN... " */
for (;;) { for (;;) {
int n1, n2; int n1, n2, len, r;
uint32_t byte; uint32_t byte;
char *cbyte;
r = extract_first_word(&pduid, &cbyte, ":", 0); r = extract_first_word(&rvalue, &cbyte, ":", 0);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue); log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue);
return 0; return 0;
} }
if (r == 0) if (r == 0)
break; break;
if (duid_start_offset + dhcp_duid_len >= MAX_DUID_LEN) { if (count >= MAX_DUID_LEN) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue); log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue);
return 0; return 0;
} }
@ -142,30 +101,11 @@ int config_parse_duid_rawdata(
} }
byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2; byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2;
raw_data[count++] = byte;
/* If DUID_TYPE_RAW, first two bytes hold DHCP DUID type code */
if (duidtype == DUID_TYPE_RAW && count < 2) {
dhcp_duid_type |= (byte << (8 * (1 - count)));
count++;
continue;
}
dhcp_duid[duid_start_offset + dhcp_duid_len] = byte;
dhcp_duid_len++;
}
if (ltype == DUID_CONFIG_SOURCE_GLOBAL) {
m->duid_type = duidtype;
m->dhcp_duid_type = dhcp_duid_type;
m->dhcp_duid_len = dhcp_duid_len;
memcpy(&m->dhcp_duid[duid_start_offset], dhcp_duid, dhcp_duid_len);
} else {
/* DUID_CONFIG_SOURCE_NETWORK */
n->duid_type = duidtype;
n->dhcp_duid_type = dhcp_duid_type;
n->dhcp_duid_len = dhcp_duid_len;
memcpy(&n->dhcp_duid[duid_start_offset], dhcp_duid, dhcp_duid_len);
} }
assert_cc(sizeof(raw_data) == sizeof(ret->raw_data));
memcpy(ret->raw_data, raw_data, count);
ret->raw_data_len = count;
return 0; return 0;
} }

View File

@ -21,14 +21,29 @@
#include "networkd.h" #include "networkd.h"
typedef enum DuidConfigSource {
DUID_CONFIG_SOURCE_GLOBAL = 0,
DUID_CONFIG_SOURCE_NETWORK,
} DuidConfigSource;
int manager_parse_config_file(Manager *m); int manager_parse_config_file(Manager *m);
const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length); const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length);
int config_parse_duid_type(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_duid_type(
int config_parse_duid_rawdata(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 *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_duid_rawdata(
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);

View File

@ -24,7 +24,7 @@
#include "dhcp-lease-internal.h" #include "dhcp-lease-internal.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "network-internal.h" #include "network-internal.h"
#include "networkd-link.h" #include "networkd.h"
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) { void *userdata) {
@ -628,28 +628,24 @@ int dhcp4_configure(Link *link) {
} }
switch (link->network->dhcp_client_identifier) { switch (link->network->dhcp_client_identifier) {
case DHCP_CLIENT_ID_DUID: case DHCP_CLIENT_ID_DUID: {
/* If configured, apply user specified DUID and/or IAID */ /* If configured, apply user specified DUID and/or IAID */
if (link->network->duid_type != _DUID_TYPE_INVALID) const DUID *duid = link_duid(link);
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->iaid, r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->dhcp_duid_type, link->network->iaid,
link->network->dhcp_duid, duid->type,
link->network->dhcp_duid_len); duid->raw_data_len > 0 ? duid->raw_data : NULL,
else duid->raw_data_len);
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->iaid,
link->manager->dhcp_duid_type,
link->manager->dhcp_duid,
link->manager->dhcp_duid_len);
if (r < 0) if (r < 0)
return r; return r;
break; break;
}
case DHCP_CLIENT_ID_MAC: case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client, r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER, ARPHRD_ETHER,
(const uint8_t *) &link->mac, (const uint8_t *) &link->mac,
sizeof (link->mac)); sizeof(link->mac));
if (r < 0) if (r < 0)
return r; return r;
break; break;

View File

@ -23,7 +23,7 @@
#include "sd-dhcp6-client.h" #include "sd-dhcp6-client.h"
#include "network-internal.h" #include "network-internal.h"
#include "networkd-link.h" #include "networkd.h"
static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
@ -206,6 +206,7 @@ int dhcp6_request_address(Link *link) {
int dhcp6_configure(Link *link) { int dhcp6_configure(Link *link) {
sd_dhcp6_client *client = NULL; sd_dhcp6_client *client = NULL;
int r; int r;
const DUID *duid;
assert(link); assert(link);
@ -234,16 +235,11 @@ int dhcp6_configure(Link *link) {
if (r < 0) if (r < 0)
goto error; goto error;
if (link->network->duid_type != _DUID_TYPE_INVALID) duid = link_duid(link);
r = sd_dhcp6_client_set_duid(client, r = sd_dhcp6_client_set_duid(client,
link->network->dhcp_duid_type, duid->type,
link->network->dhcp_duid, duid->raw_data_len > 0 ? duid->raw_data : NULL,
link->network->dhcp_duid_len); duid->raw_data_len);
else
r = sd_dhcp6_client_set_duid(client,
link->manager->dhcp_duid_type,
link->manager->dhcp_duid,
link->manager->dhcp_duid_len);
if (r < 0) if (r < 0)
goto error; goto error;

View File

@ -19,10 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
typedef struct FdbEntry FdbEntry; #include "list.h"
#include "macro.h"
#include "networkd-network.h" typedef struct Network Network;
#include "networkd.h" typedef struct FdbEntry FdbEntry;
typedef struct Link Link;
struct FdbEntry { struct FdbEntry {
Network *network; Network *network;

View File

@ -14,5 +14,5 @@ struct ConfigPerfItem;
%struct-type %struct-type
%includes %includes
%% %%
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid_type) DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_GLOBAL, offsetof(Manager, dhcp_duid) DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid)

View File

@ -21,7 +21,7 @@
#include <linux/if.h> #include <linux/if.h>
#include "network-internal.h" #include "network-internal.h"
#include "networkd-link.h" #include "networkd.h"
static int ipv4ll_address_lost(Link *link) { static int ipv4ll_address_lost(Link *link) {
_cleanup_address_free_ Address *address = NULL; _cleanup_address_free_ Address *address = NULL;

View File

@ -28,9 +28,8 @@
#include "fileio.h" #include "fileio.h"
#include "netlink-util.h" #include "netlink-util.h"
#include "network-internal.h" #include "network-internal.h"
#include "networkd-link.h" #include "networkd.h"
#include "networkd-lldp-tx.h" #include "networkd-lldp-tx.h"
#include "networkd-netdev.h"
#include "set.h" #include "set.h"
#include "socket-util.h" #include "socket-util.h"
#include "stdio-util.h" #include "stdio-util.h"
@ -2880,6 +2879,8 @@ int link_update(Link *link, sd_netlink_message *m) {
} }
if (link->dhcp_client) { if (link->dhcp_client) {
const DUID *duid = link_duid(link);
r = sd_dhcp_client_set_mac(link->dhcp_client, r = sd_dhcp_client_set_mac(link->dhcp_client,
(const uint8_t *) &link->mac, (const uint8_t *) &link->mac,
sizeof (link->mac), sizeof (link->mac),
@ -2887,23 +2888,18 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
if (link->network->duid_type != _DUID_TYPE_INVALID) r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, link->network->iaid,
link->network->iaid, duid->type,
link->network->dhcp_duid_type, duid->raw_data_len > 0 ? duid->raw_data : NULL,
link->network->dhcp_duid, duid->raw_data_len);
link->network->dhcp_duid_len);
else
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->iaid,
link->manager->dhcp_duid_type,
link->manager->dhcp_duid,
link->manager->dhcp_duid_len);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m"); return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
} }
if (link->dhcp6_client) { if (link->dhcp6_client) {
const DUID* duid = link_duid(link);
r = sd_dhcp6_client_set_mac(link->dhcp6_client, r = sd_dhcp6_client_set_mac(link->dhcp6_client,
(const uint8_t *) &link->mac, (const uint8_t *) &link->mac,
sizeof (link->mac), sizeof (link->mac),
@ -2916,16 +2912,10 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
if (link->network->duid_type != _DUID_TYPE_INVALID) r = sd_dhcp6_client_set_duid(link->dhcp6_client,
r = sd_dhcp6_client_set_duid(link->dhcp6_client, duid->type,
link->network->dhcp_duid_type, duid->raw_data_len > 0 ? duid->raw_data : NULL,
link->network->dhcp_duid, duid->raw_data_len);
link->network->dhcp_duid_len);
else
r = sd_dhcp6_client_set_duid(link->dhcp6_client,
link->manager->dhcp_duid_type,
link->manager->dhcp_duid,
link->manager->dhcp_duid_len);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m"); return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
} }

View File

@ -21,14 +21,17 @@
#include <endian.h> #include <endian.h>
#include "sd-bus.h"
#include "sd-dhcp-client.h" #include "sd-dhcp-client.h"
#include "sd-dhcp-server.h" #include "sd-dhcp-server.h"
#include "sd-dhcp6-client.h" #include "sd-dhcp6-client.h"
#include "sd-ipv4ll.h" #include "sd-ipv4ll.h"
#include "sd-lldp.h" #include "sd-lldp.h"
#include "sd-ndisc.h" #include "sd-ndisc.h"
#include "sd-netlink.h"
typedef struct Link Link; #include "list.h"
#include "set.h"
typedef enum LinkState { typedef enum LinkState {
LINK_STATE_PENDING, LINK_STATE_PENDING,
@ -54,11 +57,11 @@ typedef enum LinkOperationalState {
_LINK_OPERSTATE_INVALID = -1 _LINK_OPERSTATE_INVALID = -1
} LinkOperationalState; } LinkOperationalState;
#include "networkd-address.h" typedef struct Manager Manager;
#include "networkd-network.h" typedef struct Network Network;
#include "networkd.h" typedef struct Address Address;
struct Link { typedef struct Link {
Manager *manager; Manager *manager;
int n_ref; int n_ref;
@ -122,7 +125,7 @@ struct Link {
Hashmap *bound_by_links; Hashmap *bound_by_links;
Hashmap *bound_to_links; Hashmap *bound_to_links;
}; } Link;
Link *link_unref(Link *link); Link *link_unref(Link *link);
Link *link_ref(Link *link); Link *link_ref(Link *link);

View File

@ -21,15 +21,18 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include "alloc-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "networkd-lldp-tx.h"
#include "random-util.h" #include "random-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "string-util.h" #include "string-util.h"
#include "unaligned.h" #include "unaligned.h"
#include "networkd.h"
#include "networkd-lldp-tx.h"
#define LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } #define LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */ /* The LLDP spec calls this "txFastInit", see 9.2.5.19 */

View File

@ -1037,7 +1037,7 @@ int manager_new(Manager **ret) {
if (r < 0) if (r < 0)
return r; return r;
m->duid_type = _DUID_TYPE_INVALID; m->duid.type = DUID_TYPE_EN;
*ret = m; *ret = m;
m = NULL; m = NULL;

View File

@ -24,7 +24,7 @@
#include "sd-ndisc.h" #include "sd-ndisc.h"
#include "networkd-link.h" #include "networkd.h"
static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata; _cleanup_link_unref_ Link *link = userdata;

View File

@ -25,6 +25,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "conf-parser.h" #include "conf-parser.h"
#include "extract-word.h"
#include "missing.h" #include "missing.h"
#include "networkd-netdev-bond.h" #include "networkd-netdev-bond.h"
#include "string-table.h" #include "string-table.h"

View File

@ -20,8 +20,7 @@
***/ ***/
#include "in-addr-util.h" #include "in-addr-util.h"
#include "list.h"
typedef struct Bond Bond;
#include "networkd-netdev.h" #include "networkd-netdev.h"
@ -106,7 +105,7 @@ typedef struct ArpIpTarget {
LIST_FIELDS(struct ArpIpTarget, arp_ip_target); LIST_FIELDS(struct ArpIpTarget, arp_ip_target);
} ArpIpTarget; } ArpIpTarget;
struct Bond { typedef struct Bond {
NetDev meta; NetDev meta;
BondMode mode; BondMode mode;
@ -133,8 +132,9 @@ struct Bond {
int n_arp_ip_targets; int n_arp_ip_targets;
ArpIpTarget *arp_ip_targets; ArpIpTarget *arp_ip_targets;
}; } Bond;
DEFINE_NETDEV_CAST(BOND, Bond);
extern const NetDevVTable bond_vtable; extern const NetDevVTable bond_vtable;
const char *bond_mode_to_string(BondMode d) _const_; const char *bond_mode_to_string(BondMode d) _const_;

View File

@ -22,6 +22,7 @@
#include "missing.h" #include "missing.h"
#include "netlink-util.h" #include "netlink-util.h"
#include "networkd.h"
#include "networkd-netdev-bridge.h" #include "networkd-netdev-bridge.h"
/* callback for brige netdev's parameter set */ /* callback for brige netdev's parameter set */

View File

@ -19,11 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
typedef struct Bridge Bridge;
#include "networkd-netdev.h" #include "networkd-netdev.h"
struct Bridge { typedef struct Bridge {
NetDev meta; NetDev meta;
int mcast_querier; int mcast_querier;
@ -31,6 +29,7 @@ struct Bridge {
usec_t forward_delay; usec_t forward_delay;
usec_t hello_time; usec_t hello_time;
usec_t max_age; usec_t max_age;
}; } Bridge;
DEFINE_NETDEV_CAST(BRIDGE, Bridge);
extern const NetDevVTable bridge_vtable; extern const NetDevVTable bridge_vtable;

View File

@ -19,12 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
typedef struct Dummy Dummy;
#include "networkd-netdev.h" #include "networkd-netdev.h"
struct Dummy { typedef struct Dummy {
NetDev meta; NetDev meta;
}; } Dummy;
DEFINE_NETDEV_CAST(DUMMY, Dummy);
extern const NetDevVTable dummy_vtable; extern const NetDevVTable dummy_vtable;

View File

@ -1,11 +1,17 @@
%{ %{
#include <stddef.h> #include <stddef.h>
#include "conf-parser.h" #include "conf-parser.h"
#include "networkd-netdev.h"
#include "networkd-netdev-tunnel.h"
#include "networkd-netdev-bond.h"
#include "networkd-netdev-macvlan.h"
#include "network-internal.h" #include "network-internal.h"
#include "networkd-netdev-bond.h"
#include "networkd-netdev-ipvlan.h"
#include "networkd-netdev-macvlan.h"
#include "networkd-netdev-tunnel.h"
#include "networkd-netdev-tuntap.h"
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
#include "networkd-netdev-vxlan.h"
#include "networkd-netdev-bridge.h"
#include "networkd-netdev.h"
%} %}
struct ConfigPerfItem; struct ConfigPerfItem;
%null_strings %null_strings

View File

@ -19,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
typedef struct IPVlan IPVlan;
#include "missing.h" #include "missing.h"
#include "networkd-netdev.h" #include "networkd-netdev.h"
@ -31,12 +29,13 @@ typedef enum IPVlanMode {
_NETDEV_IPVLAN_MODE_INVALID = -1 _NETDEV_IPVLAN_MODE_INVALID = -1
} IPVlanMode; } IPVlanMode;
struct IPVlan { typedef struct IPVlan {
NetDev meta; NetDev meta;
IPVlanMode mode; IPVlanMode mode;
}; } IPVlan;
DEFINE_NETDEV_CAST(IPVLAN, IPVlan);
extern const NetDevVTable ipvlan_vtable; extern const NetDevVTable ipvlan_vtable;
const char *ipvlan_mode_to_string(IPVlanMode d) _const_; const char *ipvlan_mode_to_string(IPVlanMode d) _const_;

View File

@ -38,6 +38,8 @@ struct MacVlan {
MacVlanMode mode; MacVlanMode mode;
}; };
DEFINE_NETDEV_CAST(MACVLAN, MacVlan);
DEFINE_NETDEV_CAST(MACVTAP, MacVlan);
extern const NetDevVTable macvlan_vtable; extern const NetDevVTable macvlan_vtable;
extern const NetDevVTable macvtap_vtable; extern const NetDevVTable macvtap_vtable;

View File

@ -19,7 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
typedef struct Tunnel Tunnel; #include "in-addr-util.h"
#include "networkd-netdev.h" #include "networkd-netdev.h"
@ -37,7 +37,7 @@ typedef enum IPv6FlowLabel {
_NETDEV_IPV6_FLOWLABEL_INVALID = -1, _NETDEV_IPV6_FLOWLABEL_INVALID = -1,
} IPv6FlowLabel; } IPv6FlowLabel;
struct Tunnel { typedef struct Tunnel {
NetDev meta; NetDev meta;
uint8_t encap_limit; uint8_t encap_limit;
@ -56,8 +56,17 @@ struct Tunnel {
bool pmtudisc; bool pmtudisc;
bool copy_dscp; bool copy_dscp;
}; } Tunnel;
DEFINE_NETDEV_CAST(IPIP, Tunnel);
DEFINE_NETDEV_CAST(GRE, Tunnel);
DEFINE_NETDEV_CAST(GRETAP, Tunnel);
DEFINE_NETDEV_CAST(IP6GRE, Tunnel);
DEFINE_NETDEV_CAST(IP6GRETAP, Tunnel);
DEFINE_NETDEV_CAST(SIT, Tunnel);
DEFINE_NETDEV_CAST(VTI, Tunnel);
DEFINE_NETDEV_CAST(VTI6, Tunnel);
DEFINE_NETDEV_CAST(IP6TNL, Tunnel);
extern const NetDevVTable ipip_vtable; extern const NetDevVTable ipip_vtable;
extern const NetDevVTable sit_vtable; extern const NetDevVTable sit_vtable;
extern const NetDevVTable vti_vtable; extern const NetDevVTable vti_vtable;

View File

@ -17,10 +17,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#include <net/if.h> #include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <net/if.h>
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "fd-util.h" #include "fd-util.h"

View File

@ -34,5 +34,7 @@ struct TunTap {
bool vnet_hdr; bool vnet_hdr;
}; };
DEFINE_NETDEV_CAST(TUN, TunTap);
DEFINE_NETDEV_CAST(TAP, TunTap);
extern const NetDevVTable tun_vtable; extern const NetDevVTable tun_vtable;
extern const NetDevVTable tap_vtable; extern const NetDevVTable tap_vtable;

View File

@ -30,4 +30,5 @@ struct Veth {
struct ether_addr *mac_peer; struct ether_addr *mac_peer;
}; };
DEFINE_NETDEV_CAST(VETH, Veth);
extern const NetDevVTable veth_vtable; extern const NetDevVTable veth_vtable;

View File

@ -31,4 +31,5 @@ struct VLan {
uint64_t id; uint64_t id;
}; };
DEFINE_NETDEV_CAST(VLAN, VLan);
extern const NetDevVTable vlan_vtable; extern const NetDevVTable vlan_vtable;

View File

@ -23,8 +23,10 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "extract-word.h"
#include "parse-util.h" #include "parse-util.h"
#include "missing.h" #include "missing.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-netdev-vxlan.h" #include "networkd-netdev-vxlan.h"

View File

@ -55,6 +55,7 @@ struct VxLan {
struct ifla_vxlan_port_range port_range; struct ifla_vxlan_port_range port_range;
}; };
DEFINE_NETDEV_CAST(VXLAN, VxLan);
extern const NetDevVTable vxlan_vtable; extern const NetDevVTable vxlan_vtable;
int config_parse_vxlan_group_address(const char *unit, int config_parse_vxlan_group_address(const char *unit,

View File

@ -19,15 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#include "sd-netlink.h"
#include "list.h" #include "list.h"
#include "time-util.h"
typedef struct NetDev NetDev;
typedef struct NetDevVTable NetDevVTable;
#include "networkd-link.h"
#include "networkd.h"
typedef struct netdev_join_callback netdev_join_callback; typedef struct netdev_join_callback netdev_join_callback;
typedef struct Link Link;
struct netdev_join_callback { struct netdev_join_callback {
sd_netlink_message_handler_t callback; sd_netlink_message_handler_t callback;
@ -78,7 +76,10 @@ typedef enum NetDevCreateType {
_NETDEV_CREATE_INVALID = -1, _NETDEV_CREATE_INVALID = -1,
} NetDevCreateType; } NetDevCreateType;
struct NetDev { typedef struct Manager Manager;
typedef struct Condition Condition;
typedef struct NetDev {
Manager *manager; Manager *manager;
int n_ref; int n_ref;
@ -99,20 +100,9 @@ struct NetDev {
int ifindex; int ifindex;
LIST_HEAD(netdev_join_callback, callbacks); LIST_HEAD(netdev_join_callback, callbacks);
}; } NetDev;
#include "networkd-netdev-bond.h" typedef struct NetDevVTable {
#include "networkd-netdev-bridge.h"
#include "networkd-netdev-dummy.h"
#include "networkd-netdev-ipvlan.h"
#include "networkd-netdev-macvlan.h"
#include "networkd-netdev-tunnel.h"
#include "networkd-netdev-tuntap.h"
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
#include "networkd-netdev-vxlan.h"
struct NetDevVTable {
/* How much memory does an object of this unit type need */ /* How much memory does an object of this unit type need */
size_t object_size; size_t object_size;
@ -144,14 +134,14 @@ struct NetDevVTable {
/* verify that compulsory configuration options were specified */ /* verify that compulsory configuration options were specified */
int (*config_verify)(NetDev *netdev, const char *filename); int (*config_verify)(NetDev *netdev, const char *filename);
}; } NetDevVTable;
extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
#define NETDEV_VTABLE(n) netdev_vtable[(n)->kind] #define NETDEV_VTABLE(n) netdev_vtable[(n)->kind]
/* For casting a netdev into the various netdev kinds */ /* For casting a netdev into the various netdev kinds */
#define DEFINE_CAST(UPPERCASE, MixedCase) \ #define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \
static inline MixedCase* UPPERCASE(NetDev *n) { \ static inline MixedCase* UPPERCASE(NetDev *n) { \
if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \ if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \
return NULL; \ return NULL; \
@ -162,27 +152,6 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
/* For casting the various netdev kinds into a netdev */ /* For casting the various netdev kinds into a netdev */
#define NETDEV(n) (&(n)->meta) #define NETDEV(n) (&(n)->meta)
DEFINE_CAST(BRIDGE, Bridge);
DEFINE_CAST(BOND, Bond);
DEFINE_CAST(VLAN, VLan);
DEFINE_CAST(MACVLAN, MacVlan);
DEFINE_CAST(MACVTAP, MacVlan);
DEFINE_CAST(IPVLAN, IPVlan);
DEFINE_CAST(VXLAN, VxLan);
DEFINE_CAST(IPIP, Tunnel);
DEFINE_CAST(GRE, Tunnel);
DEFINE_CAST(GRETAP, Tunnel);
DEFINE_CAST(IP6GRE, Tunnel);
DEFINE_CAST(IP6GRETAP, Tunnel);
DEFINE_CAST(SIT, Tunnel);
DEFINE_CAST(VTI, Tunnel);
DEFINE_CAST(VTI6, Tunnel);
DEFINE_CAST(IP6TNL, Tunnel);
DEFINE_CAST(VETH, Veth);
DEFINE_CAST(DUMMY, Dummy);
DEFINE_CAST(TUN, TunTap);
DEFINE_CAST(TAP, TunTap);
int netdev_load(Manager *manager); int netdev_load(Manager *manager);
void netdev_drop(NetDev *netdev); void netdev_drop(NetDev *netdev);

View File

@ -85,8 +85,8 @@ DHCP.Hostname, config_parse_hostname,
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid_type) DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_NETWORK, offsetof(Network, dhcp_duid) DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)

View File

@ -131,7 +131,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->ipv6_accept_ra = -1; network->ipv6_accept_ra = -1;
network->ipv6_dad_transmits = -1; network->ipv6_dad_transmits = -1;
network->ipv6_hop_limit = -1; network->ipv6_hop_limit = -1;
network->duid_type = _DUID_TYPE_INVALID; network->duid.type = _DUID_TYPE_INVALID;
network->proxy_arp = -1; network->proxy_arp = -1;
r = config_parse(NULL, filename, file, r = config_parse(NULL, filename, file,

View File

@ -19,18 +19,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>. along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#include "sd-bus.h"
#include "udev.h"
#include "condition.h" #include "condition.h"
#include "dhcp-identifier.h"
#include "hashmap.h"
#include "resolve-util.h" #include "resolve-util.h"
typedef struct Network Network;
#include "dhcp-identifier.h"
#include "networkd-address.h" #include "networkd-address.h"
#include "networkd-fdb.h" #include "networkd-fdb.h"
#include "networkd-netdev.h" #include "networkd-netdev.h"
#include "networkd-route.h" #include "networkd-route.h"
#include "networkd-util.h" #include "networkd-util.h"
#include "networkd.h"
#define DHCP_ROUTE_METRIC 1024 #define DHCP_ROUTE_METRIC 1024
#define IPV4LL_ROUTE_METRIC 2048 #define IPV4LL_ROUTE_METRIC 2048
@ -67,6 +68,16 @@ typedef enum LLDPMode {
_LLDP_MODE_INVALID = -1, _LLDP_MODE_INVALID = -1,
} LLDPMode; } LLDPMode;
typedef struct DUID {
/* Value of Type in [DHCP] section */
DUIDType type;
uint8_t raw_data_len;
uint8_t raw_data[MAX_DUID_LEN];
} DUID;
typedef struct Manager Manager;
struct Network { struct Network {
Manager *manager; Manager *manager;
@ -147,12 +158,7 @@ struct Network {
struct ether_addr *mac; struct ether_addr *mac;
unsigned mtu; unsigned mtu;
uint32_t iaid; uint32_t iaid;
/* Value of Type in [DUID] section */ DUID duid;
DUIDType duid_type;
/* DUID type code - RFC 3315 */
uint16_t dhcp_duid_type;
size_t dhcp_duid_len;
uint8_t dhcp_duid[MAX_DUID_LEN];
LLDPMode lldp_mode; /* LLDP reception */ LLDPMode lldp_mode; /* LLDP reception */
bool lldp_emit; /* LLDP transmission */ bool lldp_emit; /* LLDP transmission */

View File

@ -22,7 +22,6 @@
typedef struct Route Route; typedef struct Route Route;
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd.h"
struct Route { struct Route {
Network *network; Network *network;

View File

@ -24,19 +24,30 @@
#include "sd-bus.h" #include "sd-bus.h"
#include "sd-event.h" #include "sd-event.h"
#include "sd-netlink.h" #include "sd-netlink.h"
#include "hashmap.h"
#include "list.h"
#include "udev.h" #include "udev.h"
typedef struct Manager Manager;
#include "dhcp-identifier.h" #include "dhcp-identifier.h"
#include "hashmap.h"
#include "list.h"
#include "networkd-address-pool.h" #include "networkd-address-pool.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-netdev-bond.h"
#include "networkd-netdev-bridge.h"
#include "networkd-netdev-dummy.h"
#include "networkd-netdev-ipvlan.h"
#include "networkd-netdev-macvlan.h"
#include "networkd-netdev-tunnel.h"
#include "networkd-netdev-tuntap.h"
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
#include "networkd-netdev-vlan.h"
#include "networkd-netdev-vxlan.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-util.h" #include "networkd-util.h"
extern const char* const network_dirs[];
struct Manager { struct Manager {
sd_netlink *rtnl; sd_netlink *rtnl;
sd_event *event; sd_event *event;
@ -63,17 +74,15 @@ struct Manager {
usec_t network_dirs_ts_usec; usec_t network_dirs_ts_usec;
/* Value of Type in [DUID] section */ DUID duid;
DUIDType duid_type;
/* DUID type code - RFC 3315 */
uint16_t dhcp_duid_type;
size_t dhcp_duid_len;
uint8_t dhcp_duid[MAX_DUID_LEN];
}; };
extern const char* const network_dirs[]; static inline const DUID* link_duid(const Link *link) {
if (link->network->duid.type != _DUID_TYPE_INVALID)
/* Manager */ return &link->network->duid;
else
return &link->manager->duid;
}
extern const sd_bus_vtable manager_vtable[]; extern const sd_bus_vtable manager_vtable[];

View File

@ -0,0 +1,89 @@
/***
This file is part of systemd.
Copyright 2016 Zbigniew Jędrzejewski-Szmek
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 "hexdecoct.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "networkd-conf.h"
#include "networkd-network.h"
static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected) {
DUIDType actual = 0;
int r;
r = config_parse_duid_type("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL);
log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual);
assert_se(r == ret);
assert_se(expected == actual);
}
static void test_config_parse_duid_type(void) {
test_config_parse_duid_type_one("", 0, 0);
test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT);
test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN);
test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL);
test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID);
test_config_parse_duid_type_one("foo", 0, 0);
}
static void test_config_parse_duid_rawdata_one(const char *rvalue, int ret, const DUID* expected) {
DUID actual = {};
int r;
r = config_parse_duid_rawdata("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL);
log_info_errno(r, "\"%s\"\"%s\" (%m)",
rvalue, strnull(hexmem(actual.raw_data, actual.raw_data_len)));
assert_se(r == ret);
if (expected) {
assert_se(actual.raw_data_len == expected->raw_data_len);
assert_se(memcmp(actual.raw_data, expected->raw_data, expected->raw_data_len) == 0);
}
}
#define BYTES_0_128 "0:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e:7f:80"
#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80}
static void test_config_parse_duid_rawdata(void) {
test_config_parse_duid_rawdata_one("", 0, &(DUID){});
test_config_parse_duid_rawdata_one("00:11:22:33:44:55:66:77", 0,
&(DUID){0, 8, {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}});
test_config_parse_duid_rawdata_one("00:11:22:", 0,
&(DUID){0, 3, {0x00,0x11,0x22}});
test_config_parse_duid_rawdata_one("000:11:22", 0, &(DUID){}); /* error, output is all zeros */
test_config_parse_duid_rawdata_one("00:111:22", 0, &(DUID){});
test_config_parse_duid_rawdata_one("0:1:2:3:4:5:6:7", 0,
&(DUID){0, 8, {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}});
test_config_parse_duid_rawdata_one("11::", 0, &(DUID){0, 1, {0x11}}); /* FIXME: should this be an error? */
test_config_parse_duid_rawdata_one("abcdef", 0, &(DUID){});
test_config_parse_duid_rawdata_one(BYTES_0_128, 0, &(DUID){});
test_config_parse_duid_rawdata_one(BYTES_0_128 + 2, 0, &(DUID){0, 128, BYTES_1_128});
}
int main(int argc, char **argv) {
log_parse_environment();
log_open();
test_config_parse_duid_type();
test_config_parse_duid_rawdata();
return 0;
}

View File

@ -84,28 +84,57 @@ enum {
typedef struct sd_dhcp_client sd_dhcp_client; typedef struct sd_dhcp_client sd_dhcp_client;
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
void *userdata); int sd_dhcp_client_set_callback(
int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb, sd_dhcp_client *client,
void *userdata); sd_dhcp_client_callback_t cb,
void *userdata);
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option); int sd_dhcp_client_set_request_option(
int sd_dhcp_client_set_request_address(sd_dhcp_client *client, sd_dhcp_client *client,
const struct in_addr *last_address); uint8_t option);
int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast); int sd_dhcp_client_set_request_address(
int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index); sd_dhcp_client *client,
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, const struct in_addr *last_address);
size_t addr_len, uint16_t arp_type); int sd_dhcp_client_set_request_broadcast(
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, sd_dhcp_client *client,
const uint8_t *data, size_t data_len); int broadcast);
int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid, int sd_dhcp_client_set_index(
uint16_t duid_type, uint8_t *duid, size_t duid_len); sd_dhcp_client *client,
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, int interface_index);
const uint8_t **data, size_t *data_len); int sd_dhcp_client_set_mac(
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu); sd_dhcp_client *client,
int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname); const uint8_t *addr,
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci); size_t addr_len,
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret); uint16_t arp_type);
int sd_dhcp_client_set_client_id(
sd_dhcp_client *client,
uint8_t type,
const uint8_t *data,
size_t data_len);
int sd_dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
uint32_t iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len);
int sd_dhcp_client_get_client_id(
sd_dhcp_client *client,
uint8_t *type,
const uint8_t **data,
size_t *data_len);
int sd_dhcp_client_set_mtu(
sd_dhcp_client *client,
uint32_t mtu);
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname);
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci);
int sd_dhcp_client_get_lease(
sd_dhcp_client *client,
sd_dhcp_lease **ret);
int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_stop(sd_dhcp_client *client);
int sd_dhcp_client_start(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client);
@ -115,7 +144,10 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
int sd_dhcp_client_new(sd_dhcp_client **ret); int sd_dhcp_client_new(sd_dhcp_client **ret);
int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority); int sd_dhcp_client_attach_event(
sd_dhcp_client *client,
sd_event *event,
int64_t priority);
int sd_dhcp_client_detach_event(sd_dhcp_client *client); int sd_dhcp_client_detach_event(sd_dhcp_client *client);
sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client); sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);

View File

@ -76,29 +76,52 @@ enum {
typedef struct sd_dhcp6_client sd_dhcp6_client; typedef struct sd_dhcp6_client sd_dhcp6_client;
typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata);
void *userdata); int sd_dhcp6_client_set_callback(
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client *client,
sd_dhcp6_client_callback_t cb, void *userdata); sd_dhcp6_client_callback_t cb,
void *userdata);
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index); int sd_dhcp6_client_set_index(
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address); sd_dhcp6_client *client,
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr, int interface_index);
size_t addr_len, uint16_t arp_type); int sd_dhcp6_client_set_local_address(
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type, sd_dhcp6_client *client,
uint8_t *duid, size_t duid_len); const struct in6_addr *local_address);
int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid); int sd_dhcp6_client_set_mac(
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled); sd_dhcp6_client *client,
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled); const uint8_t *addr,
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, size_t addr_len,
uint16_t option); uint16_t arp_type);
int sd_dhcp6_client_set_duid(
sd_dhcp6_client *client,
uint16_t duid_type,
const void *duid,
size_t duid_len);
int sd_dhcp6_client_set_iaid(
sd_dhcp6_client *client,
uint32_t iaid);
int sd_dhcp6_client_set_information_request(
sd_dhcp6_client *client,
int enabled);
int sd_dhcp6_client_get_information_request(
sd_dhcp6_client *client,
int *enabled);
int sd_dhcp6_client_set_request_option(
sd_dhcp6_client *client,
uint16_t option);
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret); int sd_dhcp6_client_get_lease(
sd_dhcp6_client *client,
sd_dhcp6_lease **ret);
int sd_dhcp6_client_stop(sd_dhcp6_client *client); int sd_dhcp6_client_stop(sd_dhcp6_client *client);
int sd_dhcp6_client_start(sd_dhcp6_client *client); int sd_dhcp6_client_start(sd_dhcp6_client *client);
int sd_dhcp6_client_is_running(sd_dhcp6_client *client); int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority); int sd_dhcp6_client_attach_event(
sd_dhcp6_client *client,
sd_event *event,
int64_t priority);
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client); int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client); sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client); sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);