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