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