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