Ejemplo n.º 1
0
/* Code to actually dissect the packets */
static void
dissect_mdshdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

/* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti_main, *ti_hdr, *ti_trlr;
    proto_item *hidden_item; 
    proto_tree *mdshdr_tree_main, *mdshdr_tree_hdr, *mdshdr_tree_trlr;
    int offset = 0;
    guint    pktlen;
    tvbuff_t *next_tvb;
    guint8 sof, eof;
    guint16 vsan;
    guint8 span_id;
    int trailer_start = 0; /*0 means "no trailer found"*/

    /* Make entries in Protocol column and Info column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDS Header");
    
    col_clear(pinfo->cinfo, COL_INFO);

    sof = tvb_get_guint8 (tvb, offset+MDSHDR_SOF_OFFSET) & 0x0F;
    pktlen = tvb_get_ntohs (tvb, offset+MDSHDR_PKTLEN_OFFSET) & 0x1FFF;
    vsan = tvb_get_ntohs (tvb, offset+MDSHDR_VSAN_OFFSET) & 0x0FFF;
    span_id = (tvb_get_ntohs (tvb, offset+MDSHDR_VSAN_OFFSET) & 0xF000) >> 12;
    
    /* The Mdshdr trailer is at the end of the frame */
    if (tvb_length (tvb) >= MDSHDR_HEADER_SIZE + pktlen
     /* Avoid header/trailer overlap if something wrong */
     && pktlen >= MDSHDR_TRAILER_SIZE ) {
        trailer_start = MDSHDR_HEADER_SIZE + pktlen - MDSHDR_TRAILER_SIZE; 
    
        eof = tvb_get_guint8 (tvb, trailer_start);
        tvb_set_reported_length (tvb, MDSHDR_HEADER_SIZE+pktlen);
    }
    else {
        eof = MDSHDR_EOF_UNKNOWN;
    }

    pinfo->src_idx = (tvb_get_ntohs (tvb, MDSHDR_SIDX_OFFSET) & 0x3FF);
    pinfo->dst_idx = (tvb_get_ntohs (tvb, MDSHDR_DIDX_OFFSET) & 0xFFC) >> 2;
    pinfo->vsan = vsan;
    pinfo->sof_eof = 0;

    if ((sof == MDSHDR_SOFi3) || (sof == MDSHDR_SOFi2) || (sof == MDSHDR_SOFi1)
        || (sof == MDSHDR_SOFi4)) {
        pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
    }
    else if (sof == MDSHDR_SOFf) {
        pinfo->sof_eof = PINFO_SOF_SOFF;      
    }

    if (eof != MDSHDR_EOFn) {
        pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
    }
    else if (eof != MDSHDR_EOFt) {
        pinfo->sof_eof |= PINFO_EOF_INVALID;
    }
    
    /* In the interest of speed, if "tree" is NULL, don't do any work not
       necessary to generate protocol tree items. */
    if (tree) {

        /* create display subtree for the protocol */
        ti_main = proto_tree_add_protocol_format (tree, proto_mdshdr, tvb, 0,
                                                  MDSHDR_HEADER_SIZE+pktlen,
                                                  "MDS Header(%s/%s)", 
						  val_to_str(sof, sof_vals, "Unknown(%u)"),
                                                  val_to_str(eof, eof_vals, "Unknown(%u)"));

        mdshdr_tree_main = proto_item_add_subtree (ti_main, ett_mdshdr);

        /* Add Header part as subtree first */
        ti_hdr = proto_tree_add_text (mdshdr_tree_main, tvb, MDSHDR_VER_OFFSET,
                                      MDSHDR_HEADER_SIZE, "MDS Header");

        mdshdr_tree_hdr = proto_item_add_subtree (ti_hdr, ett_mdshdr_hdr);
        hidden_item = proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_sof, tvb, MDSHDR_SOF_OFFSET,
                                    MDSHDR_SIZE_BYTE, 0);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_pkt_len, tvb, MDSHDR_PKTLEN_OFFSET, 
                             MDSHDR_SIZE_INT16, 0);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_dstidx, tvb, MDSHDR_DIDX_OFFSET,
                             MDSHDR_SIZE_INT16, 0);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_srcidx, tvb, MDSHDR_SIDX_OFFSET,
                             MDSHDR_SIZE_INT16, 0);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_vsan, tvb, MDSHDR_VSAN_OFFSET,
                             MDSHDR_SIZE_INT16, 0);
        hidden_item = proto_tree_add_uint(mdshdr_tree_hdr, hf_mdshdr_span,
                                   tvb, MDSHDR_VSAN_OFFSET,
                                   MDSHDR_SIZE_BYTE, span_id);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        
        /* Add Mdshdr Trailer part */
        if (tvb_length (tvb) >= MDSHDR_HEADER_SIZE + pktlen
         && 0 != trailer_start) {
            ti_trlr = proto_tree_add_text (mdshdr_tree_main, tvb, trailer_start,
                                           MDSHDR_TRAILER_SIZE,
                                           "MDS Trailer");
            mdshdr_tree_trlr = proto_item_add_subtree (ti_trlr, ett_mdshdr_trlr);
        
            proto_tree_add_item (mdshdr_tree_trlr, hf_mdshdr_eof, tvb,
                                 trailer_start, MDSHDR_SIZE_BYTE, 0);
            proto_tree_add_item (mdshdr_tree_trlr, hf_mdshdr_fccrc, tvb,
                                 trailer_start+2, MDSHDR_SIZE_INT32, 0);
        }
        else {
            proto_tree_add_text (mdshdr_tree_main, tvb, 0, 0, "MDS Trailer: Not Found");        
        }
    }
    
    /* If this protocol has a sub-dissector call it here, see section 1.8 */
    if (tvb_length (tvb) >= MDSHDR_HEADER_SIZE + pktlen
     && 0 != pktlen /*if something wrong*/) {
        next_tvb = tvb_new_subset (tvb, MDSHDR_HEADER_SIZE, pktlen, pktlen);
        /* XXX what to do with the rest of this frame? --ArtemTamazov */
    }
    else {
        next_tvb = tvb_new_subset_remaining (tvb, MDSHDR_HEADER_SIZE);
    }

    /* Call the Fibre Channel dissector */
    if (fc_dissector_handle) {
        call_dissector (fc_dissector_handle, next_tvb, pinfo, tree);
    }
    else {
        call_dissector (data_handle, next_tvb, pinfo, tree);
    }
}
Ejemplo n.º 2
0
static void
dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_hln;
  guint8      ar_pln;
  guint16     ar_op;
  int         tot_len;
  proto_tree  *arp_tree = NULL;
  proto_item  *ti, *item;
  const gchar *op_str;
  int         sha_offset, spa_offset, tha_offset, tpa_offset;
  const guint8      *spa_val, *tpa_val;
  gboolean    is_gratuitous;
  gboolean    duplicate_detected = FALSE;
  guint32     duplicate_ip = 0;

  /* Call it ARP, for now, so that if we throw an exception before
     we decide whether it's ARP or RARP or IARP or ATMARP, it shows
     up in the packet list as ARP.

     Clear the Info column so that, if we throw an exception, it
     shows up as a short or malformed ARP frame. */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
  col_clear(pinfo->cinfo, COL_INFO);

  /* Hardware Address Type */
  ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
  if (ar_hrd == ARPHRD_ATM2225) {
    call_dissector(atmarp_handle, tvb, pinfo, tree);
    return;
  }
  /* Protocol Address Type */
  ar_pro = tvb_get_ntohs(tvb, AR_PRO);
  /* Hardware Address Size */
  ar_hln = tvb_get_guint8(tvb, AR_HLN);
  /* Protocol Address Size */
  ar_pln = tvb_get_guint8(tvb, AR_PLN);
  /* Operation */
  ar_op  = tvb_get_ntohs(tvb, AR_OP);

  tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;

  /* Adjust the length of this tvbuff to include only the ARP datagram.
     Our caller may use that to determine how much of its packet
     was padding. */
  tvb_set_reported_length(tvb, tot_len);

  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
    switch (ar_op) {

      case ARPOP_REQUEST:
        if (global_arp_detect_request_storm)
        {
          request_seen(pinfo);
        }
	/* FALLTHRU */
      case ARPOP_REPLY:
      default:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
        break;

      case ARPOP_RREQUEST:
      case ARPOP_RREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
        break;

      case ARPOP_IREQUEST:
      case ARPOP_IREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
        break;
    }
  }

  /* Get the offsets of the addresses. */
  /* Source Hardware Address */
  sha_offset = MIN_ARP_HEADER_SIZE;
  /* Source Protocol Address */
  spa_offset = sha_offset + ar_hln;
  /* Target Hardware Address */
  tha_offset = spa_offset + ar_pln;
  /* Target Protocol Address */
  tpa_offset = tha_offset + ar_hln;

  if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
      ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
      ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {

    /* inform resolv.c module of the new discovered addresses */

    guint32 ip;
    const guint8 *mac;

    /* Add sender address if sender MAC address is neither a broadcast/
       multicast address nor an all-zero address and if sender IP address
       isn't all zeroes. */
    ip = tvb_get_ipv4(tvb, spa_offset);
    mac = tvb_get_ptr(tvb, sha_offset, 6);
    if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
    {
      add_ether_byip(ip, mac);
      if (global_arp_detect_duplicate_ip_addresses)
      {
        duplicate_detected =
          check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip,
                                        &duplicate_ip);
      }
    }

    /* Add target address if target MAC address is neither a broadcast/
       multicast address nor an all-zero address and if target IP address
       isn't all zeroes. */

    /* Do not add target address if the packet is a Request. According to the RFC,
       target addresses in requests have no meaning */

    ip = tvb_get_ipv4(tvb, tpa_offset);
    mac = tvb_get_ptr(tvb, tha_offset, 6);
    if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0
        && ar_op != ARPOP_REQUEST)
    {
      add_ether_byip(ip, mac);
      if (global_arp_detect_duplicate_ip_addresses)
      {
        duplicate_detected =
          check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip,
                                        &duplicate_ip);
      }
    }
  }

  if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
    /* We're not building a protocol tree and we're not setting the Info
       column, so we don't have any more work to do. */
    return;
  }

  spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);

  /* ARP requests/replies with the same sender and target protocol
     address are flagged as "gratuitous ARPs", i.e. ARPs sent out as,
     in effect, an announcement that the machine has MAC address
     XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to
     provoke complaints if some other machine has the same IPv4 address,
     replies are used to announce relocation of network address, like
     in failover solutions. */
  if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
    is_gratuitous = TRUE;
  else
    is_gratuitous = FALSE;

  if (check_col(pinfo->cinfo, COL_INFO)) {
    switch (ar_op) {
      case ARPOP_REQUEST:
	if (is_gratuitous)
          col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)",
                       arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
	else
          col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                       arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        break;
      case ARPOP_REPLY:
        if (is_gratuitous)
          col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)",
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        else
          col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro),
                       tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd));
        break;
      case ARPOP_RREQUEST:
      case ARPOP_IREQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s",
                     tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd),
                     tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd));
        break;
      case ARPOP_RREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                     tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd),
                     arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
        break;
      case ARPOP_IREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                     tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd),
                     arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        break;
      default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
        break;
    }
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, op_vals)))  {
      if (is_gratuitous && (ar_op == ARPOP_REQUEST))
        op_str = "request/gratuitous ARP";
      if (is_gratuitous && (ar_op == ARPOP_REPLY))
        op_str = "reply/gratuitous ARP";
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "Address Resolution Protocol (%s)", op_str);
    } else
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "Address Resolution Protocol (opcode 0x%04x)", ar_op);
    arp_tree = proto_item_add_subtree(ti, ett_arp);
    proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
    proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
    proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
    proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
    proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
    item = proto_tree_add_boolean(arp_tree, hf_arp_isgratuitous, tvb, 0, 0, is_gratuitous);
    PROTO_ITEM_SET_GENERATED(item);
    if (ar_hln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_HW_IS_ETHER(ar_hrd, ar_hln) ?
                          hf_arp_src_hw_mac :
                          hf_arp_src_hw,
                          tvb, sha_offset, ar_hln, FALSE);
    }
    if (ar_pln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_pln) ?
                          hf_arp_src_proto_ipv4 :
                          hf_arp_src_proto,
                          tvb, spa_offset, ar_pln, FALSE);
    }
    if (ar_hln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_HW_IS_ETHER(ar_hrd, ar_hln) ?
                          hf_arp_dst_hw_mac :
                          hf_arp_dst_hw,
                          tvb, tha_offset, ar_hln, FALSE);
    }
    if (ar_pln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_pln) ?
                          hf_arp_dst_proto_ipv4 :
                          hf_arp_dst_proto,
                          tvb, tpa_offset, ar_pln, FALSE);
    }
  }

  if (global_arp_detect_request_storm)
  {
    check_for_storm_count(tvb, pinfo, arp_tree);
  }

  if (duplicate_detected)
  {
    /* Also indicate in info column */
    if (check_col(pinfo->cinfo, COL_INFO))
    {
      col_append_fstr(pinfo->cinfo, COL_INFO, " (duplicate use of %s detected!)",
                      arpproaddr_to_str((guint8*)&duplicate_ip, 4, ETHERTYPE_IP));
    }
  }
}
Ejemplo n.º 3
0
/* Code to actually dissect the packets */
static void
dissect_brdwlk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

/* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti, *hidden_item;
    proto_tree *brdwlk_tree = NULL;
    tvbuff_t *next_tvb;
    guint8 error, eof, sof;
    int hdrlen = 2,
        offset = 0;
    gint len, reported_len, plen;
    guint16 pkt_cnt;
    gboolean dropped_packets;

    /* Make entries in Protocol column and Info column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Boardwalk");
    
    col_clear(pinfo->cinfo, COL_INFO);

    pinfo->vsan = (tvb_get_ntohs (tvb, offset) & 0xFFF);
    sof = (tvb_get_guint8 (tvb, offset) & 0xF0) >> 4;

    if ((sof == FCM_DELIM_SOFI3) || (sof == FCM_DELIM_SOFI2) || (sof == FCM_DELIM_SOFI1)
        || (sof == FCM_DELIM_SOFI4)) {
        pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
    }
    else if (sof == FCM_DELIM_SOFF) {
        pinfo->sof_eof = PINFO_SOF_SOFF;
    }

    if (tree) {
        ti = proto_tree_add_protocol_format (tree, proto_brdwlk, tvb, 0,
                                             hdrlen, "Boardwalk");

        brdwlk_tree = proto_item_add_subtree (ti, ett_brdwlk);

        proto_tree_add_item (brdwlk_tree, hf_brdwlk_sof, tvb, offset, 1, 0);
        proto_tree_add_item (brdwlk_tree, hf_brdwlk_vsan, tvb, offset, 2, 0);

    }

    /* Locate EOF which is the last 4 bytes of the frame */
    len = tvb_length_remaining(tvb, hdrlen);
    reported_len = tvb_reported_length_remaining(tvb, hdrlen);
    if (reported_len < 4) {
        /*
         * This packet is claimed not to even have enough data for
         * a 4-byte EOF.
         * Don't try to process the EOF.
         */
        ;
    }
    else if (len < reported_len) {
        /*
         * This packet is claimed to have enough data for a 4-byte EOF,
         * but we didn't capture all of the packet.
         * Slice off the 4-byte EOF from the reported length, and trim
         * the captured length so it's no more than the reported length;
         * that will slice off what of the EOF, if any, is in the
         * captured length.
         */
        reported_len -= 4;
        if (len > reported_len)
            len = reported_len;
    }
    else {
        /*
         * We have the entire packet, and it includes a 4-byte EOF.
         * Slice it off, and put it into the tree if we're building
         * a tree.
         */
        len -= 4;
        reported_len -= 4;
        offset = tvb_reported_length(tvb) - 4;
        pkt_cnt = tvb_get_ntohs (tvb, offset);
        if (tree) {
            proto_tree_add_uint (brdwlk_tree, hf_brdwlk_pktcnt, tvb, offset,
                                 2, pkt_cnt);
        }
        dropped_packets = FALSE;
        if (pinfo->fd->flags.visited) {
            /*
             * This isn't the first pass, so we can't use the global
             * "packet_count" variable to determine whether there were
             * any dropped frames or not.
             * We therefore attach a non-null pointer as frame data to
             * any frame preceded by dropped packets.
             */
            if (p_get_proto_data(pinfo->fd, proto_brdwlk) != NULL)
                dropped_packets = TRUE;
        } else {
            /*
             * This is the first pass, so we have to use the global
             * "packet_count" variable to determine whether there were
             * any dropped frames or not.
             *
             * XXX - can there be more than one stream of packets, so that
             * we can't just use a global variable?
             */
            if (pkt_cnt != packet_count + 1) {
                if (!first_pkt &&
                    (pkt_cnt != 0 || (packet_count != BRDWLK_MAX_PACKET_CNT))) {
                    dropped_packets = TRUE;

                    /*
                     * Mark this frame as having been preceded by dropped
                     * packets.  (The data we use as the frame data doesn't
                     * matter - it just matters that it's non-null.)
                     */
                    p_add_proto_data(pinfo->fd, proto_brdwlk, &packet_count);
                }
            }

            if (tree) {
                hidden_item = proto_tree_add_boolean (brdwlk_tree, hf_brdwlk_drop,
                                               tvb, offset, 0, dropped_packets);
                PROTO_ITEM_SET_HIDDEN(hidden_item);
            }
        }
        packet_count = pkt_cnt;

	error=tvb_get_guint8(tvb, offset+2);           
	dissect_brdwlk_err(brdwlk_tree, tvb, offset+2);

        eof = tvb_get_guint8 (tvb, offset+3);
        if (eof != FCM_DELIM_EOFN) {
            pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
        }
        else if (eof != FCM_DELIM_EOFT) {
            pinfo->sof_eof |= PINFO_EOF_INVALID;
        }
        
        if (tree) {
            proto_tree_add_item (brdwlk_tree, hf_brdwlk_eof, tvb, offset+3,
                                 1, 0);
        }

        if ((error & BRDWLK_HAS_PLEN) && tree) {
            /* In newer Boardwalks, if this bit is set, the actual frame length
             * is also provided. This length is the size between SOF & EOF
             * including FC CRC.
             */
            plen = tvb_get_ntohl (tvb, offset-4);
            plen *= 4;
            proto_tree_add_uint (brdwlk_tree, hf_brdwlk_plen, tvb, offset-4,
                                 4, plen);
            
#if 0
            /* XXX - this would throw an exception if it would increase
             * the reported length.
             */
            if (error & BRDWLK_TRUNCATED_BIT) {
                tvb_set_reported_length (tvb, plen);
            }
#endif
        }
    }
    
    next_tvb = tvb_new_subset (tvb, 2, len, reported_len);
    if (fc_dissector_handle) {
        call_dissector (fc_dissector_handle, next_tvb, pinfo, tree);
    }
}
Ejemplo n.º 4
0
/*
 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
 */
