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-netlink
/test-netlink-manual
/test-netword-conf
/test-network
/test-network-tables
/test-ns

View File

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

View File

@ -58,14 +58,14 @@
<title>Description</title>
<para>These configuration files control global network parameters.
For e.g. DHCP Unique Identifier (DUID).</para>
Currently the DHCP Unique Identifier (DUID).</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
<refsect1>
<title>[DUID] Section Options</title>
<title>[DHCP] Section Options</title>
<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
@ -73,28 +73,71 @@
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 DHCP server to uniquely identify the machine and the interface requesting a DHCP IP.
To configure IAID and ClientIdentifier, see <citerefentry><refentrytitle>systemd.network
</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
To configure IAID and ClientIdentifier, see
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</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>.</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>
<para>The following options are understood:</para>
<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>
<term><varname>RawData=</varname></term>
<listitem><para>Specifies the DUID bytes as a single newline-terminated, hexadecimal
string, with each byte separated by a ':'.</para></listitem>
<term><varname>DUIDRawData=</varname></term>
<listitem><para>Specifies the DHCP DUID value as a single newline-terminated, hexadecimal string, with each
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>
</variablelist>
</refsect1>

View File

@ -832,6 +832,7 @@
false.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ClientIdentifier=</varname></term>
<listitem>
@ -839,6 +840,7 @@
or <literal>duid</literal> (the default, see below) to use a RFC4361-compliant Client ID.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>VendorClassIdentifier=</varname></term>
<listitem>
@ -846,25 +848,25 @@
type and configuration.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>DUIDRawData=</varname></term>
<listitem><para>Specifies the DHCP DUID bytes as a single newline-terminated, hexadecimal string, with each
byte separated by a ':'. A DHCPv6 client sends the DHCP Unique Identifier (DUID) and the interface Identity
Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6 address. Similar, DHCPv4 clients
send the IAID and DUID to the DHCP server when acquiring 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 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>
<term><varname>DUIDType=</varname></term>
<listitem>
<para>Override the global <varname>DUIDType</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>
<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>
<term><varname>RequestBroadcast=</varname></term>
<listitem>
@ -876,6 +878,7 @@
networks where broadcasts are filtered out.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>

View File

