DHCP DUID, IAID configuration options

This commit is contained in:
Vinay Kulkarni 2016-03-30 16:33:55 -07:00
parent 1eb963a32d
commit 413708d106
25 changed files with 703 additions and 43 deletions

View File

@ -1960,15 +1960,21 @@ endif
if ENABLE_NETWORKD
MANPAGES += \
man/networkctl.1 \
man/networkd.conf.5 \
man/systemd-networkd-wait-online.service.8 \
man/systemd-networkd.service.8 \
man/systemd.netdev.5 \
man/systemd.network.5
MANPAGES_ALIAS += \
man/networkd.conf.d.5 \
man/systemd-networkd-wait-online.8 \
man/systemd-networkd.8
man/networkd.conf.d.5: man/networkd.conf.5
man/systemd-networkd-wait-online.8: man/systemd-networkd-wait-online.service.8
man/systemd-networkd.8: man/systemd-networkd.service.8
man/networkd.conf.d.html: man/networkd.conf.html
$(html-alias)
man/systemd-networkd-wait-online.html: man/systemd-networkd-wait-online.service.html
$(html-alias)
@ -2479,6 +2485,7 @@ EXTRA_DIST += \
man/machinectl.xml \
man/modules-load.d.xml \
man/networkctl.xml \
man/networkd.conf.xml \
man/nss-myhostname.xml \
man/nss-mymachines.xml \
man/nss-resolve.xml \

View File

@ -5398,6 +5398,8 @@ libnetworkd_core_la_CFLAGS = \
libnetworkd_core_la_SOURCES = \
src/libsystemd-network/network-internal.h \
src/network/networkd.h \
src/network/networkd-conf.h \
src/network/networkd-conf.c \
src/network/networkd-link.h \
src/network/networkd-link.c \
src/network/networkd-netdev.h \
@ -5446,6 +5448,7 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-lldp-tx.c
nodist_libnetworkd_core_la_SOURCES = \
src/network/networkd-gperf.c \
src/network/networkd-network-gperf.c \
src/network/networkd-netdev-gperf.c
@ -5542,6 +5545,7 @@ BUSNAMES_TARGET_WANTS += \
endif
gperf_gperf_sources += \
src/network/networkd-gperf.gperf \
src/network/networkd-network-gperf.gperf \
src/network/networkd-netdev-gperf.gperf

159
man/networkd.conf.xml Normal file
View File

