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