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