@ -0,0 +1,159 @@
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2014 Vinay Kulkarni
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/>.
-->
<refentry id="networkd.conf" conditional='ENABLE_NETWORKD'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>networkd.conf</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Vinay</firstname>
<surname>Kulkarni</surname>
<email>kulkarniv@vmware.com</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>networkd.conf</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>networkd.conf</refname>
<refname>networkd.conf.d</refname>
<refpurpose>Global Network configuration files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/systemd/networkd.conf</filename></para>
<para><filename>/etc/systemd/networkd.conf.d/*.conf</filename></para>
<para><filename>/usr/lib/systemd/networkd.conf.d/*.conf</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>These configuration files control global network parameters.
For e.g. DHCP Unique Identifier (DUID).</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
<refsect1>
<title>[DUID] Section Options</title>
<para>This section configures the DHCP Unique Idendifier (DUID) value used by DHCP
protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface
Identity Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6
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>
<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>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>Type=</varname></term>
<listitem><para>The type of DUID specified in this section. The following values are
supported:</para>
<para>raw : If <literal>Type=raw</literal>, then <literal>RawData=</literal> specifies
the entire DUID. For e.g: <literal>RawData=00:02:00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</literal>
specifies a 14 byte long DUID-EN ("00:02"), with enterprise number 43793 ("00:00:ab:11"),
and identifier value "f9:2a:c2:77:29:f9:5c:00".</para><para>If Type is not specified and
RawData is specified, Type defaults to 'raw'.</para>
<para>Type will support the following values in the future:</para>
<para>link-layer-and-time : If <literal>Type=link-layer-and-time</literal>, then
<literal>MACAddress=</literal> and <literal>TimeStamp=</literal> specify the hardware
address and time-stamp for DUID-LLT.</para>
<para>vendor : If <literal>Type=vendor</literal>, then <literal>EnterpriseNumber=</literal>
and <literal>RawData=</literal> specify the enterprise number and identifier for DUID-EN.</para>
<para>link-layer : If <literal>Type=link-layer</literal>, then <literal>MACAddress=</literal>
specifies the hardware address for DUID-LL.</para>
<para>uuid : If <literal>Type=uuid</literal>, then <literal>UUID=</literal> specifies DUID-UUID.
</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>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<para>The following options will be supported in the future:
</para>
<variablelist>
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem><para>Specifies the link-layer address for DUID Type <option>link-layer
</option> or <option>link-layer-and-time</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>TimeStamp=</varname></term>
<listitem><para>Specifies the DUID generation time for DUID Type <option>
link-layer-and-time</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>EnterpriseNumber=</varname></term>
<listitem><para>Specifies the enterprise number for DUID Type
<option>vendor</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>UUID=</varname></term>
<listitem><para>Specifies the UUID for DUID Type <option>uuid</option>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -204,6 +204,12 @@
understood to the base of 1024.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>IAIDValue=</varname></term>
<listitem>
<para>Identity Association Identifier for the interface, a 32-bit unsigned integer.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
@ -823,6 +829,86 @@
</refsect1>
<refsect1>
<title>[DUID] Section Options</title>
<para>This section configures the DHCP Unique Idendifier (DUID) value used by DHCP
protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface
Identity Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6
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.</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, 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>
<para>The following options are available in <literal>[DUID]</literal> section:</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>Type=</varname></term>
<listitem><para>The type of DUID specified in this section. The following values are
supported:</para>
<para>raw : If <literal>Type=raw</literal>, then <literal>RawData=</literal> specifies
the entire DUID. For e.g: <literal>RawData=00:02:00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</literal>
specifies a 14 byte long DUID-EN ("00:02"), with enterprise number 43793 ("00:00:ab:11"),
and identifier value "f9:2a:c2:77:29:f9:5c:00".</para><para>If Type is not specified and
RawData is specified, Type defaults to 'raw'.</para>
<para>Type will support the following values in the future:</para>
<para>link-layer-and-time : If <literal>Type=link-layer-and-time</literal>, then
<literal>MACAddress=</literal> and <literal>TimeStamp=</literal> specify the hardware
address and time-stamp for DUID-LLT.</para>
<para>vendor : If <literal>Type=vendor</literal>, then <literal>EnterpriseNumber=</literal>
and <literal>RawData=</literal> specify the enterprise number and identifier for DUID-EN.</para>
<para>link-layer : If <literal>Type=link-layer</literal>, then <literal>MACAddress=</literal>
specifies the hardware address for DUID-LL.</para>
<para>uuid : If <literal>Type=uuid</literal>, then <literal>UUID=</literal> specifies DUID-UUID.
</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>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<para>The following options will be supported in the future:
</para>
<variablelist>
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem><para>Specifies the link-layer address for DUID Type <option>link-layer
</option> or <option>link-layer-and-time</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>TimeStamp=</varname></term>
<listitem><para>Specifies the DUID generation time for DUID Type <option>
link-layer-and-time</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>EnterpriseNumber=</varname></term>
<listitem><para>Specifies the enterprise number for DUID Type <option>
vendor</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>UUID=</varname></term>
<listitem><para>Specifies the UUID for DUID Type <option>uuid</option>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>[DHCPServer] Section Options</title>
<para>The <literal>[DHCPServer]</literal> section contains

View File

@ -43,7 +43,7 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
if (r < 0)
return r;
unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
unaligned_write_be16(&duid->type, DUID_TYPE_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
*len = sizeof(duid->type) + sizeof(duid->en);

View File

@ -25,13 +25,23 @@
#include "sparse-endian.h"
#include "unaligned.h"
typedef enum DUIDType {
DUID_TYPE_RAW = 0,
DUID_TYPE_LLT = 1,
DUID_TYPE_EN = 2,
DUID_TYPE_LL = 3,
DUID_TYPE_UUID = 4,
_DUID_TYPE_MAX,
_DUID_TYPE_INVALID = -1,
} DUIDType;
/* RFC 3315 section 9.1:
* A DUID can be no more than 128 octets long (not including the type code).
*/
#define MAX_DUID_LEN 128
struct duid {
uint16_t type;
be16_t type;
union {
struct {
/* DHCP6_DUID_LLT */
@ -61,3 +71,32 @@ struct duid {
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_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -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;
}

View File

@ -62,13 +62,6 @@ enum {
#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC
#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC
enum {
DHCP6_DUID_LLT = 1,
DHCP6_DUID_EN = 2,
DHCP6_DUID_LL = 3,
DHCP6_DUID_UUID = 4,
};
enum DHCP6State {
DHCP6_STATE_STOPPED = 0,
DHCP6_STATE_INFORMATION_REQUEST = 1,

View File

@ -335,6 +335,35 @@ int config_parse_hwaddr(const char *unit,
return 0;
}
int config_parse_iaid(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) {
uint32_t iaid;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = safe_atou32(rvalue, &iaid);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue);
return r;
}
*((uint32_t *)data) = iaid;
return 0;
}
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
unsigned i;

View File

@ -62,6 +62,10 @@ int config_parse_ifalias(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_iaid(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 net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);

View File

@ -82,7 +82,7 @@ struct sd_dhcp_client {
} _packed_ ll;
struct {
/* 255: Node-specific (RFC 4361) */
uint32_t iaid;
be32_t iaid;
struct duid duid;
} _packed_ ns;
struct {
@ -298,6 +298,52 @@ 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) {
DHCP_CLIENT_DONT_DESTROY(client);
int r;
assert_return(client, -EINVAL);
zero(client->client_id);
client->client_id.type = 255;
/* If IAID is not configured, generate it. */
if (iaid == 0) {
r = dhcp_identifier_set_iaid(client->index, client->mac_addr,
client->mac_addr_len,
&client->client_id.ns.iaid);
if (r < 0)
return r;
} 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;
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);
}
client->client_id_len = sizeof(client->client_id.type) + duid_len +
sizeof(client->client_id.ns.iaid);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured IAID+DUID, restarting.");
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
sd_dhcp_client_start(client);
}
return 0;
}
int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
const char *hostname) {
char *new_hostname = NULL;

View File

@ -180,41 +180,29 @@ 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 type,
uint8_t *duid, size_t duid_len) {
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
uint8_t *duid, size_t duid_len) {
int r;
assert_return(client, -EINVAL);
assert_return(duid, -EINVAL);
assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
switch (type) {
case DHCP6_DUID_LLT:
if (duid_len <= sizeof(client->duid.llt))
return -EINVAL;
break;
case DHCP6_DUID_EN:
if (duid_len != sizeof(client->duid.en))
return -EINVAL;
break;
case DHCP6_DUID_LL:
if (duid_len <= sizeof(client->duid.ll))
return -EINVAL;
break;
case DHCP6_DUID_UUID:
if (duid_len != sizeof(client->duid.uuid))
return -EINVAL;
break;
default:
/* accept unknown type in order to be forward compatible */
break;
if (duid_len > 0) {
r = dhcp_validate_duid_len(duid_type, duid_len);
if (r < 0)
return r;
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.type = htobe16(type);
memcpy(&client->duid.raw.data, duid, duid_len);
client->duid_len = duid_len + sizeof(client->duid.type);
return 0;
}
int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
client->ia_na.id = htobe32(iaid);
return 0;
}

155
src/network/networkd-conf.c Normal file
View File

@ -0,0 +1,155 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
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 <ctype.h>
#include "conf-parser.h"
#include "def.h"
#include "dhcp-identifier.h"
#include "networkd-conf.h"
#include "string-table.h"
int manager_parse_config_file(Manager *m) {
assert(m);
return config_parse_many(PKGSYSCONFDIR "/networkd.conf",
CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
"DUID\0",
config_item_perf_lookup, networkd_gperf_lookup,
false, 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"
};
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");
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 r;
long byte;
char *cbyte, *pnext;
const char *pduid = rvalue;
size_t count = 0, duid_index = 0;
Manager *m;
Network *n;
DUIDType *duid_type;
uint16_t *dhcp_duid_type;
size_t *dhcp_duid_len;
uint8_t *dhcp_duid;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(userdata);
if (ltype == DUID_CONFIG_SOURCE_GLOBAL) {
m = userdata;
duid_type = &m->duid_type;
dhcp_duid_type = &m->dhcp_duid_type;
dhcp_duid_len = &m->dhcp_duid_len;
dhcp_duid = m->dhcp_duid;
} else {
/* DUID_CONFIG_SOURCE_NETWORK */
n = userdata;
duid_type = &n->duid_type;
dhcp_duid_type = &n->dhcp_duid_type;
dhcp_duid_len = &n->dhcp_duid_len;
dhcp_duid = n->dhcp_duid;
}
if (*duid_type == _DUID_TYPE_INVALID)
*duid_type = DUID_TYPE_RAW;
switch (*duid_type) {
case DUID_TYPE_LLT:
/* RawData contains DUID-LLT link-layer address (offset 6) */
duid_index = 6;
break;
case DUID_TYPE_EN:
/* RawData contains DUID-EN identifier (offset 4) */
duid_index = 4;
break;
case DUID_TYPE_LL:
/* RawData contains DUID-LL link-layer address (offset 2) */
duid_index = 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 (*duid_type != DUID_TYPE_RAW)
*dhcp_duid_type = (uint16_t)(*duid_type);
/* RawData contains DUID in format " NN:NN:NN... " */
while (true) {
r = extract_first_word(&pduid, &cbyte, ":", 0);
if (r < 0) {
log_error("Failed to read DUID.");
return -EINVAL;
}
if (r == 0)
break;
if (duid_index >= MAX_DUID_LEN) {
log_error("DUID length exceeds maximum length.");
return -EINVAL;
}
errno = 0;
byte = strtol(cbyte, &pnext, 16);
if ((errno == ERANGE && (byte == LONG_MAX || byte == LONG_MIN))
|| (errno != 0 && byte == 0) || (cbyte == pnext)) {
log_error("Invalid DUID byte: %s.", cbyte);
return -EINVAL;
}
/* If DUID_TYPE_RAW, first two bytes hold DHCP DUID type code */
if ((*duid_type == DUID_TYPE_RAW) && (count < 2)) {
*dhcp_duid_type |= (byte << (8 * (1 - count)));
count++;
continue;
}
dhcp_duid[duid_index++] = byte;
}
*dhcp_duid_len = duid_index;
return 0;
}

View File

@ -0,0 +1,36 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
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 "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);

View File

@ -625,7 +625,21 @@ int dhcp4_configure(Link *link) {
switch (link->network->dhcp_client_identifier) {
case DHCP_CLIENT_ID_DUID:
/* Library defaults to this. */
/* 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);
if (r < 0)
return r;
break;
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,

View File

@ -230,6 +230,23 @@ int dhcp6_configure(Link *link) {
if (r < 0)
goto error;
r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
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);
if (r < 0)
goto error;
r = sd_dhcp6_client_set_index(client, link->ifindex);
if (r < 0)
goto error;

View File

@ -0,0 +1,18 @@
%{
#include <stddef.h>
#include "conf-parser.h"
#include "networkd-conf.h"
%}
struct ConfigPerfItem;
%null_strings
%language=ANSI-C
%define slot-name section_and_lvalue
%define hash-function-name networkd_gperf_hash
%define lookup-function-name networkd_gperf_lookup
%readonly-tables
%omit-struct-type
%struct-type
%includes
%%
DUID.Type, config_parse_duid_type, 0, offsetof(Manager, duid_type)
DUID.RawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_GLOBAL, offsetof(Manager, dhcp_duid)

View File

@ -2781,6 +2781,21 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
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);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
}
if (link->dhcp6_client) {
@ -2790,6 +2805,24 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
r = sd_dhcp6_client_set_iaid(link->dhcp6_client,
link->network->iaid);
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);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
}
}
}

View File

@ -1037,6 +1037,8 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
m->duid_type = _DUID_TYPE_INVALID;
*ret = m;
m = NULL;

View File

@ -2,6 +2,7 @@
#include <stddef.h>
#include "conf-parser.h"
#include "networkd.h"
#include "networkd-conf.h"
#include "network-internal.h"
%}
struct ConfigPerfItem;
@ -26,6 +27,9 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
Link.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
DUID.Type, config_parse_duid_type, 0, offsetof(Network, duid_type)
DUID.RawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_NETWORK, offsetof(Network, dhcp_duid)
Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)

View File

@ -131,10 +131,12 @@ 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;
r = config_parse(NULL, filename, file,
"Match\0"
"Link\0"
"DUID\0"
"Network\0"
"Address\0"
"Route\0"

View File

@ -24,6 +24,7 @@
typedef struct Network Network;
#include "dhcp-identifier.h"
#include "networkd-address.h"
#include "networkd-fdb.h"
#include "networkd-netdev.h"
@ -144,6 +145,13 @@ 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];
LLDPMode lldp_mode; /* LLDP reception */
bool lldp_emit; /* LLDP transmission */

View File

@ -21,6 +21,7 @@
#include "capability-util.h"
#include "networkd.h"
#include "networkd-conf.h"
#include "signal-util.h"
#include "user-util.h"
@ -89,6 +90,10 @@ int main(int argc, char *argv[]) {
goto out;
}
r = manager_parse_config_file(m);
if (r < 0)
log_warning_errno(r, "Failed to parse configuration file: %m");
r = manager_load_config(m);
if (r < 0) {
log_error_errno(r, "Could not load configuration files: %m");

View File

@ -31,6 +31,7 @@
typedef struct Manager Manager;
#include "dhcp-identifier.h"
#include "networkd-address-pool.h"
#include "networkd-link.h"
#include "networkd-network.h"
@ -61,6 +62,13 @@ struct Manager {
LIST_HEAD(AddressPool, address_pools);
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];
};
extern const char* const network_dirs[];

View File

@ -98,6 +98,8 @@ 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);

View File

@ -85,8 +85,9 @@ 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 type, uint8_t *duid,
size_t duid_len);
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,