Example #1
0
    proto_item *ti;
    proto_tree *ax25_tree;
    int offset;
    int via_index;
    char *info_buffer;
    /* char v2cmdresp; */
    const char *ax25_version;
    int is_response;
    guint8 control;
    guint8 pid = AX25_P_NO_L3;
    guint8 src_ssid;
    guint8 dst_ssid;
    tvbuff_t *next_tvb = NULL;


    info_buffer = (char *)wmem_alloc( wmem_packet_scope(), STRLEN );
    info_buffer[0] = '\0';

    col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25" );
    col_clear( pinfo->cinfo, COL_INFO );

    /* start at the dst addr */
    offset = 0;
    /* create display subtree for the protocol */
    ti = proto_tree_add_protocol_format( parent_tree, proto_ax25, tvb, offset, -1, "AX.25");
    ax25_tree = proto_item_add_subtree( ti, ett_ax25 );

    proto_tree_add_item( ax25_tree, hf_ax25_dst, tvb, offset, AX25_ADDR_LEN, ENC_NA);
    set_address_tvb(&pinfo->dl_dst, AT_AX25, AX25_ADDR_LEN, tvb, offset);
    copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
    dst_ssid = tvb_get_guint8(tvb, offset+6);
Example #2
0
static void dissect_cimd_ud(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset)
{
  /* Set up structures needed to add the param subtree and manage it */
  proto_tree *param_tree;

  gchar *payloadText, *tmpBuffer, *tmpBuffer1;
  int    loop,i,poz, bufPoz = 0, bufPoz1 = 0, size, size1, resch;
  gint   g_offset, g_size;
  gchar  token[4];
  gchar  ch;
  static const char* mapping[128]  = {
    "_Oa" , "_L-", ""    , "_Y-", "_e`", "_e'", "_u`", "_i`", "_o`", "_C,",        /*10*/
    ""    , "_O/", "_o/" , ""   , "_A*", "_a*", "_gd", "_--", "_gf", "_gg", "_gl", /*21*/
    "_go" , "_gp", "_gi" , "_gs", "_gt", "_gx", "_XX", "_AE", "_ae", "_ss", "_E'", /*32*/
    ""    , ""   , "_qq" , ""   , "_ox", ""   , ""   , ""   , ""   , ""   , ""   , ""    , ""    , ""   , "", "",
    ""    , ""   , ""    , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""    , ""    , ""   , "", "",
    "_!!" , ""   , ""    , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""    , ""    , ""   , "", "",
    ""    , ""   , ""    , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""   , "_A\"", "_O\"", "_N~",
    "_U\"", "_so", "_??" , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""    , ""    , ""   ,
    ""    , ""   , ""    , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""   , ""    , ""    , ""   , "", "_a\"",
    "_o\"", "_n~", "_n\"","_a`"
  };

  param_tree = proto_tree_add_subtree(tree, tvb,
    startOffset + 1, endOffset - (startOffset + 1),
    (*vals_hdr_PC[pindex].ett_p), NULL, cimd_vals_PC[pindex].strptr
  );
  proto_tree_add_item(param_tree, hf_cimd_pcode_indicator, tvb,
    startOffset + 1, CIMD_PC_LENGTH, ENC_ASCII|ENC_NA);

  g_offset = startOffset + 1 + CIMD_PC_LENGTH + 1;
  g_size   = endOffset - g_offset;

  payloadText = tvb_format_text(tvb, g_offset, g_size);
  size = (int)strlen(payloadText);
  tmpBuffer = (gchar*)wmem_alloc(wmem_packet_scope(), size+1);
  for (loop = 0; loop < size; loop++)
  {
    if (payloadText[loop] == '_')
    {
      if (loop < size - 2)
      {
        token[0] = payloadText[loop++];
        token[1] = payloadText[loop++];
        token[2] = payloadText[loop];
        token[3] = '\0';
        poz = -1;
        for (i = 0; i < 128; i++)
        {
          if (strcmp(token, mapping[i]) == 0)
          {
            poz = i;
            break;
          }
        }
        if (poz > 0)
        {
          tmpBuffer[bufPoz++] = poz;
        }
        else
        {
          tmpBuffer[bufPoz++] = payloadText[loop-2];
          tmpBuffer[bufPoz++] = payloadText[loop-1];
          tmpBuffer[bufPoz++] = payloadText[loop];
        }
      }
      else
      {
        if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++];
        if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++];
        if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++];
      }
    }
    else
    {
      tmpBuffer[bufPoz++] = payloadText[loop];
    }
  }
  tmpBuffer[bufPoz] = '\0';

  size1 = (int)strlen(tmpBuffer);
  tmpBuffer1 = (gchar*)wmem_alloc(wmem_packet_scope(), size1+1);
  for (loop=0; loop<size1; loop++)
  {
    ch = tmpBuffer[loop];
    switch ((gint)ch)
    {
    case 0x40: resch = 0x0040; break;
    case 0x01: resch = 0x00A3; break;
    case 0x02: resch = 0x0024; break;
    case 0x03: resch = 0x00A5; break;
    case 0x04: resch = 0x00E8; break;
    case 0x05: resch = 0x00E9; break;
    case 0x06: resch = 0x00F9; break;
    case 0x07: resch = 0x00EC; break;
    case 0x08: resch = 0x00F2; break;
    case 0x09: resch = 0x00E7; break;
    case 0x0B: resch = 0x00D8; break;
    case 0x0C: resch = 0x00F8; break;
    case 0x0E: resch = 0x00C5; break;
    case 0x0F: resch = 0x00E5; break;
    case 0x11: resch = 0x005F; break;
/*  case 0x1B14: resch = 0x005E; break; */
/*  case 0x1B28: resch = 0x007B; break; */
/*  case 0x1B29: resch = 0x007D; break; */
/*  case 0x1B2F: resch = 0x005C; break; */
/*  case 0x1B3C: resch = 0x005B; break; */
/*  case 0x1B3D: resch = 0x007E; break; */
/*  case 0x1B3E: resch = 0x005D; break; */
/*  case 0x1B40: resch = 0x007C; break; */
    case 0x1C: resch = 0x00C6; break;
    case 0x1D: resch = 0x00E6; break;
    case 0x1E: resch = 0x00DF; break;
    case 0x1F: resch = 0x00C9; break;
    case 0x20: resch = 0x0020; break;
    case 0x21: resch = 0x0021; break;
    case 0x22: resch = 0x0022; break;
    case 0x23: resch = 0x0023; break;
    case 0xA4: resch = 0x00A4; break;
    case 0x25: resch = 0x0025; break;
    case 0x26: resch = 0x0026; break;
    case 0x27: resch = 0x0027; break;
    case 0x28: resch = 0x0028; break;
    case 0x29: resch = 0x0029; break;
    case 0x2A: resch = 0x002A; break;
    case 0x2B: resch = 0x002B; break;
    case 0x2C: resch = 0x002C; break;
    case 0x2D: resch = 0x002D; break;
    case 0x2E: resch = 0x002E; break;
    case 0x2F: resch = 0x002F; break;
    case 0x30: resch = 0x0030; break;
    case 0x31: resch = 0x0031; break;
    case 0x32: resch = 0x0032; break;
    case 0x33: resch = 0x0033; break;
    case 0x34: resch = 0x0034; break;
    case 0x35: resch = 0x0035; break;
    case 0x36: resch = 0x0036; break;
    case 0x37: resch = 0x0037; break;
    case 0x38: resch = 0x0038; break;
    case 0x39: resch = 0x0039; break;
    case 0x3A: resch = 0x003A; break;
    case 0x3B: resch = 0x003B; break;
    case 0x3C: resch = 0x003C; break;
    case 0x3D: resch = 0x003D; break;
    case 0x3E: resch = 0x003E; break;
    case 0x3F: resch = 0x003F; break;
/*  case 0x40: resch = 0x00A1; break; */
    case 0x41: resch = 0x0041; break;
    case 0x42: resch = 0x0042; break;
/*  case 0x42: resch = 0x0392; break; */
    case 0x43: resch = 0x0043; break;
    case 0x44: resch = 0x0044; break;
    case 0x45: resch = 0x0045; break;
    case 0x46: resch = 0x0046; break;
    case 0x47: resch = 0x0047; break;
    case 0x48: resch = 0x0048; break;
    case 0x49: resch = 0x0049; break;
    case 0x4A: resch = 0x004A; break;
    case 0x4B: resch = 0x004B; break;
    case 0x4C: resch = 0x004C; break;
    case 0x4D: resch = 0x004D; break;
    case 0x4E: resch = 0x004E; break;
    case 0x4F: resch = 0x004F; break;
    case 0x50: resch = 0x0050; break;
    case 0x51: resch = 0x0051; break;
    case 0x52: resch = 0x0052; break;
    case 0x53: resch = 0x0053; break;
    case 0x54: resch = 0x0054; break;
    case 0x55: resch = 0x0055; break;
    case 0x56: resch = 0x0056; break;
    case 0x57: resch = 0x0057; break;
    case 0x58: resch = 0x0058; break;
    case 0x59: resch = 0x0059; break;
    case 0x5A: resch = 0x005A; break;
    case 0x5B: resch = 0x00C4; break;
    case 0x5C: resch = 0x00D6; break;
    case 0x5D: resch = 0x00D1; break;
    case 0x5E: resch = 0x00DC; break;
    case 0x5F: resch = 0x00A7; break;
    case 0x60: resch = 0x00BF; break;
    case 0x61: resch = 0x0061; break;
    case 0x62: resch = 0x0062; break;
    case 0x63: resch = 0x0063; break;
    case 0x64: resch = 0x0064; break;
    case 0x65: resch = 0x0065; break;
    case 0x66: resch = 0x0066; break;
    case 0x67: resch = 0x0067; break;
    case 0x68: resch = 0x0068; break;
    case 0x69: resch = 0x0069; break;
    case 0x6A: resch = 0x006A; break;
    case 0x6B: resch = 0x006B; break;
    case 0x6C: resch = 0x006C; break;
    case 0x6D: resch = 0x006D; break;
    case 0x6E: resch = 0x006E; break;
    case 0x6F: resch = 0x006F; break;
    case 0x70: resch = 0x0070; break;
    case 0x71: resch = 0x0071; break;
    case 0x72: resch = 0x0072; break;
    case 0x73: resch = 0x0073; break;
    case 0x74: resch = 0x0074; break;
    case 0x75: resch = 0x0075; break;
    case 0x76: resch = 0x0076; break;
    case 0x77: resch = 0x0077; break;
    case 0x78: resch = 0x0078; break;
    case 0x79: resch = 0x0079; break;
    case 0x7A: resch = 0x007A; break;
    case 0x7B: resch = 0x00E4; break;
    case 0x7C: resch = 0x00F6; break;
    case 0x7D: resch = 0x00F1; break;
    case 0x7F: resch = 0x00E0; break;
    default:resch = ch; break;
    }
    tmpBuffer1[bufPoz1++] = (gchar)resch;
  }

  tmpBuffer1[bufPoz1] = '\0';
  proto_tree_add_string(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, g_offset, g_size, tmpBuffer1);
}
Example #3
0
static gint
dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item      *main_item;
    proto_tree      *main_tree;
    proto_item      *arg0_item;
    proto_tree      *arg0_tree;
    proto_item      *arg1_item;
    proto_tree      *arg1_tree;
    proto_item      *magic_item;
    proto_item      *crc_item;
    proto_tree      *crc_tree = NULL;
    proto_item      *sub_item;
    gint             offset = 0;
    guint32          command;
    guint32          arg0;
    guint32          arg1;
    guint32          data_length = 0;
    guint32          crc32 = 0;
    usb_conv_info_t *usb_conv_info = NULL;
    wmem_tree_key_t  key[5];
    guint32          interface_id;
    guint32          bus_id;
    guint32          device_address;
    guint32          side_id;
    guint32          frame_number;
    gboolean         is_command = TRUE;
    gboolean         is_next_fragment = FALSE;
    gboolean         is_service = FALSE;
    gint             proto;
    gint             direction = P2P_DIR_UNKNOWN;
    wmem_tree_t     *wmem_tree;
    command_data_t  *command_data = NULL;
    service_data_t  *service_data = NULL;

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

    main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_adb);

    frame_number       = pinfo->fd->num;

    /* XXX: Why? If interface is USB only first try is correct
     * (and seems strange...), in other cases standard check for
     * previous protocol is correct */
    proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers))));
    if (proto != proto_usb) {
        proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))));
    }

    if (proto == proto_usb) {
        usb_conv_info = (usb_conv_info_t *) data;
        DISSECTOR_ASSERT(usb_conv_info);

        direction = usb_conv_info->direction;
    } else if (proto == proto_tcp) {
        if (pinfo->destport == ADB_TCP_PORT)
            direction = P2P_DIR_SENT;
        else
            direction = P2P_DIR_RECV;
    } else {
        return offset;
    }

    if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
        interface_id = pinfo->phdr->interface_id;
    else
        interface_id = 0;

    if (proto == proto_usb) {
        bus_id             = usb_conv_info->bus_id;
        device_address     = usb_conv_info->device_address;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[1].key = &bus_id;
        key[2].length = 1;
        key[2].key = &device_address;
        key[3].length = 0;
        key[3].key = NULL;
    } else { /* tcp */
        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[2].length = 1;
        if (direction == P2P_DIR_SENT) {
            key[1].key = &pinfo->srcport;
            key[2].key = &pinfo->destport;
        } else {
            key[1].key = &pinfo->destport;
            key[2].key = &pinfo->srcport;
        }
        key[3].length = 0;
        key[3].key = NULL;
    }

    wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key);
    if (wmem_tree) {
        command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
        if (command_data && command_data->completed_in_frame >= frame_number &&
                command_data->command_in_frame <= frame_number) {

            if (command_data->command_in_frame != frame_number) {
                is_command = FALSE;
                is_next_fragment = TRUE;
            }

            data_length = command_data->data_length;
            crc32 = command_data->crc32;

            if (direction == P2P_DIR_SENT)
                if (command_data->command == A_CLSE)
                    side_id = command_data->arg1; /* OUT: local id */
                else
                    side_id = command_data->arg0; /* OUT: local id */
            else
                if (command_data->command == A_OKAY) {
                    side_id = command_data->arg1; /* IN: remote id */
                } else
                    side_id = command_data->arg1; /* IN: remote id */

            key[3].length = 1;
            key[3].key = &side_id;
            key[4].length = 0;
            key[4].key = NULL;

            wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
            if (wmem_tree) {
                service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
                if (service_data && command_data->command == A_OPEN) {
                    is_service = TRUE;
                }
            }
        }
    }