static void
dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_shtl;
  guint8      ar_shl;
  guint8      ar_sstl;
  guint8      ar_ssl;
  guint16     ar_op;
  guint8      ar_spln;
  guint8      ar_thtl;
  guint8      ar_thl;
  guint8      ar_tstl;
  guint8      ar_tsl;
  guint8      ar_tpln;
  int         tot_len;
  proto_tree  *arp_tree;
  proto_item  *ti;
  const gchar *op_str;
  int         sha_offset, ssa_offset, spa_offset;
  int         tha_offset, tsa_offset, tpa_offset;
  const guint8      *sha_val, *ssa_val, *spa_val;
  const guint8      *tha_val, *tsa_val, *tpa_val;
  const gchar       *sha_str, *ssa_str, *spa_str;
  const gchar       *tha_str, *tsa_str, *tpa_str;
  proto_tree  *tl_tree;
  proto_item  *tl;

  /* Override the setting to "ARP/RARP". */
  pinfo->current_proto = "ATMARP";

  ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
  ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
  ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
  ar_shl = ar_shtl & ATMARP_LEN_MASK;
  ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
  ar_ssl = ar_sstl & ATMARP_LEN_MASK;
  ar_op  = tvb_get_ntohs(tvb, AR_OP);
  ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
  ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
  ar_thl = ar_thtl & ATMARP_LEN_MASK;
  ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
  ar_tsl = ar_tstl & ATMARP_LEN_MASK;
  ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);

  tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
    ar_thl + ar_tsl + ar_tpln;

  /* Adjust the length of this tvbuff to include only the ARP datagram.
     Our caller may use that to determine how much of its packet
     was padding. */
  tvb_set_reported_length(tvb, tot_len);

  /* Extract the addresses.  */
  sha_offset = MIN_ATMARP_HEADER_SIZE;
  if (ar_shl != 0) {
    sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
    sha_str = atmarpnum_to_str(sha_val, ar_shtl);
  } else {
    sha_val = NULL;
    sha_str = "<No address>";
  }

  ssa_offset = sha_offset + ar_shl;
  if (ar_ssl != 0) {
    ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
    ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
  } else {
    ssa_val = NULL;
    ssa_str = NULL;
  }

  spa_offset = ssa_offset + ar_ssl;
  spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
  spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);

  tha_offset = spa_offset + ar_spln;
  if (ar_thl != 0) {
    tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
    tha_str = atmarpnum_to_str(tha_val, ar_thtl);
  } else {
    tha_val = NULL;
    tha_str = "<No address>";
  }

  tsa_offset = tha_offset + ar_thl;
  if (ar_tsl != 0) {
    tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
    tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
  } else {
    tsa_val = NULL;
    tsa_str = NULL;
  }

  tpa_offset = tsa_offset + ar_tsl;
  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
  tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);

  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
    switch (ar_op) {

      case ARPOP_REQUEST:
      case ARPOP_REPLY:
      case ATMARPOP_NAK:
      default:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
        break;

      case ARPOP_RREQUEST:
      case ARPOP_RREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
        break;

      case ARPOP_IREQUEST:
      case ARPOP_IREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
        break;
    }
  }

  if (check_col(pinfo->cinfo, COL_INFO)) {
    switch (ar_op) {
      case ARPOP_REQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                     tpa_str, spa_str);
        break;
      case ARPOP_REPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""));
        break;
      case ARPOP_IREQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
                     tha_str,
                     ((tsa_str != NULL) ? "," : ""),
                     ((tsa_str != NULL) ? tsa_str : ""),
                     sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""));
        break;
      case ARPOP_IREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
                     sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""),
                     spa_str);
        break;
      case ATMARPOP_NAK:
        col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
        break;
      default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
        break;
    }
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, atmop_vals)))
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "ATM Address Resolution Protocol (%s)",
                                          op_str);
    else
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
    arp_tree = proto_item_add_subtree(ti, ett_arp);

    proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);

    proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
                             "Sender ATM number type/length: %s/%u",
                             (ar_shtl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_shl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
    proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
                             "Sender ATM subaddress type/length: %s/%u",
                             (ar_sstl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_ssl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
    proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);

    proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);


    proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
                             "Target ATM number type/length: %s/%u",
                             (ar_thtl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_thl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
    proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
                             "Target ATM subaddress type/length: %s/%u",
                             (ar_tstl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_tsl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
    proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);

    proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);

    if (ar_shl != 0)
      dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
                         hf_atmarp_src_atm_num_nsap, arp_tree);

    if (ar_ssl != 0)
      proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
                                  ar_ssl,
                                  ssa_val,
                                  "Sender ATM subaddress: %s", ssa_str);

    if (ar_spln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
                          : hf_arp_src_proto,
                          tvb, spa_offset, ar_spln, FALSE);
    }

    if (ar_thl != 0)
      dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
                         hf_atmarp_dst_atm_num_nsap, arp_tree);

    if (ar_tsl != 0)
      proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
                                  ar_tsl,
                                  tsa_val,
                                  "Target ATM subaddress: %s", tsa_str);

    if (ar_tpln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
                          : hf_arp_dst_proto,
                          tvb, tpa_offset, ar_tpln, FALSE);
    }
  }
}
Ejemplo n.º 5
0
/* Code to actually dissect the packets */
static void
dissect_hsr_prp_supervision(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_tree *hsr_prp_supervision_tree;
    guint8 tlv_type;
    guint8 tlv_length;
    guint16 sup_version;
    int offset;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSR/PRP");

    /* may get modified later while parsing */
    col_set_str(pinfo->cinfo, COL_INFO, "HSR or PRP Supervision");

    /* create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_hsr_prp_supervision, tvb, 0, -1, ENC_NA);

    hsr_prp_supervision_tree = proto_item_add_subtree(ti, ett_hsr_prp_supervision);

    offset = 0;

    /* SupVersion */
    proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_path,
                        tvb, offset, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_version,
                        tvb, offset, 2, ENC_BIG_ENDIAN);
    sup_version = tvb_get_ntohs(tvb, 0) & 0x0fff;
    offset += 2;

    if (sup_version > 0) {
        /* SupSequenceNumber */
        proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_seqno,
                            tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
    }

    while (tvb_reported_length_remaining(tvb, offset) > 0) {
        /* TLV.type */
        tlv_type = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_tlv_type,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        /* TLV.length */
        tlv_length = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_tlv_length,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        /* TLV.value */
        if ((tlv_type == 20 || tlv_type == 21 || tlv_type == 23) && (tlv_length == 6 || tlv_length == 12)) {
            if (tlv_type == 23) {
                col_set_str(pinfo->cinfo, COL_INFO, "HSR Supervision");
            } else {
                col_set_str(pinfo->cinfo, COL_INFO, "PRP Supervision");
            }
            if (tlv_length == 12) {
                /* MacAddressA, MacAddressB (PRP only) */
                proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_source_mac_address_A,
                                    tvb, offset, 6, ENC_NA);
                proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_source_mac_address_B,
                                    tvb, offset+6, 6, ENC_NA);
                /* PRP-0 supervision: if the node is not a RedBox, we have
                   just read the last TLV. The next two octets are
                   required to be zero by PRP-0. We will dissect those as
                   "end of list" and break. */
            } else {
                /* MacAddress */
                proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_source_mac_address,
                                    tvb, offset, 6, ENC_NA);
            }
        } else if (tlv_type == 30 && tlv_length == 6) {
            /* RedBoxMacAddress */
            proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_red_box_mac_address,
                                tvb, offset, 6, ENC_NA);
            if (sup_version == 0) {
                /* PRP-0 supervision: end of TLV data. Stop now, don't
                   interpret the padding. */
                offset += tlv_length;
                break;
            }
        } else if (tlv_type == 31 && tlv_length == 6) {
            /* VdanMacAddress */
            proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_vdan_mac_address,
                                tvb, offset, 6, ENC_NA);
            if (sup_version == 0) {
                /* PRP-0 supervision: end of TLV data, padding starts */
                offset += tlv_length;
                break;
            }
        } else if (tlv_type == 0) {
            /* End of TLV list. */
            offset += tlv_length;
            break;
        } else {
            /* unknown TLV.type, or unexpected TLV.length */
        }
        offset += tlv_length;
    }

    proto_item_set_len(ti, offset);
    /* Adjust the length of this tvbuff to include only the supervision data.
       This allows the rest to be marked as padding. */
    tvb_set_reported_length(tvb, offset);
}