Example #1
0
static void
dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint8 sio;
  guint8 service_indicator;
  tvbuff_t *payload_tvb = NULL;

  sio               = tvb_get_guint8(tvb, SIO_OFFSET);
  service_indicator = sio & SERVICE_INDICATOR_MASK;

  switch (mtp3_standard) {
  case ITU_STANDARD:
    payload_tvb = tvb_new_subset_remaining(tvb, ITU_MTP_PAYLOAD_OFFSET);
    break;
  case ANSI_STANDARD:
  case CHINESE_ITU_STANDARD:
    payload_tvb = tvb_new_subset_remaining(tvb, ANSI_MTP_PAYLOAD_OFFSET);
    break;
  case JAPAN_STANDARD:
    payload_tvb = tvb_new_subset_remaining(tvb, JAPAN_MTP_PAYLOAD_OFFSET);
    break;
  default:
    DISSECTOR_ASSERT_NOT_REACHED();
  }

  col_set_str(pinfo->cinfo, COL_INFO, "DATA ");

  if (!dissector_try_uint(mtp3_sio_dissector_table, service_indicator, payload_tvb, pinfo, tree))
    call_dissector(data_handle, payload_tvb, pinfo, tree);
}
Example #2
0
static void
mtp3_pc_to_str_buf(const guint32 pc, gchar *buf, int buf_len)
{
  switch (mtp3_standard)
  {
    case ITU_STANDARD:
      switch (itu_pc_structure) {
        case ITU_PC_STRUCTURE_NONE:
          g_snprintf(buf, buf_len, "%u", pc);
          break;
        case ITU_PC_STRUCTURE_3_8_3:
          /* this format is used in international ITU networks */
          g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0);
          break;
        case ITU_PC_STRUCTURE_4_3_4_3:
          /* this format is used in some national ITU networks, the German one for example. */
          g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0);
          break;
        default:
          DISSECTOR_ASSERT_NOT_REACHED();
      }
      break;
    case ANSI_STANDARD:
    case CHINESE_ITU_STANDARD:
      g_snprintf(buf, buf_len, "%u-%u-%u", (pc & ANSI_NETWORK_MASK) >> 16, (pc & ANSI_CLUSTER_MASK) >> 8, (pc & ANSI_MEMBER_MASK));
      break;
    case JAPAN_STANDARD:
      switch (japan_pc_structure) {
        case JAPAN_PC_STRUCTURE_NONE:
          g_snprintf(buf, buf_len, "%u", pc);
          break;
        case JAPAN_PC_STRUCTURE_7_4_5:
          /* This format is specified by NTT */
          g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0xfe00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f));
          break;
        case JAPAN_PC_STRUCTURE_3_4_4_5:
          /* Where does this format come from? */
          g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0xe000)>>13, (pc & 0x1e00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f));
          break;
        default:
          DISSECTOR_ASSERT_NOT_REACHED();
      }
      break;
    default:
      DISSECTOR_ASSERT_NOT_REACHED();
  }
}
Example #3
0
static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
    tvbparse_elem_t* new_elem = NULL;
    int len = 0;
    int target_offset = offset;
#ifdef TVBPARSE_DEBUG
    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
#endif

    if ( offset + wanted->control.until.subelem->len > tt->end_offset )
        return -1;

    do {
        len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem,  &new_elem);
    } while(len < 0  && target_offset+1 < tt->end_offset);

    if (len >= 0) {

        new_elem->id = wanted->id;
        new_elem->next = NULL;
        new_elem->last = NULL;
        new_elem->wanted = wanted;
        new_elem->offset = offset;

        (*tok) = new_elem;

        switch (wanted->control.until.mode) {
            case TP_UNTIL_INCLUDE:
                new_elem->len = target_offset - offset - 1 + len;
#ifdef TVBPARSE_DEBUG
                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
#endif
                return target_offset - offset -1 + len;
            case TP_UNTIL_SPEND:
                new_elem->len = target_offset - offset - 1;
#ifdef TVBPARSE_DEBUG
                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
#endif
                return target_offset - offset - 1 + len;
            case TP_UNTIL_LEAVE:
                new_elem->len = target_offset - offset - 1;
#ifdef TVBPARSE_DEBUG
                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1);
#endif
                return target_offset - offset -1;
            default:
                DISSECTOR_ASSERT_NOT_REACHED();
                return -1;
        }

    } else {
        return -1;
    }
}
Example #4
0
static void
dissect_stt_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree)
{
    gboolean can_checksum = !pinfo->fragmented &&
                   tvb_bytes_exist(tvb, 0, tvb_reported_length(tvb));

    if (can_checksum && pref_check_checksum) {
        vec_t      cksum_vec[4];
        guint32    phdr[2];

        /* Set up the fields of the pseudo-header. */
        SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data,
                          pinfo->src.len);
        SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data,
                          pinfo->dst.len);
        switch (pinfo->src.type) {
        case AT_IPv4:
            phdr[0] = g_htonl((IP_PROTO_TCP<<16) + tvb_reported_length(tvb));
            SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4);
            break;

        case AT_IPv6:
            phdr[0] = g_htonl(tvb_reported_length(tvb));
            phdr[1] = g_htonl(IP_PROTO_TCP);
            SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8);
            break;

        default:
            /* STT runs only atop IPv4 and IPv6.... */
            DISSECTOR_ASSERT_NOT_REACHED();
            break;
        }
        SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, tvb_reported_length(tvb));

        proto_tree_add_checksum(stt_tree, tvb, 16, hf_stt_checksum, hf_stt_checksum_status, &ei_stt_checksum_bad, pinfo,
                             in_cksum(cksum_vec, 4), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
    } else {
        proto_tree_add_checksum(stt_tree, tvb, 16, hf_stt_checksum, hf_stt_checksum_status, &ei_stt_checksum_bad, pinfo,
                             0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
    }
}
Example #5
0
static void
dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree)
{
  guint32 label, dpc, opc;
  proto_item *label_item, *label_dpc_item, *label_opc_item;
  proto_item *hidden_item;
  proto_tree *label_tree;
  proto_tree *pc_subtree;
  int hf_dpc_string;
  int hf_opc_string;


  switch (mtp3_standard) {
  case ITU_STANDARD:
    label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label");
    label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);

    label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET);

    opc = (label & ITU_OPC_MASK) >> 14;
    dpc =  label & ITU_DPC_MASK;

    hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
    if (mtp3_pc_structured())
      proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc));
    if(mtp3_addr_dpc->ni == 0)
    {
      pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc);
      analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc);
	}


    label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
    if (mtp3_pc_structured())
      proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc));
    if(mtp3_addr_opc->ni == 0)
    {
      pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc);
      analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc);
	}

    proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
    break;

  case ANSI_STANDARD:
  case CHINESE_ITU_STANDARD:
    if (mtp3_standard == ANSI_STANDARD)
    {
      hf_dpc_string = hf_mtp3_ansi_dpc;
      hf_opc_string = hf_mtp3_ansi_opc;
    } else /* CHINESE_ITU_STANDARD */ {
      hf_dpc_string = hf_mtp3_chinese_dpc;
      hf_opc_string = hf_mtp3_chinese_opc;
    }

    /* Create the Routing Label Tree */
    label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label");
    label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);


    /* create and fill the DPC tree */
    dissect_mtp3_3byte_pc(tvb, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network,
			  hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc);
    /* Store dpc for mtp3_addr below */
    dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET);

    /* create and fill the OPC tree */
    dissect_mtp3_3byte_pc(tvb, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network,
			  hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc);
    /* Store opc for mtp3_addr below */
    opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET);

    /* SLS */
    if (mtp3_standard == ANSI_STANDARD) {
      if (mtp3_use_ansi_5_bit_sls)
	proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA);
      else
	proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA);
    } else /* CHINESE_ITU_STANDARD */ {
      proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA);
    }
    break;

  case JAPAN_STANDARD:
    label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, "Routing label");
    label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);

    label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET);
    if (mtp3_pc_structured()) {
      proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc));
    }

    label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET);
    if (mtp3_pc_structured()) {
      proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc));
    }

    hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    if (mtp3_use_japan_5_bit_sls) {
	proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
	proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
    } else {
	proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
	proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
    }

    break;
  default:
    DISSECTOR_ASSERT_NOT_REACHED();
  }

  mtp3_addr_opc->type = mtp3_standard;
  mtp3_addr_opc->pc = opc;
  SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);

  mtp3_addr_dpc->type = mtp3_standard;
  mtp3_addr_dpc->pc = dpc;
  SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc);
}
Example #6
0
/** Only tested for BER */
double asn1_get_real(const guint8 *real_ptr, gint len) {
  guint8 octet;
  const guint8 *p;
  guint8 *buf;
  double val = 0;

  /* 8.5.2    If the real value is the value zero,
   *          there shall be no contents octets in the encoding.
   */
  if (len < 1) return val;

  octet = real_ptr[0];
  p = real_ptr + 1;
  len -= 1;
  if (octet & 0x80) {  /* binary encoding */
    int i;
    gboolean Eneg;
    gint8 S; /* Sign */
    guint8 B; /* Base */
    guint8 F; /* scaling Factor */
    gint32 E = 0; /* Exponent (supported max 3 octets/24 bit) */
    guint64 N = 0; /* N (supported max 8 octets/64 bit) */

    guint8 lenE, lenN;

    if(octet & 0x40) S = -1; else S = 1;
    switch(octet & 0x30) {
      case 0x00: B = 2; break;
      case 0x10: B = 8; break;
      case 0x20: B = 16; break;
      case 0x30: /* Reserved */
      default:
        /* TODO Add some warning in tree about reserved value for Base */
        return 0;
    }
    F = (octet & 0x0c) >> 2;

    /* 8.5.6.4 Exponent length */
    lenE = (octet & 0x3) + 1;
    if(lenE == 4)
    {
      /* we can't handle exponents > 24 bits */
      /* TODO Next octet(s) define length of exponent */
      DISSECTOR_ASSERT_NOT_REACHED();
    }

    Eneg = (*p) & 0x80 ? TRUE : FALSE;
    for (i = 0; i < lenE; i++) {
      if(Eneg) {
        /* 2's complement: inverse bits */
        E = (E<<8) | ((guint8) ~(*p));
      } else {
        E = (E<<8) | *p;
      }
      p++;
    }
    if(Eneg) {
      /* 2's complement: ... and add 1 (and make negative of course) */
      E = -(E + 1);
    }

    lenN = len - lenE;
    if(lenN > 8)
    {
      /* we can't handle integers > 64 bits */
      DISSECTOR_ASSERT_NOT_REACHED();
    }
    for (i=0; i<lenN; i++) {
      N = (N<<8) | *p;
      p++;
    }
    val = (double) S * N * pow(2, F) * pow(B, E);
#ifdef DEBUG
    printf("S = %d, N = %lu, F = %u, B = %u, E = %d -> %f\n", S, N, F, B, E, Eneg, val);
#endif
  } else if (octet & 0x40) {  /* SpecialRealValue */
Example #7
0
/*
 * Name: dissect_esis()
 *
 * Description:
 *   Main entry area for esis de-mangling.  This will build the
 *   main esis tree data and call the sub-protocols as needed.
 *
 * Input:
 *   tvbuff *      : tvbuff referring to packet data
 *   packet_info * : info for current packet
 *   proto_tree *  : tree of display data.  May be NULL.
 *
 * Output:
 *   void, but we will add to the proto_tree if it is not NULL.
 */
static void
dissect_esis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  const char *pdu_type_string        = NULL;
  const char *pdu_type_format_string = "PDU Type      : %s (R:%s%s%s)";
  esis_hdr_t  ehdr;
  proto_item *ti;
  proto_tree *esis_tree    = NULL;
  guint8      variable_len;
  guint       tmp_uint     = 0;
  const char *cksum_status;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESIS");
  col_clear(pinfo->cinfo, COL_INFO);

  tvb_memcpy(tvb, (guint8 *)&ehdr, 0, sizeof ehdr);

  if (tree) {
    ti = proto_tree_add_item(tree, proto_esis, tvb, 0, -1, ENC_NA);
    esis_tree = proto_item_add_subtree(ti, ett_esis);

    if (ehdr.esis_version != ESIS_REQUIRED_VERSION){
      esis_dissect_unknown(tvb, esis_tree,
                           "Unknown ESIS version (%u vs %u)",
                           ehdr.esis_version, ESIS_REQUIRED_VERSION );
      return;
    }

    if (ehdr.esis_length < ESIS_HDR_FIXED_LENGTH) {
      esis_dissect_unknown(tvb, esis_tree,
                           "Bogus ESIS length (%u, must be >= %u)",
                           ehdr.esis_length, ESIS_HDR_FIXED_LENGTH );
      return;
    }
    proto_tree_add_uint( esis_tree, hf_esis_nlpi, tvb, 0, 1, ehdr.esis_nlpi );
    proto_tree_add_uint( esis_tree, hf_esis_length, tvb,
                         1, 1, ehdr.esis_length );
    proto_tree_add_uint( esis_tree, hf_esis_version, tvb, 2, 1,
                         ehdr.esis_version );
    proto_tree_add_uint( esis_tree, hf_esis_reserved, tvb, 3, 1,
                         ehdr.esis_reserved );

    pdu_type_string = val_to_str(ehdr.esis_type&OSI_PDU_TYPE_MASK,
                                 esis_vals, "Unknown (0x%x)");

    proto_tree_add_uint_format( esis_tree, hf_esis_type, tvb, 4, 1,
                                ehdr.esis_type,
                                pdu_type_format_string,
                                pdu_type_string,
                                (ehdr.esis_type&BIT_8) ? "1" : "0",
                                (ehdr.esis_type&BIT_7) ? "1" : "0",
                                (ehdr.esis_type&BIT_6) ? "1" : "0");

    tmp_uint = pntohs( ehdr.esis_holdtime );
    proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, tvb, 5, 2,
                               tmp_uint, "Holding Time  : %u seconds",
                               tmp_uint );

    tmp_uint = pntohs( ehdr.esis_checksum );

    switch (calc_checksum( tvb, 0, ehdr.esis_length, tmp_uint )) {

    case NO_CKSUM:
      cksum_status = "Not Used";
      break;

    case DATA_MISSING:
      cksum_status = "Not checkable - not all of packet was captured";
      break;

    case CKSUM_OK:
      cksum_status = "Is good";
      break;

    case CKSUM_NOT_OK:
      cksum_status = "Is wrong";
      break;

    default:
      cksum_status = NULL;
      DISSECTOR_ASSERT_NOT_REACHED();
    }
    proto_tree_add_uint_format( esis_tree, hf_esis_checksum, tvb, 7, 2,
                                tmp_uint, "Checksum      : 0x%x ( %s )",
                                tmp_uint, cksum_status );
  }


  /*
   * Let us make sure we use the same names for all our decodes
   * here.  First, dump the name into info column, and THEN
   * dispatch the sub-type.
   */
  if (check_col(pinfo->cinfo, COL_INFO)) {
    col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str( ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals,
                            "Unknown (0x%x)" ) );
  }

  variable_len = ehdr.esis_length - ESIS_HDR_FIXED_LENGTH;

  switch (ehdr.esis_type & OSI_PDU_TYPE_MASK) {
  case ESIS_ESH_PDU:
    esis_dissect_esh_pdu( variable_len, tvb, esis_tree);
    break;
  case ESIS_ISH_PDU:
    esis_dissect_ish_pdu( variable_len, tvb, esis_tree);
    break;
  case ESIS_RD_PDU:
    esis_dissect_redirect_pdu( variable_len, tvb, esis_tree);
    break;
  default:
    esis_dissect_unknown(tvb, esis_tree,
                         "Unknown ESIS packet type 0x%x",
                         ehdr.esis_type & OSI_PDU_TYPE_MASK );
  }
} /* dissect_esis */
Example #8
0
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
    gcp_trx_t* t = NULL;
    gcp_trx_msg_t* trxmsg;

    if ( !m ) return NULL;

    if (keep_persistent_data) {
        if (m->commited) {

            for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
                if (trxmsg->trx && trxmsg->trx->id == t_id) {
                    return trxmsg->trx;
                }
            }
            DISSECTOR_ASSERT_NOT_REACHED();
        } else {
            emem_tree_key_t key[] = {
                {1,&(m->hi_addr)},
                {1,&(m->lo_addr)},
                {1,&(t_id)},
                {0,NULL}
            };

            trxmsg = se_alloc(sizeof(gcp_trx_msg_t));
            t = se_tree_lookup32_array(trxs,key);

            if (!t) {
                t = se_alloc(sizeof(gcp_trx_t));
                t->initial = m;
                t->id = t_id;
                t->type = type;
                t->pendings = 0;
                t->error = 0;
                t->cmds = NULL;

                se_tree_insert32_array(trxs,key,t);
            }

            /* XXX: request, reply and ack + point to frames where they are */
            switch ( type ) {
                case GCP_TRX_PENDING:
                    t->pendings++;
                    break;
                default:
                    break;
            }

        }
    } else {
        t = ep_new(gcp_trx_t);
        trxmsg = ep_new(gcp_trx_msg_t);
        t->initial = NULL;
        t->id = t_id;
        t->type = type;
        t->pendings = 0;
        t->error = 0;
        t->cmds = NULL;
    }

    DISSECTOR_ASSERT(trxmsg);

    trxmsg->trx = t;
    trxmsg->next = NULL;
    trxmsg->last = trxmsg;

    if (m->trxs) {
        m->trxs->last = m->trxs->last->next = trxmsg;
    } else {
        m->trxs = trxmsg;
    }

    return t;
}
Example #9
0
/*
 * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03
 * (when PIM is run over IPv6, the rules for computing the PIM checksum
 * from the draft in question, not from RFC 2362, should be used).
 */
