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.6 2017/01/24 23:29:14 christos Exp $"); 38 #endif 39 40 #ifdef HAVE_CONFIG_H 41 #include "config.h" 42 #endif 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <netdissect-stdinc.h> 48 49 #include "netdissect.h" 50 #include "addrtoname.h" 51 #include "extract.h" 52 53 #include "ip.h" 54 55 #define FS_RX_PORT 7000 56 #define CB_RX_PORT 7001 57 #define PROT_RX_PORT 7002 58 #define VLDB_RX_PORT 7003 59 #define KAUTH_RX_PORT 7004 60 #define VOL_RX_PORT 7005 61 #define ERROR_RX_PORT 7006 /* Doesn't seem to be used */ 62 #define BOS_RX_PORT 7007 63 64 #define AFSNAMEMAX 256 65 #define AFSOPAQUEMAX 1024 66 #define PRNAMEMAX 64 67 #define VLNAMEMAX 65 68 #define KANAMEMAX 64 69 #define BOSNAMEMAX 256 70 71 #define PRSFS_READ 1 /* Read files */ 72 #define PRSFS_WRITE 2 /* Write files */ 73 #define PRSFS_INSERT 4 /* Insert files into a directory */ 74 #define PRSFS_LOOKUP 8 /* Lookup files into a directory */ 75 #define PRSFS_DELETE 16 /* Delete files */ 76 #define PRSFS_LOCK 32 /* Lock files */ 77 #define PRSFS_ADMINISTER 64 /* Change ACL's */ 78 79 struct rx_header { 80 uint32_t epoch; 81 uint32_t cid; 82 uint32_t callNumber; 83 uint32_t seq; 84 uint32_t serial; 85 uint8_t type; 86 #define RX_PACKET_TYPE_DATA 1 87 #define RX_PACKET_TYPE_ACK 2 88 #define RX_PACKET_TYPE_BUSY 3 89 #define RX_PACKET_TYPE_ABORT 4 90 #define RX_PACKET_TYPE_ACKALL 5 91 #define RX_PACKET_TYPE_CHALLENGE 6 92 #define RX_PACKET_TYPE_RESPONSE 7 93 #define RX_PACKET_TYPE_DEBUG 8 94 #define RX_PACKET_TYPE_PARAMS 9 95 #define RX_PACKET_TYPE_VERSION 13 96 uint8_t flags; 97 #define RX_CLIENT_INITIATED 1 98 #define RX_REQUEST_ACK 2 99 #define RX_LAST_PACKET 4 100 #define RX_MORE_PACKETS 8 101 #define RX_FREE_PACKET 16 102 #define RX_SLOW_START_OK 32 103 #define RX_JUMBO_PACKET 32 104 uint8_t userStatus; 105 uint8_t securityIndex; 106 uint16_t spare; /* How clever: even though the AFS */ 107 uint16_t serviceId; /* header files indicate that the */ 108 }; /* serviceId is first, it's really */ 109 /* encoded _after_ the spare field */ 110 /* I wasted a day figuring that out! */ 111 112 #define NUM_RX_FLAGS 7 113 114 #define RX_MAXACKS 255 115 116 struct rx_ackPacket { 117 uint16_t bufferSpace; /* Number of packet buffers available */ 118 uint16_t maxSkew; /* Max diff between ack'd packet and */ 119 /* highest packet received */ 120 uint32_t firstPacket; /* The first packet in ack list */ 121 uint32_t previousPacket; /* Previous packet recv'd (obsolete) */ 122 uint32_t serial; /* # of packet that prompted the ack */ 123 uint8_t reason; /* Reason for acknowledgement */ 124 uint8_t nAcks; /* Number of acknowledgements */ 125 uint8_t acks[RX_MAXACKS]; /* Up to RX_MAXACKS acknowledgements */ 126 }; 127 128 /* 129 * Values for the acks array 130 */ 131 132 #define RX_ACK_TYPE_NACK 0 /* Don't have this packet */ 133 #define RX_ACK_TYPE_ACK 1 /* I have this packet */ 134 135 static const struct tok rx_types[] = { 136 { RX_PACKET_TYPE_DATA, "data" }, 137 { RX_PACKET_TYPE_ACK, "ack" }, 138 { RX_PACKET_TYPE_BUSY, "busy" }, 139 { RX_PACKET_TYPE_ABORT, "abort" }, 140 { RX_PACKET_TYPE_ACKALL, "ackall" }, 141 { RX_PACKET_TYPE_CHALLENGE, "challenge" }, 142 { RX_PACKET_TYPE_RESPONSE, "response" }, 143 { RX_PACKET_TYPE_DEBUG, "debug" }, 144 { RX_PACKET_TYPE_PARAMS, "params" }, 145 { RX_PACKET_TYPE_VERSION, "version" }, 146 { 0, NULL }, 147 }; 148 149 static const struct double_tok { 150 int flag; /* Rx flag */ 151 int packetType; /* Packet type */ 152 const char *s; /* Flag string */ 153 } rx_flags[] = { 154 { RX_CLIENT_INITIATED, 0, "client-init" }, 155 { RX_REQUEST_ACK, 0, "req-ack" }, 156 { RX_LAST_PACKET, 0, "last-pckt" }, 157 { RX_MORE_PACKETS, 0, "more-pckts" }, 158 { RX_FREE_PACKET, 0, "free-pckt" }, 159 { RX_SLOW_START_OK, RX_PACKET_TYPE_ACK, "slow-start" }, 160 { RX_JUMBO_PACKET, RX_PACKET_TYPE_DATA, "jumbogram" } 161 }; 162 163 static const struct tok fs_req[] = { 164 { 130, "fetch-data" }, 165 { 131, "fetch-acl" }, 166 { 132, "fetch-status" }, 167 { 133, "store-data" }, 168 { 134, "store-acl" }, 169 { 135, "store-status" }, 170 { 136, "remove-file" }, 171 { 137, "create-file" }, 172 { 138, "rename" }, 173 { 139, "symlink" }, 174 { 140, "link" }, 175 { 141, "makedir" }, 176 { 142, "rmdir" }, 177 { 143, "oldsetlock" }, 178 { 144, "oldextlock" }, 179 { 145, "oldrellock" }, 180 { 146, "get-stats" }, 181 { 147, "give-cbs" }, 182 { 148, "get-vlinfo" }, 183 { 149, "get-vlstats" }, 184 { 150, "set-vlstats" }, 185 { 151, "get-rootvl" }, 186 { 152, "check-token" }, 187 { 153, "get-time" }, 188 { 154, "nget-vlinfo" }, 189 { 155, "bulk-stat" }, 190 { 156, "setlock" }, 191 { 157, "extlock" }, 192 { 158, "rellock" }, 193 { 159, "xstat-ver" }, 194 { 160, "get-xstat" }, 195 { 161, "dfs-lookup" }, 196 { 162, "dfs-flushcps" }, 197 { 163, "dfs-symlink" }, 198 { 220, "residency" }, 199 { 65536, "inline-bulk-status" }, 200 { 65537, "fetch-data-64" }, 201 { 65538, "store-data-64" }, 202 { 65539, "give-up-all-cbs" }, 203 { 65540, "get-caps" }, 204 { 65541, "cb-rx-conn-addr" }, 205 { 0, NULL }, 206 }; 207 208 static const struct tok cb_req[] = { 209 { 204, "callback" }, 210 { 205, "initcb" }, 211 { 206, "probe" }, 212 { 207, "getlock" }, 213 { 208, "getce" }, 214 { 209, "xstatver" }, 215 { 210, "getxstat" }, 216 { 211, "initcb2" }, 217 { 212, "whoareyou" }, 218 { 213, "initcb3" }, 219 { 214, "probeuuid" }, 220 { 215, "getsrvprefs" }, 221 { 216, "getcellservdb" }, 222 { 217, "getlocalcell" }, 223 { 218, "getcacheconf" }, 224 { 65536, "getce64" }, 225 { 65537, "getcellbynum" }, 226 { 65538, "tellmeaboutyourself" }, 227 { 0, NULL }, 228 }; 229 230 static const struct tok pt_req[] = { 231 { 500, "new-user" }, 232 { 501, "where-is-it" }, 233 { 502, "dump-entry" }, 234 { 503, "add-to-group" }, 235 { 504, "name-to-id" }, 236 { 505, "id-to-name" }, 237 { 506, "delete" }, 238 { 507, "remove-from-group" }, 239 { 508, "get-cps" }, 240 { 509, "new-entry" }, 241 { 510, "list-max" }, 242 { 511, "set-max" }, 243 { 512, "list-entry" }, 244 { 513, "change-entry" }, 245 { 514, "list-elements" }, 246 { 515, "same-mbr-of" }, 247 { 516, "set-fld-sentry" }, 248 { 517, "list-owned" }, 249 { 518, "get-cps2" }, 250 { 519, "get-host-cps" }, 251 { 520, "update-entry" }, 252 { 521, "list-entries" }, 253 { 530, "list-super-groups" }, 254 { 0, NULL }, 255 }; 256 257 static const struct tok vldb_req[] = { 258 { 501, "create-entry" }, 259 { 502, "delete-entry" }, 260 { 503, "get-entry-by-id" }, 261 { 504, "get-entry-by-name" }, 262 { 505, "get-new-volume-id" }, 263 { 506, "replace-entry" }, 264 { 507, "update-entry" }, 265 { 508, "setlock" }, 266 { 509, "releaselock" }, 267 { 510, "list-entry" }, 268 { 511, "list-attrib" }, 269 { 512, "linked-list" }, 270 { 513, "get-stats" }, 271 { 514, "probe" }, 272 { 515, "get-addrs" }, 273 { 516, "change-addr" }, 274 { 517, "create-entry-n" }, 275 { 518, "get-entry-by-id-n" }, 276 { 519, "get-entry-by-name-n" }, 277 { 520, "replace-entry-n" }, 278 { 521, "list-entry-n" }, 279 { 522, "list-attrib-n" }, 280 { 523, "linked-list-n" }, 281 { 524, "update-entry-by-name" }, 282 { 525, "create-entry-u" }, 283 { 526, "get-entry-by-id-u" }, 284 { 527, "get-entry-by-name-u" }, 285 { 528, "replace-entry-u" }, 286 { 529, "list-entry-u" }, 287 { 530, "list-attrib-u" }, 288 { 531, "linked-list-u" }, 289 { 532, "regaddr" }, 290 { 533, "get-addrs-u" }, 291 { 534, "list-attrib-n2" }, 292 { 0, NULL }, 293 }; 294 295 static const struct tok kauth_req[] = { 296 { 1, "auth-old" }, 297 { 21, "authenticate" }, 298 { 22, "authenticate-v2" }, 299 { 2, "change-pw" }, 300 { 3, "get-ticket-old" }, 301 { 23, "get-ticket" }, 302 { 4, "set-pw" }, 303 { 5, "set-fields" }, 304 { 6, "create-user" }, 305 { 7, "delete-user" }, 306 { 8, "get-entry" }, 307 { 9, "list-entry" }, 308 { 10, "get-stats" }, 309 { 11, "debug" }, 310 { 12, "get-pw" }, 311 { 13, "get-random-key" }, 312 { 14, "unlock" }, 313 { 15, "lock-status" }, 314 { 0, NULL }, 315 }; 316 317 static const struct tok vol_req[] = { 318 { 100, "create-volume" }, 319 { 101, "delete-volume" }, 320 { 102, "restore" }, 321 { 103, "forward" }, 322 { 104, "end-trans" }, 323 { 105, "clone" }, 324 { 106, "set-flags" }, 325 { 107, "get-flags" }, 326 { 108, "trans-create" }, 327 { 109, "dump" }, 328 { 110, "get-nth-volume" }, 329 { 111, "set-forwarding" }, 330 { 112, "get-name" }, 331 { 113, "get-status" }, 332 { 114, "sig-restore" }, 333 { 115, "list-partitions" }, 334 { 116, "list-volumes" }, 335 { 117, "set-id-types" }, 336 { 118, "monitor" }, 337 { 119, "partition-info" }, 338 { 120, "reclone" }, 339 { 121, "list-one-volume" }, 340 { 122, "nuke" }, 341 { 123, "set-date" }, 342 { 124, "x-list-volumes" }, 343 { 125, "x-list-one-volume" }, 344 { 126, "set-info" }, 345 { 127, "x-list-partitions" }, 346 { 128, "forward-multiple" }, 347 { 65536, "convert-ro" }, 348 { 65537, "get-size" }, 349 { 65538, "dump-v2" }, 350 { 0, NULL }, 351 }; 352 353 static const struct tok bos_req[] = { 354 { 80, "create-bnode" }, 355 { 81, "delete-bnode" }, 356 { 82, "set-status" }, 357 { 83, "get-status" }, 358 { 84, "enumerate-instance" }, 359 { 85, "get-instance-info" }, 360 { 86, "get-instance-parm" }, 361 { 87, "add-superuser" }, 362 { 88, "delete-superuser" }, 363 { 89, "list-superusers" }, 364 { 90, "list-keys" }, 365 { 91, "add-key" }, 366 { 92, "delete-key" }, 367 { 93, "set-cell-name" }, 368 { 94, "get-cell-name" }, 369 { 95, "get-cell-host" }, 370 { 96, "add-cell-host" }, 371 { 97, "delete-cell-host" }, 372 { 98, "set-t-status" }, 373 { 99, "shutdown-all" }, 374 { 100, "restart-all" }, 375 { 101, "startup-all" }, 376 { 102, "set-noauth-flag" }, 377 { 103, "re-bozo" }, 378 { 104, "restart" }, 379 { 105, "start-bozo-install" }, 380 { 106, "uninstall" }, 381 { 107, "get-dates" }, 382 { 108, "exec" }, 383 { 109, "prune" }, 384 { 110, "set-restart-time" }, 385 { 111, "get-restart-time" }, 386 { 112, "start-bozo-log" }, 387 { 113, "wait-all" }, 388 { 114, "get-instance-strings" }, 389 { 115, "get-restricted" }, 390 { 116, "set-restricted" }, 391 { 0, NULL }, 392 }; 393 394 static const struct tok ubik_req[] = { 395 { 10000, "vote-beacon" }, 396 { 10001, "vote-debug-old" }, 397 { 10002, "vote-sdebug-old" }, 398 { 10003, "vote-getsyncsite" }, 399 { 10004, "vote-debug" }, 400 { 10005, "vote-sdebug" }, 401 { 10006, "vote-xdebug" }, 402 { 10007, "vote-xsdebug" }, 403 { 20000, "disk-begin" }, 404 { 20001, "disk-commit" }, 405 { 20002, "disk-lock" }, 406 { 20003, "disk-write" }, 407 { 20004, "disk-getversion" }, 408 { 20005, "disk-getfile" }, 409 { 20006, "disk-sendfile" }, 410 { 20007, "disk-abort" }, 411 { 20008, "disk-releaselocks" }, 412 { 20009, "disk-truncate" }, 413 { 20010, "disk-probe" }, 414 { 20011, "disk-writev" }, 415 { 20012, "disk-interfaceaddr" }, 416 { 20013, "disk-setversion" }, 417 { 0, NULL }, 418 }; 419 420 #define VOTE_LOW 10000 421 #define VOTE_HIGH 10007 422 #define DISK_LOW 20000 423 #define DISK_HIGH 20013 424 425 static const struct tok cb_types[] = { 426 { 1, "exclusive" }, 427 { 2, "shared" }, 428 { 3, "dropped" }, 429 { 0, NULL }, 430 }; 431 432 static const struct tok ubik_lock_types[] = { 433 { 1, "read" }, 434 { 2, "write" }, 435 { 3, "wait" }, 436 { 0, NULL }, 437 }; 438 439 static const char *voltype[] = { "read-write", "read-only", "backup" }; 440 441 static const struct tok afs_fs_errors[] = { 442 { 101, "salvage volume" }, 443 { 102, "no such vnode" }, 444 { 103, "no such volume" }, 445 { 104, "volume exist" }, 446 { 105, "no service" }, 447 { 106, "volume offline" }, 448 { 107, "voline online" }, 449 { 108, "diskfull" }, 450 { 109, "diskquota exceeded" }, 451 { 110, "volume busy" }, 452 { 111, "volume moved" }, 453 { 112, "AFS IO error" }, 454 { 0xffffff9c, "restarting fileserver" }, /* -100, sic! */ 455 { 0, NULL } 456 }; 457 458 /* 459 * Reasons for acknowledging a packet 460 */ 461 462 static const struct tok rx_ack_reasons[] = { 463 { 1, "ack requested" }, 464 { 2, "duplicate packet" }, 465 { 3, "out of sequence" }, 466 { 4, "exceeds window" }, 467 { 5, "no buffer space" }, 468 { 6, "ping" }, 469 { 7, "ping response" }, 470 { 8, "delay" }, 471 { 9, "idle" }, 472 { 0, NULL }, 473 }; 474 475 /* 476 * Cache entries we keep around so we can figure out the RX opcode 477 * numbers for replies. This allows us to make sense of RX reply packets. 478 */ 479 480 struct rx_cache_entry { 481 uint32_t callnum; /* Call number (net order) */ 482 struct in_addr client; /* client IP address (net order) */ 483 struct in_addr server; /* server IP address (net order) */ 484 int dport; /* server port (host order) */ 485 u_short serviceId; /* Service identifier (net order) */ 486 uint32_t opcode; /* RX opcode (host order) */ 487 }; 488 489 #define RX_CACHE_SIZE 64 490 491 static struct rx_cache_entry rx_cache[RX_CACHE_SIZE]; 492 493 static int rx_cache_next = 0; 494 static int rx_cache_hint = 0; 495 static void rx_cache_insert(netdissect_options *, const u_char *, const struct ip *, int); 496 static int rx_cache_find(const struct rx_header *, const struct ip *, 497 int, int32_t *); 498 499 static void fs_print(netdissect_options *, const u_char *, int); 500 static void fs_reply_print(netdissect_options *, const u_char *, int, int32_t); 501 static void acl_print(netdissect_options *, u_char *, int, u_char *); 502 static void cb_print(netdissect_options *, const u_char *, int); 503 static void cb_reply_print(netdissect_options *, const u_char *, int, int32_t); 504 static void prot_print(netdissect_options *, const u_char *, int); 505 static void prot_reply_print(netdissect_options *, const u_char *, int, int32_t); 506 static void vldb_print(netdissect_options *, const u_char *, int); 507 static void vldb_reply_print(netdissect_options *, const u_char *, int, int32_t); 508 static void kauth_print(netdissect_options *, const u_char *, int); 509 static void kauth_reply_print(netdissect_options *, const u_char *, int, int32_t); 510 static void vol_print(netdissect_options *, const u_char *, int); 511 static void vol_reply_print(netdissect_options *, const u_char *, int, int32_t); 512 static void bos_print(netdissect_options *, const u_char *, int); 513 static void bos_reply_print(netdissect_options *, const u_char *, int, int32_t); 514 static void ubik_print(netdissect_options *, const u_char *); 515 static void ubik_reply_print(netdissect_options *, const u_char *, int, int32_t); 516 517 static void rx_ack_print(netdissect_options *, const u_char *, int); 518 519 static int is_ubik(uint32_t); 520 521 /* 522 * Handle the rx-level packet. See if we know what port it's going to so 523 * we can peek at the afs call inside 524 */ 525 526 void 527 rx_print(netdissect_options *ndo, 528 register const u_char *bp, int length, int sport, int dport, 529 const u_char *bp2) 530 { 531 register const struct rx_header *rxh; 532 int i; 533 int32_t opcode; 534 535 if (ndo->ndo_snapend - bp < (int)sizeof (struct rx_header)) { 536 ND_PRINT((ndo, " [|rx] (%d)", length)); 537 return; 538 } 539 540 rxh = (const struct rx_header *) bp; 541 542 ND_PRINT((ndo, " rx %s", tok2str(rx_types, "type %d", rxh->type))); 543 544 if (ndo->ndo_vflag) { 545 int firstflag = 0; 546 547 if (ndo->ndo_vflag > 1) 548 ND_PRINT((ndo, " cid %08x call# %d", 549 (int) EXTRACT_32BITS(&rxh->cid), 550 (int) EXTRACT_32BITS(&rxh->callNumber))); 551 552 ND_PRINT((ndo, " seq %d ser %d", 553 (int) EXTRACT_32BITS(&rxh->seq), 554 (int) EXTRACT_32BITS(&rxh->serial))); 555 556 if (ndo->ndo_vflag > 2) 557 ND_PRINT((ndo, " secindex %d serviceid %hu", 558 (int) rxh->securityIndex, 559 EXTRACT_16BITS(&rxh->serviceId))); 560 561 if (ndo->ndo_vflag > 1) 562 for (i = 0; i < NUM_RX_FLAGS; i++) { 563 if (rxh->flags & rx_flags[i].flag && 564 (!rx_flags[i].packetType || 565 rxh->type == rx_flags[i].packetType)) { 566 if (!firstflag) { 567 firstflag = 1; 568 ND_PRINT((ndo, " ")); 569 } else { 570 ND_PRINT((ndo, ",")); 571 } 572 ND_PRINT((ndo, "<%s>", rx_flags[i].s)); 573 } 574 } 575 } 576 577 /* 578 * Try to handle AFS calls that we know about. Check the destination 579 * port and make sure it's a data packet. Also, make sure the 580 * seq number is 1 (because otherwise it's a continuation packet, 581 * and we can't interpret that). Also, seems that reply packets 582 * do not have the client-init flag set, so we check for that 583 * as well. 584 */ 585 586 if (rxh->type == RX_PACKET_TYPE_DATA && 587 EXTRACT_32BITS(&rxh->seq) == 1 && 588 rxh->flags & RX_CLIENT_INITIATED) { 589 590 /* 591 * Insert this call into the call cache table, so we 592 * have a chance to print out replies 593 */ 594 595 rx_cache_insert(ndo, bp, (const struct ip *) bp2, dport); 596 597 switch (dport) { 598 case FS_RX_PORT: /* AFS file service */ 599 fs_print(ndo, bp, length); 600 break; 601 case CB_RX_PORT: /* AFS callback service */ 602 cb_print(ndo, bp, length); 603 break; 604 case PROT_RX_PORT: /* AFS protection service */ 605 prot_print(ndo, bp, length); 606 break; 607 case VLDB_RX_PORT: /* AFS VLDB service */ 608 vldb_print(ndo, bp, length); 609 break; 610 case KAUTH_RX_PORT: /* AFS Kerberos auth service */ 611 kauth_print(ndo, bp, length); 612 break; 613 case VOL_RX_PORT: /* AFS Volume service */ 614 vol_print(ndo, bp, length); 615 break; 616 case BOS_RX_PORT: /* AFS BOS service */ 617 bos_print(ndo, bp, length); 618 break; 619 default: 620 ; 621 } 622 623 /* 624 * If it's a reply (client-init is _not_ set, but seq is one) 625 * then look it up in the cache. If we find it, call the reply 626 * printing functions Note that we handle abort packets here, 627 * because printing out the return code can be useful at times. 628 */ 629 630 } else if (((rxh->type == RX_PACKET_TYPE_DATA && 631 EXTRACT_32BITS(&rxh->seq) == 1) || 632 rxh->type == RX_PACKET_TYPE_ABORT) && 633 (rxh->flags & RX_CLIENT_INITIATED) == 0 && 634 rx_cache_find(rxh, (const struct ip *) bp2, 635 sport, &opcode)) { 636 637 switch (sport) { 638 case FS_RX_PORT: /* AFS file service */ 639 fs_reply_print(ndo, bp, length, opcode); 640 break; 641 case CB_RX_PORT: /* AFS callback service */ 642 cb_reply_print(ndo, bp, length, opcode); 643 break; 644 case PROT_RX_PORT: /* AFS PT service */ 645 prot_reply_print(ndo, bp, length, opcode); 646 break; 647 case VLDB_RX_PORT: /* AFS VLDB service */ 648 vldb_reply_print(ndo, bp, length, opcode); 649 break; 650 case KAUTH_RX_PORT: /* AFS Kerberos auth service */ 651 kauth_reply_print(ndo, bp, length, opcode); 652 break; 653 case VOL_RX_PORT: /* AFS Volume service */ 654 vol_reply_print(ndo, bp, length, opcode); 655 break; 656 case BOS_RX_PORT: /* AFS BOS service */ 657 bos_reply_print(ndo, bp, length, opcode); 658 break; 659 default: 660 ; 661 } 662 663 /* 664 * If it's an RX ack packet, then use the appropriate ack decoding 665 * function (there isn't any service-specific information in the 666 * ack packet, so we can use one for all AFS services) 667 */ 668 669 } else if (rxh->type == RX_PACKET_TYPE_ACK) 670 rx_ack_print(ndo, bp, length); 671 672 673 ND_PRINT((ndo, " (%d)", length)); 674 } 675 676 /* 677 * Insert an entry into the cache. Taken from print-nfs.c 678 */ 679 680 static void 681 rx_cache_insert(netdissect_options *ndo, 682 const u_char *bp, const struct ip *ip, int dport) 683 { 684 struct rx_cache_entry *rxent; 685 const struct rx_header *rxh = (const struct rx_header *) bp; 686 687 if (ndo->ndo_snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) 688 return; 689 690 rxent = &rx_cache[rx_cache_next]; 691 692 if (++rx_cache_next >= RX_CACHE_SIZE) 693 rx_cache_next = 0; 694 695 rxent->callnum = rxh->callNumber; 696 UNALIGNED_MEMCPY(&rxent->client, &ip->ip_src, sizeof(uint32_t)); 697 UNALIGNED_MEMCPY(&rxent->server, &ip->ip_dst, sizeof(uint32_t)); 698 rxent->dport = dport; 699 rxent->serviceId = rxh->serviceId; 700 rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 701 } 702 703 /* 704 * Lookup an entry in the cache. Also taken from print-nfs.c 705 * 706 * Note that because this is a reply, we're looking at the _source_ 707 * port. 708 */ 709 710 static int 711 rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, 712 int32_t *opcode) 713 { 714 int i; 715 struct rx_cache_entry *rxent; 716 uint32_t clip; 717 uint32_t sip; 718 719 UNALIGNED_MEMCPY(&clip, &ip->ip_dst, sizeof(uint32_t)); 720 UNALIGNED_MEMCPY(&sip, &ip->ip_src, sizeof(uint32_t)); 721 722 /* Start the search where we last left off */ 723 724 i = rx_cache_hint; 725 do { 726 rxent = &rx_cache[i]; 727 if (rxent->callnum == rxh->callNumber && 728 rxent->client.s_addr == clip && 729 rxent->server.s_addr == sip && 730 rxent->serviceId == rxh->serviceId && 731 rxent->dport == sport) { 732 733 /* We got a match! */ 734 735 rx_cache_hint = i; 736 *opcode = rxent->opcode; 737 return(1); 738 } 739 if (++i >= RX_CACHE_SIZE) 740 i = 0; 741 } while (i != rx_cache_hint); 742 743 /* Our search failed */ 744 return(0); 745 } 746 747 /* 748 * These extrememly grody macros handle the printing of various AFS stuff. 749 */ 750 751 #define FIDOUT() { unsigned long n1, n2, n3; \ 752 ND_TCHECK2(bp[0], sizeof(int32_t) * 3); \ 753 n1 = EXTRACT_32BITS(bp); \ 754 bp += sizeof(int32_t); \ 755 n2 = EXTRACT_32BITS(bp); \ 756 bp += sizeof(int32_t); \ 757 n3 = EXTRACT_32BITS(bp); \ 758 bp += sizeof(int32_t); \ 759 ND_PRINT((ndo, " fid %d/%d/%d", (int) n1, (int) n2, (int) n3)); \ 760 } 761 762 #define STROUT(MAX) { unsigned int _i; \ 763 ND_TCHECK2(bp[0], sizeof(int32_t)); \ 764 _i = EXTRACT_32BITS(bp); \ 765 if (_i > (MAX)) \ 766 goto trunc; \ 767 bp += sizeof(int32_t); \ 768 ND_PRINT((ndo, " \"")); \ 769 if (fn_printn(ndo, bp, _i, ndo->ndo_snapend)) \ 770 goto trunc; \ 771 ND_PRINT((ndo, "\"")); \ 772 bp += ((_i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \ 773 } 774 775 #define INTOUT() { int _i; \ 776 ND_TCHECK2(bp[0], sizeof(int32_t)); \ 777 _i = (int) EXTRACT_32BITS(bp); \ 778 bp += sizeof(int32_t); \ 779 ND_PRINT((ndo, " %d", _i)); \ 780 } 781 782 #define UINTOUT() { unsigned long _i; \ 783 ND_TCHECK2(bp[0], sizeof(int32_t)); \ 784 _i = EXTRACT_32BITS(bp); \ 785 bp += sizeof(int32_t); \ 786 ND_PRINT((ndo, " %lu", _i)); \ 787 } 788 789 #define UINT64OUT() { uint64_t _i; \ 790 ND_TCHECK2(bp[0], sizeof(uint64_t)); \ 791 _i = EXTRACT_64BITS(bp); \ 792 bp += sizeof(uint64_t); \ 793 ND_PRINT((ndo, " %" PRIu64, _i)); \ 794 } 795 796 #define DATEOUT() { time_t _t; struct tm *tm; char str[256]; \ 797 ND_TCHECK2(bp[0], sizeof(int32_t)); \ 798 _t = (time_t) EXTRACT_32BITS(bp); \ 799 bp += sizeof(int32_t); \ 800 tm = localtime(&_t); \ 801 strftime(str, 256, "%Y/%m/%d %H:%M:%S", tm); \ 802 ND_PRINT((ndo, " %s", str)); \ 803 } 804 805 #define STOREATTROUT() { unsigned long mask, _i; \ 806 ND_TCHECK2(bp[0], (sizeof(int32_t)*6)); \ 807 mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 808 if (mask) ND_PRINT((ndo, " StoreStatus")); \ 809 if (mask & 1) { ND_PRINT((ndo, " date")); DATEOUT(); } \ 810 else bp += sizeof(int32_t); \ 811 _i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 812 if (mask & 2) ND_PRINT((ndo, " owner %lu", _i)); \ 813 _i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 814 if (mask & 4) ND_PRINT((ndo, " group %lu", _i)); \ 815 _i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 816 if (mask & 8) ND_PRINT((ndo, " mode %lo", _i & 07777)); \ 817 _i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ 818 if (mask & 16) ND_PRINT((ndo, " segsize %lu", _i)); \ 819 /* undocumented in 3.3 docu */ \ 820 if (mask & 1024) ND_PRINT((ndo, " fsync")); \ 821 } 822 823 #define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \ 824 ND_TCHECK2(bp[0], sizeof(int32_t) * 2); \ 825 epoch = EXTRACT_32BITS(bp); \ 826 bp += sizeof(int32_t); \ 827 counter = EXTRACT_32BITS(bp); \ 828 bp += sizeof(int32_t); \ 829 ND_PRINT((ndo, " %d.%d", epoch, counter)); \ 830 } 831 832 #define AFSUUIDOUT() {uint32_t temp; int _i; \ 833 ND_TCHECK2(bp[0], 11*sizeof(uint32_t)); \ 834 temp = EXTRACT_32BITS(bp); \ 835 bp += sizeof(uint32_t); \ 836 ND_PRINT((ndo, " %08x", temp)); \ 837 temp = EXTRACT_32BITS(bp); \ 838 bp += sizeof(uint32_t); \ 839 ND_PRINT((ndo, "%04x", temp)); \ 840 temp = EXTRACT_32BITS(bp); \ 841 bp += sizeof(uint32_t); \ 842 ND_PRINT((ndo, "%04x", temp)); \ 843 for (_i = 0; _i < 8; _i++) { \ 844 temp = EXTRACT_32BITS(bp); \ 845 bp += sizeof(uint32_t); \ 846 ND_PRINT((ndo, "%02x", (unsigned char) temp)); \ 847 } \ 848 } 849 850 /* 851 * This is the sickest one of all 852 */ 853 854 #define VECOUT(MAX) { u_char *sp; \ 855 u_char s[AFSNAMEMAX]; \ 856 int k; \ 857 if ((MAX) + 1 > sizeof(s)) \ 858 goto trunc; \ 859 ND_TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \ 860 sp = s; \ 861 for (k = 0; k < (MAX); k++) { \ 862 *sp++ = (u_char) EXTRACT_32BITS(bp); \ 863 bp += sizeof(int32_t); \ 864 } \ 865 s[(MAX)] = '\0'; \ 866 ND_PRINT((ndo, " \"")); \ 867 fn_print(ndo, s, NULL); \ 868 ND_PRINT((ndo, "\"")); \ 869 } 870 871 #define DESTSERVEROUT() { unsigned long n1, n2, n3; \ 872 ND_TCHECK2(bp[0], sizeof(int32_t) * 3); \ 873 n1 = EXTRACT_32BITS(bp); \ 874 bp += sizeof(int32_t); \ 875 n2 = EXTRACT_32BITS(bp); \ 876 bp += sizeof(int32_t); \ 877 n3 = EXTRACT_32BITS(bp); \ 878 bp += sizeof(int32_t); \ 879 ND_PRINT((ndo, " server %d:%d:%d", (int) n1, (int) n2, (int) n3)); \ 880 } 881 882 /* 883 * Handle calls to the AFS file service (fs) 884 */ 885 886 static void 887 fs_print(netdissect_options *ndo, 888 register const u_char *bp, int length) 889 { 890 int fs_op; 891 unsigned long i; 892 893 if (length <= (int)sizeof(struct rx_header)) 894 return; 895 896 if (ndo->ndo_snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) { 897 goto trunc; 898 } 899 900 /* 901 * Print out the afs call we're invoking. The table used here was 902 * gleaned from fsint/afsint.xg 903 */ 904 905 fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); 906 907 ND_PRINT((ndo, " fs call %s", tok2str(fs_req, "op#%d", fs_op))); 908 909 /* 910 * Print out arguments to some of the AFS calls. This stuff is 911 * all from afsint.xg 912 */ 913 914 bp += sizeof(struct rx_header) + 4; 915 916 /* 917 * Sigh. This is gross. Ritchie forgive me. 918 */ 919 920 switch (fs_op) { 921 case 130: /* Fetch data */ 922 FIDOUT(); 923 ND_PRINT((ndo, " offset")); 924 UINTOUT(); 925 ND_PRINT((ndo, " length")); 926 UINTOUT(); 927 break; 928 case 131: /* Fetch ACL */ 929 case 132: /* Fetch Status */ 930 case 143: /* Old set lock */ 931 case 144: /* Old extend lock */ 932 case 145: /* Old release lock */ 933 case 156: /* Set lock */ 934 case 157: /* Extend lock */ 935 case 158: /* Release lock */ 936 FIDOUT(); 937 break; 938 case 135: /* Store status */ 939 FIDOUT(); 940 STOREATTROUT(); 941 break; 942 case 133: /* Store data */ 943 FIDOUT(); 944 STOREATTROUT(); 945 ND_PRINT((ndo, " offset")); 946 UINTOUT(); 947 ND_PRINT((ndo, " length")); 948 UINTOUT(); 949 ND_PRINT((ndo, " flen")); 950 UINTOUT(); 951 break; 952 case 134: /* Store ACL */ 953 { 954 char a[AFSOPAQUEMAX+1]; 955 FIDOUT(); 956 ND_TCHECK2(bp[0], 4); 957 i = EXTRACT_32BITS(bp); 958 bp += sizeof(int32_t); 959 ND_TCHECK2(bp[0], i); 960 i = min(AFSOPAQUEMAX, i); 961 strncpy(a, (const char *) bp, i); 962 a[i] = '\0'; 963 acl_print(ndo, (u_char *) a, sizeof(a), (u_char *) a + i); 964 break; 965 } 966 case 137: /* Create file */ 967 case 141: /* MakeDir */ 968 FIDOUT(); 969 STROUT(AFSNAMEMAX); 970 STOREATTROUT(); 971 break; 972 case 136: /* Remove file */ 973 case 142: /* Remove directory */ 974 FIDOUT(); 975 STROUT(AFSNAMEMAX); 976 break; 977 case 138: /* Rename file */ 978 ND_PRINT((ndo, " old")); 979 FIDOUT(); 980 STROUT(AFSNAMEMAX); 981 ND_PRINT((ndo, " new")); 982 FIDOUT(); 983 STROUT(AFSNAMEMAX); 984 break; 985 case 139: /* Symlink */ 986 FIDOUT(); 987 STROUT(AFSNAMEMAX); 988 ND_PRINT((ndo, " link to")); 989 STROUT(AFSNAMEMAX); 990 break; 991 case 140: /* Link */ 992 FIDOUT(); 993 STROUT(AFSNAMEMAX); 994 ND_PRINT((ndo, " link to")); 995 FIDOUT(); 996 break; 997 case 148: /* Get volume info */ 998 STROUT(AFSNAMEMAX); 999 break; 1000 case 149: /* Get volume stats */ 1001 case 150: /* Set volume stats */ 1002 ND_PRINT((ndo, " volid")); 1003 UINTOUT(); 1004 break; 1005 case 154: /* New get volume info */ 1006 ND_PRINT((ndo, " volname")); 1007 STROUT(AFSNAMEMAX); 1008 break; 1009 case 155: /* Bulk stat */ 1010 case 65536: /* Inline bulk stat */ 1011 { 1012 unsigned long j; 1013 ND_TCHECK2(bp[0], 4); 1014 j = EXTRACT_32BITS(bp); 1015 bp += sizeof(int32_t); 1016 1017 for (i = 0; i < j; i++) { 1018 FIDOUT(); 1019 if (i != j - 1) 1020 ND_PRINT((ndo, ",")); 1021 } 1022 if (j == 0) 1023 ND_PRINT((ndo, " <none!>")); 1024 } 1025 case 65537: /* Fetch data 64 */ 1026 FIDOUT(); 1027 ND_PRINT((ndo, " offset")); 1028 UINT64OUT(); 1029 ND_PRINT((ndo, " length")); 1030 UINT64OUT(); 1031 break; 1032 case 65538: /* Store data 64 */ 1033 FIDOUT(); 1034 STOREATTROUT(); 1035 ND_PRINT((ndo, " offset")); 1036 UINT64OUT(); 1037 ND_PRINT((ndo, " length")); 1038 UINT64OUT(); 1039 ND_PRINT((ndo, " flen")); 1040 UINT64OUT(); 1041 break; 1042 case 65541: /* CallBack rx conn address */ 1043 ND_PRINT((ndo, " addr")); 1044 UINTOUT(); 1045 default: 1046 ; 1047 } 1048 1049 return; 1050 1051 trunc: 1052 ND_PRINT((ndo, " [|fs]")); 1053 } 1054 1055 /* 1056 * Handle replies to the AFS file service 1057 */ 1058 1059 static void 1060 fs_reply_print(netdissect_options *ndo, 1061 register const u_char *bp, int length, int32_t opcode) 1062 { 1063 unsigned long i; 1064 const struct rx_header *rxh; 1065 1066 if (length <= (int)sizeof(struct rx_header)) 1067 return; 1068 1069 rxh = (const struct rx_header *) bp; 1070 1071 /* 1072 * Print out the afs call we're invoking. The table used here was 1073 * gleaned from fsint/afsint.xg 1074 */ 1075 1076 ND_PRINT((ndo, " fs reply %s", tok2str(fs_req, "op#%d", opcode))); 1077 1078 bp += sizeof(struct rx_header); 1079 1080 /* 1081 * If it was a data packet, interpret the response 1082 */ 1083 1084 if (rxh->type == RX_PACKET_TYPE_DATA) { 1085 switch (opcode) { 1086 case 131: /* Fetch ACL */ 1087 { 1088 char a[AFSOPAQUEMAX+1]; 1089 ND_TCHECK2(bp[0], 4); 1090 i = EXTRACT_32BITS(bp); 1091 bp += sizeof(int32_t); 1092 ND_TCHECK2(bp[0], i); 1093 i = min(AFSOPAQUEMAX, i); 1094 strncpy(a, (const char *) bp, i); 1095 a[i] = '\0'; 1096 acl_print(ndo, (u_char *) a, sizeof(a), (u_char *) a + i); 1097 break; 1098 } 1099 case 137: /* Create file */ 1100 case 141: /* MakeDir */ 1101 ND_PRINT((ndo, " new")); 1102 FIDOUT(); 1103 break; 1104 case 151: /* Get root volume */ 1105 ND_PRINT((ndo, " root volume")); 1106 STROUT(AFSNAMEMAX); 1107 break; 1108 case 153: /* Get time */ 1109 DATEOUT(); 1110 break; 1111 default: 1112 ; 1113 } 1114 } else if (rxh->type == RX_PACKET_TYPE_ABORT) { 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 const struct rx_header *rxh; 1308 1309 if (length <= (int)sizeof(struct rx_header)) 1310 return; 1311 1312 rxh = (const 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 const struct rx_header *rxh; 1502 unsigned long i; 1503 1504 if (length < (int)sizeof(struct rx_header)) 1505 return; 1506 1507 rxh = (const 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 const struct rx_header *rxh; 1709 unsigned long i; 1710 1711 if (length < (int)sizeof(struct rx_header)) 1712 return; 1713 1714 rxh = (const 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(((const 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(((const 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 const struct rx_header *rxh; 1991 1992 if (length <= (int)sizeof(struct rx_header)) 1993 return; 1994 1995 rxh = (const 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 const struct rx_header *rxh; 2245 2246 if (length <= (int)sizeof(struct rx_header)) 2247 return; 2248 2249 rxh = (const 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 const struct rx_header *rxh; 2472 2473 if (length <= (int)sizeof(struct rx_header)) 2474 return; 2475 2476 rxh = (const 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 const struct rx_header *rxh; 2641 2642 if (length < (int)sizeof(struct rx_header)) 2643 return; 2644 2645 rxh = (const 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 const 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 = (const 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