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