⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _rx.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * This code unmangles RX packets.  RX is the mutant form of RPC that AFS
 * uses to communicate between clients and servers.
 *
 * In this code, I mainly concern myself with decoding the AFS calls, not
 * with the guts of RX, per se.
 *
 * Bah.  If I never look at rx_packet.h again, it will be too soon.
 *
 * Ken Hornstein <kenh@cmf.nrl.navy.mil>
 *
 */

#if 0
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.5.2.1 2000/01/11 06:58:27 fenner Exp $";
#endif

#include <stdio.h>
#include <string.h>

#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>

#include "interfac.h"
#include "a2name.h"
#include "rx.h"

#ifdef OLD_RX_PRINTER

static struct tok rx_types[] = {
  { RX_PACKET_TYPE_DATA, "data" },
  { RX_PACKET_TYPE_ACK, "ack" },
  { RX_PACKET_TYPE_BUSY, "busy" },
  { RX_PACKET_TYPE_ABORT, "abort" },
  { RX_PACKET_TYPE_ACKALL, "ackall" },
  { RX_PACKET_TYPE_CHALLENGE, "challenge" },
  { RX_PACKET_TYPE_RESPONSE, "response" },
  { RX_PACKET_TYPE_DEBUG, "debug" },
  { RX_PACKET_TYPE_PARAMS, "params" },
  { RX_PACKET_TYPE_VERSION, "version" },
  { 0, NULL },
};

static struct tok rx_flags[] = {
  { RX_CLIENT_INITIATED, "client-init" },
  { RX_REQUEST_ACK, "req-ack" },
  { RX_LAST_PACKET, "last-pckt" },
  { RX_MORE_PACKETS, "more-pckts" },
  { RX_FREE_PACKET, "free-pckt"}
};

static struct tok fs_req[] = {
  { 130, "fetch-data" },
  { 131, "fetch-acl" },
  { 132, "fetch-status" },
  { 133, "store-data" },
  { 134, "store-acl" },
  { 135, "store-status" },
  { 136, "remove-file" },
  { 137, "create-file" },
  { 138, "rename" },
  { 139, "symlink" },
  { 140, "link" },
  { 141, "makedir" },
  { 142, "rmdir" },
  { 143, "oldsetlock" },
  { 144, "oldextlock" },
  { 145, "oldrellock" },
  { 146, "get-stats" },
  { 147, "give-cbs" },
  { 148, "get-vlinfo" },
  { 149, "get-vlstats" },
  { 150, "set-vlstats" },
  { 151, "get-rootvl" },
  { 152, "check-token" },
  { 153, "get-time" },
  { 154, "nget-vlinfo" },
  { 155, "bulk-stat" },
  { 156, "setlock" },
  { 157, "extlock" },
  { 158, "rellock" },
  { 159, "xstat-ver" },
  { 160, "get-xstat" },
  { 161, "dfs-lookup" },
  { 162, "dfs-flushcps" },
  { 163, "dfs-symlink" },
  { 0, NULL },
};

static struct tok cb_req[] = {
  { 204, "callback" },
  { 205, "initcb" },
  { 206, "probe" },
  { 207, "getlock" },
  { 208, "getce" },
  { 209, "xstatver" },
  { 210, "getxstat" },
  { 211, "initcb2" },
  { 212, "whoareyou" },
  { 213, "initcb3" },
  { 214, "probeuuid" },
  { 0, NULL },
};

static struct tok pt_req[] = {
  { 500, "new-user" },
  { 501, "where-is-it" },
  { 502, "dump-entry" },
  { 503, "add-to-group" },
  { 504, "name-to-id" },
  { 505, "id-to-name" },
  { 506, "delete" },
  { 507, "remove-from-group" },
  { 508, "get-cps" },
  { 509, "new-entry" },
  { 510, "list-max" },
  { 511, "set-max" },
  { 512, "list-entry" },
  { 513, "change-entry" },
  { 514, "list-elements" },
  { 515, "same-mbr-of" },
  { 516, "set-fld-sentry" },
  { 517, "list-owned" },
  { 518, "get-cps2" },
  { 519, "get-host-cps" },
  { 520, "update-entry" },
  { 0, NULL },
};