/* Simple heuristics to check if packet is command or data */
    if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) {
        if (tvb_reported_length(tvb) < 24) {
            is_command = FALSE;
        } else if (tvb_reported_length(tvb) >= 24) {
            command = tvb_get_letohl(tvb, offset);

            if (command != A_SYNC && command != A_CLSE && command != A_WRTE &&
                    command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY)
                is_command = FALSE;
            else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20)))
                is_command = FALSE;

            if (is_command) {
                data_length = tvb_get_letohl(tvb, offset + 12);
                crc32 = tvb_get_letohl(tvb, offset + 16);
            }
            if (command == A_OPEN) is_service = TRUE;
        }
    }

    if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) {
        sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service);
        PROTO_ITEM_SET_GENERATED(sub_item);
    }

    if (service_data) {
        sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);

        if (service_data->close_local_in_frame < max_in_frame) {
            sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame);
            PROTO_ITEM_SET_GENERATED(sub_item);
        }

        if (service_data->close_remote_in_frame < max_in_frame) {
            sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame);
            PROTO_ITEM_SET_GENERATED(sub_item);
        }
    }

    if (is_command) {
        proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        command = tvb_get_letohl(tvb, offset);
        offset += 4;

        col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command"));

        arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0);
        arg0 = tvb_get_letohl(tvb, offset);
        offset += 4;

        arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1);
        arg1 = tvb_get_letohl(tvb, offset);
        offset += 4;

        switch (command) {
        case A_CNXN:
            proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4));
            break;
        case A_AUTH:
            proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown"));
            break;
        case A_OPEN:
            proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8));
            break;
        case A_WRTE:
            proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4));
            break;
        case A_CLSE:
        case A_OKAY:
            proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4));
            break;
        case A_SYNC:
            proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4));
            break;
        }

        proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        offset += 4;

        if (data_length > 0)
            col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length);

        crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
        crc32 = tvb_get_letohl(tvb, offset);
        offset += 4;

        magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) {
            proto_tree  *expert_tree;

            expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic);
            proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4);
        }

        if (!pinfo->fd->flags.visited)
            save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data);
        offset += 4;
    }

    if (!pinfo->fd->flags.visited && command_data) {
            if (command_data->command_in_frame != frame_number) {
                is_command = FALSE;
                is_next_fragment = TRUE;
            }

            data_length = command_data->data_length;
            crc32 = command_data->crc32;

            if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) ||
                (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24)
            ) {
                command_data->reassemble_data_length = command_data->data_length;
                command_data->completed_in_frame = frame_number;
            }
    }

    if (is_next_fragment && command_data) {
        sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);

        sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command);
        PROTO_ITEM_SET_GENERATED(sub_item);

        sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length);
        PROTO_ITEM_SET_GENERATED(sub_item);

        crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32);
        crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
        PROTO_ITEM_SET_GENERATED(crc_item);
    }

    if (command_data && command_data->completed_in_frame != frame_number) {
        sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);
    }


    if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) {
        guint32 crc = 0;
        guint32 i_offset;

        if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */
            if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) {
                tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset));
                command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset);

                if (command_data->reassemble_data_length >= command_data->data_length)
                    command_data->completed_in_frame = frame_number;
            }

            proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA);
            col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment");
            offset = tvb_captured_length(tvb);

            if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) {
                tvbuff_t            *next_tvb;
                adb_service_data_t   adb_service_data;

                next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length);
                add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data");

                adb_service_data.service = service_data->service;
                adb_service_data.direction = direction;

                adb_service_data.session_key_length = 3;
                adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
                adb_service_data.session_key[0] = interface_id;

                if (proto == proto_usb) {
                    adb_service_data.session_key[1] = usb_conv_info->bus_id;
                    adb_service_data.session_key[2] = usb_conv_info->device_address;
                } else { /* tcp */
                    if (direction == P2P_DIR_SENT) {
                        adb_service_data.session_key[1] = pinfo->srcport;
                        adb_service_data.session_key[2] = pinfo->destport;
                    } else {
                        adb_service_data.session_key[1] = pinfo->destport;
                        adb_service_data.session_key[2] = pinfo->srcport;
                    }
                }

                call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
            }
        } else { /* full message */
            for (i_offset = 0; i_offset < data_length; ++i_offset)
                crc += tvb_get_guint8(tvb, offset + i_offset);

            if (crc32 > 0 && crc32 != crc)
                proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1);

            if (is_service) {
                proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA);
                if (!pinfo->fd->flags.visited && service_data) {
                    service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII);
                }
                col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII));
                offset = tvb_captured_length(tvb);
            } else if (command_data && command_data->command == A_CNXN) {
                    gchar       *info;
                    gint         len;

                info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info);
                proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA);
                offset += len;
            } else {
                col_append_str(pinfo->cinfo, COL_INFO, "Data");

                /* Decode service payload */
                if (service_data) {
                    tvbuff_t           *next_tvb;
                    adb_service_data_t  adb_service_data;

                    adb_service_data.service = service_data->service;
                    adb_service_data.direction = direction;

                    adb_service_data.session_key_length = 3;
                    adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
                    adb_service_data.session_key[0] = interface_id;

                    if (proto == proto_usb) {
                        adb_service_data.session_key[1] = usb_conv_info->bus_id;
                        adb_service_data.session_key[2] = usb_conv_info->device_address;
                    } else { /* tcp */
                        if (direction == P2P_DIR_SENT) {
                            adb_service_data.session_key[1] = pinfo->srcport;
                            adb_service_data.session_key[2] = pinfo->destport;
                        } else {
                            adb_service_data.session_key[1] = pinfo->destport;
                            adb_service_data.session_key[2] = pinfo->srcport;
                        }
                    }

                    next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset));
                    call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);

                } else {
                    proto_item  *data_item;
                    gchar       *data_str;

                    data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA);
                    data_str = tvb_format_text(tvb, offset, data_length);
                    proto_item_append_text(data_item, ": %s", data_str);
                    col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str);
                }

                offset = tvb_captured_length(tvb);
            }
        }
    }

    return offset;
}
/*
 * Unfold and clean up a MIME-like header, and process LWS as follows:
 *      o Preserves LWS in quoted text
 *      o Remove LWS before and after a separator
 *      o Remove trailing LWS
 *      o Replace other LWS with a single space
 * Set value to the start of the value
 * Return the cleaned-up RFC2822 header (buffer must be freed).
 */
static char *
unfold_and_compact_mime_header(const char *lines, gint *first_colon_offset)
{
    const char *p = lines;
    char c;
    char *ret, *q;
    char sep_seen = 0; /* Did we see a separator ":;," */
    char lws = FALSE; /* Did we see LWS (incl. folding) */
    gint colon = -1;

    if (! lines) return NULL;

    c = *p;
    ret = (char *)wmem_alloc(wmem_packet_scope(), strlen(lines) + 1);
    q = ret;

    while (c) {
        if (c == ':') {
            lws = FALSE; /* Prevent leading LWS from showing up */
            if (colon == -1) {/* First colon */
                colon = (gint) (q - ret);
            }
            *(q++) = sep_seen = c;
            p++;
        } else if (c == ';' || c == ',' || c == '=') {
            lws = FALSE; /* Prevent leading LWS from showing up */
            *(q++) = sep_seen = c;
            p++;
        } else if (c == ' ' || c == '\t') {
            lws = TRUE;
            p++;
        } else if (c == '\n') {
            lws = FALSE; /* Skip trailing LWS */
            if ((c = *(p+1))) {
                if (c == ' ' || c == '\t') { /* Header unfolding */
                    lws = TRUE;
                    p += 2;
                } else {
                    *q = c = 0; /* Stop */
                }
            }
        } else if (c == '\r') {
            lws = FALSE;
            if ((c = *(p+1))) {
                if (c == '\n') {
                    if ((c = *(p+2))) {
                        if (c == ' ' || c == '\t') { /* Header unfolding */
                            lws = TRUE;
                            p += 3;
                        } else {
                            *q = c = 0; /* Stop */
                        }
                    }
                } else if (c == ' ' || c == '\t') { /* Header unfolding */
                    lws = TRUE;
                    p += 2;
                } else {
                    *q = c = 0; /* Stop */
                }
            }
        } else if (c == '"') { /* Start of quoted-string */
            lws = FALSE;
            *(q++) = c;
            while (c) {
                c = *(q++) = *(++p);
                if (c == '"') {
                    p++; /* Skip closing quote */
                    break;
                }
            }
            /* if already zero terminated now, rewind one char to avoid an "off by one" */
            if(c == 0) {
                q--;
            }
        } else { /* Regular character */
            if (sep_seen) {
                sep_seen = 0;
            } else {
                if (lws) {
                    *(q++) = ' ';
                }
            }
            lws = FALSE;
            *(q++) = c;
            p++; /* OK */
        }

        if (c) {
            c = *p;
        }
    }
    *q = 0;

    *first_colon_offset = colon;
    return (ret);
}
Example #5
0
static void
dissect_fw1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  /* Set up structures needed to add the protocol subtree and manage it */
  proto_item    *ti;
  proto_tree    *volatile fh_tree = NULL;
  char          direction;
  char  chain;
  char          *interface_name;
  guint32       iface_len = 10;
  wmem_strbuf_t *header;
  int           i;
  gboolean      found;
  static const char     fw1_header[] = "FW1 Monitor";
  ethertype_data_t ethertype_data;

  header = wmem_strbuf_new_label(wmem_epan_scope());
  wmem_strbuf_append(header, fw1_header);

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


  /* g_snprintf(header, sizeof(header), fw1_header); */

  /* fetch info to local variable */
  direction = tvb_get_guint8(tvb, 0);

  if (!fw1_iflist_with_chain)
    chain = ' ';
  else
    chain = tvb_get_guint8(tvb, 1);

  if (fw1_with_uuid)
    iface_len = 6;

  interface_name=(char *)wmem_alloc(wmem_packet_scope(), iface_len+1);
  tvb_get_nstringz0(tvb, 2, iface_len+1, interface_name);

  /* Known interface name - if not, remember it */
  found=FALSE;
  for (i=0; i<interface_anzahl; i++) {
    if ( strcmp(p_interfaces[i], interface_name) == 0 ) {
      found=TRUE;
      break;
    }
  }
  if (!found && interface_anzahl < MAX_INTERFACES) {
    p_interfaces[interface_anzahl] = wmem_strdup(wmem_file_scope(), interface_name);
    interface_anzahl++;
  }

  /* display all interfaces always in the same order */
  for (i=0; i<interface_anzahl; i++) {
    if ( strcmp(p_interfaces[i], interface_name) == 0 ) {
      wmem_strbuf_append_printf(header, "  %c%c %s %c%c",
                                direction == 'i' ? 'i' : (direction == 'O' ? 'O' : ' '),
                                (direction == 'i' || direction == 'O') ? chain : ' ',
                                p_interfaces[i],
                                direction == 'I' ? 'I' : (direction == 'o' ? 'o' : ' '),
                                (direction == 'I' || direction == 'o') ? chain : ' '
        );
    } else {
      wmem_strbuf_append_printf(header, "    %s  ", p_interfaces[i]);
    }
  }

  col_add_str(pinfo->cinfo, COL_IF_DIR, wmem_strbuf_get_str(header) + sizeof(fw1_header) + 1);

  if (tree) {
    if (!fw1_summary_in_tree)
      /* Do not show the summary in Protocol Tree */
      ti = proto_tree_add_protocol_format(tree, proto_fw1, tvb, 0, ETH_HEADER_SIZE, "%s", fw1_header);
    else
      ti = proto_tree_add_protocol_format(tree, proto_fw1, tvb, 0, ETH_HEADER_SIZE, "%s", wmem_strbuf_get_str(header));

    /* create display subtree for the protocol */
    fh_tree = proto_item_add_subtree(ti, ett_fw1);

    proto_tree_add_item(fh_tree, hf_fw1_direction, tvb, 0, 1, ENC_ASCII|ENC_NA);

    if (fw1_iflist_with_chain)
      proto_tree_add_item(fh_tree, hf_fw1_chain, tvb, 1, 1, ENC_ASCII|ENC_NA);

    proto_tree_add_item(fh_tree, hf_fw1_interface, tvb, 2, iface_len, ENC_ASCII|ENC_NA);

    if (fw1_with_uuid)
      proto_tree_add_item(fh_tree, hf_fw1_uuid, tvb, 8, 4, ENC_BIG_ENDIAN);
  }

  ethertype_data.etype = tvb_get_ntohs(tvb, 12);
  ethertype_data.offset_after_ethertype = ETH_HEADER_SIZE;
  ethertype_data.fh_tree = fh_tree;
  ethertype_data.etype_id = hf_fw1_type;
  ethertype_data.trailer_id = hf_fw1_trailer;
  ethertype_data.fcs_len = 0;

  call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
}
Example #6
0
/* Code to actually dissect the packets */
static void
dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    char          *szInfo;
    int            offCur        = 0;   /* current offset from start of WTP data */
    gint           returned_length, str_index = 0;

    unsigned char  b0;

    /* continuation flag */
    unsigned char  fCon;            /* Continue flag    */
    unsigned char  fRID;            /* Re-transmission indicator*/
    unsigned char  fTTR = '\0';        /* Transmission trailer    */
    guint          cbHeader       = 0;    /* Fixed header length    */
    guint          vHeader       = 0;    /* Variable header length*/
    int            abortType      = 0;

    /* Set up structures we'll need to add the protocol subtree and manage it */
    proto_item    *ti = NULL;
    proto_tree    *wtp_tree = NULL;

    char           pdut;
    char           clsTransaction = 3;
    int            numMissing = 0;        /* Number of missing packets in a negative ack */
    int            i;
    tvbuff_t      *wsp_tvb = NULL;
    guint8         psn = 0;        /* Packet sequence number*/
    guint16        TID = 0;        /* Transaction-Id    */
    int            dataOffset;
    gint           dataLen;

#define SZINFO_SIZE 256
    szInfo=(char *)wmem_alloc(wmem_packet_scope(), SZINFO_SIZE);

    b0 = tvb_get_guint8 (tvb, offCur + 0);
    /* Discover Concatenated PDUs */
    if (b0 == 0) {
        guint    c_fieldlen = 0;        /* Length of length-field    */
        guint    c_pdulen = 0;        /* Length of conc. PDU    */

        if (tree) {
            ti = proto_tree_add_item(tree, proto_wtp,
                    tvb, offCur, 1, ENC_NA);
            wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree);
            proto_item_append_text(ti, ", PDU concatenation");
        }
        offCur = 1;
        i = 1;
        while (offCur < (int) tvb_reported_length(tvb)) {
            tvbuff_t *wtp_tvb;
            /* The length of an embedded WTP PDU is coded as either:
             *    - a 7-bit value contained in one octet with highest bit == 0.
             *    - a 15-bit value contained in two octets (little endian)
             *      if the 1st octet has its highest bit == 1.
             * This means that this is NOT encoded as an uintvar-integer!!!
             */
            b0 = tvb_get_guint8(tvb, offCur + 0);
            if (b0 & 0x80) {
                c_fieldlen = 2;
                c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1);
            } else {
                c_fieldlen = 1;
                c_pdulen = b0;
            }
            if (tree) {
                proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size,
                        tvb, offCur, c_fieldlen, c_pdulen);
            }
            if (i > 1) {
                col_append_str(pinfo->cinfo, COL_INFO, ", ");
            }
            /* Skip the length field for the WTP sub-tvb */
            wtp_tvb = tvb_new_subset_length(tvb, offCur + c_fieldlen, c_pdulen);
            dissect_wtp_common(wtp_tvb, pinfo, wtp_tree);
            offCur += c_fieldlen + c_pdulen;
            i++;
        }
        if (tree) {
            proto_item_append_text(ti, ", PDU count: %u", i);
        }
        return;
    }
    /* No concatenation */
    fCon = b0 & 0x80;
    fRID = retransmission_indicator(b0);
    pdut = pdu_type(b0);

#ifdef DEBUG
    printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n",
            pinfo->fd->num, tree,
            val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"),
            pdut, tvb_captured_length(tvb));
#endif

    /* Develop the string to put in the Info column */
    returned_length =  g_snprintf(szInfo, SZINFO_SIZE, "WTP %s",
            val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"));
    str_index += MIN(returned_length, SZINFO_SIZE-str_index);

    switch (pdut) {
        case INVOKE:
            fTTR = transmission_trailer(b0);
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = 0;
            clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3));
            returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
                    " Class %d", clsTransaction);
            str_index += MIN(returned_length, SZINFO_SIZE-str_index);
            cbHeader = 4;
            break;

        case SEGMENTED_INVOKE:
        case SEGMENTED_RESULT:
            fTTR = transmission_trailer(b0);
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = tvb_get_guint8(tvb, offCur + 3);
            if (psn != 0) {
                returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
                        " (%u)", psn);
                str_index += MIN(returned_length, SZINFO_SIZE-str_index);
            }
            cbHeader = 4;
            break;

        case ABORT:
            cbHeader = 4;
            break;

        case RESULT:
            fTTR = transmission_trailer(b0);
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = 0;
            cbHeader = 3;
            break;

        case ACK:
            cbHeader = 3;
            break;

        case NEGATIVE_ACK:
            /* Variable number of missing packets */
            numMissing = tvb_get_guint8(tvb, offCur + 3);
            cbHeader = numMissing + 4;
            break;

        default:
            break;
    };
    if (fRID) {
        /*returned_length =*/ g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " R" );
        /*str_index += MIN(returned_length, SZINFO_SIZE-str_index);*/
    };
    /* In the interest of speed, if "tree" is NULL, don't do any work not
       necessary to generate protocol tree items. */
    if (tree) {
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
#endif
        /* NOTE - Length will be set when we process the TPI */
        ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, ENC_NA);
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n");
#endif
        wtp_tree = proto_item_add_subtree(ti, ett_wtp);

        /* Code to process the packet goes here */
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
        fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur);
