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