static struct tok vldb_req[] = {
  { 501, "create-entry" },
  { 502, "delete-entry" },
  { 503, "get-entry-by-id" },
  { 504, "get-entry-by-name" },
  { 505, "get-new-volume-id" },
  { 506, "replace-entry" },
  { 507, "update-entry" },
  { 508, "setlock" },
  { 509, "releaselock" },
  { 510, "list-entry" },
  { 511, "list-attrib" },
  { 512, "linked-list" },
  { 513, "get-stats" },
  { 514, "probe" },
  { 515, "get-addrs" },
  { 516, "change-addr" },
  { 517, "create-entry-n" },
  { 518, "get-entry-by-id-n" },
  { 519, "get-entry-by-name-n" },
  { 520, "replace-entry-n" },
  { 521, "list-entry-n" },
  { 522, "list-attrib-n" },
  { 523, "linked-list-n" },
  { 524, "update-entry-by-name" },
  { 525, "create-entry-u" },
  { 526, "get-entry-by-id-u" },
  { 527, "get-entry-by-name-u" },
  { 528, "replace-entry-u" },
  { 529, "list-entry-u" },
  { 530, "list-attrib-u" },
  { 531, "linked-list-u" },
  { 532, "regaddr" },
  { 533, "get-addrs-u" },
  { 0, NULL },
};

static struct tok kauth_req[] = {
  { 1, "auth-old" },
  { 21, "authenticate" },
  { 22, "authenticate-v2" },
  { 2, "change-pw" },
  { 3, "get-ticket-old" },
  { 23, "get-ticket" },
  { 4, "set-pw" },
  { 5, "set-fields" },
  { 6, "create-user" },
  { 7, "delete-user" },
  { 8, "get-entry" },
  { 9, "list-entry" },
  { 10, "get-stats" },
  { 11, "debug" },
  { 12, "get-pw" },
  { 13, "get-random-key" },
  { 14, "unlock" },
  { 15, "lock-status" },
  { 0, NULL },
};

static struct tok vol_req[] = {
  { 100, "create-volume" },
  { 101, "delete-volume" },
  { 102, "restore" },
  { 103, "forward" },
  { 104, "end-trans" },
  { 105, "clone" },
  { 106, "set-flags" },
  { 107, "get-flags" },
  { 108, "trans-create" },
  { 109, "dump" },
  { 110, "get-nth-volume" },
  { 111, "set-forwarding" },
  { 112, "get-name" },
  { 113, "get-status" },
  { 114, "sig-restore" },
  { 115, "list-partitions" },
  { 116, "list-volumes" },
  { 117, "set-id-types" },
  { 118, "monitor" },
  { 119, "partition-info" },
  { 120, "reclone" },
  { 121, "list-one-volume" },
  { 122, "nuke" },
  { 123, "set-date" },
  { 124, "x-list-volumes" },
  { 125, "x-list-one-volume" },
  { 126, "set-info" },
  { 127, "x-list-partitions" },
  { 128, "forward-multiple" },
  { 0, NULL },
};

static struct tok bos_req[] = {
  { 80, "create-bnode" },
  { 81, "delete-bnode" },
  { 82, "set-status" },
  { 83, "get-status" },
  { 84, "enumerate-instance" },
  { 85, "get-instance-info" },
  { 86, "get-instance-parm" },
  { 87, "add-superuser" },
  { 88, "delete-superuser" },
  { 89, "list-superusers" },
  { 90, "list-keys" },
  { 91, "add-key" },
  { 92, "delete-key" },
  { 93, "set-cell-name" },
  { 94, "get-cell-name" },
  { 95, "get-cell-host" },
  { 96, "add-cell-host" },
  { 97, "delete-cell-host" },
  { 98, "set-t-status" },
  { 99, "shutdown-all" },
  { 100, "restart-all" },
  { 101, "startup-all" },
  { 102, "set-noauth-flag" },
  { 103, "re-bozo" },
  { 104, "restart" },
  { 105, "start-bozo-install" },
  { 106, "uninstall" },
  { 107, "get-dates" },
  { 108, "exec" },
  { 109, "prune" },
  { 110, "set-restart-time" },
  { 111, "get-restart-time" },
  { 112, "start-bozo-log" },
  { 113, "wait-all" },
  { 114, "get-instance-strings" },
  { 0, NULL },
};