static void
dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    int offset = 0;
    guint8 pim_typever;
    guint length, pim_length;
    guint16 pim_cksum, computed_cksum;
    vec_t cksum_vec[4];
    guint32 phdr[2];
    const char *typestr;
    proto_tree *pim_tree = NULL;
    proto_item *ti;
    proto_tree *pimopt_tree = NULL;
    proto_item *tiopt;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM");
    col_clear(pinfo->cinfo, COL_INFO);

    pim_typever = tvb_get_guint8(tvb, 0);

    switch (PIM_VER(pim_typever)) {
    case 2:
        typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)");
        break;
    case 1:     /* PIMv1 - we should never see this */
    default:
        typestr = "Unknown";
        break;
    }

    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
        col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d",
                     PIM_VER(pim_typever));
    }
    if (check_col(pinfo->cinfo, COL_INFO))
        col_add_str(pinfo->cinfo, COL_INFO, typestr);

    ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA);
    pim_tree = proto_item_add_subtree(ti, ett_pim);

    proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, ENC_NA);
    pim_cksum = tvb_get_ntohs(tvb, offset + 2);
    length = tvb_length(tvb);
    if (PIM_VER(pim_typever) == 2) {
        /*
         * Well, it's PIM v2, so we can check whether this is a Register
         * message, and thus can figure out how much to checksum and
         * whether to make the columns read-only.
         */
        if (PIM_TYPE(pim_typever) == 1) {
            /*
             * Register message - the PIM header is 8 bytes long.
             * Also set the columns non-writable. Otherwise the IPv4 or
             * IPv6 dissector for the encapsulated packet that caused
             * this register will overwrite the PIM info in the columns.
             */
            pim_length = 8;
            col_set_writable(pinfo->cinfo, FALSE);
        } else {
            /*
             * Other message - checksum the entire packet.
             */
            pim_length = tvb_reported_length(tvb);
        }
    } else {
        /*
         * We don't know what type of message this is, so say that
         * the length is 0, to force it not to be checksummed.
         */
        pim_length = 0;
    }
    if (!pinfo->fragmented && length >= pim_length) {
        /*
         * The packet isn't part of a fragmented datagram and isn't
         * truncated, so we can checksum it.
         */

        switch (pinfo->src.type) {
        case AT_IPv4:
            cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
            cksum_vec[0].len = pim_length;
            computed_cksum = in_cksum(&cksum_vec[0], 1);
            break;
        case AT_IPv6:
            /* Set up the fields of the pseudo-header. */
            cksum_vec[0].ptr = pinfo->src.data;
            cksum_vec[0].len = pinfo->src.len;
            cksum_vec[1].ptr = pinfo->dst.data;
            cksum_vec[1].len = pinfo->dst.len;
            cksum_vec[2].ptr = (const guint8 *)&phdr;
            phdr[0] = g_htonl(pim_length);
            phdr[1] = g_htonl(IP_PROTO_PIM);
            cksum_vec[2].len = 8;
            cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length);
            cksum_vec[3].len = pim_length;
            computed_cksum = in_cksum(&cksum_vec[0], 4);
            break;
        default:
            /* PIM is available for IPv4 and IPv6 right now */
            computed_cksum = 0; /* squelch GCC complaints */
            DISSECTOR_ASSERT_NOT_REACHED();
            break;
        }

        if (computed_cksum == 0) {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset + 2, 2, pim_cksum,
                                       "Checksum: 0x%04x [correct]",
                                       pim_cksum);
        } else {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset + 2, 2, pim_cksum,
                                       "Checksum: 0x%04x [incorrect, should be 0x%04x]",
                                       pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum));
        }
    } else {
        proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
                            offset + 2, 2, pim_cksum);
    }

    offset += 4;

    if (tvb_reported_length_remaining(tvb, offset) > 0) {
        tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options");
        pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts);
    } else
        goto done;

    if (PIM_VER(pim_typever) != 2)
        goto done;

    /* version 2 decoder */
    switch (PIM_TYPE(pim_typever)) {
    case 0:     /*hello*/
    {
        int opt_count = 0;

        while (tvb_reported_length_remaining(tvb, offset) >= 2) {
            guint16 hello_opt, opt_len;
            guint16 opt_value;
            proto_item *opt_item;
            proto_tree *opt_tree;

            opt_count++;
            hello_opt = tvb_get_ntohs(tvb, offset);
            opt_len = tvb_get_ntohs(tvb, offset + 2);
            opt_item = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
                                           "Option %u: %s", hello_opt,
                                           val_to_str(hello_opt, pim_opt_vals, "Unknown: %u"));
            opt_tree = proto_item_add_subtree(opt_item, ett_pim_opt);
            proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, ENC_BIG_ENDIAN);
            proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, ENC_BIG_ENDIAN);

            switch(hello_opt) {
            case 1: /* Hello Hold Time Option */
                opt_value = tvb_get_ntohs(tvb, offset + 4);
                proto_tree_add_uint_format(opt_tree, hf_pim_holdtime, tvb,
                                           offset + 4, opt_len, opt_value,
                                           "Holdtime: %us %s", opt_value, opt_value == 0 ? "(goodbye)" :
                                           opt_value == 0xffff ? "(infinity)": "");
                proto_item_append_text(opt_item, ": %us %s", opt_value,
                                       opt_value == 0 ? "(goodbye)" :
                                       opt_value == 0xffff ? "(infinity)": "");
                break;

            case 2: /* LAN Prune Delay Option */
                proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item,
                                       ": T = %u, Propagation Delay = %ums, Override Interval = %ums",
                                       tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0,
                                       tvb_get_ntohs(tvb, offset + 4) & 0x7fff,
                                       tvb_get_ntohs(tvb, offset + 6));
                break;

            case 19: /* DR priority */
                proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
                break;

            case 20: /* Generation ID */
                proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
                break;

            case 21: /* State Refresh Capable Option */
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item, ": Version = %u, Interval = %us",
                                       tvb_get_guint8(tvb, offset + 4),
                                       tvb_get_guint8(tvb, offset + 5));
                break;

            case 24: /* address list */
            case 65001: /* address list (old implementations) */
            {
                int i;
                proto_tree *sub_tree = NULL;
                proto_item *addrlist_option;

                addrlist_option = proto_tree_add_text(opt_tree, tvb, offset, 4 + opt_len,
                                                      "%sAddress List (%u)",
                                                      hello_opt == 65001 ? "old " : "",
                                                      hello_opt);
                sub_tree = proto_item_add_subtree(addrlist_option, ett_pim_opt);
                for (i = offset + 4; i < offset + 4 + opt_len; ) {
                    int advance;
                    const char *s;

                    s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance);
                    if (s == NULL)
                        break;
                    proto_tree_add_text(sub_tree, tvb, offset,
                                        advance, "Address: %s", s);
                    i += advance;
                }
                break;
            }

            default:
                if (opt_len)
                    proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb,
                                        offset + 4, opt_len, ENC_NA);
                break;
            }
            offset += 4 + opt_len;
        }
        proto_item_append_text(tiopt, ": %u", opt_count);
        break;
    }

    case 1:     /* register */
    {
        guint32 flags;
        guint8 v_hl;
        tvbuff_t *next_tvb;
        proto_tree *flag_tree = NULL;
        proto_item *tiflag;

        flags = tvb_get_ntohl(tvb, offset);
        tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                                     "Flags: 0x%08x", flags);
        flag_tree = proto_item_add_subtree(tiflag, ett_pim);
        proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
                            decode_boolean_bitfield(flags, 0x80000000, 32,
                                                    "Border", "Not border"));
        proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
                            decode_boolean_bitfield(flags, 0x40000000, 32,
                                                    "Null-Register", "Not Null-Register"));
        offset += 4;

        /*
         * The rest of the packet is a multicast data packet.
         */
        next_tvb = tvb_new_subset_remaining(tvb, offset);

        /*
         * It's an IP packet - determine whether it's IPv4 or IPv6.
         */
        v_hl = tvb_get_guint8(tvb, offset);
        switch((v_hl & 0xf0) >> 4) {
        case 0:     /* Null-Register dummy header.
                     * Has the same address family as the encapsulating PIM packet,
                     * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
                     */
            if (pinfo->src.type == AT_IPv4) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv4 dummy header");
                proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4,
                                    "Source: %s",
                                    tvb_ip_to_str(tvb, offset + 12));
                proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4,
                                    "Group: %s",
                                    tvb_ip_to_str(tvb, offset + 16));
            } else if (pinfo->src.type == AT_IPv6) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv6 dummy header");
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8, 16,
                                    "Source: %s",
                                    tvb_ip6_to_str(tvb, offset + 8));
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8 + 16, 16,
                                    "Group: %s",
                                    tvb_ip6_to_str(tvb, offset + 8 + 16));
            } else
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "Dummy header for an unknown protocol");
            break;
        case 4: /* IPv4 */
#if 0
            call_dissector(ip_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        case 6: /* IPv6 */
#if 0
            call_dissector(ipv6_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        default:
            proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                "Unknown IP version %d", (v_hl & 0xf0) >> 4);
            break;
        }
        break;
    }

    case 2:     /* register-stop */
    {
        int advance;
        const char *s;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
        offset += advance;
        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
        break;
    }

    case 3:     /* join/prune */
    case 6:     /* graft */
    case 7:     /* graft-ack */
    {
        int advance;
        int off;
        const char *s;
        int ngroup, i, njoin, nprune, j;
        guint16 holdtime;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;
        proto_tree *subtree = NULL;
        proto_item *tisub;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Upstream-neighbor: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA);
        offset += 1;    /* skip reserved field */

        ngroup = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        for (i = 0; i < ngroup; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak3;
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                          "Group %d: %s", i, s);
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += advance;

            njoin = tvb_get_ntohs(tvb, offset);
            nprune = tvb_get_ntohs(tvb, offset + 2);
            tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb,
                                        offset, 2, ENC_BIG_ENDIAN);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            off = offset + 4;
            for (j = 0; j < njoin; j++) {
                s = dissect_pim_addr(tvb, off, pimv2_source, &advance);
                if (s == NULL)
                    goto breakbreak3;
                proto_tree_add_text(subtree, tvb, off, advance,
                                    "IP address: %s", s);
                off += advance;
            }

            tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
                                        offset + 2, 2, ENC_BIG_ENDIAN);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            for (j = 0; j < nprune; j++) {
                s = dissect_pim_addr(tvb, off, pimv2_source, &advance);
                if (s == NULL)
                    goto breakbreak3;
                proto_tree_add_text(subtree, tvb, off, advance,
                                    "IP address: %s", s);
                off += advance;
            }
            offset = off;
        }
    breakbreak3:
        break;
    }

    case 4:     /* bootstrap */
    {
        const char *s;
        int advance;
        int i, j;
        int frpcnt;
        guint16 holdtime;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;

        proto_tree_add_text(pimopt_tree, tvb, offset, 2,
                            "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset));
        offset += 2;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Hash mask len: %u", tvb_get_guint8(tvb, offset));
        offset += 1;
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "BSR priority: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s);
        offset += advance;

        for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak4;
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                          "Group %d: %s", i, s);
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += advance;

            proto_tree_add_text(grouptree, tvb, offset, 1,
                                "RP count: %u", tvb_get_guint8(tvb, offset));
            offset += 1;
            frpcnt = tvb_get_guint8(tvb, offset);
            proto_tree_add_text(grouptree, tvb, offset, 1,
                                "FRP count: %u", frpcnt);
            offset += 3;

            for (j = 0; j < frpcnt; j++) {
                s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
                if (s == NULL)
                    goto breakbreak4;
                proto_tree_add_text(grouptree, tvb, offset, advance,
                                    "RP %d: %s", j, s);
                offset += advance;

                holdtime = tvb_get_ntohs(tvb, offset);
                proto_tree_add_uint_format(grouptree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
                offset += 2;
                proto_tree_add_text(grouptree, tvb, offset, 1,
                                    "Priority: %u", tvb_get_guint8(tvb, offset));
                offset += 2;    /* also skips reserved field */
            }
        }

    breakbreak4:
        break;
    }

    case 5:     /* assert */
    {
        const char *s;
        int advance;
        guint32 pref;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
        break;
    }

    case 8:     /* Candidate-RP-Advertisement */
    {
        const char *s;
        int advance;
        int pfxcnt;
        guint16 holdtime;
        int i;

        pfxcnt = tvb_get_guint8(tvb, offset);
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Prefix-count: %u", pfxcnt);
        offset += 1;
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Priority: %u", tvb_get_guint8(tvb, offset));
        offset += 1;
        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s);
        offset += advance;

        for (i = 0; i < pfxcnt; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak8;
            proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                "Group %d: %s", i, s);
            offset += advance;
        }
    breakbreak8:
        break;
    }

    case 9:     /* State-Refresh */
    {
        const char *s;
        int advance;
        guint32 pref;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Group: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Source: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Originator: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Masklen: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "TTL: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8,
                                                    "set", "clear"));
        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8,
                                                    "set", "clear"));
        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8,
                                                    "set", "clear"));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Interval: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        break;
    }

    default:
        break;
    }
