Print this page
4586 dhcpv6 client id malformed
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libdhcpagent/common/dhcp_stable.c
+++ new/usr/src/lib/libdhcpagent/common/dhcp_stable.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 /*
30 28 * This module reads and writes the stable identifier values, DUID and IAID.
31 29 */
32 30
33 31 #include <stdio.h>
34 32 #include <stdlib.h>
35 33 #include <unistd.h>
36 34 #include <string.h>
37 35 #include <limits.h>
38 36 #include <fcntl.h>
39 37 #include <errno.h>
40 38 #include <libdlpi.h>
41 39 #include <uuid/uuid.h>
42 40 #include <sys/types.h>
43 41 #include <sys/stat.h>
44 42 #include <net/if.h>
45 43 #include <netinet/dhcp6.h>
46 44 #include <dhcp_inittab.h>
45 +#include <sys/ethernet.h>
47 46
48 47 #define DUID_FILE "/etc/dhcp/duid"
49 48 #define IAID_FILE "/etc/dhcp/iaid"
50 49
51 50 struct iaid_ent {
52 51 uint32_t ie_iaid;
53 52 char ie_name[LIFNAMSIZ];
54 53 };
55 54
56 55 /*
57 56 * read_stable_duid(): read the system's stable DUID, if any
58 57 *
59 58 * input: size_t *: pointer to a size_t to return the DUID length
60 59 * output: uchar_t *: the DUID buffer, or NULL on error (and errno is set)
61 60 * note: memory returned is from malloc; caller must free.
62 61 */
63 62
64 63 uchar_t *
65 64 read_stable_duid(size_t *duidlen)
66 65 {
67 66 int fd;
68 67 ssize_t retv;
69 68 struct stat sb;
70 69 uchar_t *duid = NULL;
71 70
72 71 if ((fd = open(DUID_FILE, O_RDONLY)) == -1)
73 72 return (NULL);
74 73 if (fstat(fd, &sb) != -1 && S_ISREG(sb.st_mode) &&
75 74 (duid = malloc(sb.st_size)) != NULL) {
76 75 retv = read(fd, duid, sb.st_size);
77 76 if (retv == sb.st_size) {
78 77 *duidlen = sb.st_size;
79 78 } else {
80 79 free(duid);
81 80 /*
82 81 * Make sure that errno always gets set when something
83 82 * goes wrong.
84 83 */
85 84 if (retv >= 0)
86 85 errno = EINVAL;
87 86 duid = NULL;
88 87 }
89 88 }
90 89 (void) close(fd);
91 90 return (duid);
92 91 }
93 92
94 93 /*
95 94 * write_stable_duid(): write the system's stable DUID.
96 95 *
97 96 * input: const uchar_t *: pointer to the DUID buffer
98 97 * size_t: length of the DUID
99 98 * output: int: 0 on success, -1 on error. errno is set on error.
100 99 */
101 100
102 101 int
103 102 write_stable_duid(const uchar_t *duid, size_t duidlen)
104 103 {
105 104 int fd;
106 105 ssize_t retv;
107 106
108 107 (void) unlink(DUID_FILE);
109 108 if ((fd = open(DUID_FILE, O_WRONLY | O_CREAT, 0644)) == -1)
110 109 return (-1);
111 110 retv = write(fd, duid, duidlen);
112 111 if (retv == duidlen) {
113 112 return (close(fd));
114 113 } else {
115 114 (void) close(fd);
116 115 if (retv >= 0)
117 116 errno = ENOSPC;
118 117 return (-1);
119 118 }
120 119 }
121 120
122 121 /*
123 122 * make_stable_duid(): create a new DUID
124 123 *
125 124 * input: const char *: name of physical interface for reference
126 125 * size_t *: pointer to a size_t to return the DUID length
127 126 * output: uchar_t *: the DUID buffer, or NULL on error (and errno is set)
128 127 * note: memory returned is from malloc; caller must free.
129 128 */
130 129
131 130 uchar_t *
132 131 make_stable_duid(const char *physintf, size_t *duidlen)
133 132 {
134 133 int len;
135 134 dlpi_info_t dlinfo;
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
136 135 dlpi_handle_t dh = NULL;
137 136 uint_t arptype;
138 137 duid_en_t *den;
139 138
140 139 /*
141 140 * Try to read the MAC layer address for the physical interface
142 141 * provided as a hint. If that works, we can use a DUID-LLT.
143 142 */
144 143
145 144 if (dlpi_open(physintf, &dh, 0) == DLPI_SUCCESS &&
145 + dlpi_bind(dh, ETHERTYPE_IPV6, NULL) == DLPI_SUCCESS &&
146 146 dlpi_info(dh, &dlinfo, 0) == DLPI_SUCCESS &&
147 147 (len = dlinfo.di_physaddrlen) > 0 &&
148 148 (arptype = dlpi_arptype(dlinfo.di_mactype) != 0)) {
149 149 duid_llt_t *dllt;
150 150 time_t now;
151 151
152 152 if ((dllt = malloc(sizeof (*dllt) + len)) == NULL) {
153 153 dlpi_close(dh);
154 154 return (NULL);
155 155 }
156 156
157 157 (void) memcpy((dllt + 1), dlinfo.di_physaddr, len);
158 158 dllt->dllt_dutype = htons(DHCPV6_DUID_LLT);
159 159 dllt->dllt_hwtype = htons(arptype);
160 160 now = time(NULL) - DUID_TIME_BASE;
161 161 dllt->dllt_time = htonl(now);
162 162 *duidlen = sizeof (*dllt) + len;
163 163 dlpi_close(dh);
164 164 return ((uchar_t *)dllt);
165 165 }
166 166 if (dh != NULL)
167 167 dlpi_close(dh);
168 168
169 169 /*
170 170 * If we weren't able to create a DUID based on the network interface
171 171 * in use, then generate one based on a UUID.
172 172 */
173 173 den = malloc(sizeof (*den) + UUID_LEN);
174 174 if (den != NULL) {
175 175 uuid_t uuid;
176 176
177 177 den->den_dutype = htons(DHCPV6_DUID_EN);
178 178 DHCPV6_SET_ENTNUM(den, DHCPV6_SUN_ENT);
179 179 uuid_generate(uuid);
180 180 (void) memcpy(den + 1, uuid, UUID_LEN);
181 181 *duidlen = sizeof (*den) + UUID_LEN;
182 182 }
183 183 return ((uchar_t *)den);
184 184 }
185 185
186 186 /*
187 187 * read_stable_iaid(): read a link's stable IAID, if any
188 188 *
189 189 * input: const char *: interface name
190 190 * output: uint32_t: the IAID, or 0 if none
191 191 */
192 192
193 193 uint32_t
194 194 read_stable_iaid(const char *intf)
195 195 {
196 196 int fd;
197 197 struct iaid_ent ie;
198 198
199 199 if ((fd = open(IAID_FILE, O_RDONLY)) == -1)
200 200 return (0);
201 201 while (read(fd, &ie, sizeof (ie)) == sizeof (ie)) {
202 202 if (strcmp(intf, ie.ie_name) == 0) {
203 203 (void) close(fd);
204 204 return (ie.ie_iaid);
205 205 }
206 206 }
207 207 (void) close(fd);
208 208 return (0);
209 209 }
210 210
211 211 /*
212 212 * write_stable_iaid(): write out a link's stable IAID
213 213 *
214 214 * input: const char *: interface name
215 215 * output: uint32_t: the IAID, or 0 if none
216 216 */
217 217
218 218 int
219 219 write_stable_iaid(const char *intf, uint32_t iaid)
220 220 {
221 221 int fd;
222 222 struct iaid_ent ie;
223 223 ssize_t retv;
224 224
225 225 if ((fd = open(IAID_FILE, O_RDWR | O_CREAT, 0644)) == -1)
226 226 return (0);
227 227 while (read(fd, &ie, sizeof (ie)) == sizeof (ie)) {
228 228 if (strcmp(intf, ie.ie_name) == 0) {
229 229 (void) close(fd);
230 230 if (iaid == ie.ie_iaid) {
231 231 return (0);
232 232 } else {
233 233 errno = EINVAL;
234 234 return (-1);
235 235 }
236 236 }
237 237 }
238 238 (void) memset(&ie, 0, sizeof (ie));
239 239 ie.ie_iaid = iaid;
240 240 (void) strlcpy(ie.ie_name, intf, sizeof (ie.ie_name));
241 241 retv = write(fd, &ie, sizeof (ie));
242 242 (void) close(fd);
243 243 if (retv == sizeof (ie)) {
244 244 return (0);
245 245 } else {
246 246 if (retv >= 0)
247 247 errno = ENOSPC;
248 248 return (-1);
249 249 }
250 250 }
251 251
252 252 /*
253 253 * make_stable_iaid(): create a stable IAID for a link
254 254 *
255 255 * input: const char *: interface name
256 256 * uint32_t: the ifIndex for this link (as a "hint")
257 257 * output: uint32_t: the new IAID, never zero
258 258 */
259 259
260 260 /* ARGSUSED */
261 261 uint32_t
262 262 make_stable_iaid(const char *intf, uint32_t hint)
263 263 {
264 264 int fd;
265 265 struct iaid_ent ie;
266 266 uint32_t maxid, minunused;
267 267 boolean_t recheck;
268 268
269 269 if ((fd = open(IAID_FILE, O_RDONLY)) == -1)
270 270 return (hint);
271 271 maxid = 0;
272 272 minunused = 1;
273 273 /*
274 274 * This logic is deliberately unoptimized. The reason is that it runs
275 275 * essentially just once per interface for the life of the system.
276 276 * Once the IAID is established, there's no reason to generate it
277 277 * again, and all we care about here is correctness. Also, IAIDs tend
278 278 * to get added in a logical sequence order, so the outer loop should
279 279 * not normally run more than twice.
280 280 */
281 281 do {
282 282 recheck = B_FALSE;
283 283 while (read(fd, &ie, sizeof (ie)) == sizeof (ie)) {
284 284 if (ie.ie_iaid > maxid)
285 285 maxid = ie.ie_iaid;
286 286 if (ie.ie_iaid == minunused) {
287 287 recheck = B_TRUE;
288 288 minunused++;
289 289 }
290 290 if (ie.ie_iaid == hint)
291 291 hint = 0;
292 292 }
293 293 if (recheck)
294 294 (void) lseek(fd, 0, SEEK_SET);
295 295 } while (recheck);
296 296 (void) close(fd);
297 297 if (hint != 0)
298 298 return (hint);
299 299 else if (maxid != UINT32_MAX)
300 300 return (maxid + 1);
301 301 else
302 302 return (minunused);
303 303 }
↓ open down ↓ |
148 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX