]>
Commit | Line | Data |
---|---|---|
c83321e6 VK |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
3 | /*** | |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2014 Tom Gundersen <teg@jklm.no> | |
7 | ||
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU Lesser General Public License as published by | |
10 | the Free Software Foundation; either version 2.1 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | Lesser General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU Lesser General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
22 | #include <ctype.h> | |
23 | ||
24 | #include "conf-parser.h" | |
25 | #include "def.h" | |
26 | #include "dhcp-identifier.h" | |
27 | #include "networkd-conf.h" | |
28 | #include "string-table.h" | |
29 | ||
30 | int manager_parse_config_file(Manager *m) { | |
31 | assert(m); | |
32 | ||
33 | return config_parse_many(PKGSYSCONFDIR "/networkd.conf", | |
34 | CONF_PATHS_NULSTR("systemd/networkd.conf.d"), | |
35 | "DUID\0", | |
36 | config_item_perf_lookup, networkd_gperf_lookup, | |
37 | false, m); | |
38 | } | |
39 | ||
40 | static const char* const dhcp_duid_type_table[_DHCP_DUID_TYPE_MAX] = { | |
41 | [DHCP_DUID_TYPE_RAW] = "raw", | |
42 | [DHCP_DUID_TYPE_LLT] = "link-layer-time", | |
43 | [DHCP_DUID_TYPE_EN] = "vendor", | |
44 | [DHCP_DUID_TYPE_LL] = "link-layer", | |
45 | [DHCP_DUID_TYPE_UUID] = "uuid" | |
46 | }; | |
47 | DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_duid_type, DHCPDUIDType); | |
48 | DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_duid_type, dhcp_duid_type, DHCPDUIDType, "Failed to parse DHCP DUID type"); | |
49 | ||
50 | int config_parse_dhcp_duid_raw( | |
51 | const char *unit, | |
52 | const char *filename, | |
53 | unsigned line, | |
54 | const char *section, | |
55 | unsigned section_line, | |
56 | const char *lvalue, | |
57 | int ltype, | |
58 | const char *rvalue, | |
59 | void *data, | |
60 | void *userdata) { | |
61 | int r; | |
62 | long byte; | |
63 | char *cbyte, *pnext; | |
64 | const char *pduid = (const char *)rvalue; | |
65 | size_t count = 0, duid_len = 0; | |
66 | Manager *m = userdata; | |
67 | ||
68 | assert(filename); | |
69 | assert(lvalue); | |
70 | assert(rvalue); | |
71 | assert(m); | |
72 | assert(m->dhcp_duid_type != _DHCP_DUID_TYPE_INVALID); | |
73 | ||
74 | switch (m->dhcp_duid_type) { | |
75 | case DHCP_DUID_TYPE_LLT: | |
76 | /* RawData contains DUID-LLT link-layer address (offset 6) */ | |
77 | duid_len = 6; | |
78 | break; | |
79 | case DHCP_DUID_TYPE_EN: | |
80 | /* RawData contains DUID-EN identifier (offset 4) */ | |
81 | duid_len = 4; | |
82 | break; | |
83 | case DHCP_DUID_TYPE_LL: | |
84 | /* RawData contains DUID-LL link-layer address (offset 2) */ | |
85 | duid_len = 2; | |
86 | break; | |
87 | case DHCP_DUID_TYPE_UUID: | |
88 | /* RawData specifies UUID (offset 0) - fall thru */ | |
89 | case DHCP_DUID_TYPE_RAW: | |
90 | /* First two bytes of RawData is DUID Type - fall thru */ | |
91 | default: | |
92 | break; | |
93 | } | |
94 | ||
95 | if (m->dhcp_duid_type != DHCP_DUID_TYPE_RAW) | |
96 | m->dhcp_duid.type = htobe16(m->dhcp_duid_type); | |
97 | ||
98 | /* RawData contains DUID in format " NN:NN:NN... " */ | |
99 | while (true) { | |
100 | r = extract_first_word(&pduid, &cbyte, ":", 0); | |
101 | if (r < 0) { | |
102 | log_error("Failed to read DUID."); | |
103 | return -EINVAL; | |
104 | } | |
105 | if (r == 0) | |
106 | break; | |
107 | if (duid_len >= MAX_DUID_LEN) { | |
108 | log_error("DUID length exceeds maximum length."); | |
109 | return -EINVAL; | |
110 | } | |
111 | ||
112 | errno = 0; | |
113 | byte = strtol(cbyte, &pnext, 16); | |
114 | if ((errno == ERANGE && (byte == LONG_MAX || byte == LONG_MIN)) | |
115 | || (errno != 0 && byte == 0) || (cbyte == pnext)) { | |
116 | log_error("Invalid DUID byte: %s.", cbyte); | |
117 | return -EINVAL; | |
118 | } | |
119 | ||
120 | /* If DHCP_DUID_TYPE_RAW, first two bytes holds DUID Type */ | |
121 | if ((m->dhcp_duid_type == DHCP_DUID_TYPE_RAW) && (count < 2)) { | |
122 | m->dhcp_duid.type |= (byte << (8 * count)); | |
123 | count++; | |
124 | continue; | |
125 | } | |
126 | ||
127 | m->dhcp_duid.raw.data[duid_len++] = byte; | |
128 | } | |
129 | ||
130 | m->dhcp_duid_len = sizeof(m->dhcp_duid.type) + duid_len; | |
131 | ||
132 | return 0; | |
133 | } |