summaryrefslogtreecommitdiff
path: root/src/network/networkd-conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-conf.c')
-rw-r--r--src/network/networkd-conf.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
new file mode 100644
index 0000000000..70f0121d6d
--- /dev/null
+++ b/src/network/networkd-conf.c
@@ -0,0 +1,171 @@
+/***
+ 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 "hexdecoct.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"),
+ "DHCP\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;
+ 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;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(userdata);
+
+ 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... " */
+ for (;;) {
+ int n1, n2;
+ uint32_t byte;
+
+ r = extract_first_word(&pduid, &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) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue);
+ return 0;
+ }
+
+ len = strlen(cbyte);
+ if (len != 1 && len != 2) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue);
+ return 0;
+ }
+ n1 = unhexchar(cbyte[0]);
+ if (len == 2)
+ n2 = unhexchar(cbyte[1]);
+ else
+ n2 = 0;
+
+ if (n1 < 0 || n2 < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue);
+ return 0;
+ }
+
+ 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);
+ }
+
+ return 0;
+}