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 (c) 1998,2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <arpa/inet.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <sys/time.h> 34 #include <iconv.h> 35 #include "snoop.h" 36 #include "slp.h" 37 38 #define MAXSUMLEN 30 39 40 /* define VERIFYSLP to enable full message checking in summary mode */ 41 #define VERIFYSLP 42 43 /* Globals -- ugly, yes, but fast and easy in macros */ 44 static int msglength; 45 static int retlength; 46 static char *msgend; /* the end of the summary message buffer */ 47 static char *p; /* current position in the packet */ 48 static char *msgbuf; /* message buffer for summary mode */ 49 static boolean_t url_auth = B_FALSE; 50 static boolean_t attr_auth = B_FALSE; 51 static boolean_t fresh = B_FALSE; 52 static boolean_t overflow = B_FALSE; 53 static int v1_charset = 0; /* character set; only in V1 */ 54 55 /* Entry points for parsing the protocol */ 56 static int interpret_slp_v1(int, struct slpv1_hdr *, int); 57 static int interpret_slp_v2(int, struct slpv2_hdr *, int); 58 59 /* header parsing */ 60 static int v1_header(int, struct slpv1_hdr *, int); 61 static int v2_header(int, struct slpv2_hdr *, int *, int); 62 static int v2_finish(struct slpv2_hdr *, int); 63 64 /* V2 auth blocks */ 65 static int slpv2_authblock(int); 66 67 /* From snoop_rport: */ 68 extern int add_transient(int, int (*)()); 69 70 /* 71 * Functions for parsing each protocol message 72 * Each function takes the interpreter's flags argument as its input 73 * parameter, and returns 1 on success, or 0 on message corruption. 74 * retlength is set as a side-effect in summary mode. 75 */ 76 static int v2_srv_rqst(int); 77 static int v2_srv_rply(int); 78 static int v2_srv_reg(int); 79 static int v2_srv_dereg(int); 80 static int v2_srv_ack(int); 81 static int v2_attr_rqst(int); 82 static int v2_attr_rply(int); 83 static int v2_daadvert(int); 84 static int v2_srv_type_rqst(int); 85 static int v2_srv_type_rply(int); 86 static int v2_saadvert(int); 87 88 static int v1_srv_rqst(int); 89 static int v1_srv_rply(int); 90 static int v1_srv_reg(int); 91 static int v1_srv_dereg(int); 92 static int v1_srv_ack(int); 93 static int v1_attr_rqst(int); 94 static int v1_attr_rply(int); 95 static int v1_daadvert(int); 96 static int v1_srv_type_rqst(int); 97 static int v1_srv_type_rply(int); 98 99 /* 100 * The dispatch tables for handling individual messages, keyed by 101 * function number. 102 */ 103 typedef int function_handler(); 104 105 #define V2_MAX_FUNCTION 11 106 107 static function_handler *v2_functions[V2_MAX_FUNCTION + 1] = { 108 (function_handler *) NULL, 109 (function_handler *) v2_srv_rqst, 110 (function_handler *) v2_srv_rply, 111 (function_handler *) v2_srv_reg, 112 (function_handler *) v2_srv_dereg, 113 (function_handler *) v2_srv_ack, 114 (function_handler *) v2_attr_rqst, 115 (function_handler *) v2_attr_rply, 116 (function_handler *) v2_daadvert, 117 (function_handler *) v2_srv_type_rqst, 118 (function_handler *) v2_srv_type_rply, 119 (function_handler *) v2_saadvert }; 120 121 #define V1_MAX_FUNCTION 10 122 123 static function_handler *v1_functions[V1_MAX_FUNCTION + 1] = { 124 (function_handler *) NULL, 125 (function_handler *) v1_srv_rqst, 126 (function_handler *) v1_srv_rply, 127 (function_handler *) v1_srv_reg, 128 (function_handler *) v1_srv_dereg, 129 (function_handler *) v1_srv_ack, 130 (function_handler *) v1_attr_rqst, 131 (function_handler *) v1_attr_rply, 132 (function_handler *) v1_daadvert, 133 (function_handler *) v1_srv_type_rqst, 134 (function_handler *) v1_srv_type_rply }; 135 136 /* TCP continuation handling */ 137 static boolean_t tcp_continuation = B_FALSE; 138 139 #define MAX_TCPCONT 16 140 141 static struct tcp_cont { 142 int dst_port; 143 char *msg; 144 int totallen; 145 int curr_offset; 146 } *tcp_cont[MAX_TCPCONT]; 147 148 static int current_tcp_cont; 149 150 static void reg_tcp_cont(char *, int, int, int); 151 static int add_tcp_cont(struct tcp_cont *, char *, int); 152 static struct tcp_cont *find_tcp_cont(int); 153 static void remove_tcp_cont(int); 154 155 /* Conversions from numbers to strings */ 156 static char *slpv2_func(int, boolean_t); 157 static char *slpv2_error(unsigned short); 158 static char *slpv1_func(int, boolean_t); 159 static char *slpv1_error(unsigned short); 160 static char *slpv1_charset(unsigned short); 161 162 /* 163 * The only external entry point to the SLP interpreter. This function 164 * simply dispatches the packet based on the version. 165 */ 166 void interpret_slp(int flags, char *slp, int fraglen) { 167 extern int dst_port, curr_proto; 168 struct tcp_cont *tce = NULL; 169 170 msglength = fraglen; 171 retlength = 0; 172 p = slp; 173 174 /* check if this is a TCP continuation */ 175 if (flags & F_DTAIL && curr_proto == IPPROTO_TCP) { 176 tce = find_tcp_cont(dst_port); 177 if (tce) { 178 if (add_tcp_cont(tce, slp, fraglen)) { 179 slp = tce->msg; 180 fraglen = tce->curr_offset; 181 tcp_continuation = B_TRUE; 182 } 183 } 184 } 185 if (*slp == 2 || tce) 186 interpret_slp_v2(flags, (void *)slp, fraglen); 187 else 188 interpret_slp_v1(flags, (void *)slp, fraglen); 189 190 tcp_continuation = B_FALSE; 191 } 192 193 /* 194 * Primitives. These are implemented as much as possible as macros for 195 * speed. 196 */ 197 198 #define FIELD_DEFAULT 0 199 #define FIELD_PREVRESP 1 200 #define FIELD_TYPENA 2 201 202 static long long netval = 0; /* need signed 64 bit quantity */ 203 204 /* gets two bytes from p and leaves the result in netval */ 205 #define nbtohs() \ 206 netval = ((int)(p[0] & 0xff)) << 8; \ 207 netval += ((int)(p[1] & 0xff)) 208 209 /* gets four bytes from p and leaves the result in netval */ 210 #define nbtohl() \ 211 netval = ((int)(p[0] & 0xff)) << 24; \ 212 netval += ((int)(p[1] & 0xff)) << 16; \ 213 netval += ((int)(p[2] & 0xff)) << 8; \ 214 netval += ((int)(p[3] & 0xff)) 215 216 #define get_byte() \ 217 if (msglength >= 1) { \ 218 netval = *p; \ 219 p++; \ 220 msglength--; \ 221 } else \ 222 netval = -1 223 224 #define GETBYTE(x) \ 225 get_byte(); \ 226 if ((retlength = netval) < 0) \ 227 return (0); \ 228 x = netval 229 230 #define SKIPBYTE \ 231 get_byte(); \ 232 if ((retlength = netval) < 0) \ 233 return (0); \ 234 235 /* 236 * gets two bytes from p, leaves the result in netval, and updates 237 * msglength and p. 238 */ 239 #define get_short() \ 240 if (msglength >= sizeof (unsigned short)) { \ 241 nbtohs(); \ 242 p += sizeof (unsigned short); \ 243 msglength -= sizeof (unsigned short); \ 244 } else \ 245 netval = -1 246 247 #define GETSHORT(x) \ 248 get_short(); \ 249 if ((retlength = netval) < 0) \ 250 return (0); \ 251 x = netval 252 253 #define SKIPSHORT \ 254 get_short(); \ 255 if ((retlength = netval) < 0) \ 256 return (0) 257 258 #define get_int24(pp) \ 259 netval = ((int)((pp)[0] & 0xff)) << 16; \ 260 netval += ((int)((pp)[1] & 0xff)) << 8; \ 261 netval += ((int)((pp)[2] & 0xff)) 262 263 static void slp_prevresp(char *p) { 264 char *p2; 265 266 /* cycle through all entries */ 267 for (; p != NULL; p = p2) { 268 p2 = strchr(p, ','); 269 if (p2 != NULL) 270 *p2++ = '\0'; 271 272 /* print entry at p */ 273 sprintf(get_line(0, 0), " \"%s\"", p); 274 } 275 } 276 277 static int skip_field(int type) { 278 unsigned short stringlen; 279 280 get_short(); 281 if (netval < 0) { 282 return (-1); 283 } 284 stringlen = netval; 285 286 /* special case for NA field in SrvTypeRqst */ 287 if (type == FIELD_TYPENA && stringlen == 0xffff) { 288 stringlen = 0; 289 } 290 291 if (stringlen > msglength) { 292 return (-1); 293 } 294 295 msglength -= stringlen; 296 p += stringlen; 297 298 return (stringlen); 299 } 300 301 #define SKIPFIELD(type) \ 302 if ((retlength = skip_field(type)) < 0) \ 303 return (0) 304 305 #define GETFIELD \ 306 get_short(); \ 307 if ((retlength = netval) < 0) \ 308 return (0); \ 309 strncat(msgbuf, p, (retlength > MAXSUMLEN ? MAXSUMLEN : retlength)); \ 310 p += retlength; \ 311 msglength -= retlength 312 313 /* 314 * Determines from the first five bytes of a potential SLP header 315 * if the following message is really an SLP message. Returns 1 if 316 * it is a real SLP message, 0 if not. 317 */ 318 int valid_slp(unsigned char *slphdr, int len) { 319 struct slpv1_hdr slp1; 320 struct slpv2_hdr slp2; 321 322 len -= (8 /* udp */ + 20 /* IP */ + 14 /* ether */); 323 /* a valid version will be 1 or 2 */ 324 switch (*slphdr) { 325 case 1: 326 memcpy(&slp1, slphdr, 5); 327 /* valid function? */ 328 if (slp1.function > V1_MAX_FUNCTION) { 329 return (0); 330 } 331 /* valid length heuristic */ 332 if (slp1.length > len) { 333 return (0); 334 } 335 return (1); 336 case 2: 337 memcpy(&slp2, slphdr, 5); 338 /* valid function? */ 339 if (slp2.function > V2_MAX_FUNCTION) { 340 return (0); 341 } 342 /* valid length heuristic */ 343 get_int24(&(slp2.l1)); 344 if (netval > len) { 345 return (0); 346 } 347 return (1); 348 default: 349 return (0); 350 } 351 } 352 353 /* 354 * Converts a V1 char encoding to UTF8. If this fails, returns 0, 355 * otherwise, 1. This function is the union of iconv UTF-8 356 * modules and character sets registered with IANA. 357 */ 358 static int make_utf8(char *outbuf, size_t outlen, 359 const char *inbuf, size_t inlen) { 360 iconv_t cd; 361 size_t converted; 362 363 switch (v1_charset) { 364 case 4: 365 case 1004: 366 cd = iconv_open("UTF-8", "8859-1"); 367 break; 368 case 5: 369 cd = iconv_open("UTF-8", "8859-2"); 370 break; 371 case 6: 372 cd = iconv_open("UTF-8", "8859-3"); 373 break; 374 case 7: 375 cd = iconv_open("UTF-8", "8859-4"); 376 break; 377 case 8: 378 cd = iconv_open("UTF-8", "8859-5"); 379 break; 380 case 9: 381 cd = iconv_open("UTF-8", "8859-6"); 382 break; 383 case 10: 384 cd = iconv_open("UTF-8", "8859-7"); 385 break; 386 case 11: 387 cd = iconv_open("UTF-8", "8859-8"); 388 break; 389 case 12: 390 cd = iconv_open("UTF-8", "8859-9"); 391 break; 392 case 13: 393 cd = iconv_open("UTF-8", "8859-10"); 394 break; 395 case 37: 396 cd = iconv_open("UTF-8", "ko_KR-iso2022-7"); 397 break; 398 case 104: 399 cd = iconv_open("UTF-8", "iso2022"); 400 break; 401 case 1000: 402 cd = iconv_open("UTF-8", "UCS-2"); 403 break; 404 case 1001: 405 cd = iconv_open("UTF-8", "UCS-4"); 406 break; 407 default: 408 /* 409 * charset not set, or reserved, or not supported, so 410 * just copy it and hope for the best. 411 */ 412 converted = outlen < inlen ? outlen : inlen; 413 memcpy(outbuf, inbuf, converted); 414 outbuf[converted] = 0; 415 return (1); 416 } 417 418 if (cd == (iconv_t)-1) { 419 return (0); 420 } 421 422 if ((converted = iconv(cd, &inbuf, &inlen, &outbuf, &outlen)) 423 == (size_t)-1) { 424 return (0); 425 } 426 427 outbuf[converted] = 0; 428 iconv_close(cd); 429 430 return (1); 431 } 432 433 static int slp_field(char *tag, int type) { 434 int length; 435 436 get_short(); 437 if (netval < 0) { 438 return (-1); 439 } 440 length = netval; 441 442 /* special case for NA field in SrvTypeRqst */ 443 if (type == FIELD_TYPENA && length == 0xffff) { 444 sprintf(get_line(0, 0), "%s: length = -1: Use all NAs", tag); 445 return (0); 446 } 447 448 sprintf(get_line(0, 0), "%s: length = %d", tag, length); 449 if (length > msglength) { 450 /* framing error: message is not long enough to contain data */ 451 sprintf(get_line(0, 0), 452 " [Framing error: remaining pkt length = %u]", 453 msglength); 454 return (-1); 455 } 456 457 if (length > 0) { 458 char *buf = malloc(length + 1); 459 if (buf != NULL) { 460 if (v1_charset) { 461 if (!make_utf8(buf, length, p, length)) { 462 strcpy(buf, "[Invalid Character Encoding]"); 463 } 464 } else { 465 memcpy(buf, p, length); 466 buf[length] = '\0'; /* ensure null-terminated */ 467 } 468 469 switch (type) { 470 case FIELD_PREVRESP: 471 slp_prevresp(buf); 472 break; 473 474 default: 475 sprintf(get_line(0, 0), " \"%s\"", buf); 476 break; 477 } 478 free(buf); 479 } 480 481 p += length; 482 msglength -= length; 483 } 484 485 /* return ok */ 486 return (0); 487 } 488 489 static int slpv2_url(int cnt) { 490 time_t exp; 491 int lifetime, length, n; 492 493 /* reserved */ 494 get_byte(); 495 if (netval < 0) 496 return (-1); 497 498 /* lifetime */ 499 get_short(); 500 if ((lifetime = netval) < 0) 501 return (-1); 502 503 /* length */ 504 get_short(); 505 if ((length = netval) < 0) 506 return (-1); 507 508 /* time */ 509 exp = time(0) + lifetime; 510 if (cnt == -1) 511 sprintf(get_line(0, 0), 512 "URL: length = %u, lifetime = %d (%24.24s)", 513 length, lifetime, ctime(&exp)); 514 else 515 /* number the URLs to make it easier to parse them */ 516 sprintf(get_line(0, 0), 517 "URL %d: length = %u, lifetime = %d (%24.24s)", 518 cnt, length, lifetime, ctime(&exp)); 519 520 if (length > msglength) { 521 if (!tcp_continuation) 522 /* framing error: message is not long enough to contain data */ 523 sprintf(get_line(0, 0), 524 " [Framing error: remaining pkt length = %u]", 525 msglength); 526 return (-1); 527 } 528 529 if (length > 0) { 530 char *buf = malloc(length + 1); 531 if (buf != NULL) { 532 memcpy(buf, p, length); 533 buf[length] = '\0'; /* ensure null-terminated */ 534 sprintf(get_line(0, 0), " \"%s\"", buf); 535 free(buf); 536 } 537 } 538 msglength -= length; 539 p += length; 540 541 get_byte(); 542 if ((n = netval) < 0) 543 return (-1); 544 545 if (n > 0) { 546 int i; 547 sprintf(get_line(0, 0), "%d Authentication Blocks", n); 548 for (i = 0; i < n; i++) 549 if ((length = slpv2_authblock(i)) < 0) 550 return (-1); 551 } 552 return (0); 553 } 554 555 #define DOFIELD(tag, type) \ 556 if (slp_field(tag, type) < 0) \ 557 return (0) 558 559 #define V2_DOURL(x) \ 560 if (slpv2_url(x) < 0) \ 561 return (0) 562 563 #define V2_DOERRCODE \ 564 if (msglength < sizeof (unsigned short)) \ 565 return (0); \ 566 nbtohs(); \ 567 errcode = netval; \ 568 sprintf(get_line(0, 0), "Error code = %d, %s", \ 569 errcode, slpv2_error(errcode)); \ 570 p += sizeof (unsigned short); \ 571 msglength -= sizeof (unsigned short); \ 572 if (errcode != OK) \ 573 msglength = 0; /* skip rest of message */ \ 574 if (errcode != OK) \ 575 return (0) 576 577 #define V2_DOAUTH(cnt) \ 578 if (slpv2_authblock(cnt) < 0) \ 579 return (0) 580 581 #define V2_DOTIMESTAMP \ 582 if (msglength < 4) \ 583 return (0); \ 584 nbtohl(); \ 585 timestamp = netval; \ 586 sprintf(get_line(0, 0), "Timestamp = %u, %s", \ 587 timestamp, (timestamp ? convert_ts(timestamp) : "0")); \ 588 p += 4; \ 589 msglength -= 4 590 591 /* some V1 macros */ 592 #define SKIPAUTH(auth) \ 593 if (auth && ((retlength = skip_v1authblock()) < 0)) \ 594 return (0) 595 596 #define DOERRCODE \ 597 if (msglength < sizeof (unsigned short)) \ 598 return (0); \ 599 nbtohs(); \ 600 errcode = netval; \ 601 sprintf(get_line(0, 0), "Error code = %d, %s", errcode, \ 602 slpv1_error(errcode)); \ 603 p += sizeof (unsigned short); \ 604 msglength -= sizeof (unsigned short); \ 605 if (errcode != OK) \ 606 return (0) 607 608 #define DOURL \ 609 if (slpv1_url(url_auth) < 0) \ 610 return (0) 611 612 #define DOAUTH(auth) \ 613 if (auth && slpv1_authblock() < 0) \ 614 return (0) 615 616 /* 617 * TCP Continuation handling 618 * We keep track of continuations in a fixed size cache, so as to prevent 619 * memory leaks if some continuations are never finished. The continuations 620 * are indexed by their destination ports. 621 */ 622 static void reg_tcp_cont(char *msg, int totallen, 623 int fraglen, int dst_port) { 624 struct tcp_cont *tce = malloc(sizeof (*tce)); 625 626 /* always overwrite the entry at current_tcp_cont */ 627 if (tcp_cont[current_tcp_cont]) { 628 free(tcp_cont[current_tcp_cont]->msg); 629 free(tcp_cont[current_tcp_cont]); 630 } 631 632 tce->dst_port = dst_port; 633 tce->msg = malloc(totallen); 634 memcpy(tce->msg, msg, fraglen); 635 tce->totallen = totallen; 636 tce->curr_offset = fraglen; 637 638 tcp_cont[current_tcp_cont++] = tce; 639 if (current_tcp_cont == MAX_TCPCONT) 640 current_tcp_cont = 0; 641 } 642 643 /* returns 0 if there is a mismatch error, 1 on success */ 644 static int add_tcp_cont(struct tcp_cont *tce, char *msg, int fraglen) { 645 if ((fraglen + tce->curr_offset) > tce->totallen) 646 return (0); 647 648 memcpy(tce->msg + tce->curr_offset, msg, fraglen); 649 tce->curr_offset += fraglen; 650 return (1); 651 } 652 653 static struct tcp_cont *find_tcp_cont(int dst_port) { 654 int i; 655 for (i = current_tcp_cont; i >= 0; i--) 656 if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) 657 return (tcp_cont[i]); 658 659 for (i = MAX_TCPCONT -1; i > current_tcp_cont; i--) 660 if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) 661 return (tcp_cont[i]); 662 663 return (NULL); 664 } 665 666 static void remove_tcp_cont(int dst_port) { 667 int i; 668 for (i = current_tcp_cont; i >= 0; i--) 669 if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) { 670 free(tcp_cont[i]->msg); 671 free(tcp_cont[i]); 672 tcp_cont[i] = NULL; 673 return; 674 } 675 676 for (i = MAX_TCPCONT -1; i > current_tcp_cont; i--) 677 if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) { 678 free(tcp_cont[i]->msg); 679 free(tcp_cont[i]); 680 tcp_cont[i] = NULL; 681 return; 682 } 683 } 684 685 /* 686 * V2 interpreter 687 */ 688 689 static int interpret_slp_v2(int flags, struct slpv2_hdr *slp, int fraglen) { 690 extern int src_port, dst_port, curr_proto; 691 char msgbuf_real[256]; 692 int totallen = 0; 693 694 msgbuf = msgbuf_real; 695 696 /* 697 * Somewhat of a hack to decode traffic from a server that does 698 * not send udp replies from its SLP src port. 699 */ 700 701 if (curr_proto == IPPROTO_UDP && 702 dst_port == 427 && 703 src_port != 427) { 704 add_transient(src_port, (int (*)())interpret_slp); 705 } 706 707 /* parse the header */ 708 if (v2_header(flags, slp, &totallen, fraglen)) { 709 710 if (slp->function <= V2_MAX_FUNCTION && slp->function > 0) { 711 712 /* Parse the message body */ 713 if ((v2_functions[slp->function])(flags)) { 714 715 /* finish any remaining tasks */ 716 v2_finish(slp, flags); 717 718 } 719 720 } 721 722 } 723 724 /* summary error check */ 725 if (flags & F_SUM) { 726 if (retlength < 0) { 727 if (curr_proto == IPPROTO_TCP) 728 sprintf(get_sum_line(), 729 "%s [partial TCP message]", msgbuf); 730 else if (overflow) 731 sprintf(get_sum_line(), "%s [OVERFLOW]", msgbuf); 732 else 733 sprintf(get_sum_line(), "%s [CORRUPTED MESSAGE]", msgbuf); 734 } 735 #ifdef VERIFYSLP 736 else if (msglength > 0) 737 sprintf(get_sum_line(), "%s +%d", msgbuf, msglength); 738 #endif 739 else 740 sprintf(get_sum_line(), "%s", msgbuf); 741 } else if (flags & F_DTAIL) { 742 /* detailed error check */ 743 if (msglength > 0) { 744 if (tcp_continuation) { 745 sprintf(get_line(0, 0), 746 "[TCP Continuation, %d bytes remaining]", 747 totallen - fraglen); 748 } else 749 sprintf(get_line(0, 0), 750 "[%d extra bytes at end of SLP message]", msglength); 751 } 752 753 show_trailer(); 754 755 if (tcp_continuation && msglength == 0) 756 remove_tcp_cont(dst_port); 757 } 758 759 return (0); 760 } 761 762 static int v2_header(int flags, 763 struct slpv2_hdr *slp, 764 int *totallen, 765 int fraglen) { 766 extern int curr_proto, dst_port; 767 char *prototag = (curr_proto == IPPROTO_TCP ? "/tcp" : ""); 768 769 if ((slp->flags & V2_OVERFLOW) == V2_OVERFLOW) 770 overflow = B_TRUE; 771 772 /* summary mode header parsing */ 773 if (flags & F_SUM) { 774 775 /* make sure we have at least a header */ 776 if (msglength < sizeof (*slp)) { 777 sprintf(get_sum_line(), "SLP V2 [Incomplete Header]"); 778 return (0); 779 } 780 781 sprintf(msgbuf, "SLP V2 %s [%d%s] ", 782 slpv2_func(slp->function, B_TRUE), 783 ntohs(slp->xid), prototag); 784 785 /* skip to end of header */ 786 msgend = msgbuf + strlen(msgbuf); 787 msglength -= sizeof (*slp); 788 p += sizeof (*slp); 789 790 /* skip language tag */ 791 SKIPFIELD(FIELD_DEFAULT); 792 } else if (flags & F_DTAIL) { 793 char *lang; 794 int len; 795 796 /* detailed mode header parsing */ 797 show_header("SLP: ", "Service Location Protocol (v2)", fraglen); 798 show_space(); 799 800 if (msglength < sizeof (*slp)) { 801 sprintf(get_line(0, 0), "==> Incomplete SLP header"); 802 return (0); 803 } 804 805 sprintf(get_line(0, 0), "Version = %d", slp->vers); 806 sprintf(get_line(0, 0), "Function = %d, %s", 807 slp->function, slpv2_func(slp->function, B_FALSE)); 808 get_int24(&(slp->l1)); 809 *totallen = netval; 810 sprintf(get_line(0, 0), "Message length = %u", *totallen); 811 /* check for TCP continuation */ 812 if (curr_proto == IPPROTO_TCP && 813 *totallen > msglength && 814 !tcp_continuation) { 815 tcp_continuation = B_TRUE; 816 reg_tcp_cont((char *)slp, *totallen, msglength, dst_port); 817 } 818 819 if (!tcp_continuation && *totallen != msglength) { 820 sprintf(get_line(0, 0), 821 " (Stated and on-the-wire lengths differ)"); 822 } 823 /* flags */ 824 sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags); 825 sprintf(get_line(0, 0), " %s", 826 getflag(slp->flags, V2_OVERFLOW, 827 "overflow", "no overflow")); 828 sprintf(get_line(0, 0), " %s", 829 getflag(slp->flags, V2_FRESH, 830 "fresh registration", "no fresh registration")); 831 sprintf(get_line(0, 0), " %s", 832 getflag(slp->flags, V2_MCAST, 833 "request multicast / broadcast", "unicast")); 834 /* check reserved flags that must be zero */ 835 if ((slp->flags & 7) != 0) { 836 sprintf(get_line(0, 0), 837 " .... .xxx = %d (reserved flags nonzero)", 838 slp->flags & 7); 839 } 840 /* end of flags */ 841 842 /* language tag */ 843 p = (char *)slp + sizeof (*slp); 844 msglength -= sizeof (*slp); 845 GETSHORT(len); 846 if (len > msglength) { 847 sprintf(get_line(0, 0), 848 "Language Tag Length = %u [CORRUPT MESSAGE]", 849 len); 850 return (0); 851 } 852 853 lang = get_line(0, 0); 854 strcpy(lang, "Language Tag = "); 855 strncat(lang, p, len); 856 sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid)); 857 858 /* set msglength to remaining length of SLP message */ 859 p += len; 860 msglength -= len; 861 } 862 863 return (1); 864 } 865 866 static int v2_finish(struct slpv2_hdr *slp, int flags) { 867 unsigned int firstop; 868 869 if (!(flags & F_DTAIL)) 870 return (1); 871 872 /* check for options */ 873 get_int24(&(slp->o1)); 874 firstop = netval; 875 876 if (firstop) { 877 unsigned short op_id; 878 unsigned short nextop; 879 char *op_class; 880 881 for (;;) { 882 unsigned short real_oplen; 883 884 if (msglength < 4) { 885 sprintf(get_line(0, 0), 886 "Option expected but not present"); 887 return (0); 888 } 889 890 nbtohs(); 891 op_id = netval; 892 p += sizeof (unsigned short); 893 msglength -= sizeof (unsigned short); 894 nbtohs(); 895 nextop = netval; 896 p += sizeof (unsigned short); 897 msglength -= sizeof (unsigned short); 898 899 real_oplen = nextop ? nextop : msglength; 900 901 /* known options */ 902 switch (op_id) { 903 case 1: 904 sprintf(get_line(0, 0), 905 "Option: Required Attribute Missing"); 906 DOFIELD("Template IDVer", FIELD_DEFAULT); 907 DOFIELD("Required Attrs", FIELD_DEFAULT); 908 break; 909 default: 910 sprintf(get_line(0, 0), "Option: Unknown"); 911 p += (real_oplen - 4); 912 msglength -= (real_oplen - 4); 913 break; 914 } 915 916 if (op_id < 0x3fff) 917 op_class = "Standardized, optional"; 918 else if (op_id < 0x7fff) 919 op_class = "Standardized, mandatory"; 920 else if (op_id < 0x8fff) 921 op_class = "Not standardized, private"; 922 else if (op_id < 0xffff) 923 op_class = "Reserved"; 924 sprintf(get_line(0, 0), "Option ID = 0x%04x, %s", 925 op_id, op_class); 926 if (nextop && 927 ((nextop - 4) > msglength) && 928 !tcp_continuation) { 929 sprintf(get_line(0, 0), 930 "[Framing error: remaining pkt length = %u]", 931 msglength); 932 return (0); 933 } 934 935 sprintf(get_line(0, 0), "Option Length = %u", real_oplen); 936 937 if (!nextop) 938 break; 939 } 940 } 941 942 return (1); 943 } 944 945 #ifdef VERIFYSLP 946 static int skip_v2authblock() { 947 unsigned short length, slen; 948 949 /* auth header */ 950 if (msglength < 10) 951 return (-1); 952 953 /* block descriptor: 2 bytes */ 954 p += sizeof (unsigned short); 955 /* length */ 956 nbtohs(); 957 length = netval; 958 p += sizeof (unsigned short); 959 /* timestamp */ 960 p += 4; 961 /* SPI String length */ 962 nbtohs(); 963 slen = netval; 964 p += sizeof (unsigned short); 965 966 msglength -= 10; 967 if (slen > msglength || length > (msglength + 10)) 968 return (-1); 969 970 p += slen; 971 msglength -= slen; 972 973 /* structured auth block */ 974 p += (length - 10 - slen); 975 msglength -= (length - 10 - slen); 976 return (0); 977 } 978 #endif 979 980 static char *display_bsd(unsigned short bsd) { 981 switch (bsd) { 982 case 1: return ("MD5 with RSA"); 983 case 2: return ("DSA with SHA-1"); 984 case 3: return ("Keyed HMAC with MD5"); 985 default: return ("Unknown BSD"); 986 } 987 } 988 989 static char *slpv2_func(int t, boolean_t s) { 990 static char buf[128]; 991 992 switch (t) { 993 case V2_SRVRQST: return s? "SrvRqst" : "Service Request"; 994 case V2_SRVRPLY: return s? "SrvRply" : "Service Reply"; 995 case V2_SRVREG: return s? "SrvReg" : "Service Registration"; 996 case V2_SRVDEREG: 997 return (s ? "SrvDereg" : "Service Deregistration"); 998 case V2_SRVACK: return s? "SrvAck" : "Service Acknowledge"; 999 case V2_ATTRRQST: return s? "AttrRqst" : "Attribute Request"; 1000 case V2_ATTRRPLY: return s? "AttrRply" : "Attribute Reply"; 1001 case V2_DAADVERT: return s? "DAAdvert" : "DA advertisement"; 1002 case V2_SRVTYPERQST: 1003 return (s ? "SrvTypeRqst" : "Service Type Request"); 1004 case V2_SRVTYPERPLY: 1005 return (s ? "SrvTypeRply" : "Service Type Reply"); 1006 case V2_SAADVERT: return s? "SAAdvert" : "SA advertisement"; 1007 } 1008 sprintf(buf, "(func %d)", t); 1009 return (s ? buf : "unknown function"); 1010 } 1011 1012 static char *slpv2_error(unsigned short code) { 1013 static char buf[128]; 1014 1015 switch (code) { 1016 case OK: return "ok"; 1017 case LANG_NOT_SUPPORTED: return "language not supported"; 1018 case PROTOCOL_PARSE_ERR: return "protocol parse error"; 1019 case INVALID_REGISTRATION: return "invalid registration"; 1020 case SCOPE_NOT_SUPPORTED: return "scope not supported"; 1021 case AUTHENTICATION_UNKNOWN: return "authentication unknown"; 1022 case V2_AUTHENTICATION_ABSENT: return "authentication absent"; 1023 case V2_AUTHENTICATION_FAILED: return "authentication failed"; 1024 case V2_VER_NOT_SUPPORTED: return "version not supported"; 1025 case V2_INTERNAL_ERROR: return "internal error"; 1026 case V2_DA_BUSY_NOW: return "DA busy"; 1027 case V2_OPTION_NOT_UNDERSTOOD: return "option not understood"; 1028 case V2_INVALID_UPDATE: return "invalid update"; 1029 case V2_RQST_NOT_SUPPORTED: return "request not supported"; 1030 case INVALID_LIFETIME: return "invalid lifetime"; 1031 } 1032 sprintf(buf, "error %d", code); 1033 return (buf); 1034 } 1035 1036 static char *convert_ts(unsigned int timestamp) { 1037 /* timestamp is in UNIX time */ 1038 static char buff[128]; 1039 1040 strcpy(buff, ctime((time_t *)×tamp)); 1041 buff[strlen(buff) - 1] = '\0'; 1042 return (buff); 1043 } 1044 1045 static int slpv2_authblock(int cnt) { 1046 unsigned short bsd, length, slen; 1047 char *pp, *scopes; 1048 unsigned int timestamp; 1049 1050 if (msglength < 10) { 1051 sprintf(get_line(0, 0), 1052 " [no room for auth block header: remaining msg length = %u]", 1053 msglength); 1054 return (-1); 1055 } 1056 1057 /* bsd */ 1058 nbtohs(); 1059 bsd = netval; 1060 p += sizeof (unsigned short); 1061 1062 /* length */ 1063 nbtohs(); 1064 length = netval; 1065 p += sizeof (unsigned short); 1066 1067 /* timestamp */ 1068 nbtohl(); 1069 timestamp = netval; 1070 p += 4; 1071 1072 /* SPI String length */ 1073 nbtohs(); 1074 slen = netval; 1075 p += sizeof (unsigned short); 1076 1077 msglength -= 10; 1078 if (slen > msglength) { 1079 sprintf(get_line(0, 0), 1080 " [no room for auth block scopes: remaining msg length = %u]", 1081 msglength); 1082 return (-1); 1083 } 1084 1085 if (length > (msglength + 10)) { 1086 if (!tcp_continuation) 1087 /* framing error: message is not long enough to contain data */ 1088 sprintf(get_line(0, 0), 1089 " [Framing error: remaining pkt length = %u]", 1090 msglength); 1091 return (-1); 1092 } 1093 1094 scopes = p; 1095 p += slen; 1096 msglength -= slen; 1097 1098 sprintf(get_line(0, 0), 1099 "Auth block %d: timestamp = %s", cnt, 1100 (timestamp) ? convert_ts(timestamp) : "0"); 1101 1102 pp = get_line(0, 0); 1103 strcpy(pp, " SPI = "); 1104 strncat(pp, scopes, slen); 1105 1106 sprintf(get_line(0, 0), 1107 " block desc = 0x%04x: %s", bsd, display_bsd(bsd)); 1108 1109 sprintf(get_line(0, 0), " length = %u", length); 1110 1111 p += (length - 10 - slen); 1112 msglength -= (length - 10 - slen); 1113 return (0); 1114 } 1115 1116 static int v2_srv_rqst(int flags) { 1117 if (flags & F_SUM) { 1118 SKIPFIELD(FIELD_DEFAULT); /* PR list */ 1119 GETFIELD; /* service type */ 1120 SKIPFIELD(FIELD_DEFAULT); /* scopes */ 1121 strcat(msgend, " ["); 1122 GETFIELD; /* predicate */ 1123 strcat(msgend, "]"); 1124 SKIPFIELD(FIELD_DEFAULT); /* SPI */ 1125 } else if (flags & F_DTAIL) { 1126 DOFIELD("Previous responders", FIELD_DEFAULT); 1127 DOFIELD("Service type", FIELD_DEFAULT); 1128 DOFIELD("Scopes", FIELD_DEFAULT); 1129 DOFIELD("Predicate string", FIELD_DEFAULT); 1130 DOFIELD("Requested SPI", FIELD_DEFAULT); 1131 } 1132 1133 return (1); 1134 } 1135 1136 static int v2_srv_rply(int flags) { 1137 unsigned short itemcnt, errcode; 1138 int n; 1139 1140 if (flags & F_SUM) { 1141 int i, auth_cnt; 1142 1143 GETSHORT(errcode); 1144 if (errcode != OK) { 1145 strcat(msgbuf, slpv2_error(errcode)); 1146 msglength = 0; /* skip rest of message */ 1147 return (0); 1148 } else { 1149 GETSHORT(itemcnt); 1150 sprintf(msgend, "%d URL entries", itemcnt); 1151 #ifdef VERIFYSLP 1152 for (n = 0; n < itemcnt; n++) { 1153 SKIPBYTE; /* reserved */ 1154 SKIPSHORT; /* lifetime */ 1155 SKIPFIELD(FIELD_DEFAULT); /* URL */ 1156 GETBYTE(auth_cnt); 1157 for (i = 0; i < auth_cnt; auth_cnt++) 1158 if (skip_v2authblock() < 0) 1159 return (0); 1160 } 1161 #endif 1162 } 1163 } else if (flags & F_DTAIL) { 1164 V2_DOERRCODE; 1165 GETSHORT(itemcnt); 1166 sprintf(get_line(0, 0), "URL entry count = %d", itemcnt); 1167 for (n = 0; n < itemcnt; n++) { 1168 V2_DOURL(n); 1169 } 1170 } 1171 1172 return (1); 1173 } 1174 1175 static int v2_srv_reg(int flags) { 1176 int i, auth_cnt; 1177 1178 if (flags & F_SUM) { 1179 SKIPBYTE; /* reserved */ 1180 SKIPSHORT; /* lifetime */ 1181 GETFIELD; /* URL */ 1182 #ifdef VERIFYSLP 1183 GETBYTE(auth_cnt); 1184 for (i = 0; i < auth_cnt; i++) 1185 if (skip_v2authblock() < 0) 1186 return (0); 1187 SKIPFIELD(FIELD_DEFAULT); /* type */ 1188 SKIPFIELD(FIELD_DEFAULT); /* scopes */ 1189 SKIPFIELD(FIELD_DEFAULT); /* attrs */ 1190 GETBYTE(auth_cnt); 1191 for (i = 0; i < auth_cnt; i++) 1192 if (skip_v2authblock() < 0) 1193 return (0); 1194 #endif 1195 } if (flags & F_DTAIL) { 1196 V2_DOURL(-1); 1197 DOFIELD("Service type", FIELD_DEFAULT); 1198 DOFIELD("Scopes", FIELD_DEFAULT); 1199 DOFIELD("Attribute list", FIELD_DEFAULT); 1200 /* auth */ 1201 GETBYTE(auth_cnt); 1202 for (i = 0; i < auth_cnt; i++) 1203 V2_DOAUTH(i); 1204 } 1205 1206 return (1); 1207 } 1208 1209 static int v2_srv_dereg(int flags) { 1210 if (flags & F_SUM) { 1211 int i, auth_cnt; 1212 1213 SKIPFIELD(FIELD_DEFAULT); /* scopes */ 1214 SKIPBYTE; /* reserved */ 1215 SKIPSHORT; /* lifetime */ 1216 GETFIELD; /* URL */ 1217 1218 #ifdef VERIFYSLP 1219 GETBYTE(auth_cnt); 1220 for (i = 0; i < auth_cnt; i++) 1221 if (skip_v2authblock() < 0) 1222 return (0); 1223 SKIPFIELD(FIELD_DEFAULT); /* attrs */ 1224 #endif 1225 } else if (flags & F_DTAIL) { 1226 DOFIELD("Scopes", FIELD_DEFAULT); 1227 V2_DOURL(-1); 1228 DOFIELD("Tag list", FIELD_DEFAULT); 1229 } 1230 1231 return (1); 1232 } 1233 1234 static int v2_srv_ack(int flags) { 1235 unsigned short errcode; 1236 if (flags & F_SUM) { 1237 GETSHORT(errcode); 1238 strcat(msgbuf, slpv2_error(errcode)); 1239 } else if (flags & F_DTAIL) { 1240 V2_DOERRCODE; 1241 } 1242 1243 return (1); 1244 } 1245 1246 static int v2_attr_rqst(int flags) { 1247 if (flags & F_SUM) { 1248 SKIPFIELD(FIELD_DEFAULT); /* PR list */ 1249 GETFIELD; /* URL */ 1250 SKIPFIELD(FIELD_DEFAULT); /* scopes */ 1251 strcat(msgend, " ["); 1252 GETFIELD; /* attrs */ 1253 strcat(msgend, "]"); 1254 1255 #ifdef VERIFYSLP 1256 SKIPFIELD(FIELD_DEFAULT); /* SPI */ 1257 #endif 1258 } else if (flags & F_DTAIL) { 1259 DOFIELD("Previous responders", FIELD_DEFAULT); 1260 DOFIELD("URL", FIELD_DEFAULT); 1261 DOFIELD("Scopes", FIELD_DEFAULT); 1262 DOFIELD("Tag list", FIELD_DEFAULT); 1263 DOFIELD("Requested SPI", FIELD_DEFAULT); 1264 } 1265 1266 return (1); 1267 } 1268 1269 static int v2_attr_rply(int flags) { 1270 int auth_cnt, i; 1271 unsigned short errcode; 1272 1273 if (flags & F_SUM) { 1274 GETSHORT(errcode); 1275 if (errcode != OK) { 1276 strcat(msgbuf, slpv2_error(errcode)); 1277 msglength = 0; /* skip rest of message */ 1278 return (0); 1279 } else { 1280 GETFIELD; /* attr list */ 1281 1282 #ifdef VERIFYSLP 1283 GETBYTE(auth_cnt); 1284 for (i = 0; i < auth_cnt; i++) 1285 if (skip_v2authblock() < 0) 1286 return (0); 1287 #endif 1288 } 1289 } else if (flags & F_DTAIL) { 1290 V2_DOERRCODE; 1291 DOFIELD("Attribute list", FIELD_DEFAULT); 1292 /* auth */ 1293 GETBYTE(auth_cnt); 1294 for (i = 0; i < auth_cnt; i++) 1295 V2_DOAUTH(i); 1296 } 1297 1298 return (1); 1299 } 1300 1301 static int v2_daadvert(int flags) { 1302 int auth_cnt, i; 1303 unsigned short errcode; 1304 unsigned int timestamp; 1305 1306 if (flags & F_SUM) { 1307 SKIPSHORT; /* error code */ 1308 SKIPSHORT; SKIPSHORT; /* timestamp */ 1309 GETFIELD; /* URL */ 1310 1311 #ifdef VERIFYSLP 1312 SKIPFIELD(FIELD_DEFAULT); /* scopes */ 1313 SKIPFIELD(FIELD_DEFAULT); /* attrs */ 1314 SKIPFIELD(FIELD_DEFAULT); /* SPIs */ 1315 1316 GETBYTE(auth_cnt); 1317 for (i = 0; i < auth_cnt; i++) 1318 if (skip_v2authblock() < 0) 1319 return (0); 1320 #endif 1321 } else if (flags & F_DTAIL) { 1322 V2_DOERRCODE; 1323 V2_DOTIMESTAMP; 1324 DOFIELD("URL", FIELD_DEFAULT); 1325 DOFIELD("Scope list", FIELD_DEFAULT); 1326 DOFIELD("Attribute list", FIELD_DEFAULT); 1327 DOFIELD("Configured SPIs", FIELD_DEFAULT); 1328 /* auth */ 1329 GETBYTE(auth_cnt); 1330 for (i = 0; i < auth_cnt; i++) 1331 V2_DOAUTH(i); 1332 } 1333 1334 return (1); 1335 } 1336 1337 static int v2_srv_type_rqst(int flags) { 1338 if (flags & F_SUM) { 1339 SKIPFIELD(FIELD_DEFAULT); /* prev responders */ 1340 SKIPFIELD(FIELD_TYPENA); /* naming authority */ 1341 GETFIELD; /* scope */ 1342 } else if (flags & F_DTAIL) { 1343 DOFIELD("Previous responders", FIELD_DEFAULT); 1344 DOFIELD("Naming authority", FIELD_TYPENA); 1345 DOFIELD("Scopes", FIELD_DEFAULT); 1346 } 1347 1348 return (1); 1349 } 1350 1351 static int v2_srv_type_rply(int flags) { 1352 unsigned short errcode; 1353 1354 if (flags & F_SUM) { 1355 GETSHORT(errcode); 1356 if (errcode != OK) 1357 strcat(msgbuf, slpv2_error(errcode)); 1358 else 1359 GETFIELD; 1360 } else if (flags & F_DTAIL) { 1361 V2_DOERRCODE; 1362 DOFIELD("Service types", FIELD_DEFAULT); 1363 } 1364 1365 return (1); 1366 } 1367 1368 static int v2_saadvert(int flags) { 1369 int auth_cnt, i; 1370 1371 if (flags & F_SUM) { 1372 GETFIELD; /* URL */ 1373 1374 #ifdef VERIFYSLP 1375 SKIPFIELD(FIELD_DEFAULT); /* scopes */ 1376 SKIPFIELD(FIELD_DEFAULT); /* attrs */ 1377 1378 GETBYTE(auth_cnt); 1379 for (i = 0; i < auth_cnt; i++) 1380 if (skip_v2authblock() < 0) 1381 return (0); 1382 #endif 1383 } else if (flags & F_DTAIL) { 1384 DOFIELD("URL", FIELD_DEFAULT); 1385 DOFIELD("Scopes", FIELD_DEFAULT); 1386 DOFIELD("Attribute list", FIELD_DEFAULT); 1387 /* auth */ 1388 GETBYTE(auth_cnt); 1389 for (i = 0; i < auth_cnt; i++) 1390 V2_DOAUTH(i); 1391 } 1392 1393 return (1); 1394 } 1395 1396 /* 1397 * V1 Interpreter 1398 */ 1399 1400 static int interpret_slp_v1(int flags, struct slpv1_hdr *slp, int fraglen) { 1401 char msgbuf_real[256]; 1402 extern int src_port, dst_port, curr_proto; 1403 boolean_t overflow = B_FALSE; 1404 1405 msgbuf = msgbuf_real; 1406 1407 if (msglength >= sizeof (*slp)) { 1408 if ((slp->flags & V1_URL_AUTH) == V1_URL_AUTH) 1409 url_auth = B_TRUE; 1410 if ((slp->flags & V1_ATTR_AUTH) == V1_ATTR_AUTH) 1411 attr_auth = B_TRUE; 1412 if ((slp->flags & V1_FRESH_REG) == V1_FRESH_REG) 1413 fresh = B_TRUE; 1414 if ((slp->flags & V1_OVERFLOW) == V1_OVERFLOW) 1415 overflow = B_TRUE; 1416 } 1417 1418 /* 1419 * Somewhat of a hack to decode traffic from a server that does 1420 * not send udp replies from its SLP src port. 1421 */ 1422 if (curr_proto == IPPROTO_UDP && 1423 dst_port == 427 && 1424 src_port != 427) 1425 add_transient(src_port, (int (*)())interpret_slp); 1426 1427 /* parse the header */ 1428 if (v1_header(flags, slp, fraglen)) { 1429 1430 if (slp->function <= V1_MAX_FUNCTION && slp->function > 0) { 1431 1432 /* Parse the message body */ 1433 (v1_functions[slp->function])(flags); 1434 1435 } 1436 1437 } 1438 1439 /* summary error check */ 1440 if (flags & F_SUM) { 1441 if (retlength < 0) { 1442 if (curr_proto == IPPROTO_TCP) 1443 sprintf(get_sum_line(), 1444 "%s [partial TCP message]", 1445 msgbuf); 1446 else if (overflow) 1447 sprintf(get_sum_line(), "%s [OVERFLOW]", msgbuf); 1448 else 1449 sprintf(get_sum_line(), "%s [CORRUPTED MESSAGE]", msgbuf); 1450 } 1451 #ifdef VERIFYSLP 1452 else if (msglength > 0) 1453 sprintf(get_sum_line(), "%s +%d", msgbuf, msglength); 1454 #endif 1455 else 1456 sprintf(get_sum_line(), "%s", msgbuf); 1457 } else if (flags & F_DTAIL) { 1458 /* detail error check */ 1459 if (msglength > 0) { 1460 sprintf(get_line(0, 0), 1461 "[%d extra bytes at end of SLP message]", msglength); 1462 } 1463 1464 show_trailer(); 1465 1466 } 1467 1468 v1_charset = 0; 1469 1470 return (0); 1471 } 1472 1473 static int v1_header(int flags, 1474 struct slpv1_hdr *slp, 1475 int fraglen) { 1476 extern int src_port, dst_port, curr_proto; 1477 char *prototag = (curr_proto == IPPROTO_TCP? "/tcp" : ""); 1478 1479 if (flags & F_SUM) { 1480 char portflag = ' '; 1481 1482 if (msglength < sizeof (*slp)) { 1483 sprintf(msgbuf, "SLP V1 [incomplete header]"); 1484 return (0); 1485 } 1486 1487 if (slp->vers != 1) { 1488 if (curr_proto == IPPROTO_TCP) 1489 sprintf(msgbuf, "SLP [TCP Continuation]"); 1490 else 1491 sprintf(msgbuf, "SLP [unknown version %d]", slp->vers); 1492 return (0); 1493 } 1494 1495 if (src_port != 427 && dst_port != 427) 1496 portflag = '-'; 1497 1498 sprintf(msgbuf, "SLP V1%c%s [%d%s] ", portflag, 1499 slpv1_func(slp->function, B_TRUE), 1500 ntohs(slp->xid), prototag); 1501 msgend = msgbuf + strlen(msgbuf); 1502 msglength -= sizeof (*slp); 1503 p += sizeof (*slp); 1504 } else if (flags & F_DTAIL) { 1505 show_header("SLP: ", "Service Location Protocol (v1)", fraglen); 1506 show_space(); 1507 1508 if (msglength < sizeof (*slp)) { 1509 sprintf(get_line(0, 0), "==> Incomplete SLP header"); 1510 return (0); 1511 } 1512 1513 sprintf(get_line(0, 0), "Version = %d", slp->vers); 1514 if (slp->vers != 1) { 1515 if (curr_proto == IPPROTO_TCP) 1516 sprintf(get_line(0, 0), "==> TCP continuation"); 1517 else 1518 sprintf(get_line(0, 0), "==> Unexpected version number"); 1519 return (0); 1520 } 1521 sprintf(get_line(0, 0), "Function = %d, %s", 1522 slp->function, slpv1_func(slp->function, B_FALSE)); 1523 sprintf(get_line(0, 0), "Message length = %u", ntohs(slp->length)); 1524 1525 /* flags */ 1526 sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags); 1527 sprintf(get_line(0, 0), " %s", 1528 getflag(slp->flags, V1_OVERFLOW, 1529 "overflow", "no overflow")); 1530 sprintf(get_line(0, 0), " %s", 1531 getflag(slp->flags, V1_MONOLINGUAL, 1532 "monolingual", "not monolingual")); 1533 sprintf(get_line(0, 0), " %s", 1534 getflag(slp->flags, V1_URL_AUTH, 1535 "url authentication", "no url authentication")); 1536 sprintf(get_line(0, 0), " %s", 1537 getflag(slp->flags, V1_ATTR_AUTH, 1538 "attribute authentication", "no attribute authentication")); 1539 sprintf(get_line(0, 0), " %s", 1540 getflag(slp->flags, V1_FRESH_REG, 1541 "fresh registration", "no fresh registration")); 1542 /* check reserved flags that must be zero */ 1543 if ((slp->flags & 7) != 0) { 1544 sprintf(get_line(0, 0), 1545 " .... .xxx = %d (reserved flags nonzero)", 1546 slp->flags & 7); 1547 } 1548 /* end of flags */ 1549 1550 sprintf(get_line(0, 0), "Dialect = %u", slp->dialect); 1551 sprintf(get_line(0, 0), "Language = 0x%02x%02x, %c%c", 1552 slp->language[0], slp->language[1], 1553 slp->language[0], slp->language[1]); 1554 v1_charset = ntohs(slp->charset); 1555 sprintf(get_line(0, 0), "Character encoding = %u, %s", 1556 v1_charset, 1557 slpv1_charset(v1_charset)); 1558 sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid)); 1559 1560 /* set msglength to remaining length of SLP message */ 1561 msglength -= sizeof (*slp); 1562 p += sizeof (*slp); 1563 } 1564 1565 return (1); 1566 } 1567 1568 static char *slpv1_func(int t, boolean_t s) { 1569 static char buf[128]; 1570 switch (t) { 1571 case V1_SRVREQ: return s? "SrvRqst" : "Service Request"; 1572 case V1_SRVRPLY: return s? "SrvRply" : "Service Reply"; 1573 case V1_SRVREG: return s? "SrvReg" : "Service Registration"; 1574 case V1_SRVDEREG: return s? 1575 "SrvDereg" : "Service Deregistration"; 1576 case V1_SRVACK: return s? "SrvAck" : "Service Acknowledge"; 1577 case V1_ATTRRQST: return s? "AttrRqst" : "Attribute Request"; 1578 case V1_ATTRRPLY: return s? "AttrRply" : "Attribute Reply"; 1579 case V1_DAADVERT: return s? "DAAdvert" : "DA advertisement"; 1580 case V1_SRVTYPERQST:return s? "SrvTypeRqst" : "Service Type Request"; 1581 case V1_SRVTYPERPLY:return s? "SrvTypeRply" : "Service Type Reply"; 1582 } 1583 sprintf(buf, "(func %d)", t); 1584 return (s ? buf : "unknown function"); 1585 } 1586 1587 static char *slpv1_error(unsigned short code) { 1588 static char buf[128]; 1589 1590 switch (code) { 1591 case OK: return "ok"; 1592 case LANG_NOT_SUPPORTED: return "language not supported"; 1593 case PROTOCOL_PARSE_ERR: return "protocol parse error"; 1594 case INVALID_REGISTRATION: return "invalid registration"; 1595 case SCOPE_NOT_SUPPORTED: return "scope not supported"; 1596 case CHARSET_NOT_UNDERSTOOD:return "character set not understood"; 1597 case AUTHENTICATION_INVALID:return "invalid authentication"; 1598 case NOT_SUPPORTED_YET: return "not yet supported"; 1599 case REQUEST_TIMED_OUT: return "request timed out"; 1600 case COULD_NOT_INIT_NET_RESOURCES: 1601 return ("could not initialize net resources"); 1602 case COULD_NOT_ALLOCATE_MEMORY: 1603 return ("could not allocate memory"); 1604 case PARAMETER_BAD: return "bad parameter"; 1605 case INTERNAL_NET_ERROR: return "internal network error"; 1606 case INTERNAL_SYSTEM_ERROR: return "internal system error"; 1607 } 1608 sprintf(buf, "error %d", code); 1609 return (buf); 1610 } 1611 1612 /* 1613 * Character set info from 1614 * www.isi.edu/in-notes/iana/assignments/character-sets 1615 * 1616 * Assigned MIB enum Numbers 1617 * ------------------------- 1618 * 0 Reserved 1619 * 1 Reserved 1620 * 3-106 Set By Standards Organizations 1621 * 1000-1010 Unicode / 10646 1622 * 2000-2087 Vendor 1623 * 2250-2258 Vendor 1624 * 1625 * MIBenum: 3 1626 * Alias: US-ASCII (preferred MIME name) 1627 * Source: ECMA registry [RFC1345] 1628 * 1629 * MIBenum: 106 1630 * Name: UTF-8 1631 * Source: RFC 2044 1632 */ 1633 1634 static char *slpv1_charset(unsigned short code) { 1635 if (code <= 1) 1636 return ("Reserved"); 1637 if (code == 3) 1638 return ("US-ASCII"); 1639 if (code == 4) 1640 return ("latin1"); 1641 if (code == 106) 1642 return ("UTF-8"); 1643 if (code >= 3 && code <= 106) 1644 return ("set by standards organization"); 1645 if (code >= 1000 && code <= 1010) 1646 return ("Unicode variant"); 1647 if ((code >= 2000 && code <= 2087) || 1648 (code >= 2250 && code <= 2258)) 1649 return ("Vendor assigned"); 1650 1651 return ("unknown"); 1652 } 1653 1654 #ifdef VERIFYSLP 1655 static int skip_v1authblock() { 1656 unsigned short length; 1657 1658 /* auth header: 12 bytes total */ 1659 if (msglength < 12) 1660 return (-1); 1661 1662 /* timestamp: 8 bytes */ 1663 p += 8; /* timestamp: 8 bytes */ 1664 p += sizeof (short); /* block descriptor: 2 bytes */ 1665 nbtohs(); 1666 length = netval; 1667 p += sizeof (short); 1668 msglength -= 12; 1669 1670 if (length > msglength) { 1671 /* framing error: message is not long enough to contain data */ 1672 return (-1); 1673 } 1674 1675 p += length; 1676 msglength -= length; 1677 return (0); 1678 } 1679 #endif 1680 1681 static int slpv1_authblock() { 1682 unsigned short bsd, length; 1683 char msgbuf[128]; 1684 int n; 1685 1686 if (msglength < 12) { 1687 sprintf(get_line(0, 0), 1688 " [no room for auth block: remaining msg length = %u]", 1689 msglength); 1690 return (-1); 1691 } 1692 1693 /* timestamp: 8 bytes */ 1694 *msgbuf = '\0'; 1695 for (n = 0; n < 8; n++, p += 1) { 1696 char tmp[16]; 1697 sprintf(tmp, "%02x", (unsigned char)(*p)); 1698 strcat(msgbuf, tmp); 1699 } 1700 1701 nbtohs(); 1702 bsd = netval; 1703 p += sizeof (short); 1704 nbtohs(); 1705 length = netval; 1706 p += sizeof (short); 1707 msglength -= 12; 1708 1709 sprintf(get_line(0, 0), 1710 " Auth block: timestamp = %s", 1711 msgbuf); 1712 sprintf(get_line(0, 0), 1713 " block desc = 0x%04x, length = %u", 1714 bsd, length); 1715 if (length > msglength) { 1716 /* framing error: message is not long enough to contain data */ 1717 sprintf(get_line(0, 0), 1718 " [Framing error: remaining pkt length = %u]", msglength); 1719 return (-1); 1720 } 1721 1722 p += length; 1723 msglength -= length; 1724 return (0); 1725 } 1726 1727 static int slpv1_url(boolean_t auth_present) { 1728 time_t exp; 1729 int lifetime, length; 1730 1731 get_short(); 1732 if ((lifetime = netval) < 0) 1733 return (-1); 1734 get_short(); 1735 if ((length = netval) < 0) 1736 return (-1); 1737 1738 exp = time(0) + lifetime; 1739 sprintf(get_line(0, 0), "URL: length = %u, lifetime = %d (%24.24s)", 1740 length, lifetime, ctime(&exp)); 1741 if (length > msglength) { 1742 /* framing error: message is not long enough to contain data */ 1743 sprintf(get_line(0, 0), 1744 " [Framing error: remaining pkt length = %u]", msglength); 1745 return (-1); 1746 } 1747 1748 if (length > 0) { 1749 char *buf = malloc(length + 1); 1750 if (buf != NULL) { 1751 if (!make_utf8(buf, length, p, length)) { 1752 strcpy(buf, "[Invalid Character Encoding]"); 1753 } 1754 sprintf(get_line(0, 0), " \"%s\"", buf); 1755 free(buf); 1756 } 1757 } 1758 msglength -= length; 1759 p += length; 1760 1761 if (auth_present) 1762 return (slpv1_authblock()); 1763 1764 return (0); 1765 } 1766 1767 static int v1_srv_rqst(int flags) { 1768 if (flags & F_SUM) { 1769 SKIPFIELD(FIELD_PREVRESP); /* prev responders */ 1770 GETFIELD; /* predicate */ 1771 } else if (flags & F_DTAIL) { 1772 DOFIELD("Previous responders", FIELD_PREVRESP); 1773 DOFIELD("predicate string", FIELD_DEFAULT); 1774 } 1775 1776 return (1); 1777 } 1778 1779 static int v1_srv_rply(int flags) { 1780 unsigned short errcode, itemcnt; 1781 int n; 1782 1783 if (flags & F_SUM) { 1784 GETSHORT(errcode); 1785 if (errcode != OK) { 1786 strcat(msgbuf, slpv1_error(errcode)); 1787 } else { 1788 GETSHORT(itemcnt); 1789 sprintf(msgend, "%d URL entries", itemcnt); 1790 #ifdef VERIFYSLP 1791 for (n = 0; n < itemcnt; n++) { 1792 SKIPSHORT; /* lifetime */ 1793 SKIPFIELD(FIELD_DEFAULT); /* URL */ 1794 SKIPAUTH(url_auth); /* URL auth */ 1795 } 1796 #endif 1797 } 1798 } else if (flags & F_DTAIL) { 1799 DOERRCODE; 1800 GETSHORT(itemcnt); 1801 sprintf(get_line(0, 0), "URL entry count = %d", itemcnt); 1802 for (n = 0; n < itemcnt; n++) { 1803 DOURL; 1804 } 1805 } 1806 1807 return (1); 1808 } 1809 1810 static int v1_srv_reg(int flags) { 1811 if (flags & F_SUM) { 1812 SKIPSHORT; /* lifetime */ 1813 GETFIELD; /* URL */ 1814 #ifdef VERIFYSLP 1815 SKIPAUTH(url_auth); /* URL auth */ 1816 SKIPFIELD(FIELD_DEFAULT); /* attribute list */ 1817 SKIPAUTH(attr_auth); /* attr auth */ 1818 #endif 1819 } else if (flags & F_DTAIL) { 1820 DOURL; 1821 DOFIELD("Attribute list", FIELD_DEFAULT); 1822 DOAUTH(attr_auth); 1823 } 1824 1825 return (1); 1826 } 1827 1828 static int v1_srv_ack(int flags) { 1829 unsigned short errcode; 1830 1831 if (flags & F_SUM) { 1832 GETSHORT(errcode); 1833 strcat(msgbuf, slpv1_error(errcode)); 1834 if (errcode == OK && fresh) { 1835 strcat(msgbuf, " [Fresh]"); 1836 } 1837 } else if (flags & F_DTAIL) { 1838 DOERRCODE; 1839 } 1840 1841 return (1); 1842 } 1843 1844 static int v1_srv_dereg(int flags) { 1845 if (flags & F_SUM) { 1846 GETFIELD; /* URL */ 1847 #ifdef VERIFYSLP 1848 SKIPAUTH(url_auth); 1849 SKIPFIELD(FIELD_DEFAULT); /* tag spec */ 1850 #endif 1851 } else if (flags & F_DTAIL) { 1852 DOFIELD("URL", FIELD_DEFAULT); 1853 DOAUTH(url_auth); 1854 DOFIELD("Tag spec", FIELD_DEFAULT); 1855 } 1856 1857 return (1); 1858 } 1859 1860 static int v1_attr_rqst(int flags) { 1861 if (flags & F_SUM) { 1862 SKIPFIELD(FIELD_PREVRESP); /* prev responders */ 1863 GETFIELD; /* URL */ 1864 #ifdef VERIFYSLP 1865 SKIPFIELD(FIELD_DEFAULT); /* scope */ 1866 SKIPFIELD(FIELD_DEFAULT); /* select list */ 1867 #endif 1868 } else if (flags & F_DTAIL) { 1869 DOFIELD("Previous responders", FIELD_PREVRESP); 1870 DOFIELD("URL", FIELD_DEFAULT); 1871 DOFIELD("Scope", FIELD_DEFAULT); 1872 DOFIELD("Select list", FIELD_DEFAULT); 1873 } 1874 1875 return (1); 1876 } 1877 1878 static int v1_attr_rply(int flags) { 1879 unsigned short errcode; 1880 1881 if (flags & F_SUM) { 1882 GETSHORT(errcode); 1883 if (errcode != OK) { 1884 strcat(msgbuf, slpv1_error(errcode)); 1885 } else { 1886 GETFIELD; /* attr list */ 1887 #ifdef VERIFYSLP 1888 SKIPAUTH(attr_auth); 1889 #endif 1890 } 1891 } else if (flags & F_DTAIL) { 1892 DOERRCODE; 1893 DOFIELD("Attribute list", FIELD_DEFAULT); 1894 DOAUTH(attr_auth); 1895 } 1896 1897 return (1); 1898 } 1899 1900 static int v1_daadvert(int flags) { 1901 unsigned short errcode; 1902 1903 if (flags & F_SUM) { 1904 GETSHORT(errcode); 1905 if (errcode != OK) { 1906 strcat(msgbuf, slpv1_error(errcode)); 1907 } else { 1908 GETFIELD; /* URL */ 1909 #ifdef VERIFYSLP 1910 SKIPFIELD(FIELD_DEFAULT); /* scope list */ 1911 #endif 1912 } 1913 } else if (flags & F_DTAIL) { 1914 DOERRCODE; 1915 DOFIELD("URL", FIELD_DEFAULT); 1916 DOFIELD("Scope list", FIELD_DEFAULT); 1917 } 1918 1919 return (1); 1920 } 1921 1922 static int v1_srv_type_rqst(int flags) { 1923 if (flags & F_SUM) { 1924 SKIPFIELD(FIELD_PREVRESP); /* prev responders */ 1925 SKIPFIELD(FIELD_TYPENA); /* naming authority */ 1926 GETFIELD; /* scope */ 1927 } else if (flags & F_DTAIL) { 1928 DOFIELD("Previous responders", FIELD_PREVRESP); 1929 DOFIELD("Naming authority", FIELD_TYPENA); 1930 DOFIELD("Scope string", FIELD_DEFAULT); 1931 } 1932 1933 return (1); 1934 } 1935 1936 static int v1_srv_type_rply(int flags) { 1937 unsigned short errcode, itemcnt; 1938 int n; 1939 1940 if (flags & F_SUM) { 1941 GETSHORT(errcode); 1942 if (errcode != OK) { 1943 strcat(msgbuf, slpv1_error(errcode)); 1944 } else { 1945 GETSHORT(itemcnt); 1946 sprintf(msgend, "%d type entries", itemcnt); 1947 #ifdef VERIFYSLP 1948 for (n = 0; n < itemcnt; n++) { 1949 SKIPFIELD(FIELD_DEFAULT); /* Service type item */ 1950 } 1951 #endif 1952 } 1953 } else if (flags & F_DTAIL) { 1954 DOERRCODE; 1955 GETSHORT(itemcnt); 1956 sprintf(get_line(0, 0), "Service type count = %d", itemcnt); 1957 for (n = 0; n < itemcnt; n++) { 1958 DOFIELD(" Service type item", FIELD_DEFAULT); 1959 } 1960 } 1961 1962 return (1); 1963 } 1964