@ -31,6 +31,37 @@
#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)
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) {
sd_id128_t machine_id;
uint64_t hash;

View File

@ -26,7 +26,6 @@
#include "unaligned.h"
typedef enum DUIDType {
DUID_TYPE_RAW = 0,
DUID_TYPE_LLT = 1,
DUID_TYPE_EN = 2,
DUID_TYPE_LL = 3,
@ -40,27 +39,28 @@ typedef enum DUIDType {
*/
#define MAX_DUID_LEN 128
/* https://tools.ietf.org/html/rfc3315#section-9.1 */
struct duid {
be16_t type;
union {
struct {
/* DHCP6_DUID_LLT */
/* DUID_TYPE_LLT */
uint16_t htype;
uint32_t time;
uint8_t haddr[0];
} _packed_ llt;
struct {
/* DHCP6_DUID_EN */
/* DUID_TYPE_EN */
uint32_t pen;
uint8_t id[8];
} _packed_ en;
struct {
/* DHCP6_DUID_LL */
/* DUID_TYPE_LL */
int16_t htype;
uint8_t haddr[0];
} _packed_ ll;
struct {
/* DHCP6_DUID_UUID */
/* DUID_TYPE_UUID */
sd_id128_t uuid;
} _packed_ uuid;
struct {
@ -69,36 +69,6 @@ struct duid {
};
} _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_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,
};
static int client_receive_message_raw(sd_event_source *s, int fd,
uint32_t revents, void *userdata);
static int client_receive_message_udp(sd_event_source *s, int fd,
uint32_t revents, void *userdata);
static int client_receive_message_raw(
sd_event_source *s,
int fd,
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);
int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
void *userdata) {
int sd_dhcp_client_set_callback(
sd_dhcp_client *client,
sd_dhcp_client_callback_t cb,
void *userdata) {
assert_return(client, -EINVAL);
client->cb = cb;
@ -171,8 +179,9 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
return 0;
}
int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
const struct in_addr *last_addr) {
int sd_dhcp_client_set_request_address(
sd_dhcp_client *client,
const struct in_addr *last_addr) {
assert_return(client, -EINVAL);
assert_return (IN_SET(client->state, DHCP_STATE_INIT,
DHCP_STATE_STOPPED), -EBUSY);
@ -196,8 +205,12 @@ int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
return 0;
}
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type) {
int sd_dhcp_client_set_mac(
sd_dhcp_client *client,
const uint8_t *addr,
size_t addr_len,
uint16_t arp_type) {
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
@ -234,8 +247,11 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
return 0;
}
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_get_client_id(
sd_dhcp_client *client,
uint8_t *type,
const uint8_t **data,
size_t *data_len) {
assert_return(client, -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;
}
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_client_id(
sd_dhcp_client *client,
uint8_t type,
const uint8_t *data,
size_t data_len) {
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
@ -298,13 +318,32 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
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);
int r;
assert_return(client, -EINVAL);
zero(client->client_id);
size_t len;
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;
/* 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
client->client_id.ns.iaid = htobe32(iaid);
/* If DUID is not configured, generate DUID-EN. */
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;
if (duid != NULL) {
client->client_id.ns.duid.type = htobe16(duid_type);
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);
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;
}
int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
const char *hostname) {
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname) {
char *new_hostname = NULL;
assert_return(client, -EINVAL);
@ -368,8 +405,10 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
return 0;
}
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
const char *vci) {
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci) {
char *new_vci = NULL;
assert_return(client, -EINVAL);
@ -452,8 +491,13 @@ static void client_stop(sd_dhcp_client *client, int error) {
client_initialize(client);
}
static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
uint8_t type, size_t *_optlen, size_t *_optoffset) {
static int client_message_init(
sd_dhcp_client *client,
DHCPPacket **ret,
uint8_t type,
size_t *_optlen,
size_t *_optoffset) {
_cleanup_free_ DHCPPacket *packet = NULL;
size_t optlen, optoffset, size;
be16_t max_size;
@ -594,8 +638,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
return 0;
}
static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
const char *fqdn) {
static int client_append_fqdn_option(
DHCPMessage *message,
size_t optlen,
size_t *optoffset,
const char *fqdn) {
uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
int r;
@ -612,8 +660,11 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t
return r;
}
static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
size_t len) {
static int dhcp_client_send_raw(
sd_dhcp_client *client,
DHCPPacket *packet,
size_t len) {
dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
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_timeout_resend(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_resend(
sd_event_source *s,
uint64_t usec,
void *userdata) {
sd_dhcp_client *client = userdata;
DHCP_CLIENT_DONT_DESTROY(client);
usec_t next_timeout = 0;
@ -965,8 +1019,10 @@ error:
return 0;
}
static int client_initialize_io_events(sd_dhcp_client *client,
sd_event_io_handler_t io_callback) {
static int client_initialize_io_events(
sd_dhcp_client *client,
sd_event_io_handler_t io_callback) {
int r;
assert(client);
@ -1033,8 +1089,7 @@ error:
}
static int client_initialize_events(sd_dhcp_client *client,
sd_event_io_handler_t io_callback) {
static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
client_initialize_io_events(client, io_callback);
client_initialize_time_events(client);
@ -1074,8 +1129,7 @@ static int client_start(sd_dhcp_client *client) {
return client_start_delayed(client);
}
static int client_timeout_expire(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp_client *client = userdata;
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);
}
static int client_timeout_t1(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp_client *client = userdata;
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);
}
static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
size_t len) {
static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
int r;
@ -1178,8 +1230,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
return 0;
}
static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
size_t len) {
static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
int r;
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;
}
static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
size_t len) {
static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) {
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
_cleanup_free_ char *error_message = NULL;
int r;
@ -1420,8 +1470,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return 0;
}
static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
int len) {
static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) {
DHCP_CLIENT_DONT_DESTROY(client);
char time_string[FORMAT_TIMESPAN_MAX];
int r = 0, notify_event = 0;
@ -1567,8 +1616,12 @@ error:
return r;
}
static int client_receive_message_udp(sd_event_source *s, int fd,
uint32_t revents, void *userdata) {
static int client_receive_message_udp(
sd_event_source *s,
int fd,
uint32_t revents,
void *userdata) {
sd_dhcp_client *client = userdata;
_cleanup_free_ DHCPMessage *message = NULL;
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);
}
static int client_receive_message_raw(sd_event_source *s, int fd,
uint32_t revents, void *userdata) {
static int client_receive_message_raw(
sd_event_source *s,
int fd,
uint32_t revents,
void *userdata) {
sd_dhcp_client *client = userdata;
_cleanup_free_ DHCPPacket *packet = NULL;
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);
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);
client->cb = cb;
@ -131,7 +134,10 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
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(local_address, -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);
}
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;
assert_return(client, -EINVAL);
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
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);
if (r < 0)
return r;
}
if (duid != NULL) {
client->duid.type = htobe16(duid_type);
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;
}
@ -427,8 +451,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return 0;
}
static int client_timeout_t2(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp6_client *client = userdata;
assert_return(s, -EINVAL);
@ -445,8 +468,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec,
return 0;
}
static int client_timeout_t1(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp6_client *client = userdata;
assert_return(s, -EINVAL);
@ -463,8 +485,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
return 0;
}
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp6_client *client = userdata;
DHCP6_CLIENT_DONT_DESTROY(client);
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;
}
static int client_timeout_resend(sd_event_source *s, uint64_t usec,
void *userdata) {
static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) {
int r = 0;
sd_dhcp6_client *client = userdata;
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;
}
static int client_parse_message(sd_dhcp6_client *client,
DHCP6Message *message, size_t len,
sd_dhcp6_lease *lease) {
static int client_parse_message(
sd_dhcp6_client *client,
DHCP6Message *message,
size_t len,
sd_dhcp6_lease *lease) {
int r;
uint8_t *optval, *option, *id = NULL;
uint16_t optcode, status;

View File

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

View File

@ -28,10 +28,12 @@ typedef struct Address Address;
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd.h"
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
typedef struct Network Network;
typedef struct Link Link;
struct Address {
Network *network;
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] = {
[DUID_TYPE_RAW] = "raw",
[DUID_TYPE_LLT] = "link-layer-time",
[DUID_TYPE_EN] = "vendor",
[DUID_TYPE_LL] = "link-layer",
[DUID_TYPE_UUID] = "uuid"
[DUID_TYPE_UUID] = "uuid",
};
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");
@ -58,69 +57,29 @@ int config_parse_duid_rawdata(
void *data,
void *userdata) {
int r;
char *cbyte;
const char *pduid = rvalue;
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;
DUID *ret = data;
uint8_t raw_data[MAX_DUID_LEN];
unsigned count = 0;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(userdata);
assert(ret);
duidtype = (ltype == DUID_CONFIG_SOURCE_GLOBAL) ? m->duid_type : n->duid_type;
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... " */
/* RawData contains DUID in format "NN:NN:NN..." */
for (;;) {
int n1, n2;
int n1, n2, len, r;
uint32_t byte;
char *cbyte;
r = extract_first_word(&pduid, &cbyte, ":", 0);
r = extract_first_word(&rvalue, &cbyte, ":", 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue);
return 0;
}
if (r == 0)
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);
return 0;
}
@ -142,30 +101,11 @@ int config_parse_duid_rawdata(
}
byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2;
/* 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);
raw_data[count++] = byte;
}
assert_cc(sizeof(raw_data) == sizeof(ret->raw_data));
memcpy(ret->raw_data, raw_data, count);
ret->raw_data_len = count;
return 0;
}

View File

@ -21,14 +21,29 @@
#include "networkd.h"
typedef enum DuidConfigSource {
DUID_CONFIG_SOURCE_GLOBAL = 0,
DUID_CONFIG_SOURCE_NETWORK,
} DuidConfigSource;
int manager_parse_config_file(Manager *m);
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_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);
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_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 "hostname-util.h"
#include "network-internal.h"
#include "networkd-link.h"
#include "networkd.h"
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
@ -628,28 +628,24 @@ int dhcp4_configure(Link *link) {
}
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 (link->network->duid_type != _DUID_TYPE_INVALID)
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->iaid,
link->network->dhcp_duid_type,
link->network->dhcp_duid,
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);
const DUID *duid = link_duid(link);
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->iaid,
duid->type,
duid->raw_data_len > 0 ? duid->raw_data : NULL,
duid->raw_data_len);
if (r < 0)
return r;
break;
}
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
(const uint8_t *) &link->mac,
sizeof (link->mac));
sizeof(link->mac));
if (r < 0)
return r;
break;

View File

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

View File

@ -19,10 +19,12 @@
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"
#include "networkd.h"
typedef struct Network Network;
typedef struct FdbEntry FdbEntry;
typedef struct Link Link;
struct FdbEntry {
Network *network;

View File

@ -14,5 +14,5 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
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.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid)

View File

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

View File

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

View File

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

View File

@ -21,15 +21,18 @@
#include <inttypes.h>
#include <string.h>
#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "hostname-util.h"
#include "networkd-lldp-tx.h"
#include "random-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "unaligned.h"
#include "networkd.h"
#include "networkd-lldp-tx.h"
#define LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
/* 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)
return r;
m->duid_type = _DUID_TYPE_INVALID;
m->duid.type = DUID_TYPE_EN;
*ret = m;
m = NULL;

View File

@ -24,7 +24,7 @@
#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) {
_cleanup_link_unref_ Link *link = userdata;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,17 @@
%{
#include <stddef.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 "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;
%null_strings

View File

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

View File

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

View File

@ -19,7 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
typedef struct Tunnel Tunnel;
#include "in-addr-util.h"
#include "networkd-netdev.h"
@ -37,7 +37,7 @@ typedef enum IPv6FlowLabel {
_NETDEV_IPV6_FLOWLABEL_INVALID = -1,
} IPv6FlowLabel;
struct Tunnel {
typedef struct Tunnel {
NetDev meta;
uint8_t encap_limit;
@ -56,8 +56,17 @@ struct Tunnel {
bool pmtudisc;
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 sit_vtable;
extern const NetDevVTable vti_vtable;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -55,6 +55,7 @@ struct VxLan {
struct ifla_vxlan_port_range port_range;
};
DEFINE_NETDEV_CAST(VXLAN, VxLan);
extern const NetDevVTable vxlan_vtable;
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/>.
***/
#include "sd-netlink.h"
#include "list.h"
typedef struct NetDev NetDev;
typedef struct NetDevVTable NetDevVTable;
#include "networkd-link.h"
#include "networkd.h"
#include "time-util.h"
typedef struct netdev_join_callback netdev_join_callback;
typedef struct Link Link;
struct netdev_join_callback {
sd_netlink_message_handler_t callback;
@ -78,7 +76,10 @@ typedef enum NetDevCreateType {
_NETDEV_CREATE_INVALID = -1,
} NetDevCreateType;
struct NetDev {
typedef struct Manager Manager;
typedef struct Condition Condition;
typedef struct NetDev {
Manager *manager;
int n_ref;
@ -99,20 +100,9 @@ struct NetDev {
int ifindex;
LIST_HEAD(netdev_join_callback, callbacks);
};
} NetDev;
#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-vxlan.h"
struct NetDevVTable {
typedef struct NetDevVTable {
/* How much memory does an object of this unit type need */
size_t object_size;
@ -144,14 +134,14 @@ struct NetDevVTable {
/* verify that compulsory configuration options were specified */
int (*config_verify)(NetDev *netdev, const char *filename);
};
} NetDevVTable;
extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
#define NETDEV_VTABLE(n) netdev_vtable[(n)->kind]
/* 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) { \
if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \
return NULL; \
@ -162,27 +152,6 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
/* For casting the various netdev kinds into a netdev */
#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);
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.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
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.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
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)

View File

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

View File

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

View File

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

View File

@ -24,19 +24,30 @@
#include "sd-bus.h"
#include "sd-event.h"
#include "sd-netlink.h"
#include "hashmap.h"
#include "list.h"
#include "udev.h"
typedef struct Manager Manager;
#include "dhcp-identifier.h"
#include "hashmap.h"
#include "list.h"
#include "networkd-address-pool.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-util.h"
extern const char* const network_dirs[];
struct Manager {
sd_netlink *rtnl;
sd_event *event;
@ -63,17 +74,15 @@ struct Manager {
usec_t network_dirs_ts_usec;
/* Value of Type in [DUID] section */
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];
DUID duid;
};
extern const char* const network_dirs[];
/* Manager */
static inline const DUID* link_duid(const Link *link) {
if (link->network->duid.type != _DUID_TYPE_INVALID)
return &link->network->duid;
else
return &link->manager->duid;
}
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 void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event,
void *userdata);
int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
void *userdata);
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
int sd_dhcp_client_set_callback(
sd_dhcp_client *client,
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_address(sd_dhcp_client *client,
const struct in_addr *last_address);
int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
size_t addr_len, 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, uint8_t *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_set_request_option(
sd_dhcp_client *client,
uint8_t option);
int sd_dhcp_client_set_request_address(
sd_dhcp_client *client,
const struct in_addr *last_address);
int sd_dhcp_client_set_request_broadcast(
sd_dhcp_client *client,
int broadcast);
int sd_dhcp_client_set_index(
sd_dhcp_client *client,
int interface_index);
int sd_dhcp_client_set_mac(
sd_dhcp_client *client,
const uint8_t *addr,
size_t addr_len,
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_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_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);
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 void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event,
void *userdata);
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
sd_dhcp6_client_callback_t cb, void *userdata);
typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata);
int sd_dhcp6_client_set_callback(
sd_dhcp6_client *client,
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_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
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_duid(sd_dhcp6_client *client, uint16_t duid_type,
uint8_t *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_set_index(
sd_dhcp6_client *client,
int interface_index);
int sd_dhcp6_client_set_local_address(
sd_dhcp6_client *client,
const struct in6_addr *local_address);
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_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_start(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);
sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);