static struct tok ubik_req[] = {
  { 10000, "vote-beacon" },
  { 10001, "vote-debug-old" },
  { 10002, "vote-sdebug-old" },
  { 10003, "vote-getsyncsite" },
  { 10004, "vote-debug" },
  { 10005, "vote-sdebug" },
  { 20000, "disk-begin" },
  { 20001, "disk-commit" },
  { 20002, "disk-lock" },
  { 20003, "disk-write" },
  { 20004, "disk-getversion" },
  { 20005, "disk-getfile" },
  { 20006, "disk-sendfile" },
  { 20007, "disk-abort" },
  { 20008, "disk-releaselocks" },
  { 20009, "disk-truncate" },
  { 20010, "disk-probe" },
  { 20011, "disk-writev" },
  { 20012, "disk-interfaceaddr" },
  { 20013, "disk-setversion" },
  { 0, NULL },
};

#define VOTE_LOW   10000
#define VOTE_HIGH  10005
#define DISK_LOW   20000
#define DISK_HIGH  20013

static struct tok cb_types[] = {
  { 1, "exclusive" },
  { 2, "shared" },
  { 3, "dropped" },
  { 0, NULL },
};

static struct tok ubik_lock_types[] = {
  { 1, "read" },
  { 2, "write" },
  { 3, "wait" },
  { 0, NULL },
};

static char *voltype[] = {
            "read-write",
            "read-only",
            "backup"
          };

/*
 * Cache entries we keep around so we can figure out the RX opcode
 * numbers for replies.  This allows us to make sense of RX reply packets.
 */       
struct rx_cache_entry
{
  u_int32_t      callnum;     /* Call number (net order) */
  struct in_addr client;      /* client IP address (net order) */
  struct in_addr server;      /* server IP address (net order) */
  int            dport;       /* server port (host order) */
  u_short        serviceId;   /* Service identifier (net order) */
  u_int32_t      opcode;      /* RX opcode (host order) */
};

#define RX_CACHE_SIZE  64

static struct rx_cache_entry rx_cache[RX_CACHE_SIZE];

static int rx_cache_next = 0;
static int rx_cache_hint = 0;

static void rx_cache_insert  (const u_char *, const struct ip *, int, int);
static int  rx_cache_find    (const struct rx_header *, const struct ip *, int, int32_t *);

static void acl_print        (u_char *, u_char *);
static void fs_print         (const u_char *, int);
static void fs_reply_print   (const u_char *, int, int32_t);
static void cb_print         (const u_char *, int);
static void cb_reply_print   (const u_char *, int, int32_t);
static void prot_print       (const u_char *, int);
static void prot_reply_print (const u_char *, int, int32_t);
static void vldb_print       (const u_char *, int);
static void vldb_reply_print (const u_char *, int, int32_t);
static void kauth_print      (const u_char *, int);
static void kauth_reply_print(const u_char *, int, int32_t);
static void vol_print        (const u_char *, int);
static void vol_reply_print  (const u_char *, int, int32_t);
static void bos_print        (const u_char *, int);
static void bos_reply_print  (const u_char *, int, int32_t);
static void ubik_print       (const u_char *, int);
static void ubik_reply_print (const u_char *, int, int32_t);

/*
 * Check to see if this is a Ubik opcode.
 */
static __inline int is_ubik (u_int32_t opcode)
{
  if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
      (opcode >= DISK_LOW && opcode <= DISK_HIGH))
    return (1);
  return (0);
}

/*
 * Handle the rx-level packet.  See if we know what port it's going to so
 * we can peek at the afs call inside
 */
void rx_print (const u_char *bp, u_int length, u_int sport, u_int dport,
               u_char *bp2)
{
  struct  rx_header *rxh;
  int     i;
  int32_t opcode;

  if (snapend - bp < sizeof(struct rx_header))
  {
    PRINTF (" [|rx] (%d)", length);
    return;
  }

  rxh = (struct rx_header *) bp;

  PRINTF (" rx %s", tok2str (rx_types, "type %d", rxh->type));

  if (vflag > 1)
  {
    int firstflag = 0;

    PRINTF (" cid %08x call# %d seq %d ser %d",
            (int)ntohl(rxh->cid), (int)ntohl(rxh->callNumber),
            (int)ntohl(rxh->seq), (int)ntohl(rxh->serial));
    if (vflag > 2)
       PRINTF (" secindex %d serviceid %hu",
               (int)rxh->securityIndex, ntohs(rxh->serviceId));

    for (i = 0; i < NUM_RX_FLAGS; i++)
    {
      if (rxh->flags & rx_flags[i].v)
      {
        if (!firstflag)
        {
          firstflag = 1;
          PUTCHAR (' ');
        }
        else
          PUTCHAR (',');
        PRINTF ("<%s>", rx_flags[i].s);
      }
    }
  }

  /*
   * Try to handle AFS calls that we know about.  Check the destination
   * port and make sure it's a data packet.  Also, make sure the
   * seq number is 1 (because otherwise it's a continuation packet,
   * and we can't interpret that).  Also, seems that reply packets
   * do not have the client-init flag set, so we check for that
   * as well.
   */
  if (rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1 &&
      rxh->flags & RX_CLIENT_INITIATED)
  {
    /*
     * Insert this call into the call cache table, so we
     * have a chance to print out replies
     */
    rx_cache_insert (bp, (const struct ip*)bp2, dport, length);

    switch (dport)
    {
      case FS_RX_PORT:       /* AFS file service */
           fs_print (bp, length);
           break;
      case CB_RX_PORT:       /* AFS callback service */
           cb_print (bp, length);
           break;
      case PROT_RX_PORT:     /* AFS protection service */
           prot_print (bp, length);
           break;
      case VLDB_RX_PORT:     /* AFS VLDB service */
           vldb_print (bp, length);
           break;
      case KAUTH_RX_PORT:    /* AFS Kerberos auth service */
           kauth_print (bp, length);
           break;
      case VOL_RX_PORT:      /* AFS Volume service */
           vol_print (bp, length);
           break;
      case BOS_RX_PORT:      /* AFS BOS service */
           bos_print (bp, length);
           break;
      default:
           ;
    }

    /*
     * If it's a reply (client-init is _not_ set, but seq is one)
     * then look it up in the cache.  If we find it, call the reply
     * printing functions  Note that we handle abort packets here,
     * because printing out the return code can be useful at times.
     */
  }
  else if (((rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1) ||
            rxh->type == RX_PACKET_TYPE_ABORT) &&
           (rxh->flags & RX_CLIENT_INITIATED) == 0 &&
            rx_cache_find (rxh, (const struct ip*)bp2, sport, &opcode))
  {
    switch (sport)
    {
      case FS_RX_PORT:      /* AFS file service */
           fs_reply_print (bp, length, opcode);
           break;
      case CB_RX_PORT:      /* AFS callback service */
           cb_reply_print (bp, length, opcode);
           break;
      case PROT_RX_PORT:    /* AFS PT service */
           prot_reply_print (bp, length, opcode);
           break;
      case VLDB_RX_PORT:    /* AFS VLDB service */
           vldb_reply_print (bp, length, opcode);
           break;
      case KAUTH_RX_PORT:    /* AFS Kerberos auth service */
           kauth_reply_print (bp, length, opcode);
           break;
      case VOL_RX_PORT:      /* AFS Volume service */
           vol_reply_print (bp, length, opcode);
           break;
      case BOS_RX_PORT:      /* AFS BOS service */
           bos_reply_print (bp, length, opcode);
           break;
    }
  }
  PRINTF (" (%d)", length);
}

/*
 * Insert an entry into the cache.  Taken from print-nfs.c
 */
static void rx_cache_insert (const u_char *bp, const struct ip *ip, int dport, int length)
{
  struct rx_cache_entry *rxent;
  const  struct rx_header *rxh = (const struct rx_header *) bp;

  if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t))
     return;

  rxent = &rx_cache[rx_cache_next];

  if (++rx_cache_next >= RX_CACHE_SIZE)
    rx_cache_next = 0;

  rxent->callnum   = rxh->callNumber;
  rxent->client    = ip->ip_src;
  rxent->server    = ip->ip_dst;
  rxent->dport     = dport;
  rxent->serviceId = rxh->serviceId;
  rxent->opcode    = ntohl (*((int*)(bp+sizeof(struct rx_header))));
}

/*
 * Lookup an entry in the cache.  Also taken from print-nfs.c
 *
 * Note that because this is a reply, we're looking at the _source_
 * port.
 */
static int rx_cache_find (const struct rx_header *rxh, const struct ip *ip, int sport, int32_t *opcode)
{
  struct rx_cache_entry *rxent;
  u_int32_t clip = ip->ip_dst.s_addr;
  u_int32_t sip  = ip->ip_src.s_addr;

  /* Start the search where we last left off
   */
  int i = rx_cache_hint;
  do
  {
    rxent = &rx_cache[i];
    if (rxent->callnum == rxh->callNumber  &&
        rxent->client.s_addr == clip       &&
        rxent->server.s_addr == sip        &&
        rxent->serviceId == rxh->serviceId &&
        rxent->dport == sport)
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -