1 /* 2 * Copyright: (c) 2000 United States Government as represented by the 3 * Secretary of the Navy. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 3. The names of the authors may not be used to endorse or promote 16 * products derived from this software without specific prior 17 * written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 /* 24 * This code unmangles RX packets. RX is the mutant form of RPC that AFS 25 * uses to communicate between clients and servers. 26 * 27 * In this code, I mainly concern myself with decoding the AFS calls, not 28 * with the guts of RX, per se. 29 * 30 * Bah. If I never look at rx_packet.h again, it will be too soon. 31 * 32 * Ken Hornstein <kenh (at) cmf.nrl.navy.mil> 33 */ 34 35 #ifndef lint 36 static const char rcsid[] _U_ = 37 "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.42 2008-07-01 07:44:50 guy Exp $"; 38 #endif 39 40 #ifdef HAVE_CONFIG_H 41 #include "config.h" 42 #endif 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <tcpdump-stdinc.h> 48 49 #include "interface.h" 50 #include "addrtoname.h" 51 #include "extract.h" 52 53 #include "rx.h" 54 55 #include "ip.h" 56 57 static const struct tok rx_types[] = { 58 { RX_PACKET_TYPE_DATA, "data" }, 59 { RX_PACKET_TYPE_ACK, "ack" }, 60 { RX_PACKET_TYPE_BUSY, "busy" }, 61 { RX_PACKET_TYPE_ABORT, "abort" }, 62 { RX_PACKET_TYPE_ACKALL, "ackall" }, 63 { RX_PACKET_TYPE_CHALLENGE, "challenge" }, 64 { RX_PACKET_TYPE_RESPONSE, "response" }, 65 { RX_PACKET_TYPE_DEBUG, "debug" }, 66 { RX_PACKET_TYPE_PARAMS, "params" }, 67 { RX_PACKET_TYPE_VERSION, "version" }, 68 { 0, NULL }, 69 }; 70 71 static struct double_tok { 72 int flag; /* Rx flag */ 73 int packetType; /* Packet type */ 74 const char *s; /* Flag string */ 75 } rx_flags[] = { 76 { RX_CLIENT_INITIATED, 0, "client-init" }, 77 { RX_REQUEST_ACK, 0, "req-ack" }, 78 { RX_LAST_PACKET, 0, "last-pckt" }, 79 { RX_MORE_PACKETS, 0, "more-pckts" }, 80 { RX_FREE_PACKET, 0, "free-pckt" }, 81 { RX_SLOW_START_OK, RX_PACKET_TYPE_ACK, "slow-start" }, 82 { RX_JUMBO_PACKET, RX_PACKET_TYPE_DATA, "jumbogram" } 83 }; 84 85 static const struct tok fs_req[] = { 86 { 130, "fetch-data" }, 87 { 131, "fetch-acl" }, 88 { 132, "fetch-status" }, 89 { 133, "store-data" }, 90 { 134, "store-acl" }, 91 { 135, "store-status" }, 92 { 136, "remove-file" }, 93 { 137, "create-file" }, 94 { 138, "rename" }, 95 { 139, "symlink" }, 96 { 140, "link" }, 97 { 141, "makedir" }, 98 { 142, "rmdir" }, 99 { 143, "oldsetlock" }, 100 { 144, "oldextlock" }, 101 { 145, "oldrellock" }, 102 { 146, "get-stats" }, 103 { 147, "give-cbs" }, 104 { 148, "get-vlinfo" }, 105 { 149, "get-vlstats" }, 106 { 150, "set-vlstats" }, 107 { 151, "get-rootvl" }, 108 { 152, "check-token" }, 109 { 153, "get-time" }, 110 { 154, "nget-vlinfo" }, 111 { 155, "bulk-stat" }, 112 { 156, "setlock" }, 113 { 157, "extlock" }, 114 { 158, "rellock" }, 115 { 159, "xstat-ver" }, 116 { 160, "get-xstat" }, 117 { 161, "dfs-lookup" }, 118 { 162, "dfs-flushcps" }, 119 { 163, "dfs-symlink" }, 120 { 220, "residency" }, 121 { 65536, "inline-bulk-status" }, 122 { 65537, "fetch-data-64" }, 123 { 65538, "store-data-64" }, 124 { 65539, "give-up-all-cbs" }, 125 { 65540, "get-caps" }, 126 { 65541, "cb-rx-conn-addr" }, 127 { 0, NULL }, 128 }; 129 130 static const struct tok cb_req[] = { 131 { 204, "callback" }, 132 { 205, "initcb" }, 133 { 206, "probe" }, 134 { 207, "getlock" }, 135 { 208, "getce" }, 136 { 209, "xstatver" }, 137 { 210, "getxstat" }, 138 { 211, "initcb2" }, 139 { 212, "whoareyou" }, 140 { 213, "initcb3" }, 141 { 214, "probeuuid" }, 142 { 215, "getsrvprefs" }, 143 { 216, "getcellservdb" }, 144 { 217, "getlocalcell" }, 145 { 218, "getcacheconf" }, 146 { 65536, "getce64" }, 147 { 65537, "getcellbynum" }, 148 { 65538, "tellmeaboutyourself" }, 149 { 0, NULL }, 150 }; 151 152 static const struct tok pt_req[] = { 153 { 500, "new-user" }, 154 { 501, "where-is-it" }, 155 { 502, "dump-entry" }, 156 { 503, "add-to-group" }, 157 { 504, "name-to-id" }, 158 { 505, "id-to-name" }, 159 { 506, "delete" }, 160 { 507, "remove-from-group" }, 161 { 508, "get-cps" }, 162 { 509, "new-entry" }, 163 { 510, "list-max" }, 164 { 511, "set-max" }, 165 { 512, "list-entry" }, 166 { 513, "change-entry" }, 167 { 514, "list-elements" }, 168 { 515, "same-mbr-of" }, 169 { 516, "set-fld-sentry" }, 170 { 517, "list-owned" }, 171 { 518, "get-cps2" }, 172 { 519, "get-host-cps" }, 173 { 520, "update-entry" }, 174 { 521, "list-entries" }, 175 { 530, "list-super-groups" }, 176 { 0, NULL }, 177 }; 178 179 static const struct tok vldb_req[] = { 180 { 501, "create-entry" }, 181 { 502, "delete-entry" }, 182 { 503, "get-entry-by-id" }, 183 { 504, "get-entry-by-name" }, 184 { 505, "get-new-volume-id" }, 185 { 506, "replace-entry" }, 186 { 507, "update-entry" }, 187 { 508, "setlock" }, 188 { 509, "releaselock" }, 189 { 510, "list-entry" }, 190 { 511, "list-attrib" }, 191 { 512, "linked-list" }, 192 { 513, "get-stats" }, 193 { 514, "probe" }, 194 { 515, "get-addrs" }, 195 { 516, "change-addr" }, 196 { 517, "create-entry-n" }, 197 { 518, "get-entry-by-id-n" }, 198 { 519, "get-entry-by-name-n" }, 199 { 520, "replace-entry-n" }, 200 { 521, "list-entry-n" }, 201 { 522, "list-attrib-n" }, 202 { 523, "linked-list-n" }, 203 { 524, "update-entry-by-name" }, 204 { 525, "create-entry-u" }, 205 { 526, "get-entry-by-id-u" }, 206 { 527, "get-entry-by-name-u" }, 207 { 528, "replace-entry-u" }, 208 { 529, "list-entry-u" }, 209 { 530, "list-attrib-u" }, 210 { 531, "linked-list-u" }, 211 { 532, "regaddr" }, 212 { 533, "get-addrs-u" }, 213 { 534, "list-attrib-n2" }, 214 { 0, NULL }, 215 }; 216 217 static const struct tok kauth_req[] = { 218 { 1, "auth-old" }, 219 { 21, "authenticate" }, 220 { 22, "authenticate-v2" }, 221 { 2, "change-pw" }, 222 { 3, "get-ticket-old" }, 223 { 23, "get-ticket" }, 224 { 4, "set-pw" }, 225 { 5, "set-fields" }, 226 { 6, "create-user" }, 227 { 7, "delete-user" }, 228 { 8, "get-entry" }, 229 { 9, "list-entry" }, 230 { 10, "get-stats" }, 231 { 11, "debug" }, 232 { 12, "get-pw" }, 233 { 13, "get-random-key" }, 234 { 14, "unlock" }, 235 { 15, "lock-status" }, 236 { 0, NULL }, 237 }; 238 239 static const struct tok vol_req[] = { 240 { 100, "create-volume" }, 241 { 101, "delete-volume" }, 242 { 102, "restore" }, 243 { 103, "forward" }, 244 { 104, "end-trans" }, 245 { 105, "clone" }, 246 { 106, "set-flags" }, 247 { 107, "get-flags" }, 248 { 108, "trans-create" }, 249 { 109, "dump" }, 250 { 110, "get-nth-volume" }, 251 { 111, "set-forwarding" }, 252 { 112, "get-name" }, 253 { 113, "get-status" }, 254 { 114, "sig-restore" }, 255 { 115, "list-partitions" }, 256 { 116, "list-volumes" }, 257 { 117, "set-id-types" }, 258 { 118, "monitor" }, 259 { 119, "partition-info" }, 260 { 120, "reclone" }, 261 { 121, "list-one-volume" }, 262 { 122, "nuke" }, 263 { 123, "set-date" }, 264 { 124, "x-list-volumes" }, 265 { 125, "x-list-one-volume" }, 266 { 126, "set-info" }, 267 { 127, "x-list-partitions" }, 268 { 128, "forward-multiple" }, 269 { 65536, "convert-ro" }, 270 { 65537, "get-size" }, 271 { 65538, "dump-v2" }, 272 { 0, NULL }, 273 }; 274 275 static const struct tok bos_req[] = { 276 { 80, "create-bnode" }, 277 { 81, "delete-bnode" }, 278 { 82, "set-status" }, 279 { 83, "get-status" }, 280 { 84, "enumerate-instance" }, 281 { 85, "get-instance-info" }, 282 { 86, "get-instance-parm" }, 283 { 87, "add-superuser" }, 284 { 88, "delete-superuser" }, 285 { 89, "list-superusers" }, 286 { 90, "list-keys" }, 287 { 91, "add-key" }, 288 { 92, "delete-key" }, 289 { 93, "set-cell-name" }, 290 { 94, "get-cell-name" }, 291 { 95, "get-cell-host" }, 292 { 96, "add-cell-host" }, 293 { 97, "delete-cell-host" }, 294 { 98, "set-t-status" }, 295 { 99, "shutdown-all" }, 296 { 100, "restart-all" }, 297 { 101, "startup-all" }, 298 { 102, "set-noauth-flag" }, 299 { 103, "re-bozo" }, 300 { 104, "restart" }, 301 { 105, "start-bozo-install" }, 302 { 106, "uninstall" }, 303 { 107, "get-dates" }, 304 { 108, "exec" }, 305 { 109, "prune" }, 306 { 110, "set-restart-time" }, 307 { 111, "get-restart-time" }, 308 { 112, "start-bozo-log" }, 309 { 113, "wait-all" }, 310 { 114, "get-instance-strings" }, 311 { 115, "get-restricted" }, 312 { 116, "set-restricted" }, 313 { 0, NULL }, 314 }; 315 316 static const struct tok ubik_req[] = { 317 { 10000, "vote-beacon" }, 318 { 10001, "vote-debug-old" }, 319 { 10002, "vote-sdebug-old" }, 320 { 10003, "vote-getsyncsite" }, 321 { 10004, "vote-debug" }, 322 { 10005, "vote-sdebug" }, 323 { 10006, "vote-xdebug" }, 324 { 10007, "vote-xsdebug" }, 325 { 20000, "disk-begin" }, 326 { 20001, "disk-commit" }, 327 { 20002, "disk-lock" }, 328 { 20003, "disk-write" }, 329 { 20004, "disk-getversion" }, 330 { 20005, "disk-getfile" }, 331 { 20006, "disk-sendfile" }, 332 { 20007, "disk-abort" }, 333 { 20008, "disk-releaselocks" }, 334 { 20009, "disk-truncate" }, 335 { 20010, "disk-probe" }, 336 { 20011, "disk-writev" }, 337 { 20012, "disk-interfaceaddr" }, 338 { 20013, "disk-setversion" }, 339 { 0, NULL }, 340 }; 341 342 #define VOTE_LOW 10000 343 #define VOTE_HIGH 10007 344 #define DISK_LOW 20000 345 #define DISK_HIGH 20013 346 347 static const struct tok cb_types[] = { 348 { 1, "exclusive" }, 349 { 2, "shared" }, 350 { 3, "dropped" }, 351 { 0, NULL }, 352 }; 353 354 static const struct tok ubik_lock_types[] = { 355 { 1, "read" }, 356 { 2, "write" }, 357 { 3, "wait" }, 358 { 0, NULL }, 359 }; 360 361 static const char *voltype[] = { "read-write", "read-only", "backup" }; 362 363 static const struct tok afs_fs_errors[] = { 364 { 101, "salvage volume" }, 365 { 102, "no such vnode" }, 366 { 103, "no such volume" }, 367 { 104, "volume exist" }, 368 { 105, "no service" }, 369 { 106, "volume offline" }, 370 { 107, "voline online" }, 371 { 108, "diskfull" }, 372 { 109, "diskquota exceeded" }, 373 { 110, "volume busy" }, 374 { 111, "volume moved" }, 375 { 112, "AFS IO error" }, 376 { -100, "restarting fileserver" }, 377 { 0, NULL } 378 }; 379 380 /* 381 * Reasons for acknowledging a packet 382 */ 383 384 static const struct tok rx_ack_reasons[] = { 385 { 1, "ack requested" }, 386 { 2, "duplicate packet" }, 387 { 3, "out of sequence" }, 388 { 4, "exceeds window" }, 389 { 5, "no buffer space" }, 390 { 6, "ping" }, 391 { 7, "ping response" }, 392 { 8, "delay" }, 393 { 9, "idle" }, 394 { 0, NULL }, 395 }; 396 397 /* 398 * Cache entries we keep around so we can figure out the RX opcode 399 * numbers for replies. This allows us to make sense of RX reply packets. 400 */ 401 402 struct rx_cache_entry { 403 u_int32_t callnum; /* Call number (net order) */ 404 struct in_addr client; /* client IP address (net order) */ 405 struct in_addr server; /* server IP address (net order) */ 406 int dport; /* server port (host order) */ 407 u_short serviceId; /* Service identifier (net order) */ 408 u_int32_t opcode; /* RX opcode (host order) */ 409 }; 410 411 #define RX_CACHE_SIZE 64 412 413 static struct rx_cache_entry rx_cache[RX_CACHE_SIZE]; 414 415 static int rx_cache_next = 0; 416 static int rx_cache_hint = 0; 417 static void rx_cache_insert(const u_char *, const struct ip *, int); 418 static int rx_cache_find(const struct rx_header *, const struct ip *, 419 int, int32_t *); 420 421 static void fs_print(const u_char *, int); 422 static void fs_reply_print(const u_char *, int, int32_t); 423 static void acl_print(u_char *, int, u_char *); 424 static void cb_print(const u_char *, int); 425 static void cb_reply_print(const u_char *, int, int32_t); 426 static void prot_print(const u_char *, int); 427 static void prot_reply_print(const u_char *, int, int32_t); 428 static void vldb_print(const u_char *, int); 429 static void vldb_reply_print(const u_char *, int, int32_t); 430 static void kauth_print(const u_char *, int); 431 static void kauth_reply_print(const u_char *, int, int32_t); 432 static void vol_print(const u_char *, int); 433 static void vol_reply_print(const u_char *, int, int32_t); 434 static void bos_print(const u_char *, int); 435 static void bos_reply_print(const u_char *, int, int32_t); 436 static void ubik_print(const u_char *); 437 static void ubik_reply_print(const u_char *, int, int32_t); 438 439 static void rx_ack_print(const u_char *, int); 440 441 static int is_ubik(u_int32_t); 442 443 /* 444 * Handle the rx-level packet. See if we know what port it's going to so 445 * we can peek at the afs call inside 446 */ 447 448 void 449 rx_print(register const u_char *bp, int length, int sport, int dport, 450 u_char *bp2) 451 { 452 register struct rx_header *rxh; 453 int i; 454 int32_t opcode; 455 456 if (snapend - bp < (int)sizeof (struct rx_header)) { 457 printf(" [|rx] (%d)", length); 458 return; 459 } 460 461 rxh = (struct rx_header *) bp; 462 463 printf(" rx %s", tok2str(rx_types, "type %d", rxh->type)); 464 465 if (vflag) { 466 int firstflag = 0; 467 468 if (vflag > 1) 469 printf(" cid %08x call# %d", 470 (int) EXTRACT_32BITS(&rxh->cid), 471 (int) EXTRACT_32BITS(&rxh->callNumber)); 472 473 printf(" seq %d ser %d", 474 (int) EXTRACT_32BITS(&rxh->seq), 475 (int) EXTRACT_32BITS(&rxh->serial)); 476 477 if (vflag > 2) 478 printf(" secindex %d serviceid %hu", 479 (int) rxh->securityIndex, 480 EXTRACT_16BITS(&rxh->serviceId)); 481 482 if (vflag > 1) 483 for (i = 0; i < NUM_RX_FLAGS; i++) { 484 if (rxh->flags & rx_flags[i].flag && 485 (!rx_flags[i].packetType || 486 rxh->type == rx_flags[i].packetType)) { 487 if (!firstflag) { 488 firstflag = 1; 489 printf(" "); 490 } else { 491 printf(","); 492 } 493 printf("<%s>", rx_flags[i].s); 494 } 495 } 496 } 497 498 /* 499 * Try to handle AFS calls that we know about. Check the destination 500 * port and make sure it's a data packet. Also, make sure the 501 * seq number is 1 (because otherwise it's a continuation packet, 502 * and we can't interpret that). Also, seems that reply packets 503 * do not have the client-init flag set, so we check for that 504 * as well. 505 */ 506 507 if (rxh->type == RX_PACKET_TYPE_DATA && 508 EXTRACT_32BITS(&rxh->seq) == 1 && 509 rxh->flags & RX_CLIENT_INITIATED) { 510 511 /* 512 * Insert this call into the call cache table, so we 513 * have a chance to print out replies 514 */ 515 516 rx_cache_insert(bp, (const struct ip *) bp2, dport); 517 518 switch (dport) { 519 case FS_RX_PORT: /* AFS file service */ 520 fs_print(bp, length); 521 break; 522 case CB_RX_PORT: /* AFS callback service */ 523 cb_print(bp, length); 524 break; 525 case PROT_RX_PORT: /* AFS protection service */ 526 prot_print(bp, length); 527 break; 528 case VLDB_RX_PORT: /* AFS VLDB service */ 529 vldb_print(bp, length); 530 break; 531 case KAUTH_RX_PORT: /* AFS Kerberos auth service */ 532 kauth_print(bp, length); 533 break; 534 case VOL_RX_PORT: /* AFS Volume service */ 535 vol_print(bp, length); 536 break; 537 case BOS_RX_PORT: /* AFS BOS service */ 538 bos_print(bp, length); 539 break; 540 default: 541 ; 542 } 543 544 /* 545 * If it's a reply (client-init is _not_ set, but seq is one) 546 * then look it up in the cache. If we find it, call the reply 547 * printing functions Note that we handle abort packets here, 548 * because printing out the return code can be useful at times. 549 */ 550 551 } else if (((rxh->type == RX_PACKET_TYPE_DATA && 552 EXTRACT_32BITS(&rxh->seq) == 1) || 553 rxh->type == RX_PACKET_TYPE_ABORT) && 554 (rxh->flags & RX_CLIENT_INITIATED) == 0 && 555 rx_cache_find(rxh, (const struct ip *) bp2, 556 sport, &opcode)) { 557 558 switch (sport) { 559 case FS_RX_PORT: /* AFS file service */ 560 fs_reply_print(bp, length, opcode); 561 break; 562 case CB_RX_PORT: /* AFS callback service */ 563 cb_reply_print(bp, length, opcode); 564 break; 565 case PROT_RX_PORT: /* AFS PT service */ 566 prot_reply_print(bp, length, opcode); 567 break; 568 case VLDB_RX_PORT: /* AFS VLDB service */ 569 vldb_reply_print(bp, length, opcode); 570 break; 571 case KAUTH_RX_PORT: /* AFS Kerberos auth service */ 572 kauth_reply_print(bp, length, opcode); 573 break; 574 case VOL_RX_PORT: /* AFS Volume service */ 575 vol_reply_print(bp, length, opcode); 576 break; 577 case BOS_RX_PORT: /* AFS BOS service */ 578 bos_reply_print(bp, length, opcode); 579 break; 580 default: 581 ; 582 } 583 584 /* 585 * If it's an RX ack packet, then use the appropriate ack decoding 586 * function (there isn't any service-specific information in the 587 * ack packet, so we can use one for all AFS services) 588 */ 589 590 } else if (rxh->type == RX_PACKET_TYPE_ACK) 591 rx_ack_print(bp, length); 592 593 594 printf(" (%d)", length); 595 } 596 597 /* 598 * Insert an entry into the cache. Taken from print-nfs.c 599 */ 600 601 static void 602 rx_cache_insert(const u_char *bp, const struct ip *ip, int dport) 603 { 604 struct rx_cache_entry *rxent; 605 const struct rx_header *rxh = (const struct rx_header *) bp; 606 607 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) 608 return; 609 610 rxent = &rx_cache[rx_cache_next]; 611 612 if (++rx_cache_next >= RX_CACHE_SIZE) 613 rx_cache_next = 0; 614 615 rxent->callnum = rxh->callNumber; 616 rxent->client = ip->ip_src; 617 rxent->server = ip->ip_dst; 618 rxent->dport = dport; 619 rxent->serviceId = rxh->serviceId; 620 rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 621 } 622 623 /* 624 * Lookup an entry in the cache. Also taken from print-nfs.c 625 * 626 * Note that because this is a reply, we're looking at the _source_ 627 * port. 628 */ 629 630 static int 631 rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, 632 int32_t *opcode) 633 { 634 int i; 635 struct rx_cache_entry *rxent; 636 u_int32_t clip = ip->ip_dst.s_addr; 637 u_int32_t sip = ip->ip_src.s_addr; 638 639 /* Start the search where we last left off */ 640 641 i = rx_cache_hint; 642 do { 643 rxent = &rx_cache[i]; 644 if (rxent->callnum == rxh->callNumber && 645 rxent->client.s_addr == clip && 646 rxent->server.s_addr == sip && 647 rxent->serviceId == rxh->serviceId && 648 rxent->dport == sport) { 649 650 /* We got a match! */ 651 652 rx_cache_hint = i; 653 *opcode = rxent->opcode; 654 return(1); 655 } 656 if (++i >= RX_CACHE_SIZE) 657 i = 0; 658 } while (i != rx_cache_hint); 659 660 /* Our search failed */ 661 return(0); 662 } 663 664 /* 665 * These extrememly grody macros handle the printing of various AFS stuff. 666 */ 667 668 #define FIDOUT() { unsigned long n1, n2, n3; \ 669 TCHECK2(bp[0], sizeof(int32_t) * 3); \ 670 n1 = EXTRACT_32BITS(bp); \ 671 bp += sizeof(int32_t); \ 672 n2 = EXTRACT_32BITS(bp); \ 673 bp += sizeof(int32_t); \ 674 n3 = EXTRACT_32BITS(bp); \ 675 bp += sizeof(int32_t); \ 676 printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \ 677 } 678 679 #define STROUT(MAX) { unsigned int i; \ 680 TCHECK2(bp[0], sizeof(int32_t)); \ 681 i = EXTRACT_32BITS(bp); \ 682 if (i > (MAX)) \ 683 goto trunc; \ 684 bp += sizeof(int32_t); \ 685 printf(" \""); \ 686 if (fn_printn(bp, i, snapend)) \ 687 goto trunc; \ 688 printf("\""); \ 689 bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \ 690 } 691 692 #define INTOUT() { int i; \ 693 TCHECK2(bp[0], sizeof(int32_t)); \ 694 i = (int) EXTRACT_32BITS(bp); \ 695 bp += sizeof(int32_t); \ 696 printf(" %d", i); \ 697 } 698 699 #define UINTOUT() { unsigned long i; \ 700 TCHECK2(bp[0], sizeof(int32_t)); \ 701 i = EXTRACT_32BITS(bp); \ 702 bp += sizeof(int32_t); \ 703 printf(" %lu", i); \ 704 } 705 706 #define UINT64OUT() { u_int64_t i; \ 707 TCHECK2(bp[0], sizeof(u_int64_t)); \ 708 i = EXTRACT_64BITS(bp); \ 709 bp += sizeof(u_int64_t); \ 710 printf(" %" PRIu64, i); \ 711 } 712 713 #define DATEOUT() { time_t t; struct tm *tm; char str[256]; \ 714 TCHECK2(bp[0], sizeof(int32_t)); \ 715 t = (time_t) EXTRACT_32BITS(bp); \ 716 bp += sizeof(int32_t); \ 717 tm = localtime(&t); \ 718 strftime(str, 256, "%Y/%m/%d %T", tm); \ 719 printf(" %s", str); \ 720 } 721 722 #define STOREATTROUT() { unsigned long mask, i; \ 723 TCHECK2(bp[0], (sizeof(int32_t)*6)); \ 724 mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 725 if (mask) printf (" StoreStatus"); \ 726 if (mask & 1) { printf(" date"); DATEOUT(); } \ 727 else bp += sizeof(int32_t); \ 728 i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 729 if (mask & 2) printf(" owner %lu", i); \ 730 i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 731 if (mask & 4) printf(" group %lu", i); \ 732 i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 733 if (mask & 8) printf(" mode %lo", i & 07777); \ 734 i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 735 if (mask & 16) printf(" segsize %lu", i); \ 736 /* undocumented in 3.3 docu */ \ 737 if (mask & 1024) printf(" fsync"); \ 738 } 739 740 #define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \ 741 TCHECK2(bp[0], sizeof(int32_t) * 2); \ 742 epoch = EXTRACT_32BITS(bp); \ 743 bp += sizeof(int32_t); \ 744 counter = EXTRACT_32BITS(bp); \ 745 bp += sizeof(int32_t); \ 746 printf(" %d.%d", epoch, counter); \ 747 } 748 749 #define AFSUUIDOUT() {u_int32_t temp; int i; \ 750 TCHECK2(bp[0], 11*sizeof(u_int32_t)); \ 751 temp = EXTRACT_32BITS(bp); \ 752 bp += sizeof(u_int32_t); \ 753 printf(" %08x", temp); \ 754 temp = EXTRACT_32BITS(bp); \ 755 bp += sizeof(u_int32_t); \ 756 printf("%04x", temp); \ 757 temp = EXTRACT_32BITS(bp); \ 758 bp += sizeof(u_int32_t); \ 759 printf("%04x", temp); \ 760 for (i = 0; i < 8; i++) { \ 761 temp = EXTRACT_32BITS(bp); \ 762 bp += sizeof(u_int32_t); \ 763 printf("%02x", (unsigned char) temp); \ 764 } \ 765 } 766 767 /* 768 * This is the sickest one of all 769 */ 770 771 #define VECOUT(MAX) { u_char *sp; \ 772 u_char s[AFSNAMEMAX]; \ 773 int k; \ 774 if ((MAX) + 1 > sizeof(s)) \ 775 goto trunc; \ 776 TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \ 777 sp = s; \ 778 for (k = 0; k < (MAX); k++) { \ 779 *sp++ = (u_char) EXTRACT_32BITS(bp); \ 780 bp += sizeof(int32_t); \ 781 } \ 782 s[(MAX)] = '\0'; \ 783 printf(" \""); \ 784 fn_print(s, NULL); \ 785 printf("\""); \ 786 } 787 788 #define DESTSERVEROUT() { unsigned long n1, n2, n3; \ 789 TCHECK2(bp[0], sizeof(int32_t) * 3); \ 790 n1 = EXTRACT_32BITS(bp); \ 791 bp += sizeof(int32_t); \ 792 n2 = EXTRACT_32BITS(bp); \ 793 bp += sizeof(int32_t); \ 794 n3 = EXTRACT_32BITS(bp); \ 795 bp += sizeof(int32_t); \ 796 printf(" server %d:%d:%d", (int) n1, (int) n2, (int) n3); \ 797 } 798 799 /* 800 * Handle calls to the AFS file service (fs) 801 */ 802 803 static void 804 fs_print(register const u_char *bp, int length) 805 { 806 int fs_op; 807 unsigned long i; 808 809 if (length <= (int)sizeof(struct rx_header)) 810 return; 811 812 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 813 goto trunc; 814 } 815 816 /* 817 * Print out the afs call we're invoking. The table used here was 818 * gleaned from fsint/afsint.xg 819 */ 820 821 fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 822 823 printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op)); 824 825 /* 826 * Print out arguments to some of the AFS calls. This stuff is 827 * all from afsint.xg 828 */ 829 830 bp += sizeof(struct rx_header) + 4; 831 832 /* 833 * Sigh. This is gross. Ritchie forgive me. 834 */ 835 836 switch (fs_op) { 837 case 130: /* Fetch data */ 838 FIDOUT(); 839 printf(" offset"); 840 UINTOUT(); 841 printf(" length"); 842 UINTOUT(); 843 break; 844 case 131: /* Fetch ACL */ 845 case 132: /* Fetch Status */ 846 case 143: /* Old set lock */ 847 case 144: /* Old extend lock */ 848 case 145: /* Old release lock */ 849 case 156: /* Set lock */ 850 case 157: /* Extend lock */ 851 case 158: /* Release lock */ 852 FIDOUT(); 853 break; 854 case 135: /* Store status */ 855 FIDOUT(); 856 STOREATTROUT(); 857 break; 858 case 133: /* Store data */ 859 FIDOUT(); 860 STOREATTROUT(); 861 printf(" offset"); 862 UINTOUT(); 863 printf(" length"); 864 UINTOUT(); 865 printf(" flen"); 866 UINTOUT(); 867 break; 868 case 134: /* Store ACL */ 869 { 870 char a[AFSOPAQUEMAX+1]; 871 FIDOUT(); 872 TCHECK2(bp[0], 4); 873 i = EXTRACT_32BITS(bp); 874 bp += sizeof(int32_t); 875 TCHECK2(bp[0], i); 876 i = min(AFSOPAQUEMAX, i); 877 strncpy(a, (char *) bp, i); 878 a[i] = '\0'; 879 acl_print((u_char *) a, sizeof(a), (u_char *) a + i); 880 break; 881 } 882 case 137: /* Create file */ 883 case 141: /* MakeDir */ 884 FIDOUT(); 885 STROUT(AFSNAMEMAX); 886 STOREATTROUT(); 887 break; 888 case 136: /* Remove file */ 889 case 142: /* Remove directory */ 890 FIDOUT(); 891 STROUT(AFSNAMEMAX); 892 break; 893 case 138: /* Rename file */ 894 printf(" old"); 895 FIDOUT(); 896 STROUT(AFSNAMEMAX); 897 printf(" new"); 898 FIDOUT(); 899 STROUT(AFSNAMEMAX); 900 break; 901 case 139: /* Symlink */ 902 FIDOUT(); 903 STROUT(AFSNAMEMAX); 904 printf(" link to"); 905 STROUT(AFSNAMEMAX); 906 break; 907 case 140: /* Link */ 908 FIDOUT(); 909 STROUT(AFSNAMEMAX); 910 printf(" link to"); 911 FIDOUT(); 912 break; 913 case 148: /* Get volume info */ 914 STROUT(AFSNAMEMAX); 915 break; 916 case 149: /* Get volume stats */ 917 case 150: /* Set volume stats */ 918 printf(" volid"); 919 UINTOUT(); 920 break; 921 case 154: /* New get volume info */ 922 printf(" volname"); 923 STROUT(AFSNAMEMAX); 924 break; 925 case 155: /* Bulk stat */ 926 case 65536: /* Inline bulk stat */ 927 { 928 unsigned long j; 929 TCHECK2(bp[0], 4); 930 j = EXTRACT_32BITS(bp); 931 bp += sizeof(int32_t); 932 933 for (i = 0; i < j; i++) { 934 FIDOUT(); 935 if (i != j - 1) 936 printf(","); 937 } 938 if (j == 0) 939 printf(" <none!>"); 940 } 941 case 65537: /* Fetch data 64 */ 942 FIDOUT(); 943 printf(" offset"); 944 UINT64OUT(); 945 printf(" length"); 946 UINT64OUT(); 947 break; 948 case 65538: /* Store data 64 */ 949 FIDOUT(); 950 STOREATTROUT(); 951 printf(" offset"); 952 UINT64OUT(); 953 printf(" length"); 954 UINT64OUT(); 955 printf(" flen"); 956 UINT64OUT(); 957 break; 958 case 65541: /* CallBack rx conn address */ 959 printf(" addr"); 960 UINTOUT(); 961 default: 962 ; 963 } 964 965 return; 966 967 trunc: 968 printf(" [|fs]"); 969 } 970 971 /* 972 * Handle replies to the AFS file service 973 */ 974 975 static void 976 fs_reply_print(register const u_char *bp, int length, int32_t opcode) 977 { 978 unsigned long i; 979 struct rx_header *rxh; 980 981 if (length <= (int)sizeof(struct rx_header)) 982 return; 983 984 rxh = (struct rx_header *) bp; 985 986 /* 987 * Print out the afs call we're invoking. The table used here was 988 * gleaned from fsint/afsint.xg 989 */ 990 991 printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode)); 992 993 bp += sizeof(struct rx_header); 994 995 /* 996 * If it was a data packet, interpret the response 997 */ 998 999 if (rxh->type == RX_PACKET_TYPE_DATA) { 1000 switch (opcode) { 1001 case 131: /* Fetch ACL */ 1002 { 1003 char a[AFSOPAQUEMAX+1]; 1004 TCHECK2(bp[0], 4); 1005 i = EXTRACT_32BITS(bp); 1006 bp += sizeof(int32_t); 1007 TCHECK2(bp[0], i); 1008 i = min(AFSOPAQUEMAX, i); 1009 strncpy(a, (char *) bp, i); 1010 a[i] = '\0'; 1011 acl_print((u_char *) a, sizeof(a), (u_char *) a + i); 1012 break; 1013 } 1014 case 137: /* Create file */ 1015 case 141: /* MakeDir */ 1016 printf(" new"); 1017 FIDOUT(); 1018 break; 1019 case 151: /* Get root volume */ 1020 printf(" root volume"); 1021 STROUT(AFSNAMEMAX); 1022 break; 1023 case 153: /* Get time */ 1024 DATEOUT(); 1025 break; 1026 default: 1027 ; 1028 } 1029 } else if (rxh->type == RX_PACKET_TYPE_ABORT) { 1030 int i; 1031 1032 /* 1033 * Otherwise, just print out the return code 1034 */ 1035 TCHECK2(bp[0], sizeof(int32_t)); 1036 i = (int) EXTRACT_32BITS(bp); 1037 bp += sizeof(int32_t); 1038 1039 printf(" error %s", tok2str(afs_fs_errors, "#%d", i)); 1040 } else { 1041 printf(" strange fs reply of type %d", rxh->type); 1042 } 1043 1044 return; 1045 1046 trunc: 1047 printf(" [|fs]"); 1048 } 1049 1050 /* 1051 * Print out an AFS ACL string. An AFS ACL is a string that has the 1052 * following format: 1053 * 1054 * <positive> <negative> 1055 * <uid1> <aclbits1> 1056 * .... 1057 * 1058 * "positive" and "negative" are integers which contain the number of 1059 * positive and negative ACL's in the string. The uid/aclbits pair are 1060 * ASCII strings containing the UID/PTS record and and a ascii number 1061 * representing a logical OR of all the ACL permission bits 1062 */ 1063 1064 static void 1065 acl_print(u_char *s, int maxsize, u_char *end) 1066 { 1067 int pos, neg, acl; 1068 int n, i; 1069 char *user; 1070 char fmt[1024]; 1071 1072 if ((user = (char *)malloc(maxsize)) == NULL) 1073 return; 1074 1075 if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2) 1076 goto finish; 1077 1078 s += n; 1079 1080 if (s > end) 1081 goto finish; 1082 1083 /* 1084 * This wacky order preserves the order used by the "fs" command 1085 */ 1086 1087 #define ACLOUT(acl) \ 1088 if (acl & PRSFS_READ) \ 1089 printf("r"); \ 1090 if (acl & PRSFS_LOOKUP) \ 1091 printf("l"); \ 1092 if (acl & PRSFS_INSERT) \ 1093 printf("i"); \ 1094 if (acl & PRSFS_DELETE) \ 1095 printf("d"); \ 1096 if (acl & PRSFS_WRITE) \ 1097 printf("w"); \ 1098 if (acl & PRSFS_LOCK) \ 1099 printf("k"); \ 1100 if (acl & PRSFS_ADMINISTER) \ 1101 printf("a"); 1102 1103 for (i = 0; i < pos; i++) { 1104 snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1); 1105 if (sscanf((char *) s, fmt, user, &acl, &n) != 2) 1106 goto finish; 1107 s += n; 1108 printf(" +{"); 1109 fn_print((u_char *)user, NULL); 1110 printf(" "); 1111 ACLOUT(acl); 1112 printf("}"); 1113 if (s > end) 1114 goto finish; 1115 } 1116 1117 for (i = 0; i < neg; i++) { 1118 snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1); 1119 if (sscanf((char *) s, fmt, user, &acl, &n) != 2) 1120 goto finish; 1121 s += n; 1122 printf(" -{"); 1123 fn_print((u_char *)user, NULL); 1124 printf(" "); 1125 ACLOUT(acl); 1126 printf("}"); 1127 if (s > end) 1128 goto finish; 1129 } 1130 1131 finish: 1132 free(user); 1133 return; 1134 } 1135 1136 #undef ACLOUT 1137 1138 /* 1139 * Handle calls to the AFS callback service 1140 */ 1141 1142 static void 1143 cb_print(register const u_char *bp, int length) 1144 { 1145 int cb_op; 1146 unsigned long i; 1147 1148 if (length <= (int)sizeof(struct rx_header)) 1149 return; 1150 1151 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 1152 goto trunc; 1153 } 1154 1155 /* 1156 * Print out the afs call we're invoking. The table used here was 1157 * gleaned from fsint/afscbint.xg 1158 */ 1159 1160 cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 1161 1162 printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op)); 1163 1164 bp += sizeof(struct rx_header) + 4; 1165 1166 /* 1167 * Print out the afs call we're invoking. The table used here was 1168 * gleaned from fsint/afscbint.xg 1169 */ 1170 1171 switch (cb_op) { 1172 case 204: /* Callback */ 1173 { 1174 unsigned long j, t; 1175 TCHECK2(bp[0], 4); 1176 j = EXTRACT_32BITS(bp); 1177 bp += sizeof(int32_t); 1178 1179 for (i = 0; i < j; i++) { 1180 FIDOUT(); 1181 if (i != j - 1) 1182 printf(","); 1183 } 1184 1185 if (j == 0) 1186 printf(" <none!>"); 1187 1188 j = EXTRACT_32BITS(bp); 1189 bp += sizeof(int32_t); 1190 1191 if (j != 0) 1192 printf(";"); 1193 1194 for (i = 0; i < j; i++) { 1195 printf(" ver"); 1196 INTOUT(); 1197 printf(" expires"); 1198 DATEOUT(); 1199 TCHECK2(bp[0], 4); 1200 t = EXTRACT_32BITS(bp); 1201 bp += sizeof(int32_t); 1202 tok2str(cb_types, "type %d", t); 1203 } 1204 } 1205 case 214: { 1206 printf(" afsuuid"); 1207 AFSUUIDOUT(); 1208 break; 1209 } 1210 default: 1211 ; 1212 } 1213 1214 return; 1215 1216 trunc: 1217 printf(" [|cb]"); 1218 } 1219 1220 /* 1221 * Handle replies to the AFS Callback Service 1222 */ 1223 1224 static void 1225 cb_reply_print(register const u_char *bp, int length, int32_t opcode) 1226 { 1227 struct rx_header *rxh; 1228 1229 if (length <= (int)sizeof(struct rx_header)) 1230 return; 1231 1232 rxh = (struct rx_header *) bp; 1233 1234 /* 1235 * Print out the afs call we're invoking. The table used here was 1236 * gleaned from fsint/afscbint.xg 1237 */ 1238 1239 printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode)); 1240 1241 bp += sizeof(struct rx_header); 1242 1243 /* 1244 * If it was a data packet, interpret the response. 1245 */ 1246 1247 if (rxh->type == RX_PACKET_TYPE_DATA) 1248 switch (opcode) { 1249 case 213: /* InitCallBackState3 */ 1250 AFSUUIDOUT(); 1251 break; 1252 default: 1253 ; 1254 } 1255 else { 1256 /* 1257 * Otherwise, just print out the return code 1258 */ 1259 printf(" errcode"); 1260 INTOUT(); 1261 } 1262 1263 return; 1264 1265 trunc: 1266 printf(" [|cb]"); 1267 } 1268 1269 /* 1270 * Handle calls to the AFS protection database server 1271 */ 1272 1273 static void 1274 prot_print(register const u_char *bp, int length) 1275 { 1276 unsigned long i; 1277 int pt_op; 1278 1279 if (length <= (int)sizeof(struct rx_header)) 1280 return; 1281 1282 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 1283 goto trunc; 1284 } 1285 1286 /* 1287 * Print out the afs call we're invoking. The table used here was 1288 * gleaned from ptserver/ptint.xg 1289 */ 1290 1291 pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 1292 1293 printf(" pt"); 1294 1295 if (is_ubik(pt_op)) { 1296 ubik_print(bp); 1297 return; 1298 } 1299 1300 printf(" call %s", tok2str(pt_req, "op#%d", pt_op)); 1301 1302 /* 1303 * Decode some of the arguments to the PT calls 1304 */ 1305 1306 bp += sizeof(struct rx_header) + 4; 1307 1308 switch (pt_op) { 1309 case 500: /* I New User */ 1310 STROUT(PRNAMEMAX); 1311 printf(" id"); 1312 INTOUT(); 1313 printf(" oldid"); 1314 INTOUT(); 1315 break; 1316 case 501: /* Where is it */ 1317 case 506: /* Delete */ 1318 case 508: /* Get CPS */ 1319 case 512: /* List entry */ 1320 case 514: /* List elements */ 1321 case 517: /* List owned */ 1322 case 518: /* Get CPS2 */ 1323 case 519: /* Get host CPS */ 1324 case 530: /* List super groups */ 1325 printf(" id"); 1326 INTOUT(); 1327 break; 1328 case 502: /* Dump entry */ 1329 printf(" pos"); 1330 INTOUT(); 1331 break; 1332 case 503: /* Add to group */ 1333 case 507: /* Remove from group */ 1334 case 515: /* Is a member of? */ 1335 printf(" uid"); 1336 INTOUT(); 1337 printf(" gid"); 1338 INTOUT(); 1339 break; 1340 case 504: /* Name to ID */ 1341 { 1342 unsigned long j; 1343 TCHECK2(bp[0], 4); 1344 j = EXTRACT_32BITS(bp); 1345 bp += sizeof(int32_t); 1346 1347 /* 1348 * Who designed this chicken-shit protocol? 1349 * 1350 * Each character is stored as a 32-bit 1351 * integer! 1352 */ 1353 1354 for (i = 0; i < j; i++) { 1355 VECOUT(PRNAMEMAX); 1356 } 1357 if (j == 0) 1358 printf(" <none!>"); 1359 } 1360 break; 1361 case 505: /* Id to name */ 1362 { 1363 unsigned long j; 1364 printf(" ids:"); 1365 TCHECK2(bp[0], 4); 1366 i = EXTRACT_32BITS(bp); 1367 bp += sizeof(int32_t); 1368 for (j = 0; j < i; j++) 1369 INTOUT(); 1370 if (j == 0) 1371 printf(" <none!>"); 1372 } 1373 break; 1374 case 509: /* New entry */ 1375 STROUT(PRNAMEMAX); 1376 printf(" flag"); 1377 INTOUT(); 1378 printf(" oid"); 1379 INTOUT(); 1380 break; 1381 case 511: /* Set max */ 1382 printf(" id"); 1383 INTOUT(); 1384 printf(" gflag"); 1385 INTOUT(); 1386 break; 1387 case 513: /* Change entry */ 1388 printf(" id"); 1389 INTOUT(); 1390 STROUT(PRNAMEMAX); 1391 printf(" oldid"); 1392 INTOUT(); 1393 printf(" newid"); 1394 INTOUT(); 1395 break; 1396 case 520: /* Update entry */ 1397 printf(" id"); 1398 INTOUT(); 1399 STROUT(PRNAMEMAX); 1400 break; 1401 default: 1402 ; 1403 } 1404 1405 1406 return; 1407 1408 trunc: 1409 printf(" [|pt]"); 1410 } 1411 1412 /* 1413 * Handle replies to the AFS protection service 1414 */ 1415 1416 static void 1417 prot_reply_print(register const u_char *bp, int length, int32_t opcode) 1418 { 1419 struct rx_header *rxh; 1420 unsigned long i; 1421 1422 if (length < (int)sizeof(struct rx_header)) 1423 return; 1424 1425 rxh = (struct rx_header *) bp; 1426 1427 /* 1428 * Print out the afs call we're invoking. The table used here was 1429 * gleaned from ptserver/ptint.xg. Check to see if it's a 1430 * Ubik call, however. 1431 */ 1432 1433 printf(" pt"); 1434 1435 if (is_ubik(opcode)) { 1436 ubik_reply_print(bp, length, opcode); 1437 return; 1438 } 1439 1440 printf(" reply %s", tok2str(pt_req, "op#%d", opcode)); 1441 1442 bp += sizeof(struct rx_header); 1443 1444 /* 1445 * If it was a data packet, interpret the response 1446 */ 1447 1448 if (rxh->type == RX_PACKET_TYPE_DATA) 1449 switch (opcode) { 1450 case 504: /* Name to ID */ 1451 { 1452 unsigned long j; 1453 printf(" ids:"); 1454 TCHECK2(bp[0], 4); 1455 i = EXTRACT_32BITS(bp); 1456 bp += sizeof(int32_t); 1457 for (j = 0; j < i; j++) 1458 INTOUT(); 1459 if (j == 0) 1460 printf(" <none!>"); 1461 } 1462 break; 1463 case 505: /* ID to name */ 1464 { 1465 unsigned long j; 1466 TCHECK2(bp[0], 4); 1467 j = EXTRACT_32BITS(bp); 1468 bp += sizeof(int32_t); 1469 1470 /* 1471 * Who designed this chicken-shit protocol? 1472 * 1473 * Each character is stored as a 32-bit 1474 * integer! 1475 */ 1476 1477 for (i = 0; i < j; i++) { 1478 VECOUT(PRNAMEMAX); 1479 } 1480 if (j == 0) 1481 printf(" <none!>"); 1482 } 1483 break; 1484 case 508: /* Get CPS */ 1485 case 514: /* List elements */ 1486 case 517: /* List owned */ 1487 case 518: /* Get CPS2 */ 1488 case 519: /* Get host CPS */ 1489 { 1490 unsigned long j; 1491 TCHECK2(bp[0], 4); 1492 j = EXTRACT_32BITS(bp); 1493 bp += sizeof(int32_t); 1494 for (i = 0; i < j; i++) { 1495 INTOUT(); 1496 } 1497 if (j == 0) 1498 printf(" <none!>"); 1499 } 1500 break; 1501 case 510: /* List max */ 1502 printf(" maxuid"); 1503 INTOUT(); 1504 printf(" maxgid"); 1505 INTOUT(); 1506 break; 1507 default: 1508 ; 1509 } 1510 else { 1511 /* 1512 * Otherwise, just print out the return code 1513 */ 1514 printf(" errcode"); 1515 INTOUT(); 1516 } 1517 1518 return; 1519 1520 trunc: 1521 printf(" [|pt]"); 1522 } 1523 1524 /* 1525 * Handle calls to the AFS volume location database service 1526 */ 1527 1528 static void 1529 vldb_print(register const u_char *bp, int length) 1530 { 1531 int vldb_op; 1532 unsigned long i; 1533 1534 if (length <= (int)sizeof(struct rx_header)) 1535 return; 1536 1537 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 1538 goto trunc; 1539 } 1540 1541 /* 1542 * Print out the afs call we're invoking. The table used here was 1543 * gleaned from vlserver/vldbint.xg 1544 */ 1545 1546 vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 1547 1548 printf(" vldb"); 1549 1550 if (is_ubik(vldb_op)) { 1551 ubik_print(bp); 1552 return; 1553 } 1554 printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op)); 1555 1556 /* 1557 * Decode some of the arguments to the VLDB calls 1558 */ 1559 1560 bp += sizeof(struct rx_header) + 4; 1561 1562 switch (vldb_op) { 1563 case 501: /* Create new volume */ 1564 case 517: /* Create entry N */ 1565 VECOUT(VLNAMEMAX); 1566 break; 1567 case 502: /* Delete entry */ 1568 case 503: /* Get entry by ID */ 1569 case 507: /* Update entry */ 1570 case 508: /* Set lock */ 1571 case 509: /* Release lock */ 1572 case 518: /* Get entry by ID N */ 1573 printf(" volid"); 1574 INTOUT(); 1575 TCHECK2(bp[0], sizeof(int32_t)); 1576 i = EXTRACT_32BITS(bp); 1577 bp += sizeof(int32_t); 1578 if (i <= 2) 1579 printf(" type %s", voltype[i]); 1580 break; 1581 case 504: /* Get entry by name */ 1582 case 519: /* Get entry by name N */ 1583 case 524: /* Update entry by name */ 1584 case 527: /* Get entry by name U */ 1585 STROUT(VLNAMEMAX); 1586 break; 1587 case 505: /* Get new vol id */ 1588 printf(" bump"); 1589 INTOUT(); 1590 break; 1591 case 506: /* Replace entry */ 1592 case 520: /* Replace entry N */ 1593 printf(" volid"); 1594 INTOUT(); 1595 TCHECK2(bp[0], sizeof(int32_t)); 1596 i = EXTRACT_32BITS(bp); 1597 bp += sizeof(int32_t); 1598 if (i <= 2) 1599 printf(" type %s", voltype[i]); 1600 VECOUT(VLNAMEMAX); 1601 break; 1602 case 510: /* List entry */ 1603 case 521: /* List entry N */ 1604 printf(" index"); 1605 INTOUT(); 1606 break; 1607 default: 1608 ; 1609 } 1610 1611 return; 1612 1613 trunc: 1614 printf(" [|vldb]"); 1615 } 1616 1617 /* 1618 * Handle replies to the AFS volume location database service 1619 */ 1620 1621 static void 1622 vldb_reply_print(register const u_char *bp, int length, int32_t opcode) 1623 { 1624 struct rx_header *rxh; 1625 unsigned long i; 1626 1627 if (length < (int)sizeof(struct rx_header)) 1628 return; 1629 1630 rxh = (struct rx_header *) bp; 1631 1632 /* 1633 * Print out the afs call we're invoking. The table used here was 1634 * gleaned from vlserver/vldbint.xg. Check to see if it's a 1635 * Ubik call, however. 1636 */ 1637 1638 printf(" vldb"); 1639 1640 if (is_ubik(opcode)) { 1641 ubik_reply_print(bp, length, opcode); 1642 return; 1643 } 1644 1645 printf(" reply %s", tok2str(vldb_req, "op#%d", opcode)); 1646 1647 bp += sizeof(struct rx_header); 1648 1649 /* 1650 * If it was a data packet, interpret the response 1651 */ 1652 1653 if (rxh->type == RX_PACKET_TYPE_DATA) 1654 switch (opcode) { 1655 case 510: /* List entry */ 1656 printf(" count"); 1657 INTOUT(); 1658 printf(" nextindex"); 1659 INTOUT(); 1660 case 503: /* Get entry by id */ 1661 case 504: /* Get entry by name */ 1662 { unsigned long nservers, j; 1663 VECOUT(VLNAMEMAX); 1664 TCHECK2(bp[0], sizeof(int32_t)); 1665 bp += sizeof(int32_t); 1666 printf(" numservers"); 1667 TCHECK2(bp[0], sizeof(int32_t)); 1668 nservers = EXTRACT_32BITS(bp); 1669 bp += sizeof(int32_t); 1670 printf(" %lu", nservers); 1671 printf(" servers"); 1672 for (i = 0; i < 8; i++) { 1673 TCHECK2(bp[0], sizeof(int32_t)); 1674 if (i < nservers) 1675 printf(" %s", 1676 intoa(((struct in_addr *) bp)->s_addr)); 1677 bp += sizeof(int32_t); 1678 } 1679 printf(" partitions"); 1680 for (i = 0; i < 8; i++) { 1681 TCHECK2(bp[0], sizeof(int32_t)); 1682 j = EXTRACT_32BITS(bp); 1683 if (i < nservers && j <= 26) 1684 printf(" %c", 'a' + (int)j); 1685 else if (i < nservers) 1686 printf(" %lu", j); 1687 bp += sizeof(int32_t); 1688 } 1689 TCHECK2(bp[0], 8 * sizeof(int32_t)); 1690 bp += 8 * sizeof(int32_t); 1691 printf(" rwvol"); 1692 UINTOUT(); 1693 printf(" rovol"); 1694 UINTOUT(); 1695 printf(" backup"); 1696 UINTOUT(); 1697 } 1698 break; 1699 case 505: /* Get new volume ID */ 1700 printf(" newvol"); 1701 UINTOUT(); 1702 break; 1703 case 521: /* List entry */ 1704 case 529: /* List entry U */ 1705 printf(" count"); 1706 INTOUT(); 1707 printf(" nextindex"); 1708 INTOUT(); 1709 case 518: /* Get entry by ID N */ 1710 case 519: /* Get entry by name N */ 1711 { unsigned long nservers, j; 1712 VECOUT(VLNAMEMAX); 1713 printf(" numservers"); 1714 TCHECK2(bp[0], sizeof(int32_t)); 1715 nservers = EXTRACT_32BITS(bp); 1716 bp += sizeof(int32_t); 1717 printf(" %lu", nservers); 1718 printf(" servers"); 1719 for (i = 0; i < 13; i++) { 1720 TCHECK2(bp[0], sizeof(int32_t)); 1721 if (i < nservers) 1722 printf(" %s", 1723 intoa(((struct in_addr *) bp)->s_addr)); 1724 bp += sizeof(int32_t); 1725 } 1726 printf(" partitions"); 1727 for (i = 0; i < 13; i++) { 1728 TCHECK2(bp[0], sizeof(int32_t)); 1729 j = EXTRACT_32BITS(bp); 1730 if (i < nservers && j <= 26) 1731 printf(" %c", 'a' + (int)j); 1732 else if (i < nservers) 1733 printf(" %lu", j); 1734 bp += sizeof(int32_t); 1735 } 1736 TCHECK2(bp[0], 13 * sizeof(int32_t)); 1737 bp += 13 * sizeof(int32_t); 1738 printf(" rwvol"); 1739 UINTOUT(); 1740 printf(" rovol"); 1741 UINTOUT(); 1742 printf(" backup"); 1743 UINTOUT(); 1744 } 1745 break; 1746 case 526: /* Get entry by ID U */ 1747 case 527: /* Get entry by name U */ 1748 { unsigned long nservers, j; 1749 VECOUT(VLNAMEMAX); 1750 printf(" numservers"); 1751 TCHECK2(bp[0], sizeof(int32_t)); 1752 nservers = EXTRACT_32BITS(bp); 1753 bp += sizeof(int32_t); 1754 printf(" %lu", nservers); 1755 printf(" servers"); 1756 for (i = 0; i < 13; i++) { 1757 if (i < nservers) { 1758 printf(" afsuuid"); 1759 AFSUUIDOUT(); 1760 } else { 1761 TCHECK2(bp[0], 44); 1762 bp += 44; 1763 } 1764 } 1765 TCHECK2(bp[0], 4 * 13); 1766 bp += 4 * 13; 1767 printf(" partitions"); 1768 for (i = 0; i < 13; i++) { 1769 TCHECK2(bp[0], sizeof(int32_t)); 1770 j = EXTRACT_32BITS(bp); 1771 if (i < nservers && j <= 26) 1772 printf(" %c", 'a' + (int)j); 1773 else if (i < nservers) 1774 printf(" %lu", j); 1775 bp += sizeof(int32_t); 1776 } 1777 TCHECK2(bp[0], 13 * sizeof(int32_t)); 1778 bp += 13 * sizeof(int32_t); 1779 printf(" rwvol"); 1780 UINTOUT(); 1781 printf(" rovol"); 1782 UINTOUT(); 1783 printf(" backup"); 1784 UINTOUT(); 1785 } 1786 default: 1787 ; 1788 } 1789 1790 else { 1791 /* 1792 * Otherwise, just print out the return code 1793 */ 1794 printf(" errcode"); 1795 INTOUT(); 1796 } 1797 1798 return; 1799 1800 trunc: 1801 printf(" [|vldb]"); 1802 } 1803 1804 /* 1805 * Handle calls to the AFS Kerberos Authentication service 1806 */ 1807 1808 static void 1809 kauth_print(register const u_char *bp, int length) 1810 { 1811 int kauth_op; 1812 1813 if (length <= (int)sizeof(struct rx_header)) 1814 return; 1815 1816 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 1817 goto trunc; 1818 } 1819 1820 /* 1821 * Print out the afs call we're invoking. The table used here was 1822 * gleaned from kauth/kauth.rg 1823 */ 1824 1825 kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 1826 1827 printf(" kauth"); 1828 1829 if (is_ubik(kauth_op)) { 1830 ubik_print(bp); 1831 return; 1832 } 1833 1834 1835 printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op)); 1836 1837 /* 1838 * Decode some of the arguments to the KA calls 1839 */ 1840 1841 bp += sizeof(struct rx_header) + 4; 1842 1843 switch (kauth_op) { 1844 case 1: /* Authenticate old */; 1845 case 21: /* Authenticate */ 1846 case 22: /* Authenticate-V2 */ 1847 case 2: /* Change PW */ 1848 case 5: /* Set fields */ 1849 case 6: /* Create user */ 1850 case 7: /* Delete user */ 1851 case 8: /* Get entry */ 1852 case 14: /* Unlock */ 1853 case 15: /* Lock status */ 1854 printf(" principal"); 1855 STROUT(KANAMEMAX); 1856 STROUT(KANAMEMAX); 1857 break; 1858 case 3: /* GetTicket-old */ 1859 case 23: /* GetTicket */ 1860 { 1861 int i; 1862 printf(" kvno"); 1863 INTOUT(); 1864 printf(" domain"); 1865 STROUT(KANAMEMAX); 1866 TCHECK2(bp[0], sizeof(int32_t)); 1867 i = (int) EXTRACT_32BITS(bp); 1868 bp += sizeof(int32_t); 1869 TCHECK2(bp[0], i); 1870 bp += i; 1871 printf(" principal"); 1872 STROUT(KANAMEMAX); 1873 STROUT(KANAMEMAX); 1874 break; 1875 } 1876 case 4: /* Set Password */ 1877 printf(" principal"); 1878 STROUT(KANAMEMAX); 1879 STROUT(KANAMEMAX); 1880 printf(" kvno"); 1881 INTOUT(); 1882 break; 1883 case 12: /* Get password */ 1884 printf(" name"); 1885 STROUT(KANAMEMAX); 1886 break; 1887 default: 1888 ; 1889 } 1890 1891 return; 1892 1893 trunc: 1894 printf(" [|kauth]"); 1895 } 1896 1897 /* 1898 * Handle replies to the AFS Kerberos Authentication Service 1899 */ 1900 1901 static void 1902 kauth_reply_print(register const u_char *bp, int length, int32_t opcode) 1903 { 1904 struct rx_header *rxh; 1905 1906 if (length <= (int)sizeof(struct rx_header)) 1907 return; 1908 1909 rxh = (struct rx_header *) bp; 1910 1911 /* 1912 * Print out the afs call we're invoking. The table used here was 1913 * gleaned from kauth/kauth.rg 1914 */ 1915 1916 printf(" kauth"); 1917 1918 if (is_ubik(opcode)) { 1919 ubik_reply_print(bp, length, opcode); 1920 return; 1921 } 1922 1923 printf(" reply %s", tok2str(kauth_req, "op#%d", opcode)); 1924 1925 bp += sizeof(struct rx_header); 1926 1927 /* 1928 * If it was a data packet, interpret the response. 1929 */ 1930 1931 if (rxh->type == RX_PACKET_TYPE_DATA) 1932 /* Well, no, not really. Leave this for later */ 1933 ; 1934 else { 1935 /* 1936 * Otherwise, just print out the return code 1937 */ 1938 printf(" errcode"); 1939 INTOUT(); 1940 } 1941 1942 return; 1943 1944 trunc: 1945 printf(" [|kauth]"); 1946 } 1947 1948 /* 1949 * Handle calls to the AFS Volume location service 1950 */ 1951 1952 static void 1953 vol_print(register const u_char *bp, int length) 1954 { 1955 int vol_op; 1956 1957 if (length <= (int)sizeof(struct rx_header)) 1958 return; 1959 1960 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 1961 goto trunc; 1962 } 1963 1964 /* 1965 * Print out the afs call we're invoking. The table used here was 1966 * gleaned from volser/volint.xg 1967 */ 1968 1969 vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 1970 1971 printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op)); 1972 1973 bp += sizeof(struct rx_header) + 4; 1974 1975 switch (vol_op) { 1976 case 100: /* Create volume */ 1977 printf(" partition"); 1978 UINTOUT(); 1979 printf(" name"); 1980 STROUT(AFSNAMEMAX); 1981 printf(" type"); 1982 UINTOUT(); 1983 printf(" parent"); 1984 UINTOUT(); 1985 break; 1986 case 101: /* Delete volume */ 1987 case 107: /* Get flags */ 1988 printf(" trans"); 1989 UINTOUT(); 1990 break; 1991 case 102: /* Restore */ 1992 printf(" totrans"); 1993 UINTOUT(); 1994 printf(" flags"); 1995 UINTOUT(); 1996 break; 1997 case 103: /* Forward */ 1998 printf(" fromtrans"); 1999 UINTOUT(); 2000 printf(" fromdate"); 2001 DATEOUT(); 2002 DESTSERVEROUT(); 2003 printf(" desttrans"); 2004 INTOUT(); 2005 break; 2006 case 104: /* End trans */ 2007 printf(" trans"); 2008 UINTOUT(); 2009 break; 2010 case 105: /* Clone */ 2011 printf(" trans"); 2012 UINTOUT(); 2013 printf(" purgevol"); 2014 UINTOUT(); 2015 printf(" newtype"); 2016 UINTOUT(); 2017 printf(" newname"); 2018 STROUT(AFSNAMEMAX); 2019 break; 2020 case 106: /* Set flags */ 2021 printf(" trans"); 2022 UINTOUT(); 2023 printf(" flags"); 2024 UINTOUT(); 2025 break; 2026 case 108: /* Trans create */ 2027 printf(" vol"); 2028 UINTOUT(); 2029 printf(" partition"); 2030 UINTOUT(); 2031 printf(" flags"); 2032 UINTOUT(); 2033 break; 2034 case 109: /* Dump */ 2035 case 655537: /* Get size */ 2036 printf(" fromtrans"); 2037 UINTOUT(); 2038 printf(" fromdate"); 2039 DATEOUT(); 2040 break; 2041 case 110: /* Get n-th volume */ 2042 printf(" index"); 2043 UINTOUT(); 2044 break; 2045 case 111: /* Set forwarding */ 2046 printf(" tid"); 2047 UINTOUT(); 2048 printf(" newsite"); 2049 UINTOUT(); 2050 break; 2051 case 112: /* Get name */ 2052 case 113: /* Get status */ 2053 printf(" tid"); 2054 break; 2055 case 114: /* Signal restore */ 2056 printf(" name"); 2057 STROUT(AFSNAMEMAX); 2058 printf(" type"); 2059 UINTOUT(); 2060 printf(" pid"); 2061 UINTOUT(); 2062 printf(" cloneid"); 2063 UINTOUT(); 2064 break; 2065 case 116: /* List volumes */ 2066 printf(" partition"); 2067 UINTOUT(); 2068 printf(" flags"); 2069 UINTOUT(); 2070 break; 2071 case 117: /* Set id types */ 2072 printf(" tid"); 2073 UINTOUT(); 2074 printf(" name"); 2075 STROUT(AFSNAMEMAX); 2076 printf(" type"); 2077 UINTOUT(); 2078 printf(" pid"); 2079 UINTOUT(); 2080 printf(" clone"); 2081 UINTOUT(); 2082 printf(" backup"); 2083 UINTOUT(); 2084 break; 2085 case 119: /* Partition info */ 2086 printf(" name"); 2087 STROUT(AFSNAMEMAX); 2088 break; 2089 case 120: /* Reclone */ 2090 printf(" tid"); 2091 UINTOUT(); 2092 break; 2093 case 121: /* List one volume */ 2094 case 122: /* Nuke volume */ 2095 case 124: /* Extended List volumes */ 2096 case 125: /* Extended List one volume */ 2097 case 65536: /* Convert RO to RW volume */ 2098 printf(" partid"); 2099 UINTOUT(); 2100 printf(" volid"); 2101 UINTOUT(); 2102 break; 2103 case 123: /* Set date */ 2104 printf(" tid"); 2105 UINTOUT(); 2106 printf(" date"); 2107 DATEOUT(); 2108 break; 2109 case 126: /* Set info */ 2110 printf(" tid"); 2111 UINTOUT(); 2112 break; 2113 case 128: /* Forward multiple */ 2114 printf(" fromtrans"); 2115 UINTOUT(); 2116 printf(" fromdate"); 2117 DATEOUT(); 2118 { 2119 unsigned long i, j; 2120 TCHECK2(bp[0], 4); 2121 j = EXTRACT_32BITS(bp); 2122 bp += sizeof(int32_t); 2123 for (i = 0; i < j; i++) { 2124 DESTSERVEROUT(); 2125 if (i != j - 1) 2126 printf(","); 2127 } 2128 if (j == 0) 2129 printf(" <none!>"); 2130 } 2131 break; 2132 case 65538: /* Dump version 2 */ 2133 printf(" fromtrans"); 2134 UINTOUT(); 2135 printf(" fromdate"); 2136 DATEOUT(); 2137 printf(" flags"); 2138 UINTOUT(); 2139 break; 2140 default: 2141 ; 2142 } 2143 return; 2144 2145 trunc: 2146 printf(" [|vol]"); 2147 } 2148 2149 /* 2150 * Handle replies to the AFS Volume Service 2151 */ 2152 2153 static void 2154 vol_reply_print(register const u_char *bp, int length, int32_t opcode) 2155 { 2156 struct rx_header *rxh; 2157 2158 if (length <= (int)sizeof(struct rx_header)) 2159 return; 2160 2161 rxh = (struct rx_header *) bp; 2162 2163 /* 2164 * Print out the afs call we're invoking. The table used here was 2165 * gleaned from volser/volint.xg 2166 */ 2167 2168 printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode)); 2169 2170 bp += sizeof(struct rx_header); 2171 2172 /* 2173 * If it was a data packet, interpret the response. 2174 */ 2175 2176 if (rxh->type == RX_PACKET_TYPE_DATA) { 2177 switch (opcode) { 2178 case 100: /* Create volume */ 2179 printf(" volid"); 2180 UINTOUT(); 2181 printf(" trans"); 2182 UINTOUT(); 2183 break; 2184 case 104: /* End transaction */ 2185 UINTOUT(); 2186 break; 2187 case 105: /* Clone */ 2188 printf(" newvol"); 2189 UINTOUT(); 2190 break; 2191 case 107: /* Get flags */ 2192 UINTOUT(); 2193 break; 2194 case 108: /* Transaction create */ 2195 printf(" trans"); 2196 UINTOUT(); 2197 break; 2198 case 110: /* Get n-th volume */ 2199 printf(" volume"); 2200 UINTOUT(); 2201 printf(" partition"); 2202 UINTOUT(); 2203 break; 2204 case 112: /* Get name */ 2205 STROUT(AFSNAMEMAX); 2206 break; 2207 case 113: /* Get status */ 2208 printf(" volid"); 2209 UINTOUT(); 2210 printf(" nextuniq"); 2211 UINTOUT(); 2212 printf(" type"); 2213 UINTOUT(); 2214 printf(" parentid"); 2215 UINTOUT(); 2216 printf(" clone"); 2217 UINTOUT(); 2218 printf(" backup"); 2219 UINTOUT(); 2220 printf(" restore"); 2221 UINTOUT(); 2222 printf(" maxquota"); 2223 UINTOUT(); 2224 printf(" minquota"); 2225 UINTOUT(); 2226 printf(" owner"); 2227 UINTOUT(); 2228 printf(" create"); 2229 DATEOUT(); 2230 printf(" access"); 2231 DATEOUT(); 2232 printf(" update"); 2233 DATEOUT(); 2234 printf(" expire"); 2235 DATEOUT(); 2236 printf(" backup"); 2237 DATEOUT(); 2238 printf(" copy"); 2239 DATEOUT(); 2240 break; 2241 case 115: /* Old list partitions */ 2242 break; 2243 case 116: /* List volumes */ 2244 case 121: /* List one volume */ 2245 { 2246 unsigned long i, j; 2247 TCHECK2(bp[0], 4); 2248 j = EXTRACT_32BITS(bp); 2249 bp += sizeof(int32_t); 2250 for (i = 0; i < j; i++) { 2251 printf(" name"); 2252 VECOUT(32); 2253 printf(" volid"); 2254 UINTOUT(); 2255 printf(" type"); 2256 bp += sizeof(int32_t) * 21; 2257 if (i != j - 1) 2258 printf(","); 2259 } 2260 if (j == 0) 2261 printf(" <none!>"); 2262 } 2263 break; 2264 2265 2266 default: 2267 ; 2268 } 2269 } else { 2270 /* 2271 * Otherwise, just print out the return code 2272 */ 2273 printf(" errcode"); 2274 INTOUT(); 2275 } 2276 2277 return; 2278 2279 trunc: 2280 printf(" [|vol]"); 2281 } 2282 2283 /* 2284 * Handle calls to the AFS BOS service 2285 */ 2286 2287 static void 2288 bos_print(register const u_char *bp, int length) 2289 { 2290 int bos_op; 2291 2292 if (length <= (int)sizeof(struct rx_header)) 2293 return; 2294 2295 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 2296 goto trunc; 2297 } 2298 2299 /* 2300 * Print out the afs call we're invoking. The table used here was 2301 * gleaned from bozo/bosint.xg 2302 */ 2303 2304 bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 2305 2306 printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op)); 2307 2308 /* 2309 * Decode some of the arguments to the BOS calls 2310 */ 2311 2312 bp += sizeof(struct rx_header) + 4; 2313 2314 switch (bos_op) { 2315 case 80: /* Create B node */ 2316 printf(" type"); 2317 STROUT(BOSNAMEMAX); 2318 printf(" instance"); 2319 STROUT(BOSNAMEMAX); 2320 break; 2321 case 81: /* Delete B node */ 2322 case 83: /* Get status */ 2323 case 85: /* Get instance info */ 2324 case 87: /* Add super user */ 2325 case 88: /* Delete super user */ 2326 case 93: /* Set cell name */ 2327 case 96: /* Add cell host */ 2328 case 97: /* Delete cell host */ 2329 case 104: /* Restart */ 2330 case 106: /* Uninstall */ 2331 case 108: /* Exec */ 2332 case 112: /* Getlog */ 2333 case 114: /* Get instance strings */ 2334 STROUT(BOSNAMEMAX); 2335 break; 2336 case 82: /* Set status */ 2337 case 98: /* Set T status */ 2338 STROUT(BOSNAMEMAX); 2339 printf(" status"); 2340 INTOUT(); 2341 break; 2342 case 86: /* Get instance parm */ 2343 STROUT(BOSNAMEMAX); 2344 printf(" num"); 2345 INTOUT(); 2346 break; 2347 case 84: /* Enumerate instance */ 2348 case 89: /* List super users */ 2349 case 90: /* List keys */ 2350 case 91: /* Add key */ 2351 case 92: /* Delete key */ 2352 case 95: /* Get cell host */ 2353 INTOUT(); 2354 break; 2355 case 105: /* Install */ 2356 STROUT(BOSNAMEMAX); 2357 printf(" size"); 2358 INTOUT(); 2359 printf(" flags"); 2360 INTOUT(); 2361 printf(" date"); 2362 INTOUT(); 2363 break; 2364 default: 2365 ; 2366 } 2367 2368 return; 2369 2370 trunc: 2371 printf(" [|bos]"); 2372 } 2373 2374 /* 2375 * Handle replies to the AFS BOS Service 2376 */ 2377 2378 static void 2379 bos_reply_print(register const u_char *bp, int length, int32_t opcode) 2380 { 2381 struct rx_header *rxh; 2382 2383 if (length <= (int)sizeof(struct rx_header)) 2384 return; 2385 2386 rxh = (struct rx_header *) bp; 2387 2388 /* 2389 * Print out the afs call we're invoking. The table used here was 2390 * gleaned from volser/volint.xg 2391 */ 2392 2393 printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode)); 2394 2395 bp += sizeof(struct rx_header); 2396 2397 /* 2398 * If it was a data packet, interpret the response. 2399 */ 2400 2401 if (rxh->type == RX_PACKET_TYPE_DATA) 2402 /* Well, no, not really. Leave this for later */ 2403 ; 2404 else { 2405 /* 2406 * Otherwise, just print out the return code 2407 */ 2408 printf(" errcode"); 2409 INTOUT(); 2410 } 2411 2412 return; 2413 2414 trunc: 2415 printf(" [|bos]"); 2416 } 2417 2418 /* 2419 * Check to see if this is a Ubik opcode. 2420 */ 2421 2422 static int 2423 is_ubik(u_int32_t opcode) 2424 { 2425 if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) || 2426 (opcode >= DISK_LOW && opcode <= DISK_HIGH)) 2427 return(1); 2428 else 2429 return(0); 2430 } 2431 2432 /* 2433 * Handle Ubik opcodes to any one of the replicated database services 2434 */ 2435 2436 static void 2437 ubik_print(register const u_char *bp) 2438 { 2439 int ubik_op; 2440 int32_t temp; 2441 2442 /* 2443 * Print out the afs call we're invoking. The table used here was 2444 * gleaned from ubik/ubik_int.xg 2445 */ 2446 2447 ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 2448 2449 printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op)); 2450 2451 /* 2452 * Decode some of the arguments to the Ubik calls 2453 */ 2454 2455 bp += sizeof(struct rx_header) + 4; 2456 2457 switch (ubik_op) { 2458 case 10000: /* Beacon */ 2459 TCHECK2(bp[0], 4); 2460 temp = EXTRACT_32BITS(bp); 2461 bp += sizeof(int32_t); 2462 printf(" syncsite %s", temp ? "yes" : "no"); 2463 printf(" votestart"); 2464 DATEOUT(); 2465 printf(" dbversion"); 2466 UBIK_VERSIONOUT(); 2467 printf(" tid"); 2468 UBIK_VERSIONOUT(); 2469 break; 2470 case 10003: /* Get sync site */ 2471 printf(" site"); 2472 UINTOUT(); 2473 break; 2474 case 20000: /* Begin */ 2475 case 20001: /* Commit */ 2476 case 20007: /* Abort */ 2477 case 20008: /* Release locks */ 2478 case 20010: /* Writev */ 2479 printf(" tid"); 2480 UBIK_VERSIONOUT(); 2481 break; 2482 case 20002: /* Lock */ 2483 printf(" tid"); 2484 UBIK_VERSIONOUT(); 2485 printf(" file"); 2486 INTOUT(); 2487 printf(" pos"); 2488 INTOUT(); 2489 printf(" length"); 2490 INTOUT(); 2491 temp = EXTRACT_32BITS(bp); 2492 bp += sizeof(int32_t); 2493 tok2str(ubik_lock_types, "type %d", temp); 2494 break; 2495 case 20003: /* Write */ 2496 printf(" tid"); 2497 UBIK_VERSIONOUT(); 2498 printf(" file"); 2499 INTOUT(); 2500 printf(" pos"); 2501 INTOUT(); 2502 break; 2503 case 20005: /* Get file */ 2504 printf(" file"); 2505 INTOUT(); 2506 break; 2507 case 20006: /* Send file */ 2508 printf(" file"); 2509 INTOUT(); 2510 printf(" length"); 2511 INTOUT(); 2512 printf(" dbversion"); 2513 UBIK_VERSIONOUT(); 2514 break; 2515 case 20009: /* Truncate */ 2516 printf(" tid"); 2517 UBIK_VERSIONOUT(); 2518 printf(" file"); 2519 INTOUT(); 2520 printf(" length"); 2521 INTOUT(); 2522 break; 2523 case 20012: /* Set version */ 2524 printf(" tid"); 2525 UBIK_VERSIONOUT(); 2526 printf(" oldversion"); 2527 UBIK_VERSIONOUT(); 2528 printf(" newversion"); 2529 UBIK_VERSIONOUT(); 2530 break; 2531 default: 2532 ; 2533 } 2534 2535 return; 2536 2537 trunc: 2538 printf(" [|ubik]"); 2539 } 2540 2541 /* 2542 * Handle Ubik replies to any one of the replicated database services 2543 */ 2544 2545 static void 2546 ubik_reply_print(register const u_char *bp, int length, int32_t opcode) 2547 { 2548 struct rx_header *rxh; 2549 2550 if (length < (int)sizeof(struct rx_header)) 2551 return; 2552 2553 rxh = (struct rx_header *) bp; 2554 2555 /* 2556 * Print out the ubik call we're invoking. This table was gleaned 2557 * from ubik/ubik_int.xg 2558 */ 2559 2560 printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode)); 2561 2562 bp += sizeof(struct rx_header); 2563 2564 /* 2565 * If it was a data packet, print out the arguments to the Ubik calls 2566 */ 2567 2568 if (rxh->type == RX_PACKET_TYPE_DATA) 2569 switch (opcode) { 2570 case 10000: /* Beacon */ 2571 printf(" vote no"); 2572 break; 2573 case 20004: /* Get version */ 2574 printf(" dbversion"); 2575 UBIK_VERSIONOUT(); 2576 break; 2577 default: 2578 ; 2579 } 2580 2581 /* 2582 * Otherwise, print out "yes" it it was a beacon packet (because 2583 * that's how yes votes are returned, go figure), otherwise 2584 * just print out the error code. 2585 */ 2586 2587 else 2588 switch (opcode) { 2589 case 10000: /* Beacon */ 2590 printf(" vote yes until"); 2591 DATEOUT(); 2592 break; 2593 default: 2594 printf(" errcode"); 2595 INTOUT(); 2596 } 2597 2598 return; 2599 2600 trunc: 2601 printf(" [|ubik]"); 2602 } 2603 2604 /* 2605 * Handle RX ACK packets. 2606 */ 2607 2608 static void 2609 rx_ack_print(register const u_char *bp, int length) 2610 { 2611 struct rx_ackPacket *rxa; 2612 int i, start, last; 2613 u_int32_t firstPacket; 2614 2615 if (length < (int)sizeof(struct rx_header)) 2616 return; 2617 2618 bp += sizeof(struct rx_header); 2619 2620 /* 2621 * This may seem a little odd .... the rx_ackPacket structure 2622 * contains an array of individual packet acknowledgements 2623 * (used for selective ack/nack), but since it's variable in size, 2624 * we don't want to truncate based on the size of the whole 2625 * rx_ackPacket structure. 2626 */ 2627 2628 TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS); 2629 2630 rxa = (struct rx_ackPacket *) bp; 2631 bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS); 2632 2633 /* 2634 * Print out a few useful things from the ack packet structure 2635 */ 2636 2637 if (vflag > 2) 2638 printf(" bufspace %d maxskew %d", 2639 (int) EXTRACT_16BITS(&rxa->bufferSpace), 2640 (int) EXTRACT_16BITS(&rxa->maxSkew)); 2641 2642 firstPacket = EXTRACT_32BITS(&rxa->firstPacket); 2643 printf(" first %d serial %d reason %s", 2644 firstPacket, EXTRACT_32BITS(&rxa->serial), 2645 tok2str(rx_ack_reasons, "#%d", (int) rxa->reason)); 2646 2647 /* 2648 * Okay, now we print out the ack array. The way _this_ works 2649 * is that we start at "first", and step through the ack array. 2650 * If we have a contiguous range of acks/nacks, try to 2651 * collapse them into a range. 2652 * 2653 * If you're really clever, you might have noticed that this 2654 * doesn't seem quite correct. Specifically, due to structure 2655 * padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually 2656 * yield the start of the ack array (because RX_MAXACKS is 255 2657 * and the structure will likely get padded to a 2 or 4 byte 2658 * boundary). However, this is the way it's implemented inside 2659 * of AFS - the start of the extra fields are at 2660 * sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_ 2661 * the exact start of the ack array. Sigh. That's why we aren't 2662 * using bp, but instead use rxa->acks[]. But nAcks gets added 2663 * to bp after this, so bp ends up at the right spot. Go figure. 2664 */ 2665 2666 if (rxa->nAcks != 0) { 2667 2668 TCHECK2(bp[0], rxa->nAcks); 2669 2670 /* 2671 * Sigh, this is gross, but it seems to work to collapse 2672 * ranges correctly. 2673 */ 2674 2675 for (i = 0, start = last = -2; i < rxa->nAcks; i++) 2676 if (rxa->acks[i] == RX_ACK_TYPE_ACK) { 2677 2678 /* 2679 * I figured this deserved _some_ explanation. 2680 * First, print "acked" and the packet seq 2681 * number if this is the first time we've 2682 * seen an acked packet. 2683 */ 2684 2685 if (last == -2) { 2686 printf(" acked %d", 2687 firstPacket + i); 2688 start = i; 2689 } 2690 2691 /* 2692 * Otherwise, if the there is a skip in 2693 * the range (such as an nacked packet in 2694 * the middle of some acked packets), 2695 * then print the current packet number 2696 * seperated from the last number by 2697 * a comma. 2698 */ 2699 2700 else if (last != i - 1) { 2701 printf(",%d", firstPacket + i); 2702 start = i; 2703 } 2704 2705 /* 2706 * We always set last to the value of 2707 * the last ack we saw. Conversely, start 2708 * is set to the value of the first ack 2709 * we saw in a range. 2710 */ 2711 2712 last = i; 2713 2714 /* 2715 * Okay, this bit a code gets executed when 2716 * we hit a nack ... in _this_ case we 2717 * want to print out the range of packets 2718 * that were acked, so we need to print 2719 * the _previous_ packet number seperated 2720 * from the first by a dash (-). Since we 2721 * already printed the first packet above, 2722 * just print the final packet. Don't 2723 * do this if there will be a single-length 2724 * range. 2725 */ 2726 } else if (last == i - 1 && start != last) 2727 printf("-%d", firstPacket + i - 1); 2728 2729 /* 2730 * So, what's going on here? We ran off the end of the 2731 * ack list, and if we got a range we need to finish it up. 2732 * So we need to determine if the last packet in the list 2733 * was an ack (if so, then last will be set to it) and 2734 * we need to see if the last range didn't start with the 2735 * last packet (because if it _did_, then that would mean 2736 * that the packet number has already been printed and 2737 * we don't need to print it again). 2738 */ 2739 2740 if (last == i - 1 && start != last) 2741 printf("-%d", firstPacket + i - 1); 2742 2743 /* 2744 * Same as above, just without comments 2745 */ 2746 2747 for (i = 0, start = last = -2; i < rxa->nAcks; i++) 2748 if (rxa->acks[i] == RX_ACK_TYPE_NACK) { 2749 if (last == -2) { 2750 printf(" nacked %d", 2751 firstPacket + i); 2752 start = i; 2753 } else if (last != i - 1) { 2754 printf(",%d", firstPacket + i); 2755 start = i; 2756 } 2757 last = i; 2758 } else if (last == i - 1 && start != last) 2759 printf("-%d", firstPacket + i - 1); 2760 2761 if (last == i - 1 && start != last) 2762 printf("-%d", firstPacket + i - 1); 2763 2764 bp += rxa->nAcks; 2765 } 2766 2767 2768 /* 2769 * These are optional fields; depending on your version of AFS, 2770 * you may or may not see them 2771 */ 2772 2773 #define TRUNCRET(n) if (snapend - bp + 1 <= n) return; 2774 2775 if (vflag > 1) { 2776 TRUNCRET(4); 2777 printf(" ifmtu"); 2778 INTOUT(); 2779 2780 TRUNCRET(4); 2781 printf(" maxmtu"); 2782 INTOUT(); 2783 2784 TRUNCRET(4); 2785 printf(" rwind"); 2786 INTOUT(); 2787 2788 TRUNCRET(4); 2789 printf(" maxpackets"); 2790 INTOUT(); 2791 } 2792 2793 return; 2794 2795 trunc: 2796 printf(" [|ack]"); 2797 } 2798 #undef TRUNCRET 2799