done:;
}
Example #10
0
static void
process_rtsp_request(tvbuff_t *tvb, int offset, const guchar *data,
                     size_t linelen, size_t next_line_offset, proto_tree *tree)
{
	proto_tree		*sub_tree = NULL;
	proto_item		*ti = NULL;
	const guchar	*lineend = data + linelen;
	unsigned		ii;
	const guchar	*url;
	const guchar	*url_start;
	guchar			*tmp_url;

	/* Request Methods */
	for (ii = 0; ii < RTSP_NMETHODS; ii++) {
		size_t len = strlen(rtsp_methods[ii]);
		if (linelen >= len &&
		    g_ascii_strncasecmp(rtsp_methods[ii], data, len) == 0 &&
		    (len == linelen || isspace(data[len])))
			break;
	}
	if (ii == RTSP_NMETHODS) {
		/*
		 * We got here because "is_rtsp_request_or_reply()" returned
		 * RTSP_REQUEST, so we know one of the request methods
		 * matched, so we "can't get here".
		 */
		DISSECTOR_ASSERT_NOT_REACHED();
	}

	/* Add a tree for this request */
	ti = proto_tree_add_string(tree, hf_rtsp_request, tvb, offset,
	                          (gint) (next_line_offset - offset),
	                          tvb_format_text(tvb, offset, (gint) (next_line_offset - offset)));
	sub_tree = proto_item_add_subtree(ti, ett_rtsp_method);

	
	/* Add method name to tree */
	proto_tree_add_string(sub_tree, hf_rtsp_method, tvb, offset,
	                      (gint) strlen(rtsp_methods[ii]), rtsp_methods[ii]);

	/* URL */
	url = data;
	/* Skip method name again */
	while (url < lineend && !isspace(*url))
		url++;
	/* Skip spaces */
	while (url < lineend && isspace(*url))
		url++;
	/* URL starts here */
	url_start = url;
	/* Scan to end of URL */
	while (url < lineend && !isspace(*url))
		url++;
	/* Create a URL-sized buffer and copy contents */
	tmp_url = ep_alloc(url - url_start + 1);
	memcpy(tmp_url, url_start, url - url_start);
	tmp_url[url - url_start] = '\0';
	
	/* Add URL to tree */
	proto_tree_add_string(sub_tree, hf_rtsp_url, tvb,
	                      offset + (gint) (url_start - data), (gint) (url - url_start), tmp_url);
}
static void dissect_1722a (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti                 = NULL;
    proto_tree *ieee1722a_tree     = NULL;
    proto_tree *audio_tree         = NULL;
    proto_tree *sample_tree        = NULL;
    proto_tree *timestamp_tree     = NULL;
    gint        offset             = 0;
    guint16     datalen            = 0;
    guint16     channels_per_frame = 0;
    guint8      subtype            = 0;
    gint        sample_width       = 0;
    int         i, j;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE1722a");

    col_set_str(pinfo->cinfo, COL_INFO, "AVB Transportation Protocol");

    if (tree)
    {
        ti = proto_tree_add_item(tree, proto_1722a, tvb, 0, -1, ENC_NA);
        ieee1722a_tree = proto_item_add_subtree(ti, ett_1722a);
    }

    /* Version field ends the common AVTPDU. Now parse the specfic packet type */
    subtype = tvb_get_guint8(tvb, IEEE_1722A_CD_OFFSET);
    subtype &= IEEE_1722A_SUBTYPE_MASK;

    switch (subtype)
    {
    case IEEE_1722A_SUBTYPE_AVTP_AUDIO:
        if (tree)
        {
            proto_tree_add_item(ieee1722a_tree, hf_1722a_mrfield,         tvb, IEEE_1722A_VERSION_OFFSET,     1, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_tvfield,         tvb, IEEE_1722A_VERSION_OFFSET,     1, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_seqnum,          tvb, IEEE_1722A_SEQ_NUM_OFFSET,     1, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_tufield,         tvb, IEEE_1722A_TU_FIELD_OFFSET,    1, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_id,       tvb, IEEE_1722A_STREAM_ID_OFFSET,   8, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_avbtp_timestamp, tvb, IEEE_1722A_TIMESTAMP_OFFSET,   4, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_format_info,     tvb, IEEE_1722A_FORMAT_INFO_OFFSET, 1, ENC_BIG_ENDIAN);

            proto_tree_add_item(ieee1722a_tree, hf_1722a_nominal_sample_rate, tvb, IEEE_1722A_NOM_SAMPLE_RATE_OFFSET,        1, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_channels_per_frame,  tvb, IEEE_1722A_CHANNELS_PER_FRAME_OFFSET,     2, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_bit_depth,           tvb, IEEE_1722A_BIT_DEPTH_OFFSET,              1, ENC_BIG_ENDIAN);
            ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_data_length, tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(ti, " bytes");
            proto_tree_add_item(ieee1722a_tree, hf_1722a_sparse_timestamp, tvb, IEEE_1722A_SPARSE_TIMESTAMP_OFFSET, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(ieee1722a_tree, hf_1722a_evtfield,         tvb, IEEE_1722A_EVT_OFFSET,              1, ENC_BIG_ENDIAN);
        }
        /* Make the Audio sample tree. */
        datalen    = tvb_get_ntohs(tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET); /* Length of audio data in bytes */
        ti         = proto_tree_add_item(ieee1722a_tree, hf_1722a_data, tvb, IEEE_1722A_DATA_OFFSET, datalen, ENC_NA);
        audio_tree = proto_item_add_subtree(ti, ett_1722a_audio);

        /* Need to get the offset of where the audio data starts */
        offset              = IEEE_1722A_DATA_OFFSET;
        channels_per_frame  = tvb_get_ntohs(tvb, IEEE_1722A_CHANNELS_PER_FRAME_OFFSET);
        channels_per_frame &= IEEE_1722A_CHANNEL_PER_FRAME_MASK;

        switch (tvb_get_guint8(tvb, IEEE_1722A_FORMAT_INFO_OFFSET))
        {
        case 0:
            break;
        case 1:
            sample_width = 32;
            break;
        case 2:
            sample_width = 32;
            break;
        case 3:
            sample_width = 24;
            break;
        case 4:
            sample_width = 16;
            break;
        default:
            expert_add_info(pinfo, ti, &ei_format_info);
            break;
        }

        if (sample_width == 0)
        {
            expert_add_info(pinfo, ti, &ei_sample_width);
        }
        else
        {
            if (channels_per_frame == 0)
            {
                expert_add_info(pinfo, ti, &ei_channels_per_frame);
            }
            else
            {
                if (tree)
                {
                    /* Loop through all samples and add them to the audio tree. */
                    for (j = 0; j < ((datalen * 8) / (channels_per_frame * sample_width)); j++)
                    {
                        sample_tree = proto_tree_add_subtree_format(audio_tree, tvb, offset, 1,
                                                        ett_1722a_sample, &ti, "Sample Chunk %d", j);
                        for (i = 0; i < channels_per_frame; i++)
                        {
                            ti = proto_tree_add_item(sample_tree, hf_1722a_sample, tvb, offset, sample_width / 8, ENC_NA);
                            proto_item_prepend_text(ti, "Channel: %d ", i);
                            offset += (sample_width / 8);
                        }
                    }
                }
            }
        }
        break;
    case IEEE_1722A_SUBTYPE_CRF:
        proto_tree_add_item(ieee1722a_tree, hf_1722a_mrfield,   tvb, IEEE_1722A_VERSION_OFFSET,   1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ieee1722a_tree, hf_1722a_tvfield,   tvb, IEEE_1722A_VERSION_OFFSET,   1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ieee1722a_tree, hf_1722a_seqnum,    tvb, IEEE_1722A_SEQ_NUM_OFFSET,   1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ieee1722a_tree, hf_1722a_tufield,   tvb, IEEE_1722A_TU_FIELD_OFFSET,  1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_id, tvb, IEEE_1722A_STREAM_ID_OFFSET, 8, ENC_BIG_ENDIAN);
        ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_data_length, tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET, 2, ENC_BIG_ENDIAN);
        proto_item_append_text(ti, " bytes");
        proto_tree_add_item(ieee1722a_tree, hf_1722a_crf_type,  tvb, IEEE_1722A_CRF_TYPE_OFFSET,  2, ENC_BIG_ENDIAN);

        switch (tvb_get_ntohs(tvb, IEEE_1722A_CRF_TYPE_OFFSET))
        {
        /* Audio Timestamp Case */
        case IEEE_1722A_CRF_AUDIO_SAMPLE_TIMESTAMP:
            if (tree)
            {
                proto_tree_add_item(ieee1722a_tree, hf_1722a_clock_frequency,    tvb, IEEE_1722A_CRF_CLOCK_FREQUENCY_OFFSET,    1, ENC_BIG_ENDIAN);
                proto_tree_add_item(ieee1722a_tree, hf_1722a_clock_multiplier,   tvb, IEEE_1722A_CRF_CLOCK_MULTIPLIER_OFFSET,   1, ENC_BIG_ENDIAN);
                proto_tree_add_item(ieee1722a_tree, hf_1722a_timestamp_interval, tvb, IEEE_1722A_CRF_TIMESTAMP_INTERVAL_OFFSET, 2, ENC_BIG_ENDIAN);
                /* Make the Timestamp tree. */
                datalen = tvb_get_ntohs(tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET);
                datalen = datalen - 6; /* remove type field and type header */
                ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_crf_timestamp, tvb, IEEE_1722A_CRF_AUDIO_TIMESTAMP_OFFSET, datalen, ENC_NA);
                timestamp_tree = proto_item_add_subtree(ti, ett_1722a_crf_timestamp);
                offset = IEEE_1722A_CRF_AUDIO_TIMESTAMP_OFFSET;
                /* Loop through all timestamps and add them to the timestamp tree. */
                for (j = 0; j < (datalen / IEEE_1722A_CRF_TIMESTAMP_SIZE); j++)
                {
                    proto_tree_add_item(timestamp_tree, hf_1722a_crf_timestamp_data, tvb, offset, IEEE_1722A_CRF_TIMESTAMP_SIZE, ENC_NA);
                    offset += IEEE_1722A_CRF_TIMESTAMP_SIZE;
                }
            }
            break;
        default:
            expert_add_info(pinfo, ti, &ei_clock_reference_type);
            break;
        }
        break;
    default:
        /* This dissector only registers for subtype 0x02 (AVTP Audio Format) and 0x05 (Clock Reference Format)
           which will be handled above. So we won`t enter the default path. */
        DISSECTOR_ASSERT_NOT_REACHED();
        break;
    }
}
Example #12
0
/* AU Header dissection */
static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *ismacryp_tree, guint set_version )
{
	proto_item *ismacryp_item;
	proto_tree *ismacryp_header_tree;
	proto_tree *ismacryp_header_byte_tree;

	guint16 header_len_bytes = 0; /* total length of non-first AU header in bytes (rounded up) */
	gint header_len = 0; /* length of AU headers in bits */
	gint cts_flag =0;
	gint dts_flag =0;
	gboolean first_au_flag=FALSE;
	gint bit_offset = 0;

	/*first determine total AU header length */
	/* calculate each AU header length in bits first */
	switch (set_version) {
		case V11:
			if (selective_encryption)
				header_len+=8; /* add one byte to header length */
			break;
		case V20:
			if (selective_encryption || slice_indication || padding_indication)
				header_len+=8; /* add one byte to header length */
			break;
		default:
			DISSECTOR_ASSERT_NOT_REACHED();
			break;
	}	/* end switch */
	header_len+=au_size_length; /* add au size length */

	if (poffset->offset_bytes==AU_HEADERS_LENGTH_SIZE){	/*first AU */
		header_len+=8*(iv_length);                      /* add IV length */
		header_len+=8*key_indicator_length;             /* add key indicator length */
		header_len+=au_index_length;                    /* add AU index length */
		first_au_flag = TRUE;
	}
	else { /* not the first AU */
		if (key_indicator_per_au_flag == TRUE)
			header_len+=8*key_indicator_length; /* add key indicator length */
		header_len+=8*(delta_iv_length);                /* add delta IV length */
		header_len+=au_index_delta_length;              /* add AU delta index length */
	}
	/* CTS flag is present? */
	if (cts_delta_length != 0){    /* need to test whether cts_delta_flag is TRUE or FALSE */
		cts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit CTS flag  */
		header_len+=1;         /* add CTS flag bit */
		if (cts_flag==1)
			header_len+=cts_delta_length; /* add CTS delta length bits if CTS flag SET */
	}
	/* DTS flag is present? */
	if (dts_delta_length != 0){ /* need to test whether dts_delta_flag is TRUE or FALSE */
		dts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit DTS flag */
		header_len+=1;      /* add DTS flag bit */
		if (dts_flag==1)
			header_len+=dts_delta_length; /* add DTS delta length bits if DTS flag SET */
	}
	/* RAP flag present? */
	if (random_access_indication != FALSE)
		header_len+=1;      /* add 1 bit RAP flag */

	/* stream state indication present */
	if (stream_state_indication !=0)
		header_len+=stream_state_indication; /* add stream state indication bits */

	/* convert header_len to bytes (rounded up) */
	if (header_len% 8!=0)
	{
		header_len_bytes=((header_len)/8)+1; /*add 1 */
	}
	else
		header_len_bytes=((header_len)/8);

	/* add AU header tree  */
	ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_header, tvb, poffset->offset_bytes, header_len_bytes, ENC_NA );
	proto_item_append_text(ismacryp_item, ": Length=%d bits", header_len); /* add text to Header tree indicating length */
	/* sanity check if actual AU header length is zero bits, which indicates an error */
	if ( header_len == 0) /* something wrong */
	{
		proto_item_append_text(ismacryp_item, " Error - zero bit AU header size - check parameters!");
	}
	ismacryp_header_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header);

	/* ismacryp header analysis */
	/* we are being asked for details  */

	/* Extra 1 Byte Header? */

	if ((set_version==V20 && (selective_encryption || slice_indication || padding_indication))
		|| (set_version==V11 && selective_encryption)){

		/* add  header byte tree	*/
		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_header_byte,
						    tvb, poffset->offset_bytes, 1, ENC_NA );
		proto_item_append_text(ismacryp_item, ": Length=8 bits"); /* add text to Header byte tree indicating length */
		ismacryp_header_byte_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header_byte);

		/*ismacryp_header_byte_tree */
		/* we are being asked for details */
		/* tvb is network order, so get MSB bits first, so shift 8 bits and work "backwards" */
		add_bits(poffset,7);   /*shift 7 bits to get correct bit */
		/* AU_is_encrypted bit */
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		if (selective_encryption){ /* bit used */
			proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_au_is_encrypted,
						 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit AU_is_encrypted */
		}
		else { /* bit unused */
			proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
						 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */
		}
		switch (set_version){ /* ISMACryp version? */
			case V11:
				/* Reserved bits */
				add_bits(poffset, -7); /* move back 7 bits for reserved bits */
				bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
				proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits,
							 tvb, bit_offset, 7, ENC_BIG_ENDIAN); /*fetch 7 bits reserved */
				add_bits(poffset,8);   /* offset to next byte */
				break;
			case V20:
				/* Slice_start bit */
				add_bits(poffset, -1); /* move back 1 bit for slice_start */
				bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
				if (slice_indication){
					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_start,
								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit slice_start */
				}
				else { /* bit unused */
					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */
				}
				add_bits(poffset, -1); /* move back 1 bit for slice_end */

				/* Slice_end bit */
				bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
				if (slice_indication){
					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_end,
								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit Slice_end */
				}
				else { /* bit unused */
					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */
				}
				add_bits(poffset, -3); /* move back 3 bits for padding_bitcount */

				/* Padding_bitcount bits */
				bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
				if (padding_indication){
					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_padding_bitcount,
								 tvb, bit_offset, 3, ENC_BIG_ENDIAN); /*fetch 3 bits padding_bitcount */
				}
				else { /* bits unused */
					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
								 tvb, bit_offset, 3, ENC_BIG_ENDIAN); /*fetch 3 bits unused */
				}
				add_bits(poffset, -2); /* move back 2 bits for reserved bits */

				/* Reserved bits */
				bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
				proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits,
							 tvb, bit_offset, 2, ENC_BIG_ENDIAN); /*fetch 2 bits reserved */
				add_bits(poffset,8); /* offset to next byte */
				break;
			default:
				DISSECTOR_ASSERT_NOT_REACHED();
				break;
		} /* end switch set_version */
	} /* end selective encryption */
	/* IV */
	if (first_au_flag == TRUE && iv_length != 0)
	{
		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_iv, tvb, poffset->offset_bytes, iv_length, ENC_NA);
		proto_item_append_text(ismacryp_item, ": Length=%d bytes",iv_length); /* add IV info */
		col_append_fstr( pinfo->cinfo, COL_INFO,
			", IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, iv_length,' '));

		poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */
	}
	/*Delta  IV */
	if (first_au_flag == FALSE && delta_iv_length != 0)
	{
		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_delta_iv,
						    tvb, poffset->offset_bytes, delta_iv_length, ENC_NA);
		proto_item_append_text(ismacryp_item, ": Length=%d bytes",delta_iv_length); /* add delta IV info */
		col_append_fstr( pinfo->cinfo, COL_INFO,
			", Delta IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, delta_iv_length,' '));
		poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */
	}
	/* Key Indicator */
	if ( key_indicator_length != 0 && ( first_au_flag == TRUE || key_indicator_per_au_flag == TRUE) )
	{
		/* (first AU or KI for each AU) and non-zero KeyIndicator size */
		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_key_indicator,
						    tvb, poffset->offset_bytes, key_indicator_length, ENC_NA);
		proto_item_append_text(ismacryp_item,": Length=%d bytes",key_indicator_length); /* add KI info */
		col_append_fstr( pinfo->cinfo, COL_INFO,
					 ", KI=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, key_indicator_length,' '));
		poffset->offset_bytes+=key_indicator_length; /* add KI length to offset_bytes */
	}
	/* AU size */
	if (au_size_length != 0) /* in bits */
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_size,
							 tvb, bit_offset, au_size_length, ENC_BIG_ENDIAN);
		proto_item_append_text(ismacryp_item, " bytes: Length=%d bits",au_size_length); /* add AU size info */
		/*bit_offset+=au_size_length;*/
		add_bits(poffset, au_size_length);
	}
	/* AU Index */
	if (first_au_flag == TRUE && au_index_length != 0) /* first AU and non-zero AU size */
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index,
							 tvb, bit_offset, au_index_length, ENC_BIG_ENDIAN);
		proto_item_append_text(ismacryp_item, " bits: Length=%d bits",au_index_length); /* add AU index info */
		/*bit_offset+=au_index_length;*/
		add_bits(poffset, au_index_length);
	}
	/* AU index delta */
	if (first_au_flag == FALSE && au_index_delta_length != 0) /* not first AU and non-zero AU delta size */
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index_delta,
							 tvb, bit_offset, au_index_delta_length, ENC_BIG_ENDIAN);
		proto_item_append_text(ismacryp_item, ": Length=%d bits", au_index_delta_length); /* add AU index info */
		/*bit_offset+=au_index_delta_length;*/
		add_bits(poffset, au_index_delta_length);
	}
	/* CTS delta value */
	if (cts_delta_length != 0)
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_flag,
					 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read CTS flag */
		add_bits(poffset, 1);
		if (cts_flag==1)
		{
			/* now fetch CTS delta value (remember offset 1 bit due to CTS flag) */
			bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
			ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_delta,
								 tvb, bit_offset, cts_delta_length, ENC_BIG_ENDIAN); /* read CTS delta value */
			proto_item_append_text(ismacryp_item, ": Length=%d bits",cts_delta_length); /* add CTS delta info */
			add_bits(poffset, cts_delta_length);
		}
	}
	/* DTS delta value */
	if (dts_delta_length != 0)
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_flag,
					 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read DTS flag */
		add_bits(poffset, 1);

		/* now fetch DTS delta value (remember offset x bits due to DTS flag) */
		if (dts_flag ==1)
		{
			bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
			ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_delta,
								 tvb, bit_offset, dts_delta_length, ENC_BIG_ENDIAN); /* read DTS delta value */
			proto_item_append_text(ismacryp_item, ": Length=%d bits",dts_delta_length); /* add DTS delta info */
			add_bits(poffset, dts_delta_length);
		}
	}
	/* RAP */
	if (random_access_indication != FALSE)
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_rap_flag,
					 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read RAP flag */
		add_bits(poffset, 1);
	}
	/*STREAM STATE */
	if (stream_state_indication != 0)
	{
		bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_stream_state,
					 tvb, bit_offset, stream_state_indication, ENC_BIG_ENDIAN); /* read stream state */
		add_bits(poffset, stream_state_indication);
	}
	/* end header details */
