You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C++中编写Wireshark解析器插件:packed BCD编码解析疑问

更优雅的Packed BCD解析方案(Wireshark C++插件)

嘿,你这个问题我之前做类似插件时也碰到过——Wireshark确实没内置Packed BCD的直接支持,但你的临时方案虽然能显示,最大的问题是没法利用Wireshark的过滤、统计这些核心功能,毕竟proto_item_set_text只是改了显示文本,底层字段值还是原始字节,用户没法用protocol.foo == 123456789012这类规则过滤。

给你两个更优的方案,完全适配Wireshark的工作流:

方案1:转换为数值类型(推荐,支持数值过滤)

如果你的Packed BCD是用来存储十进制整数(比如12位ID、金额),直接把它转换成uint64_t(12位十进制最大是999999999999,远小于uint64_t的上限),然后用标准的数值字段添加方法:

步骤1:定义字段为数值类型

在field_array里把字段注册成FT_UINT64(如果是有符号数就用FT_INT64):

static hf_register_info field_array[] = {
    { &fields.foo, { "Foo Field", "protocol.foo", FT_UINT64, BASE_DEC, NULL, 0x0, "12-digit Packed BCD value", HFILL } },
    // 其他字段...
};

步骤2:编写Packed BCD转数值的工具函数

uint64_t packed_bcd_to_uint64(tvbuff_t *tvb, gint offset, gint length) {
    uint64_t result = 0;
    for (gint i = 0; i < length; i++) {
        guint8 byte = tvb_get_guint8(tvb, offset + i);
        // 每个字节的高4位是十位,低4位是个位
        result = result * 100 + ((byte >> 4) & 0x0F) * 10 + (byte & 0x0F);
    }
    return result;
}

步骤3:在解析器中使用

替换原来的proto_tree_add_item,改用数值添加方法:

uint64_t foo_value = packed_bcd_to_uint64(tvb, offset, 6); // 6字节对应12位十进制
proto_tree_add_uint64(body, fields.foo, tvb, offset, 6, foo_value);

这样一来,Wireshark不仅会显示转换后的十进制数值,还支持数值过滤、排序、统计,完全和原生字段一样。

方案2:转换为字符串类型(适合带格式的场景)

如果你的Packed BCD需要显示为带前导零的字符串(比如固定12位的编号),可以转换成ASCII字符串,注册为FT_STRING类型:

步骤1:定义字段为字符串类型

static hf_register_info field_array[] = {
    { &fields.foo, { "Foo Field", "protocol.foo", FT_STRING, BASE_NONE, NULL, 0x0, "12-digit Packed BCD string", HFILL } },
    // 其他字段...
};

步骤2:编写Packed BCD转字符串的工具函数

gchar* packed_bcd_to_string(tvbuff_t *tvb, gint offset, gint length) {
    gchar* str = (gchar*)g_malloc0(length * 2 + 1); // 每个字节对应2个字符
    for (gint i = 0; i < length; i++) {
        guint8 byte = tvb_get_guint8(tvb, offset + i);
        str[i*2] = '0' + ((byte >> 4) & 0x0F);
        str[i*2+1] = '0' + (byte & 0x0F);
    }
    return str;
}

步骤3:在解析器中使用

gchar* foo_str = packed_bcd_to_string(tvb, offset, 6);
proto_tree_add_string(body, fields.foo, tvb, offset, 6, foo_str);
g_free(foo_str); // 记得释放内存!

这个方案适合需要精确字符串匹配过滤的场景,比如protocol.foo contains "1234"。

额外优化:同时显示原始字节和转换后的值

如果想让用户同时看到转换后的值和原始Packed BCD字节,可以用proto_item_append_text补充显示:

proto_item* foo_item = proto_tree_add_uint64(body, fields.foo, tvb, offset, 6, foo_value);
proto_item_append_text(foo_item, " (raw: %s)", tvb_bytes_to_str_punct(tvb, offset, 6, ':'));

这样详情面板里会显示类似123456789012 (raw: 12:34:56:78:90:12)的内容,方便调试。

内容的提问来源于stack exchange,提问作者Anton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:08:56