1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <netinet/in.h> 30 #include <limits.h> 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 34 #include <mdb/mdb_string.h> 35 #include <mdb/mdb_modapi.h> 36 #include <mdb/mdb_lex.h> 37 #include <mdb/mdb_debug.h> 38 #include <mdb/mdb.h> 39 40 /* 41 * Convert the specified integer value to a string represented in the given 42 * base. The flags parameter is a bitfield of the formatting flags defined in 43 * mdb_string.h. A pointer to a static conversion buffer is returned. 44 */ 45 const char * 46 numtostr(uintmax_t uvalue, int base, uint_t flags) 47 { 48 static const char ldigits[] = "0123456789abcdef"; 49 static const char udigits[] = "0123456789ABCDEF"; 50 51 static char buf[68]; /* Enough for ULLONG_MAX in binary plus prefixes */ 52 53 const char *digits = (flags & NTOS_UPCASE) ? udigits : ldigits; 54 int i = sizeof (buf); 55 56 intmax_t value = (intmax_t)uvalue; 57 int neg = (flags & NTOS_UNSIGNED) == 0 && value < 0; 58 uintmax_t rem = neg ? -value : value; 59 60 buf[--i] = 0; 61 62 do { 63 buf[--i] = digits[rem % base]; 64 rem /= base; 65 } while (rem != 0); 66 67 if (flags & NTOS_SHOWBASE) { 68 uintmax_t lim; 69 char c = 0; 70 71 switch (base) { 72 case 2: 73 lim = 1; 74 c = 'i'; 75 break; 76 case 8: 77 lim = 7; 78 c = 'o'; 79 break; 80 case 10: 81 lim = 9; 82 c = 't'; 83 break; 84 case 16: 85 lim = 9; 86 c = 'x'; 87 break; 88 } 89 90 if (c != 0 && uvalue > lim) { 91 buf[--i] = c; 92 buf[--i] = '0'; 93 } 94 } 95 96 if (neg) 97 buf[--i] = '-'; 98 else if (flags & NTOS_SIGNPOS) 99 buf[--i] = '+'; 100 101 return ((const char *)(&buf[i])); 102 } 103 104 #define CTOI(x) (((x) >= '0' && (x) <= '9') ? (x) - '0' : \ 105 ((x) >= 'a' && (x) <= 'z') ? (x) + 10 - 'a' : (x) + 10 - 'A') 106 107 /* 108 * Convert a string to an unsigned integer value using the specified base. 109 * In the event of overflow or an invalid character, we generate an 110 * error message and longjmp back to the main loop using yyerror(). 111 */ 112 uintmax_t 113 strtonum(const char *s, int base) 114 { 115 uintmax_t multmax = (uintmax_t)ULLONG_MAX / (uintmax_t)(uint_t)base; 116 uintmax_t val = 0; 117 int c, i, neg = 0; 118 119 switch (c = *s) { 120 case '-': 121 neg++; 122 /*FALLTHRU*/ 123 case '+': 124 c = *++s; 125 } 126 127 if (c == '\0') 128 goto done; 129 130 if ((val = CTOI(c)) >= base) 131 yyerror("digit '%c' is invalid in current base\n", c); 132 133 for (c = *++s; c != '\0'; c = *++s) { 134 if (val > multmax) 135 goto oflow; 136 137 if ((i = CTOI(c)) >= base) 138 yyerror("digit '%c' is invalid in current base\n", c); 139 140 val *= base; 141 142 if ((uintmax_t)ULLONG_MAX - val < (uintmax_t)i) 143 goto oflow; 144 145 val += i; 146 } 147 done: 148 return (neg ? -val : val); 149 oflow: 150 yyerror("specified value exceeds maximum immediate value\n"); 151 return ((uintmax_t)ULLONG_MAX); 152 } 153 154 /* 155 * Quick string to unsigned long conversion function. This function performs 156 * no overflow checking and is only meant for internal mdb use. It allows 157 * the caller to specify the length of the string in bytes and a base. 158 */ 159 ulong_t 160 strntoul(const char *s, size_t nbytes, int base) 161 { 162 ulong_t n; 163 int c; 164 165 for (n = 0; nbytes != 0 && (c = *s) != '\0'; s++, nbytes--) 166 n = n * base + CTOI(c); 167 168 return (n); 169 } 170 171 /* 172 * Return a boolean value indicating whether or not a string consists 173 * solely of characters which are digits 0..9. 174 */ 175 int 176 strisnum(const char *s) 177 { 178 for (; *s != '\0'; s++) { 179 if (*s < '0' || *s > '9') 180 return (0); 181 } 182 183 return (1); 184 } 185 186 /* 187 * Return a boolean value indicating whether or not a string contains a 188 * number. The number may be in the current radix, or it may have an 189 * explicit radix qualifier. The number will be validated against the 190 * legal characters for the given radix. 191 */ 192 int 193 strisbasenum(const char *s) 194 { 195 char valid[] = "0123456789aAbBcCdDeEfF"; 196 int radix = mdb.m_radix; 197 198 if (s[0] == '0') { 199 switch (s[1]) { 200 case 'I': 201 case 'i': 202 radix = 2; 203 s += 2; 204 break; 205 case 'O': 206 case 'o': 207 radix = 8; 208 s += 2; 209 break; 210 case 'T': 211 case 't': 212 radix = 10; 213 s += 2; 214 break; 215 case 'x': 216 case 'X': 217 radix = 16; 218 s += 2; 219 break; 220 } 221 } 222 223 /* limit `valid' to the digits valid for this base */ 224 valid[radix > 10 ? 10 + (radix - 10) * 2 : radix] = '\0'; 225 226 do { 227 if (!strchr(valid, *s)) 228 return (0); 229 } while (*++s != '\0'); 230 231 return (1); 232 } 233 234 /* 235 * Quick string to integer (base 10) conversion function. This performs 236 * no overflow checking and is only meant for internal mdb use. 237 */ 238 int 239 strtoi(const char *s) 240 { 241 int c, n; 242 243 for (n = 0; (c = *s) >= '0' && c <= '9'; s++) 244 n = n * 10 + c - '0'; 245 246 return (n); 247 } 248 249 /* 250 * Create a copy of string s using the mdb allocator interface. 251 */ 252 char * 253 strdup(const char *s) 254 { 255 char *s1 = mdb_alloc(strlen(s) + 1, UM_SLEEP); 256 257 (void) strcpy(s1, s); 258 return (s1); 259 } 260 261 /* 262 * Create a copy of string s, but only duplicate the first n bytes. 263 */ 264 char * 265 strndup(const char *s, size_t n) 266 { 267 char *s2 = mdb_alloc(n + 1, UM_SLEEP); 268 269 (void) strncpy(s2, s, n); 270 s2[n] = '\0'; 271 return (s2); 272 } 273 274 /* 275 * Convenience routine for freeing strings. 276 */ 277 void 278 strfree(char *s) 279 { 280 mdb_free(s, strlen(s) + 1); 281 } 282 283 /* 284 * Transform string s inline, converting each embedded C escape sequence string 285 * to the corresponding character. For example, the substring "\n" is replaced 286 * by an inline '\n' character. The length of the resulting string is returned. 287 */ 288 size_t 289 stresc2chr(char *s) 290 { 291 char *p, *q, c; 292 int esc = 0; 293 294 for (p = q = s; (c = *p) != '\0'; p++) { 295 if (esc) { 296 switch (c) { 297 case '0': 298 case '1': 299 case '2': 300 case '3': 301 case '4': 302 case '5': 303 case '6': 304 case '7': 305 c -= '0'; 306 p++; 307 308 if (*p >= '0' && *p <= '7') { 309 c = c * 8 + *p++ - '0'; 310 311 if (*p >= '0' && *p <= '7') 312 c = c * 8 + *p - '0'; 313 else 314 p--; 315 } else 316 p--; 317 318 *q++ = c; 319 break; 320 321 case 'a': 322 *q++ = '\a'; 323 break; 324 case 'b': 325 *q++ = '\b'; 326 break; 327 case 'f': 328 *q++ = '\f'; 329 break; 330 case 'n': 331 *q++ = '\n'; 332 break; 333 case 'r': 334 *q++ = '\r'; 335 break; 336 case 't': 337 *q++ = '\t'; 338 break; 339 case 'v': 340 *q++ = '\v'; 341 break; 342 case '"': 343 case '\\': 344 *q++ = c; 345 break; 346 default: 347 *q++ = '\\'; 348 *q++ = c; 349 } 350 351 esc = 0; 352 353 } else { 354 if ((esc = c == '\\') == 0) 355 *q++ = c; 356 } 357 } 358 359 *q = '\0'; 360 return ((size_t)(q - s)); 361 } 362 363 /* 364 * Create a copy of string s in which certain unprintable or special characters 365 * have been converted to the string representation of their C escape sequence. 366 * For example, the newline character is expanded to the string "\n". 367 */ 368 char * 369 strchr2esc(const char *s, size_t n) 370 { 371 const char *p; 372 char *q, *s2, c; 373 size_t addl = 0; 374 375 for (p = s; p < s + n; p++) { 376 switch (c = *p) { 377 case '\0': 378 case '\a': 379 case '\b': 380 case '\f': 381 case '\n': 382 case '\r': 383 case '\t': 384 case '\v': 385 case '"': 386 case '\\': 387 addl++; /* 1 add'l char needed to follow \ */ 388 break; 389 case ' ': 390 break; 391 default: 392 if (c < '!' || c > '~') 393 addl += 3; /* 3 add'l chars following \ */ 394 } 395 } 396 397 s2 = mdb_alloc(n + addl + 1, UM_SLEEP); 398 399 for (p = s, q = s2; p < s + n; p++) { 400 switch (c = *p) { 401 case '\0': 402 *q++ = '\\'; 403 *q++ = '0'; 404 break; 405 case '\a': 406 *q++ = '\\'; 407 *q++ = 'a'; 408 break; 409 case '\b': 410 *q++ = '\\'; 411 *q++ = 'b'; 412 break; 413 case '\f': 414 *q++ = '\\'; 415 *q++ = 'f'; 416 break; 417 case '\n': 418 *q++ = '\\'; 419 *q++ = 'n'; 420 break; 421 case '\r': 422 *q++ = '\\'; 423 *q++ = 'r'; 424 break; 425 case '\t': 426 *q++ = '\\'; 427 *q++ = 't'; 428 break; 429 case '\v': 430 *q++ = '\\'; 431 *q++ = 'v'; 432 break; 433 case '"': 434 *q++ = '\\'; 435 *q++ = '"'; 436 break; 437 case '\\': 438 *q++ = '\\'; 439 *q++ = '\\'; 440 break; 441 case ' ': 442 *q++ = c; 443 break; 444 default: 445 if (c < '!' || c > '~') { 446 *q++ = '\\'; 447 *q++ = ((c >> 6) & 3) + '0'; 448 *q++ = ((c >> 3) & 7) + '0'; 449 *q++ = (c & 7) + '0'; 450 } else 451 *q++ = c; 452 } 453 } 454 455 *q = '\0'; 456 return (s2); 457 } 458 459 /* 460 * Create a copy of string s in which certain unprintable or special characters 461 * have been converted to an odd representation of their escape sequence. 462 * This algorithm is the old adb convention for representing such sequences. 463 */ 464 char * 465 strchr2adb(const char *s, size_t n) 466 { 467 size_t addl = 0; 468 const char *p; 469 char *q, *s2; 470 471 for (p = s; p < s + n; p++) { 472 char c = *p & CHAR_MAX; 473 474 if (c < ' ' || c == CHAR_MAX) 475 addl++; /* 1 add'l char needed for "^" */ 476 } 477 478 s2 = mdb_alloc(n + addl + 1, UM_SLEEP); 479 480 for (p = s, q = s2; p < s + n; p++) { 481 char c = *p & CHAR_MAX; 482 483 if (c == CHAR_MAX) { 484 *q++ = '^'; 485 *q++ = '?'; 486 } else if (c < ' ') { 487 *q++ = '^'; 488 *q++ = c + '@'; 489 } else 490 *q++ = c; 491 } 492 493 *q = '\0'; 494 return (s2); 495 } 496 497 /* 498 * Same as strchr, but we only search the first n characters 499 */ 500 char * 501 strnchr(const char *s, int c, size_t n) 502 { 503 int i = 0; 504 505 for (i = 0; i < n; i++) { 506 if (*(s + i) == (char)c) 507 return ((char *)(s + i)); 508 } 509 510 return (NULL); 511 } 512 513 /* 514 * Split the string s at the first occurrence of character c. This character 515 * is replaced by \0, and a pointer to the remainder of the string is returned. 516 */ 517 char * 518 strsplit(char *s, char c) 519 { 520 char *p; 521 522 if ((p = strchr(s, c)) == NULL) 523 return (NULL); 524 525 *p++ = '\0'; 526 return (p); 527 } 528 529 /* 530 * Same as strsplit, but split from the last occurrence of character c. 531 */ 532 char * 533 strrsplit(char *s, char c) 534 { 535 char *p; 536 537 if ((p = strrchr(s, c)) == NULL) 538 return (NULL); 539 540 *p++ = '\0'; 541 return (p); 542 } 543 544 /* 545 * Return the address of the first occurrence of any character from s2 546 * in the string s1, or NULL if none exists. This is similar to libc's 547 * strpbrk, but we add a third parameter to limit the search to the 548 * specified number of bytes in s1, or a \0 character, whichever is 549 * encountered first. 550 */ 551 const char * 552 strnpbrk(const char *s1, const char *s2, size_t nbytes) 553 { 554 const char *p; 555 556 if (nbytes == 0) 557 return (NULL); 558 559 do { 560 for (p = s2; *p != '\0' && *p != *s1; p++) 561 continue; 562 563 if (*p != '\0') 564 return (s1); 565 566 } while (--nbytes != 0 && *s1++ != '\0'); 567 568 return (NULL); 569 } 570 571 /* 572 * Abbreviate a string if it meets or exceeds the specified length, including 573 * the terminating null character. The string is abbreviated by replacing the 574 * last four characters with " ...". strabbr is useful in constructs such as 575 * this one, where nbytes = sizeof (buf): 576 * 577 * if (mdb_snprintf(buf, nbytes, "%s %d %c", ...) >= nbytes) 578 * (void) strabbr(buf, nbytes); 579 * 580 * No modifications are made if nbytes is too small to hold the suffix itself. 581 */ 582 char * 583 strabbr(char *s, size_t nbytes) 584 { 585 static const char suffix[] = " ..."; 586 587 if (nbytes > sizeof (suffix) && strlen(s) >= nbytes - 1) 588 (void) strcpy(&s[nbytes - sizeof (suffix)], suffix); 589 590 return (s); 591 } 592 593 /* 594 * Return the basename (name after final /) of the given string. We use 595 * strbasename rather than basename to avoid conflicting with libgen.h's 596 * non-const function prototype. 597 */ 598 const char * 599 strbasename(const char *s) 600 { 601 const char *p = strrchr(s, '/'); 602 603 if (p == NULL) 604 return (s); 605 606 return (++p); 607 } 608 609 /* 610 * Return the directory name (name prior to the final /) of the given string. 611 * The string itself is modified. 612 */ 613 char * 614 strdirname(char *s) 615 { 616 static char slash[] = "/"; 617 static char dot[] = "."; 618 char *p; 619 620 if (s == NULL || *s == '\0') 621 return (dot); 622 623 for (p = s + strlen(s); p != s && *--p == '/'; ) 624 continue; 625 626 if (p == s && *p == '/') 627 return (slash); 628 629 while (p != s) { 630 if (*--p == '/') { 631 while (*p == '/' && p != s) 632 p--; 633 *++p = '\0'; 634 return (s); 635 } 636 } 637 638 return (dot); 639 } 640 641 /* 642 * Return a pointer to the first character in the string that makes it an 643 * invalid identifer (i.e. incompatible with the mdb syntax), or NULL if 644 * the string is a valid identifier. 645 */ 646 const char * 647 strbadid(const char *s) 648 { 649 return (strpbrk(s, "#%^&*-+=,:$/\\?<>;|!`'\"[]\n\t() {}")); 650 } 651 652 /* 653 * Return a boolean value indicating if the given string consists solely 654 * of printable ASCII characters terminated by \0. 655 */ 656 int 657 strisprint(const char *s) 658 { 659 for (; *s != '\0'; s++) { 660 if (*s < ' ' || *s > '~') 661 return (0); 662 } 663 664 return (1); 665 } 666 667 /* 668 * This is a near direct copy of the inet_ntop() code in 669 * uts/common/inet/ip/ipv6.c, duplicated here for kmdb's sake. 670 */ 671 static void 672 convert2ascii(char *buf, const in6_addr_t *addr) 673 { 674 int hexdigits; 675 int head_zero = 0; 676 int tail_zero = 0; 677 /* tempbuf must be big enough to hold ffff:\0 */ 678 char tempbuf[6]; 679 char *ptr; 680 uint16_t *addr_component, host_component; 681 size_t len; 682 int first = FALSE; 683 int med_zero = FALSE; 684 int end_zero = FALSE; 685 686 addr_component = (uint16_t *)addr; 687 ptr = buf; 688 689 /* First count if trailing zeroes higher in number */ 690 for (hexdigits = 0; hexdigits < 8; hexdigits++) { 691 if (*addr_component == 0) { 692 if (hexdigits < 4) 693 head_zero++; 694 else 695 tail_zero++; 696 } 697 addr_component++; 698 } 699 addr_component = (uint16_t *)addr; 700 if (tail_zero > head_zero && (head_zero + tail_zero) != 7) 701 end_zero = TRUE; 702 703 for (hexdigits = 0; hexdigits < 8; hexdigits++) { 704 /* if entry is a 0 */ 705 if (*addr_component == 0) { 706 if (!first && *(addr_component + 1) == 0) { 707 if (end_zero && (hexdigits < 4)) { 708 *ptr++ = '0'; 709 *ptr++ = ':'; 710 } else { 711 if (hexdigits == 0) 712 *ptr++ = ':'; 713 /* add another */ 714 *ptr++ = ':'; 715 first = TRUE; 716 med_zero = TRUE; 717 } 718 } else if (first && med_zero) { 719 if (hexdigits == 7) 720 *ptr++ = ':'; 721 addr_component++; 722 continue; 723 } else { 724 *ptr++ = '0'; 725 *ptr++ = ':'; 726 } 727 addr_component++; 728 continue; 729 } 730 if (med_zero) 731 med_zero = FALSE; 732 733 tempbuf[0] = '\0'; 734 mdb_nhconvert(&host_component, addr_component, 735 sizeof (uint16_t)); 736 (void) mdb_snprintf(tempbuf, sizeof (tempbuf), "%x:", 737 host_component & 0xffff); 738 len = strlen(tempbuf); 739 bcopy(tempbuf, ptr, len); 740 ptr = ptr + len; 741 addr_component++; 742 } 743 *--ptr = '\0'; 744 } 745 746 char * 747 mdb_inet_ntop(int af, const void *addr, char *buf, size_t buflen) 748 { 749 in6_addr_t *v6addr; 750 uchar_t *v4addr; 751 char *caddr; 752 753 #define UC(b) (((int)b) & 0xff) 754 switch (af) { 755 case AF_INET: 756 ASSERT(buflen >= INET_ADDRSTRLEN); 757 v4addr = (uchar_t *)addr; 758 (void) mdb_snprintf(buf, buflen, "%d.%d.%d.%d", 759 UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3])); 760 return (buf); 761 762 case AF_INET6: 763 ASSERT(buflen >= INET6_ADDRSTRLEN); 764 v6addr = (in6_addr_t *)addr; 765 if (IN6_IS_ADDR_V4MAPPED(v6addr)) { 766 caddr = (char *)addr; 767 (void) mdb_snprintf(buf, buflen, "::ffff:%d.%d.%d.%d", 768 UC(caddr[12]), UC(caddr[13]), 769 UC(caddr[14]), UC(caddr[15])); 770 } else if (IN6_IS_ADDR_V4COMPAT(v6addr)) { 771 caddr = (char *)addr; 772 (void) mdb_snprintf(buf, buflen, "::%d.%d.%d.%d", 773 UC(caddr[12]), UC(caddr[13]), UC(caddr[14]), 774 UC(caddr[15])); 775 } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) { 776 (void) mdb_snprintf(buf, buflen, "::"); 777 } else { 778 convert2ascii(buf, v6addr); 779 } 780 return (buf); 781 } 782 #undef UC 783 784 return (NULL); 785 } 786