1 /* 2 * This code unmangles RX packets. RX is the mutant form of RPC that AFS 3 * uses to communicate between clients and servers. 4 * 5 * In this code, I mainly concern myself with decoding the AFS calls, not 6 * with the guts of RX, per se. 7 * 8 * Bah. If I never look at rx_packet.h again, it will be too soon. 9 * 10 * Ken Hornstein <kenh@cmf.nrl.navy.mil> 11 * 12 */ 13 14 #ifndef lint 15 static const char rcsid[] = 16 "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.5.2.1 2000/01/11 06:58:27 fenner Exp $"; 17 #endif 18 19 #ifdef HAVE_CONFIG_H 20 #include "config.h" 21 #endif 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <sys/param.h> 26 #include <sys/time.h> 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <netinet/in.h> 30 #include <netinet/in_systm.h> 31 #include <netinet/ip.h> 32 #include <arpa/inet.h> 33 34 #include "interface.h" 35 #include "addrtoname.h" 36 37 #undef NOERROR /* Solaris sucks */ 38 #include <arpa/nameser.h> 39 40 #include "rx.h" 41 42 static struct tok rx_types[] = { 43 { RX_PACKET_TYPE_DATA, "data" }, 44 { RX_PACKET_TYPE_ACK, "ack" }, 45 { RX_PACKET_TYPE_BUSY, "busy" }, 46 { RX_PACKET_TYPE_ABORT, "abort" }, 47 { RX_PACKET_TYPE_ACKALL, "ackall" }, 48 { RX_PACKET_TYPE_CHALLENGE, "challenge" }, 49 { RX_PACKET_TYPE_RESPONSE, "response" }, 50 { RX_PACKET_TYPE_DEBUG, "debug" }, 51 { RX_PACKET_TYPE_PARAMS, "params" }, 52 { RX_PACKET_TYPE_VERSION, "version" }, 53 { 0, NULL }, 54 }; 55 56 static struct tok rx_flags[] = { 57 { RX_CLIENT_INITIATED, "client-init" }, 58 { RX_REQUEST_ACK, "req-ack" }, 59 { RX_LAST_PACKET, "last-pckt" }, 60 { RX_MORE_PACKETS, "more-pckts" }, 61 { RX_FREE_PACKET, "free-pckt" } 62 }; 63 64 static struct tok fs_req[] = { 65 { 130, "fetch-data" }, 66 { 131, "fetch-acl" }, 67 { 132, "fetch-status" }, 68 { 133, "store-data" }, 69 { 134, "store-acl" }, 70 { 135, "store-status" }, 71 { 136, "remove-file" }, 72 { 137, "create-file" }, 73 { 138, "rename" }, 74 { 139, "symlink" }, 75 { 140, "link" }, 76 { 141, "makedir" }, 77 { 142, "rmdir" }, 78 { 143, "oldsetlock" }, 79 { 144, "oldextlock" }, 80 { 145, "oldrellock" }, 81 { 146, "get-stats" }, 82 { 147, "give-cbs" }, 83 { 148, "get-vlinfo" }, 84 { 149, "get-vlstats" }, 85 { 150, "set-vlstats" }, 86 { 151, "get-rootvl" }, 87 { 152, "check-token" }, 88 { 153, "get-time" }, 89 { 154, "nget-vlinfo" }, 90 { 155, "bulk-stat" }, 91 { 156, "setlock" }, 92 { 157, "extlock" }, 93 { 158, "rellock" }, 94 { 159, "xstat-ver" }, 95 { 160, "get-xstat" }, 96 { 161, "dfs-lookup" }, 97 { 162, "dfs-flushcps" }, 98 { 163, "dfs-symlink" }, 99 { 0, NULL }, 100 }; 101 102 static struct tok cb_req[] = { 103 { 204, "callback" }, 104 { 205, "initcb" }, 105 { 206, "probe" }, 106 { 207, "getlock" }, 107 { 208, "getce" }, 108 { 209, "xstatver" }, 109 { 210, "getxstat" }, 110 { 211, "initcb2" }, 111 { 212, "whoareyou" }, 112 { 213, "initcb3" }, 113 { 214, "probeuuid" }, 114 { 0, NULL }, 115 }; 116 117 static struct tok pt_req[] = { 118 { 500, "new-user" }, 119 { 501, "where-is-it" }, 120 { 502, "dump-entry" }, 121 { 503, "add-to-group" }, 122 { 504, "name-to-id" }, 123 { 505, "id-to-name" }, 124 { 506, "delete" }, 125 { 507, "remove-from-group" }, 126 { 508, "get-cps" }, 127 { 509, "new-entry" }, 128 { 510, "list-max" }, 129 { 511, "set-max" }, 130 { 512, "list-entry" }, 131 { 513, "change-entry" }, 132 { 514, "list-elements" }, 133 { 515, "same-mbr-of" }, 134 { 516, "set-fld-sentry" }, 135 { 517, "list-owned" }, 136 { 518, "get-cps2" }, 137 { 519, "get-host-cps" }, 138 { 520, "update-entry" }, 139 { 0, NULL }, 140 }; 141 142 static struct tok vldb_req[] = { 143 { 501, "create-entry" }, 144 { 502, "delete-entry" }, 145 { 503, "get-entry-by-id" }, 146 { 504, "get-entry-by-name" }, 147 { 505, "get-new-volume-id" }, 148 { 506, "replace-entry" }, 149 { 507, "update-entry" }, 150 { 508, "setlock" }, 151 { 509, "releaselock" }, 152 { 510, "list-entry" }, 153 { 511, "list-attrib" }, 154 { 512, "linked-list" }, 155 { 513, "get-stats" }, 156 { 514, "probe" }, 157 { 515, "get-addrs" }, 158 { 516, "change-addr" }, 159 { 517, "create-entry-n" }, 160 { 518, "get-entry-by-id-n" }, 161 { 519, "get-entry-by-name-n" }, 162 { 520, "replace-entry-n" }, 163 { 521, "list-entry-n" }, 164 { 522, "list-attrib-n" }, 165 { 523, "linked-list-n" }, 166 { 524, "update-entry-by-name" }, 167 { 525, "create-entry-u" }, 168 { 526, "get-entry-by-id-u" }, 169 { 527, "get-entry-by-name-u" }, 170 { 528, "replace-entry-u" }, 171 { 529, "list-entry-u" }, 172 { 530, "list-attrib-u" }, 173 { 531, "linked-list-u" }, 174 { 532, "regaddr" }, 175 { 533, "get-addrs-u" }, 176 { 0, NULL }, 177 }; 178 179 static struct tok kauth_req[] = { 180 { 1, "auth-old" }, 181 { 21, "authenticate" }, 182 { 22, "authenticate-v2" }, 183 { 2, "change-pw" }, 184 { 3, "get-ticket-old" }, 185 { 23, "get-ticket" }, 186 { 4, "set-pw" }, 187 { 5, "set-fields" }, 188 { 6, "create-user" }, 189 { 7, "delete-user" }, 190 { 8, "get-entry" }, 191 { 9, "list-entry" }, 192 { 10, "get-stats" }, 193 { 11, "debug" }, 194 { 12, "get-pw" }, 195 { 13, "get-random-key" }, 196 { 14, "unlock" }, 197 { 15, "lock-status" }, 198 { 0, NULL }, 199 }; 200 201 static struct tok vol_req[] = { 202 { 100, "create-volume" }, 203 { 101, "delete-volume" }, 204 { 102, "restore" }, 205 { 103, "forward" }, 206 { 104, "end-trans" }, 207 { 105, "clone" }, 208 { 106, "set-flags" }, 209 { 107, "get-flags" }, 210 { 108, "trans-create" }, 211 { 109, "dump" }, 212 { 110, "get-nth-volume" }, 213 { 111, "set-forwarding" }, 214 { 112, "get-name" }, 215 { 113, "get-status" }, 216 { 114, "sig-restore" }, 217 { 115, "list-partitions" }, 218 { 116, "list-volumes" }, 219 { 117, "set-id-types" }, 220 { 118, "monitor" }, 221 { 119, "partition-info" }, 222 { 120, "reclone" }, 223 { 121, "list-one-volume" }, 224 { 122, "nuke" }, 225 { 123, "set-date" }, 226 { 124, "x-list-volumes" }, 227 { 125, "x-list-one-volume" }, 228 { 126, "set-info" }, 229 { 127, "x-list-partitions" }, 230 { 128, "forward-multiple" }, 231 { 0, NULL }, 232 }; 233 234 static struct tok bos_req[] = { 235 { 80, "create-bnode" }, 236 { 81, "delete-bnode" }, 237 { 82, "set-status" }, 238 { 83, "get-status" }, 239 { 84, "enumerate-instance" }, 240 { 85, "get-instance-info" }, 241 { 86, "get-instance-parm" }, 242 { 87, "add-superuser" }, 243 { 88, "delete-superuser" }, 244 { 89, "list-superusers" }, 245 { 90, "list-keys" }, 246 { 91, "add-key" }, 247 { 92, "delete-key" }, 248 { 93, "set-cell-name" }, 249 { 94, "get-cell-name" }, 250 { 95, "get-cell-host" }, 251 { 96, "add-cell-host" }, 252 { 97, "delete-cell-host" }, 253 { 98, "set-t-status" }, 254 { 99, "shutdown-all" }, 255 { 100, "restart-all" }, 256 { 101, "startup-all" }, 257 { 102, "set-noauth-flag" }, 258 { 103, "re-bozo" }, 259 { 104, "restart" }, 260 { 105, "start-bozo-install" }, 261 { 106, "uninstall" }, 262 { 107, "get-dates" }, 263 { 108, "exec" }, 264 { 109, "prune" }, 265 { 110, "set-restart-time" }, 266 { 111, "get-restart-time" }, 267 { 112, "start-bozo-log" }, 268 { 113, "wait-all" }, 269 { 114, "get-instance-strings" }, 270 { 0, NULL }, 271 }; 272 273 static struct tok ubik_req[] = { 274 { 10000, "vote-beacon" }, 275 { 10001, "vote-debug-old" }, 276 { 10002, "vote-sdebug-old" }, 277 { 10003, "vote-getsyncsite" }, 278 { 10004, "vote-debug" }, 279 { 10005, "vote-sdebug" }, 280 { 20000, "disk-begin" }, 281 { 20001, "disk-commit" }, 282 { 20002, "disk-lock" }, 283 { 20003, "disk-write" }, 284 { 20004, "disk-getversion" }, 285 { 20005, "disk-getfile" }, 286 { 20006, "disk-sendfile" }, 287 { 20007, "disk-abort" }, 288 { 20008, "disk-releaselocks" }, 289 { 20009, "disk-truncate" }, 290 { 20010, "disk-probe" }, 291 { 20011, "disk-writev" }, 292 { 20012, "disk-interfaceaddr" }, 293 { 20013, "disk-setversion" }, 294 { 0, NULL }, 295 }; 296 297 #define VOTE_LOW 10000 298 #define VOTE_HIGH 10005 299 #define DISK_LOW 20000 300 #define DISK_HIGH 20013 301 302 static struct tok cb_types[] = { 303 { 1, "exclusive" }, 304 { 2, "shared" }, 305 { 3, "dropped" }, 306 { 0, NULL }, 307 }; 308 309 static struct tok ubik_lock_types[] = { 310 { 1, "read" }, 311 { 2, "write" }, 312 { 3, "wait" }, 313 { 0, NULL }, 314 }; 315 316 static char *voltype[] = { "read-write", "read-only", "backup" }; 317 318 /* 319 * Cache entries we keep around so we can figure out the RX opcode 320 * numbers for replies. This allows us to make sense of RX reply packets. 321 */ 322 323 struct rx_cache_entry { 324 u_int32_t callnum; /* Call number (net order) */ 325 struct in_addr client; /* client IP address (net order) */ 326 struct in_addr server; /* server IP address (net order) */ 327 int dport; /* server port (host order) */ 328 u_short serviceId; /* Service identifier (net order) */ 329 u_int32_t opcode; /* RX opcode (host order) */ 330 }; 331 332 #define RX_CACHE_SIZE 64 333 334 static struct rx_cache_entry rx_cache[RX_CACHE_SIZE]; 335 336 static int rx_cache_next = 0; 337 static int rx_cache_hint = 0; 338 static void rx_cache_insert(const u_char *, const struct ip *, int, int); 339 static int rx_cache_find(const struct rx_header *, const struct ip *, 340 int, int32_t *); 341 342 static void fs_print(const u_char *, int); 343 static void fs_reply_print(const u_char *, int, int32_t); 344 static void acl_print(u_char *, u_char *); 345 static void cb_print(const u_char *, int); 346 static void cb_reply_print(const u_char *, int, int32_t); 347 static void prot_print(const u_char *, int); 348 static void prot_reply_print(const u_char *, int, int32_t); 349 static void vldb_print(const u_char *, int); 350 static void vldb_reply_print(const u_char *, int, int32_t); 351 static void kauth_print(const u_char *, int); 352 static void kauth_reply_print(const u_char *, int, int32_t); 353 static void vol_print(const u_char *, int); 354 static void vol_reply_print(const u_char *, int, int32_t); 355 static void bos_print(const u_char *, int); 356 static void bos_reply_print(const u_char *, int, int32_t); 357 static void ubik_print(const u_char *, int); 358 static void ubik_reply_print(const u_char *, int, int32_t); 359 360 static int is_ubik(u_int32_t); 361 362 /* 363 * Handle the rx-level packet. See if we know what port it's going to so 364 * we can peek at the afs call inside 365 */ 366 367 void 368 rx_print(register const u_char *bp, int length, int sport, int dport, 369 u_char *bp2) 370 { 371 register struct rx_header *rxh; 372 int i; 373 int32_t opcode; 374 375 if (snapend - bp < sizeof (struct rx_header)) { 376 printf(" [|rx] (%d)", length); 377 return; 378 } 379 380 rxh = (struct rx_header *) bp; 381 382 printf(" rx %s", tok2str(rx_types, "type %d", rxh->type)); 383 384 if (vflag > 1) { 385 int firstflag = 0; 386 printf(" cid %08x call# %d seq %d ser %d", 387 (int) ntohl(rxh->cid), 388 (int) ntohl(rxh->callNumber), 389 (int) ntohl(rxh->seq), 390 (int) ntohl(rxh->serial)); 391 if (vflag > 2) 392 printf(" secindex %d serviceid %hu", 393 (int) rxh->securityIndex, 394 ntohs(rxh->serviceId)); 395 for (i = 0; i < NUM_RX_FLAGS; i++) { 396 if (rxh->flags & rx_flags[i].v) { 397 if (!firstflag) { 398 firstflag = 1; 399 printf(" "); 400 } else { 401 printf(","); 402 } 403 printf("<%s>", rx_flags[i].s); 404 } 405 } 406 } 407 408 /* 409 * Try to handle AFS calls that we know about. Check the destination 410 * port and make sure it's a data packet. Also, make sure the 411 * seq number is 1 (because otherwise it's a continuation packet, 412 * and we can't interpret that). Also, seems that reply packets 413 * do not have the client-init flag set, so we check for that 414 * as well. 415 */ 416 417 if (rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1 && 418 rxh->flags & RX_CLIENT_INITIATED) { 419 420 /* 421 * Insert this call into the call cache table, so we 422 * have a chance to print out replies 423 */ 424 425 rx_cache_insert(bp, (const struct ip *) bp2, dport, length); 426 427 switch (dport) { 428 case FS_RX_PORT: /* AFS file service */ 429 fs_print(bp, length); 430 break; 431 case CB_RX_PORT: /* AFS callback service */ 432 cb_print(bp, length); 433 break; 434 case PROT_RX_PORT: /* AFS protection service */ 435 prot_print(bp, length); 436 break; 437 case VLDB_RX_PORT: /* AFS VLDB service */ 438 vldb_print(bp, length); 439 break; 440 case KAUTH_RX_PORT: /* AFS Kerberos auth service */ 441 kauth_print(bp, length); 442 break; 443 case VOL_RX_PORT: /* AFS Volume service */ 444 vol_print(bp, length); 445 break; 446 case BOS_RX_PORT: /* AFS BOS service */ 447 bos_print(bp, length); 448 break; 449 default: 450 ; 451 } 452 453 /* 454 * If it's a reply (client-init is _not_ set, but seq is one) 455 * then look it up in the cache. If we find it, call the reply 456 * printing functions Note that we handle abort packets here, 457 * because printing out the return code can be useful at times. 458 */ 459 460 } else if (((rxh->type == RX_PACKET_TYPE_DATA && 461 ntohl(rxh->seq) == 1) || 462 rxh->type == RX_PACKET_TYPE_ABORT) && 463 (rxh->flags & RX_CLIENT_INITIATED) == 0 && 464 rx_cache_find(rxh, (const struct ip *) bp2, 465 sport, &opcode)) { 466 467 switch (sport) { 468 case FS_RX_PORT: /* AFS file service */ 469 fs_reply_print(bp, length, opcode); 470 break; 471 case CB_RX_PORT: /* AFS callback service */ 472 cb_reply_print(bp, length, opcode); 473 break; 474 case PROT_RX_PORT: /* AFS PT service */ 475 prot_reply_print(bp, length, opcode); 476 break; 477 case VLDB_RX_PORT: /* AFS VLDB service */ 478 vldb_reply_print(bp, length, opcode); 479 break; 480 case KAUTH_RX_PORT: /* AFS Kerberos auth service */ 481 kauth_reply_print(bp, length, opcode); 482 break; 483 case VOL_RX_PORT: /* AFS Volume service */ 484 vol_reply_print(bp, length, opcode); 485 break; 486 case BOS_RX_PORT: /* AFS BOS service */ 487 bos_reply_print(bp, length, opcode); 488 break; 489 default: 490 ; 491 } 492 } 493 494 495 printf(" (%d)", length); 496 } 497 498 /* 499 * Insert an entry into the cache. Taken from print-nfs.c 500 */ 501 502 static void 503 rx_cache_insert(const u_char *bp, const struct ip *ip, int dport, 504 int length) 505 { 506 struct rx_cache_entry *rxent; 507 const struct rx_header *rxh = (const struct rx_header *) bp; 508 509 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) 510 return; 511 512 rxent = &rx_cache[rx_cache_next]; 513 514 if (++rx_cache_next >= RX_CACHE_SIZE) 515 rx_cache_next = 0; 516 517 rxent->callnum = rxh->callNumber; 518 rxent->client = ip->ip_src; 519 rxent->server = ip->ip_dst; 520 rxent->dport = dport; 521 rxent->serviceId = rxh->serviceId; 522 rxent->opcode = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 523 } 524 525 /* 526 * Lookup an entry in the cache. Also taken from print-nfs.c 527 * 528 * Note that because this is a reply, we're looking at the _source_ 529 * port. 530 */ 531 532 static int 533 rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, 534 int32_t *opcode) 535 { 536 int i; 537 struct rx_cache_entry *rxent; 538 u_int32_t clip = ip->ip_dst.s_addr; 539 u_int32_t sip = ip->ip_src.s_addr; 540 541 /* Start the search where we last left off */ 542 543 i = rx_cache_hint; 544 do { 545 rxent = &rx_cache[i]; 546 if (rxent->callnum == rxh->callNumber && 547 rxent->client.s_addr == clip && 548 rxent->server.s_addr == sip && 549 rxent->serviceId == rxh->serviceId && 550 rxent->dport == sport) { 551 552 /* We got a match! */ 553 554 rx_cache_hint = i; 555 *opcode = rxent->opcode; 556 return(1); 557 } 558 if (++i > RX_CACHE_SIZE) 559 i = 0; 560 } while (i != rx_cache_hint); 561 562 /* Our search failed */ 563 return(0); 564 } 565 566 /* 567 * These extrememly grody macros handle the printing of various AFS stuff. 568 */ 569 570 #define TRUNC(n) if (snapend - bp + 1 <= n) goto trunc; 571 #define FIDOUT() { unsigned long n1, n2, n3; \ 572 TRUNC(sizeof(int32_t) * 3); \ 573 n1 = ntohl(*((int *) bp)); \ 574 bp += sizeof(int32_t); \ 575 n2 = ntohl(*((int *) bp)); \ 576 bp += sizeof(int32_t); \ 577 n3 = ntohl(*((int *) bp)); \ 578 bp += sizeof(int32_t); \ 579 printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \ 580 } 581 582 #define STROUT(MAX) { int i; \ 583 TRUNC(sizeof(int32_t)); \ 584 i = (int) ntohl(*((int *) bp)); \ 585 bp += sizeof(int32_t); \ 586 TRUNC(i); \ 587 strncpy(s, bp, min(MAX, i)); \ 588 s[i] = '\0'; \ 589 printf(" \"%s\"", s); \ 590 bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \ 591 } 592 593 #define INTOUT() { int i; \ 594 TRUNC(sizeof(int32_t)); \ 595 i = (int) ntohl(*((int *) bp)); \ 596 bp += sizeof(int32_t); \ 597 printf(" %d", i); \ 598 } 599 600 #define UINTOUT() { unsigned long i; \ 601 TRUNC(sizeof(int32_t)); \ 602 i = ntohl(*((int *) bp)); \ 603 bp += sizeof(int32_t); \ 604 printf(" %lu", i); \ 605 } 606 607 #define DATEOUT() { time_t t; struct tm *tm; char str[256]; \ 608 TRUNC(sizeof(int32_t)); \ 609 t = (time_t) ntohl(*((int *) bp)); \ 610 bp += sizeof(int32_t); \ 611 tm = localtime(&t); \ 612 strftime(str, 256, "%Y/%m/%d %T", tm); \ 613 printf(" %s", str); \ 614 } 615 616 #define STOREATTROUT() { unsigned long mask, i; \ 617 TRUNC((sizeof(int32_t)*6)); \ 618 mask = ntohl(*((int *) bp)); bp += sizeof(int32_t); \ 619 if (mask) printf (" StoreStatus"); \ 620 if (mask & 1) { printf(" date"); DATEOUT(); } \ 621 else bp += sizeof(int32_t); \ 622 i = ntohl(*((int *) bp)); bp += sizeof(int32_t); \ 623 if (mask & 2) printf(" owner %lu", i); \ 624 i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \ 625 if (mask & 4) printf(" group %lu", i); \ 626 i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \ 627 if (mask & 8) printf(" mode %lo", i & 07777); \ 628 i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \ 629 if (mask & 16) printf(" segsize %lu", i); \ 630 /* undocumented in 3.3 docu */ \ 631 if (mask & 1024) printf(" fsync"); \ 632 } 633 634 #define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \ 635 TRUNC(sizeof(int32_t) * 2); \ 636 epoch = ntohl(*((int *) bp)); \ 637 bp += sizeof(int32_t); \ 638 counter = ntohl(*((int *) bp)); \ 639 bp += sizeof(int32_t); \ 640 printf(" %d.%d", epoch, counter); \ 641 } 642 643 #define AFSUUIDOUT() {u_int32_t temp; int i; \ 644 TRUNC(11*sizeof(u_int32_t)); \ 645 temp = ntohl(*((int *) bp)); \ 646 bp += sizeof(u_int32_t); \ 647 printf(" %08x", temp); \ 648 temp = ntohl(*((int *) bp)); \ 649 bp += sizeof(u_int32_t); \ 650 printf("%04x", temp); \ 651 temp = ntohl(*((int *) bp)); \ 652 bp += sizeof(u_int32_t); \ 653 printf("%04x", temp); \ 654 for (i = 0; i < 8; i++) { \ 655 temp = ntohl(*((int *) bp)); \ 656 bp += sizeof(u_int32_t); \ 657 printf("%02x", (unsigned char) temp); \ 658 } \ 659 } 660 661 /* 662 * This is the sickest one of all 663 */ 664 665 #define VECOUT(MAX) { char *sp; \ 666 int k; \ 667 TRUNC(MAX * sizeof(int32_t)); \ 668 sp = s; \ 669 for (k = 0; k < MAX; k++) { \ 670 *sp++ = (char) ntohl(*((int *) bp)); \ 671 bp += sizeof(int32_t); \ 672 } \ 673 s[MAX] = '\0'; \ 674 printf(" \"%s\"", s); \ 675 } 676 677 /* 678 * Handle calls to the AFS file service (fs) 679 */ 680 681 void 682 fs_print(register const u_char *bp, int length) 683 { 684 int fs_op; 685 unsigned long i; 686 char s[AFSNAMEMAX]; 687 688 if (length <= sizeof(struct rx_header)) 689 return; 690 691 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 692 goto trunc; 693 } 694 695 /* 696 * Print out the afs call we're invoking. The table used here was 697 * gleaned from fsint/afsint.xg 698 */ 699 700 fs_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 701 702 printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op)); 703 704 /* 705 * Print out arguments to some of the AFS calls. This stuff is 706 * all from afsint.xg 707 */ 708 709 bp += sizeof(struct rx_header) + 4; 710 711 /* 712 * Sigh. This is gross. Ritchie forgive me. 713 */ 714 715 switch (fs_op) { 716 case 130: /* Fetch data */ 717 FIDOUT(); 718 printf(" offset"); 719 UINTOUT(); 720 printf(" length"); 721 UINTOUT(); 722 break; 723 case 131: /* Fetch ACL */ 724 case 132: /* Fetch Status */ 725 case 143: /* Old set lock */ 726 case 144: /* Old extend lock */ 727 case 145: /* Old release lock */ 728 case 156: /* Set lock */ 729 case 157: /* Extend lock */ 730 case 158: /* Release lock */ 731 FIDOUT(); 732 break; 733 case 135: /* Store status */ 734 FIDOUT(); 735 STOREATTROUT(); 736 break; 737 case 133: /* Store data */ 738 FIDOUT(); 739 STOREATTROUT(); 740 printf(" offset"); 741 UINTOUT(); 742 printf(" length"); 743 UINTOUT(); 744 printf(" flen"); 745 UINTOUT(); 746 break; 747 case 134: /* Store ACL */ 748 { 749 char a[AFSOPAQUEMAX]; 750 FIDOUT(); 751 TRUNC(4); 752 i = ntohl(*((int *) bp)); 753 bp += sizeof(int32_t); 754 TRUNC(i); 755 strncpy(a, bp, min(AFSOPAQUEMAX, i)); 756 a[i] = '\0'; 757 acl_print((u_char *) a, (u_char *) a + i); 758 break; 759 } 760 case 137: /* Create file */ 761 case 141: /* MakeDir */ 762 FIDOUT(); 763 STROUT(AFSNAMEMAX); 764 STOREATTROUT(); 765 break; 766 case 136: /* Remove file */ 767 case 142: /* Remove directory */ 768 FIDOUT(); 769 STROUT(AFSNAMEMAX); 770 break; 771 case 138: /* Rename file */ 772 printf(" old"); 773 FIDOUT(); 774 STROUT(AFSNAMEMAX); 775 printf(" new"); 776 FIDOUT(); 777 STROUT(AFSNAMEMAX); 778 break; 779 case 139: /* Symlink */ 780 FIDOUT(); 781 STROUT(AFSNAMEMAX); 782 printf(" link to"); 783 STROUT(AFSNAMEMAX); 784 break; 785 case 140: /* Link */ 786 FIDOUT(); 787 STROUT(AFSNAMEMAX); 788 printf(" link to"); 789 FIDOUT(); 790 break; 791 case 148: /* Get volume info */ 792 STROUT(AFSNAMEMAX); 793 break; 794 case 149: /* Get volume stats */ 795 case 150: /* Set volume stats */ 796 printf(" volid"); 797 UINTOUT(); 798 break; 799 case 154: /* New get volume info */ 800 printf(" volname"); 801 STROUT(AFSNAMEMAX); 802 break; 803 case 155: /* Bulk stat */ 804 { 805 unsigned long j; 806 TRUNC(4); 807 j = ntohl(*((int *) bp)); 808 bp += sizeof(int32_t); 809 810 for (i = 0; i < j; i++) { 811 FIDOUT(); 812 if (i != j - 1) 813 printf(","); 814 } 815 if (j == 0) 816 printf(" <none!>"); 817 } 818 default: 819 ; 820 } 821 822 return; 823 824 trunc: 825 printf(" [|fs]"); 826 } 827 828 /* 829 * Handle replies to the AFS file service 830 */ 831 832 static void 833 fs_reply_print(register const u_char *bp, int length, int32_t opcode) 834 { 835 unsigned long i; 836 char s[AFSNAMEMAX]; 837 struct rx_header *rxh; 838 839 if (length <= sizeof(struct rx_header)) 840 return; 841 842 rxh = (struct rx_header *) bp; 843 844 /* 845 * Print out the afs call we're invoking. The table used here was 846 * gleaned from fsint/afsint.xg 847 */ 848 849 printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode)); 850 851 bp += sizeof(struct rx_header); 852 853 /* 854 * If it was a data packet, interpret the response 855 */ 856 857 if (rxh->type == RX_PACKET_TYPE_DATA) 858 switch (opcode) { 859 case 131: /* Fetch ACL */ 860 { 861 char a[AFSOPAQUEMAX]; 862 TRUNC(4); 863 i = ntohl(*((int *) bp)); 864 bp += sizeof(int32_t); 865 TRUNC(i); 866 strncpy(a, bp, min(AFSOPAQUEMAX, i)); 867 a[i] = '\0'; 868 acl_print((u_char *) a, (u_char *) a + i); 869 break; 870 } 871 case 137: /* Create file */ 872 case 141: /* MakeDir */ 873 printf(" new"); 874 FIDOUT(); 875 break; 876 case 151: /* Get root volume */ 877 printf(" root volume"); 878 STROUT(AFSNAMEMAX); 879 break; 880 case 153: /* Get time */ 881 DATEOUT(); 882 break; 883 default: 884 ; 885 } 886 else { 887 /* 888 * Otherwise, just print out the return code 889 */ 890 printf(" errcode"); 891 INTOUT(); 892 } 893 894 return; 895 896 trunc: 897 printf(" [|fs]"); 898 } 899 900 /* 901 * Print out an AFS ACL string. An AFS ACL is a string that has the 902 * following format: 903 * 904 * <positive> <negative> 905 * <uid1> <aclbits1> 906 * .... 907 * 908 * "positive" and "negative" are integers which contain the number of 909 * positive and negative ACL's in the string. The uid/aclbits pair are 910 * ASCII strings containing the UID/PTS record and and a ascii number 911 * representing a logical OR of all the ACL permission bits 912 */ 913 914 static void 915 acl_print(u_char *s, u_char *end) 916 { 917 int pos, neg, acl; 918 int n, i; 919 char user[128]; 920 921 if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2) 922 return; 923 924 s += n; 925 926 if (s > end) 927 return; 928 929 /* 930 * This wacky order preserves the order used by the "fs" command 931 */ 932 933 #define ACLOUT(acl) \ 934 if (acl & PRSFS_READ) \ 935 printf("r"); \ 936 if (acl & PRSFS_LOOKUP) \ 937 printf("l"); \ 938 if (acl & PRSFS_INSERT) \ 939 printf("i"); \ 940 if (acl & PRSFS_DELETE) \ 941 printf("d"); \ 942 if (acl & PRSFS_WRITE) \ 943 printf("w"); \ 944 if (acl & PRSFS_LOCK) \ 945 printf("k"); \ 946 if (acl & PRSFS_ADMINISTER) \ 947 printf("a"); 948 949 for (i = 0; i < pos; i++) { 950 if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2) 951 return; 952 s += n; 953 printf(" +{%s ", user); 954 ACLOUT(acl); 955 printf("}"); 956 if (s > end) 957 return; 958 } 959 960 for (i = 0; i < neg; i++) { 961 if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2) 962 return; 963 s += n; 964 printf(" -{%s ", user); 965 ACLOUT(acl); 966 printf("}"); 967 if (s > end) 968 return; 969 } 970 } 971 972 #undef ACLOUT 973 974 /* 975 * Handle calls to the AFS callback service 976 */ 977 978 static void 979 cb_print(register const u_char *bp, int length) 980 { 981 int cb_op; 982 unsigned long i; 983 984 if (length <= sizeof(struct rx_header)) 985 return; 986 987 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 988 goto trunc; 989 } 990 991 /* 992 * Print out the afs call we're invoking. The table used here was 993 * gleaned from fsint/afscbint.xg 994 */ 995 996 cb_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 997 998 printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op)); 999 1000 bp += sizeof(struct rx_header) + 4; 1001 1002 /* 1003 * Print out the afs call we're invoking. The table used here was 1004 * gleaned from fsint/afscbint.xg 1005 */ 1006 1007 switch (cb_op) { 1008 case 204: /* Callback */ 1009 { 1010 unsigned long j, t; 1011 TRUNC(4); 1012 j = ntohl(*((int *) bp)); 1013 bp += sizeof(int32_t); 1014 1015 for (i = 0; i < j; i++) { 1016 FIDOUT(); 1017 if (i != j - 1) 1018 printf(","); 1019 } 1020 1021 if (j == 0) 1022 printf(" <none!>"); 1023 1024 j = ntohl(*((int *) bp)); 1025 bp += sizeof(int32_t); 1026 1027 if (j != 0) 1028 printf(";"); 1029 1030 for (i = 0; i < j; i++) { 1031 printf(" ver"); 1032 INTOUT(); 1033 printf(" expires"); 1034 DATEOUT(); 1035 TRUNC(4); 1036 t = ntohl(*((int *) bp)); 1037 bp += sizeof(int32_t); 1038 tok2str(cb_types, "type %d", t); 1039 } 1040 } 1041 case 214: { 1042 printf(" afsuuid"); 1043 AFSUUIDOUT(); 1044 break; 1045 } 1046 default: 1047 ; 1048 } 1049 1050 return; 1051 1052 trunc: 1053 printf(" [|cb]"); 1054 } 1055 1056 /* 1057 * Handle replies to the AFS Callback Service 1058 */ 1059 1060 static void 1061 cb_reply_print(register const u_char *bp, int length, int32_t opcode) 1062 { 1063 struct rx_header *rxh; 1064 1065 if (length <= sizeof(struct rx_header)) 1066 return; 1067 1068 rxh = (struct rx_header *) bp; 1069 1070 /* 1071 * Print out the afs call we're invoking. The table used here was 1072 * gleaned from fsint/afscbint.xg 1073 */ 1074 1075 printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode)); 1076 1077 bp += sizeof(struct rx_header); 1078 1079 /* 1080 * If it was a data packet, interpret the response. 1081 */ 1082 1083 if (rxh->type == RX_PACKET_TYPE_DATA) 1084 switch (opcode) { 1085 case 213: /* InitCallBackState3 */ 1086 AFSUUIDOUT(); 1087 break; 1088 default: 1089 ; 1090 } 1091 else { 1092 /* 1093 * Otherwise, just print out the return code 1094 */ 1095 printf(" errcode"); 1096 INTOUT(); 1097 } 1098 1099 return; 1100 1101 trunc: 1102 printf(" [|cb]"); 1103 } 1104 1105 /* 1106 * Handle calls to the AFS protection database server 1107 */ 1108 1109 static void 1110 prot_print(register const u_char *bp, int length) 1111 { 1112 unsigned long i; 1113 char s[AFSNAMEMAX]; 1114 int pt_op; 1115 1116 if (length <= sizeof(struct rx_header)) 1117 return; 1118 1119 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 1120 goto trunc; 1121 } 1122 1123 /* 1124 * Print out the afs call we're invoking. The table used here was 1125 * gleaned from ptserver/ptint.xg 1126 */ 1127 1128 pt_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 1129 1130 printf(" pt"); 1131 1132 if (is_ubik(pt_op)) { 1133 ubik_print(bp, length); 1134 return; 1135 } 1136 1137 printf(" call %s", tok2str(pt_req, "op#%d", pt_op)); 1138 1139 /* 1140 * Decode some of the arguments to the PT calls 1141 */ 1142 1143 bp += sizeof(struct rx_header) + 4; 1144 1145 switch (pt_op) { 1146 case 500: /* I New User */ 1147 STROUT(PRNAMEMAX); 1148 printf(" id"); 1149 INTOUT(); 1150 printf(" oldid"); 1151 INTOUT(); 1152 break; 1153 case 501: /* Where is it */ 1154 case 506: /* Delete */ 1155 case 508: /* Get CPS */ 1156 case 512: /* List entry */ 1157 case 514: /* List elements */ 1158 case 517: /* List owned */ 1159 case 518: /* Get CPS2 */ 1160 case 519: /* Get host CPS */ 1161 printf(" id"); 1162 INTOUT(); 1163 break; 1164 case 502: /* Dump entry */ 1165 printf(" pos"); 1166 INTOUT(); 1167 break; 1168 case 503: /* Add to group */ 1169 case 507: /* Remove from group */ 1170 case 515: /* Is a member of? */ 1171 printf(" uid"); 1172 INTOUT(); 1173 printf(" gid"); 1174 INTOUT(); 1175 break; 1176 case 504: /* Name to ID */ 1177 { 1178 unsigned long j; 1179 TRUNC(4); 1180 j = ntohl(*((int *) bp)); 1181 bp += sizeof(int32_t); 1182 1183 /* 1184 * Who designed this chicken-shit protocol? 1185 * 1186 * Each character is stored as a 32-bit 1187 * integer! 1188 */ 1189 1190 for (i = 0; i < j; i++) { 1191 VECOUT(PRNAMEMAX); 1192 } 1193 if (j == 0) 1194 printf(" <none!>"); 1195 } 1196 break; 1197 case 505: /* Id to name */ 1198 { 1199 unsigned long j; 1200 printf(" ids:"); 1201 TRUNC(4); 1202 i = ntohl(*((int *) bp)); 1203 bp += sizeof(int32_t); 1204 for (j = 0; j < i; j++) 1205 INTOUT(); 1206 if (j == 0) 1207 printf(" <none!>"); 1208 } 1209 break; 1210 case 509: /* New entry */ 1211 STROUT(PRNAMEMAX); 1212 printf(" flag"); 1213 INTOUT(); 1214 printf(" oid"); 1215 INTOUT(); 1216 break; 1217 case 511: /* Set max */ 1218 printf(" id"); 1219 INTOUT(); 1220 printf(" gflag"); 1221 INTOUT(); 1222 break; 1223 case 513: /* Change entry */ 1224 printf(" id"); 1225 INTOUT(); 1226 STROUT(PRNAMEMAX); 1227 printf(" oldid"); 1228 INTOUT(); 1229 printf(" newid"); 1230 INTOUT(); 1231 break; 1232 case 520: /* Update entry */ 1233 printf(" id"); 1234 INTOUT(); 1235 STROUT(PRNAMEMAX); 1236 break; 1237 default: 1238 ; 1239 } 1240 1241 1242 return; 1243 1244 trunc: 1245 printf(" [|pt]"); 1246 } 1247 1248 /* 1249 * Handle replies to the AFS protection service 1250 */ 1251 1252 static void 1253 prot_reply_print(register const u_char *bp, int length, int32_t opcode) 1254 { 1255 struct rx_header *rxh; 1256 unsigned long i; 1257 char s[AFSNAMEMAX]; 1258 1259 if (length < sizeof(struct rx_header)) 1260 return; 1261 1262 rxh = (struct rx_header *) bp; 1263 1264 /* 1265 * Print out the afs call we're invoking. The table used here was 1266 * gleaned from ptserver/ptint.xg. Check to see if it's a 1267 * Ubik call, however. 1268 */ 1269 1270 printf(" pt"); 1271 1272 if (is_ubik(opcode)) { 1273 ubik_reply_print(bp, length, opcode); 1274 return; 1275 } 1276 1277 printf(" reply %s", tok2str(pt_req, "op#%d", opcode)); 1278 1279 bp += sizeof(struct rx_header); 1280 1281 /* 1282 * If it was a data packet, interpret the response 1283 */ 1284 1285 if (rxh->type == RX_PACKET_TYPE_DATA) 1286 switch (opcode) { 1287 case 504: /* Name to ID */ 1288 { 1289 unsigned long j; 1290 printf(" ids:"); 1291 TRUNC(4); 1292 i = ntohl(*((int *) bp)); 1293 bp += sizeof(int32_t); 1294 for (j = 0; j < i; j++) 1295 INTOUT(); 1296 if (j == 0) 1297 printf(" <none!>"); 1298 } 1299 break; 1300 case 505: /* ID to name */ 1301 { 1302 unsigned long j; 1303 TRUNC(4); 1304 j = ntohl(*((int *) bp)); 1305 bp += sizeof(int32_t); 1306 1307 /* 1308 * Who designed this chicken-shit protocol? 1309 * 1310 * Each character is stored as a 32-bit 1311 * integer! 1312 */ 1313 1314 for (i = 0; i < j; i++) { 1315 VECOUT(PRNAMEMAX); 1316 } 1317 if (j == 0) 1318 printf(" <none!>"); 1319 } 1320 break; 1321 case 508: /* Get CPS */ 1322 case 514: /* List elements */ 1323 case 517: /* List owned */ 1324 case 518: /* Get CPS2 */ 1325 case 519: /* Get host CPS */ 1326 { 1327 unsigned long j; 1328 TRUNC(4); 1329 j = ntohl(*((int *) bp)); 1330 bp += sizeof(int32_t); 1331 for (i = 0; i < j; i++) { 1332 INTOUT(); 1333 } 1334 if (j == 0) 1335 printf(" <none!>"); 1336 } 1337 break; 1338 case 510: /* List max */ 1339 printf(" maxuid"); 1340 INTOUT(); 1341 printf(" maxgid"); 1342 INTOUT(); 1343 break; 1344 default: 1345 ; 1346 } 1347 else { 1348 /* 1349 * Otherwise, just print out the return code 1350 */ 1351 printf(" errcode"); 1352 INTOUT(); 1353 } 1354 1355 return; 1356 1357 trunc: 1358 printf(" [|pt]"); 1359 } 1360 1361 /* 1362 * Handle calls to the AFS volume location database service 1363 */ 1364 1365 static void 1366 vldb_print(register const u_char *bp, int length) 1367 { 1368 int vldb_op; 1369 unsigned long i; 1370 char s[AFSNAMEMAX]; 1371 1372 if (length <= sizeof(struct rx_header)) 1373 return; 1374 1375 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 1376 goto trunc; 1377 } 1378 1379 /* 1380 * Print out the afs call we're invoking. The table used here was 1381 * gleaned from vlserver/vldbint.xg 1382 */ 1383 1384 vldb_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 1385 1386 printf(" vldb"); 1387 1388 if (is_ubik(vldb_op)) { 1389 ubik_print(bp, length); 1390 return; 1391 } 1392 printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op)); 1393 1394 /* 1395 * Decode some of the arguments to the VLDB calls 1396 */ 1397 1398 bp += sizeof(struct rx_header) + 4; 1399 1400 switch (vldb_op) { 1401 case 501: /* Create new volume */ 1402 case 517: /* Create entry N */ 1403 VECOUT(VLNAMEMAX); 1404 break; 1405 case 502: /* Delete entry */ 1406 case 503: /* Get entry by ID */ 1407 case 507: /* Update entry */ 1408 case 508: /* Set lock */ 1409 case 509: /* Release lock */ 1410 case 518: /* Get entry by ID N */ 1411 printf(" volid"); 1412 INTOUT(); 1413 TRUNC(sizeof(int32_t)); 1414 i = ntohl(*((int *) bp)); 1415 bp += sizeof(int32_t); 1416 if (i <= 2) 1417 printf(" type %s", voltype[i]); 1418 break; 1419 case 504: /* Get entry by name */ 1420 case 519: /* Get entry by name N */ 1421 case 524: /* Update entry by name */ 1422 case 527: /* Get entry by name U */ 1423 STROUT(VLNAMEMAX); 1424 break; 1425 case 505: /* Get new vol id */ 1426 printf(" bump"); 1427 INTOUT(); 1428 break; 1429 case 506: /* Replace entry */ 1430 case 520: /* Replace entry N */ 1431 printf(" volid"); 1432 INTOUT(); 1433 TRUNC(sizeof(int32_t)); 1434 i = ntohl(*((int *) bp)); 1435 bp += sizeof(int32_t); 1436 if (i <= 2) 1437 printf(" type %s", voltype[i]); 1438 VECOUT(VLNAMEMAX); 1439 break; 1440 case 510: /* List entry */ 1441 case 521: /* List entry N */ 1442 printf(" index"); 1443 INTOUT(); 1444 break; 1445 default: 1446 ; 1447 } 1448 1449 return; 1450 1451 trunc: 1452 printf(" [|vldb]"); 1453 } 1454 1455 /* 1456 * Handle replies to the AFS volume location database service 1457 */ 1458 1459 static void 1460 vldb_reply_print(register const u_char *bp, int length, int32_t opcode) 1461 { 1462 struct rx_header *rxh; 1463 unsigned long i; 1464 char s[AFSNAMEMAX]; 1465 1466 if (length < sizeof(struct rx_header)) 1467 return; 1468 1469 rxh = (struct rx_header *) bp; 1470 1471 /* 1472 * Print out the afs call we're invoking. The table used here was 1473 * gleaned from vlserver/vldbint.xg. Check to see if it's a 1474 * Ubik call, however. 1475 */ 1476 1477 printf(" vldb"); 1478 1479 if (is_ubik(opcode)) { 1480 ubik_reply_print(bp, length, opcode); 1481 return; 1482 } 1483 1484 printf(" reply %s", tok2str(vldb_req, "op#%d", opcode)); 1485 1486 bp += sizeof(struct rx_header); 1487 1488 /* 1489 * If it was a data packet, interpret the response 1490 */ 1491 1492 if (rxh->type == RX_PACKET_TYPE_DATA) 1493 switch (opcode) { 1494 case 510: /* List entry */ 1495 printf(" count"); 1496 INTOUT(); 1497 printf(" nextindex"); 1498 INTOUT(); 1499 case 503: /* Get entry by id */ 1500 case 504: /* Get entry by name */ 1501 { unsigned long nservers, j; 1502 VECOUT(VLNAMEMAX); 1503 TRUNC(sizeof(int32_t)); 1504 bp += sizeof(int32_t); 1505 printf(" numservers"); 1506 TRUNC(sizeof(int32_t)); 1507 nservers = ntohl(*((int *) bp)); 1508 bp += sizeof(int32_t); 1509 printf(" %lu", nservers); 1510 printf(" servers"); 1511 for (i = 0; i < 8; i++) { 1512 TRUNC(sizeof(int32_t)); 1513 if (i < nservers) 1514 printf(" %s", 1515 inet_ntoa(*((struct in_addr *) bp))); 1516 bp += sizeof(int32_t); 1517 } 1518 printf(" partitions"); 1519 for (i = 0; i < 8; i++) { 1520 TRUNC(sizeof(int32_t)); 1521 j = ntohl(*((int *) bp)); 1522 if (i < nservers && j <= 26) 1523 printf(" %c", 'a' + (int)j); 1524 else if (i < nservers) 1525 printf(" %lu", j); 1526 bp += sizeof(int32_t); 1527 } 1528 TRUNC(8 * sizeof(int32_t)); 1529 bp += 8 * sizeof(int32_t); 1530 printf(" rwvol"); 1531 UINTOUT(); 1532 printf(" rovol"); 1533 UINTOUT(); 1534 printf(" backup"); 1535 UINTOUT(); 1536 } 1537 break; 1538 case 505: /* Get new volume ID */ 1539 printf(" newvol"); 1540 UINTOUT(); 1541 break; 1542 case 521: /* List entry */ 1543 case 529: /* List entry U */ 1544 printf(" count"); 1545 INTOUT(); 1546 printf(" nextindex"); 1547 INTOUT(); 1548 case 518: /* Get entry by ID N */ 1549 case 519: /* Get entry by name N */ 1550 { unsigned long nservers, j; 1551 VECOUT(VLNAMEMAX); 1552 printf(" numservers"); 1553 TRUNC(sizeof(int32_t)); 1554 nservers = ntohl(*((int *) bp)); 1555 bp += sizeof(int32_t); 1556 printf(" %lu", nservers); 1557 printf(" servers"); 1558 for (i = 0; i < 13; i++) { 1559 TRUNC(sizeof(int32_t)); 1560 if (i < nservers) 1561 printf(" %s", 1562 inet_ntoa(*((struct in_addr *) bp))); 1563 bp += sizeof(int32_t); 1564 } 1565 printf(" partitions"); 1566 for (i = 0; i < 13; i++) { 1567 TRUNC(sizeof(int32_t)); 1568 j = ntohl(*((int *) bp)); 1569 if (i < nservers && j <= 26) 1570 printf(" %c", 'a' + (int)j); 1571 else if (i < nservers) 1572 printf(" %lu", j); 1573 bp += sizeof(int32_t); 1574 } 1575 TRUNC(13 * sizeof(int32_t)); 1576 bp += 13 * sizeof(int32_t); 1577 printf(" rwvol"); 1578 UINTOUT(); 1579 printf(" rovol"); 1580 UINTOUT(); 1581 printf(" backup"); 1582 UINTOUT(); 1583 } 1584 break; 1585 case 526: /* Get entry by ID U */ 1586 case 527: /* Get entry by name U */ 1587 { unsigned long nservers, j; 1588 VECOUT(VLNAMEMAX); 1589 printf(" numservers"); 1590 TRUNC(sizeof(int32_t)); 1591 nservers = ntohl(*((int *) bp)); 1592 bp += sizeof(int32_t); 1593 printf(" %lu", nservers); 1594 printf(" servers"); 1595 for (i = 0; i < 13; i++) { 1596 if (i < nservers) { 1597 printf(" afsuuid"); 1598 AFSUUIDOUT(); 1599 } else { 1600 TRUNC(44); 1601 bp += 44; 1602 } 1603 } 1604 TRUNC(4 * 13); 1605 bp += 4 * 13; 1606 printf(" partitions"); 1607 for (i = 0; i < 13; i++) { 1608 TRUNC(sizeof(int32_t)); 1609 j = ntohl(*((int *) bp)); 1610 if (i < nservers && j <= 26) 1611 printf(" %c", 'a' + (int)j); 1612 else if (i < nservers) 1613 printf(" %lu", j); 1614 bp += sizeof(int32_t); 1615 } 1616 TRUNC(13 * sizeof(int32_t)); 1617 bp += 13 * sizeof(int32_t); 1618 printf(" rwvol"); 1619 UINTOUT(); 1620 printf(" rovol"); 1621 UINTOUT(); 1622 printf(" backup"); 1623 UINTOUT(); 1624 } 1625 default: 1626 ; 1627 } 1628 1629 else { 1630 /* 1631 * Otherwise, just print out the return code 1632 */ 1633 printf(" errcode"); 1634 INTOUT(); 1635 } 1636 1637 return; 1638 1639 trunc: 1640 printf(" [|vldb]"); 1641 } 1642 1643 /* 1644 * Handle calls to the AFS Kerberos Authentication service 1645 */ 1646 1647 static void 1648 kauth_print(register const u_char *bp, int length) 1649 { 1650 int kauth_op; 1651 char s[AFSNAMEMAX]; 1652 1653 if (length <= sizeof(struct rx_header)) 1654 return; 1655 1656 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 1657 goto trunc; 1658 } 1659 1660 /* 1661 * Print out the afs call we're invoking. The table used here was 1662 * gleaned from kauth/kauth.rg 1663 */ 1664 1665 kauth_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 1666 1667 printf(" kauth"); 1668 1669 if (is_ubik(kauth_op)) { 1670 ubik_print(bp, length); 1671 return; 1672 } 1673 1674 1675 printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op)); 1676 1677 /* 1678 * Decode some of the arguments to the KA calls 1679 */ 1680 1681 bp += sizeof(struct rx_header) + 4; 1682 1683 switch (kauth_op) { 1684 case 1: /* Authenticate old */; 1685 case 21: /* Authenticate */ 1686 case 22: /* Authenticate-V2 */ 1687 case 2: /* Change PW */ 1688 case 5: /* Set fields */ 1689 case 6: /* Create user */ 1690 case 7: /* Delete user */ 1691 case 8: /* Get entry */ 1692 case 14: /* Unlock */ 1693 case 15: /* Lock status */ 1694 printf(" principal"); 1695 STROUT(KANAMEMAX); 1696 STROUT(KANAMEMAX); 1697 break; 1698 case 3: /* GetTicket-old */ 1699 case 23: /* GetTicket */ 1700 { 1701 int i; 1702 printf(" kvno"); 1703 INTOUT(); 1704 printf(" domain"); 1705 STROUT(KANAMEMAX); 1706 TRUNC(sizeof(int32_t)); 1707 i = (int) ntohl(*((int *) bp)); 1708 bp += sizeof(int32_t); 1709 TRUNC(i); 1710 bp += i; 1711 printf(" principal"); 1712 STROUT(KANAMEMAX); 1713 STROUT(KANAMEMAX); 1714 break; 1715 } 1716 case 4: /* Set Password */ 1717 printf(" principal"); 1718 STROUT(KANAMEMAX); 1719 STROUT(KANAMEMAX); 1720 printf(" kvno"); 1721 INTOUT(); 1722 break; 1723 case 12: /* Get password */ 1724 printf(" name"); 1725 STROUT(KANAMEMAX); 1726 break; 1727 default: 1728 ; 1729 } 1730 1731 return; 1732 1733 trunc: 1734 printf(" [|kauth]"); 1735 } 1736 1737 /* 1738 * Handle replies to the AFS Kerberos Authentication Service 1739 */ 1740 1741 static void 1742 kauth_reply_print(register const u_char *bp, int length, int32_t opcode) 1743 { 1744 struct rx_header *rxh; 1745 1746 if (length <= sizeof(struct rx_header)) 1747 return; 1748 1749 rxh = (struct rx_header *) bp; 1750 1751 /* 1752 * Print out the afs call we're invoking. The table used here was 1753 * gleaned from kauth/kauth.rg 1754 */ 1755 1756 printf(" kauth"); 1757 1758 if (is_ubik(opcode)) { 1759 ubik_reply_print(bp, length, opcode); 1760 return; 1761 } 1762 1763 printf(" reply %s", tok2str(kauth_req, "op#%d", opcode)); 1764 1765 bp += sizeof(struct rx_header); 1766 1767 /* 1768 * If it was a data packet, interpret the response. 1769 */ 1770 1771 if (rxh->type == RX_PACKET_TYPE_DATA) 1772 /* Well, no, not really. Leave this for later */ 1773 ; 1774 else { 1775 /* 1776 * Otherwise, just print out the return code 1777 */ 1778 printf(" errcode"); 1779 INTOUT(); 1780 } 1781 1782 return; 1783 1784 trunc: 1785 printf(" [|kauth]"); 1786 } 1787 1788 /* 1789 * Handle calls to the AFS Volume location service 1790 */ 1791 1792 static void 1793 vol_print(register const u_char *bp, int length) 1794 { 1795 int vol_op; 1796 1797 if (length <= sizeof(struct rx_header)) 1798 return; 1799 1800 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 1801 goto trunc; 1802 } 1803 1804 /* 1805 * Print out the afs call we're invoking. The table used here was 1806 * gleaned from volser/volint.xg 1807 */ 1808 1809 vol_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 1810 1811 printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op)); 1812 1813 /* 1814 * Normally there would be a switch statement here to decode the 1815 * arguments to the AFS call, but since I don't have access to 1816 * an AFS server (yet) and I'm not an AFS admin, I can't 1817 * test any of these calls. Leave this blank for now. 1818 */ 1819 1820 return; 1821 1822 trunc: 1823 printf(" [|vol]"); 1824 } 1825 1826 /* 1827 * Handle replies to the AFS Volume Service 1828 */ 1829 1830 static void 1831 vol_reply_print(register const u_char *bp, int length, int32_t opcode) 1832 { 1833 struct rx_header *rxh; 1834 1835 if (length <= sizeof(struct rx_header)) 1836 return; 1837 1838 rxh = (struct rx_header *) bp; 1839 1840 /* 1841 * Print out the afs call we're invoking. The table used here was 1842 * gleaned from volser/volint.xg 1843 */ 1844 1845 printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode)); 1846 1847 bp += sizeof(struct rx_header); 1848 1849 /* 1850 * If it was a data packet, interpret the response. 1851 */ 1852 1853 if (rxh->type == RX_PACKET_TYPE_DATA) 1854 /* Well, no, not really. Leave this for later */ 1855 ; 1856 else { 1857 /* 1858 * Otherwise, just print out the return code 1859 */ 1860 printf(" errcode"); 1861 INTOUT(); 1862 } 1863 1864 return; 1865 1866 trunc: 1867 printf(" [|vol]"); 1868 } 1869 1870 /* 1871 * Handle calls to the AFS BOS service 1872 */ 1873 1874 static void 1875 bos_print(register const u_char *bp, int length) 1876 { 1877 int bos_op; 1878 char s[BOSNAMEMAX]; 1879 1880 if (length <= sizeof(struct rx_header)) 1881 return; 1882 1883 if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) { 1884 goto trunc; 1885 } 1886 1887 /* 1888 * Print out the afs call we're invoking. The table used here was 1889 * gleaned from bozo/bosint.xg 1890 */ 1891 1892 bos_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 1893 1894 printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op)); 1895 1896 /* 1897 * Decode some of the arguments to the BOS calls 1898 */ 1899 1900 bp += sizeof(struct rx_header) + 4; 1901 1902 switch (bos_op) { 1903 case 80: /* Create B node */ 1904 printf(" type"); 1905 STROUT(BOSNAMEMAX); 1906 printf(" instance"); 1907 STROUT(BOSNAMEMAX); 1908 break; 1909 case 81: /* Delete B node */ 1910 case 83: /* Get status */ 1911 case 85: /* Get instance info */ 1912 case 87: /* Add super user */ 1913 case 88: /* Delete super user */ 1914 case 93: /* Set cell name */ 1915 case 96: /* Add cell host */ 1916 case 97: /* Delete cell host */ 1917 case 104: /* Restart */ 1918 case 106: /* Uninstall */ 1919 case 108: /* Exec */ 1920 case 112: /* Getlog */ 1921 case 114: /* Get instance strings */ 1922 STROUT(BOSNAMEMAX); 1923 break; 1924 case 82: /* Set status */ 1925 case 98: /* Set T status */ 1926 STROUT(BOSNAMEMAX); 1927 printf(" status"); 1928 INTOUT(); 1929 break; 1930 case 86: /* Get instance parm */ 1931 STROUT(BOSNAMEMAX); 1932 printf(" num"); 1933 INTOUT(); 1934 break; 1935 case 84: /* Enumerate instance */ 1936 case 89: /* List super users */ 1937 case 90: /* List keys */ 1938 case 91: /* Add key */ 1939 case 92: /* Delete key */ 1940 case 95: /* Get cell host */ 1941 INTOUT(); 1942 break; 1943 case 105: /* Install */ 1944 STROUT(BOSNAMEMAX); 1945 printf(" size"); 1946 INTOUT(); 1947 printf(" flags"); 1948 INTOUT(); 1949 printf(" date"); 1950 INTOUT(); 1951 break; 1952 default: 1953 ; 1954 } 1955 1956 return; 1957 1958 trunc: 1959 printf(" [|bos]"); 1960 } 1961 1962 /* 1963 * Handle replies to the AFS BOS Service 1964 */ 1965 1966 static void 1967 bos_reply_print(register const u_char *bp, int length, int32_t opcode) 1968 { 1969 struct rx_header *rxh; 1970 1971 if (length <= sizeof(struct rx_header)) 1972 return; 1973 1974 rxh = (struct rx_header *) bp; 1975 1976 /* 1977 * Print out the afs call we're invoking. The table used here was 1978 * gleaned from volser/volint.xg 1979 */ 1980 1981 printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode)); 1982 1983 bp += sizeof(struct rx_header); 1984 1985 /* 1986 * If it was a data packet, interpret the response. 1987 */ 1988 1989 if (rxh->type == RX_PACKET_TYPE_DATA) 1990 /* Well, no, not really. Leave this for later */ 1991 ; 1992 else { 1993 /* 1994 * Otherwise, just print out the return code 1995 */ 1996 printf(" errcode"); 1997 INTOUT(); 1998 } 1999 2000 return; 2001 2002 trunc: 2003 printf(" [|bos]"); 2004 } 2005 2006 /* 2007 * Check to see if this is a Ubik opcode. 2008 */ 2009 2010 static int 2011 is_ubik(u_int32_t opcode) 2012 { 2013 if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) || 2014 (opcode >= DISK_LOW && opcode <= DISK_HIGH)) 2015 return(1); 2016 else 2017 return(0); 2018 } 2019 2020 /* 2021 * Handle Ubik opcodes to any one of the replicated database services 2022 */ 2023 2024 static void 2025 ubik_print(register const u_char *bp, int length) 2026 { 2027 int ubik_op; 2028 int32_t temp; 2029 2030 /* 2031 * Print out the afs call we're invoking. The table used here was 2032 * gleaned from ubik/ubik_int.xg 2033 */ 2034 2035 ubik_op = ntohl(*((int *) (bp + sizeof(struct rx_header)))); 2036 2037 printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op)); 2038 2039 /* 2040 * Decode some of the arguments to the Ubik calls 2041 */ 2042 2043 bp += sizeof(struct rx_header) + 4; 2044 2045 switch (ubik_op) { 2046 case 10000: /* Beacon */ 2047 TRUNC(4); 2048 temp = ntohl(*((int *) bp)); 2049 bp += sizeof(int32_t); 2050 printf(" syncsite %s", temp ? "yes" : "no"); 2051 printf(" votestart"); 2052 DATEOUT(); 2053 printf(" dbversion"); 2054 UBIK_VERSIONOUT(); 2055 printf(" tid"); 2056 UBIK_VERSIONOUT(); 2057 break; 2058 case 10003: /* Get sync site */ 2059 printf(" site"); 2060 UINTOUT(); 2061 break; 2062 case 20000: /* Begin */ 2063 case 20001: /* Commit */ 2064 case 20007: /* Abort */ 2065 case 20008: /* Release locks */ 2066 case 20010: /* Writev */ 2067 printf(" tid"); 2068 UBIK_VERSIONOUT(); 2069 break; 2070 case 20002: /* Lock */ 2071 printf(" tid"); 2072 UBIK_VERSIONOUT(); 2073 printf(" file"); 2074 INTOUT(); 2075 printf(" pos"); 2076 INTOUT(); 2077 printf(" length"); 2078 INTOUT(); 2079 temp = ntohl(*((int *) bp)); 2080 bp += sizeof(int32_t); 2081 tok2str(ubik_lock_types, "type %d", temp); 2082 break; 2083 case 20003: /* Write */ 2084 printf(" tid"); 2085 UBIK_VERSIONOUT(); 2086 printf(" file"); 2087 INTOUT(); 2088 printf(" pos"); 2089 INTOUT(); 2090 break; 2091 case 20005: /* Get file */ 2092 printf(" file"); 2093 INTOUT(); 2094 break; 2095 case 20006: /* Send file */ 2096 printf(" file"); 2097 INTOUT(); 2098 printf(" length"); 2099 INTOUT(); 2100 printf(" dbversion"); 2101 UBIK_VERSIONOUT(); 2102 break; 2103 case 20009: /* Truncate */ 2104 printf(" tid"); 2105 UBIK_VERSIONOUT(); 2106 printf(" file"); 2107 INTOUT(); 2108 printf(" length"); 2109 INTOUT(); 2110 break; 2111 case 20012: /* Set version */ 2112 printf(" tid"); 2113 UBIK_VERSIONOUT(); 2114 printf(" oldversion"); 2115 UBIK_VERSIONOUT(); 2116 printf(" newversion"); 2117 UBIK_VERSIONOUT(); 2118 break; 2119 default: 2120 ; 2121 } 2122 2123 return; 2124 2125 trunc: 2126 printf(" [|ubik]"); 2127 } 2128 2129 /* 2130 * Handle Ubik replies to any one of the replicated database services 2131 */ 2132 2133 static void 2134 ubik_reply_print(register const u_char *bp, int length, int32_t opcode) 2135 { 2136 struct rx_header *rxh; 2137 2138 if (length < sizeof(struct rx_header)) 2139 return; 2140 2141 rxh = (struct rx_header *) bp; 2142 2143 /* 2144 * Print out the ubik call we're invoking. This table was gleaned 2145 * from ubik/ubik_int.xg 2146 */ 2147 2148 printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode)); 2149 2150 bp += sizeof(struct rx_header); 2151 2152 /* 2153 * If it was a data packet, print out the arguments to the Ubik calls 2154 */ 2155 2156 if (rxh->type == RX_PACKET_TYPE_DATA) 2157 switch (opcode) { 2158 case 10000: /* Beacon */ 2159 printf(" vote no"); 2160 break; 2161 case 20004: /* Get version */ 2162 printf(" dbversion"); 2163 UBIK_VERSIONOUT(); 2164 break; 2165 default: 2166 ; 2167 } 2168 2169 /* 2170 * Otherwise, print out "yes" it it was a beacon packet (because 2171 * that's how yes votes are returned, go figure), otherwise 2172 * just print out the error code. 2173 */ 2174 2175 else 2176 switch (opcode) { 2177 case 10000: /* Beacon */ 2178 printf(" vote yes until"); 2179 DATEOUT(); 2180 break; 2181 default: 2182 printf(" errcode"); 2183 INTOUT(); 2184 } 2185 2186 return; 2187 2188 trunc: 2189 printf(" [|ubik]"); 2190 } 2191