return poffset;
}
Example #13
0
static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version)
{
	guint set_version;           /* ISMACryp version used during dissection */
	proto_item *ismacryp_item;
	proto_tree *ismacryp_tree;
	proto_tree *ismacryp_message_tree;

	/* select and display ISMACryp version */
	if ((ismacryp_version!=version_type) && override_flag){
		/* override -> use manual preference setting */
		col_append_str(pinfo->cinfo, COL_INFO, " Manual version");
		set_version = version_type; /* set to preference value */
	}
	else {
		set_version = ismacryp_version;
	}

	if (set_version == V11){
		col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11);
		/* display mode */
		if (pref_user_mode == FALSE){
			col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str_const(mode, modetypenames, "user mode"));
		} else {
			col_append_str(pinfo->cinfo, COL_INFO, ", user mode");
		}
		user_mode = pref_user_mode;
	}
	if (set_version == V20){
		col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20);
		user_mode = TRUE;
		/* display mode */
		col_append_str(pinfo->cinfo, COL_INFO, ", user mode");
	}
	/* select correct AU values depending on version & selected mode in preferences menu if not in user_mode */
	if (user_mode == TRUE){ /* use values set in preference menu */
		au_size_length = pref_au_size_length;
		au_index_length = pref_au_index_length;
		au_index_delta_length = pref_au_index_delta_length;
		cts_delta_length = pref_cts_delta_length;
		dts_delta_length = pref_dts_delta_length;
		random_access_indication = pref_random_access_indication;
		stream_state_indication = pref_stream_state_indication;
	} /* end if user_mode == TRUE */
	if (user_mode == FALSE){
		switch (mode){
			case AAC_HBR_MODE:
				au_size_length = 13;
				au_index_length = 3;
				au_index_delta_length = 3;
				cts_delta_length = 0;
				dts_delta_length = 0;
				random_access_indication = FALSE;
				stream_state_indication = 0;
				break;
			case MPEG4_VIDEO_MODE:
				au_size_length = 0;
				au_index_length = 0;
				au_index_delta_length = 0;
				cts_delta_length = 0;
				dts_delta_length = 22;
				random_access_indication = TRUE;
				stream_state_indication = 0;
				break;
			case AVC_VIDEO_MODE:
				au_size_length = 0;
				au_index_length = 0;
				au_index_delta_length = 0;
				cts_delta_length = 0;
				dts_delta_length = 22;
				random_access_indication = TRUE;
				stream_state_indication = 0;
				break;
			default:
				DISSECTOR_ASSERT_NOT_REACHED();
				break;
		} /* end switch */
	} /* end if user_mode == FALSE */

	/* navigate through buffer */
	if (tree)
	{
		/* we are being asked for details */

		guint16 au_headers_length = 0; /* total length of AU headers */
		guint16 totalbits =0;          /* keeps track of total number of AU header bits treated (used to determine end of AU headers) */
		int deltabits = -1;            /* keeps track of extra bits per AU header treated (used to determine end of AU heafers ) */
		guint16 totalbit_offset = 0;   /* total offset in bits*/
		int nbpadding_bits = 0;        /* number of padding bits*/
		offset_struct s_offset;
		offset_struct* poffset;
		guint16 nbmessage_bytes = 0;   /*nb of message data bytes */
		s_offset.offset_bytes = 0;     /* initialise byte offset */
		s_offset.offset_bits = 0;      /* initialise bit offset */
		poffset = &s_offset;

		ismacryp_item = proto_tree_add_item(tree, proto_ismacryp, tvb, 0, -1, ENC_NA);
		ismacryp_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp);
		proto_item_append_text(tree, ", %s", "ismacryp packet"); /* add text to tree */

		/* ismacryp_tree analysis */
		/* we are being asked for details */
		/* get total length of AU headers (first 2 bytes) */
		ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_au_headers_length,
						    tvb, poffset->offset_bytes, AU_HEADERS_LENGTH_SIZE, ENC_BIG_ENDIAN );
		proto_item_append_text(ismacryp_item, " (bits)"); /* add text to AU Header tree indicating length */
		au_headers_length=tvb_get_ntohs(tvb,poffset->offset_bytes); /* 2 byte au headers length */
		poffset->offset_bytes+=AU_HEADERS_LENGTH_SIZE;
		/* ADD HEADER(S) BRANCH  */

		/* AU Header loop */
		totalbits=(poffset->offset_bytes*8)+poffset->offset_bits;
		while( ((totalbits-8*AU_HEADERS_LENGTH_SIZE)<au_headers_length) && deltabits!=0 ) /* subtract AU headers length bits*/
		{
			poffset=dissect_auheader( tvb, poffset, pinfo, ismacryp_tree, set_version);
			deltabits=(poffset->offset_bytes*8)+poffset->offset_bits - totalbits; /* if zero this means no actual AU header so exit while loop */
			totalbits+=deltabits;
		}
		/* reached end of AU Header(s) */
		/* sanity check if actual total AU headers length in bits i.e. totalbits is */
		/*  the same as expected AU headers length from 2 bytes at start of buffer */
		if ( (totalbits-8*AU_HEADERS_LENGTH_SIZE) != au_headers_length) /* something wrong */
		{
			proto_item_append_text(ismacryp_item,
					       " Error - expected total AU headers size (%d bits) "
					       "does not match calculated size (%d bits) - check parameters!",
					       au_headers_length,(totalbits-8*AU_HEADERS_LENGTH_SIZE));
		}
		/* add padding if need to byte align */
		if (poffset->offset_bits!=0)
		{
			totalbit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
			nbpadding_bits = (8-poffset->offset_bits); /* number of padding bits for byte alignment */
			ismacryp_item = proto_tree_add_bits_item(ismacryp_tree, hf_ismacryp_padding,
								 tvb, totalbit_offset, nbpadding_bits , ENC_BIG_ENDIAN); /* padding bits */
			proto_item_append_text(ismacryp_item, ": Length=%d bits",nbpadding_bits); /* add padding info */
			add_bits(poffset, nbpadding_bits);
		}
		/* ADD MESSAGE BRANCH  */
		ismacryp_item = proto_tree_add_item( ismacryp_tree, hf_ismacryp_message,
						     tvb, poffset->offset_bytes, -1, ENC_NA );
		ismacryp_message_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_message);
		proto_item_append_text(ismacryp_item, ", %s", "Encrypted data"); /* add text to Message tree */
		nbmessage_bytes = tvb_reported_length_remaining(tvb, poffset->offset_bytes);
		proto_item_append_text(ismacryp_item, ", Length= %d bytes", nbmessage_bytes ); /* add length of message */

		/* ismacryp message tree analysis (encrypted AUs) */
		if (ismacryp_message_tree)
		{	/* we are being asked for details */
			poffset->offset_bytes+= nbmessage_bytes;	/* */
		}  /* end message details */
		/* end ismacryp tree details */
	} /* end if tree */
}
Example #14
0
static void
dissect_llrp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        guint16 type, guint offset)
{
    guint8  requested_data;
    guint16 antenna_id, gpi_port, gpo_port;
    guint32 spec_id;
    proto_item *ti;

    switch (type)
    {
        /* Simple cases just have normal TLV or TV parameters */
        case LLRP_TYPE_CLOSE_CONNECTION_RESPONSE:
        case LLRP_TYPE_GET_READER_CAPABILITES_RESPONSE:
        case LLRP_TYPE_ADD_ROSPEC:
        case LLRP_TYPE_ADD_ROSPEC_RESPONSE:
        case LLRP_TYPE_DELETE_ROSPEC_RESPONSE:
        case LLRP_TYPE_START_ROSPEC_RESPONSE:
        case LLRP_TYPE_STOP_ROSPEC_RESPONSE:
        case LLRP_TYPE_ENABLE_ROSPEC_RESPONSE:
        case LLRP_TYPE_DISABLE_ROSPEC_RESPONSE:
        case LLRP_TYPE_GET_ROSPECS_RESPONSE:
        case LLRP_TYPE_ADD_ACCESSSPEC:
        case LLRP_TYPE_ADD_ACCESSSPEC_RESPONSE:
        case LLRP_TYPE_DELETE_ACCESSSPEC_RESPONSE:
        case LLRP_TYPE_ENABLE_ACCESSSPEC_RESPONSE:
        case LLRP_TYPE_DISABLE_ACCESSSPEC_RESPONSE:
        case LLRP_TYPE_GET_ACCESSSPECS:
        case LLRP_TYPE_CLIENT_REQUEST_OP:
        case LLRP_TYPE_CLIENT_RESQUEST_OP_RESPONSE:
        case LLRP_TYPE_RO_ACCESS_REPORT:
        case LLRP_TYPE_READER_EVENT_NOTIFICATION:
        case LLRP_TYPE_ERROR_MESSAGE:
        case LLRP_TYPE_GET_READER_CONFIG_RESPONSE:
        case LLRP_TYPE_SET_READER_CONFIG_RESPONSE:
        case LLRP_TYPE_SET_PROTOCOL_VERSION_RESPONSE:
        case LLRP_TYPE_GET_ACCESSSPECS_RESPONSE:
        case LLRP_TYPE_GET_REPORT:
        case LLRP_TYPE_ENABLE_EVENTS_AND_REPORTS:
            dissect_llrp_parameters(tvb, pinfo, tree, offset);
            break;
        /* Some just have an ROSpec ID */
        case LLRP_TYPE_START_ROSPEC:
        case LLRP_TYPE_STOP_ROSPEC:
        case LLRP_TYPE_ENABLE_ROSPEC:
        case LLRP_TYPE_DISABLE_ROSPEC:
        case LLRP_TYPE_DELETE_ROSPEC:
            spec_id = tvb_get_ntohl(tvb, offset);
            if (spec_id == LLRP_ROSPEC_ALL)
                proto_tree_add_uint_format(tree, hf_llrp_rospec, tvb,
                        offset, 4, spec_id, "All ROSpecs (%u)", spec_id);
            else
                proto_tree_add_item(tree, hf_llrp_rospec, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
            break;
        /* Some just have an AccessSpec ID */
        case LLRP_TYPE_ENABLE_ACCESSSPEC:
        case LLRP_TYPE_DELETE_ACCESSSPEC:
        case LLRP_TYPE_DISABLE_ACCESSSPEC:
            spec_id = tvb_get_ntohl(tvb, offset);
            if (spec_id == LLRP_ACCESSSPEC_ALL)
                proto_tree_add_uint_format(tree, hf_llrp_accessspec, tvb,
                        offset, 4, spec_id, "All Access Specs (%u)", spec_id);
            else
                proto_tree_add_item(tree, hf_llrp_accessspec, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
            proto_tree_add_item(tree, hf_llrp_accessspec, tvb, offset, 4, ENC_BIG_ENDIAN);
            break;
        case LLRP_TYPE_GET_READER_CAPABILITES:
            proto_tree_add_item(tree, hf_llrp_req_cap, tvb, offset, 1, ENC_NA);
            offset++;
            dissect_llrp_parameters(tvb, pinfo, tree, offset);
            break;
        /* GET_READER_CONFIG is complicated */
        case LLRP_TYPE_GET_READER_CONFIG:
            requested_data = tvb_get_guint8(tvb, offset + 2);
            switch (requested_data)
            {
                case LLRP_CONF_ALL:
                    antenna_id = tvb_get_ntohs(tvb, offset);
                    if (antenna_id == LLRP_ANTENNA_ALL)
                        proto_tree_add_uint_format(tree, hf_llrp_antenna_id, tvb,
                                offset, 2, antenna_id, "All Antennas (%u)", antenna_id);
                    else
                        proto_tree_add_item(tree, hf_llrp_antenna_id, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                    proto_tree_add_item(tree, hf_llrp_req_conf, tvb,
                            offset, 1, ENC_NA);
                    offset++;
                    gpi_port = tvb_get_ntohs(tvb, offset);
                    if (gpi_port == LLRP_GPI_PORT_ALL)
                        proto_tree_add_uint_format(tree, hf_llrp_gpi_port, tvb,
                                offset, 2, gpi_port, "All GPI Ports (%u)", gpi_port);
                    else
                        proto_tree_add_item(tree, hf_llrp_gpi_port, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                    gpo_port = tvb_get_ntohs(tvb, offset);
                    if (gpo_port == LLRP_GPO_PORT_ALL)
                        proto_tree_add_uint_format(tree, hf_llrp_gpo_port, tvb,
                                offset, 2, gpo_port, "All GPO Ports (%u)", gpo_port);
                    else
                        proto_tree_add_item(tree, hf_llrp_gpo_port, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                    break;
                case LLRP_CONF_ANTENNA_PROPERTIES:
                case LLRP_CONF_ANTENNA_CONFIGURATION:
                    antenna_id = tvb_get_ntohs(tvb, offset);
                    if (antenna_id == LLRP_ANTENNA_ALL)
                        proto_tree_add_uint_format(tree, hf_llrp_antenna_id, tvb,
                                offset, 2, antenna_id, "All Antennas (%u)", antenna_id);
                    else
                        proto_tree_add_item(tree, hf_llrp_antenna_id, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                    proto_tree_add_item(tree, hf_llrp_req_conf, tvb,
                            offset, 1, ENC_NA);
                    offset++;
                    offset += 4; /* Skip both GPI and GPO ports */
                    break;
                case LLRP_CONF_IDENTIFICATION:
                case LLRP_CONF_RO_REPORT_SPEC:
                case LLRP_CONF_READER_EVENT_NOTIFICATION_SPEC:
                case LLRP_CONF_ACCESS_REPORT_SPEC:
                case LLRP_CONF_LLRP_CONFIGURATION_STATE:
                case LLRP_CONF_KEEPALIVE_SPEC:
                case LLRP_CONF_EVENTS_AND_REPORTS:
                    offset += 2; /* Skip antenna ID */
                    proto_tree_add_item(tree, hf_llrp_req_conf, tvb,
                            offset, 1, ENC_NA);
                    offset++;
                    offset += 4; /* Skip both GPI and GPO ports */
                    break;
                case LLRP_CONF_GPI_PORT_CURRENT_STATE:
                    offset += 2; /* Skip antenna ID */
                    proto_tree_add_item(tree, hf_llrp_req_conf, tvb,
                            offset, 1, ENC_NA);
                    offset++;
                    gpi_port = tvb_get_ntohs(tvb, offset);
                    if (gpi_port == LLRP_GPI_PORT_ALL)
                        proto_tree_add_uint_format(tree, hf_llrp_gpi_port, tvb,
                                offset, 2, gpi_port, "All GPI Ports (%u)", gpi_port);
                    else
                        proto_tree_add_item(tree, hf_llrp_gpi_port, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                    offset += 2; /* Skip GPO Port */
                    break;
                case LLRP_CONF_GPO_WRITE_DATA:
                    offset += 2; /* Skip antenna ID */
                    proto_tree_add_item(tree, hf_llrp_req_conf, tvb,
                            offset, 1, ENC_NA);
                    offset++;
                    offset += 2; /* Skip GPI Port */
                    gpo_port = tvb_get_ntohs(tvb, offset);
                    if (gpo_port == LLRP_GPO_PORT_ALL)
                        proto_tree_add_uint_format(tree, hf_llrp_gpo_port, tvb,
                                offset, 2, gpo_port, "All GPO Ports (%u)", gpo_port);
                    else
                        proto_tree_add_item(tree, hf_llrp_gpo_port, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                    break;
                default:
                    offset += 2; /* Skip antenna ID */
                    ti = proto_tree_add_item(tree, hf_llrp_req_conf, tvb,
                            offset, 1, ENC_NA);
                    expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
                            "Unrecognized configuration request: %u",
                            requested_data);
                    offset++;
                    offset += 4; /* Skip both GPI and GPO ports */
                    break;
            };
            dissect_llrp_parameters(tvb, pinfo, tree, offset);
            break;
        /* END GET_READER_CONFIG */
        /* Misc */
        case LLRP_TYPE_SET_READER_CONFIG:
            proto_tree_add_item(tree, hf_llrp_rest_fact, tvb, offset, 1, ENC_NA);
            offset++;
            dissect_llrp_parameters(tvb, pinfo, tree, offset);
            break;
        case LLRP_TYPE_SET_PROTOCOL_VERSION:
            proto_tree_add_item(tree, hf_llrp_version, tvb, offset, 1, ENC_NA);
            break;
        case LLRP_TYPE_GET_SUPPORTED_VERSION_RESPONSE:
            proto_tree_add_item(tree, hf_llrp_cur_ver, tvb, offset, 1, ENC_NA);
            offset++;
            proto_tree_add_item(tree, hf_llrp_sup_ver, tvb, offset, 1, ENC_NA);
            offset++;
            dissect_llrp_parameters(tvb, pinfo, tree, offset);
            break;
        case LLRP_TYPE_CUSTOM_MESSAGE:
            proto_tree_add_item(tree, hf_llrp_vendor, tvb, offset, 4, ENC_BIG_ENDIAN);
            break;
        /* Some have no extra data expected */
        case LLRP_TYPE_KEEPALIVE:
        case LLRP_TYPE_KEEPALIVE_ACK:
        case LLRP_TYPE_CLOSE_CONNECTION:
        case LLRP_TYPE_GET_ROSPECS:
        case LLRP_TYPE_GET_SUPPORTED_VERSION:
            break;
        default:
            /* We shouldn't be called if we don't already recognize the value */
            DISSECTOR_ASSERT_NOT_REACHED();
    };
}
Example #15
0
/* Dissect OSC message */
static int
dissect_osc_message(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len)
{
    proto_tree *message_tree = NULL;
    proto_tree *header_tree = NULL;
    gint slen;
    gint rem;
    gint end = offset + len;
    const gchar *path = NULL;
    gint path_len;
    gint path_offset;
    const gchar *format = NULL;
    gint format_offset;
    gint format_len;
    const gchar *ptr = NULL;

    /* peek/read path */
    path_offset = offset;
    path = tvb_get_const_stringz(tvb, path_offset, &path_len);
    if( (rem = path_len%4) ) path_len += 4-rem;

    if(!is_valid_path(path))
        return -1;

    /* peek/read fmt */
    format_offset = path_offset + path_len;
    format = tvb_get_const_stringz(tvb, format_offset, &format_len);
    if( (rem = format_len%4) ) format_len += 4-rem;

    if(!is_valid_format(format))
        return -1;

    /* create message */
    ti = proto_tree_add_none_format(osc_tree, hf_osc_message_type, tvb, offset, len, "Message: %s %s", path, format);
    message_tree = proto_item_add_subtree(ti, ett_osc_message);

    /* append header */
    ti = proto_tree_add_item(message_tree, hf_osc_message_header_type, tvb, offset, path_len+format_len, ENC_NA);
    header_tree = proto_item_add_subtree(ti, ett_osc_message_header);

    /* append path */
    proto_tree_add_item(header_tree, hf_osc_message_path_type, tvb, path_offset, path_len, ENC_ASCII | ENC_NA);

    /* append format */
    proto_tree_add_item(header_tree, hf_osc_message_format_type, tvb, format_offset, format_len, ENC_ASCII | ENC_NA);

    offset += path_len + format_len;

    /* ::parse argument:: */
    ptr = format + 1; /* skip ',' */
    while( (*ptr != '\0') && (offset < end) )
    {
        switch(*ptr)
        {
            case OSC_INT32:
                proto_tree_add_item(message_tree, hf_osc_message_int32_type, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
            case OSC_FLOAT:
                proto_tree_add_item(message_tree, hf_osc_message_float_type, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
            case OSC_STRING:
                slen = tvb_strsize(tvb, offset);
                if( (rem = slen%4) ) slen += 4-rem;
                proto_tree_add_item(message_tree, hf_osc_message_string_type, tvb, offset, slen, ENC_ASCII | ENC_NA);
                offset += slen;
                break;
            case OSC_BLOB:
            {
                proto_item *bi = NULL;
                proto_tree *blob_tree = NULL;

                gint32 blen = tvb_get_ntohl(tvb, offset);
                slen = blen;
                if( (rem = slen%4) ) slen += 4-rem;

                bi = proto_tree_add_none_format(message_tree, hf_osc_message_blob_type, tvb, offset, 4+slen, "Blob: %i bytes", blen);
                blob_tree = proto_item_add_subtree(bi, ett_osc_blob);

                proto_tree_add_int_format_value(blob_tree, hf_osc_message_blob_size_type, tvb, offset, 4, blen, "%i bytes", blen);
                offset += 4;

                /* check for zero length blob */
                if(blen == 0)
                    break;

                proto_tree_add_item(blob_tree, hf_osc_message_blob_data_type, tvb, offset, slen, ENC_NA);
                offset += slen;
                break;
            }

            case OSC_TRUE:
                proto_tree_add_item(message_tree, hf_osc_message_true_type, tvb, offset, 0, ENC_NA);
                break;
            case OSC_FALSE:
                proto_tree_add_item(message_tree, hf_osc_message_false_type, tvb, offset, 0, ENC_NA);
                break;
            case OSC_NIL:
                proto_tree_add_item(message_tree, hf_osc_message_nil_type, tvb, offset, 0, ENC_NA);
                break;
            case OSC_BANG:
                proto_tree_add_item(message_tree, hf_osc_message_bang_type, tvb, offset, 0, ENC_NA);
                break;

            case OSC_INT64:
                proto_tree_add_item(message_tree, hf_osc_message_int64_type, tvb, offset, 8, ENC_BIG_ENDIAN);
                offset += 8;
                break;
            case OSC_DOUBLE:
                proto_tree_add_item(message_tree, hf_osc_message_double_type, tvb, offset, 8, ENC_BIG_ENDIAN);
                offset += 8;
                break;
            case OSC_TIMETAG:
            {
                guint32 sec = tvb_get_ntohl(tvb, offset);
                guint32 frac = tvb_get_ntohl(tvb, offset+4);
                nstime_t ns;
                if( (sec == 0UL) && (frac == 1UL) )
                    proto_tree_add_time_format_value(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str);
                else
                    proto_tree_add_item(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
                offset += 8;
            }
                break;

            case OSC_SYMBOL:
                slen = tvb_strsize(tvb, offset);
                if( (rem = slen%4) ) slen += 4-rem;
                proto_tree_add_item(message_tree, hf_osc_message_symbol_type, tvb, offset, slen, ENC_ASCII | ENC_NA);
                offset += slen;
                break;
            case OSC_CHAR:
                offset += 3;
                proto_tree_add_item(message_tree, hf_osc_message_char_type, tvb, offset, 1, ENC_ASCII | ENC_NA);
                offset += 1;
                break;
            case OSC_RGBA:
            {
                proto_item *ri = NULL;
                proto_tree *rgba_tree = NULL;

                ri = proto_tree_add_item(message_tree, hf_osc_message_rgba_type, tvb, offset, 4, ENC_BIG_ENDIAN);
                rgba_tree = proto_item_add_subtree(ri, ett_osc_rgba);

                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_red_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_green_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_blue_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_alpha_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
            }
            case OSC_MIDI:
            {
                const gchar *status_str = NULL;
                const gchar *control_str = NULL;
                proto_item *mi = NULL;
                proto_tree *midi_tree = NULL;
                guint8 channel;
                guint8 status;
                guint8 data1;
                guint8 data2;

                channel = tvb_get_guint8(tvb, offset);
                status = tvb_get_guint8(tvb, offset+1);
                data1 = tvb_get_guint8(tvb, offset+2);
                data2 = tvb_get_guint8(tvb, offset+3);

                status_str = val_to_str_const(status, MIDI_status, "Unknown");

                if(status == MIDI_STATUS_CONTROLLER) /* MIDI Controller */
                {
                    control_str = val_to_str_const(data1, MIDI_control, "Unknown");

                    mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                            "MIDI: Channel %2i, %s (0x%02x), %s (0x%02x), 0x%02x",
                            channel,
                            status_str, status,
                            control_str, data1,
                            data2);
                }
                else
                    mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                            "MIDI: Channel %2i, %s (0x%02x), 0x%02x, 0x%02x",
                            channel,
                            status_str, status,
                            data1, data2);
                midi_tree = proto_item_add_subtree(mi, ett_osc_midi);

                proto_tree_add_item(midi_tree, hf_osc_message_midi_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(midi_tree, hf_osc_message_midi_status_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                if(status == MIDI_STATUS_CONTROLLER)
                {
                    proto_tree_add_item(midi_tree, hf_osc_message_midi_controller_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;

                    proto_tree_add_item(midi_tree, hf_osc_message_midi_value_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;
                }
                else
                {
                    proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;

                    proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;
                }

                break;
            }

            default:
                /* if we get here, there must be a bug in the dissector  */
                DISSECTOR_ASSERT_NOT_REACHED();
                break;
        }
        ptr++;
    }

    if(offset != end)
        return -1;
    else
        return 0;
}
Example #16
0
/* Dissect OSC message */
static int
dissect_osc_message(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len)
{
    proto_tree  *message_tree;
    proto_tree  *header_tree;
    gint         slen;
    gint         rem;
    gint         end = offset + len;
    const gchar *path;
    gint         path_len;
    gint         path_offset;
    const gchar *format;
    gint         format_offset;
    gint         format_len;
    const gchar *ptr;

    /* peek/read path */
    path_offset = offset;
    path = tvb_get_const_stringz(tvb, path_offset, &path_len);
    if( (rem = path_len%4) ) path_len += 4-rem;

    if(!is_valid_path(path))
        return -1;

    /* peek/read fmt */
    format_offset = path_offset + path_len;
    format = tvb_get_const_stringz(tvb, format_offset, &format_len);
    if( (rem = format_len%4) ) format_len += 4-rem;

    if(!is_valid_format(format))
        return -1;

    /* create message */
    ti = proto_tree_add_none_format(osc_tree, hf_osc_message_type, tvb, offset, len, "Message: %s %s", path, format);
    message_tree = proto_item_add_subtree(ti, ett_osc_message);

    /* append header */
    ti = proto_tree_add_item(message_tree, hf_osc_message_header_type, tvb, offset, path_len+format_len, ENC_NA);
    header_tree = proto_item_add_subtree(ti, ett_osc_message_header);

    /* append path */
    proto_tree_add_item(header_tree, hf_osc_message_path_type, tvb, path_offset, path_len, ENC_ASCII | ENC_NA);

    /* append format */
    proto_tree_add_item(header_tree, hf_osc_message_format_type, tvb, format_offset, format_len, ENC_ASCII | ENC_NA);

    offset += path_len + format_len;

    /* ::parse argument:: */
    ptr = format + 1; /* skip ',' */
    while( (*ptr != '\0') && (offset < end) )
    {
        switch(*ptr)
        {
            case OSC_INT32:
                proto_tree_add_item(message_tree, hf_osc_message_int32_type, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
            case OSC_FLOAT:
                proto_tree_add_item(message_tree, hf_osc_message_float_type, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
            case OSC_STRING:
                slen = tvb_strsize(tvb, offset);
                if( (rem = slen%4) ) slen += 4-rem;
                proto_tree_add_item(message_tree, hf_osc_message_string_type, tvb, offset, slen, ENC_ASCII | ENC_NA);
                offset += slen;
                break;
            case OSC_BLOB:
            {
                proto_item *bi;
                proto_tree *blob_tree;

                gint32 blen = tvb_get_ntohl(tvb, offset);
                slen = blen;
                if( (rem = slen%4) ) slen += 4-rem;

                bi = proto_tree_add_none_format(message_tree, hf_osc_message_blob_type, tvb, offset, 4+slen, "Blob: %i bytes", blen);
                blob_tree = proto_item_add_subtree(bi, ett_osc_blob);

                proto_tree_add_int_format_value(blob_tree, hf_osc_message_blob_size_type, tvb, offset, 4, blen, "%i bytes", blen);
                offset += 4;

                /* check for zero length blob */
                if(blen == 0)
                    break;

                proto_tree_add_item(blob_tree, hf_osc_message_blob_data_type, tvb, offset, slen, ENC_NA);
                offset += slen;
                break;
            }

            case OSC_TRUE:
                proto_tree_add_item(message_tree, hf_osc_message_true_type, tvb, offset, 0, ENC_NA);
                break;
            case OSC_FALSE:
                proto_tree_add_item(message_tree, hf_osc_message_false_type, tvb, offset, 0, ENC_NA);
                break;
            case OSC_NIL:
                proto_tree_add_item(message_tree, hf_osc_message_nil_type, tvb, offset, 0, ENC_NA);
                break;
            case OSC_BANG:
                proto_tree_add_item(message_tree, hf_osc_message_bang_type, tvb, offset, 0, ENC_NA);
                break;

            case OSC_INT64:
                proto_tree_add_item(message_tree, hf_osc_message_int64_type, tvb, offset, 8, ENC_BIG_ENDIAN);
                offset += 8;
                break;
            case OSC_DOUBLE:
                proto_tree_add_item(message_tree, hf_osc_message_double_type, tvb, offset, 8, ENC_BIG_ENDIAN);
                offset += 8;
                break;
            case OSC_TIMETAG:
            {
                guint32  sec  = tvb_get_ntohl(tvb, offset);
                guint32  frac = tvb_get_ntohl(tvb, offset+4);
                nstime_t ns;
                if( (sec == 0) && (frac == 1) )
                    proto_tree_add_time_format_value(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str);
                else
                    proto_tree_add_item(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
                offset += 8;
            }
                break;

            case OSC_SYMBOL:
                slen = tvb_strsize(tvb, offset);
                if( (rem = slen%4) ) slen += 4-rem;
                proto_tree_add_item(message_tree, hf_osc_message_symbol_type, tvb, offset, slen, ENC_ASCII | ENC_NA);
                offset += slen;
                break;
            case OSC_CHAR:
                offset += 3;
                proto_tree_add_item(message_tree, hf_osc_message_char_type, tvb, offset, 1, ENC_ASCII | ENC_NA);
                offset += 1;
                break;
            case OSC_RGBA:
            {
                proto_item *ri;
                proto_tree *rgba_tree;

                ri = proto_tree_add_item(message_tree, hf_osc_message_rgba_type, tvb, offset, 4, ENC_BIG_ENDIAN);
                rgba_tree = proto_item_add_subtree(ri, ett_osc_rgba);

                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_red_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_green_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_blue_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(rgba_tree, hf_osc_message_rgba_alpha_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
            }
            case OSC_MIDI:
            {
                const gchar *status_str;
                proto_item  *mi = NULL;
                proto_tree  *midi_tree;
                guint8       port;
                guint8       command;
                guint8       data1;
                guint8       data2;
                guint8       status;
                guint8       channel;
                gboolean     system_msg;
                guint8       status_shifted;

                port = tvb_get_guint8(tvb, offset);
                command  = tvb_get_guint8(tvb, offset+1);
                data1   = tvb_get_guint8(tvb, offset+2);
                data2   = tvb_get_guint8(tvb, offset+3);

                status  = command & 0xF0;
                channel = command & 0x0F;

                system_msg = status == 0xF0; /* is system message */
                status_shifted = status >> 4;

                if(system_msg)
                    status_str = val_to_str_ext_const(command, &MIDI_system_ext, "Unknown");
                else
                    status_str = val_to_str_ext_const(status_shifted, &MIDI_status_ext, "Unknown");

                if(system_msg)
                {
                    mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                            "MIDI: Port %i, %s, %i, %i",
                            port, status_str, data1, data2);
                }
                else
                {
                    switch(status_shifted)
                    {
                        case MIDI_STATUS_NOTE_ON:
                        case MIDI_STATUS_NOTE_OFF:
                        case MIDI_STATUS_NOTE_PRESSURE:
                        {
                            const gchar *note_str;
                            note_str = val_to_str_ext_const(data1, &MIDI_note_ext, "Unknown");

                            mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                                    "MIDI: Port %i, Channel %i, %s, %s, %i",
                                    port, channel, status_str, note_str, data2);
                            break;
                        }
                        case MIDI_STATUS_CONTROLLER:
                        {
                            const gchar *control_str;
                            control_str = val_to_str_ext_const(data1, &MIDI_control_ext, "Unknown");

                            mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                                    "MIDI: Port %i, Channel %i, %s, %s, %i",
                                    port, channel, status_str, control_str, data2);
                            break;
                        }
                        case MIDI_STATUS_PITCH_BENDER:
                        {
                            const gint bender = (((gint)data2 << 7) | (gint)data1) - 0x2000;

                            mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                                    "MIDI: Port %i, Channel %i, %s, %i",
                                    port, channel, status_str, bender);
                            break;
                        }
                        default:
                        {
                            mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4,
                                    "MIDI: Port %i, Channel %i, %s, %i, %i",
                                    port, channel, status_str, data1, data2);
                            break;
                        }
                    }
                }
                midi_tree = proto_item_add_subtree(mi, ett_osc_midi);

                proto_tree_add_item(midi_tree, hf_osc_message_midi_port_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                if(system_msg)
                {
                    proto_tree_add_item(midi_tree, hf_osc_message_midi_system_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;

                    proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;

                    proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;
                }
                else
                {
                    proto_tree_add_item(midi_tree, hf_osc_message_midi_status_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(midi_tree, hf_osc_message_midi_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset += 1;

                    switch(status_shifted)
                    {
                        case MIDI_STATUS_NOTE_ON:
                        case MIDI_STATUS_NOTE_OFF:
                        {
                            proto_tree_add_item(midi_tree, hf_osc_message_midi_note_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            proto_tree_add_item(midi_tree, hf_osc_message_midi_velocity_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            break;
                        }
                        case MIDI_STATUS_NOTE_PRESSURE:
                        {
                            proto_tree_add_item(midi_tree, hf_osc_message_midi_note_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            proto_tree_add_item(midi_tree, hf_osc_message_midi_pressure_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            break;
                        }
                        case MIDI_STATUS_CONTROLLER:
                        {
                            proto_tree_add_item(midi_tree, hf_osc_message_midi_controller_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            break;
                        }
                        case MIDI_STATUS_CHANNEL_PRESSURE:
                        {
                            proto_tree_add_item(midi_tree, hf_osc_message_midi_pressure_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            break;
                        }
                        case MIDI_STATUS_PITCH_BENDER:
                        {
                            const gint bender = (((gint)data2 << 7) | (gint)data1) - 0x2000;

                            proto_tree_add_int(midi_tree, hf_osc_message_midi_bender_type, tvb, offset, 2, bender);
                            offset += 2;

                            break;
                        }
                        default:
                        {
                            proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                            offset += 1;

                            break;
                        }
                    }
                }

                break;
            }

            default:
                /* if we get here, there must be a bug in the dissector  */
                DISSECTOR_ASSERT_NOT_REACHED();
                break;
        }
        ptr++;
    }

    if(offset != end)
        return -1;
    else
        return 0;
}
Example #17
0
static void
dissect_omapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_item *ti;
  proto_tree *omapi_tree;
  ptvcursor_t* cursor;

  guint32 authlength;
  guint32 msglength;
  guint32 objlength;


  col_set_str(pinfo->cinfo, COL_PROTOCOL, "OMAPI");

  col_clear(pinfo->cinfo, COL_INFO);

  ti = proto_tree_add_item(tree, proto_omapi, tvb, 0, -1, ENC_NA);
  omapi_tree = proto_item_add_subtree(ti, ett_omapi);
  cursor = ptvcursor_new(omapi_tree, tvb, 0);

  if (tvb_reported_length_remaining(tvb, 0) < 8)
  {
    /* Payload too small for OMAPI */
    DISSECTOR_ASSERT_NOT_REACHED();
  }
  else if (tvb_reported_length_remaining(tvb, 0) < 24)
  {
    /* This is a startup message */
    ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN);

    col_set_str(pinfo->cinfo, COL_INFO, "Status message");
    proto_item_append_text(ti, ", Status message");

    return;
  }
  else if ( !(tvb_get_ntohl(tvb, 8) || tvb_get_ntohl(tvb, 12)) )
  {
    /* This is a startup message, and more */
    ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN);

    col_append_str(pinfo->cinfo, COL_INFO, "Status message");

    proto_item_append_text(ti, ", Status message");
  }

  ptvcursor_add(cursor, hf_omapi_auth_id, 4, ENC_BIG_ENDIAN);
  authlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor));
  ptvcursor_add(cursor, hf_omapi_auth_len, 4, ENC_BIG_ENDIAN);

  col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
      val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)"));

  proto_item_append_text(ti, ", Opcode: %s",
    val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)"));

  ptvcursor_add(cursor, hf_omapi_opcode, 4, ENC_BIG_ENDIAN);
  ptvcursor_add(cursor, hf_omapi_handle, 4, ENC_BIG_ENDIAN);
  ptvcursor_add(cursor, hf_omapi_id, 4, ENC_BIG_ENDIAN);
  ptvcursor_add(cursor, hf_omapi_rid, 4, ENC_BIG_ENDIAN);

  msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  while (msglength)
  {
    ptvcursor_add(cursor, hf_omapi_msg_name_len, 2, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_msg_name, msglength, ENC_ASCII|ENC_NA);
    msglength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor));
    ptvcursor_add(cursor, hf_omapi_msg_value_len, 4, ENC_BIG_ENDIAN);

    if (msglength == 0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string");
    }
    else if (msglength == (guint32)~0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value");
    }
    else
    {
      ptvcursor_add(cursor, hf_omapi_msg_value, msglength, ENC_ASCII|ENC_NA);
    }

    msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  }

  proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Message end tag");
  ptvcursor_advance(cursor, 2);

  objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  while (objlength)
  {
    ptvcursor_add(cursor, hf_omapi_obj_name_len, 2, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_obj_name, objlength, ENC_ASCII|ENC_NA);
    objlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor));
    ptvcursor_add(cursor, hf_omapi_obj_value_len, 4, ENC_BIG_ENDIAN);

    if (objlength == 0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string");
    }
    else if (objlength == (guint32)~0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value");
    }
    else
    {
      ptvcursor_add(cursor, hf_omapi_obj_value, objlength, ENC_NA);
    }

    objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  }

  proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Object end tag");
  ptvcursor_advance(cursor, 2);

  if (authlength > 0) {
    ptvcursor_add(cursor, hf_omapi_signature, authlength, ENC_NA);
  }
}
Example #18
0
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
    gcp_trx_t* t = NULL;
    gcp_trx_msg_t* trxmsg;

    if ( !m ) return NULL;

    if (keep_persistent_data) {
        if (m->committed) {

            for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
                if (trxmsg->trx && trxmsg->trx->id == t_id) {
                    return trxmsg->trx;
                }
            }
            DISSECTOR_ASSERT_NOT_REACHED();
        } else {
            wmem_tree_key_t key[4];

            key[0].length = 1;
            key[0].key = &(m->hi_addr);
            key[1].length = 1;
            key[1].key = &(m->lo_addr);
            key[2].length = 1;
            key[2].key = &(t_id);
            key[3].length = 0;
            key[3].key = NULL;

            trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t);
            t = (gcp_trx_t *)wmem_tree_lookup32_array(trxs,key);

            if (!t) {
                t = wmem_new(wmem_file_scope(), gcp_trx_t);
                t->initial = m;
                t->id = t_id;
                t->type = type;
                t->pendings = 0;
                t->error = 0;
                t->cmds = NULL;

                wmem_tree_insert32_array(trxs,key,t);
            }

            /* XXX: request, reply and ack + point to frames where they are */
            switch ( type ) {
                case GCP_TRX_PENDING:
                    t->pendings++;
                    break;
                default:
                    break;
            }

        }
    } else {
        t = wmem_new(wmem_packet_scope(), gcp_trx_t);
        trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t);
        t->initial = NULL;
        t->id = t_id;
        t->type = type;
        t->pendings = 0;
        t->error = 0;
        t->cmds = NULL;
    }

    DISSECTOR_ASSERT(trxmsg);

    trxmsg->trx = t;
    trxmsg->next = NULL;
    trxmsg->last = trxmsg;

    if (m->trxs) {
        m->trxs->last = m->trxs->last->next = trxmsg;
    } else {
        m->trxs = trxmsg;
    }

    return t;
}
Example #19
0
static
void dissect_pw_cesopsn( tvbuff_t * tvb_original
						,packet_info * pinfo
						,proto_tree * tree
						,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);

	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = PWC_PACKET_PROPERTIES_T_INITIALIZER;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC5086:
		 * [LEN (bits (10 to 15) MAY be used to carry the length of the CESoPSN
		 * packet (defined as the size of the CESoPSN header + the payload size)
		 * if it is less than 64 bytes, and MUST be set to zero otherwise.
		 * Note:  If fixed RTP header is used in the encapsulation, it is
		 * considered part of the CESoPSN header.]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC5086's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}

	{
		guint8 cw_lm;
		cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/;
		if (NULL == try_val_to_str(cw_lm, vals_cw_lm))
		{
			properties |= PWC_CW_SUSPECT_LM;
		}

		{
			guint8 l_bit, m_bits;
			l_bit  = (cw_lm & 0x08) >> 3;
			m_bits = (cw_lm & 0x03) >> 0;
			if ((l_bit == 0 && m_bits == 0x0) /*CESoPSN data packet - normal situation*/
			    ||(l_bit == 0 && m_bits == 0x2) /*CESoPSN data packet - RDI on the AC*/ )
			{
				if ((payload_size == 0) || ((payload_size % 8) != 0))
				{
					properties |= PWC_PAY_SIZE_BAD;
				}
			}
			else if (l_bit == 1 && m_bits == 0x0) /*TDM data is invalid; payload MAY be omitted*/
			{
				/*allow any size of payload*/
			}
			else /*reserved combinations*/
			{
				/*allow any size of payload*/
			}
		}
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}
	else if (properties & PWC_ANYOF_CW_SUSPECT)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "CW:Suspect, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
	}

	col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}

	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset(tvb_original, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2,tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_lm,  tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_SUSPECT_LM)
						{
							expert_add_info(pinfo, item3, &ei_cw_lm);
						}

						proto_tree_add_item(tree3, hf_cw_r, tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be 0 if CESoPSN packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);

					}
				}
			}
		}

		/* payload */
		if (payload_size == 0)
		{
			if (properties & PWC_PAY_SIZE_BAD)
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_error,
					"CESoPSN payload: none found. Size of payload must be <> 0");
			}
			else
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_undecoded,
					"CESoPSN payload: omitted to conserve bandwidth");
			}
		}
		else
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW, payload_size, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				if (properties & PWC_PAY_SIZE_BAD)
				{
					expert_add_info_format(pinfo, item2, &ei_payload_size_invalid_error,
						"CESoPSN packet payload size must be multiple of 8");
				}
				tree2 = proto_item_add_subtree(item2, ett);
				call_dissector(data_handle, tvb, pinfo, tree2);
				item2 = proto_tree_add_int(tree2, hf_payload_l, tvb, 0, 0
					,(int)payload_size); /* allow filtering */
				PROTO_ITEM_SET_HIDDEN(item2);
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
Example #20
0
static int
dissect_mint_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
	guint32 offset, guint32 packet_length, guint received_via)
{
	proto_item *ti;
	proto_tree *mint_tree = NULL;
	proto_tree *mint_header_tree = NULL;
	proto_tree *mint_data_tree = NULL;
	proto_tree *mint_ctrl_tree = NULL;
	guint16 bytes_remaining;
	guint16 packet_type;
	guint8 type, length, header_length;
	guint32 message_type;
	guint8 element_length;
	static header_field_info *display_hfi_tlv_vals;

	packet_type = tvb_get_ntohs(tvb, offset + 12);

	col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
	col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type,
		mint_packettype_vals, "Type 0x%02x"));

	ti = proto_tree_add_item(tree, hfi_mint, tvb,
		offset, packet_length, ENC_NA);
	mint_tree = proto_item_add_subtree(ti, ett_mint);

	ti = proto_tree_add_item(mint_tree, &hfi_mint_header, tvb,
		offset, 16, ENC_NA);
	mint_header_tree = proto_item_add_subtree(ti, ett_mint_header);

	/* MiNT header */
	proto_tree_add_item(mint_header_tree, &hfi_mint_header_unknown1, tvb,
		offset, 4, ENC_NA);
	offset += 4;
	proto_tree_add_item(mint_header_tree, &hfi_mint_header_dstid, tvb,
		offset, 4, ENC_NA);
	offset += 4;
	proto_tree_add_item(mint_header_tree, &hfi_mint_header_srcid, tvb,
		offset, 4, ENC_NA);
	offset += 4;
	proto_tree_add_item(mint_header_tree, &hfi_mint_header_dstdatatype, tvb,
		offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(mint_header_tree, &hfi_mint_header_srcdatatype, tvb,
		offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	/* FIXME: This is probably not the right way to determine the packet type.
	 *	  It's more likely something in mint_header_unknown1 but I haven't
	 *        found out what. */
	switch(packet_type) {
	case MINT_TYPE_DATA_UC:
		ti = proto_tree_add_item(mint_tree, &hfi_mint_data, tvb,
			offset, packet_length - 16, ENC_NA);
		mint_data_tree = proto_item_add_subtree(ti, ett_mint_data);
		proto_tree_add_item(mint_data_tree, &hfi_mint_data_unknown1, tvb,
			offset, 2, ENC_NA);
		offset += 2;
		/* Transported user frame */
		if (offset < packet_length)
			offset += dissect_eth_frame(tvb, pinfo, tree,
				offset, packet_length - offset);
		break;
	case MINT_TYPE_DATA_BCMC:
		ti = proto_tree_add_item(mint_tree, &hfi_mint_data, tvb,
			offset, packet_length - 16, ENC_NA);
		mint_data_tree = proto_item_add_subtree(ti, ett_mint_data);
		/* Decode as vlan only for now. To be verified against a capture
		 * with CoS != 0 */
		proto_tree_add_item(mint_data_tree, &hfi_mint_data_vlan, tvb,
			offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(mint_data_tree, &hfi_mint_data_seqno, tvb,
			offset, 4, ENC_NA);
		offset += 4;
		proto_tree_add_item(mint_data_tree, &hfi_mint_data_unknown1, tvb,
			offset, 4, ENC_NA);
		offset += 4;
		/* Transported user frame */
		if (offset < packet_length)
			offset += dissect_eth_frame(tvb, pinfo, tree,
				offset, packet_length - offset);
		break;
	case MINT_TYPE_CTRL_0x0c:
		ti = proto_tree_add_item(mint_tree, &hfi_mint_control, tvb,
			offset, packet_length - 16, ENC_NA);
		mint_ctrl_tree = proto_item_add_subtree(ti, ett_mint_ctrl);
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_32zerobytes, tvb,
			offset, 32, ENC_NA);
		offset += 32;

		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_unknown1, tvb,
			offset, 1, ENC_NA);
		offset += 1;
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_unknown2, tvb,
			offset, 1, ENC_NA);
		offset += 1;
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_unknown3, tvb,
			offset, 1, ENC_NA);
		offset += 1;
		header_length = tvb_get_guint8(tvb, offset);
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_header_length, tvb,
			offset, 1, ENC_NA);
		offset += 1;
		message_type = tvb_get_ntohl(tvb, offset);
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_message_type, tvb,
			offset, 4, ENC_NA);
		offset += 4;
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_header_sender, tvb,
			offset, 4, ENC_NA);
		offset += 4;
		switch (message_type) {
			case 0x43534E50: /* CSNP */
				element_length = 12;
				display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_csnp;
				break;
			case 0x48454C4F: /* HELO */
				element_length = 0;
				display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_helo;
				break;
			case 0x4C535000: /* LSP */
				element_length = 8;
				display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_lsp;
				break;
			case 0x50534E50: /* PSNP */
				element_length = 4;
				display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_psnp;
				break;
			default:
				element_length = 0;
				display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_unknown;
		}
		/* FIXME: This should go into the per message_type switch above */
		if (header_length > 12) {
			proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_header_unknown, tvb,
				offset, header_length - 12, ENC_NA);
			offset += header_length - 12;
		}
		while (offset < packet_length - 2) {
			type = tvb_get_guint8(tvb, offset);
			proto_tree_add_item(mint_ctrl_tree, display_hfi_tlv_vals, tvb,
				offset, 1, ENC_NA);
			offset += 1;
			length = tvb_get_guint8(tvb, offset);
			/* FIXME: This is a hack - reliable array detection missing */
			if (type == 1 && length == 128) {
				proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_array, tvb,
					offset, 1, ENC_NA);
				offset += 1;
				length = tvb_get_guint8(tvb, offset);
			}
			proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_length, tvb,
				offset, 1, ENC_NA);
			offset += 1;
			if (offset + length > packet_length) {
				/* FIXME: print expert information */
				break;
			}
			if (type == 1 && element_length) {
				guint32 end_offset = offset + length;
				for (; offset < end_offset; offset += element_length) {
					proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_element, tvb,
						offset, element_length, ENC_NA);
				}
			} else {
				proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_value, tvb,
					offset, length, ENC_NA);
				offset += length;
			}
		}
		break;
	case MINT_TYPE_CTRL_0x1e:
		ti = proto_tree_add_item(mint_tree, &hfi_mint_control, tvb,
			offset, packet_length - 16, ENC_NA);
		mint_ctrl_tree = proto_item_add_subtree(ti, ett_mint_ctrl);
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_32zerobytes, tvb,
			offset, 32, ENC_NA);
		offset += 32;
		bytes_remaining = packet_length - offset;
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x1e_unknown, tvb,
			offset, bytes_remaining, ENC_NA);
		offset += bytes_remaining;
		break;
	case MINT_TYPE_ETH_0x22:
		ti = proto_tree_add_item(mint_tree, &hfi_mint_control, tvb,
			offset, packet_length - 16, ENC_NA);
		mint_ctrl_tree = proto_item_add_subtree(ti, ett_mint_ctrl);
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_32zerobytes, tvb,
			offset, 32, ENC_NA);
		offset += 32;
		proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_message, tvb,
			offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		while (offset < packet_length - 2) {
			proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_type, tvb,
				offset, 1, ENC_NA);
			offset += 1;
			length = tvb_get_guint8(tvb, offset);
			proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_length, tvb,
				offset, 1, ENC_NA);
			offset += 1;
			if (offset + length > packet_length) {
				/* print expert information */
				break;
			}
			proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_value, tvb,
				offset, length, ENC_NA);
			offset += length;
		}
		break;
	default:
		bytes_remaining = packet_length - offset;
		switch(received_via) {
		case PORT_MINT_CONTROL_TUNNEL:
		case ETHERTYPE_MINT:
			proto_tree_add_item(mint_tree, &hfi_mint_control_unknown1, tvb,
				offset, bytes_remaining, ENC_NA);
			break;
		case PORT_MINT_DATA_TUNNEL:
			proto_tree_add_item(mint_tree, &hfi_mint_data_unknown1, tvb,
				offset, bytes_remaining, ENC_NA);
			break;
		default:
			DISSECTOR_ASSERT_NOT_REACHED();
		}
		offset += bytes_remaining;
		break;
	}
#if defined MINT_DEVELOPMENT
	tree_expanded_set(ett_mint, TRUE);
	tree_expanded_set(ett_mint_ethshim, TRUE);
	tree_expanded_set(ett_mint_header, TRUE);
	tree_expanded_set(ett_mint_ctrl, TRUE);
	tree_expanded_set(ett_mint_data, TRUE);
#endif
	return offset;
}
Example #21
0
gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent) {
    gcp_terms_t* ct;
    gcp_terms_t* ct2;

    static gcp_term_t all_terms = {"$",(guint8*)"",1,GCP_TERM_TYPE_UNKNOWN,NULL,NULL,NULL};

    if ( !c ) return NULL;

    if ( wildcard == GCP_WILDCARD_CHOOSE) {
        return &all_terms;
    }

    if (persistent) {
        if ( c->msg->commited ) {
            if (wildcard == GCP_WILDCARD_ALL) {
                for (ct = c->ctx->terms.next; ct; ct = ct->next) {
                    /* XXX not handling more wilcards in one msg */
                    if ( ct->term->start == m ) {
                        return ct->term;
                    }
                }
                return NULL;
            } else {
                for (ct = c->ctx->terms.next; ct; ct = ct->next) {
                    if ( g_str_equal(ct->term->str,t->str) ) {
                        return ct->term;
                    }
                }
                return NULL;
            }
        } else {

            for (ct = c->ctx->terms.next; ct; ct = ct->next) {
                if ( g_str_equal(ct->term->str,t->str) || ct->term->start == m) {
                    break;
                }
            }

            if ( ! ct ) {

                if (wildcard == GCP_WILDCARD_ALL) {
                    ct = se_alloc(sizeof(gcp_terms_t));
                    ct->next = NULL;
                    ct->term = se_alloc0(sizeof(gcp_term_t));

                    ct->term->start = m;
                    ct->term->str = "*";
                    ct->term->buffer = NULL;
                    ct->term->len = 0;

                    c->terms.last = c->terms.last->next = ct;

                    ct2 = se_alloc0(sizeof(gcp_terms_t));
                    ct2->term = ct->term;

                    c->ctx->terms.last->next = ct2;
                    c->ctx->terms.last = ct2;

                    return ct->term;
                } else {
                    for (ct = c->ctx->terms.next; ct; ct = ct->next) {
                        /* XXX not handling more wilcards in one msg */
                        if ( ct->term->buffer == NULL && tr->cmds->cmd->msg == ct->term->start ) {
                            ct->term->str = se_strdup(t->str);
                            ct->term->buffer = se_memdup(t->buffer,t->len);
                            ct->term->len = t->len;

                            ct2 = se_alloc0(sizeof(gcp_terms_t));
                            ct2->term = ct->term;

                            c->terms.last = c->terms.last->next = ct2;

                            return ct->term;
                        }

                        if  ( g_str_equal(ct->term->str,t->str) ) {
                            ct2 = se_alloc0(sizeof(gcp_terms_t));
                            ct2->term = ct->term;

                            c->terms.last = c->terms.last->next = ct2;

                            return ct->term;
                        }
                    }

                    ct = se_alloc(sizeof(gcp_terms_t));
                    ct->next = NULL;
                    ct->term = se_alloc0(sizeof(gcp_term_t));

                    ct->term->start = m;
                    ct->term->str = se_strdup(t->str);
                    ct->term->buffer = se_memdup(t->buffer,t->len);
                    ct->term->len = t->len;

                    ct2 = se_alloc0(sizeof(gcp_terms_t));
                    ct2->term = ct->term;

                    c->terms.last = c->terms.last->next = ct2;

                    ct2 = se_alloc0(sizeof(gcp_terms_t));
                    ct2->term = ct->term;

                    c->ctx->terms.last = c->ctx->terms.last->next = ct2;

                    return ct->term;
                }
            } else {
                ct2 = se_alloc0(sizeof(gcp_terms_t));
                ct2->term = ct->term;

                c->terms.last = c->terms.last->next = ct2;
                return ct->term;
            }

            DISSECTOR_ASSERT_NOT_REACHED();
            return NULL;
        }
    } else {
        ct = ep_new(gcp_terms_t);
        ct->term = t;
        ct->next = NULL;
        c->terms.last = c->terms.last->next = ct;

        return t;
    }

}
Example #22
0
static void
dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
{
  proto_tree *udp_tree = NULL;
  proto_item *ti, *hidden_item, *port_item;
  guint      len;
  guint      reported_len;
  vec_t      cksum_vec[4];
  guint32    phdr[2];
  guint16    computed_cksum;
  int        offset = 0;
  e_udphdr *udph;
  proto_tree *checksum_tree;
  proto_item *item;
  conversation_t *conv = NULL;
  struct udp_analysis *udpd = NULL;
  proto_tree *process_tree;

  udph=ep_new(e_udphdr);
  SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
  SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);

  col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite");
  col_clear(pinfo->cinfo, COL_INFO);

  udph->uh_sport=tvb_get_ntohs(tvb, offset);
  udph->uh_dport=tvb_get_ntohs(tvb, offset+2);

  col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s  Destination port: %s",
    get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport));

  if (tree) {
    if (udp_summary_in_tree) {
      if (ip_proto == IP_PROTO_UDP) {
        ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
        "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
        get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
      } else {
        ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8,
        "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
        get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
      }
    } else {
      ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA);
    }
    udp_tree = proto_item_add_subtree(ti, ett_udp);

    port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport,
	"Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
    /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code
     * further assumes that 3 attempts are made per hop */
    if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30)
	    expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u",
				   ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1,
				   ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1
				   );

    port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
	"Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
    if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30)
	    expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u",
				   ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1,
				   ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1
				   );

    hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
  }

  if (ip_proto == IP_PROTO_UDP) {
    udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
    if (udph->uh_ulen < 8) {
      /* Bogus length - it includes the header, so it must be >= 8. */
      /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */
      item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
          udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen);
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen);
      return;
    }
    if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) {
      /* Bogus length - it goes past the end of the IP payload */
      item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
          udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb));
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen);
    } else {
      if (tree) {
        proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
        /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */
        hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4,
                                          0, udph->uh_sum_cov);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
      }
    }
  } else {
    udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen;
    udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
    if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) {
      /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */
      if (tree) {
        hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
      }
      item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2,
          udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))",
          udph->uh_sum_cov, udph->uh_ulen);
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u",
                             udph->uh_sum_cov, udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]",
                        udph->uh_sum_cov, udph->uh_ulen);
      if (!udplite_ignore_checksum_coverage)
        return;
    } else {
      if (tree) {
        hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov);
      }
    }
  }

  udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen;
  udph->uh_sum = tvb_get_ntohs(tvb, offset+6);
  reported_len = tvb_reported_length(tvb);
  len = tvb_length(tvb);
  if (udph->uh_sum == 0) {
    /* No checksum supplied in the packet. */
    if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
        "Checksum: 0x%04x (none)", 0);

      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
    } else {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
        "Checksum: 0x%04x (Illegal)", 0);
      expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)");
      col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]");

      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, TRUE);
      PROTO_ITEM_SET_GENERATED(item);
    }
  } else if (!pinfo->fragmented && len >= reported_len &&
             len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov &&
             udph->uh_sum_cov >=8) {
    /* The packet isn't part of a fragmented datagram and isn't
       truncated, so we can checksum it.
       XXX - make a bigger scatter-gather list once we do fragment
       reassembly? */

    if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) ||
        ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) {
      /* Set up the fields of the pseudo-header. */
      cksum_vec[0].ptr = (const guint8 *)pinfo->src.data;
      cksum_vec[0].len = pinfo->src.len;
      cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data;
      cksum_vec[1].len = pinfo->dst.len;
      cksum_vec[2].ptr = (const guint8 *)&phdr;
      switch (pinfo->src.type) {

      case AT_IPv4:
        if (ip_proto == IP_PROTO_UDP)
          phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen);
	else
          phdr[0] = g_htonl((ip_proto<<16) | reported_len);
        cksum_vec[2].len = 4;
        break;

      case AT_IPv6:
        if (ip_proto == IP_PROTO_UDP)
          phdr[0] = g_htonl(udph->uh_ulen);
	else
          phdr[0] = g_htonl(reported_len);
        phdr[1] = g_htonl(ip_proto);
        cksum_vec[2].len = 8;
        break;

      default:
        /* UDP runs only atop IPv4 and IPv6.... */
        DISSECTOR_ASSERT_NOT_REACHED();
        break;
      }
      cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov);
      cksum_vec[3].len = udph->uh_sum_cov;
      computed_cksum = in_cksum(&cksum_vec[0], 4);
      if (computed_cksum == 0) {
        item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
          offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum);

        checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                                      offset + 6, 2, TRUE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                                      offset + 6, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      } else {
        item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
                                          offset + 6, 2, udph->uh_sum,
          "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum,
          in_cksum_shouldbe(udph->uh_sum, computed_cksum));

        checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                                      offset + 6, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                                      offset + 6, 2, TRUE);
        PROTO_ITEM_SET_GENERATED(item);
        expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");

        col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]");
      }
    } else {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
        offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum);
      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
    }
  } else {
    item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
      offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum);

    checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
    item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
    PROTO_ITEM_SET_GENERATED(item);
    item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
    PROTO_ITEM_SET_GENERATED(item);
  }

  /* Skip over header */
  offset += 8;

  pinfo->ptype = PT_UDP;
  pinfo->srcport = udph->uh_sport;
  pinfo->destport = udph->uh_dport;

  tap_queue_packet(udp_tap, pinfo, udph);

  /* find(or create if needed) the conversation for this udp session */
  if (udp_process_info) {
    conv=find_or_create_conversation(pinfo);
    udpd=get_udp_conversation_data(conv,pinfo);
  }

  if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) {
    ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information");
	PROTO_ITEM_SET_GENERATED(ti);
    process_tree = proto_item_add_subtree(ti, ett_udp_process_info);
	if (udpd->fwd && udpd->fwd->command) {
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0,
              udpd->fwd->process_uid, "%u", udpd->fwd->process_uid);
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0,
              udpd->fwd->process_pid, "%u", udpd->fwd->process_pid);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0,
              udpd->fwd->username, "%s", udpd->fwd->username);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0,
              udpd->fwd->command, "%s", udpd->fwd->command);
    }
    if (udpd->rev->command) {
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0,
              udpd->rev->process_uid, "%u", udpd->rev->process_uid);
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0,
              udpd->rev->process_pid, "%u", udpd->rev->process_pid);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0,
              udpd->rev->username, "%s", udpd->rev->username);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0,
              udpd->rev->command, "%s", udpd->rev->command);
    }
  }

  /*
   * Call sub-dissectors.
   *
   * XXX - should we do this if this is included in an error packet?
   * It might be nice to see the details of the packet that caused the
   * ICMP error, but it might not be nice to have the dissector update
   * state based on it.
   * Also, we probably don't want to run UDP taps on those packets.
   *
   * We definitely don't want to do it for an error packet if there's
   * nothing left in the packet.
   */
  if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
    decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport,
                     udph->uh_ulen);
}
Example #23
0
static
void dissect_pw_satop(tvbuff_t * tvb_original
					,packet_info * pinfo
					,proto_tree * tree
					,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	enum {
		PAY_NO_IDEA = 0
		,PAY_LIKE_E1
		,PAY_LIKE_T1
		,PAY_LIKE_E3_T3
		,PAY_LIKE_OCTET_ALIGNED_T1
	} payload_properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);
	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_cw_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = 0;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/))
	{
		properties |= PWC_CW_BAD_RSV;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC4553:
		 * [...MAY be used to carry the length of the SAToP
		 * packet (defined as the size of the SAToP header + the payload
		 * size) if it is less than 64 bytes, and MUST be set to zero
		 * otherwise... ]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC4553's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}
	if (payload_size == 0)
	{
		/*
		 * As CW.L it indicates that PW payload is invalid, dissector should
		 * not blame packets with bad payload (including "bad" or "strange" SIZE of
		 * payload) when L bit is set.
		 */
		if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/))
		{
			properties |= PWC_PAY_SIZE_BAD;
		}
	}

	/* guess about payload type */
	if (payload_size == 256)
	{
		payload_properties = PAY_LIKE_E1;
	}
	else if (payload_size == 192)
	{
		payload_properties = PAY_LIKE_T1;
	}
	else if (payload_size == 1024)
	{
		payload_properties = PAY_LIKE_E3_T3;
	}
	else if ((payload_size != 0) && (payload_size % 25 == 0))
	{
		payload_properties = PAY_LIKE_OCTET_ALIGNED_T1;
	}
	else
	{
		payload_properties = PAY_NO_IDEA; /*we do not have any ideas about payload type*/
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:0 (Bad)");
	}
	else
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);
	}

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}


	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2, tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item2, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						proto_tree_add_item(tree3, hf_cw_l  , tvb, 0, 1, ENC_BIG_ENDIAN);
						proto_tree_add_item(tree3, hf_cw_r  , tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_RSV)
						{
							expert_add_info(pinfo, item3, &ei_cw_rsv);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: must be 0 if SAToP packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);
					}
				}
			}
		}

		/* payload */
		if (properties & PWC_PAY_SIZE_BAD)
		{
			expert_add_info_format(pinfo, item, &ei_payload_size_invalid,
				"SAToP payload: none found. Size of payload must be <> 0");
		}
		else if (payload_size == 0)
		{
			expert_add_info(pinfo, item, &ei_payload_size_invalid_undecoded);
		}
		else
		{

			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				{
					proto_tree* tree3;
					const char* s;
					switch(payload_properties)
					{
					case PAY_LIKE_E1:
						s = " (looks like E1)";
						break;
					case PAY_LIKE_T1:
						s = " (looks like T1)";
						break;
					case PAY_LIKE_E3_T3:
						s = " (looks like E3/T3)";
						break;
					case PAY_LIKE_OCTET_ALIGNED_T1:
						s = " (looks like octet-aligned T1)";
						break;
					case PAY_NO_IDEA:
					default:
						s = "";
						break;
					}
					proto_item_append_text(item2, "%s", s);
					tree3 = proto_item_add_subtree(item2, ett);
					call_data_dissector(tvb, pinfo, tree3);
					item2 = proto_tree_add_int(tree3, hf_payload_l, tvb, 0, 0
						,(int)payload_size); /* allow filtering */
					PROTO_ITEM_SET_HIDDEN(item2);
				}
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
Example #24
0
static void
dissect_stt_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree)
{
    proto_tree *checksum_tree;
    proto_item *item;
    guint16 checksum = tvb_get_ntohs(tvb, 16);
    gboolean can_checksum;
    guint16 computed_cksum;
    gboolean checksum_good = FALSE, checksum_bad = FALSE;

    item = proto_tree_add_uint_format_value(stt_tree, hf_stt_checksum,
                                            tvb, 16, 2, checksum,
                                            "0x%04x", checksum);

    can_checksum = !pinfo->fragmented &&
                   tvb_bytes_exist(tvb, 0, tvb_reported_length(tvb));

    if (can_checksum && pref_check_checksum) {
        vec_t      cksum_vec[4];
        guint32    phdr[2];

        /* Set up the fields of the pseudo-header. */
        SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data,
                          pinfo->src.len);
        SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data,
                          pinfo->dst.len);
        switch (pinfo->src.type) {
        case AT_IPv4:
            phdr[0] = g_htonl((IP_PROTO_TCP<<16) + tvb_reported_length(tvb));
            SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4);
            break;

        case AT_IPv6:
            phdr[0] = g_htonl(tvb_reported_length(tvb));
            phdr[1] = g_htonl(IP_PROTO_TCP);
            SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8);
            break;

        default:
            /* STT runs only atop IPv4 and IPv6.... */
            DISSECTOR_ASSERT_NOT_REACHED();
            break;
        }
        SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, tvb_reported_length(tvb));
        computed_cksum = in_cksum(cksum_vec, 4);

        checksum_good = (computed_cksum == 0);
        checksum_bad = !checksum_good;

        if (checksum_good) {
            proto_item_append_text(item, " [correct]");
        } else if (checksum_bad) {
            guint16 expected_cksum = in_cksum_shouldbe(checksum, computed_cksum);

            proto_item_append_text(item, " [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]",
                                   expected_cksum);

            expert_add_info(pinfo, item, &ei_stt_checksum_bad);
            checksum = expected_cksum;
        }
    } else if (pref_check_checksum) {
        proto_item_append_text(item, " [unchecked, not all data available]");
    } else {
        proto_item_append_text(item, " [validation disabled]");
    }

    checksum_tree = proto_item_add_subtree(item, ett_stt_checksum);

    if (checksum_good || checksum_bad) {
        item = proto_tree_add_uint(checksum_tree, hf_stt_checksum_calculated,
                                   tvb, 16, 2, checksum);
        PROTO_ITEM_SET_GENERATED(item);
    }
    item = proto_tree_add_boolean(checksum_tree, hf_stt_checksum_good, tvb,
                                  16, 2, checksum_good);
    PROTO_ITEM_SET_GENERATED(item);
    item = proto_tree_add_boolean(checksum_tree, hf_stt_checksum_bad, tvb,
                                  16, 2, checksum_bad);
    PROTO_ITEM_SET_GENERATED(item);
}