#endif
        /* Add common items: only CON and PDU Type */
        proto_tree_add_item(
                wtp_tree,             /* tree */
                hf_wtp_header_flag_continue,     /* id */
                tvb,
                offCur,             /* start of highlight */
                1,                /* length of highlight*/
                b0                /* value */
                );
        proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, ENC_LITTLE_ENDIAN);

        switch(pdut) {
            case INVOKE:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_item_append_text(ti,
                        ", PDU: Invoke (%u)"
                        ", Transaction Class: %s (%u)",
                        INVOKE,
                        val_to_str_const(clsTransaction, vals_transaction_classes, "Undefined"),
                        clsTransaction);
                break;

            case RESULT:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(ti, ", PDU: Result (%u)", RESULT);
                break;

            case ACK:
                proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(ti, ", PDU: ACK (%u)", ACK);
                break;

            case ABORT:
                abortType = tvb_get_guint8 (tvb, offCur) & 0x07;
                proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                if (abortType == PROVIDER) {
                    guint8 reason = tvb_get_guint8(tvb, offCur + 3);
                    proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti,
                            ", PDU: Abort (%u)"
                            ", Type: Provider (%u)"
                            ", Reason: %s (%u)",
                            ABORT,
                            PROVIDER,
                            val_to_str_const(reason, vals_abort_reason_provider, "Undefined"),
                            reason);
                }
                else if (abortType == USER) {
                    guint8 reason = tvb_get_guint8(tvb, offCur + 3);
                    proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti,
                            ", PDU: Abort (%u)"
                            ", Type: User (%u)"
                            ", Reason: %s (%u)",
                            ABORT,
                            PROVIDER,
                            val_to_str_ext_const(reason, &vals_wsp_reason_codes_ext, "Undefined"),
                            reason);
                }
                break;

            case SEGMENTED_INVOKE:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_item_append_text(ti,
                        ", PDU: Segmented Invoke (%u)"
                        ", Packet Sequence Number: %u",
                        SEGMENTED_INVOKE, psn);
                break;

            case SEGMENTED_RESULT:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_item_append_text(ti,
                        ", PDU: Segmented Result (%u)"
                        ", Packet Sequence Number: %u",
                        SEGMENTED_RESULT, psn);
                break;

            case NEGATIVE_ACK:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                /* Iterate through missing packets */
                for (i = 0; i < numMissing; i++)
                {
                    proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, ENC_LITTLE_ENDIAN);
                }
                proto_item_append_text(ti,
                        ", PDU: Negative Ack (%u)"
                        ", Missing Packets: %u",
                        NEGATIVE_ACK, numMissing);
                break;

            default:
                break;
        };
        if (fRID) {
            proto_item_append_text(ti, ", Retransmission");
        }
    } else { /* tree is NULL */
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree);
#endif
    }
    /* Process the variable part */
    if (fCon) {            /* Now, analyze variable part    */
        guint8    tCon;
        guint8    tByte;
        guint     tpiLen;
        tvbuff_t *tmp_tvb;

        vHeader = 0;        /* Start scan all over    */

        do {
            tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader);
            tCon = tByte & 0x80;
            if (tByte & 0x04)    /* Long TPI    */
                tpiLen = 2 + tvb_get_guint8(tvb, offCur + cbHeader + vHeader + 1);
            else
                tpiLen = 1 + (tByte & 0x03);
            if (tree)
            {
                tmp_tvb = tvb_new_subset_length(tvb, offCur + cbHeader + vHeader, tpiLen);
                wtp_handle_tpi(wtp_tree, tmp_tvb);
            }
            vHeader += tpiLen;
        } while (tCon);
    } else {
        /* There is no variable part */
    }    /* End of variable part of header */

    /* Set the length of the WTP protocol part now we know the length of the
     * fixed and variable WTP headers */
    if (tree)
        proto_item_set_len(ti, cbHeader + vHeader);

#ifdef DEBUG
    fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader );
#endif

    /*
     * Any remaining data ought to be WSP data (if not WTP ACK, NACK
     * or ABORT pdu), so, if we have any remaining data, and it's
     * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the
     * WSP dissector.
     * Note that the last packet of a fragmented WTP message needn't
     * contain any data, so we allow payloadless packets to be
     * reassembled.  (XXX - does the reassembly code handle this
     * for packets other than the last packet?)
     *
     * Try calling a subdissector only if:
     *    - The WTP payload is ressembled in this very packet,
     *    - The WTP payload is not fragmented across packets.
     */
    dataOffset = offCur + cbHeader + vHeader;
    dataLen = tvb_reported_length_remaining(tvb, dataOffset);
    if ((dataLen >= 0) &&
            ! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)))
    {
        /* Try to reassemble if needed, and hand over to WSP
         * A fragmented WTP packet is either:
         *    - An INVOKE with fTTR (transmission trailer) not set,
         *    - a SEGMENTED_INVOKE,
         *    - A RESULT with fTTR (transmission trailer) not set,
         *    - a SEGMENTED_RESULT.
         */
        if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT)
                    || ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) )
             ) && tvb_bytes_exist(tvb, dataOffset, dataLen) )
        {
            /* Try reassembling fragments */
            fragment_head *fd_wtp = NULL;
            guint32 reassembled_in = 0;
            gboolean save_fragmented = pinfo->fragmented;

            pinfo->fragmented = TRUE;
            fd_wtp = fragment_add_seq(&wtp_reassembly_table, tvb, dataOffset,
                    pinfo, TID, NULL, psn, dataLen, !fTTR, 0);
            /* XXX - fragment_add_seq() yields NULL unless Wireshark knows
             * that the packet is part of a reassembled whole. This means
             * that fd_wtp will be NULL as long as Wireshark did not encounter
             * (and process) the packet containing the last fragment.
             * This implies that Wireshark needs two passes over the data for
             * correct reassembly. At the first pass, a capture containing
             * three fragments plus a retransmssion of the last fragment
             * will progressively show:
             *
             *        Packet 1: (Unreassembled fragment 1)
             *        Packet 2: (Unreassembled fragment 2)
             *        Packet 3: (Reassembled WTP)
             *        Packet 4: (WTP payload reassembled in packet 3)
             *
             * However at subsequent evaluation (e.g., by applying a display
             * filter) the packet summary will show:
             *
             *        Packet 1: (WTP payload reassembled in packet 3)
             *        Packet 2: (WTP payload reassembled in packet 3)
             *        Packet 3: (Reassembled WTP)
             *        Packet 4: (WTP payload reassembled in packet 3)
             *
             * This is important to know, and also affects read filters!
             */
            wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo,
                    "Reassembled WTP", fd_wtp, &wtp_frag_items,
                    NULL, wtp_tree);
#ifdef DEBUG
            printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n",
                    pinfo->fd->num,
                    fd_wtp ? "Reassembled" : "Not reassembled",
                    fd_wtp ? fd_wtp->reassembled_in : -1,
                    wsp_tvb,
                    fd_wtp
                  );
#endif
            if (fd_wtp) {
                /* Reassembled */
                reassembled_in = fd_wtp->reassembled_in;
                if (pinfo->fd->num == reassembled_in) {
                    /* Reassembled in this very packet:
                     * We can safely hand the tvb to the WSP dissector */
                    call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
                } else {
                    /* Not reassembled in this packet */
                    col_append_fstr(pinfo->cinfo, COL_INFO,
                            "%s (WTP payload reassembled in packet %u)",
                            szInfo, fd_wtp->reassembled_in);

                    proto_tree_add_item(wtp_tree, hf_wtp_payload, tvb, dataOffset, -1, ENC_NA);
                }
            } else {
                /* Not reassembled yet, or not reassembled at all */
                col_append_fstr(pinfo->cinfo, COL_INFO,
                        "%s (Unreassembled fragment %u)",
                        szInfo, psn);
                proto_tree_add_item(wtp_tree, hf_wtp_payload, tvb, dataOffset, -1, ENC_NA);
            }
            /* Now reset fragmentation information in pinfo */
            pinfo->fragmented = save_fragmented;
        }
        else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) )
        {
            /* Non-fragmented payload */
            wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset);
            /* We can safely hand the tvb to the WSP dissector */
            call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
        }
        else
        {
            /* Nothing to hand to subdissector */
            col_append_str(pinfo->cinfo, COL_INFO, szInfo);
        }
    }
    else
    {
        /* Nothing to hand to subdissector */
        col_append_str(pinfo->cinfo, COL_INFO, szInfo);
    }
}
Example #7
0
static void dissect_cimd_dcs(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset)
{
  /* Set up structures needed to add the param subtree and manage it */
  proto_item *param_item;
  proto_tree *param_tree;
  gint        offset;
  guint       dcs;
  guint       dcs_cg;           /* coding group */
  guint       dcs_cf;           /* compressed flag */
  guint       dcs_mcm;          /* message class meaning flag */
  guint       dcs_chs;          /* character set */
  guint       dcs_mc;           /* message class */
  guint       dcs_is;           /* indication sense */
  guint       dcs_it;           /* indication type */

  gchar* bigbuf = (gchar*)wmem_alloc(wmem_packet_scope(), 1024);

  param_item = proto_tree_add_text(tree, tvb,
    startOffset + 1, endOffset - (startOffset + 1),
    "%s", cimd_vals_PC[pindex].strptr
  );
  param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p));
  proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb,
    startOffset + 1, CIMD_PC_LENGTH,
    tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH)
  );

  offset = startOffset + 1 + CIMD_PC_LENGTH + 1;
  dcs    = decimal_int_value(tvb, offset, endOffset - offset);
  proto_tree_add_uint(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, offset, endOffset - offset, dcs);

  dcs_cg = (dcs & 0xF0) >> 4;
  other_decode_bitfield_value(bigbuf, dcs, (dcs_cg <= 0x07 ? 0xC0 : 0xF0), 8);
  proto_tree_add_uint_format(param_tree, hf_cimd_dcs_coding_group_indicator, tvb, offset, 1,
    dcs_cg, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_coding_group_indicator)->name,
    val_to_str(dcs_cg, cimd_dcs_coding_groups, "Unknown (%d)"), dcs_cg
  );

  if (dcs_cg <= 0x07)
  {
    dcs_cf = (dcs & 0x20) >> 5;
    other_decode_bitfield_value(bigbuf, dcs, 0x20, 8);
    proto_tree_add_uint_format(param_tree, hf_cimd_dcs_compressed_indicator, tvb, offset, 1,
      dcs_cf, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_compressed_indicator)->name,
      val_to_str(dcs_cf, cimd_dcs_compressed, "Unknown (%d)"), dcs_cf
    );

    dcs_mcm = (dcs & 0x10) >> 4;
    other_decode_bitfield_value(bigbuf, dcs, 0x10, 8);
    proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_meaning_indicator, tvb, offset, 1,
      dcs_mcm, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_meaning_indicator)->name,
      val_to_str(dcs_mcm, cimd_dcs_message_class_meaning, "Unknown (%d)"), dcs_mcm
    );

    dcs_chs = (dcs & 0x0C) >> 2;
    other_decode_bitfield_value(bigbuf, dcs, 0x0C, 8);
    proto_tree_add_uint_format(param_tree, hf_cimd_dcs_character_set_indicator, tvb, offset, 1,
      dcs_chs, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_character_set_indicator)->name,
      val_to_str(dcs_chs, cimd_dcs_character_set, "Unknown (%d)"), dcs_chs
    );

    if (dcs_mcm)
    {
      dcs_mc = (dcs & 0x03);
      other_decode_bitfield_value(bigbuf, dcs, 0x03, 8);
      proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_indicator, tvb, offset, 1,
        dcs_mc, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_indicator)->name,
        val_to_str(dcs_mc, cimd_dcs_message_class, "Unknown (%d)"), dcs_mc
      );
    }
  }
/** Dissector for SoupBinTCP messages */
static void
dissect_soupbintcp_common(
    tvbuff_t    *tvb,
    packet_info *pinfo,
    proto_tree  *tree)
{
    struct conv_data *conv_data;
    struct pdu_data  *pdu_data;
    const char       *pkt_name;
    const char       *tmp_buf;
    proto_item       *ti;
    proto_tree       *soupbintcp_tree = NULL;
    conversation_t   *conv            = NULL;
    guint16           expected_len;
    guint8            pkt_type;
    gint              offset          = 0;
    guint             this_seq        = 0, next_seq;
    heur_dtbl_entry_t *hdtbl_entry;

    /* Get the 16-bit big-endian SOUP packet length */
    expected_len = tvb_get_ntohs(tvb, 0);

    /* Get the 1-byte SOUP message type */
    pkt_type = tvb_get_guint8(tvb, 2);

    /* Since we use the packet name a few times, get and save that value */
    pkt_name = val_to_str(pkt_type, pkt_type_val, "Unknown (%u)");

    /* Set the protocol name in the summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SoupBinTCP");

    /* Set the packet name in the info column */
    col_add_str(pinfo->cinfo, COL_INFO, pkt_name);

    /* Sequence number tracking
     *
     * SOUP does not number packets from client to server (the server
     * acknowledges all important messages, so the client should use
     * the acks to figure out if the server received the message, and
     * otherwise resend it).
     *
     * Packets from server to client are numbered, but it's implicit.
     * The Login Accept packet contains the next sequence number that
     * the server will send, and the client needs to count the
     * Sequenced Data packets that it receives to know what their
     * sequence numbers are.
     *
     * So, we grab the next sequence number from the Login Acceptance
     * packet, and save it in a conversation_t we associate with the
     * TCP session.  Then, for each Sequenced Data packet we receive,
     * the first time it's processed (when PINFO_FD_VISITED() is
     * false), we write it into the PDU's frame's private data pointer
     * and increment the saved sequence number (in the conversation_t).
     *
     * If the visited flag is true, then we've dissected this packet
     * already, and so we can fetch the sequence number from the
     * frame's private data area.
     *
     * In either case, if there's any problem, we report zero as the
     * sequence number, and try to continue dissecting. */

    /* If first dissection of Login Accept, save sequence number */
    if (pkt_type == 'A' && !PINFO_FD_VISITED(pinfo)) {
        tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, 13, 20, ENC_ASCII);
        next_seq = atoi(tmp_buf);

        /* Create new conversation for this session */
        conv = conversation_new(PINFO_FD_NUM(pinfo),
                                &pinfo->src,
                                &pinfo->dst,
                                pinfo->ptype,
                                pinfo->srcport,
                                pinfo->destport,
                                0);

        /* Store starting sequence number for session's packets */
        conv_data = (struct conv_data *)wmem_alloc(wmem_file_scope(), sizeof(struct conv_data));
        conv_data->next_seq = next_seq;
        conversation_add_proto_data(conv, proto_soupbintcp, conv_data);
    }

    /* Handle sequence numbering for a Sequenced Data packet */
    if (pkt_type == 'S') {
        if (!PINFO_FD_VISITED(pinfo)) {
            /* Get next expected sequence number from conversation */
            conv = find_conversation(PINFO_FD_NUM(pinfo),
                                     &pinfo->src,
                                     &pinfo->dst,
                                     pinfo->ptype,
                                     pinfo->srcport,
                                     pinfo->destport,
                                     0);
            if (!conv) {
                this_seq = 0;
            } else {
                conv_data = (struct conv_data *)conversation_get_proto_data(conv,
                                                        proto_soupbintcp);
                if (conv_data) {
                    this_seq = conv_data->next_seq++;
                } else {
                    this_seq = 0;
                }

                pdu_data = (struct pdu_data *)wmem_alloc(
                    wmem_file_scope(),
                    sizeof(struct pdu_data));
                pdu_data->seq_num = this_seq;
                p_add_proto_data(wmem_file_scope(), pinfo, proto_soupbintcp, 0, pdu_data);
            }
        } else {
            pdu_data = (struct pdu_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_soupbintcp, 0);
            if (pdu_data) {
                this_seq = pdu_data->seq_num;
            } else {
                this_seq = 0;
            }
        }

        col_append_fstr(pinfo->cinfo, COL_INFO, ", SeqNum = %u", this_seq);
    }

    if (tree) {
        /* Create sub-tree for SoupBinTCP details */
        ti = proto_tree_add_item(tree,
                                 proto_soupbintcp,
                                 tvb, 0, -1, ENC_NA);

        soupbintcp_tree = proto_item_add_subtree(ti, ett_soupbintcp);

        /* Append the packet name to the sub-tree item */
        proto_item_append_text(ti, ", %s", pkt_name);

        /* Length */
        proto_tree_add_item(soupbintcp_tree,
                            hf_soupbintcp_packet_length,
                            tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        /* Type */
        proto_tree_add_item(soupbintcp_tree,
                            hf_soupbintcp_packet_type,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        switch (pkt_type) {
        case '+': /* Debug Message */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_text,
                                tvb, offset, expected_len - 1, ENC_ASCII|ENC_NA);
            break;

        case 'A': /* Login Accept */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_session,
                                tvb, offset, 10, ENC_ASCII|ENC_NA);
            offset += 10;

            tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 20, ENC_ASCII);
            proto_tree_add_string_format_value(soupbintcp_tree,
                                               hf_soupbintcp_next_seq_num,
                                               tvb, offset, 20,
                                               "X", "%d", atoi(tmp_buf));
            break;

        case 'J': /* Login Reject */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_reject_code,
                                tvb, offset, 1, ENC_BIG_ENDIAN);
            break;

        case 'U': /* Unsequenced Data */
            /* Display handled by sub-dissector */
            break;

        case 'S': /* Sequenced Data */
            proto_item_append_text(ti, ", SeqNum=%u", this_seq);
            proto_tree_add_string_format_value(soupbintcp_tree,
                                               hf_soupbintcp_seq_num,
                                               tvb, offset, 0,
                                               "X",
                                               "%u (Calculated)",
                                               this_seq);

            /* Display handled by sub-dissector */
            break;

        case 'L': /* Login Request */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_username,
                                tvb, offset, 6, ENC_ASCII|ENC_NA);
            offset += 6;

            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_password,
                                tvb, offset, 10, ENC_ASCII|ENC_NA);
            offset += 10;

            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_session,
                                tvb, offset, 10, ENC_ASCII|ENC_NA);
            offset += 10;

            tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 20, ENC_ASCII);
            proto_tree_add_string_format_value(soupbintcp_tree,
                                               hf_soupbintcp_req_seq_num,
                                               tvb, offset, 20,
                                               "X", "%d", atoi(tmp_buf));
            break;

        case 'H': /* Server Heartbeat */
            break;

        case 'O': /* Logout Request */
            break;

        case 'R': /* Client Heartbeat */
            break;

        case 'Z': /* End of Session */
            break;

        default:
            /* Unknown */
            proto_tree_add_item(tree,
                                hf_soupbintcp_message,
                                tvb, offset, -1, ENC_NA);
            break;
        }
    }

    /* Call sub-dissector for encapsulated data */
    if (pkt_type == 'S' || pkt_type == 'U') {
        tvbuff_t         *sub_tvb;

        /* Sub-dissector tvb starts at 3 (length (2) + pkt_type (1)) */
        sub_tvb = tvb_new_subset_remaining(tvb, 3);

#if 0   /* XXX: It's not valid for a soupbintcp subdissector to call       */
        /*  conversation_set_dissector() since the conversation is really  */
        /*  a TCP conversation.  (A 'soupbintcp' port type would need to   */
        /*  be defined to be able to use conversation_set_dissector()).    */
        /* In addition, no current soupbintcp subdissector calls           */
        /*  conversation_set_dissector().                                  */

        /* If this packet is part of a conversation, call dissector
         * for the conversation if available */
        if (try_conversation_dissector(&pinfo->dst, &pinfo->src, pinfo->ptype,
                                       pinfo->srcport, pinfo->destport,
                                       sub_tvb, pinfo, tree, NULL)) {
            return;
        }
#endif

        /* Otherwise, try heuristic dissectors */
        if (dissector_try_heuristic(heur_subdissector_list,
                                    sub_tvb,
                                    pinfo,
                                    tree,
                                    &hdtbl_entry,
                                    NULL)) {
            return;
        }

        /* Otherwise, give up, and just print the bytes in hex */
        if (tree) {
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_message,
                                sub_tvb, 0, -1,
                                ENC_NA);
        }
    }
}
int PBE_decrypt_data(const char *object_identifier_id_param, tvbuff_t *encrypted_tvb, asn1_ctx_t *actx, proto_item *item)
{
#ifdef HAVE_LIBGCRYPT
	const char	*encryption_algorithm;
	gcry_cipher_hd_t cipher;
	gcry_error_t	err;
	int		algo;
	int		mode;
	int		ivlen = 0;
	int		keylen = 0;
	int		datalen = 0;
	char		*key = NULL;
	char		*iv = NULL;
	char		*clear_data = NULL;
	tvbuff_t	*clear_tvb = NULL;
	const gchar     *oidname;
	GString		*name;
	proto_tree	*tree;
	char		byte;
	gboolean	decrypt_ok = TRUE;

	if(((password == NULL) || (*password == '\0')) && (try_null_password == FALSE)) {
		/* we are not configured to decrypt */
		return FALSE;
	}

	encryption_algorithm = x509af_get_last_algorithm_id();

	/* these are the only encryption schemes we understand for now */
	if(!strcmp(encryption_algorithm, PKCS12_PBE_3DES_SHA1_OID)) {
		ivlen = 8;
		keylen = 24;
		algo = GCRY_CIPHER_3DES;
		mode = GCRY_CIPHER_MODE_CBC;
	} else if(!strcmp(encryption_algorithm, PKCS12_PBE_ARCFOUR_SHA1_OID)) {
		ivlen = 0;
		keylen = 16;
		algo = GCRY_CIPHER_ARCFOUR;
		mode = GCRY_CIPHER_MODE_NONE;
	} else if(!strcmp(encryption_algorithm, PKCS12_PBE_RC2_40_SHA1_OID)) {
		ivlen = 8;
		keylen = 5;
		algo = GCRY_CIPHER_RFC2268_40;
		mode = GCRY_CIPHER_MODE_CBC;
	} else {
		/* we don't know how to decrypt this */

		proto_item_append_text(item, " [Unsupported encryption algorithm]");
		return FALSE;
	}

	if((iteration_count == 0) || (salt == NULL)) {
		proto_item_append_text(item, " [Insufficient parameters]");
		return FALSE;
	}

	/* allocate buffers */
	key = (char *)wmem_alloc(wmem_packet_scope(), keylen);

	if(!generate_key_or_iv(1 /*LEY */, salt, iteration_count, password, keylen, key))
		return FALSE;

	if(ivlen) {

		iv = (char *)wmem_alloc(wmem_packet_scope(), ivlen);

		if(!generate_key_or_iv(2 /* IV */, salt, iteration_count, password, ivlen, iv))
			return FALSE;
	}

	/* now try an internal function */
	err = gcry_cipher_open(&cipher, algo, mode, 0);
	if (gcry_err_code (err))
			return FALSE;

	err = gcry_cipher_setkey (cipher, key, keylen);
	if (gcry_err_code (err)) {
			gcry_cipher_close (cipher);
			return FALSE;
	}

	if(ivlen) {
		  err = gcry_cipher_setiv (cipher, iv, ivlen);
		  if (gcry_err_code (err)) {
			  gcry_cipher_close (cipher);
			  return FALSE;
		  }
	}

	datalen = tvb_captured_length(encrypted_tvb);
	clear_data = (char *)g_malloc(datalen);

	err = gcry_cipher_decrypt (cipher, clear_data, datalen, (char *)tvb_memdup(wmem_packet_scope(), encrypted_tvb, 0, datalen), datalen);
	if (gcry_err_code (err)) {

		proto_item_append_text(item, " [Failed to decrypt with password preference]");

		gcry_cipher_close (cipher);
		g_free(clear_data);
		return FALSE;
	}

	gcry_cipher_close (cipher);

	/* We don't know if we have successfully decrypted the data or not so we:
		a) check the trailing bytes
		b) see if we start with a sequence or a set (is this too constraining?
		*/

	/* first the trailing bytes */
	byte = clear_data[datalen-1];
	if(byte <= 0x08) {
		int i;

		for(i = (int)byte; i > 0 ; i--) {
			if(clear_data[datalen - i] != byte) {
				decrypt_ok = FALSE;
				break;
			}
		}
	} else {
		/* XXX: is this a failure? */
	}

	/* we assume the result is ASN.1 - check it is a SET or SEQUENCE */
	byte = clear_data[0];
	if((byte != 0x30) && (byte != 0x31)) { /* do we need more here? OCTET STRING? */
		decrypt_ok = FALSE;
	}

	if(!decrypt_ok) {
		g_free(clear_data);
		proto_item_append_text(item, " [Failed to decrypt with supplied password]");

		return FALSE;
	}

	proto_item_append_text(item, " [Decrypted successfully]");

	tree = proto_item_add_subtree(item, ett_decrypted_pbe);

	/* OK - so now clear_data contains the decrypted data */

	clear_tvb = tvb_new_child_real_data(encrypted_tvb,(const guint8 *)clear_data, datalen, datalen);
	tvb_set_free_cb(clear_tvb, g_free);

	name = g_string_new("");
	oidname = oid_resolved_from_string(object_identifier_id_param);
	g_string_printf(name, "Decrypted %s", oidname ? oidname : object_identifier_id_param);

	/* add it as a new source */
	add_new_data_source(actx->pinfo, clear_tvb, name->str);

	g_string_free(name, TRUE);

	/* now try and decode it */
	call_ber_oid_callback(object_identifier_id_param, clear_tvb, 0, actx->pinfo, tree, NULL);

	return TRUE;
#else
	/* we cannot decrypt */
	return FALSE;

#endif
}
Example #10
0
static void
dissect_ax25_nol3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree )
{
	proto_item *ti;
	proto_tree *ax25_nol3_tree;
	char       *info_buffer;
	int         offset;
	tvbuff_t   *next_tvb = NULL;
	guint8      dti      = 0;
	gboolean    dissected;

	info_buffer = (char *)wmem_alloc( wmem_packet_scope(), STRLEN );
	info_buffer[0] = '\0';

	col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25-NoL3");

	col_clear( pinfo->cinfo, COL_INFO);

	offset = 0;
	g_snprintf( info_buffer, STRLEN, "Text" );

	if ( gPREF_APRS )
		{
		dti = tvb_get_guint8( tvb, offset );
		if ( isaprs( dti ) )
			g_snprintf( info_buffer, STRLEN, "APRS" );
		}
	if ( gPREF_DX )
		{
		if ( tvb_get_guint8( tvb, offset ) == 'D' && tvb_get_guint8( tvb, offset + 1 ) == 'X' )
		g_snprintf( info_buffer, STRLEN, "DX cluster" );
		}

	col_add_str( pinfo->cinfo, COL_INFO, info_buffer );

	/* Call sub-dissectors here */

	if ( parent_tree )
		{
		/* create display subtree for the protocol */
		ti = proto_tree_add_protocol_format( parent_tree,
							proto_ax25_nol3,
							tvb,
							0,
							-1,
							"AX.25 No Layer 3 - (%s)", info_buffer );
		ax25_nol3_tree = proto_item_add_subtree( ti, ett_ax25_nol3 );

		next_tvb = tvb_new_subset_remaining(tvb, offset);
		dissected = FALSE;
		if ( gPREF_APRS )
			{
			if ( isaprs( dti ) )
				{
				dissected = TRUE;
				call_dissector( aprs_handle , next_tvb, pinfo, ax25_nol3_tree );
				}
			}
		if ( gPREF_DX )
			{
			if ( tvb_get_guint8( tvb, offset ) == 'D' && tvb_get_guint8( tvb, offset + 1 ) == 'X' )
				{
				dissected = TRUE;
				dissect_dx( next_tvb, pinfo, ax25_nol3_tree );
				}
			}
		if ( ! dissected )
			call_dissector( default_handle , next_tvb, pinfo, ax25_nol3_tree );

		}
}
static const char *
COM_Parse (const char *data, int data_len, int* token_start, int* token_len)
{
	int c;
	char* com_token = (char*)wmem_alloc(wmem_packet_scope(), data_len+1);

	com_token[0] = '\0';
	*token_start = 0;
	*token_len = 0;

	if (data == NULL)
		return NULL;

	/* skip whitespace */
skipwhite:
	while (TRUE) {
		c = *data;
		if (c == '\0')
			return NULL;	/* end of file; */
		if ((c != ' ') && (!g_ascii_iscntrl(c)))
		    break;
		data++;
		(*token_start)++;
	}

	/* skip // comments */
	if ((c=='/') && (data[1]=='/')) {
		while (*data && *data != '\n'){
			data++;
			(*token_start)++;
		}
		goto skipwhite;
	}

	/* handle quoted strings specially */
	if (c == '\"') {
		data++;
		(*token_start)++;
		while (*token_len < data_len) {
			c = *data++;
			if ((c=='\"') || (c=='\0')) {
				com_token[*token_len] = '\0';
				return data;
			}
			com_token[*token_len] = c;
			(*token_len)++;
		}
	}

	if (*token_len == data_len) {
		com_token[*token_len] = '\0';
		return data;
	}

	/* parse a regular word */
	do {
		com_token[*token_len] = c;
		data++;
		(*token_len)++;
		c = *data;
	} while (( c != ' ') && (!g_ascii_iscntrl(c)) && (*token_len < data_len));

	com_token[*token_len] = '\0';
	return data;
}
Example #12
0
static int dissect_aim_chat_userinfo_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *chat_tree)
{
	int offset = 0;
	while(tvb_length_remaining(tvb, offset) > 0) {
		offset = dissect_aim_userinfo(tvb, pinfo, offset, chat_tree);
	}
	return offset;
}

static int dissect_aim_chat_outgoing_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *chat_tree _U_)
{
	guchar *buddyname;
	guchar *msg;
	int buddyname_length;

	buddyname=(guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUDDYNAME_LENGTH+1);
	msg=(guchar *)wmem_alloc(wmem_packet_scope(), 1000);
	buddyname_length = aim_get_buddyname( buddyname, tvb, 30, 31 );

	/* channel message from client */
	aim_get_message( msg, tvb, 40 + buddyname_length, tvb_length(tvb)
					 - 40 - buddyname_length );

	col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);

	return tvb_length(tvb);
}


static int dissect_aim_chat_incoming_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *chat_tree)
{
static gint
dissect_adb_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item          *main_item;
    proto_tree          *main_tree;
    proto_item          *sub_item;
    proto_tree          *sub_tree;
    gint                 offset = 0;
    adb_service_data_t  *adb_service_data = (adb_service_data_t *) data;
    const guint8        *service;
    wmem_tree_key_t      key[5];
    wmem_tree_t         *subtree;
    guint32              i_key;

    main_item = proto_tree_add_item(tree, proto_adb_service, tvb, offset, -1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_adb_service);

    DISSECTOR_ASSERT(adb_service_data);

    service = adb_service_data->service;

    sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service);
    PROTO_ITEM_SET_GENERATED(sub_item);

        if (g_strcmp0(service, "host:version") == 0) {
            guint32               version;
            guint32               data_length;
            continuation_data_t  *continuation_data;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_infos, key);
            continuation_data = (subtree) ? (continuation_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
            if (continuation_data && continuation_data->completed_in_frame < pinfo->num)
                continuation_data = NULL;

            if (!continuation_data || (continuation_data && continuation_data->length_in_frame == pinfo->num))
                offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            if (!pinfo->fd->flags.visited && !continuation_data && tvb_reported_length_remaining(tvb, offset) < 4) {
                key[i_key].length = 1;
                key[i_key++].key = &pinfo->num;
                key[i_key].length = 0;
                key[i_key].key = NULL;

                continuation_data = wmem_new(wmem_file_scope(), continuation_data_t);
                continuation_data->length_in_frame = pinfo->num;
                continuation_data->completed_in_frame = G_MAXUINT32;
                continuation_data->length = data_length;

                wmem_tree_insert32_array(continuation_infos, key, continuation_data);
                continuation_data = NULL;
            }

            if (tvb_reported_length_remaining(tvb, offset) >= 4 ||
                        (continuation_data && continuation_data->completed_in_frame == pinfo->num)) {
                if (!pinfo->fd->flags.visited && continuation_data) {
                    continuation_data->completed_in_frame = pinfo->num;
                }
                offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_version, ett_version, hf_version, tvb, offset, &version);

                col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version);
            }

        } else if (g_strcmp0(service, "host:devices") == 0 ||
                g_strcmp0(service, "host:devices-l") == 0 ||
                g_strcmp0(service, "host:track-devices") == 0) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_NA | ENC_ASCII);
            if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                expert_add_info(pinfo, sub_item, &ei_incomplete_message);
            }
        } else if (g_strcmp0(service, "host:get-state") == 0 ||
                g_strcmp0(service, "host:get-serialno") == 0 ||
                g_strcmp0(service, "host:get-devpath") == 0 ||
                g_str_has_prefix(service, "connect:") ||
                g_str_has_prefix(service, "disconnect:")) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
            if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                expert_add_info(pinfo, sub_item, &ei_incomplete_message);
            }
        } else if (g_str_has_prefix(service, "framebuffer:")) {
            framebuffer_data_t  *framebuffer_data = NULL;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(framebuffer_infos, key);
            framebuffer_data = (subtree) ? (framebuffer_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
            if (framebuffer_data && framebuffer_data->completed_in_frame < pinfo->num)
                framebuffer_data = NULL;

            if (!pinfo->fd->flags.visited && !framebuffer_data) {
                key[i_key].length = 1;
                key[i_key++].key = &pinfo->num;
                key[i_key].length = 0;
                key[i_key].key = NULL;

                framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t);
                framebuffer_data->data_in      = pinfo->num;
                framebuffer_data->current_size = 0;
                framebuffer_data->completed_in_frame = G_MAXUINT32;
                framebuffer_data->size         = tvb_get_letohl(tvb, offset + 4 * 2);
                framebuffer_data->red_offset   = tvb_get_letohl(tvb, offset + 4 * 5);
                framebuffer_data->red_length   = tvb_get_letohl(tvb, offset + 4 * 6);
                framebuffer_data->green_offset = tvb_get_letohl(tvb, offset + 4 * 7);
                framebuffer_data->green_length = tvb_get_letohl(tvb, offset + 4 * 8);
                framebuffer_data->blue_offset  = tvb_get_letohl(tvb, offset + 4 * 9);
                framebuffer_data->blue_length  = tvb_get_letohl(tvb, offset + 4 * 10);
                framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset + 4 * 11);
                framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset + 4 * 12);

                wmem_tree_insert32_array(framebuffer_infos, key, framebuffer_data);
            }

            if (framebuffer_data && framebuffer_data->data_in == pinfo->num) {
                proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_width, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_height, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_red_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_red_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_blue_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_blue_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_green_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_green_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_alpha_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_alpha_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;
            }

            if (tvb_reported_length_remaining(tvb, offset) > 0) {
                sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
                sub_tree = proto_item_add_subtree(sub_item, ett_data);

                if (!pinfo->fd->flags.visited && framebuffer_data) {
                    framebuffer_data->current_size += tvb_captured_length_remaining(tvb, offset);
                    if (framebuffer_data->current_size >= framebuffer_data->size)
                        framebuffer_data->completed_in_frame = pinfo->num;
                }

                if (pref_dissect_more_detail_framebuffer) {
                    proto_item  *pixel_item;
                    proto_tree  *pixel_tree;

                    if (framebuffer_data &&
                        framebuffer_data->red_length == 5 &&
                        framebuffer_data->green_length == 6 &&
                        framebuffer_data->blue_length == 5 &&
                        framebuffer_data->red_offset == 11 &&
                        framebuffer_data->green_offset == 5 &&
                        framebuffer_data->blue_offset == 0) {
                        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                            if (tvb_reported_length_remaining(tvb, offset) < 2) {
                                proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
                                offset += 1;
                            }

                            pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA);
                            pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);

                            proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            offset += 2;
                        }
                    } else if (framebuffer_data &&
                            framebuffer_data->red_length == 8 &&
                            framebuffer_data->green_length == 8 &&
                            framebuffer_data->blue_length == 8 &&
                            (framebuffer_data->alpha_length == 0 ||
                            framebuffer_data->alpha_length == 8)) {
                        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                            if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && framebuffer_data->alpha_offset > 0)) {
                                proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
                                offset = tvb_captured_length(tvb);
                                break;
                            }

                            pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA);
                            pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);

                            proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + framebuffer_data->red_offset / 8, 1, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + framebuffer_data->green_offset / 8, 1, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + framebuffer_data->blue_offset / 8, 1, ENC_LITTLE_ENDIAN);

                            if (framebuffer_data->alpha_offset > 0) {
                                if (framebuffer_data->alpha_length == 0)
                                    proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN);
                                else
                                    proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN);
                                offset += 1;
                                proto_item_set_len(pixel_item, 4);
                            }
                            offset += 3;
                        }
                    } else {
                        offset = tvb_captured_length(tvb);
                    }
                } else {
                    offset = tvb_captured_length(tvb);
                }
            }
        } else if (g_strcmp0(service, "track-jdwp") == 0) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            if (tvb_reported_length_remaining(tvb, offset) > 0) {
                sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_NA | ENC_ASCII);
                if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                    expert_add_info(pinfo, sub_item, &ei_incomplete_message);
                }
            }
            offset = tvb_captured_length(tvb);
        } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) ||
                (g_strcmp0(service, "shell:logcat -B") == 0)) {
            tvbuff_t    *next_tvb;
            tvbuff_t    *new_tvb;
            guint8      *buffer = NULL;
            gint         size = 0;
            gint         i_offset = offset;
            gint         old_offset;
            gint         i_char = 0;
            guint8       c1;
            guint8       c2 = '\0';
            guint16      payload_length;
            guint16      try_header_size;
            gint         logcat_length = 0;
            fragment_t  *fragment;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key);
            fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->num - 1) : NULL;
            if (fragment) {
                if (!pinfo->fd->flags.visited && fragment->reassembled_in_frame == -1)
                    fragment->reassembled_in_frame = pinfo->num;

                if (fragment->reassembled_in_frame == pinfo->num) {
                    size += fragment->length;
                    i_char += fragment->length;
                }
            }

            size += tvb_reported_length_remaining(tvb, i_offset);
            if (size > 0) {
                buffer = (guint8 *) wmem_alloc(pinfo->pool, size);
                if (fragment && i_char > 0)
                    memcpy(buffer, fragment->data, i_char);

                if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_guint8(tvb, i_offset) == '\n') {
                    buffer[i_char - 1] = '\n';
                    i_offset += 1;
                }

                c1 = tvb_get_guint8(tvb, i_offset);
                i_offset += 1;
                old_offset = i_offset;

                while (tvb_reported_length_remaining(tvb, i_offset) > 0) {
                    c2 = tvb_get_guint8(tvb, i_offset);

                    if (c1 == '\r' && c2 == '\n') {
                        buffer[i_char] = c2;
                        if (tvb_reported_length_remaining(tvb, i_offset) > 1) {
                            c1 = tvb_get_guint8(tvb, i_offset + 1);
                            i_offset += 2;
                            i_char += 1;
                        } else {
                            i_offset += 1;
                        }

                        continue;
                    }

                    buffer[i_char] = c1;
                    c1 = c2;
                    i_char += 1;
                    i_offset += 1;
                }

                if (tvb_reported_length_remaining(tvb, old_offset) == 0) {
                    buffer[i_char] = c1;
                    i_char += 1;
                } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) {
                    buffer[i_char] = c2;
                    i_char += 1;
                }

                next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char);
                add_new_data_source(pinfo, next_tvb, "Logcat");

                i_offset = 0;
                while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) {
                    if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) {
                        payload_length = tvb_get_letohs(next_tvb, i_offset);
                        try_header_size = tvb_get_letohs(next_tvb, i_offset + 2);

                        if (try_header_size != 24)
                            logcat_length = payload_length + 20;
                        else
                            logcat_length = payload_length + 24;
                    }

                    if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) {
                        new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length);

                        call_dissector(logcat_handle, new_tvb, pinfo, main_tree);
                        i_offset += logcat_length;
                    } else {

                        if (!pinfo->fd->flags.visited) {
                            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 2 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
                            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                                key[i_key].length = 1;
                                key[i_key].key = &adb_service_data->session_key[i_key];
                            }
                            key[i_key].length = 1;
                            key[i_key++].key = &pinfo->num;
                            key[i_key].length = 0;
                            key[i_key].key = NULL;

                            fragment = wmem_new(wmem_file_scope(), fragment_t);

                            fragment->length = tvb_captured_length_remaining(next_tvb, i_offset);
                            fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), fragment->length);
                            tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length);
                            fragment->reassembled_in_frame = -1;

                            wmem_tree_insert32_array(fragments, key, fragment);
                        }

                        proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA);
                        i_offset = tvb_captured_length(next_tvb);
                    }
                }
            }

            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "shell:")) {
            if (adb_service_data->direction == P2P_DIR_SENT) {
                proto_tree_add_item(main_tree, hf_stdin, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Stdin=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));

            } else {
                proto_tree_add_item(main_tree, hf_stdout, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Stdout=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));
            }
            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "jdwp:")) {
/* TODO */
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "sync:")) {
/* TODO */
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        } else if (g_strcmp0(service, "host:list-forward") == 0 ||
                g_str_has_prefix(service, "root:") ||
                g_str_has_prefix(service, "remount:")  ||
                g_str_has_prefix(service, "tcpip:")  ||
                g_str_has_prefix(service, "usb:")) {
            if (tvb_reported_length_remaining(tvb, offset)) {
                proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Result=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));

                offset = tvb_captured_length(tvb);
            }
        } else {
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        }

    return offset;
}
Example #14
0
#define EOMc    (0x11)
#define EOMu    (0x12)
#define EOMi    (0x13)

#define MAX_EOM_MSG_SIZE    (16)            /* max size of an EOMx indicator string */

static void
dissect_ipars(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree)
{
    int       bytes;
    guint8    ia     = 0, ta = 0, cmd = 0, la = 0;
    tvbuff_t *next_tvb;
    int       offset = 0;
    gchar    *eom_msg;

    eom_msg    = (gchar *)wmem_alloc(wmem_packet_scope(), MAX_EOM_MSG_SIZE);
    eom_msg[0] = 0;

    col_clear(pinfo->cinfo, COL_INFO);

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

    if (tvb_length_remaining(tvb, 0) >= 2 ) {
        ia = tvb_get_guint8(tvb, 0) & 0x3f;
        ta = tvb_get_guint8(tvb, 1) & 0x3f;
        if (ia == S1 && ta == S2) { /* if the first two bytes are S1/S2 skip over them */
            offset = 2;
        }
    }
    if (tvb_length_remaining(tvb, offset) >= 1) ia = tvb_get_guint8(tvb, offset + 0);
    if (tvb_length_remaining(tvb, offset) >= 2) ta = tvb_get_guint8(tvb, offset + 1);
Example #15
0
/* Code to actually dissect the packets */
static void
dissect_manolito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	unsigned int offset;

	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *ti;
	proto_tree *manolito_tree;
	const char* packet_type = 0;

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

	ti = proto_tree_add_item(tree, proto_manolito, tvb, 0, -1, ENC_NA);

	manolito_tree = proto_item_add_subtree(ti, ett_manolito);

	/* MANOLITO packet header (network byte order) */
	proto_tree_add_item(manolito_tree,
	    hf_manolito_checksum, tvb, 0, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(manolito_tree,
	    hf_manolito_seqno, tvb, 4, 4, ENC_BIG_ENDIAN);

	proto_tree_add_item(manolito_tree,
	    hf_manolito_src, tvb, 8, 4, ENC_BIG_ENDIAN);

	proto_tree_add_item(manolito_tree,
	    hf_manolito_dest, tvb, 12, 4, ENC_BIG_ENDIAN);

	if (tvb_reported_length(tvb) == 19) {
		packet_type = "Ping (truncated)";
		proto_tree_add_item(manolito_tree,
		    hf_manolito_options_short, tvb, 16, 3, ENC_BIG_ENDIAN);
	} else {
		proto_tree_add_item(manolito_tree,
		    hf_manolito_options, tvb, 16, 4, ENC_BIG_ENDIAN);
	}

	if (tvb_reported_length(tvb) <= 20)      /* no payload, just headers */
	{
		col_set_str(pinfo->cinfo, COL_INFO, "Ping");
	} else {
		offset = 20;            /* fields start here */

	 	/* fields format: 2-byte name, optional NULL, 1-byte lenlen, */
		/* that many bytes(len or data), for NI,CN,VL is len, more */
		/* (that many bytes) data follows; else is raw data. */
		do
		{
			guint16 field_name;      /* 16-bit field name */
			guint8 dtype;            /* data-type */
			guint8 length;           /* length */
			guint8* data;            /* payload */
			int start;               /* field starting location */
			char field_name_str[3];  /* printable name */
			const char* longname;    /* human-friendly field name */

			start = offset;

			/* 2-byte field name */
			field_name = tvb_get_ntohs(tvb, offset);
			offset += 2;

			/* Identify the packet based on existing fields */
			/* Maybe using the options fields is a better idea...*/
			if (field_name == 0x434b)    /* CK */
				packet_type = "Search Hit";
			if (field_name == 0x4e43)    /* NC */
				packet_type = "User Information";
			if (field_name == 0x464e)    /* FN - if only field */
				packet_type = "Search Query";
			if (field_name == 0x4944)    /* ID ?? search by CK? */
				packet_type = "Search Query (by hash)";
			if (field_name == 0x5054)    /* PT */
				packet_type = "Download Request";
			if (field_name == 0x4d45)    /* ME */
				packet_type = "Chat";

			if (tvb_reported_length(tvb) == 20)   /* no fields */
				packet_type = "Ping";

			/* Find the long name of the field */
			switch(field_name)
			{
			case 0x5346: longname = "Shared Files"; break;    /* SF */
			case 0x534b: longname = "Shared Kilobytes";break; /* SK */
			case 0x4e49: longname = "Network ID"; break;      /* NI */
			case 0x4e43: longname = "Num. Connections";break; /* NC */
			case 0x4356: longname = "Client Version"; break;  /* CV */
			case 0x564c: longname = "Velocity"; break;        /* VL */
			case 0x464e: longname = "Filename"; break;        /* FN */
			case 0x464c: longname = "File Length"; break;     /* FL */
			case 0x4252: longname = "Bit Rate"; break;        /* BR */
			case 0x4643: longname = "Frequency"; break;       /* FC */
			case 0x5354: longname = "???"; break;             /* ST */
			case 0x534c: longname = "Song Length (s)"; break; /* SL */
			case 0x434b: longname = "Checksum"; break;    /* CK */
			case 0x4e4e: longname = "Nickname"; break;        /* NN */
			case 0x434e: longname = "Client Name"; break;     /* CN */
			case 0x5054: longname = "Port"; break;            /* PT */
			case 0x484e: longname = "???"; break;             /* HN */
			case 0x4d45: longname = "Message"; break;         /* ME */
			case 0x4944: longname = "Identification"; break;  /* ID */
			case 0x4144: longname = "???"; break;             /* AD */
			default: longname = "unknown"; break;
			}

			/* 1-byte data type */
#define MANOLITO_STRING		1
#define MANOLITO_INTEGER	0
			dtype = tvb_get_guint8(tvb, offset);
			length = tvb_get_guint8(tvb, ++offset);

			/*
			 * Get the payload.
			 *
			 * XXX - is the cast necessary?  I think the
			 * "usual arithmetic conversions" should
			 * widen it past 8 bits, so there shouldn't
			 * be an overflow.
			 */
			data = (guint8 *)wmem_alloc(wmem_packet_scope(), (guint)length + 1);
			tvb_memcpy(tvb, data, ++offset, length);
			offset += length;

			/* convert the 16-bit integer field name to a string */
                        /* XXX: changed this to use g_htons */
			field_name_str[0] = g_htons(field_name) & 0x00ff;
			field_name_str[1] = (g_htons(field_name) & 0xff00) >> 8;
			field_name_str[2] = 0;

			if (dtype == MANOLITO_STRING)
			{
				data[length] = 0;
				proto_tree_add_text(manolito_tree, tvb, start,
					offset - start, "%s (%s): %s",
					(char*)field_name_str, longname, data);
			} else if (dtype == MANOLITO_INTEGER) {
			 	int n = 0;

				/* integers can be up to 5 bytes */
				switch(length)
				{
				case 5: n += data[4] << ((length - 5) * 8);
				case 4: n += data[3] << ((length - 4) * 8);
				case 3: n += data[2] << ((length - 3) * 8);
				case 2: n += data[1] << ((length - 2) * 8);
				case 1: n += data[0] << ((length - 1) * 8);
				}
				proto_tree_add_text(manolito_tree, tvb, start,
					offset - start, "%s (%s): %d",
					(char*)field_name_str, longname, n);
			} else {
				proto_tree_add_text(manolito_tree, tvb, start,
					offset - start, "unknown type %d", dtype);
			}

		} while(offset < tvb_reported_length(tvb));

	}

	if (packet_type)
	{
		col_set_str(pinfo->cinfo, COL_INFO, packet_type);
	}
}
Example #16
0
static void
dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  gboolean        is_request;
  proto_tree      *imap_tree, *reqresp_tree;
  proto_item      *ti, *hidden_item;
  gint            offset = 0;
  gint            uid_offset = 0;
  gint            folder_offset = 0;
  const guchar    *line;
  const guchar    *uid_line;
  const guchar    *folder_line;
  gint            next_offset;
  int             linelen;
  int             tokenlen;
  int             uid_tokenlen;
  int             folder_tokenlen;
  const guchar    *next_token;
  const guchar    *uid_next_token;
  const guchar    *folder_next_token;
  guchar          *tokenbuf;
  guchar          *command_token;
  int             iter;
  int             commandlen;

  tokenbuf = (guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUFFER);
  command_token = (guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUFFER);
  memset(tokenbuf, '\0', MAX_BUFFER);
  memset(command_token, '\0', MAX_BUFFER);
  commandlen = 0;
  folder_offset = 0;
  folder_tokenlen = 0;
  folder_line = NULL;
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMAP");


  if (pinfo->match_uint == pinfo->destport)
    is_request = TRUE;
  else
    is_request = FALSE;

  /*
   * Put the first line from the buffer into the summary
   * (but leave out the line terminator).
   */
  linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
  line = tvb_get_ptr(tvb, offset, linelen);

  col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen));

  if (tree) {
    ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1, ENC_NA);
    imap_tree = proto_item_add_subtree(ti, ett_imap);

    hidden_item = proto_tree_add_boolean(imap_tree, hf_imap_isrequest, tvb, 0, 0, is_request);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    while(tvb_length_remaining(tvb, offset) > 0) {

      /*
       * Find the end of each line
       *
       * Note that "tvb_find_line_end()" will return a value that is
       * not longer than what's in the buffer, so the "tvb_get_ptr()"
       * call won't throw an exception.
       */
      linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
      line = tvb_get_ptr(tvb, offset, linelen);

      /*
       * Put the line into the protocol tree.
       */
      ti = proto_tree_add_item(imap_tree, hf_imap_line, tvb, offset, next_offset - offset, ENC_ASCII|ENC_NA);

      reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp);

      /*
       * Check that the line doesn't begin with '*', because that's a continuation line.
       * Otherwise if a tag is present then extract tokens.
       */
      if ( (line) && ((line[0] != '*') || (TRUE == is_request)) ) {
        /*
         * Show each line as tags + requests or replies.
         */

        /*
         * Extract the first token, and, if there is a first
         * token, add it as the request or reply tag.
         */
        tokenlen = get_token_len(line, line + linelen, &next_token);
        if (tokenlen != 0) {
          proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_tag : hf_imap_response_tag, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);

          offset += (gint) (next_token - line);
          linelen -= (int) (next_token - line);
          line = next_token;
        }

        /*
         * Extract second token, and, if there is a second
         * token, and it's not uid, add it as the request or reply command.
         */
        tokenlen = get_token_len(line, line + linelen, &next_token);
        if (tokenlen != 0) {
          for (iter = 0; iter < tokenlen && iter < MAX_BUFFER-1; iter++) {
            tokenbuf[iter] = g_ascii_tolower(line[iter]);
          }
          if ( TRUE == is_request && strncmp(tokenbuf,"uid",tokenlen) == 0) {
            proto_tree_add_item(reqresp_tree, hf_imap_request_uid, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
            /*
             * UID is a precursor to a command, if following the tag,
              * so move to next token to grab the actual command.
              */
            uid_offset = offset;
            uid_offset += (gint) (next_token - line);
            uid_line = next_token;
            uid_tokenlen = get_token_len(uid_line, uid_line + (linelen - tokenlen), &uid_next_token);
            if (tokenlen != 0) {
              proto_tree_add_item(reqresp_tree, hf_imap_request_command, tvb, uid_offset, uid_tokenlen, ENC_ASCII|ENC_NA);

              /*
               * Save command string to do specialized processing.
               */
              for (iter = 0; iter < uid_tokenlen && iter < MAX_BUFFER-1; iter++) {
                command_token[iter] = g_ascii_tolower(uid_line[iter]);
              }
              commandlen = uid_tokenlen;

              folder_offset = uid_offset;
              folder_offset += (gint) (uid_next_token - uid_line);
              folder_line = uid_next_token;
              folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - uid_tokenlen), &folder_next_token);
            }
          } else {
            /*
             * Not a UID request so perform normal parsing.
             */
            proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_command : hf_imap_response_status, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);

            if (is_request) {
              /*
               * Save command string to do specialized processing.
               */
              for (iter = 0; iter < tokenlen && iter < 256; iter++) {
                command_token[iter] = g_ascii_tolower(line[iter]);
              }
              commandlen = tokenlen;

              folder_offset = offset;
              folder_offset += (gint) (next_token - line);
              folder_line = next_token;
              folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - 1), &folder_next_token);
            }
          }

          if (commandlen > 0 && (
              strncmp(command_token, "select", commandlen) == 0 ||
              strncmp(command_token, "examine", commandlen) == 0 ||
              strncmp(command_token, "create", commandlen) == 0 ||
              strncmp(command_token, "delete", commandlen) == 0 ||
              strncmp(command_token, "rename", commandlen) == 0 ||
              strncmp(command_token, "subscribe", commandlen) == 0 ||
              strncmp(command_token, "unsubscribe", commandlen) == 0 ||
              strncmp(command_token, "status", commandlen) == 0 ||
              strncmp(command_token, "append", commandlen) == 0 ||
              strncmp(command_token, "search", commandlen) == 0)) {
            /*
             * These commands support folder as an argument,
             * so parse out the folder name.
             */
            if (folder_tokenlen != 0)
              proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA);
          }

          if ( is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) {
            /*
             * Handle the copy command separately since folder
             * is the second argument for this command.
             */
            folder_offset += (gint) (folder_next_token - folder_line);
            folder_line = folder_next_token;
            folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen), &folder_next_token);

            if (folder_tokenlen != 0)
              proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA);
          }

        }

        /*
         * Add the rest of the line as request or reply data.
         */
        if (linelen != 0) {
          proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request : hf_imap_response, tvb, offset, linelen, ENC_ASCII|ENC_NA);
        }

      }

      offset = next_offset; /* Skip over last line and \r\n at the end of it */
    }
  }
}
 // Allocate our records using wmem.
 static void *operator new(size_t size) {
     return wmem_alloc(wmem_file_scope(), size);
 }
Example #18
0
static void
dissect_pgmopts(ptvcursor_t* cursor, packet_info *pinfo, const char *pktname)
{
	proto_item *tf, *ti, *ti_len;
	proto_tree *opts_tree = NULL;
	proto_tree *opt_tree  = NULL;
	tvbuff_t   *tvb       = ptvcursor_tvbuff(cursor);

	gboolean theend = FALSE;

	guint16 opts_total_len;
	guint8  genopts_type;
	guint8  genopts_len;
	guint8  opts_type;

	opts_tree = proto_tree_add_subtree_format(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), -1,
		ett_pgm_opts, &tf, "%s Options", pktname);
	ptvcursor_set_tree(cursor, opts_tree);
	opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
	ti = ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN);
	if (opts_type != PGM_OPT_LENGTH) {
		expert_add_info_format(pinfo, ti, &ei_pgm_opt_type,
		    "%s Options - initial option is %s, should be %s",
		    pktname,
		    val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"),
		    val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)"));
		return;
	}
	ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN);
	opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
	proto_item_append_text(tf, " (Total Length %d)", opts_total_len);
	proto_item_set_len(tf, opts_total_len);
	ti_len = ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN);
	if (opts_total_len < 4) {
		expert_add_info_format(pinfo, ti_len, &ei_pgm_opt_tlen,
			"%s Options (Total Length %u - invalid, must be >= 4)",
			pktname, opts_total_len);
		return;
	}

	for (opts_total_len -= 4; !theend && opts_total_len != 0;){
		if (opts_total_len < 4) {
			expert_add_info_format(pinfo, ti_len, &ei_pgm_opt_tlen,
				"Remaining total options length doesn't have enough for an options header");
			break;
		}

		genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
		genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1);

		if (genopts_type & PGM_OPT_END)  {
			genopts_type &= ~PGM_OPT_END;
			theend = TRUE;
		}

		switch(genopts_type) {
		case PGM_OPT_JOIN:{
			TLV_CHECK(ett_pgm_opts_join);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_JOIN_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_JOIN_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_PRM:{
			guint8 optdata_po;

			TLV_CHECK(ett_pgm_opts_parityprm);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);


			if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor),
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_PRM_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			proto_tree_add_uint_format_value(opt_tree, hf_pgm_opt_parity_prm_po, tvb,
				ptvcursor_current_offset(cursor), 1, optdata_po, "%s (0x%x)",
				paritystr(optdata_po), optdata_po);
			ptvcursor_advance(cursor, 1);

			ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_GRP:{
			TLV_CHECK(ett_pgm_opts_paritygrp);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_GRP_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_LIST:{
			guint8 optdata_len;
			guint32 naklist[PGM_MAX_NAK_LIST_SZ+1];
			unsigned char *nakbuf;
			gboolean firsttime;
			int i, j, naks, soffset;

			TLV_CHECK(ett_pgm_opts_naklist);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN);

			optdata_len -= PGM_OPT_NAK_LIST_SIZE;
			tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len);
			firsttime = TRUE;
			soffset = 0;
			naks = (int)(optdata_len/sizeof(guint32));
			nakbuf = (unsigned char *)wmem_alloc(wmem_packet_scope(), 8192);
			j = 0;
			/*
			 * Print out 8 per line
			 */
			for (i=0; i < naks; i++) {
				soffset += MIN(8192-soffset,
					g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ",
						(unsigned long)g_ntohl(naklist[i])));
				if ((++j % 8) == 0) {
					if (firsttime) {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List(%d): %s", naks, nakbuf);
						soffset = 0;
						firsttime = FALSE;
					} else {
						proto_tree_add_bytes_format_value(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "%s", nakbuf);
						soffset = 0;
					}
					ptvcursor_advance(cursor, j*4);
					j = 0;
				}
			}
			if (j) {
				if (firsttime) {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List(%d): %s", naks, nakbuf);
				} else {
					proto_tree_add_bytes_format_value(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "%s", nakbuf);
				}
				ptvcursor_advance(cursor, j*4);
			}
			break;
		}
		case PGM_OPT_PGMCC_DATA:{
			guint16 optdata_afi;

			TLV_CHECK(ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_DATA_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			break;
		}
		case PGM_OPT_PGMCC_FEEDBACK:{
			guint16 optdata_afi;

			TLV_CHECK(ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			break;
		}
		case PGM_OPT_NAK_BO_IVL:{
			TLV_CHECK(ett_pgm_opts_nak_bo_ivl);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_IVL_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_BO_RNG:{
			TLV_CHECK(ett_pgm_opts_nak_bo_rng);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_RNG_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_REDIRECT:{
			guint16 optdata_afi;

			TLV_CHECK(ett_pgm_opts_redirect);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_REDIRECT_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_REDIRECT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			break;
		}
		case PGM_OPT_FRAGMENT:{
			TLV_CHECK(ett_pgm_opts_fragment);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_FRAGMENT_SIZE) {
				proto_tree_add_uint_format_value(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"%u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_FRAGMENT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN);

			break;
		}
		default:{
			TLV_CHECK(ett_pgm_opts);
			ptvcursor_advance(cursor, genopts_len);
			break;
		}
		}

		opts_total_len -= genopts_len;
	}
	return;
}
void *PacketListRecord::operator new(size_t size)
{
    return wmem_alloc(wmem_file_scope(), size);
}
Example #20
0
static int
nmas_string(tvbuff_t* tvb, int hfinfo, proto_tree *nmas_tree, int offset, gboolean little)
{
    int     foffset = offset;
    guint32 str_length;
    char    *buffer;
    guint32 i;
    guint16 c_char;
    guint32 length_remaining = 0;

    buffer = (char *)wmem_alloc(wmem_packet_scope(), ITEM_LABEL_LENGTH+1);
    if (little) {
        str_length = tvb_get_letohl(tvb, foffset);
    } else {
        str_length = tvb_get_ntohl(tvb, foffset);
    }
    foffset += 4;
    if (str_length >= ITEM_LABEL_LENGTH) {
        proto_tree_add_string(nmas_tree, hfinfo, tvb, foffset,
                              length_remaining + 4, "<String too long to process>");
        foffset += length_remaining;
        return foffset;
    }
    if (str_length == 0) {
        proto_tree_add_string(nmas_tree, hfinfo, tvb, offset, 4,
                              "<Not Specified>");
        return foffset;
    }
    /*
     * XXX - other than the special-casing of null bytes,
     * we could just use "proto_tree_add_item()", as for
     * FT_STRING, FT_STRINGZ, and FT_UINT_STRING fields,
     * the display representation of an item is generated
     * using "format_text()", so it handles non-printable
     * characters.
     */
    for ( i = 0; i < str_length; i++ ) {
        c_char = tvb_get_guint8(tvb, foffset );
        if (c_char<0x20 || c_char>0x7e) {
            if (c_char != 0x00) {
                c_char = 0x2e;
                buffer[i] = c_char & 0xff;
            } else {
                i--;
                str_length--;
            }
        } else {
            buffer[i] = c_char & 0xff;
        }
        foffset++;
        length_remaining--;

        if (length_remaining==1) {
            i++;
            break;
        }
    }
    buffer[i] = '\0';

    if (little) {
        str_length = tvb_get_letohl(tvb, offset);
    } else {
        str_length = tvb_get_ntohl(tvb, offset);
    }
    proto_tree_add_string(nmas_tree, hfinfo, tvb, offset+4, str_length, buffer);
    return foffset;
}
Example #21
0
/* Code to actually dissect the packets */
static void
dissect_ax25_kiss( tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree )
{
	proto_item *ti;
	proto_tree *kiss_tree;
	int         offset;
	int         kiss_cmd;
	int         kiss_type;
	int         kiss_port;
	int         kiss_param;
	int         kiss_param_len;
	const char *frame_type_text;
	char       *info_buffer;
	tvbuff_t   *next_tvb = NULL;

	info_buffer    = (char *)wmem_alloc( wmem_packet_scope(), STRLEN );
	info_buffer[0] = '\0';

	col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25 KISS" );
	col_clear( pinfo->cinfo, COL_INFO );

	/* protocol offset for the KISS header */
	offset = 0;

	kiss_cmd   = tvb_get_guint8( tvb, offset ) & 0xff;
	kiss_type  = kiss_cmd & KISS_CMD_MASK;
	kiss_port  = (kiss_cmd & KISS_PORT_MASK) >> 4;
	offset    += KISS_HEADER_SIZE;

	kiss_param      = 0;
	kiss_param_len  = 0;
	switch ( kiss_type )
		{
		case KISS_TXDELAY	: kiss_param_len = 1; kiss_param = tvb_get_guint8( tvb, offset ) & 0xff; break;
		case KISS_PERSISTENCE	: kiss_param_len = 1; kiss_param = tvb_get_guint8( tvb, offset ) & 0xff; break;
		case KISS_SLOT_TIME	: kiss_param_len = 1; kiss_param = tvb_get_guint8( tvb, offset ) & 0xff; break;
		case KISS_TXTAIL	: kiss_param_len = 1; kiss_param = tvb_get_guint8( tvb, offset ) & 0xff; break;
		case KISS_FULLDUPLEX	: kiss_param_len = 1; kiss_param = tvb_get_guint8( tvb, offset ) & 0xff; break;
		case KISS_SETHARDWARE	: kiss_param_len = 1; kiss_param = tvb_get_guint8( tvb, offset ) & 0xff; break;
		default			: break;
		}
	frame_type_text = val_to_str(kiss_type, kiss_frame_types, "Unknown (%u)");
	g_snprintf( info_buffer, STRLEN, "%s, Port %u", frame_type_text, kiss_port );
	if ( kiss_param_len > 0 )
		g_snprintf( info_buffer, STRLEN, "%s %u, Port %u", frame_type_text, kiss_param, kiss_port );

	offset += kiss_param_len;

	col_add_str( pinfo->cinfo, COL_INFO, info_buffer );

	if ( parent_tree )
		{
		/* protocol offset for the KISS header */
		offset = 0;

		/* create display subtree for the protocol */
		ti = proto_tree_add_protocol_format( parent_tree, proto_ax25_kiss, tvb, offset,
			KISS_HEADER_SIZE + kiss_param_len,
			"KISS: %s",
			info_buffer
			);

		kiss_tree = proto_item_add_subtree( ti, ett_ax25_kiss );

		proto_tree_add_uint( kiss_tree, hf_ax25_kiss_cmd,  tvb, offset, KISS_HEADER_SIZE,
					kiss_cmd );
		proto_tree_add_uint( kiss_tree, hf_ax25_kiss_port, tvb, offset, KISS_HEADER_SIZE,
					kiss_port );
		offset += KISS_HEADER_SIZE;

		switch ( kiss_type  )
			{
			case KISS_DATA_FRAME	: break;
			case KISS_TXDELAY	:
						proto_tree_add_uint( kiss_tree, hf_ax25_kiss_txdelay,
							tvb, offset, kiss_param_len, kiss_param );
						offset += kiss_param_len;
						break;
			case KISS_PERSISTENCE	:
						proto_tree_add_uint( kiss_tree, hf_ax25_kiss_persistence,
							tvb, offset, kiss_param_len, kiss_param );
						offset += kiss_param_len;
						break;
			case KISS_SLOT_TIME	:
						proto_tree_add_uint( kiss_tree, hf_ax25_kiss_slottime,
							tvb, offset, kiss_param_len, kiss_param );
						offset += kiss_param_len;
						break;
			case KISS_TXTAIL	:
						proto_tree_add_uint( kiss_tree, hf_ax25_kiss_txtail,
							tvb, offset, kiss_param_len, kiss_param );
						offset += kiss_param_len;
						break;
			case KISS_FULLDUPLEX	:
						proto_tree_add_uint( kiss_tree, hf_ax25_kiss_fullduplex,
							tvb, offset, kiss_param_len, kiss_param );
						offset += kiss_param_len;
						break;
			case KISS_SETHARDWARE	:
						proto_tree_add_uint( kiss_tree, hf_ax25_kiss_sethardware,
							tvb, offset, kiss_param_len, kiss_param );
						offset += kiss_param_len;
						break;
			case KISS_RETURN	: break;
			default			: break;
			}

	}
	/* Call sub-dissectors here */

	if ( kiss_type == KISS_DATA_FRAME )
		{
		next_tvb = tvb_new_subset_remaining( tvb, offset );
		call_dissector( ax25_handle, next_tvb, pinfo, parent_tree );
		}
}
Example #22
0
static void
save_command(guint32 cmd, guint32 arg0, guint32 arg1, guint32 data_length,
        guint32 crc32, service_data_t *service_data, gint proto, void *data,
        packet_info *pinfo, service_data_t **returned_service_data,
        command_data_t **returned_command_data)
{
    wmem_tree_key_t  key[6];
    guint32          interface_id;
    guint32          bus_id;
    guint32          device_address;
    guint32          side_id;
    guint32          frame_number;
    command_data_t  *command_data;
    wmem_tree_t     *wmem_tree;
    gint             direction = P2P_DIR_UNKNOWN;
    usb_conv_info_t *usb_conv_info = (usb_conv_info_t *) data;

    frame_number = pinfo->fd->num;

    if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
        interface_id = pinfo->phdr->interface_id;
    else
        interface_id = 0;

    if (proto == proto_usb) {
        usb_conv_info = (usb_conv_info_t *) data;
        DISSECTOR_ASSERT(usb_conv_info);

        direction = usb_conv_info->direction;

        bus_id             = usb_conv_info->bus_id;
        device_address     = usb_conv_info->device_address;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[1].key = &bus_id;
        key[2].length = 1;
        key[2].key = &device_address;
        key[3].length = 1;
        key[3].key = &side_id;
        key[4].length = 1;
        key[4].key = &frame_number;
        key[5].length = 0;
        key[5].key = NULL;
    } else { /* tcp */
        if (pinfo->destport == ADB_TCP_PORT)
            direction = P2P_DIR_SENT;
        else
            direction = P2P_DIR_RECV;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[2].length = 1;
        if (direction == P2P_DIR_SENT) {
            key[1].key = &pinfo->srcport;
            key[2].key = &pinfo->destport;
        } else {
            key[1].key = &pinfo->destport;
            key[2].key = &pinfo->srcport;
        }
        key[3].length = 1;
        key[3].key = &side_id;
        key[4].length = 1;
        key[4].key = &frame_number;
        key[5].length = 0;
        key[5].key = NULL;
    }

    if (direction == P2P_DIR_SENT)
        if (cmd == A_CLSE)
            side_id = arg1; /* OUT: local id */
        else
            side_id = arg0; /* OUT: local id */
    else
        side_id = arg1; /* IN: remote id */

    if (cmd == A_OPEN) {
        service_data = wmem_new(wmem_file_scope(), service_data_t);

        service_data->start_in_frame = pinfo->fd->num;
        service_data->close_local_in_frame = max_in_frame;
        service_data->close_remote_in_frame = max_in_frame;

        service_data->local_id = arg0;
        service_data->remote_id = arg1;

        service_data->service = "unknown";

        wmem_tree_insert32_array(service_info, key, service_data);
    }

    command_data = wmem_new(wmem_file_scope(), command_data_t);

    command_data->command = cmd;
    command_data->arg0 = arg0;
    command_data->arg1 = arg1;

    command_data->command_in_frame = pinfo->fd->num;
    command_data->response_in_frame = max_in_frame;

    command_data->crc32 = crc32;
    command_data->data_length = data_length;
    if (data_length == 0)
        command_data->completed_in_frame = pinfo->fd->num;
    else
        command_data->completed_in_frame = max_in_frame;
    command_data->reassemble_data_length = 0;
    command_data->reassemble_data = (guint8 *) wmem_alloc(wmem_file_scope(), command_data->data_length);

    key[3].length = 1;
    key[3].key = &frame_number;
    key[4].length = 0;
    key[4].key = NULL;
    wmem_tree_insert32_array(command_info, key, command_data);

    if (direction == P2P_DIR_SENT)
        if (command_data->command == A_CLSE)
            side_id = command_data->arg1; /* OUT: local id */
        else
            side_id = command_data->arg0; /* OUT: local id */
    else
        side_id = command_data->arg1; /* IN: remote id */

    key[3].length = 1;
    key[3].key = &side_id;
    key[4].length = 0;
    key[4].key = NULL;

    wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
    if (wmem_tree) {
        service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
    }

    if (cmd == A_OKAY) {
        if (!service_data) {
            if (direction == P2P_DIR_SENT)
                side_id = command_data->arg0; /* OUT: local id */
            else
                side_id = command_data->arg1; /* IN: remote id */

            wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
            if (wmem_tree) {
                service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
            }
        }

        if  (service_data && service_data->remote_id == 0 && direction == P2P_DIR_RECV) {
            if (direction == P2P_DIR_SENT) {
                service_data->remote_id = arg1;
            } else {
                service_data->remote_id = arg0;
            }

            side_id = service_data->remote_id;

            key[4].length = 1;
            key[4].key = &frame_number;
            key[5].length = 0;
            key[5].key = NULL;

            wmem_tree_insert32_array(service_info, key, service_data);
        }
    } else if (cmd == A_CLSE) {
        if (service_data) {
            if (direction == P2P_DIR_RECV && service_data->local_id == arg1)
                service_data->close_local_in_frame = pinfo->fd->num;
            else if (direction == P2P_DIR_SENT  && service_data->remote_id == arg1)
                service_data->close_remote_in_frame = pinfo->fd->num;
        }
    }

    DISSECTOR_ASSERT(returned_service_data && returned_command_data);
    *returned_service_data = service_data;
    *returned_command_data = command_data;
}
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zbee_secure
 *  DESCRIPTION
 *      Dissects and decrypts secured ZigBee frames.
 *
 *      Will return a valid tvbuff only if security processing was
 *      successful. If processing fails, then this function will
 *      handle internally and return NULL.
 *  PARAMETERS
 *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
 *      packet_info *pinfo  - pointer to packet information fields
 *      proto_tree  *tree   - pointer to data tree Wireshark uses to display packet.
 *      guint       offset  - pointer to the start of the auxiliary security header.
 *      guint64     src64   - extended source address, or 0 if unknown.
 *  RETURNS
 *      tvbuff_t *
 *---------------------------------------------------------------
 */
tvbuff_t *
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset)
{
    proto_tree     *sec_tree;

    zbee_security_packet    packet;
    guint           mic_len;
    gint            payload_len;
    tvbuff_t       *payload_tvb;

#ifdef HAVE_LIBGCRYPT
    proto_item         *ti;
    proto_item         *key_item;
    guint8             *enc_buffer;
    guint8             *dec_buffer;
    gboolean            decrypted;
    GSList            **nwk_keyring;
    GSList             *GSList_i;
    key_record_t       *key_rec = NULL;
#endif
    zbee_nwk_hints_t   *nwk_hints;
    ieee802154_hints_t *ieee_hints;
    ieee802154_map_rec *map_rec = NULL;

    static const int * sec_flags[] = {
        &hf_zbee_sec_key_id,
        &hf_zbee_sec_nonce,
        NULL
    };

    /* Init */
    memset(&packet, 0, sizeof(zbee_security_packet));

    /* Get pointers to any useful frame data from lower layers */
    nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
                proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK), 0);
    ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
                 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);

    /* Create a subtree for the security information. */
    sec_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_zbee_sec, NULL, "ZigBee Security Header");

    /*  Get and display the Security control field */
    packet.control  = tvb_get_guint8(tvb, offset);

    /* Patch the security level. */
    packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
    packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);

    /*
     * Eww, I think I just threw up a little...  ZigBee requires this field
     * to be patched before computing the MIC, but we don't have write-access
     * to the tvbuff. So we need to allocate a copy of the whole thing just
     * so we can fix these 3 bits. Memory allocated by tvb_memdup(wmem_packet_scope(),...)
     * is automatically freed before the next packet is processed.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_captured_length(tvb));
    /*
     * Override the const qualifiers and patch the security level field, we
     * know it is safe to overide the const qualifiers because we just
     * allocated this memory via tvb_memdup(wmem_packet_scope(),...).
     */
    enc_buffer[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
    packet.level    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
    packet.key_id   = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
    packet.nonce    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);

    proto_tree_add_bitmask(sec_tree, tvb, offset, hf_zbee_sec_field, ett_zbee_sec_control, sec_flags, ENC_NA);
    offset += 1;

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter);
    offset += 4;

    if (packet.nonce) {
        /* Get and display the source address of the device that secured this payload. */
        packet.src64 = tvb_get_letoh64(tvb, offset);
        proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
#if 1
        if (!pinfo->fd->flags.visited) {
            switch ( packet.key_id ) {
            case ZBEE_SEC_KEY_LINK:
                if (nwk_hints && ieee_hints) {
                    /* Map this long address with the nwk layer short address. */
                    nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src,
                                         ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num);
                }
                break;

            case ZBEE_SEC_KEY_NWK:
                if (ieee_hints) {
                    /* Map this long address with the ieee short address. */
                    ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16,
                                          ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num);
                }
                break;

            /* We ignore the extended source addresses used to encrypt payloads with these
             * types of keys, because they can emerge from APS tunnels created by nodes whose
             * short address is not recorded in the packet. */
            case ZBEE_SEC_KEY_TRANSPORT:
            case ZBEE_SEC_KEY_LOAD:
                break;
            }
        }
#endif
        offset += 8;
    }
    else {
        /* Look for a source address in hints */
        switch ( packet.key_id ) {
        case ZBEE_SEC_KEY_NWK:
            /* use the ieee extended source address for NWK decryption */
            if ( ieee_hints && (map_rec = ieee_hints->map_rec) )
                packet.src64 = map_rec->addr64;
            else
                proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0);
            break;

        default:
            /* use the nwk extended source address for APS decryption */
            if ( nwk_hints && (map_rec = nwk_hints->map_rec) )
                packet.src64 = map_rec->addr64;
            else
                proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0);
            break;
        }
    }

    if (packet.key_id == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno);
        offset += 1;
    }

    /* Determine the length of the MIC. */
    switch (packet.level) {
    case ZBEE_SEC_ENC:
    case ZBEE_SEC_NONE:
    default:
        mic_len=0;
        break;

    case ZBEE_SEC_ENC_MIC32:
    case ZBEE_SEC_MIC32:
        mic_len=4;
        break;

    case ZBEE_SEC_ENC_MIC64:
    case ZBEE_SEC_MIC64:
        mic_len=8;
        break;

    case ZBEE_SEC_ENC_MIC128:
    case ZBEE_SEC_MIC128:
        mic_len=16;
        break;
    } /* switch */

    /* Get and display the MIC. */
    if (mic_len) {
        /* Display the MIC. */
        proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_captured_length(tvb)-mic_len),
                            mic_len, ENC_NA);
    }

    /* Check for null payload. */
    payload_len = tvb_reported_length_remaining(tvb, offset+mic_len);
    if (payload_len == 0)
        return NULL;

    /**********************************************
     *  Perform Security Operations on the Frame  *
     **********************************************
     */
    if ((packet.level == ZBEE_SEC_NONE) ||
            (packet.level == ZBEE_SEC_MIC32) ||
            (packet.level == ZBEE_SEC_MIC64) ||
            (packet.level == ZBEE_SEC_MIC128)) {

        /* Payload is only integrity protected. Just return the sub-tvbuff. */
        return tvb_new_subset_length(tvb, offset, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Have we captured all the payload? */
    if (tvb_captured_length_remaining(tvb, offset+mic_len) < payload_len) {
        /*
         * No - don't try to decrypt it.
         *
         * XXX - it looks as if the decryption code is assuming we have the
         * MIC, which won't be the case if the packet was cut short.  Is
         * that in fact that case, or can we still make this work with a
         * partially-captured packet?
         */
        /* Add expert info. */
        expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload_sliced);
        /* Create a buffer for the undecrypted payload. */
        payload_tvb = tvb_new_subset_length(tvb, offset, payload_len);
        /* Dump the payload to the data dissector. */
        call_data_dissector(payload_tvb, pinfo, tree);
        /* Couldn't decrypt, so return NULL. */
        return NULL;
    }

    /* Allocate memory to decrypt the payload into. */
    dec_buffer = (guint8 *)wmem_alloc(pinfo->pool, payload_len);

    decrypted = FALSE;
    if ( packet.src64 ) {
        if (pinfo->fd->flags.visited) {
            if ( nwk_hints ) {
                /* Use previously found key */
                switch ( packet.key_id ) {
                case ZBEE_SEC_KEY_NWK:
                    if ( (key_rec = nwk_hints->nwk) ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                                              payload_len, mic_len, nwk_hints->nwk->key);
                    }
                    break;

                default:
                    if ( (key_rec = nwk_hints->link) ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                                              payload_len, mic_len, nwk_hints->link->key);
                    }
                    break;
                }
            }
        } /* ( !pinfo->fd->flags.visited ) */
        else {
            /* We only search for sniffed keys in the first pass,
             * to save time, and because decrypting with keys
             * transported in future packets is cheating */

            /* Lookup NWK and link key in hash for this pan. */
            /* This overkill approach is a placeholder for a hash that looks up
             * a key ring for a link key associated with a pair of devices.
             */
            if ( nwk_hints ) {
                nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);

                if ( nwk_keyring ) {
                    GSList_i = *nwk_keyring;
                    while ( GSList_i && !decrypted ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                                              payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                        if (decrypted) {
                            /* save pointer to the successful key record */
                            switch (packet.key_id) {
                            case ZBEE_SEC_KEY_NWK:
                                key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                break;

                            default:
                                key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                break;
                            }
                        } else {
                            GSList_i = g_slist_next(GSList_i);
                        }
                    }
                }

                /* Loop through user's password table for preconfigured keys, our last resort */
                GSList_i = zbee_pc_keyring;
                while ( GSList_i && !decrypted ) {
                    decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                                          payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                    if (decrypted) {
                        /* save pointer to the successful key record */
                        switch (packet.key_id) {
                        case ZBEE_SEC_KEY_NWK:
                            key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                            break;

                        default:
                            key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                            break;
                        }
                    } else {
                        GSList_i = g_slist_next(GSList_i);
                    }
                }
            }
        } /* ( ! pinfo->fd->flags.visited ) */
    } /* ( packet.src64 ) */

    if ( decrypted ) {
        if ( tree && key_rec ) {
            key_item = proto_tree_add_bytes(sec_tree, hf_zbee_sec_key, tvb, 0, ZBEE_SEC_CONST_KEYSIZE, key_rec->key);
            PROTO_ITEM_SET_GENERATED(key_item);

            if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
                ti = proto_tree_add_string(sec_tree, hf_zbee_sec_decryption_key, tvb, 0, 0, key_rec->label);
            } else {
                ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0,
                                         key_rec->frame_num);
            }
            PROTO_ITEM_SET_GENERATED(ti);
        }

        /* Found a key that worked, setup the new tvbuff_t and return */
        payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
        add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");

        /* Done! */
        return payload_tvb;
    }
#endif /* HAVE_LIBGCRYPT */

    /* Add expert info. */
    expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload);
    /* Create a buffer for the undecrypted payload. */
    payload_tvb = tvb_new_subset_length(tvb, offset, payload_len);
    /* Dump the payload to the data dissector. */
    call_data_dissector(payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;
} /* dissect_zbee_secure */
Example #24
0

/*
 * Main dissection functions
 */

static guint16
dissect_control(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int is_response)
{
	proto_tree *ctl_tree;
	proto_item *ctl_ti;
	guint16 ctl, poll_final;
	const char *frame_type;
	char *info;

	info = (char *)wmem_alloc(wmem_packet_scope(), 80);

	/* Grab complete control field */
	ctl = tvb_get_ntohs(tvb, 1) >> 4;

	poll_final = ctl & LAPSAT_CTL_P_F;

	/* Generate small 'descriptive' text */
	switch (ctl & LAPSAT_CTL_TYPE_S_U_MSK) {
	case LAPSAT_CTL_TYPE_S:
		/*
		 * Supervisory frame.
		 */
		switch (ctl & LAPSAT_CTL_S_FTYPE_MSK) {
		case LAPSAT_RR:
			frame_type = "RR";
Example #25
0
/* dissect the "device" suboption */
static int
dissect_PNDCP_Suboption_Device(tvbuff_t *tvb, int offset, packet_info *pinfo,
                               proto_tree *tree, proto_item *block_item, proto_item *dcp_item,
                               guint8 service_id, gboolean is_response)
{
    guint8    suboption;
    guint16   block_length;
    gchar    *info_str;
    guint8    device_role;
    guint16   vendor_id;
    guint16   device_id;
    char     *typeofstation;
    char     *nameofstation;
    char     *aliasname;
    guint16   block_info;
    guint16   block_qualifier;
    gboolean  have_block_info      = FALSE;
    gboolean  have_block_qualifier = FALSE;
    guint8    device_instance_high;
    guint8    device_instance_low;


    /* SuboptionDevice... */
    offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device, &suboption);
    /* DCPBlockLength */
    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length);

    /* BlockInfo? */
    if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) &&  is_response) ||
         ((service_id == PNDCP_SERVICE_ID_HELLO)    && !is_response) ||
         ((service_id == PNDCP_SERVICE_ID_GET)      &&  is_response)) {
        offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info);
        have_block_info = TRUE;
        block_length -= 2;
    }

    /* BlockQualifier? */
    if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) {
        offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier);
        have_block_qualifier = TRUE;
        block_length -= 2;
    }

    switch (suboption) {
    case PNDCP_SUBOPTION_DEVICE_MANUF:
        typeofstation = (char *)wmem_alloc(wmem_packet_scope(), block_length+1);
        tvb_memcpy(tvb, (guint8 *) typeofstation, offset, block_length);
        typeofstation[block_length] = '\0';
        proto_tree_add_string (tree, hf_pn_dcp_suboption_device_typeofstation, tvb, offset, block_length, typeofstation);
        pn_append_info(pinfo, dcp_item, ", DeviceVendorValue");
        proto_item_append_text(block_item, "Device/Manufacturer specific");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info){
            proto_item_append_text(block_item, ", BlockInfo: %s",
                                   val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        }
        proto_item_append_text(block_item, ", DeviceVendorValue: \"%s\"", typeofstation);
        offset += block_length;
        break;
    case PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION:
        nameofstation = (char *)wmem_alloc(wmem_packet_scope(), block_length+1);
        tvb_memcpy(tvb, (guint8 *) nameofstation, offset, block_length);
        nameofstation[block_length] = '\0';
        proto_tree_add_string (tree, hf_pn_dcp_suboption_device_nameofstation, tvb, offset, block_length, nameofstation);
        pn_append_info(pinfo, dcp_item, wmem_strdup_printf(wmem_packet_scope(), ", NameOfStation:\"%s\"", nameofstation));
        proto_item_append_text(block_item, "Device/NameOfStation");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info) {
            proto_item_append_text(block_item, ", BlockInfo: %s",
                                   val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        }
        proto_item_append_text(block_item, ", \"%s\"", nameofstation);
        offset += block_length;
        break;
    case PNDCP_SUBOPTION_DEVICE_DEV_ID:
        offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_vendor_id, &vendor_id);
        offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_id, &device_id);
        pn_append_info(pinfo, dcp_item, ", Dev-ID");
        proto_item_append_text(block_item, "Device/Device ID");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info) {
            proto_item_append_text(block_item, ", BlockInfo: %s",
                                   val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        }
        proto_item_append_text(block_item, ", VendorID: 0x%04x / DeviceID: 0x%04x", vendor_id, device_id);
        break;
    case PNDCP_SUBOPTION_DEVICE_DEV_ROLE:
        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_role, &device_role);
        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_reserved8, NULL);
        pn_append_info(pinfo, dcp_item, ", Dev-Role");
        proto_item_append_text(block_item, "Device/Device Role");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info)
            proto_item_append_text(block_item, ", BlockInfo: %s", val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        if (device_role & 0x01)
            proto_item_append_text(block_item, ", IO-Device");
        if (device_role & 0x02)
            proto_item_append_text(block_item, ", IO-Controller");
        if (device_role & 0x04)
            proto_item_append_text(block_item, ", IO-Multidevice");
        if (device_role & 0x08)
            proto_item_append_text(block_item, ", PN-Supervisor");
        break;
    case PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS:
        info_str = wmem_strdup_printf(wmem_packet_scope(), ", Dev-Options(%u)", block_length/2);
        pn_append_info(pinfo, dcp_item, info_str);
        proto_item_append_text(block_item, "Device/Device Options");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info) {
            proto_item_append_text(block_item, ", BlockInfo: %s",
                                   val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        }
        proto_item_append_text(block_item, ", %u options", block_length/2);
        for( ; block_length != 0; block_length -= 2) {
            offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, NULL /*block_item*/, hf_pn_dcp_option,
                FALSE /* append_col */);
        }
        break;
    case PNDCP_SUBOPTION_DEVICE_ALIAS_NAME:
        aliasname = (char *)wmem_alloc(wmem_packet_scope(), block_length+1);
        tvb_memcpy(tvb, (guint8 *) aliasname, offset, block_length);
        aliasname[block_length] = '\0';
        proto_tree_add_string (tree, hf_pn_dcp_suboption_device_aliasname, tvb, offset, block_length, aliasname);
        pn_append_info(pinfo, dcp_item, wmem_strdup_printf(wmem_packet_scope(), ", AliasName:\"%s\"", aliasname));
        proto_item_append_text(block_item, "Device/AliasName");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info) {
            proto_item_append_text(block_item, ", BlockInfo: %s",
                                   val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        }
        proto_item_append_text(block_item, ", \"%s\"", aliasname);
        offset += block_length;
        break;
    case PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE:
        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_high, &device_instance_high);
        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_low, &device_instance_low);
        pn_append_info(pinfo, dcp_item, ", Dev-Instance");
        proto_item_append_text(block_item, "Device/Device Instance");
        if (have_block_qualifier) {
            proto_item_append_text(block_item, ", BlockQualifier: %s",
                                   val_to_str(block_qualifier, pn_dcp_block_qualifier, "Unknown"));
        }
        if (have_block_info) {
            proto_item_append_text(block_item, ", BlockInfo: %s",
                                   val_to_str(block_info, pn_dcp_block_info, "Unknown"));
        }
        proto_item_append_text(block_item, ", InstanceHigh: %d, Instance Low: %d",
                               device_instance_high, device_instance_low);
        break;
    default:
        offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length);
    }

    return offset;
}
static int
get_form_key_value(tvbuff_t *tvb, char **ptr, int offset, char stop)
{
	const int orig_offset = offset;
	char *tmp;
	int len;

	len = 0;
	while (tvb_reported_length_remaining(tvb, offset) > 0) {
		guint8 ch;

		ch = tvb_get_guint8(tvb, offset);
		if (!ch)
			return -1;
		if (ch == stop)
			break;
		if (ch == '%') {
			offset++;
			ch = tvb_get_guint8(tvb, offset);
			if (ws_xton(ch) == -1)
				return -1;

			offset++;
			ch = tvb_get_guint8(tvb, offset);
			if (ws_xton(ch) == -1)
				return -1;
		}

		len++;
		offset++;
	}

	*ptr = tmp = (char*)wmem_alloc(wmem_packet_scope(), len + 1);
	tmp[len] = '\0';

	len = 0;
	offset = orig_offset;
	while (tvb_reported_length_remaining(tvb, offset) > 0) {
		guint8 ch;

		ch = tvb_get_guint8(tvb, offset);
		if (!ch)
			return -1;
		if (ch == stop)
			break;

		if (ch == '%') {
			guint8 ch1, ch2;

			offset++;
			ch1 = tvb_get_guint8(tvb, offset);

			offset++;
			ch2 = tvb_get_guint8(tvb, offset);

			tmp[len] = ws_xton(ch1) << 4 | ws_xton(ch2);

		} else if (ch == '+')
			tmp[len] = ' ';
		else
			tmp[len] = ch;

		len++;
		offset++;
	}

	return offset;
}
static cattp_pck*
parse_cattp_packet(tvbuff_t *tvb)
{
    cattp_pck* ret;
    ret = wmem_alloc(wmem_packet_scope(),sizeof(cattp_pck));

    /* Check if the standard header fits in. */
    gulong len;
    len = tvb_captured_length(tvb);
    if (len < CATTP_HBLEN) {
        /* this is not a valid CATTP packet */
        return NULL;
    }

    /* Parse the header. */
    int offset;
    offset = 0;
    guint8 fb;
    fb = tvb_get_guint8(tvb,offset);
    offset++;

    ret->flags = fb & 0xFC; /* mask the flags only */

    ret->syn = (fb & F_SYN) > 0;
    ret->ack = (fb & F_ACK) > 0;
    ret->eak = (fb & F_EAK) > 0;
    ret->rst = (fb & F_RST) > 0;
    ret->nul = (fb & F_NUL) > 0;
    ret->seg = (fb & F_SEG) > 0;

    ret->version = fb & M_VERSION; /* mask the version only */

    ret->rfu = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->hlen = tvb_get_guint8(tvb,offset);
    offset++;
    ret->srcport = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->dstport = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->dlen = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->seqno = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->ackno = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->wsize = tvb_get_ntohs(tvb,offset);
    offset+=2;
    ret->chksum = tvb_get_ntohs(tvb,offset);
    offset+=2;

    /* Verify the header: */
    if ((ret->hlen + ret->dlen) != len) {
        /* Invalid header/data len -> abort */
        return NULL;
    }

    /* Parse SYN (only syn flag set) */
    if ((ret->flags & M_PDU_SYN) == F_SYN) {
        ret->pdu.syn.maxpdu = tvb_get_ntohs(tvb,offset);
        offset+=2;
        ret->pdu.syn.maxsdu = tvb_get_ntohs(tvb,offset);
        offset+=2;

        int idlen;
        idlen = ret->pdu.syn.idlen = tvb_get_guint8(tvb,offset);
        offset++;

        if (idlen != ret->hlen - offset) {
            return NULL;
        }

        guint8* id;
        id = wmem_alloc(wmem_packet_scope(),sizeof(guint8) * idlen + 1);

        int i;
        for (i = 0; i <idlen; i++) {
            id[i] = tvb_get_guint8(tvb,offset);
            offset++;
        }
        id[idlen] = 0;
        ret->pdu.syn.id = id;
        return ret;
    }

    /* Parse ACK PDU */
    if ((ret->flags & M_PDU_ACK) == F_ACK) {
        if (ret->flags & F_EAK) {
            int eak_len;
            eak_len = ret->pdu.ack.eak_len = (len-CATTP_HBLEN) >> 1;
            ret->pdu.ack.eaks = wmem_alloc(wmem_packet_scope(),sizeof(guint8) * eak_len +1);

            int i;
            for (i = 0; i < eak_len; i++) {
                ret->pdu.ack.eaks[i] = tvb_get_ntohs(tvb,offset);
                offset+=2;
            }
            ret->pdu.ack.eaks[eak_len] = 0;
        } else {