Print this page
4587 snoop misdecodes DHCPv6 DHCPV6_DUID_LL identifiers
Reviewed by: Sebastien Roy <sebastien.roy@delphix.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcpv6.c
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcpv6.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
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Dynamic Host Configuration Protocol version 6, for IPv6. Supports
29 29 * RFCs 3315, 3319, 3646, 3898, 4075, 4242, 4280, 4580, 4649, and 4704.
30 30 */
31 31
32 +#include <ctype.h>
32 33 #include <stdio.h>
33 34 #include <stdlib.h>
34 35 #include <string.h>
35 36 #include <time.h>
36 37 #include <sys/types.h>
37 38 #include <sys/socket.h>
38 39 #include <netinet/in.h>
39 40 #include <netinet/dhcp6.h>
40 41 #include <arpa/inet.h>
41 42 #include <dhcp_impl.h>
42 43 #include <dhcp_inittab.h>
43 44
44 45 #include "snoop.h"
45 46
46 47 static const char *mtype_to_str(uint8_t);
47 48 static const char *option_to_str(uint8_t);
48 49 static const char *duidtype_to_str(uint16_t);
49 50 static const char *status_to_str(uint16_t);
50 51 static const char *entr_to_str(uint32_t);
51 52 static const char *reconf_to_str(uint8_t);
52 53 static const char *authproto_to_str(uint8_t);
53 54 static const char *authalg_to_str(uint8_t, uint8_t);
54 55 static const char *authrdm_to_str(uint8_t);
55 56 static const char *cwhat_to_str(uint8_t);
56 57 static const char *catype_to_str(uint8_t);
57 58 static void show_hex(const uint8_t *, int, const char *);
58 59 static void show_ascii(const uint8_t *, int, const char *);
59 60 static void show_address(const char *, const void *);
60 61 static void show_options(const uint8_t *, int);
61 62
62 63 int
63 64 interpret_dhcpv6(int flags, const uint8_t *data, int len)
64 65 {
65 66 int olen = len;
66 67 char *line, *lstart;
67 68 dhcpv6_relay_t d6r;
68 69 dhcpv6_message_t d6m;
69 70 uint_t optlen;
70 71 uint16_t statuscode;
71 72
72 73 if (len <= 0) {
73 74 (void) strlcpy(get_sum_line(), "DHCPv6?", MAXLINE);
74 75 return (0);
75 76 }
76 77 if (flags & F_SUM) {
77 78 uint_t ias;
78 79 dhcpv6_option_t *d6o;
79 80 in6_addr_t link, peer;
80 81 char linkstr[INET6_ADDRSTRLEN];
81 82 char peerstr[INET6_ADDRSTRLEN];
82 83
83 84 line = lstart = get_sum_line();
84 85 line += snprintf(line, MAXLINE, "DHCPv6 %s",
85 86 mtype_to_str(data[0]));
86 87 if (data[0] == DHCPV6_MSG_RELAY_FORW ||
87 88 data[0] == DHCPV6_MSG_RELAY_REPL) {
88 89 if (len < sizeof (d6r)) {
89 90 (void) strlcpy(line, "?",
90 91 MAXLINE - (line - lstart));
91 92 return (olen);
92 93 }
93 94 /* Not much in DHCPv6 is aligned. */
94 95 (void) memcpy(&d6r, data, sizeof (d6r));
95 96 (void) memcpy(&link, d6r.d6r_linkaddr, sizeof (link));
96 97 (void) memcpy(&peer, d6r.d6r_peeraddr, sizeof (peer));
97 98 line += snprintf(line, MAXLINE - (line - lstart),
98 99 " HC=%d link=%s peer=%s", d6r.d6r_hop_count,
99 100 inet_ntop(AF_INET6, &link, linkstr,
100 101 sizeof (linkstr)),
101 102 inet_ntop(AF_INET6, &peer, peerstr,
102 103 sizeof (peerstr)));
103 104 data += sizeof (d6r);
104 105 len -= sizeof (d6r);
105 106 } else {
106 107 if (len < sizeof (d6m)) {
107 108 (void) strlcpy(line, "?",
108 109 MAXLINE - (line - lstart));
109 110 return (olen);
110 111 }
111 112 (void) memcpy(&d6m, data, sizeof (d6m));
112 113 line += snprintf(line, MAXLINE - (line - lstart),
113 114 " xid=%x", DHCPV6_GET_TRANSID(&d6m));
114 115 data += sizeof (d6m);
115 116 len -= sizeof (d6m);
116 117 }
117 118 ias = 0;
118 119 d6o = NULL;
119 120 while ((d6o = dhcpv6_find_option(data, len, d6o,
120 121 DHCPV6_OPT_IA_NA, NULL)) != NULL)
121 122 ias++;
122 123 if (ias > 0)
123 124 line += snprintf(line, MAXLINE - (line - lstart),
124 125 " IAs=%u", ias);
125 126 d6o = dhcpv6_find_option(data, len, NULL,
126 127 DHCPV6_OPT_STATUS_CODE, &optlen);
127 128 optlen -= sizeof (*d6o);
128 129 if (d6o != NULL && optlen >= sizeof (statuscode)) {
129 130 (void) memcpy(&statuscode, d6o + 1,
130 131 sizeof (statuscode));
131 132 line += snprintf(line, MAXLINE - (line - lstart),
132 133 " status=%u", ntohs(statuscode));
133 134 optlen -= sizeof (statuscode);
134 135 if (optlen > 0) {
135 136 line += snprintf(line,
136 137 MAXLINE - (line - lstart), " \"%.*s\"",
137 138 optlen, (char *)(d6o + 1) + 2);
138 139 }
139 140 }
140 141 d6o = dhcpv6_find_option(data, len, NULL,
141 142 DHCPV6_OPT_RELAY_MSG, &optlen);
142 143 optlen -= sizeof (*d6o);
143 144 if (d6o != NULL && optlen >= 1) {
144 145 line += snprintf(line, MAXLINE - (line - lstart),
145 146 " relay=%s", mtype_to_str(*(uint8_t *)(d6o + 1)));
146 147 }
147 148 } else if (flags & F_DTAIL) {
148 149 show_header("DHCPv6: ",
149 150 "Dynamic Host Configuration Protocol Version 6", len);
150 151 show_space();
151 152 (void) snprintf(get_line(0, 0), get_line_remain(),
152 153 "Message type (msg-type) = %u (%s)", data[0],
153 154 mtype_to_str(data[0]));
154 155 if (data[0] == DHCPV6_MSG_RELAY_FORW ||
155 156 data[0] == DHCPV6_MSG_RELAY_REPL) {
156 157 if (len < sizeof (d6r)) {
157 158 (void) strlcpy(get_line(0, 0), "Truncated",
158 159 get_line_remain());
159 160 return (olen);
160 161 }
161 162 (void) memcpy(&d6r, data, sizeof (d6r));
162 163 (void) snprintf(get_line(0, 0), get_line_remain(),
163 164 "Hop count = %u", d6r.d6r_hop_count);
164 165 show_address("Link address", d6r.d6r_linkaddr);
165 166 show_address("Peer address", d6r.d6r_peeraddr);
166 167 data += sizeof (d6r);
167 168 len -= sizeof (d6r);
168 169 } else {
169 170 if (len < sizeof (d6m)) {
170 171 (void) strlcpy(get_line(0, 0), "Truncated",
171 172 get_line_remain());
172 173 return (olen);
173 174 }
174 175 (void) memcpy(&d6m, data, sizeof (d6m));
175 176 (void) snprintf(get_line(0, 0), get_line_remain(),
176 177 "Transaction ID = %x", DHCPV6_GET_TRANSID(&d6m));
177 178 data += sizeof (d6m);
178 179 len -= sizeof (d6m);
179 180 }
180 181 show_space();
181 182 show_options(data, len);
182 183 show_space();
183 184 }
184 185 return (olen);
185 186 }
186 187
187 188 static const char *
188 189 mtype_to_str(uint8_t mtype)
189 190 {
190 191 switch (mtype) {
191 192 case DHCPV6_MSG_SOLICIT:
192 193 return ("Solicit");
193 194 case DHCPV6_MSG_ADVERTISE:
194 195 return ("Advertise");
195 196 case DHCPV6_MSG_REQUEST:
196 197 return ("Request");
197 198 case DHCPV6_MSG_CONFIRM:
198 199 return ("Confirm");
199 200 case DHCPV6_MSG_RENEW:
200 201 return ("Renew");
201 202 case DHCPV6_MSG_REBIND:
202 203 return ("Rebind");
203 204 case DHCPV6_MSG_REPLY:
204 205 return ("Reply");
205 206 case DHCPV6_MSG_RELEASE:
206 207 return ("Release");
207 208 case DHCPV6_MSG_DECLINE:
208 209 return ("Decline");
209 210 case DHCPV6_MSG_RECONFIGURE:
210 211 return ("Reconfigure");
211 212 case DHCPV6_MSG_INFO_REQ:
212 213 return ("Information-Request");
213 214 case DHCPV6_MSG_RELAY_FORW:
214 215 return ("Relay-Forward");
215 216 case DHCPV6_MSG_RELAY_REPL:
216 217 return ("Relay-Reply");
217 218 default:
218 219 return ("Unknown");
219 220 }
220 221 }
221 222
222 223 static const char *
223 224 option_to_str(uint8_t mtype)
224 225 {
225 226 switch (mtype) {
226 227 case DHCPV6_OPT_CLIENTID:
227 228 return ("Client Identifier");
228 229 case DHCPV6_OPT_SERVERID:
229 230 return ("Server Identifier");
230 231 case DHCPV6_OPT_IA_NA:
231 232 return ("Identity Association for Non-temporary Addresses");
232 233 case DHCPV6_OPT_IA_TA:
233 234 return ("Identity Association for Temporary Addresses");
234 235 case DHCPV6_OPT_IAADDR:
235 236 return ("IA Address");
236 237 case DHCPV6_OPT_ORO:
237 238 return ("Option Request");
238 239 case DHCPV6_OPT_PREFERENCE:
239 240 return ("Preference");
240 241 case DHCPV6_OPT_ELAPSED_TIME:
241 242 return ("Elapsed Time");
242 243 case DHCPV6_OPT_RELAY_MSG:
243 244 return ("Relay Message");
244 245 case DHCPV6_OPT_AUTH:
245 246 return ("Authentication");
246 247 case DHCPV6_OPT_UNICAST:
247 248 return ("Server Unicast");
248 249 case DHCPV6_OPT_STATUS_CODE:
249 250 return ("Status Code");
250 251 case DHCPV6_OPT_RAPID_COMMIT:
251 252 return ("Rapid Commit");
252 253 case DHCPV6_OPT_USER_CLASS:
253 254 return ("User Class");
254 255 case DHCPV6_OPT_VENDOR_CLASS:
255 256 return ("Vendor Class");
256 257 case DHCPV6_OPT_VENDOR_OPT:
257 258 return ("Vendor-specific Information");
258 259 case DHCPV6_OPT_INTERFACE_ID:
259 260 return ("Interface-Id");
260 261 case DHCPV6_OPT_RECONF_MSG:
261 262 return ("Reconfigure Message");
262 263 case DHCPV6_OPT_RECONF_ACC:
263 264 return ("Reconfigure Accept");
264 265 case DHCPV6_OPT_SIP_NAMES:
265 266 return ("SIP Servers Domain Name List");
266 267 case DHCPV6_OPT_SIP_ADDR:
267 268 return ("SIP Servers IPv6 Address List");
268 269 case DHCPV6_OPT_DNS_ADDR:
269 270 return ("DNS Recursive Name Server");
270 271 case DHCPV6_OPT_DNS_SEARCH:
271 272 return ("Domain Search List");
272 273 case DHCPV6_OPT_IA_PD:
273 274 return ("Identity Association for Prefix Delegation");
274 275 case DHCPV6_OPT_IAPREFIX:
275 276 return ("IA_PD Prefix");
276 277 case DHCPV6_OPT_NIS_SERVERS:
277 278 return ("Network Information Service Servers");
278 279 case DHCPV6_OPT_NIS_DOMAIN:
279 280 return ("Network Information Service Domain Name");
280 281 case DHCPV6_OPT_SNTP_SERVERS:
281 282 return ("Simple Network Time Protocol Servers");
282 283 case DHCPV6_OPT_INFO_REFTIME:
283 284 return ("Information Refresh Time");
284 285 case DHCPV6_OPT_BCMCS_SRV_D:
285 286 return ("BCMCS Controller Domain Name List");
286 287 case DHCPV6_OPT_BCMCS_SRV_A:
287 288 return ("BCMCS Controller IPv6 Address");
288 289 case DHCPV6_OPT_GEOCONF_CVC:
289 290 return ("Civic Location");
290 291 case DHCPV6_OPT_REMOTE_ID:
291 292 return ("Relay Agent Remote-ID");
292 293 case DHCPV6_OPT_SUBSCRIBER:
293 294 return ("Relay Agent Subscriber-ID");
294 295 case DHCPV6_OPT_CLIENT_FQDN:
295 296 return ("Client FQDN");
296 297 default:
297 298 return ("Unknown");
298 299 }
299 300 }
300 301
301 302 static const char *
302 303 duidtype_to_str(uint16_t dtype)
303 304 {
304 305 switch (dtype) {
305 306 case DHCPV6_DUID_LLT:
306 307 return ("Link-layer Address Plus Time");
307 308 case DHCPV6_DUID_EN:
308 309 return ("Enterprise Number");
309 310 case DHCPV6_DUID_LL:
310 311 return ("Link-layer Address");
311 312 default:
312 313 return ("Unknown");
313 314 }
314 315 }
315 316
316 317 static const char *
317 318 status_to_str(uint16_t status)
318 319 {
319 320 switch (status) {
320 321 case DHCPV6_STAT_SUCCESS:
321 322 return ("Success");
322 323 case DHCPV6_STAT_UNSPECFAIL:
323 324 return ("Failure, reason unspecified");
324 325 case DHCPV6_STAT_NOADDRS:
325 326 return ("No addresses for IAs");
326 327 case DHCPV6_STAT_NOBINDING:
327 328 return ("Client binding unavailable");
328 329 case DHCPV6_STAT_NOTONLINK:
329 330 return ("Prefix not on link");
330 331 case DHCPV6_STAT_USEMCAST:
331 332 return ("Use multicast");
332 333 case DHCPV6_STAT_NOPREFIX:
333 334 return ("No prefix available");
334 335 default:
335 336 return ("Unknown");
336 337 }
337 338 }
338 339
339 340 static const char *
340 341 entr_to_str(uint32_t entr)
341 342 {
342 343 switch (entr) {
343 344 case DHCPV6_SUN_ENT:
344 345 return ("Sun Microsystems");
345 346 default:
346 347 return ("Unknown");
347 348 }
348 349 }
349 350
350 351 static const char *
351 352 reconf_to_str(uint8_t msgtype)
352 353 {
353 354 switch (msgtype) {
354 355 case DHCPV6_RECONF_RENEW:
355 356 return ("Renew");
356 357 case DHCPV6_RECONF_INFO:
357 358 return ("Information-request");
358 359 default:
359 360 return ("Unknown");
360 361 }
361 362 }
362 363
363 364 static const char *
364 365 authproto_to_str(uint8_t aproto)
365 366 {
366 367 switch (aproto) {
367 368 case DHCPV6_PROTO_DELAYED:
368 369 return ("Delayed");
369 370 case DHCPV6_PROTO_RECONFIG:
370 371 return ("Reconfigure Key");
371 372 default:
372 373 return ("Unknown");
373 374 }
374 375 }
375 376
376 377 static const char *
377 378 authalg_to_str(uint8_t aproto, uint8_t aalg)
378 379 {
379 380 switch (aproto) {
380 381 case DHCPV6_PROTO_DELAYED:
381 382 case DHCPV6_PROTO_RECONFIG:
382 383 switch (aalg) {
383 384 case DHCPV6_ALG_HMAC_MD5:
384 385 return ("HMAC-MD5 Signature");
385 386 default:
386 387 return ("Unknown");
387 388 }
388 389 break;
389 390 default:
390 391 return ("Unknown");
391 392 }
392 393 }
393 394
394 395 static const char *
395 396 authrdm_to_str(uint8_t ardm)
396 397 {
397 398 switch (ardm) {
398 399 case DHCPV6_RDM_MONOCNT:
399 400 return ("Monotonic Counter");
400 401 default:
401 402 return ("Unknown");
402 403 }
403 404 }
404 405
405 406 static const char *
406 407 cwhat_to_str(uint8_t what)
407 408 {
408 409 switch (what) {
409 410 case DHCPV6_CWHAT_SERVER:
410 411 return ("Server");
411 412 case DHCPV6_CWHAT_NETWORK:
412 413 return ("Network");
413 414 case DHCPV6_CWHAT_CLIENT:
414 415 return ("Client");
415 416 default:
416 417 return ("Unknown");
417 418 }
418 419 }
419 420
420 421 static const char *
421 422 catype_to_str(uint8_t catype)
422 423 {
423 424 switch (catype) {
424 425 case CIVICADDR_LANG:
425 426 return ("Language; RFC 2277");
426 427 case CIVICADDR_A1:
427 428 return ("National division (state)");
428 429 case CIVICADDR_A2:
429 430 return ("County");
430 431 case CIVICADDR_A3:
431 432 return ("City");
432 433 case CIVICADDR_A4:
433 434 return ("City division");
434 435 case CIVICADDR_A5:
435 436 return ("Neighborhood");
436 437 case CIVICADDR_A6:
437 438 return ("Street group");
438 439 case CIVICADDR_PRD:
439 440 return ("Leading street direction");
440 441 case CIVICADDR_POD:
441 442 return ("Trailing street suffix");
442 443 case CIVICADDR_STS:
443 444 return ("Street suffix or type");
444 445 case CIVICADDR_HNO:
445 446 return ("House number");
446 447 case CIVICADDR_HNS:
447 448 return ("House number suffix");
448 449 case CIVICADDR_LMK:
449 450 return ("Landmark");
450 451 case CIVICADDR_LOC:
451 452 return ("Additional location information");
452 453 case CIVICADDR_NAM:
453 454 return ("Name/occupant");
454 455 case CIVICADDR_PC:
455 456 return ("Postal Code/ZIP");
456 457 case CIVICADDR_BLD:
457 458 return ("Building");
458 459 case CIVICADDR_UNIT:
459 460 return ("Unit/apt/suite");
460 461 case CIVICADDR_FLR:
461 462 return ("Floor");
462 463 case CIVICADDR_ROOM:
463 464 return ("Room number");
464 465 case CIVICADDR_TYPE:
465 466 return ("Place type");
466 467 case CIVICADDR_PCN:
467 468 return ("Postal community name");
468 469 case CIVICADDR_POBOX:
469 470 return ("Post office box");
470 471 case CIVICADDR_ADDL:
471 472 return ("Additional code");
472 473 case CIVICADDR_SEAT:
473 474 return ("Seat/desk");
474 475 case CIVICADDR_ROAD:
475 476 return ("Primary road or street");
476 477 case CIVICADDR_RSEC:
477 478 return ("Road section");
478 479 case CIVICADDR_RBRA:
479 480 return ("Road branch");
480 481 case CIVICADDR_RSBR:
481 482 return ("Road sub-branch");
482 483 case CIVICADDR_SPRE:
483 484 return ("Street name pre-modifier");
484 485 case CIVICADDR_SPOST:
485 486 return ("Street name post-modifier");
486 487 case CIVICADDR_SCRIPT:
487 488 return ("Script");
488 489 default:
489 490 return ("Unknown");
490 491 }
491 492 }
492 493
493 494 static void
494 495 show_hex(const uint8_t *data, int len, const char *name)
495 496 {
496 497 char buffer[16 * 3 + 1];
497 498 int nlen;
498 499 int i;
499 500 char sep;
500 501
501 502 nlen = strlen(name);
502 503 sep = '=';
503 504 while (len > 0) {
504 505 for (i = 0; i < 16 && i < len; i++)
505 506 (void) snprintf(buffer + 3 * i, 4, " %02x", *data++);
506 507 (void) snprintf(get_line(0, 0), get_line_remain(), "%*s %c%s",
507 508 nlen, name, sep, buffer);
508 509 name = "";
509 510 sep = ' ';
510 511 len -= i;
511 512 }
512 513 }
513 514
514 515 static void
515 516 show_ascii(const uint8_t *data, int len, const char *name)
516 517 {
517 518 char buffer[64], *bp;
518 519 int nlen;
519 520 int i;
520 521 char sep;
521 522
522 523 nlen = strlen(name);
523 524 sep = '=';
524 525 while (len > 0) {
525 526 bp = buffer;
526 527 for (i = 0; i < sizeof (buffer) - 4 && len > 0; len--) {
527 528 if (!isascii(*data) || !isprint(*data))
528 529 bp += snprintf(bp, 5, "\\%03o", *data++);
529 530 else
530 531 *bp++;
531 532 }
532 533 *bp = '\0';
533 534 (void) snprintf(get_line(0, 0), get_line_remain(),
534 535 "%*s %c \"%s\"", nlen, name, sep, buffer);
535 536 sep = ' ';
536 537 name = "";
537 538 }
538 539 }
539 540
540 541 static void
541 542 show_address(const char *addrname, const void *aptr)
542 543 {
543 544 char *hname;
544 545 char addrstr[INET6_ADDRSTRLEN];
545 546 in6_addr_t addr;
546 547
547 548 (void) memcpy(&addr, aptr, sizeof (in6_addr_t));
548 549 (void) inet_ntop(AF_INET6, &addr, addrstr, sizeof (addrstr));
549 550 hname = addrtoname(AF_INET6, &addr);
550 551 if (strcmp(hname, addrstr) == 0) {
551 552 (void) snprintf(get_line(0, 0), get_line_remain(), "%s = %s",
552 553 addrname, addrstr);
553 554 } else {
554 555 (void) snprintf(get_line(0, 0), get_line_remain(),
555 556 "%s = %s (%s)", addrname, addrstr, hname);
556 557 }
557 558 }
558 559
559 560 static void
560 561 nest_options(const uint8_t *data, uint_t olen, char *prefix, char *title)
561 562 {
562 563 char *str, *oldnest, *oldprefix;
563 564
564 565 if (olen <= 0)
565 566 return;
566 567 oldprefix = prot_prefix;
567 568 oldnest = prot_nest_prefix;
568 569 str = malloc(strlen(prot_nest_prefix) + strlen(prot_prefix) + 1);
569 570 if (str == NULL) {
570 571 prot_nest_prefix = prot_prefix;
571 572 } else {
572 573 (void) sprintf(str, "%s%s", prot_nest_prefix, prot_prefix);
573 574 prot_nest_prefix = str;
574 575 }
575 576 show_header(prefix, title, 0);
576 577 show_options(data, olen);
577 578 free(str);
578 579 prot_prefix = oldprefix;
579 580 prot_nest_prefix = oldnest;
580 581 }
581 582
582 583 static void
583 584 show_options(const uint8_t *data, int len)
584 585 {
585 586 dhcpv6_option_t d6o;
586 587 uint_t olen, retlen;
587 588 uint16_t val16;
588 589 uint16_t type;
589 590 uint32_t val32;
590 591 const uint8_t *ostart;
591 592 char *str, *sp;
592 593 char *oldnest;
593 594
594 595 /*
595 596 * Be very careful with negative numbers; ANSI signed/unsigned
596 597 * comparison doesn't work as expected.
597 598 */
598 599 while (len >= (signed)sizeof (d6o)) {
599 600 (void) memcpy(&d6o, data, sizeof (d6o));
600 601 d6o.d6o_code = ntohs(d6o.d6o_code);
601 602 d6o.d6o_len = olen = ntohs(d6o.d6o_len);
602 603 (void) snprintf(get_line(0, 0), get_line_remain(),
603 604 "Option Code = %u (%s)", d6o.d6o_code,
604 605 option_to_str(d6o.d6o_code));
605 606 ostart = data += sizeof (d6o);
606 607 len -= sizeof (d6o);
607 608 if (olen > len) {
608 609 (void) strlcpy(get_line(0, 0), "Option truncated",
609 610 get_line_remain());
610 611 olen = len;
611 612 }
612 613 switch (d6o.d6o_code) {
613 614 case DHCPV6_OPT_CLIENTID:
614 615 case DHCPV6_OPT_SERVERID:
615 616 if (olen < sizeof (val16))
616 617 break;
617 618 (void) memcpy(&val16, data, sizeof (val16));
618 619 data += sizeof (val16);
619 620 olen -= sizeof (val16);
620 621 type = ntohs(val16);
621 622 (void) snprintf(get_line(0, 0), get_line_remain(),
622 623 " DUID Type = %u (%s)", type,
623 624 duidtype_to_str(type));
↓ open down ↓ |
582 lines elided |
↑ open up ↑ |
624 625 if (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) {
625 626 if (olen < sizeof (val16))
626 627 break;
627 628 (void) memcpy(&val16, data, sizeof (val16));
628 629 data += sizeof (val16);
629 630 olen -= sizeof (val16);
630 631 val16 = ntohs(val16);
631 632 (void) snprintf(get_line(0, 0),
632 633 get_line_remain(),
633 634 " Hardware Type = %u (%s)", val16,
634 - arp_htype(type));
635 + arp_htype(val16));
635 636 }
636 637 if (type == DHCPV6_DUID_LLT) {
637 638 time_t timevalue;
638 639
639 640 if (olen < sizeof (val32))
640 641 break;
641 642 (void) memcpy(&val32, data, sizeof (val32));
642 643 data += sizeof (val32);
643 644 olen -= sizeof (val32);
644 645 timevalue = ntohl(val32) + DUID_TIME_BASE;
645 646 (void) snprintf(get_line(0, 0),
646 647 get_line_remain(),
647 648 " Time = %lu (%.24s)", ntohl(val32),
648 649 ctime(&timevalue));
649 650 }
650 651 if (type == DHCPV6_DUID_EN) {
651 652 if (olen < sizeof (val32))
652 653 break;
653 654 (void) memcpy(&val32, data, sizeof (val32));
654 655 data += sizeof (val32);
655 656 olen -= sizeof (val32);
656 657 val32 = ntohl(val32);
657 658 (void) snprintf(get_line(0, 0),
658 659 get_line_remain(),
659 660 " Enterprise Number = %lu (%s)", val32,
660 661 entr_to_str(val32));
661 662 }
662 663 if (olen == 0)
663 664 break;
664 665 if ((str = malloc(olen * 3)) == NULL)
665 666 pr_err("interpret_dhcpv6: no mem");
666 667 sp = str + snprintf(str, 3, "%02x", *data++);
667 668 while (--olen > 0) {
668 669 *sp++ = (type == DHCPV6_DUID_LLT ||
669 670 type == DHCPV6_DUID_LL) ? ':' : ' ';
670 671 sp = sp + snprintf(sp, 3, "%02x", *data++);
671 672 }
672 673 (void) snprintf(get_line(0, 0), get_line_remain(),
673 674 (type == DHCPV6_DUID_LLT ||
674 675 type == DHCPV6_DUID_LL) ?
675 676 " Link Layer Address = %s" :
676 677 " Identifier = %s", str);
677 678 free(str);
678 679 break;
679 680 case DHCPV6_OPT_IA_NA:
680 681 case DHCPV6_OPT_IA_PD: {
681 682 dhcpv6_ia_na_t d6in;
682 683
683 684 if (olen < sizeof (d6in) - sizeof (d6o))
684 685 break;
685 686 (void) memcpy(&d6in, data - sizeof (d6o),
686 687 sizeof (d6in));
687 688 data += sizeof (d6in) - sizeof (d6o);
688 689 olen -= sizeof (d6in) - sizeof (d6o);
689 690 (void) snprintf(get_line(0, 0), get_line_remain(),
690 691 " IAID = %u", ntohl(d6in.d6in_iaid));
691 692 (void) snprintf(get_line(0, 0), get_line_remain(),
692 693 " T1 (renew) = %u seconds", ntohl(d6in.d6in_t1));
693 694 (void) snprintf(get_line(0, 0), get_line_remain(),
694 695 " T2 (rebind) = %u seconds", ntohl(d6in.d6in_t2));
695 696 nest_options(data, olen, "IA: ",
696 697 "Identity Association");
697 698 break;
698 699 }
699 700 case DHCPV6_OPT_IA_TA: {
700 701 dhcpv6_ia_ta_t d6it;
701 702
702 703 if (olen < sizeof (d6it) - sizeof (d6o))
703 704 break;
704 705 (void) memcpy(&d6it, data - sizeof (d6o),
705 706 sizeof (d6it));
706 707 data += sizeof (d6it) - sizeof (d6o);
707 708 olen -= sizeof (d6it) - sizeof (d6o);
708 709 (void) snprintf(get_line(0, 0), get_line_remain(),
709 710 " IAID = %u", ntohl(d6it.d6it_iaid));
710 711 nest_options(data, olen, "IA: ",
711 712 "Identity Association");
712 713 break;
713 714 }
714 715 case DHCPV6_OPT_IAADDR: {
715 716 dhcpv6_iaaddr_t d6ia;
716 717
717 718 if (olen < sizeof (d6ia) - sizeof (d6o))
718 719 break;
719 720 (void) memcpy(&d6ia, data - sizeof (d6o),
720 721 sizeof (d6ia));
721 722 data += sizeof (d6ia) - sizeof (d6o);
722 723 olen -= sizeof (d6ia) - sizeof (d6o);
723 724 show_address(" Address", &d6ia.d6ia_addr);
724 725 (void) snprintf(get_line(0, 0), get_line_remain(),
725 726 " Preferred lifetime = %u seconds",
726 727 ntohl(d6ia.d6ia_preflife));
727 728 (void) snprintf(get_line(0, 0), get_line_remain(),
728 729 " Valid lifetime = %u seconds",
729 730 ntohl(d6ia.d6ia_vallife));
730 731 nest_options(data, olen, "ADDR: ", "Address");
731 732 break;
732 733 }
733 734 case DHCPV6_OPT_ORO:
734 735 while (olen >= sizeof (val16)) {
735 736 (void) memcpy(&val16, data, sizeof (val16));
736 737 val16 = ntohs(val16);
737 738 (void) snprintf(get_line(0, 0),
738 739 get_line_remain(),
739 740 " Requested Option Code = %u (%s)", val16,
740 741 option_to_str(val16));
741 742 data += sizeof (val16);
742 743 olen -= sizeof (val16);
743 744 }
744 745 break;
745 746 case DHCPV6_OPT_PREFERENCE:
746 747 if (olen > 0) {
747 748 (void) snprintf(get_line(0, 0),
748 749 get_line_remain(),
749 750 *data == 255 ?
750 751 " Preference = %u (immediate)" :
751 752 " Preference = %u", *data);
752 753 }
753 754 break;
754 755 case DHCPV6_OPT_ELAPSED_TIME:
755 756 if (olen == sizeof (val16)) {
756 757 (void) memcpy(&val16, data, sizeof (val16));
757 758 val16 = ntohs(val16);
758 759 (void) snprintf(get_line(0, 0),
759 760 get_line_remain(),
760 761 " Elapsed Time = %u.%02u seconds",
761 762 val16 / 100, val16 % 100);
762 763 }
763 764 break;
764 765 case DHCPV6_OPT_RELAY_MSG:
765 766 if (olen > 0) {
766 767 oldnest = prot_nest_prefix;
767 768 prot_nest_prefix = prot_prefix;
768 769 retlen = interpret_dhcpv6(F_DTAIL, data, olen);
769 770 prot_prefix = prot_nest_prefix;
770 771 prot_nest_prefix = oldnest;
771 772 }
772 773 break;
773 774 case DHCPV6_OPT_AUTH: {
774 775 dhcpv6_auth_t d6a;
775 776
776 777 if (olen < DHCPV6_AUTH_SIZE - sizeof (d6o))
777 778 break;
778 779 (void) memcpy(&d6a, data - sizeof (d6o),
779 780 DHCPV6_AUTH_SIZE);
780 781 data += DHCPV6_AUTH_SIZE - sizeof (d6o);
781 782 olen += DHCPV6_AUTH_SIZE - sizeof (d6o);
782 783 (void) snprintf(get_line(0, 0), get_line_remain(),
783 784 " Protocol = %u (%s)", d6a.d6a_proto,
784 785 authproto_to_str(d6a.d6a_proto));
785 786 (void) snprintf(get_line(0, 0), get_line_remain(),
786 787 " Algorithm = %u (%s)", d6a.d6a_alg,
787 788 authalg_to_str(d6a.d6a_proto, d6a.d6a_alg));
788 789 (void) snprintf(get_line(0, 0), get_line_remain(),
789 790 " Replay Detection Method = %u (%s)", d6a.d6a_rdm,
790 791 authrdm_to_str(d6a.d6a_rdm));
791 792 show_hex(d6a.d6a_replay, sizeof (d6a.d6a_replay),
792 793 " RDM Data");
793 794 if (olen > 0)
794 795 show_hex(data, olen, " Auth Info");
795 796 break;
796 797 }
797 798 case DHCPV6_OPT_UNICAST:
798 799 if (olen >= sizeof (in6_addr_t))
799 800 show_address(" Server Address", data);
800 801 break;
801 802 case DHCPV6_OPT_STATUS_CODE:
802 803 if (olen < sizeof (val16))
803 804 break;
804 805 (void) memcpy(&val16, data, sizeof (val16));
805 806 val16 = ntohs(val16);
806 807 (void) snprintf(get_line(0, 0), get_line_remain(),
807 808 " Status Code = %u (%s)", val16,
808 809 status_to_str(val16));
809 810 data += sizeof (val16);
810 811 olen -= sizeof (val16);
811 812 if (olen > 0)
812 813 (void) snprintf(get_line(0, 0),
813 814 get_line_remain(), " Text = \"%.*s\"",
814 815 olen, data);
815 816 break;
816 817 case DHCPV6_OPT_VENDOR_CLASS:
817 818 if (olen < sizeof (val32))
818 819 break;
819 820 (void) memcpy(&val32, data, sizeof (val32));
820 821 data += sizeof (val32);
821 822 olen -= sizeof (val32);
822 823 val32 = ntohl(val32);
823 824 (void) snprintf(get_line(0, 0), get_line_remain(),
824 825 " Enterprise Number = %lu (%s)", val32,
825 826 entr_to_str(val32));
826 827 /* FALLTHROUGH */
827 828 case DHCPV6_OPT_USER_CLASS:
828 829 while (olen >= sizeof (val16)) {
829 830 (void) memcpy(&val16, data, sizeof (val16));
830 831 data += sizeof (val16);
831 832 olen -= sizeof (val16);
832 833 val16 = ntohs(val16);
833 834 if (val16 > olen) {
834 835 (void) strlcpy(get_line(0, 0),
835 836 " Truncated class",
836 837 get_line_remain());
837 838 val16 = olen;
838 839 }
839 840 show_hex(data, olen, " Class");
840 841 data += val16;
841 842 olen -= val16;
842 843 }
843 844 break;
844 845 case DHCPV6_OPT_VENDOR_OPT: {
845 846 dhcpv6_option_t sd6o;
846 847
847 848 if (olen < sizeof (val32))
848 849 break;
849 850 (void) memcpy(&val32, data, sizeof (val32));
850 851 data += sizeof (val32);
851 852 olen -= sizeof (val32);
852 853 val32 = ntohl(val32);
853 854 (void) snprintf(get_line(0, 0), get_line_remain(),
854 855 " Enterprise Number = %lu (%s)", val32,
855 856 entr_to_str(val32));
856 857 while (olen >= sizeof (sd6o)) {
857 858 (void) memcpy(&sd6o, data, sizeof (sd6o));
858 859 sd6o.d6o_code = ntohs(sd6o.d6o_code);
859 860 sd6o.d6o_len = ntohs(sd6o.d6o_len);
860 861 (void) snprintf(get_line(0, 0),
861 862 get_line_remain(),
862 863 " Vendor Option Code = %u", d6o.d6o_code);
863 864 data += sizeof (d6o);
864 865 olen -= sizeof (d6o);
865 866 if (sd6o.d6o_len > olen) {
866 867 (void) strlcpy(get_line(0, 0),
867 868 " Vendor Option truncated",
868 869 get_line_remain());
869 870 sd6o.d6o_len = olen;
870 871 }
871 872 if (sd6o.d6o_len > 0) {
872 873 show_hex(data, sd6o.d6o_len,
873 874 " Data");
874 875 data += sd6o.d6o_len;
875 876 olen -= sd6o.d6o_len;
876 877 }
877 878 }
878 879 break;
879 880 }
880 881 case DHCPV6_OPT_REMOTE_ID:
881 882 if (olen < sizeof (val32))
882 883 break;
883 884 (void) memcpy(&val32, data, sizeof (val32));
884 885 data += sizeof (val32);
885 886 olen -= sizeof (val32);
886 887 val32 = ntohl(val32);
887 888 (void) snprintf(get_line(0, 0), get_line_remain(),
888 889 " Enterprise Number = %lu (%s)", val32,
889 890 entr_to_str(val32));
890 891 /* FALLTHROUGH */
891 892 case DHCPV6_OPT_INTERFACE_ID:
892 893 case DHCPV6_OPT_SUBSCRIBER:
893 894 if (olen > 0)
894 895 show_hex(data, olen, " ID");
895 896 break;
896 897 case DHCPV6_OPT_RECONF_MSG:
897 898 if (olen > 0) {
898 899 (void) snprintf(get_line(0, 0),
899 900 get_line_remain(),
900 901 " Message Type = %u (%s)", *data,
901 902 reconf_to_str(*data));
902 903 }
903 904 break;
904 905 case DHCPV6_OPT_SIP_NAMES:
905 906 case DHCPV6_OPT_DNS_SEARCH:
906 907 case DHCPV6_OPT_NIS_DOMAIN:
907 908 case DHCPV6_OPT_BCMCS_SRV_D: {
908 909 dhcp_symbol_t *symp;
909 910 char *sp2;
910 911
911 912 symp = inittab_getbycode(
912 913 ITAB_CAT_STANDARD | ITAB_CAT_V6, ITAB_CONS_SNOOP,
913 914 d6o.d6o_code);
914 915 if (symp != NULL) {
915 916 str = inittab_decode(symp, data, olen, B_TRUE);
916 917 if (str != NULL) {
917 918 sp = str;
918 919 do {
919 920 sp2 = strchr(sp, ' ');
920 921 if (sp2 != NULL)
921 922 *sp2++ = '\0';
922 923 (void) snprintf(get_line(0, 0),
923 924 get_line_remain(),
924 925 " Name = %s", sp);
925 926 } while ((sp = sp2) != NULL);
926 927 free(str);
927 928 }
928 929 free(symp);
929 930 }
930 931 break;
931 932 }
932 933 case DHCPV6_OPT_SIP_ADDR:
933 934 case DHCPV6_OPT_DNS_ADDR:
934 935 case DHCPV6_OPT_NIS_SERVERS:
935 936 case DHCPV6_OPT_SNTP_SERVERS:
936 937 case DHCPV6_OPT_BCMCS_SRV_A:
937 938 while (olen >= sizeof (in6_addr_t)) {
938 939 show_address(" Address", data);
939 940 data += sizeof (in6_addr_t);
940 941 olen -= sizeof (in6_addr_t);
941 942 }
942 943 break;
943 944 case DHCPV6_OPT_IAPREFIX: {
944 945 dhcpv6_iaprefix_t d6ip;
945 946
946 947 if (olen < DHCPV6_IAPREFIX_SIZE - sizeof (d6o))
947 948 break;
948 949 (void) memcpy(&d6ip, data - sizeof (d6o),
949 950 DHCPV6_IAPREFIX_SIZE);
950 951 data += DHCPV6_IAPREFIX_SIZE - sizeof (d6o);
951 952 olen -= DHCPV6_IAPREFIX_SIZE - sizeof (d6o);
952 953 show_address(" Prefix", d6ip.d6ip_addr);
953 954 (void) snprintf(get_line(0, 0), get_line_remain(),
954 955 " Preferred lifetime = %u seconds",
955 956 ntohl(d6ip.d6ip_preflife));
956 957 (void) snprintf(get_line(0, 0), get_line_remain(),
957 958 " Valid lifetime = %u seconds",
958 959 ntohl(d6ip.d6ip_vallife));
959 960 (void) snprintf(get_line(0, 0), get_line_remain(),
960 961 " Prefix length = %u", d6ip.d6ip_preflen);
961 962 nest_options(data, olen, "ADDR: ", "Address");
962 963 break;
963 964 }
964 965 case DHCPV6_OPT_INFO_REFTIME:
965 966 if (olen < sizeof (val32))
966 967 break;
967 968 (void) memcpy(&val32, data, sizeof (val32));
968 969 (void) snprintf(get_line(0, 0), get_line_remain(),
969 970 " Refresh Time = %lu seconds", ntohl(val32));
970 971 break;
971 972 case DHCPV6_OPT_GEOCONF_CVC: {
972 973 dhcpv6_civic_t d6c;
973 974 int solen;
974 975
975 976 if (olen < DHCPV6_CIVIC_SIZE - sizeof (d6o))
976 977 break;
977 978 (void) memcpy(&d6c, data - sizeof (d6o),
978 979 DHCPV6_CIVIC_SIZE);
979 980 data += DHCPV6_CIVIC_SIZE - sizeof (d6o);
980 981 olen -= DHCPV6_CIVIC_SIZE - sizeof (d6o);
981 982 (void) snprintf(get_line(0, 0), get_line_remain(),
982 983 " What Location = %u (%s)", d6c.d6c_what,
983 984 cwhat_to_str(d6c.d6c_what));
984 985 (void) snprintf(get_line(0, 0), get_line_remain(),
985 986 " Country Code = %.*s", sizeof (d6c.d6c_cc),
986 987 d6c.d6c_cc);
987 988 while (olen >= 2) {
988 989 (void) snprintf(get_line(0, 0),
989 990 get_line_remain(),
990 991 " CA Element = %u (%s)", *data,
991 992 catype_to_str(*data));
992 993 solen = data[1];
993 994 data += 2;
994 995 olen -= 2;
995 996 if (solen > olen) {
996 997 (void) strlcpy(get_line(0, 0),
997 998 " CA Element truncated",
998 999 get_line_remain());
999 1000 solen = olen;
1000 1001 }
1001 1002 if (solen > 0) {
1002 1003 show_ascii(data, solen, " CA Data");
1003 1004 data += solen;
1004 1005 olen -= solen;
1005 1006 }
1006 1007 }
1007 1008 break;
1008 1009 }
1009 1010 case DHCPV6_OPT_CLIENT_FQDN: {
1010 1011 dhcp_symbol_t *symp;
1011 1012
1012 1013 if (olen == 0)
1013 1014 break;
1014 1015 (void) snprintf(get_line(0, 0), get_line_remain(),
1015 1016 " Flags = %02x", *data);
1016 1017 (void) snprintf(get_line(0, 0), get_line_remain(),
1017 1018 " %s", getflag(*data, DHCPV6_FQDNF_S,
1018 1019 "Perform AAAA RR updates", "No AAAA RR updates"));
1019 1020 (void) snprintf(get_line(0, 0), get_line_remain(),
1020 1021 " %s", getflag(*data, DHCPV6_FQDNF_O,
1021 1022 "Server override updates",
1022 1023 "No server override updates"));
1023 1024 (void) snprintf(get_line(0, 0), get_line_remain(),
1024 1025 " %s", getflag(*data, DHCPV6_FQDNF_N,
1025 1026 "Server performs no updates",
1026 1027 "Server performs updates"));
1027 1028 symp = inittab_getbycode(
1028 1029 ITAB_CAT_STANDARD | ITAB_CAT_V6, ITAB_CONS_SNOOP,
1029 1030 d6o.d6o_code);
1030 1031 if (symp != NULL) {
1031 1032 str = inittab_decode(symp, data, olen, B_TRUE);
1032 1033 if (str != NULL) {
1033 1034 (void) snprintf(get_line(0, 0),
1034 1035 get_line_remain(),
1035 1036 " FQDN = %s", str);
1036 1037 free(str);
1037 1038 }
1038 1039 free(symp);
1039 1040 }
1040 1041 break;
1041 1042 }
1042 1043 }
1043 1044 data = ostart + d6o.d6o_len;
1044 1045 len -= d6o.d6o_len;
1045 1046 }
1046 1047 if (len != 0) {
1047 1048 (void) strlcpy(get_line(0, 0), "Option entry truncated",
1048 1049 get_line_remain());
1049 1050 }
1050 1051 }
↓ open down ↓ |
406 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX