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

📄 _pim.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 1995, 1996
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
 * the University nor the names of its contributors may be used to endorse
 * or promote products derived from this software without specific prior
 * written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#if 0
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.15.2.1 2000/01/25 18:29:05 itojun Exp $ (LBL)";
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>

#include "interfac.h"
#include "a2name.h"
#include "extract.h"

/*
 * XXX: We consider a case where IPv6 is not ready yet for portability,
 * but PIM dependent defintions should be independent of IPv6...
 */

struct pim
{
  u_int8_t pim_typever;
  /* upper 4bit: the PIM message type, currently they are:
   * Hello, Register, Register-Stop, Join/Prune,
   * Bootstrap, Assert, Graft (PIM-DM only),
   * Graft-Ack (PIM-DM only), C-RP-Adv
   */
  /* lower 4bit: PIM version number; 2 for PIMv2
   */
#define PIM_TYPE(x)    (((x) & 0xf0) >> 4)
#define PIM_VER(x)     ((x) & 0x0f)
  u_char  pim_rsv;     /* Reserved */
  u_short pim_cksum;   /* IP style check sum */
};


static void pimv2_print (const u_char * bp, u_int len);

static void pimv1_join_prune_print (const u_char * bp, u_int len)
{
  int maddrlen, addrlen, ngroups, njoin, nprune;
  int njp;

  /* If it's a single group and a single source, use 1-line output. */
  if (TTEST2 (bp[0], 30) && bp[11] == 1 && ((njoin = EXTRACT_16BITS (&bp[20])) + EXTRACT_16BITS (&bp[22])) == 1)
  {
    int hold;

    PRINTF (" RPF %s ", ipaddr_string (bp));
    hold = EXTRACT_16BITS (&bp[6]);
    if (hold != 180)
    {
      PUTS ("Hold ");
      relts_print (hold);
    }
    PRINTF ("%s (%s/%d, %s", njoin ? "Join" : "Prune",
            ipaddr_string (&bp[26]), bp[25] & 0x3f,
            ipaddr_string (&bp[12]));
    if (EXTRACT_32BITS (&bp[16]) != 0xffffffff)
       PRINTF ("/%s", ipaddr_string (&bp[16]));
    PRINTF (") %s%s %s",
            (bp[24] & 0x01) ? "Sparse" : "Dense",
            (bp[25] & 0x80) ? " WC"    : "",
            (bp[25] & 0x40) ? "RP"     : "SPT");
    return;
  }

  TCHECK2 (bp[0], 4);
  PRINTF ("\n Upstream Nbr: %s", ipaddr_string (bp));

  TCHECK2 (bp[6], 2);
  PUTS ("\n Hold time: ");
  relts_print (EXTRACT_16BITS (&bp[6]));
  bp  += 8;
  len -= 8;

  TCHECK2 (bp[0], 4);
  maddrlen = bp[1];
  addrlen  = bp[2];
  ngroups  = bp[3];
  bp  += 4;
  len -= 4;

  while (ngroups--)
  {
    TCHECK2 (bp[0], 4);
    PRINTF ("\n\tGroup: %s", ipaddr_string (bp));
    if (EXTRACT_32BITS (&bp[4]) != 0xffffffff)
       PRINTF ("/%s", ipaddr_string (&bp[4]));
    TCHECK2 (bp[8], 4);
    njoin  = EXTRACT_16BITS (&bp[8]);
    nprune = EXTRACT_16BITS (&bp[10]);
    PRINTF (" joined: %d pruned: %d", njoin, nprune);
    bp  += 12;
    len -= 12;
    for (njp = 0; njp < (njoin + nprune); njp++)
    {
      char *type;

      if (njp < njoin)
           type = "Join ";
      else type = "Prune";

      TCHECK2 (bp[0], 6);
      PRINTF ("\n\t%s %s%s%s%s/%d", type,
              (bp[0] & 0x01) ? "Sparse " : "Dense ",
              (bp[1] & 0x80) ? "WC "     : "",
              (bp[1] & 0x40) ? "RP "     : "SPT ",
              ipaddr_string (&bp[2]), bp[1] & 0x3f);
      bp  += 6;
      len -= 6;
    }
  }
  return;

trunc:
  PUTS ("[|pim]");
}

void pimv1_print (const u_char * bp, u_int len)
{
  const u_char *ep = (const u_char *) snapend;
  u_char        type;

  if (bp >= ep)
     return;

  type = bp[1];

  switch (type)
  {
    case 0:
         PUTS (" Query");
         if (TTEST (bp[8]))
         {
           switch (bp[8] >> 4)
           {
             case 0:
                  PUTS (" Dense-mode");
                  break;
             case 1:
                  PUTS (" Sparse-mode");
                  break;
             case 2:
                  PUTS (" Sparse-Dense-mode");
                  break;
             default:
                  PRINTF (" mode-%d", bp[8] >> 4);
                  break;
           }
         }
         if (vflag)
         {
           TCHECK2 (bp[10], 2);
           PUTS (" (Hold-time ");
           relts_print (EXTRACT_16BITS (&bp[10]));
           PUTCHAR (')');
         }
         break;

    case 1:
         PUTS (" Register");
         TCHECK2 (bp[8], 20);    /* ip header */
         PRINTF (" for %s > %s",
                 ipaddr_string (&bp[20]),
                 ipaddr_string (&bp[24]));
         break;

    case 2:
         PUTS (" Register-Stop");
         TCHECK2 (bp[12], 4);
         PRINTF (" for %s > %s",
                 ipaddr_string (&bp[8]),
                 ipaddr_string (&bp[12]));
         break;

    case 3:
         PUTS (" Join/Prune");
         if (vflag)
            pimv1_join_prune_print (&bp[8], len - 8);
         break;

    case 4:
         PUTS (" RP-reachable");
         if (vflag)
         {
           TCHECK2 (bp[22], 2);
           PRINTF (" group %s", ipaddr_string (&bp[8]));
           if (EXTRACT_32BITS (&bp[12]) != 0xffffffff)
              PRINTF ("/%s", ipaddr_string (&bp[12]));
           PRINTF (" RP %s hold ", ipaddr_string (&bp[16]));
           relts_print (EXTRACT_16BITS (&bp[22]));
         }
         break;

    case 5:
         PUTS (" Assert");
         TCHECK2 (bp[16], 4);
         PRINTF (" for %s > %s",
                 ipaddr_string (&bp[16]),
                 ipaddr_string (&bp[8]));
         if (EXTRACT_32BITS (&bp[12]) != 0xffffffff)
            PRINTF ("/%s", ipaddr_string (&bp[12]));
         TCHECK2 (bp[24], 4);
         PRINTF (" %s pref %d metric %d",
                 (bp[20] & 0x80) ? "RP-tree" : "SPT",
                 EXTRACT_32BITS (&bp[20]) & 0x7fffffff,
                 EXTRACT_32BITS (&bp[24]));
         break;

    case 6:
         PUTS (" Graft");
         if (vflag)
            pimv1_join_prune_print (&bp[8], len - 8);
         break;

    case 7:
         PUTS (" Graft-ACK");
         if (vflag)
            pimv1_join_prune_print (&bp[8], len - 8);
         break;

    case 8:
         PUTS (" Mode");
         break;

    default:
         PRINTF (" [type %d]", type);
         break;
  }
  if ((bp[4] >> 4) != 1)
     PRINTF (" [v%d]", bp[4] >> 4);
  return;

trunc:
  PUTS ("[|pim]");
}

/*
 * auto-RP is a cisco protocol, documented at
 * ftp://ftpeng.cisco.com/ipmulticast/pim-autorp-spec01.txt
 */
void cisco_autorp_print (const u_char * bp, u_int len)
{
  int type, numrps, hold;

  TCHECK (bp[0]);
  PUTS (" auto-rp ");
  type = bp[0];
  switch (type)
  {
    case 0x11:
         PUTS ("candidate-advert");
         break;
    case 0x12:
         PUTS ("mapping");
         break;
    default:
         PRINTF ("type-0x%02x", type);
         break;
  }

  TCHECK (bp[1]);
  numrps = bp[1];

  TCHECK2 (bp[2], 2);
  PUTS (" Hold ");
  hold = EXTRACT_16BITS (&bp[2]);
  if (hold)
       relts_print (EXTRACT_16BITS (&bp[2]));
  else PUTS ("FOREVER");

  /* Next 4 bytes are reserved.
   */
  bp  += 8;
  len -= 8;

  /* XXX skip unless -v? */

  /*
   * Rest of packet:
   * numrps entries of the form:
   * 32 bits: RP
   * 6 bits: reserved
   * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
   * 8 bits: # of entries for this RP
   * each entry: 7 bits: reserved, 1 bit: negative,
   *             8 bits: mask 32 bits: source
   * lather, rinse, repeat.
   */
  while (numrps--)
  {
    int  nentries;
    char s;

    TCHECK2 (bp[0], 4);
    PRINTF (" RP %s", ipaddr_string (bp));
    TCHECK (bp[4]);
    switch (bp[4] & 0x3)
    {
      case 0:
           PUTS (" PIMv?");
           break;
      case 1:
           PUTS (" PIMv1");
           break;
      case 2:
           PUTS (" PIMv2");
           break;
      case 3:
           PUTS (" PIMv1+2");
           break;
    }
    TCHECK (bp[5]);
    nentries = bp[5];
    bp  += 6;
    len -= 6;
    s = ' ';
    for (; nentries; nentries--)
    {
      TCHECK2 (bp[0], 6);
      PRINTF ("%c%s%s/%d", s, bp[0] & 1 ? "!" : "",
              ipaddr_string (&bp[2]), bp[1]);
      s = ',';
      bp  += 6;
      len -= 6;
    }
  }
  return;

trunc:
  PUTS ("[|autorp]");
}

void pim_print (const u_char * bp, u_int len)
{
  const u_char *ep  = (const u_char *) snapend;
  struct pim   *pim = (struct pim *) bp;

  if (bp >= ep)
     return;

#ifdef notyet          /* currently we see only version and type */
  TCHECK (pim->pim_rsv);
#endif

  switch (PIM_VER (pim->pim_typever))
  {
    case 2:                  /* avoid hardcoding? */
         PUTS ("v2");
         pimv2_print (bp, len);
         break;
    default:
         PRINTF ("v%d", PIM_VER (pim->pim_typever));
         break;
  }
}

/*
 * PIMv2 uses encoded address representations.
 *
 * The last PIM-SM I-D before RFC2117 was published specified the
 * following representation for unicast addresses.  However, RFC2117
 * specified no encoding for unicast addresses with the unicast
 * address length specified in the header.  Therefore, we have to
 * guess which encoding is being used (Cisco's PIMv2 implementation
 * uses the non-RFC encoding).  RFC2117 turns a previously "Reserved"
 * field into a 'unicast-address-length-in-bytes' field.  We guess
 * that it's the draft encoding if this reserved field is zero.
 *
 * RFC2362 goes back to the encoded format, and calls the addr length
 * field "reserved" again.
 *
 * The first byte is the address family, from:
 *
 *    0    Reserved
 *    1    IP (IP version 4)
 *    2    IP6 (IP version 6)
 *    3    NSAP
 *    4    HDLC (8-bit multidrop)
 *    5    BBN 1822
 *    6    802 (includes all 802 media plus Ethernet "canonical format")
 *    7    E.163
 *    8    E.164 (SMDS, Frame Relay, ATM)
 *    9    F.69 (Telex)
 *   10    X.121 (X.25, Frame Relay)
 *   11    IPX
 *   12    Appletalk
 *   13    Decnet IV
 *   14    Banyan Vines
 *   15    E.164 with NSAP format subaddress
 *
 * In addition, the second byte is an "Encoding".  0 is the default
 * encoding for the address family, and no other encodings are currently
 * specified.
 *
 */

static int pimv2_addr_len;

enum pimv2_addrtype {
     pimv2_unicast, pimv2_group, pimv2_source
   };

#if 0
static char *addrtypestr[] = {
            "unicast", "group", "source"
};
#endif

/*  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | Addr Family   | Encoding Type |     Unicast Address           |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | Addr Family   | Encoding Type |   Reserved    |  Mask Len     |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                Group multicast Address                        |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | Addr Family   | Encoding Type | Rsrvd   |S|W|R|  Mask Len     |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                        Source Address                         |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
static int pimv2_addr_print (const u_char *bp, enum pimv2_addrtype at, int silent)
{
  char *afstr;
  int   af, len, hdrlen;

  TCHECK (bp[0]);

  if (pimv2_addr_len == 0)
  {
    TCHECK (bp[1]);
    switch (bp[0])
    {
      case 1:
           af = AF_INET;
           afstr = "IPv4";
           len = 4;
           break;
#ifdef USE_INET6
      case 2:
           af = AF_INET6;
           afstr = "IPv6";
           len = 16;
           break;
#endif
      default:
           return -1;
    }
    if (bp[1] != 0)
       return -1;
    hdrlen = 2;
  }
  else
  {
    switch (pimv2_addr_len)
    {
      case 4:
           af = AF_INET;
           afstr = "IPv4";
           break;
#ifdef USE_INET6
      case 16:
           af = AF_INET6;
           afstr = "IPv6";
           break;
#endif
      default:
           return -1;
    }
    len = pimv2_addr_len;
    hdrlen = 0;
  }

⌨️ 快捷键说明

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