Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libdhcputil/common/dhcp_inittab.c
+++ new/usr/src/lib/libdhcputil/common/dhcp_inittab.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.
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
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 /*
22 - * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
22 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 26 #include <sys/types.h>
29 27 #include <string.h>
30 28 #include <stdlib.h>
31 29 #include <stdio.h>
32 30 #include <errno.h>
33 31 #include <stdarg.h>
34 32 #include <limits.h>
35 33 #include <ctype.h>
36 34 #include <libgen.h>
37 35 #include <sys/isa_defs.h>
38 36 #include <sys/socket.h>
39 37 #include <net/if_arp.h>
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
40 38 #include <netinet/in.h>
41 39 #include <arpa/inet.h>
42 40 #include <sys/sysmacros.h>
43 41 #include <libinetutil.h>
44 42 #include <libdlpi.h>
45 43 #include <netinet/dhcp6.h>
46 44
47 45 #include "dhcp_symbol.h"
48 46 #include "dhcp_inittab.h"
49 47
50 -static uint64_t dhcp_htonll(uint64_t);
51 -static uint64_t dhcp_ntohll(uint64_t);
52 48 static void inittab_msg(const char *, ...);
53 49 static uchar_t category_to_code(const char *);
54 50 static boolean_t encode_number(uint8_t, uint8_t, boolean_t, uint8_t,
55 51 const char *, uint8_t *, int *);
56 52 static boolean_t decode_number(uint8_t, uint8_t, boolean_t, uint8_t,
57 53 const uint8_t *, char *, int *);
58 54 static dhcp_symbol_t *inittab_lookup(uchar_t, char, const char *, int32_t,
59 55 size_t *);
60 56 static dsym_category_t itabcode_to_dsymcode(uchar_t);
61 57 static boolean_t parse_entry(char *, char **);
62 58
63 59 /*
64 60 * forward declaration of our internal inittab_table[]. too bulky to put
65 61 * up front -- check the end of this file for its definition.
66 62 *
67 63 * Note: we have only an IPv4 version here. The inittab_verify() function is
68 64 * used by the DHCP server and manager. We'll need a new function if the
69 65 * server is extended to DHCPv6.
70 66 */
71 67 static dhcp_symbol_t inittab_table[];
72 68
73 69 /*
74 70 * the number of fields in the inittab and names for the fields. note that
75 71 * this order is meaningful to parse_entry(); other functions should just
76 72 * use them as indexes into the array returned from parse_entry().
77 73 */
78 74 #define ITAB_FIELDS 7
79 75 enum { ITAB_NAME, ITAB_CODE, ITAB_TYPE, ITAB_GRAN, ITAB_MAX, ITAB_CONS,
80 76 ITAB_CAT };
81 77
82 78 /*
83 79 * the category_map_entry_t is used to map the inittab category codes to
84 80 * the dsym codes. the reason the codes are different is that the inittab
85 81 * needs to have the codes be ORable such that queries can retrieve more
86 82 * than one category at a time. this map is also used to map the inittab
87 83 * string representation of a category to its numerical code.
88 84 */
89 85 typedef struct category_map_entry {
90 86 dsym_category_t cme_dsymcode;
91 87 char *cme_name;
92 88 uchar_t cme_itabcode;
93 89 } category_map_entry_t;
94 90
95 91 static category_map_entry_t category_map[] = {
96 92 { DSYM_STANDARD, "STANDARD", ITAB_CAT_STANDARD },
97 93 { DSYM_FIELD, "FIELD", ITAB_CAT_FIELD },
98 94 { DSYM_INTERNAL, "INTERNAL", ITAB_CAT_INTERNAL },
99 95 { DSYM_VENDOR, "VENDOR", ITAB_CAT_VENDOR },
100 96 { DSYM_SITE, "SITE", ITAB_CAT_SITE }
101 97 };
102 98
103 99 /*
104 100 * inittab_load(): returns all inittab entries with the specified criteria
105 101 *
106 102 * input: uchar_t: the categories the consumer is interested in
107 103 * char: the consumer type of the caller
108 104 * size_t *: set to the number of entries returned
109 105 * output: dhcp_symbol_t *: an array of dynamically allocated entries
110 106 * on success, NULL upon failure
111 107 */
112 108
113 109 dhcp_symbol_t *
114 110 inittab_load(uchar_t categories, char consumer, size_t *n_entries)
115 111 {
116 112 return (inittab_lookup(categories, consumer, NULL, -1, n_entries));
117 113 }
118 114
119 115 /*
120 116 * inittab_getbyname(): returns an inittab entry with the specified criteria
121 117 *
122 118 * input: int: the categories the consumer is interested in
123 119 * char: the consumer type of the caller
124 120 * char *: the name of the inittab entry the consumer wants
125 121 * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure
126 122 * on success, NULL upon failure
127 123 */
128 124
129 125 dhcp_symbol_t *
130 126 inittab_getbyname(uchar_t categories, char consumer, const char *name)
131 127 {
132 128 return (inittab_lookup(categories, consumer, name, -1, NULL));
133 129 }
134 130
135 131 /*
136 132 * inittab_getbycode(): returns an inittab entry with the specified criteria
137 133 *
138 134 * input: uchar_t: the categories the consumer is interested in
139 135 * char: the consumer type of the caller
140 136 * uint16_t: the code of the inittab entry the consumer wants
141 137 * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure
142 138 * on success, NULL upon failure
143 139 */
144 140
145 141 dhcp_symbol_t *
146 142 inittab_getbycode(uchar_t categories, char consumer, uint16_t code)
147 143 {
148 144 return (inittab_lookup(categories, consumer, NULL, code, NULL));
149 145 }
150 146
151 147 /*
152 148 * inittab_lookup(): returns inittab entries with the specified criteria
153 149 *
154 150 * input: uchar_t: the categories the consumer is interested in
155 151 * char: the consumer type of the caller
156 152 * const char *: the name of the entry the caller is interested
157 153 * in, or NULL if the caller doesn't care
158 154 * int32_t: the code the caller is interested in, or -1 if the
159 155 * caller doesn't care
160 156 * size_t *: set to the number of entries returned
161 157 * output: dhcp_symbol_t *: dynamically allocated dhcp_symbol structures
162 158 * on success, NULL upon failure
163 159 */
164 160
165 161 static dhcp_symbol_t *
166 162 inittab_lookup(uchar_t categories, char consumer, const char *name,
167 163 int32_t code, size_t *n_entriesp)
168 164 {
169 165 FILE *inittab_fp;
170 166 dhcp_symbol_t *new_entries, *entries = NULL;
171 167 dhcp_symbol_t entry;
172 168 char buffer[ITAB_MAX_LINE_LEN];
173 169 char *fields[ITAB_FIELDS];
174 170 unsigned long line = 0;
175 171 size_t i, n_entries = 0;
176 172 const char *inittab_path;
177 173 uchar_t category_code;
178 174 dsym_cdtype_t type;
179 175
180 176 if (categories & ITAB_CAT_V6) {
181 177 inittab_path = getenv("DHCP_INITTAB6_PATH");
182 178 if (inittab_path == NULL)
183 179 inittab_path = ITAB_INITTAB6_PATH;
184 180 } else {
185 181 inittab_path = getenv("DHCP_INITTAB_PATH");
186 182 if (inittab_path == NULL)
187 183 inittab_path = ITAB_INITTAB_PATH;
188 184 }
189 185
190 186 inittab_fp = fopen(inittab_path, "r");
191 187 if (inittab_fp == NULL) {
192 188 inittab_msg("inittab_lookup: fopen: %s: %s",
193 189 inittab_path, strerror(errno));
194 190 return (NULL);
195 191 }
196 192
197 193 (void) bufsplit(",\n", 0, NULL);
198 194 while (fgets(buffer, sizeof (buffer), inittab_fp) != NULL) {
199 195
200 196 line++;
201 197
202 198 /*
203 199 * make sure the string didn't overflow our buffer
204 200 */
205 201 if (strchr(buffer, '\n') == NULL) {
206 202 inittab_msg("inittab_lookup: line %li: too long, "
207 203 "skipping", line);
208 204 continue;
209 205 }
210 206
211 207 /*
212 208 * skip `pure comment' lines
213 209 */
214 210 for (i = 0; buffer[i] != '\0'; i++)
215 211 if (isspace(buffer[i]) == 0)
216 212 break;
217 213
218 214 if (buffer[i] == ITAB_COMMENT_CHAR || buffer[i] == '\0')
219 215 continue;
220 216
221 217 /*
222 218 * parse the entry out into fields.
223 219 */
224 220 if (parse_entry(buffer, fields) == B_FALSE) {
225 221 inittab_msg("inittab_lookup: line %li: syntax error, "
226 222 "skipping", line);
227 223 continue;
228 224 }
229 225
230 226 /*
231 227 * validate the values in the entries; skip if invalid.
232 228 */
233 229 if (atoi(fields[ITAB_GRAN]) > ITAB_GRAN_MAX) {
234 230 inittab_msg("inittab_lookup: line %li: granularity `%s'"
235 231 " out of range, skipping", line, fields[ITAB_GRAN]);
236 232 continue;
237 233 }
238 234
239 235 if (atoi(fields[ITAB_MAX]) > ITAB_MAX_MAX) {
240 236 inittab_msg("inittab_lookup: line %li: maximum `%s' "
241 237 "out of range, skipping", line, fields[ITAB_MAX]);
242 238 continue;
243 239 }
244 240
245 241 if (dsym_get_type_id(fields[ITAB_TYPE], &type, B_FALSE) !=
246 242 DSYM_SUCCESS) {
247 243 inittab_msg("inittab_lookup: line %li: type `%s' "
248 244 "is invalid, skipping", line, fields[ITAB_TYPE]);
249 245 continue;
250 246 }
251 247
252 248 /*
253 249 * find out whether this entry of interest to our consumer,
254 250 * and if so, throw it onto the set of entries we'll return.
255 251 * check categories last since it's the most expensive check.
256 252 */
257 253 if (strchr(fields[ITAB_CONS], consumer) == NULL)
258 254 continue;
259 255
260 256 if (code != -1 && atoi(fields[ITAB_CODE]) != code)
261 257 continue;
262 258
263 259 if (name != NULL && strcasecmp(fields[ITAB_NAME], name) != 0)
264 260 continue;
265 261
266 262 category_code = category_to_code(fields[ITAB_CAT]);
267 263 if ((category_code & categories) == 0)
268 264 continue;
269 265
270 266 /*
271 267 * looks like a match. allocate an entry and fill it in
272 268 */
273 269 new_entries = realloc(entries, (n_entries + 1) *
274 270 sizeof (dhcp_symbol_t));
275 271
276 272 /*
277 273 * if we run out of memory, might as well return what we can
278 274 */
279 275 if (new_entries == NULL) {
280 276 inittab_msg("inittab_lookup: ran out of memory "
281 277 "allocating dhcp_symbol_t's");
282 278 break;
283 279 }
284 280
285 281 entry.ds_max = atoi(fields[ITAB_MAX]);
286 282 entry.ds_code = atoi(fields[ITAB_CODE]);
287 283 entry.ds_type = type;
288 284 entry.ds_gran = atoi(fields[ITAB_GRAN]);
289 285 entry.ds_category = itabcode_to_dsymcode(category_code);
290 286 entry.ds_classes.dc_cnt = 0;
291 287 entry.ds_classes.dc_names = NULL;
292 288 (void) strlcpy(entry.ds_name, fields[ITAB_NAME],
293 289 sizeof (entry.ds_name));
294 290 entry.ds_dhcpv6 = (categories & ITAB_CAT_V6) ? 1 : 0;
295 291
296 292 entries = new_entries;
297 293 entries[n_entries++] = entry;
298 294 }
299 295
300 296 if (ferror(inittab_fp) != 0) {
301 297 inittab_msg("inittab_lookup: error on inittab stream");
302 298 clearerr(inittab_fp);
303 299 }
304 300
305 301 (void) fclose(inittab_fp);
306 302
307 303 if (n_entriesp != NULL)
308 304 *n_entriesp = n_entries;
309 305
310 306 return (entries);
311 307 }
312 308
313 309 /*
314 310 * parse_entry(): parses an entry out into its constituent fields
315 311 *
316 312 * input: char *: the entry
317 313 * char **: an array of ITAB_FIELDS length which contains
318 314 * pointers into the entry on upon return
319 315 * output: boolean_t: B_TRUE on success, B_FALSE on failure
320 316 */
321 317
322 318 static boolean_t
323 319 parse_entry(char *entry, char **fields)
324 320 {
325 321 char *category, *spacep;
326 322 size_t n_fields, i;
327 323
328 324 /*
329 325 * due to a mistake made long ago, the first and second fields of
330 326 * each entry are not separated by a comma, but rather by
331 327 * whitespace -- have bufsplit() treat the two fields as one, then
332 328 * pull them apart afterwards.
333 329 */
334 330 n_fields = bufsplit(entry, ITAB_FIELDS - 1, fields);
335 331 if (n_fields != (ITAB_FIELDS - 1))
336 332 return (B_FALSE);
337 333
338 334 /*
339 335 * pull the first and second fields apart. this is complicated
340 336 * since the first field can contain embedded whitespace (so we
341 337 * must separate the two fields by the last span of whitespace).
342 338 *
343 339 * first, find the initial span of whitespace. if there isn't one,
344 340 * then the entry is malformed.
345 341 */
346 342 category = strpbrk(fields[ITAB_NAME], " \t");
347 343 if (category == NULL)
348 344 return (B_FALSE);
349 345
350 346 /*
351 347 * find the last span of whitespace.
352 348 */
353 349 do {
354 350 while (isspace(*category))
355 351 category++;
356 352
357 353 spacep = strpbrk(category, " \t");
358 354 if (spacep != NULL)
359 355 category = spacep;
360 356 } while (spacep != NULL);
361 357
362 358 /*
363 359 * NUL-terminate the first byte of the last span of whitespace, so
364 360 * that the first field doesn't have any residual trailing
365 361 * whitespace.
366 362 */
367 363 spacep = category - 1;
368 364 while (isspace(*spacep))
369 365 spacep--;
370 366
371 367 if (spacep <= fields[0])
372 368 return (B_FALSE);
373 369
374 370 *++spacep = '\0';
375 371
376 372 /*
377 373 * remove any whitespace from the fields.
378 374 */
379 375 for (i = 0; i < n_fields; i++) {
380 376 while (isspace(*fields[i]))
381 377 fields[i]++;
382 378 }
383 379 fields[ITAB_CAT] = category;
384 380
385 381 return (B_TRUE);
386 382 }
387 383
388 384 /*
389 385 * inittab_verify(): verifies that a given inittab entry matches an internal
390 386 * definition
391 387 *
392 388 * input: dhcp_symbol_t *: the inittab entry to verify
393 389 * dhcp_symbol_t *: if non-NULL, a place to store the internal
394 390 * inittab entry upon return
395 391 * output: int: ITAB_FAILURE, ITAB_SUCCESS, or ITAB_UNKNOWN
396 392 *
397 393 * notes: IPv4 only
398 394 */
399 395
400 396 int
401 397 inittab_verify(const dhcp_symbol_t *inittab_ent, dhcp_symbol_t *internal_ent)
402 398 {
403 399 unsigned int i;
404 400
405 401 for (i = 0; inittab_table[i].ds_name[0] != '\0'; i++) {
406 402
407 403 if (inittab_ent->ds_category != inittab_table[i].ds_category)
408 404 continue;
409 405
410 406 if (inittab_ent->ds_code == inittab_table[i].ds_code) {
411 407 if (internal_ent != NULL)
412 408 *internal_ent = inittab_table[i];
413 409
414 410 if (inittab_table[i].ds_type != inittab_ent->ds_type ||
415 411 inittab_table[i].ds_gran != inittab_ent->ds_gran ||
416 412 inittab_table[i].ds_max != inittab_ent->ds_max)
417 413 return (ITAB_FAILURE);
418 414
419 415 return (ITAB_SUCCESS);
420 416 }
421 417 }
422 418
423 419 return (ITAB_UNKNOWN);
424 420 }
425 421
426 422 /*
427 423 * get_hw_type(): interpret ",hwtype" in the input string, as part of a DUID.
428 424 * The hwtype string is optional, and must be 0-65535 if
429 425 * present.
430 426 *
431 427 * input: char **: pointer to string pointer
432 428 * int *: error return value
433 429 * output: int: hardware type, or -1 for empty, or -2 for error.
434 430 */
435 431
436 432 static int
437 433 get_hw_type(char **strp, int *ierrnop)
438 434 {
439 435 char *str = *strp;
440 436 ulong_t hwtype;
441 437
442 438 if (*str++ != ',') {
443 439 *ierrnop = ITAB_BAD_NUMBER;
444 440 return (-2);
445 441 }
446 442 if (*str == ',' || *str == '\0') {
447 443 *strp = str;
448 444 return (-1);
449 445 }
450 446 hwtype = strtoul(str, strp, 0);
451 447 if (errno != 0 || *strp == str || hwtype > 65535) {
452 448 *ierrnop = ITAB_BAD_NUMBER;
453 449 return (-2);
454 450 } else {
455 451 return ((int)hwtype);
456 452 }
457 453 }
458 454
459 455 /*
460 456 * get_mac_addr(): interpret ",macaddr" in the input string, as part of a DUID.
461 457 * The 'macaddr' may be a hex string (in any standard format),
462 458 * or the name of a physical interface. If an interface name
463 459 * is given, then the interface type is extracted as well.
464 460 *
465 461 * input: const char *: input string
466 462 * int *: error return value
467 463 * uint16_t *: hardware type output (network byte order)
468 464 * int: hardware type input; -1 for empty
469 465 * uchar_t *: output buffer for MAC address
470 466 * output: int: length of MAC address, or -1 for error
471 467 */
472 468
473 469 static int
474 470 get_mac_addr(const char *str, int *ierrnop, uint16_t *hwret, int hwtype,
475 471 uchar_t *outbuf)
476 472 {
477 473 int maclen;
478 474 int dig, val;
479 475 dlpi_handle_t dh;
480 476 dlpi_info_t dlinfo;
481 477 char chr;
482 478
483 479 if (*str != '\0') {
484 480 if (*str++ != ',')
485 481 goto failed;
486 482 if (dlpi_open(str, &dh, 0) != DLPI_SUCCESS) {
487 483 maclen = 0;
488 484 dig = val = 0;
489 485 /*
490 486 * Allow MAC addresses with separators matching regexp
491 487 * (:|-| *).
492 488 */
493 489 while ((chr = *str++) != '\0') {
494 490 if (isdigit(chr)) {
495 491 val = (val << 4) + chr - '0';
496 492 } else if (isxdigit(chr)) {
497 493 val = (val << 4) + chr -
498 494 (isupper(chr) ? 'A' : 'a') + 10;
499 495 } else if (isspace(chr) && dig == 0) {
500 496 continue;
501 497 } else if (chr == ':' || chr == '-' ||
502 498 isspace(chr)) {
503 499 dig = 1;
504 500 } else {
505 501 goto failed;
506 502 }
507 503 if (++dig == 2) {
508 504 *outbuf++ = val;
509 505 maclen++;
510 506 dig = val = 0;
511 507 }
512 508 }
513 509 } else {
514 510 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) {
515 511 dlpi_close(dh);
516 512 goto failed;
517 513 }
518 514 maclen = dlinfo.di_physaddrlen;
519 515 (void) memcpy(outbuf, dlinfo.di_physaddr, maclen);
520 516 dlpi_close(dh);
521 517 if (hwtype == -1)
522 518 hwtype = dlpi_arptype(dlinfo.di_mactype);
523 519 }
524 520 }
525 521 if (hwtype == -1)
526 522 goto failed;
527 523 *hwret = htons(hwtype);
528 524 return (maclen);
529 525
530 526 failed:
531 527 *ierrnop = ITAB_BAD_NUMBER;
532 528 return (-1);
533 529 }
534 530
535 531 /*
536 532 * inittab_encode_e(): converts a string representation of a given datatype into
537 533 * binary; used for encoding ascii values into a form that
538 534 * can be put in DHCP packets to be sent on the wire.
539 535 *
540 536 * input: const dhcp_symbol_t *: the entry describing the value option
541 537 * const char *: the value to convert
542 538 * uint16_t *: set to the length of the binary data returned
543 539 * boolean_t: if false, return a full DHCP option
544 540 * int *: error return value
545 541 * output: uchar_t *: a dynamically allocated byte array with converted data
546 542 */
547 543
548 544 uchar_t *
549 545 inittab_encode_e(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp,
550 546 boolean_t just_payload, int *ierrnop)
551 547 {
552 548 int hlen = 0;
553 549 uint16_t length;
554 550 uchar_t n_entries = 0;
555 551 const char *valuep;
556 552 char *currp;
557 553 uchar_t *result = NULL;
558 554 uchar_t *optstart;
559 555 unsigned int i;
560 556 uint8_t type_size = inittab_type_to_size(ie);
561 557 boolean_t is_signed;
562 558 uint_t vallen, reslen;
563 559 dhcpv6_option_t *d6o;
564 560 int type;
565 561 char *cp2;
566 562
567 563 *ierrnop = 0;
568 564 if (type_size == 0) {
569 565 *ierrnop = ITAB_SYNTAX_ERROR;
570 566 return (NULL);
571 567 }
572 568
573 569 switch (ie->ds_type) {
574 570 case DSYM_ASCII:
575 571 n_entries = strlen(value); /* no NUL */
576 572 break;
577 573
578 574 case DSYM_OCTET:
579 575 vallen = strlen(value);
580 576 n_entries = vallen / 2;
581 577 n_entries += vallen % 2;
582 578 break;
583 579
584 580 case DSYM_DOMAIN:
585 581 /*
586 582 * Maximum (worst-case) encoded length is one byte more than
587 583 * the number of characters on input.
588 584 */
589 585 n_entries = strlen(value) + 1;
590 586 break;
591 587
592 588 case DSYM_DUID:
593 589 /* Worst case is ":::::" */
594 590 n_entries = strlen(value);
595 591 if (n_entries < DLPI_PHYSADDR_MAX)
596 592 n_entries = DLPI_PHYSADDR_MAX;
597 593 n_entries += sizeof (duid_llt_t);
598 594 break;
599 595
600 596 default:
601 597 /*
602 598 * figure out the number of entries by counting the spaces
603 599 * in the value string
604 600 */
605 601 for (valuep = value; valuep++ != NULL; n_entries++)
606 602 valuep = strchr(valuep, ' ');
607 603 break;
608 604 }
609 605
610 606 /*
611 607 * if we're gonna return a complete option, then include the
612 608 * option length and code in the size of the packet we allocate
613 609 */
614 610 if (!just_payload)
615 611 hlen = ie->ds_dhcpv6 ? sizeof (*d6o) : 2;
616 612
617 613 length = n_entries * type_size;
618 614 if (hlen + length > 0)
619 615 result = malloc(hlen + length);
620 616
621 617 if ((optstart = result) != NULL && !just_payload)
622 618 optstart += hlen;
623 619
624 620 switch (ie->ds_type) {
625 621
626 622 case DSYM_ASCII:
627 623
628 624 if (optstart == NULL) {
629 625 *ierrnop = ITAB_NOMEM;
630 626 return (NULL);
631 627 }
632 628
633 629 (void) memcpy(optstart, value, length);
634 630 break;
635 631
636 632 case DSYM_DOMAIN:
637 633 if (optstart == NULL) {
638 634 *ierrnop = ITAB_NOMEM;
639 635 return (NULL);
640 636 }
641 637
642 638 /*
643 639 * Note that this encoder always presents the trailing 0-octet
644 640 * when dealing with a list. This means that you can't have
645 641 * non-fully-qualified members anywhere but at the end of a
646 642 * list (or as the only member of the list).
647 643 */
648 644 valuep = value;
649 645 while (*valuep != '\0') {
650 646 int dig, val, inchr;
651 647 boolean_t escape;
652 648 uchar_t *flen;
653 649
654 650 /*
655 651 * Skip over whitespace that delimits list members.
656 652 */
657 653 if (isascii(*valuep) && isspace(*valuep)) {
658 654 valuep++;
659 655 continue;
660 656 }
661 657 dig = val = 0;
662 658 escape = B_FALSE;
663 659 flen = optstart++;
664 660 while ((inchr = *valuep) != '\0') {
665 661 valuep++;
666 662 /*
667 663 * Just copy non-ASCII text directly to the
668 664 * output string. This simplifies the use of
669 665 * other ctype macros below, as, unlike the
670 666 * special isascii function, they don't handle
671 667 * non-ASCII.
672 668 */
673 669 if (!isascii(inchr)) {
674 670 escape = B_FALSE;
675 671 *optstart++ = inchr;
676 672 continue;
677 673 }
678 674 if (escape) {
679 675 /*
680 676 * Handle any of \D, \DD, or \DDD for
681 677 * a digit escape.
682 678 */
683 679 if (isdigit(inchr)) {
684 680 val = val * 10 + inchr - '0';
685 681 if (++dig == 3) {
686 682 *optstart++ = val;
687 683 dig = val = 0;
688 684 escape = B_FALSE;
689 685 }
690 686 continue;
691 687 } else if (dig > 0) {
692 688 /*
693 689 * User terminated \D or \DD
694 690 * with non-digit. An error,
695 691 * but we can assume he means
696 692 * to treat as \00D or \0DD.
697 693 */
698 694 *optstart++ = val;
699 695 dig = val = 0;
700 696 }
701 697 /* Fall through and copy character */
702 698 escape = B_FALSE;
703 699 } else if (inchr == '\\') {
704 700 escape = B_TRUE;
705 701 continue;
706 702 } else if (inchr == '.') {
707 703 /*
708 704 * End of component. Write the length
709 705 * prefix. If the component is zero
710 706 * length (i.e., ".."), the just omit
711 707 * it.
712 708 */
713 709 *flen = (optstart - flen) - 1;
714 710 if (*flen > 0)
715 711 flen = optstart++;
716 712 continue;
717 713 } else if (isspace(inchr)) {
718 714 /*
719 715 * Unescaped space; end of domain name
720 716 * in list.
721 717 */
722 718 break;
723 719 }
724 720 *optstart++ = inchr;
725 721 }
726 722 /*
727 723 * Handle trailing escape sequence. If string ends
728 724 * with \, then assume user wants \ at end of encoded
729 725 * string. If it ends with \D or \DD, assume \00D or
730 726 * \0DD.
731 727 */
732 728 if (escape)
733 729 *optstart++ = dig > 0 ? val : '\\';
734 730 *flen = (optstart - flen) - 1;
735 731 /*
736 732 * If user specified FQDN with trailing '.', then above
737 733 * will result in zero for the last component length.
738 734 * We're done, and optstart already points to the start
739 735 * of the next in list. Otherwise, we need to write a
740 736 * single zero byte to end the entry, if there are more
741 737 * entries that will be decoded.
742 738 */
743 739 while (isascii(*valuep) && isspace(*valuep))
744 740 valuep++;
745 741 if (*flen > 0 && *valuep != '\0')
746 742 *optstart++ = '\0';
747 743 }
748 744 length = (optstart - result) - hlen;
749 745 break;
750 746
751 747 case DSYM_DUID:
752 748 if (optstart == NULL) {
753 749 *ierrnop = ITAB_NOMEM;
754 750 return (NULL);
755 751 }
756 752
757 753 errno = 0;
758 754 type = strtoul(value, &currp, 0);
759 755 if (errno != 0 || value == currp || type > 65535 ||
760 756 (*currp != ',' && *currp != '\0')) {
761 757 free(result);
762 758 *ierrnop = ITAB_BAD_NUMBER;
763 759 return (NULL);
764 760 }
765 761 switch (type) {
766 762 case DHCPV6_DUID_LLT: {
767 763 duid_llt_t dllt;
768 764 int hwtype;
769 765 ulong_t tstamp;
770 766 int maclen;
771 767
772 768 if ((hwtype = get_hw_type(&currp, ierrnop)) == -2) {
773 769 free(result);
774 770 return (NULL);
775 771 }
776 772 if (*currp++ != ',') {
777 773 free(result);
778 774 *ierrnop = ITAB_BAD_NUMBER;
779 775 return (NULL);
780 776 }
781 777 if (*currp == ',' || *currp == '\0') {
782 778 tstamp = time(NULL) - DUID_TIME_BASE;
783 779 } else {
784 780 tstamp = strtoul(currp, &cp2, 0);
785 781 if (errno != 0 || currp == cp2) {
786 782 free(result);
787 783 *ierrnop = ITAB_BAD_NUMBER;
788 784 return (NULL);
789 785 }
790 786 currp = cp2;
791 787 }
792 788 maclen = get_mac_addr(currp, ierrnop,
793 789 &dllt.dllt_hwtype, hwtype,
794 790 optstart + sizeof (dllt));
795 791 if (maclen == -1) {
796 792 free(result);
797 793 return (NULL);
798 794 }
799 795 dllt.dllt_dutype = htons(type);
800 796 dllt.dllt_time = htonl(tstamp);
801 797 (void) memcpy(optstart, &dllt, sizeof (dllt));
802 798 length = maclen + sizeof (dllt);
803 799 break;
804 800 }
805 801 case DHCPV6_DUID_EN: {
806 802 duid_en_t den;
807 803 ulong_t enterp;
808 804
809 805 if (*currp++ != ',') {
810 806 free(result);
811 807 *ierrnop = ITAB_BAD_NUMBER;
812 808 return (NULL);
813 809 }
814 810 enterp = strtoul(currp, &cp2, 0);
815 811 DHCPV6_SET_ENTNUM(&den, enterp);
816 812 if (errno != 0 || currp == cp2 ||
817 813 enterp != DHCPV6_GET_ENTNUM(&den) ||
818 814 (*cp2 != ',' && *cp2 != '\0')) {
819 815 free(result);
820 816 *ierrnop = ITAB_BAD_NUMBER;
821 817 return (NULL);
822 818 }
823 819 if (*cp2 == ',')
824 820 cp2++;
825 821 vallen = strlen(cp2);
826 822 reslen = (vallen + 1) / 2;
827 823 if (hexascii_to_octet(cp2, vallen,
828 824 optstart + sizeof (den), &reslen) != 0) {
829 825 free(result);
830 826 *ierrnop = ITAB_BAD_NUMBER;
831 827 return (NULL);
832 828 }
833 829 den.den_dutype = htons(type);
834 830 (void) memcpy(optstart, &den, sizeof (den));
835 831 length = reslen + sizeof (den);
836 832 break;
837 833 }
838 834 case DHCPV6_DUID_LL: {
839 835 duid_ll_t dll;
840 836 int hwtype;
841 837 int maclen;
842 838
843 839 if ((hwtype = get_hw_type(&currp, ierrnop)) == -2) {
844 840 free(result);
845 841 return (NULL);
846 842 }
847 843 maclen = get_mac_addr(currp, ierrnop, &dll.dll_hwtype,
848 844 hwtype, optstart + sizeof (dll));
849 845 if (maclen == -1) {
850 846 free(result);
851 847 return (NULL);
852 848 }
853 849 dll.dll_dutype = htons(type);
854 850 (void) memcpy(optstart, &dll, sizeof (dll));
855 851 length = maclen + sizeof (dll);
856 852 break;
857 853 }
858 854 default:
859 855 if (*currp == ',')
860 856 currp++;
861 857 vallen = strlen(currp);
862 858 reslen = (vallen + 1) / 2;
863 859 if (hexascii_to_octet(currp, vallen, optstart + 2,
864 860 &reslen) != 0) {
865 861 free(result);
866 862 *ierrnop = ITAB_BAD_NUMBER;
867 863 return (NULL);
868 864 }
869 865 optstart[0] = type >> 8;
870 866 optstart[1] = type;
871 867 length = reslen + 2;
872 868 break;
873 869 }
874 870 break;
875 871
876 872 case DSYM_OCTET:
877 873
878 874 if (optstart == NULL) {
879 875 *ierrnop = ITAB_BAD_OCTET;
880 876 return (NULL);
881 877 }
882 878
883 879 reslen = length;
884 880 /* Call libinetutil function to decode */
885 881 if (hexascii_to_octet(value, vallen, optstart, &reslen) != 0) {
886 882 free(result);
887 883 *ierrnop = ITAB_BAD_OCTET;
888 884 return (NULL);
889 885 }
890 886 break;
891 887
892 888 case DSYM_IP:
893 889 case DSYM_IPV6:
894 890
895 891 if (optstart == NULL) {
896 892 *ierrnop = ITAB_BAD_IPADDR;
897 893 return (NULL);
898 894 }
899 895 if (n_entries % ie->ds_gran != 0) {
900 896 *ierrnop = ITAB_BAD_GRAN;
901 897 inittab_msg("inittab_encode: number of entries "
902 898 "not compatible with option granularity");
903 899 free(result);
904 900 return (NULL);
905 901 }
906 902
907 903 for (valuep = value, i = 0; i < n_entries; i++, valuep++) {
908 904
909 905 currp = strchr(valuep, ' ');
910 906 if (currp != NULL)
911 907 *currp = '\0';
912 908 if (inet_pton(ie->ds_type == DSYM_IP ? AF_INET :
913 909 AF_INET6, valuep, optstart) != 1) {
914 910 *ierrnop = ITAB_BAD_IPADDR;
915 911 inittab_msg("inittab_encode: bogus ip address");
916 912 free(result);
917 913 return (NULL);
918 914 }
919 915
920 916 valuep = currp;
921 917 if (valuep == NULL) {
922 918 if (i < (n_entries - 1)) {
923 919 *ierrnop = ITAB_NOT_ENOUGH_IP;
924 920 inittab_msg("inittab_encode: too few "
925 921 "ip addresses");
926 922 free(result);
927 923 return (NULL);
928 924 }
929 925 break;
930 926 }
931 927 optstart += type_size;
932 928 }
933 929 break;
934 930
935 931 case DSYM_NUMBER: /* FALLTHRU */
936 932 case DSYM_UNUMBER8: /* FALLTHRU */
937 933 case DSYM_SNUMBER8: /* FALLTHRU */
938 934 case DSYM_UNUMBER16: /* FALLTHRU */
939 935 case DSYM_SNUMBER16: /* FALLTHRU */
940 936 case DSYM_UNUMBER24: /* FALLTHRU */
941 937 case DSYM_UNUMBER32: /* FALLTHRU */
942 938 case DSYM_SNUMBER32: /* FALLTHRU */
943 939 case DSYM_UNUMBER64: /* FALLTHRU */
944 940 case DSYM_SNUMBER64:
945 941
946 942 if (optstart == NULL) {
947 943 *ierrnop = ITAB_BAD_NUMBER;
948 944 return (NULL);
949 945 }
950 946
951 947 is_signed = (ie->ds_type == DSYM_SNUMBER64 ||
952 948 ie->ds_type == DSYM_SNUMBER32 ||
953 949 ie->ds_type == DSYM_SNUMBER16 ||
954 950 ie->ds_type == DSYM_SNUMBER8);
955 951
956 952 if (encode_number(n_entries, type_size, is_signed, 0, value,
957 953 optstart, ierrnop) == B_FALSE) {
958 954 free(result);
959 955 return (NULL);
960 956 }
961 957 break;
962 958
963 959 default:
964 960 if (ie->ds_type == DSYM_BOOL)
965 961 *ierrnop = ITAB_BAD_BOOLEAN;
966 962 else
967 963 *ierrnop = ITAB_SYNTAX_ERROR;
968 964
969 965 inittab_msg("inittab_encode: unsupported type `%d'",
970 966 ie->ds_type);
971 967
972 968 free(result);
973 969 return (NULL);
974 970 }
975 971
976 972 /*
977 973 * if just_payload is false, then we need to add the option
978 974 * code and length fields in.
979 975 */
980 976 if (!just_payload) {
981 977 if (ie->ds_dhcpv6) {
982 978 /* LINTED: alignment */
983 979 d6o = (dhcpv6_option_t *)result;
984 980 d6o->d6o_code = htons(ie->ds_code);
985 981 d6o->d6o_len = htons(length);
986 982 } else {
987 983 result[0] = ie->ds_code;
988 984 result[1] = length;
989 985 }
990 986 }
991 987
992 988 if (lengthp != NULL)
993 989 *lengthp = length + hlen;
994 990
995 991 return (result);
996 992 }
997 993
998 994 /*
999 995 * inittab_decode_e(): converts a binary representation of a given datatype into
1000 996 * a string; used for decoding DHCP options in a packet off
1001 997 * the wire into ascii
1002 998 *
1003 999 * input: dhcp_symbol_t *: the entry describing the payload option
1004 1000 * uchar_t *: the payload to convert
1005 1001 * uint16_t: the payload length (only used if just_payload is true)
1006 1002 * boolean_t: if false, payload is assumed to be a DHCP option
1007 1003 * int *: set to extended error code if error occurs.
1008 1004 * output: char *: a dynamically allocated string containing the converted data
1009 1005 */
1010 1006
1011 1007 char *
1012 1008 inittab_decode_e(const dhcp_symbol_t *ie, const uchar_t *payload,
1013 1009 uint16_t length, boolean_t just_payload, int *ierrnop)
1014 1010 {
1015 1011 char *resultp, *result = NULL;
1016 1012 uint_t n_entries;
1017 1013 struct in_addr in_addr;
1018 1014 in6_addr_t in6_addr;
1019 1015 uint8_t type_size = inittab_type_to_size(ie);
1020 1016 boolean_t is_signed;
1021 1017 int type;
1022 1018
1023 1019 *ierrnop = 0;
1024 1020 if (type_size == 0) {
1025 1021 *ierrnop = ITAB_SYNTAX_ERROR;
1026 1022 return (NULL);
1027 1023 }
1028 1024
1029 1025 if (!just_payload) {
1030 1026 if (ie->ds_dhcpv6) {
1031 1027 dhcpv6_option_t d6o;
1032 1028
1033 1029 (void) memcpy(&d6o, payload, sizeof (d6o));
1034 1030 length = ntohs(d6o.d6o_len);
1035 1031 payload += sizeof (d6o);
1036 1032 } else {
1037 1033 length = payload[1];
1038 1034 payload += 2;
1039 1035 }
1040 1036 }
1041 1037
1042 1038 /*
1043 1039 * figure out the number of elements to convert. note that
1044 1040 * for ds_type NUMBER, the granularity is really 1 since the
1045 1041 * value of ds_gran is the number of bytes in the number.
1046 1042 */
1047 1043 if (ie->ds_type == DSYM_NUMBER)
1048 1044 n_entries = MIN(ie->ds_max, length / type_size);
1049 1045 else
1050 1046 n_entries = MIN(ie->ds_max * ie->ds_gran, length / type_size);
1051 1047
1052 1048 if (n_entries == 0)
1053 1049 n_entries = length / type_size;
1054 1050
1055 1051 if ((length % type_size) != 0) {
1056 1052 inittab_msg("inittab_decode: length of string not compatible "
1057 1053 "with option type `%i'", ie->ds_type);
1058 1054 *ierrnop = ITAB_BAD_STRING;
1059 1055 return (NULL);
1060 1056 }
1061 1057
1062 1058 switch (ie->ds_type) {
1063 1059
1064 1060 case DSYM_ASCII:
1065 1061
1066 1062 result = malloc(n_entries + 1);
1067 1063 if (result == NULL) {
1068 1064 *ierrnop = ITAB_NOMEM;
1069 1065 return (NULL);
1070 1066 }
1071 1067
1072 1068 (void) memcpy(result, payload, n_entries);
1073 1069 result[n_entries] = '\0';
1074 1070 break;
1075 1071
1076 1072 case DSYM_DOMAIN:
1077 1073
1078 1074 /*
1079 1075 * A valid, decoded RFC 1035 domain string or sequence of
1080 1076 * strings is always the same size as the encoded form, but we
1081 1077 * allow for RFC 1035 \DDD and \\ and \. escaping.
1082 1078 *
1083 1079 * Decoding stops at the end of the input or the first coding
1084 1080 * violation. Coding violations result in discarding the
1085 1081 * offending list entry entirely. Note that we ignore the 255
1086 1082 * character overall limit on domain names.
1087 1083 */
1088 1084 if ((result = malloc(4 * length + 1)) == NULL) {
1089 1085 *ierrnop = ITAB_NOMEM;
1090 1086 return (NULL);
1091 1087 }
1092 1088 resultp = result;
1093 1089 while (length > 0) {
1094 1090 char *dstart;
1095 1091 int slen;
1096 1092
1097 1093 dstart = resultp;
1098 1094 while (length > 0) {
1099 1095 slen = *payload++;
1100 1096 length--;
1101 1097 /* Upper two bits of length must be zero */
1102 1098 if ((slen & 0xc0) != 0 || slen > length) {
1103 1099 length = 0;
1104 1100 resultp = dstart;
1105 1101 break;
1106 1102 }
1107 1103 if (resultp != dstart)
1108 1104 *resultp++ = '.';
1109 1105 if (slen == 0)
1110 1106 break;
1111 1107 length -= slen;
1112 1108 while (slen > 0) {
1113 1109 if (!isascii(*payload) ||
1114 1110 !isgraph(*payload)) {
1115 1111 (void) snprintf(resultp, 5,
1116 1112 "\\%03d",
1117 1113 *(unsigned char *)payload);
1118 1114 resultp += 4;
1119 1115 payload++;
1120 1116 } else {
1121 1117 if (*payload == '.' ||
1122 1118 *payload == '\\')
1123 1119 *resultp++ = '\\';
1124 1120 *resultp++ = *payload++;
1125 1121 }
1126 1122 slen--;
1127 1123 }
1128 1124 }
1129 1125 if (resultp != dstart && length > 0)
1130 1126 *resultp++ = ' ';
1131 1127 }
1132 1128 *resultp = '\0';
1133 1129 break;
1134 1130
1135 1131 case DSYM_DUID:
1136 1132
1137 1133 /*
1138 1134 * First, determine the type of DUID. We need at least two
1139 1135 * octets worth of data to grab the type code. Once we have
1140 1136 * that, the number of octets required for representation
1141 1137 * depends on the type.
1142 1138 */
1143 1139
1144 1140 if (length < 2) {
1145 1141 *ierrnop = ITAB_BAD_GRAN;
1146 1142 return (NULL);
1147 1143 }
1148 1144 type = (payload[0] << 8) + payload[1];
1149 1145 switch (type) {
1150 1146 case DHCPV6_DUID_LLT: {
1151 1147 duid_llt_t dllt;
1152 1148
1153 1149 if (length < sizeof (dllt)) {
1154 1150 *ierrnop = ITAB_BAD_GRAN;
1155 1151 return (NULL);
1156 1152 }
1157 1153 (void) memcpy(&dllt, payload, sizeof (dllt));
1158 1154 payload += sizeof (dllt);
1159 1155 length -= sizeof (dllt);
1160 1156 n_entries = sizeof ("1,65535,4294967295,") +
1161 1157 length * 3;
1162 1158 if ((result = malloc(n_entries)) == NULL) {
1163 1159 *ierrnop = ITAB_NOMEM;
1164 1160 return (NULL);
1165 1161 }
1166 1162 (void) snprintf(result, n_entries, "%d,%u,%u,", type,
1167 1163 ntohs(dllt.dllt_hwtype), ntohl(dllt.dllt_time));
1168 1164 break;
1169 1165 }
1170 1166 case DHCPV6_DUID_EN: {
1171 1167 duid_en_t den;
1172 1168
1173 1169 if (length < sizeof (den)) {
1174 1170 *ierrnop = ITAB_BAD_GRAN;
1175 1171 return (NULL);
1176 1172 }
1177 1173 (void) memcpy(&den, payload, sizeof (den));
1178 1174 payload += sizeof (den);
1179 1175 length -= sizeof (den);
1180 1176 n_entries = sizeof ("2,4294967295,") + length * 2;
1181 1177 if ((result = malloc(n_entries)) == NULL) {
1182 1178 *ierrnop = ITAB_NOMEM;
1183 1179 return (NULL);
1184 1180 }
1185 1181 (void) snprintf(result, n_entries, "%d,%u,", type,
1186 1182 DHCPV6_GET_ENTNUM(&den));
1187 1183 break;
1188 1184 }
1189 1185 case DHCPV6_DUID_LL: {
1190 1186 duid_ll_t dll;
1191 1187
1192 1188 if (length < sizeof (dll)) {
1193 1189 *ierrnop = ITAB_BAD_GRAN;
1194 1190 return (NULL);
1195 1191 }
1196 1192 (void) memcpy(&dll, payload, sizeof (dll));
1197 1193 payload += sizeof (dll);
1198 1194 length -= sizeof (dll);
1199 1195 n_entries = sizeof ("3,65535,") + length * 3;
1200 1196 if ((result = malloc(n_entries)) == NULL) {
1201 1197 *ierrnop = ITAB_NOMEM;
1202 1198 return (NULL);
1203 1199 }
1204 1200 (void) snprintf(result, n_entries, "%d,%u,", type,
1205 1201 ntohs(dll.dll_hwtype));
1206 1202 break;
1207 1203 }
1208 1204 default:
1209 1205 n_entries = sizeof ("0,") + length * 2;
1210 1206 if ((result = malloc(n_entries)) == NULL) {
1211 1207 *ierrnop = ITAB_NOMEM;
1212 1208 return (NULL);
1213 1209 }
1214 1210 (void) snprintf(result, n_entries, "%d,", type);
1215 1211 break;
1216 1212 }
1217 1213 resultp = result + strlen(result);
1218 1214 n_entries -= strlen(result);
1219 1215 if (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) {
1220 1216 if (length > 0) {
1221 1217 resultp += snprintf(resultp, 3, "%02X",
1222 1218 *payload++);
1223 1219 length--;
1224 1220 }
1225 1221 while (length-- > 0) {
1226 1222 resultp += snprintf(resultp, 4, ":%02X",
1227 1223 *payload++);
1228 1224 }
1229 1225 } else {
1230 1226 while (length-- > 0) {
1231 1227 resultp += snprintf(resultp, 3, "%02X",
1232 1228 *payload++);
1233 1229 }
1234 1230 }
1235 1231 break;
1236 1232
1237 1233 case DSYM_OCTET:
1238 1234
1239 1235 result = malloc(n_entries * (sizeof ("0xNN") + 1));
1240 1236 if (result == NULL) {
1241 1237 *ierrnop = ITAB_NOMEM;
1242 1238 return (NULL);
1243 1239 }
1244 1240
1245 1241 result[0] = '\0';
1246 1242 resultp = result;
1247 1243 if (n_entries > 0) {
1248 1244 resultp += sprintf(resultp, "0x%02X", *payload++);
1249 1245 n_entries--;
1250 1246 }
1251 1247 while (n_entries-- > 0)
1252 1248 resultp += sprintf(resultp, " 0x%02X", *payload++);
1253 1249
1254 1250 break;
1255 1251
1256 1252 case DSYM_IP:
1257 1253 case DSYM_IPV6:
1258 1254 if ((length / type_size) % ie->ds_gran != 0) {
1259 1255 *ierrnop = ITAB_BAD_GRAN;
1260 1256 inittab_msg("inittab_decode: number of entries "
1261 1257 "not compatible with option granularity");
1262 1258 return (NULL);
1263 1259 }
1264 1260
1265 1261 result = malloc(n_entries * (ie->ds_type == DSYM_IP ?
1266 1262 INET_ADDRSTRLEN : INET6_ADDRSTRLEN));
1267 1263 if (result == NULL) {
1268 1264 *ierrnop = ITAB_NOMEM;
1269 1265 return (NULL);
1270 1266 }
1271 1267
1272 1268 for (resultp = result; n_entries != 0; n_entries--) {
1273 1269 if (ie->ds_type == DSYM_IP) {
1274 1270 (void) memcpy(&in_addr.s_addr, payload,
1275 1271 sizeof (ipaddr_t));
1276 1272 (void) strcpy(resultp, inet_ntoa(in_addr));
1277 1273 } else {
1278 1274 (void) memcpy(&in6_addr, payload,
1279 1275 sizeof (in6_addr));
1280 1276 (void) inet_ntop(AF_INET6, &in6_addr, resultp,
1281 1277 INET6_ADDRSTRLEN);
1282 1278 }
1283 1279 resultp += strlen(resultp);
1284 1280 if (n_entries > 1)
1285 1281 *resultp++ = ' ';
1286 1282 payload += type_size;
1287 1283 }
1288 1284 *resultp = '\0';
1289 1285 break;
1290 1286
1291 1287 case DSYM_NUMBER: /* FALLTHRU */
1292 1288 case DSYM_UNUMBER8: /* FALLTHRU */
1293 1289 case DSYM_SNUMBER8: /* FALLTHRU */
1294 1290 case DSYM_UNUMBER16: /* FALLTHRU */
1295 1291 case DSYM_SNUMBER16: /* FALLTHRU */
1296 1292 case DSYM_UNUMBER32: /* FALLTHRU */
1297 1293 case DSYM_SNUMBER32: /* FALLTHRU */
1298 1294 case DSYM_UNUMBER64: /* FALLTHRU */
1299 1295 case DSYM_SNUMBER64:
1300 1296
1301 1297 is_signed = (ie->ds_type == DSYM_SNUMBER64 ||
1302 1298 ie->ds_type == DSYM_SNUMBER32 ||
1303 1299 ie->ds_type == DSYM_SNUMBER16 ||
1304 1300 ie->ds_type == DSYM_SNUMBER8);
1305 1301
1306 1302 result = malloc(n_entries * ITAB_MAX_NUMBER_LEN);
1307 1303 if (result == NULL) {
1308 1304 *ierrnop = ITAB_NOMEM;
1309 1305 return (NULL);
1310 1306 }
1311 1307
1312 1308 if (decode_number(n_entries, type_size, is_signed, ie->ds_gran,
1313 1309 payload, result, ierrnop) == B_FALSE) {
1314 1310 free(result);
1315 1311 return (NULL);
1316 1312 }
1317 1313 break;
1318 1314
1319 1315 default:
1320 1316 inittab_msg("inittab_decode: unsupported type `%d'",
1321 1317 ie->ds_type);
1322 1318 break;
1323 1319 }
1324 1320
1325 1321 return (result);
1326 1322 }
1327 1323
1328 1324 /*
1329 1325 * inittab_encode(): converts a string representation of a given datatype into
1330 1326 * binary; used for encoding ascii values into a form that
1331 1327 * can be put in DHCP packets to be sent on the wire.
1332 1328 *
1333 1329 * input: dhcp_symbol_t *: the entry describing the value option
1334 1330 * const char *: the value to convert
1335 1331 * uint16_t *: set to the length of the binary data returned
1336 1332 * boolean_t: if false, return a full DHCP option
1337 1333 * output: uchar_t *: a dynamically allocated byte array with converted data
1338 1334 */
1339 1335
1340 1336 uchar_t *
1341 1337 inittab_encode(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp,
1342 1338 boolean_t just_payload)
1343 1339 {
1344 1340 int ierrno;
1345 1341
1346 1342 return (inittab_encode_e(ie, value, lengthp, just_payload, &ierrno));
1347 1343 }
1348 1344
1349 1345 /*
1350 1346 * inittab_decode(): converts a binary representation of a given datatype into
1351 1347 * a string; used for decoding DHCP options in a packet off
1352 1348 * the wire into ascii
1353 1349 *
1354 1350 * input: dhcp_symbol_t *: the entry describing the payload option
1355 1351 * uchar_t *: the payload to convert
1356 1352 * uint16_t: the payload length (only used if just_payload is true)
1357 1353 * boolean_t: if false, payload is assumed to be a DHCP option
1358 1354 * output: char *: a dynamically allocated string containing the converted data
1359 1355 */
1360 1356
1361 1357 char *
1362 1358 inittab_decode(const dhcp_symbol_t *ie, const uchar_t *payload, uint16_t length,
1363 1359 boolean_t just_payload)
1364 1360 {
1365 1361 int ierrno;
1366 1362
1367 1363 return (inittab_decode_e(ie, payload, length, just_payload, &ierrno));
1368 1364 }
1369 1365
1370 1366 /*
1371 1367 * inittab_msg(): prints diagnostic messages if INITTAB_DEBUG is set
1372 1368 *
1373 1369 * const char *: a printf-like format string
1374 1370 * ...: arguments to the format string
1375 1371 * output: void
1376 1372 */
1377 1373
1378 1374 /*PRINTFLIKE1*/
1379 1375 static void
1380 1376 inittab_msg(const char *fmt, ...)
1381 1377 {
1382 1378 enum { INITTAB_MSG_CHECK, INITTAB_MSG_RETURN, INITTAB_MSG_OUTPUT };
1383 1379
1384 1380 va_list ap;
1385 1381 char buf[512];
1386 1382 static int action = INITTAB_MSG_CHECK;
1387 1383
1388 1384 /*
1389 1385 * check DHCP_INITTAB_DEBUG the first time in; thereafter, use
1390 1386 * the the cached result (stored in `action').
1391 1387 */
1392 1388 switch (action) {
1393 1389
1394 1390 case INITTAB_MSG_CHECK:
1395 1391
1396 1392 if (getenv("DHCP_INITTAB_DEBUG") == NULL) {
1397 1393 action = INITTAB_MSG_RETURN;
1398 1394 return;
1399 1395 }
1400 1396
1401 1397 action = INITTAB_MSG_OUTPUT;
1402 1398
1403 1399 /* FALLTHRU into INITTAB_MSG_OUTPUT */
1404 1400
1405 1401 case INITTAB_MSG_OUTPUT:
1406 1402
1407 1403 va_start(ap, fmt);
1408 1404
1409 1405 (void) snprintf(buf, sizeof (buf), "inittab: %s\n", fmt);
1410 1406 (void) vfprintf(stderr, buf, ap);
1411 1407
1412 1408 va_end(ap);
1413 1409 break;
1414 1410
1415 1411 case INITTAB_MSG_RETURN:
1416 1412
1417 1413 return;
1418 1414 }
1419 1415 }
1420 1416
1421 1417 /*
1422 1418 * decode_number(): decodes a sequence of numbers from binary into ascii;
1423 1419 * binary is coming off of the network, so it is in nbo
1424 1420 *
1425 1421 * input: uint8_t: the number of "granularity" numbers to decode
1426 1422 * uint8_t: the length of each number
1427 1423 * boolean_t: whether the numbers should be considered signed
1428 1424 * uint8_t: the number of numbers per granularity
1429 1425 * const uint8_t *: where to decode the numbers from
1430 1426 * char *: where to decode the numbers to
1431 1427 * output: boolean_t: true on successful conversion, false on failure
1432 1428 */
1433 1429
1434 1430 static boolean_t
1435 1431 decode_number(uint8_t n_entries, uint8_t size, boolean_t is_signed,
1436 1432 uint8_t granularity, const uint8_t *from, char *to, int *ierrnop)
1437 1433 {
1438 1434 uint16_t uint16;
1439 1435 uint32_t uint32;
1440 1436 uint64_t uint64;
1441 1437
1442 1438 if (granularity != 0) {
1443 1439 if ((granularity % n_entries) != 0) {
1444 1440 inittab_msg("decode_number: number of entries "
1445 1441 "not compatible with option granularity");
1446 1442 *ierrnop = ITAB_BAD_GRAN;
1447 1443 return (B_FALSE);
1448 1444 }
1449 1445 }
1450 1446
1451 1447 for (; n_entries != 0; n_entries--, from += size) {
1452 1448
1453 1449 switch (size) {
1454 1450
1455 1451 case 1:
1456 1452 to += sprintf(to, is_signed ? "%d" : "%u", *from);
1457 1453 break;
1458 1454
1459 1455 case 2:
1460 1456 (void) memcpy(&uint16, from, 2);
1461 1457 to += sprintf(to, is_signed ? "%hd" : "%hu",
1462 1458 ntohs(uint16));
1463 1459 break;
1464 1460
1465 1461 case 3:
1466 1462 uint32 = 0;
1467 1463 (void) memcpy((uchar_t *)&uint32 + 1, from, 3);
1468 1464 to += sprintf(to, is_signed ? "%ld" : "%lu",
1469 1465 ntohl(uint32));
1470 1466 break;
↓ open down ↓ |
1409 lines elided |
↑ open up ↑ |
1471 1467
1472 1468 case 4:
1473 1469 (void) memcpy(&uint32, from, 4);
1474 1470 to += sprintf(to, is_signed ? "%ld" : "%lu",
1475 1471 ntohl(uint32));
1476 1472 break;
1477 1473
1478 1474 case 8:
1479 1475 (void) memcpy(&uint64, from, 8);
1480 1476 to += sprintf(to, is_signed ? "%lld" : "%llu",
1481 - dhcp_ntohll(uint64));
1477 + ntohll(uint64));
1482 1478 break;
1483 1479
1484 1480 default:
1485 1481 *ierrnop = ITAB_BAD_NUMBER;
1486 1482 inittab_msg("decode_number: unknown integer size `%d'",
1487 1483 size);
1488 1484 return (B_FALSE);
1489 1485 }
1490 1486 if (n_entries > 0)
1491 1487 *to++ = ' ';
1492 1488 }
1493 1489
1494 1490 *to = '\0';
1495 1491 return (B_TRUE);
1496 1492 }
1497 1493
1498 1494 /*
1499 1495 * encode_number(): encodes a sequence of numbers from ascii into binary;
1500 1496 * number will end up on the wire so it needs to be in nbo
1501 1497 *
1502 1498 * input: uint8_t: the number of "granularity" numbers to encode
1503 1499 * uint8_t: the length of each number
1504 1500 * boolean_t: whether the numbers should be considered signed
1505 1501 * uint8_t: the number of numbers per granularity
1506 1502 * const uint8_t *: where to encode the numbers from
1507 1503 * char *: where to encode the numbers to
1508 1504 * int *: set to extended error code if error occurs.
1509 1505 * output: boolean_t: true on successful conversion, false on failure
1510 1506 */
1511 1507
1512 1508 static boolean_t /* ARGSUSED */
1513 1509 encode_number(uint8_t n_entries, uint8_t size, boolean_t is_signed,
1514 1510 uint8_t granularity, const char *from, uint8_t *to, int *ierrnop)
1515 1511 {
1516 1512 uint8_t i;
1517 1513 uint16_t uint16;
1518 1514 uint32_t uint32;
1519 1515 uint64_t uint64;
1520 1516 char *endptr;
1521 1517
1522 1518 if (granularity != 0) {
1523 1519 if ((granularity % n_entries) != 0) {
1524 1520 *ierrnop = ITAB_BAD_GRAN;
1525 1521 inittab_msg("encode_number: number of entries "
1526 1522 "not compatible with option granularity");
1527 1523 return (B_FALSE);
1528 1524 }
1529 1525 }
1530 1526
1531 1527 for (i = 0; i < n_entries; i++, from++, to += size) {
1532 1528
1533 1529 /*
1534 1530 * totally obscure c factoid: it is legal to pass a
1535 1531 * string representing a negative number to strtoul().
1536 1532 * in this case, strtoul() will return an unsigned
1537 1533 * long that if cast to a long, would represent the
1538 1534 * negative number. we take advantage of this to
1539 1535 * cut down on code here.
1540 1536 */
1541 1537
1542 1538 errno = 0;
1543 1539 switch (size) {
1544 1540
1545 1541 case 1:
1546 1542 *to = strtoul(from, &endptr, 0);
1547 1543 if (errno != 0 || from == endptr) {
1548 1544 goto error;
1549 1545 }
1550 1546 break;
1551 1547
1552 1548 case 2:
1553 1549 uint16 = htons(strtoul(from, &endptr, 0));
1554 1550 if (errno != 0 || from == endptr) {
1555 1551 goto error;
1556 1552 }
1557 1553 (void) memcpy(to, &uint16, 2);
1558 1554 break;
1559 1555
1560 1556 case 3:
1561 1557 uint32 = htonl(strtoul(from, &endptr, 0));
1562 1558 if (errno != 0 || from == endptr) {
1563 1559 goto error;
1564 1560 }
1565 1561 (void) memcpy(to, (uchar_t *)&uint32 + 1, 3);
1566 1562 break;
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
1567 1563
1568 1564 case 4:
1569 1565 uint32 = htonl(strtoul(from, &endptr, 0));
1570 1566 if (errno != 0 || from == endptr) {
1571 1567 goto error;
1572 1568 }
1573 1569 (void) memcpy(to, &uint32, 4);
1574 1570 break;
1575 1571
1576 1572 case 8:
1577 - uint64 = dhcp_htonll(strtoull(from, &endptr, 0));
1573 + uint64 = htonll(strtoull(from, &endptr, 0));
1578 1574 if (errno != 0 || from == endptr) {
1579 1575 goto error;
1580 1576 }
1581 1577 (void) memcpy(to, &uint64, 8);
1582 1578 break;
1583 1579
1584 1580 default:
1585 1581 inittab_msg("encode_number: unsupported integer "
1586 1582 "size `%d'", size);
1587 1583 return (B_FALSE);
1588 1584 }
1589 1585
1590 1586 from = strchr(from, ' ');
1591 1587 if (from == NULL)
1592 1588 break;
1593 1589 }
1594 1590
1595 1591 return (B_TRUE);
1596 1592
1597 1593 error:
1598 1594 *ierrnop = ITAB_BAD_NUMBER;
1599 1595 inittab_msg("encode_number: cannot convert to integer");
1600 1596 return (B_FALSE);
1601 1597 }
1602 1598
1603 1599 /*
1604 1600 * inittab_type_to_size(): given an inittab entry, returns size of one entry of
1605 1601 * its type
1606 1602 *
1607 1603 * input: dhcp_symbol_t *: an entry of the given type
1608 1604 * output: uint8_t: the size in bytes of an entry of that type
1609 1605 */
1610 1606
1611 1607 uint8_t
1612 1608 inittab_type_to_size(const dhcp_symbol_t *ie)
1613 1609 {
1614 1610 switch (ie->ds_type) {
1615 1611
1616 1612 case DSYM_DUID:
1617 1613 case DSYM_DOMAIN:
1618 1614 case DSYM_ASCII:
1619 1615 case DSYM_OCTET:
1620 1616 case DSYM_SNUMBER8:
1621 1617 case DSYM_UNUMBER8:
1622 1618
1623 1619 return (1);
1624 1620
1625 1621 case DSYM_SNUMBER16:
1626 1622 case DSYM_UNUMBER16:
1627 1623
1628 1624 return (2);
1629 1625
1630 1626 case DSYM_UNUMBER24:
1631 1627
1632 1628 return (3);
1633 1629
1634 1630 case DSYM_SNUMBER32:
1635 1631 case DSYM_UNUMBER32:
1636 1632 case DSYM_IP:
1637 1633
1638 1634 return (4);
1639 1635
1640 1636 case DSYM_SNUMBER64:
1641 1637 case DSYM_UNUMBER64:
1642 1638
1643 1639 return (8);
1644 1640
1645 1641 case DSYM_NUMBER:
1646 1642
1647 1643 return (ie->ds_gran);
1648 1644
1649 1645 case DSYM_IPV6:
1650 1646
1651 1647 return (sizeof (in6_addr_t));
1652 1648 }
1653 1649
1654 1650 return (0);
1655 1651 }
1656 1652
1657 1653 /*
1658 1654 * itabcode_to_dsymcode(): maps an inittab category code to its dsym
1659 1655 * representation
1660 1656 *
1661 1657 * input: uchar_t: the inittab category code
1662 1658 * output: dsym_category_t: the dsym category code
1663 1659 */
1664 1660
1665 1661 static dsym_category_t
1666 1662 itabcode_to_dsymcode(uchar_t itabcode)
1667 1663 {
1668 1664
1669 1665 unsigned int i;
1670 1666
1671 1667 for (i = 0; i < ITAB_CAT_COUNT; i++)
1672 1668 if (category_map[i].cme_itabcode == itabcode)
1673 1669 return (category_map[i].cme_dsymcode);
1674 1670
1675 1671 return (DSYM_BAD_CAT);
1676 1672 }
1677 1673
1678 1674 /*
1679 1675 * category_to_code(): maps a category name to its numeric representation
1680 1676 *
1681 1677 * input: const char *: the category name
1682 1678 * output: uchar_t: its internal code (numeric representation)
1683 1679 */
1684 1680
1685 1681 static uchar_t
1686 1682 category_to_code(const char *category)
1687 1683 {
↓ open down ↓ |
100 lines elided |
↑ open up ↑ |
1688 1684 unsigned int i;
1689 1685
1690 1686 for (i = 0; i < ITAB_CAT_COUNT; i++)
1691 1687 if (strcasecmp(category_map[i].cme_name, category) == 0)
1692 1688 return (category_map[i].cme_itabcode);
1693 1689
1694 1690 return (0);
1695 1691 }
1696 1692
1697 1693 /*
1698 - * dhcp_htonll(): converts a 64-bit number from host to network byte order
1699 - *
1700 - * input: uint64_t: the number to convert
1701 - * output: uint64_t: its value in network byte order
1702 - */
1703 -
1704 -static uint64_t
1705 -dhcp_htonll(uint64_t uint64_hbo)
1706 -{
1707 - return (dhcp_ntohll(uint64_hbo));
1708 -}
1709 -
1710 -/*
1711 - * dhcp_ntohll(): converts a 64-bit number from network to host byte order
1712 - *
1713 - * input: uint64_t: the number to convert
1714 - * output: uint64_t: its value in host byte order
1715 - */
1716 -
1717 -static uint64_t
1718 -dhcp_ntohll(uint64_t uint64_nbo)
1719 -{
1720 -#ifdef _LITTLE_ENDIAN
1721 - return ((uint64_t)ntohl(uint64_nbo & 0xffffffff) << 32 |
1722 - ntohl(uint64_nbo >> 32));
1723 -#else
1724 - return (uint64_nbo);
1725 -#endif
1726 -}
1727 -
1728 -/*
1729 1694 * our internal table of DHCP option values, used by inittab_verify()
1730 1695 */
1731 1696 static dhcp_symbol_t inittab_table[] =
1732 1697 {
1733 1698 { DSYM_INTERNAL, 1024, "Hostname", DSYM_BOOL, 0, 0 },
1734 1699 { DSYM_INTERNAL, 1025, "LeaseNeg", DSYM_BOOL, 0, 0 },
1735 1700 { DSYM_INTERNAL, 1026, "EchoVC", DSYM_BOOL, 0, 0 },
1736 1701 { DSYM_INTERNAL, 1027, "BootPath", DSYM_ASCII, 1, 128 },
1737 1702 { DSYM_FIELD, 0, "Opcode", DSYM_UNUMBER8, 1, 1 },
1738 1703 { DSYM_FIELD, 1, "Htype", DSYM_UNUMBER8, 1, 1 },
1739 1704 { DSYM_FIELD, 2, "HLen", DSYM_UNUMBER8, 1, 1 },
1740 1705 { DSYM_FIELD, 3, "Hops", DSYM_UNUMBER8, 1, 1 },
1741 1706 { DSYM_FIELD, 4, "Xid", DSYM_UNUMBER32, 1, 1 },
1742 1707 { DSYM_FIELD, 8, "Secs", DSYM_UNUMBER16, 1, 1 },
1743 1708 { DSYM_FIELD, 10, "Flags", DSYM_OCTET, 1, 2 },
1744 1709 { DSYM_FIELD, 12, "Ciaddr", DSYM_IP, 1, 1 },
1745 1710 { DSYM_FIELD, 16, "Yiaddr", DSYM_IP, 1, 1 },
1746 1711 { DSYM_FIELD, 20, "BootSrvA", DSYM_IP, 1, 1 },
1747 1712 { DSYM_FIELD, 24, "Giaddr", DSYM_IP, 1, 1 },
1748 -{ DSYM_FIELD, 28, "Chaddr", DSYM_OCTET, 1, 16 },
1713 +{ DSYM_FIELD, 28, "Chaddr", DSYM_OCTET, 1, 16 },
1749 1714 { DSYM_FIELD, 44, "BootSrvN", DSYM_ASCII, 1, 64 },
1750 1715 { DSYM_FIELD, 108, "BootFile", DSYM_ASCII, 1, 128 },
1751 1716 { DSYM_FIELD, 236, "Magic", DSYM_OCTET, 1, 4 },
1752 1717 { DSYM_FIELD, 240, "Options", DSYM_OCTET, 1, 60 },
1753 1718 { DSYM_STANDARD, 1, "Subnet", DSYM_IP, 1, 1 },
1754 1719 { DSYM_STANDARD, 2, "UTCoffst", DSYM_SNUMBER32, 1, 1 },
1755 1720 { DSYM_STANDARD, 3, "Router", DSYM_IP, 1, 0 },
1756 1721 { DSYM_STANDARD, 4, "Timeserv", DSYM_IP, 1, 0 },
1757 1722 { DSYM_STANDARD, 5, "IEN116ns", DSYM_IP, 1, 0 },
1758 1723 { DSYM_STANDARD, 6, "DNSserv", DSYM_IP, 1, 0 },
1759 1724 { DSYM_STANDARD, 7, "Logserv", DSYM_IP, 1, 0 },
1760 1725 { DSYM_STANDARD, 8, "Cookie", DSYM_IP, 1, 0 },
1761 1726 { DSYM_STANDARD, 9, "Lprserv", DSYM_IP, 1, 0 },
1762 1727 { DSYM_STANDARD, 10, "Impress", DSYM_IP, 1, 0 },
1763 1728 { DSYM_STANDARD, 11, "Resource", DSYM_IP, 1, 0 },
1764 1729 { DSYM_STANDARD, 12, "Hostname", DSYM_ASCII, 1, 0 },
1765 1730 { DSYM_STANDARD, 13, "Bootsize", DSYM_UNUMBER16, 1, 1 },
1766 1731 { DSYM_STANDARD, 14, "Dumpfile", DSYM_ASCII, 1, 0 },
1767 1732 { DSYM_STANDARD, 15, "DNSdmain", DSYM_ASCII, 1, 0 },
1768 1733 { DSYM_STANDARD, 16, "Swapserv", DSYM_IP, 1, 1 },
1769 1734 { DSYM_STANDARD, 17, "Rootpath", DSYM_ASCII, 1, 0 },
1770 1735 { DSYM_STANDARD, 18, "ExtendP", DSYM_ASCII, 1, 0 },
1771 1736 { DSYM_STANDARD, 19, "IpFwdF", DSYM_UNUMBER8, 1, 1 },
1772 1737 { DSYM_STANDARD, 20, "NLrouteF", DSYM_UNUMBER8, 1, 1 },
1773 1738 { DSYM_STANDARD, 21, "PFilter", DSYM_IP, 2, 0 },
1774 1739 { DSYM_STANDARD, 22, "MaxIpSiz", DSYM_UNUMBER16, 1, 1 },
1775 1740 { DSYM_STANDARD, 23, "IpTTL", DSYM_UNUMBER8, 1, 1 },
1776 1741 { DSYM_STANDARD, 24, "PathTO", DSYM_UNUMBER32, 1, 1 },
1777 1742 { DSYM_STANDARD, 25, "PathTbl", DSYM_UNUMBER16, 1, 0 },
1778 1743 { DSYM_STANDARD, 26, "MTU", DSYM_UNUMBER16, 1, 1 },
1779 1744 { DSYM_STANDARD, 27, "SameMtuF", DSYM_UNUMBER8, 1, 1 },
1780 1745 { DSYM_STANDARD, 28, "Broadcst", DSYM_IP, 1, 1 },
1781 1746 { DSYM_STANDARD, 29, "MaskDscF", DSYM_UNUMBER8, 1, 1 },
1782 1747 { DSYM_STANDARD, 30, "MaskSupF", DSYM_UNUMBER8, 1, 1 },
1783 1748 { DSYM_STANDARD, 31, "RDiscvyF", DSYM_UNUMBER8, 1, 1 },
1784 1749 { DSYM_STANDARD, 32, "RSolictS", DSYM_IP, 1, 1 },
1785 1750 { DSYM_STANDARD, 33, "StaticRt", DSYM_IP, 2, 0 },
1786 1751 { DSYM_STANDARD, 34, "TrailerF", DSYM_UNUMBER8, 1, 1 },
1787 1752 { DSYM_STANDARD, 35, "ArpTimeO", DSYM_UNUMBER32, 1, 1 },
1788 1753 { DSYM_STANDARD, 36, "EthEncap", DSYM_UNUMBER8, 1, 1 },
1789 1754 { DSYM_STANDARD, 37, "TcpTTL", DSYM_UNUMBER8, 1, 1 },
1790 1755 { DSYM_STANDARD, 38, "TcpKaInt", DSYM_UNUMBER32, 1, 1 },
1791 1756 { DSYM_STANDARD, 39, "TcpKaGbF", DSYM_UNUMBER8, 1, 1 },
1792 1757 { DSYM_STANDARD, 40, "NISdmain", DSYM_ASCII, 1, 0 },
1793 1758 { DSYM_STANDARD, 41, "NISservs", DSYM_IP, 1, 0 },
1794 1759 { DSYM_STANDARD, 42, "NTPservs", DSYM_IP, 1, 0 },
1795 1760 { DSYM_STANDARD, 43, "Vendor", DSYM_OCTET, 1, 0 },
1796 1761 { DSYM_STANDARD, 44, "NetBNms", DSYM_IP, 1, 0 },
1797 1762 { DSYM_STANDARD, 45, "NetBDsts", DSYM_IP, 1, 0 },
1798 1763 { DSYM_STANDARD, 46, "NetBNdT", DSYM_UNUMBER8, 1, 1 },
1799 1764 { DSYM_STANDARD, 47, "NetBScop", DSYM_ASCII, 1, 0 },
1800 1765 { DSYM_STANDARD, 48, "XFontSrv", DSYM_IP, 1, 0 },
1801 1766 { DSYM_STANDARD, 49, "XDispMgr", DSYM_IP, 1, 0 },
1802 1767 { DSYM_STANDARD, 50, "ReqIP", DSYM_IP, 1, 1 },
1803 1768 { DSYM_STANDARD, 51, "LeaseTim", DSYM_UNUMBER32, 1, 1 },
1804 1769 { DSYM_STANDARD, 52, "OptOvrld", DSYM_UNUMBER8, 1, 1 },
1805 1770 { DSYM_STANDARD, 53, "DHCPType", DSYM_UNUMBER8, 1, 1 },
1806 1771 { DSYM_STANDARD, 54, "ServerID", DSYM_IP, 1, 1 },
1807 1772 { DSYM_STANDARD, 55, "ReqList", DSYM_OCTET, 1, 0 },
1808 1773 { DSYM_STANDARD, 56, "Message", DSYM_ASCII, 1, 0 },
1809 1774 { DSYM_STANDARD, 57, "DHCP_MTU", DSYM_UNUMBER16, 1, 1 },
1810 1775 { DSYM_STANDARD, 58, "T1Time", DSYM_UNUMBER32, 1, 1 },
1811 1776 { DSYM_STANDARD, 59, "T2Time", DSYM_UNUMBER32, 1, 1 },
1812 1777 { DSYM_STANDARD, 60, "ClassID", DSYM_ASCII, 1, 0 },
1813 1778 { DSYM_STANDARD, 61, "ClientID", DSYM_OCTET, 1, 0 },
1814 1779 { DSYM_STANDARD, 62, "NW_dmain", DSYM_ASCII, 1, 0 },
1815 1780 { DSYM_STANDARD, 63, "NWIPOpts", DSYM_OCTET, 1, 128 },
1816 1781 { DSYM_STANDARD, 64, "NIS+dom", DSYM_ASCII, 1, 0 },
1817 1782 { DSYM_STANDARD, 65, "NIS+serv", DSYM_IP, 1, 0 },
1818 1783 { DSYM_STANDARD, 66, "TFTPsrvN", DSYM_ASCII, 1, 64 },
1819 1784 { DSYM_STANDARD, 67, "OptBootF", DSYM_ASCII, 1, 128 },
1820 1785 { DSYM_STANDARD, 68, "MblIPAgt", DSYM_IP, 1, 0 },
1821 1786 { DSYM_STANDARD, 69, "SMTPserv", DSYM_IP, 1, 0 },
1822 1787 { DSYM_STANDARD, 70, "POP3serv", DSYM_IP, 1, 0 },
1823 1788 { DSYM_STANDARD, 71, "NNTPserv", DSYM_IP, 1, 0 },
1824 1789 { DSYM_STANDARD, 72, "WWWservs", DSYM_IP, 1, 0 },
1825 1790 { DSYM_STANDARD, 73, "Fingersv", DSYM_IP, 1, 0 },
1826 1791 { DSYM_STANDARD, 74, "IRCservs", DSYM_IP, 1, 0 },
1827 1792 { DSYM_STANDARD, 75, "STservs", DSYM_IP, 1, 0 },
1828 1793 { DSYM_STANDARD, 76, "STDAservs", DSYM_IP, 1, 0 },
1829 1794 { DSYM_STANDARD, 77, "UserClas", DSYM_ASCII, 1, 0 },
1830 1795 { DSYM_STANDARD, 78, "SLP_DA", DSYM_OCTET, 1, 0 },
1831 1796 { DSYM_STANDARD, 79, "SLP_SS", DSYM_OCTET, 1, 0 },
1832 1797 { DSYM_STANDARD, 82, "AgentOpt", DSYM_OCTET, 1, 0 },
1833 1798 { DSYM_STANDARD, 89, "FQDN", DSYM_OCTET, 1, 0 },
1834 1799 { 0, 0, "", 0, 0, 0 }
1835 1800 };
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX