Exemplo n.º 1
0
static void
dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint       op;
    guint       sub;
    guint       rlen;
    proto_item *ti;
    proto_item *item;
    proto_tree *fip_tree;
    proto_tree *subtree;
    guint       dtype;
    guint       dlen;
    guint       desc_offset;
    guint       val;
    tvbuff_t   *desc_tvb;
    const char *info;

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

    if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) {
        col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]");
        if (tree)
            proto_tree_add_protocol_format(tree, proto_fip, tvb, 0,
                                            -1, "FIP [packet too short]");
        return;
    }

    op  = tvb_get_ntohs(tvb, 2);
    sub = tvb_get_guint8(tvb, 5);

    switch (op) {
    case FIP_OP_DISC:
        info = val_to_str(sub, fip_disc_subcodes, "Discovery 0x%x");
        break;
    case FIP_OP_LS:
        info = val_to_str(sub, fip_ls_subcodes, "Link Service 0x%x");
        break;
    case FIP_OP_CTRL:
        info = val_to_str(sub, fip_ctrl_subcodes, "Control 0x%x");
        break;
    case FIP_OP_VLAN:
        info = val_to_str(sub, fip_vlan_subcodes, "VLAN 0x%x");
        break;
    case FIP_OP_VN2VN:
        info = val_to_str(sub, fip_vn2vn_subcodes, "VN2VN 0x%x");
        break;
    default:
        info = val_to_str(op, fip_opcodes, "Unknown op 0x%x");
        break;
    }

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

    rlen = tvb_get_ntohs(tvb, 6);

    ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0,
                                        FIP_HEADER_LEN + rlen * FIP_BPW,
                                        "FIP %s", info);
    fip_tree = proto_item_add_subtree(ti, ett_fip);
    proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(fip_tree, hf_fip_reserved12, tvb, 0, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(fip_tree, hf_fip_reserved8, tvb, 4, 1, ENC_NA);
    switch (op) {
    case FIP_OP_DISC:
        proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_LS:
        proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_CTRL:
        proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_VLAN:
        proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_VN2VN:
        proto_tree_add_item(fip_tree, hf_fip_vn2vn_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    default:
        proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    }
    proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, ENC_BIG_ENDIAN);

    proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags,
            ett_fip_flags, hf_fip_flags_fields, ENC_BIG_ENDIAN);

    desc_offset = FIP_HEADER_LEN;
    rlen *= FIP_BPW;
    proto_tree_add_bytes_format(fip_tree, hf_fip_descriptors, tvb, desc_offset, rlen, NULL, "Descriptors");

    while ((rlen > 0) && tvb_bytes_exist(tvb, desc_offset, 2)) {
        dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW;
        if (!dlen) {
            proto_tree_add_expert(fip_tree, pinfo, &ei_fip_descriptors, tvb, desc_offset, -1);
            break;
        }
        if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) {
            break;
        }
        desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1);
        dtype = tvb_get_guint8(desc_tvb, 0);
        desc_offset += dlen;
        rlen -= dlen;

        switch (dtype) {
        case FIP_DT_PRI:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_pri, &item);
            proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb,
                    3, 1, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3));
            break;
        case FIP_DT_MAC:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mac, &item);
            proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_item_append_text(item, "%s",
                    tvb_bytes_to_str_punct(wmem_packet_scope(), desc_tvb, 2, 6, ':'));
            break;
        case FIP_DT_MAP_OUI:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_map, &item);
            proto_tree_add_item(subtree, hf_fip_desc_map, desc_tvb,
                    5, 3, ENC_NA);
            proto_item_append_text(item, "%s", tvb_fc_to_str(desc_tvb, 5));
            break;
        case FIP_DT_NAME:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_name, &item);
            proto_tree_add_item(subtree, hf_fip_desc_name, desc_tvb, 4, 8, ENC_NA);
            proto_item_append_text(item, "%s", tvb_fcwwn_to_str(desc_tvb, 4));
            break;
        case FIP_DT_FAB:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fab, &item);
            proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_tree_add_item(subtree, hf_fip_desc_fab_map, desc_tvb,
                    5, 3, ENC_NA);
            proto_tree_add_item(subtree, hf_fip_desc_fab_name, desc_tvb, 8, 8, ENC_NA);
            proto_item_append_text(item, "%s", tvb_fcwwn_to_str(desc_tvb, 8));
            break;
        case FIP_DT_FCOE_SIZE:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mdl, &item);
            proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FLOGI:
        case FIP_DT_FDISC:
        case FIP_DT_LOGO:
        case FIP_DT_ELP: {
            tvbuff_t *ls_tvb;
            fc_data_t fc_data = {ETHERTYPE_FIP, 0};

            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_caps, &item);
            ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1);
            call_dissector_with_data(fc_handle, ls_tvb, pinfo, subtree, &fc_data);
            proto_item_append_text(item, "%u bytes", dlen - 4);
        }
            break;
        case FIP_DT_VN:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vn, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb,
                    9, 3, ENC_BIG_ENDIAN);
            proto_tree_add_item(subtree, hf_fip_desc_vn_wwpn,
                    desc_tvb, 12, 8, ENC_NA);
            proto_item_append_text(item, "MAC %s  FC_ID %6.6x",
                    tvb_bytes_to_str_punct(wmem_packet_scope(), desc_tvb, 2, 6, ':'),
                    tvb_get_ntoh24(desc_tvb, 9));
            break;
        case FIP_DT_FKA:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fka, &item);
            val = tvb_get_ntohl(desc_tvb, 4);
            proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka,
                    desc_tvb, 4, 4, val, "%u ms", val);
            proto_item_append_text(item, "%u ms", val);
            break;
        case FIP_DT_VEND:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vend, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb,
                    4, 8, ENC_NA);
            if (tvb_bytes_exist(desc_tvb, 9, -1)) {
                proto_tree_add_item(subtree, hf_fip_desc_vend_data,
                     desc_tvb, 9, -1, ENC_NA);
            }
            break;
        case FIP_DT_VLAN:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vlan, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FC4F:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fc4f, &item);
            fip_desc_fc4f(desc_tvb, subtree, item);
            break;
        default:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_unk, &item);
            proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb,
                    2, -1, ENC_NA);
            break;
        }
    }
}
Exemplo n.º 2
0
static void
dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint op;
    guint sub;
    guint rlen;
    guint flags;
    proto_item *ti;
    proto_item *item;
    proto_tree *fip_tree;
    proto_tree *subtree;
    guint dtype;
    guint dlen;
    guint desc_offset;
    guint val;
    tvbuff_t *desc_tvb;
    tvbuff_t *ls_tvb = NULL;
    const char *info;
    char *text;

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

    if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) {
        col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]");
        if (tree)
            proto_tree_add_protocol_format(tree, proto_fip, tvb, 0,
                                           -1, "FIP [packet too short]");
        return;
    }

    op = tvb_get_ntohs(tvb, 2);
    sub = tvb_get_guint8(tvb, 5);

    switch (op) {
    case FIP_OP_DISC:
        info = val_to_str(sub, fip_disc_subcodes, "Discovery 0x%x");
        break;
    case FIP_OP_LS:
        info = val_to_str(sub, fip_ls_subcodes, "Link Service 0x%x");
        break;
    case FIP_OP_CTRL:
        info = val_to_str(sub, fip_ctrl_subcodes, "Control 0x%x");
        break;
    case FIP_OP_VLAN:
        info = val_to_str(sub, fip_vlan_subcodes, "VLAN 0x%x");
        break;
    default:
        info = val_to_str(op, fip_opcodes, "Unknown op 0x%x");
        break;
    }

    if (check_col(pinfo->cinfo, COL_INFO))
        col_set_str(pinfo->cinfo, COL_INFO, info);

    rlen = tvb_get_ntohs(tvb, 6);
    flags = tvb_get_ntohs(tvb, 8);

    ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0,
                                        FIP_HEADER_LEN + rlen * FIP_BPW,
                                        "FIP %s", info);
    fip_tree = proto_item_add_subtree(ti, ett_fip);
    proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, FALSE);
    proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, FALSE);
    switch (op) {
    case FIP_OP_DISC:
        proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, FALSE);
        break;
    case FIP_OP_LS:
        proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, FALSE);
        break;
    case FIP_OP_CTRL:
        proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, FALSE);
        break;
    case FIP_OP_VLAN:
        proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, FALSE);
        break;
    default:
        proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, FALSE);
        break;
    }
    proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, FALSE);

    proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags,
                           ett_fip_flags, hf_fip_flags_fields, FALSE);

    desc_offset = FIP_HEADER_LEN;
    rlen *= FIP_BPW;
    proto_tree_add_text(fip_tree, tvb, desc_offset, rlen, "Descriptors:");

    while (rlen > 0 && tvb_bytes_exist(tvb, desc_offset, 2)) {
        dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW;
        if (!dlen) {
            proto_tree_add_text(fip_tree, tvb, desc_offset, -1,
                                "Descriptor [length error]");
            break;
        }
        if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) {
            break;
        }
        desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1);
        dtype = tvb_get_guint8(desc_tvb, 0);
        desc_offset += dlen;
        rlen -= dlen;

        item = proto_tree_add_text(fip_tree, desc_tvb, 0, -1, "Descriptor: %s ",
                                   val_to_str(dtype, fip_desc_types, "Unknown 0x%x"));

        switch (dtype) {
        case FIP_DT_PRI:
            subtree = proto_item_add_subtree(item, ett_fip_dt_pri);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb,
                                3, 1, FALSE);
            proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3));
            break;
        case FIP_DT_MAC:
            subtree = proto_item_add_subtree(item, ett_fip_dt_mac);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb,
                                2, 6, FALSE);
            proto_item_append_text(item, "%s",
                                   tvb_bytes_to_str_punct(desc_tvb, 2, 6, ':'));
            break;
        case FIP_DT_MAP_OUI:
            subtree = proto_item_add_subtree(item, ett_fip_dt_map);
            fip_desc_type_len(subtree, desc_tvb);
            text = fc_to_str(tvb_get_ptr(desc_tvb, 5, 3));
            proto_tree_add_string(subtree, hf_fip_desc_map, desc_tvb,
                                  5, 3, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_NAME:
            subtree = proto_item_add_subtree(item, ett_fip_dt_name);
            fip_desc_type_len(subtree, desc_tvb);
            text = fcwwn_to_str(tvb_get_ptr(desc_tvb, 4, 8));
            proto_tree_add_string(subtree, hf_fip_desc_name,
                                  desc_tvb, 4, 8, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_FAB:
            subtree = proto_item_add_subtree(item, ett_fip_dt_fab);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb,
                                2, 2, FALSE);
            text = fc_to_str(tvb_get_ptr(desc_tvb, 5, 3));
            proto_tree_add_string(subtree, hf_fip_desc_fab_map, desc_tvb,
                                  5, 3, text);
            text = fcwwn_to_str(tvb_get_ptr(desc_tvb, 8, 8));
            proto_tree_add_string(subtree, hf_fip_desc_fab_name,
                                  desc_tvb, 8, 8, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_FCOE_SIZE:
            subtree = proto_item_add_subtree(item, ett_fip_dt_mdl);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb,
                                2, 2, FALSE);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FLOGI:
        case FIP_DT_FDISC:
        case FIP_DT_LOGO:
        case FIP_DT_ELP:
            subtree = proto_item_add_subtree(item, ett_fip_dt_caps);
            fip_desc_type_len(subtree, desc_tvb);
            ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1);
            call_dissector(fc_handle, ls_tvb, pinfo, subtree);
            proto_item_append_text(item, "%u bytes", dlen - 4);
            break;
        case FIP_DT_VN:
            subtree = proto_item_add_subtree(item, ett_fip_dt_vn);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb,
                                2, 6, FALSE);
            proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb,
                                9, 3, FALSE);
            text = fcwwn_to_str(tvb_get_ptr(desc_tvb, 12, 8));
            proto_tree_add_string(subtree, hf_fip_desc_vn_wwpn,
                                  desc_tvb, 12, 8, text);
            proto_item_append_text(item, "MAC %s  FC_ID %6.6x",
                                   tvb_bytes_to_str_punct(desc_tvb, 2, 6, ':'),
                                   tvb_get_ntoh24(desc_tvb, 9));
            break;
        case FIP_DT_FKA:
            subtree = proto_item_add_subtree(item, ett_fip_dt_fka);
            fip_desc_type_len(subtree, desc_tvb);
            val = tvb_get_ntohl(desc_tvb, 4);
            proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka,
                                             desc_tvb, 4, 4, val, "%u ms", val);
            proto_item_append_text(item, "%u ms", val);
            break;
        case FIP_DT_VEND:
            subtree = proto_item_add_subtree(item, ett_fip_dt_vend);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb,
                                4, 8, FALSE);
            if (tvb_bytes_exist(desc_tvb, 9, -1)) {
                proto_tree_add_item(subtree, hf_fip_desc_vend_data,
                                    desc_tvb, 9, -1, FALSE);
            }
            break;
        case FIP_DT_VLAN:
            subtree = proto_item_add_subtree(item, ett_fip_dt_vlan);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb,
                                2, 2, FALSE);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        default:
            subtree = proto_item_add_subtree(item, ett_fip_dt_unk);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb,
                                2, -1, FALSE);
            break;
        }
    }
}