Wireshark cmpp30协议lua插件解析

本文有参考cmpp20协议lua插件,原文网址已遗失,抱歉!

-- CMPPv3.lua
-- author: admin

local p_CMPPv3 = Proto("CMPPv3", "China Mobile Peer to Peer Protocol v3.0")
--消息长度
local f_length = ProtoField.uint32("CMPPv3.length","MsgLength(消息长度)",base.DEC)
--命令或响应类型
local f_command_id = ProtoField.uint32("CMPPv3.commandId","CommandId(消息类型)",base.HEX,{
    [1] = "Connect",
    [2] = "Terminate",
    [4] = "Submit",
    [5] = "Deliver",
    [6] = "Query",
    [8] = "ActiveTest",
    [0x80000001] = "ConnectResp",
    [0x80000002] = "TerminateResp",
    [0x80000004] = "SubmitResp",
    [0x80000005] = "DeliverResp",
    [0x80000006] = "QueryResp",
    [0x80000008] = "ActiveTestResp"
})
--消息流水号
local f_sequence_id = ProtoField.uint32("CMPPv3.sequenceId","SequenceId(序列号)",base.DEC);

local f_msg_id_timestamp = ProtoField.string("CMPPv3.msgIdTimestamp","时间戳",base.NONE)
local f_msg_id_sgw_id = ProtoField.uint32("CMPPv3.msgIdSgwId","网关Id");
local f_msg_id_sequence = ProtoField.uint16("CMPPv3.msgIdSequence","序号");
local f_message_id = ProtoField.bytes("CMPPv3.messageId","MsgId(消息Id)")
local f_pk_total = ProtoField.uint8("CMPPv3.pkTotal","PkTotal(相同消息Id的信息总条数)")
local f_pk_number = ProtoField.uint8("CMPPv3.pkNumber","PkNumber(相同消息Id的信息序号)")
local yes_or_no = {
    [1] = "是",
    [0] = "否"
}
local f_registered_delivery = ProtoField.uint8("CMPPv3.registeredDelivery","RegisteredDelivery(是否返回状态报告)", base.DEC, yes_or_no)
local f_is_delivery_report = ProtoField.uint8("CMPPv3.isReport","RegisteredDelivery(是否状态报告)", base.DEC, yes_or_no)
local f_message_level = ProtoField.uint8("CMPPv3.messageLevel","MsgLevel(消息级别)")
local f_service_id = ProtoField.string("CMPPv3.serviceId","ServiceId(业务类型)",base.NONE)
local f_fee_user_type = ProtoField.uint8("CMPPv3.feeUserType","FeeUserType(计费类型)", base.DEC, {
    [0] = "对目的终端MSISDN计费",
    [1] = "对源终端MSISDN计费",
    [2] = "对SP计费",
    [3] = "本字段无效"
})
local f_fee_terminal_id = ProtoField.string("CMPPv3.feeTerminalId","FeeTerminalId(计费用户号码)",base.NONE)
local f_message_src = ProtoField.string("CMPPv3.messageSrc","MessageSrc(信息内容来源)",base.NONE)
local f_src_id = ProtoField.string("CMPPv3.srcId","SrcId(源号码)",base.NONE)
local f_SrcTerminalId = ProtoField.string("CMPPv3.srcTerminalId","SrcTerminalId(源终端号码)",base.NONE)
local f_reserved = ProtoField.bytes("CMPPv3.reserved","Reserve(保留域)")

local f_data = ProtoField.bytes("CMPPv3.data","Data(字节数据)")
local f_result = ProtoField.uint8("CMPPv3.result","Result(结果)",base.DEC,{
    [0] = "成功",
    [1] = "消息结构错",
    [2] = "命令字错",
    [3] = "消息序号重复",
    [4] = "消息长度错",
    [5] = "资费代码错",
    [6] = "超过最大信息长",
    [7] = "业务代码错",
    [8] = "流量控制错",
    [9] = "其他错误"
})
local f_dest_user_count = ProtoField.uint8("CMPPv3.destUserCount","DestUserCount(接收用户数)",base.DEC)
local f_dest_terminal_id = ProtoField.string("CMPPv3.destTerminalId","DestTerminalId(接收用户号码)",base.NONE)
local f_fee_type = ProtoField.uint16("CMPPv3.feeType","FeeType(计费类型)", base.HEX, {
    [0x03031] = "免费",
    [0x03032] = "按条计费",
    [0x03033] = "包月收费",
    [0x03034] = "封顶收费",
    [0x03035] = "SP收取"
})
--Fee_terminal_type 对于cmpp2.0新增部分
local f_fee_terminal_type = ProtoField.uint8("CMPPv3.feeTerminalType","FeeTerminalType(被计费用户的号码类型)", base.DEC, {
    [0] = "真实号码",
    [1] = "伪码"
})
--Dest_terminal_type 对于cmpp2.0新增部分
local f_dest_terminal_type = ProtoField.uint8("CMPPv3.destTerminalType","DestTerminalType(被计费用户的号码类型)", base.DEC, {
    [0] = "真实号码",
    [1] = "伪码"
})

local f_fee_value = ProtoField.string("CMPPv3.feeValue","FeeValue(资费)",base.NONE)
local f_valid_time = ProtoField.string("CMPPv3.validTime","ValidTime(有效期)",base.NONE)
local f_at_time = ProtoField.string("CMPPv3.atTime","AtTime(定时发送时间)",base.NONE)
local f_tp_pid = ProtoField.uint8("CMPPv3.tpPid","TpPid(TP协议标识符)")
local f_tp_udhi = ProtoField.uint8("CMPPv3.tpUdhi","TpUdhi(TP用户数据首部指示符)", base.DEC, {
    [0] = "用户数据只含短信内容",
    [1] = "用户数据含首部及短信内容"
})
local f_msg_fmt = ProtoField.uint8("CMPPv3.messageFormat","MsgFmt(内容编码)", base.DEC, {
    [0] = "ASCII",
    [3] = "短信写卡",
    [4] = "二进制",
    [8] = "UCS2",
    [15] = "GB18030"
})
local f_message_length = ProtoField.uint8("CMPPv3.messageLength","MessageLength(消息内容字节数)")
local f_msg_content = ProtoField.bytes("CMPPv3.msgContent","MsgContent(消息内容)")
local f_msg_content_decoded = ProtoField.string("CMPPv3.messageContentDecoded","MessageContentDecoded",base.NONE)
local f_dest_id = ProtoField.string("CMPPv3.destId","DestId(接收号码)",base.NONE)

-- 状态报告内容中的各字段
local f_content_msg_id = ProtoField.bytes("CMPPv3.contentMsgId","MsgId(消息Id)")
local f_content_stat = ProtoField.string("CMPPv3.contentStat","Stat(应答结果)",base.NONE)
local f_content_submit_time = ProtoField.string("CMPPv3.contentSubmitTime","SubmitTime(提交时间)",base.NONE)
local f_content_done_time = ProtoField.string("CMPPv3.contentDoneTime","DoneTime(完成时间)",base.NONE)
local f_content_dest_terminal_id = ProtoField.string("CMPPv3.contentDestTerminalId","DestTerminalId(目的终端号码)",base.NONE)
local f_content_sequence = ProtoField.uint32("CMPPv3.contentSequence","Sequence(序列号)")

local f_source_addr = ProtoField.string("CMPPv3.sourceAddr","SourceAddr(源地址)",base.NONE)
local f_authenticator_source = ProtoField.string("CMPPv3.authenticatorSource","AuthenticatorSource(源地址认证码)",base.NONE)
local f_version = ProtoField.uint8("CMPPv3.version","Version(版本号)",base.DEC,{[32] = "v2.0",[48] = "v3.0"})
local f_timestamp = ProtoField.uint32("CMPPv3.timestamp","Timestamp(时间戳)")
local f_status = ProtoField.uint8("CMPPv3.status","Status(状态)", base.DEC, {[0] = "成功",[1] = "消息结构错",[2] = "非法源地址",[3] = "认证错",[4] = "版本太高",[5] = "其他错误"})
local f_authenticator_ismg = ProtoField.string("CMPPv3.authenticatorIsmg","AuthenticatorIsmg(短信网关认证码)",base.NONE)
local f_msg_content_header = ProtoField.bytes("CMPPv3.messageContentHeader", "Header(首部)")

p_CMPPv3.fields = {
    f_length, f_command_id, f_sequence_id, f_data, f_result, f_dest_user_count, f_dest_terminal_id,
    f_fee_type, f_fee_value, f_valid_time, f_at_time, f_tp_pid, f_tp_udhi, f_msg_fmt, f_message_length, f_msg_content,
    f_message_id, f_pk_total, f_pk_number, f_registered_delivery, f_message_level, f_service_id, f_fee_user_type,
    f_fee_terminal_id, f_message_src, f_src_id, f_reserved, f_msg_id_timestamp, f_msg_id_sgw_id, f_msg_id_sequence,
    f_SrcTerminalId, f_dest_id, f_content_msg_id, f_content_stat, f_content_submit_time, f_content_done_time,
    f_content_dest_terminal_id, f_content_sequence, f_is_delivery_report, f_msg_content_header,f_source_addr,f_authenticator_source,
    f_version,f_timestamp,f_status,f_authenticator_ismg,f_fee_terminal_type,f_dest_terminal_type
}

-- 处理MessageId:除MessageId本身外,还解析其中包含的时间戳、网关Id和序列号
local function process_message_id(field, buffer, t)
    local node = t:add(field, buffer)
    node:add(f_msg_id_timestamp, tostring(buffer:bitfield(0, 4)) .. "/" .. tostring(buffer:bitfield(4, 5)) .. " " .. tostring(buffer:bitfield(9, 5)) .. ":" .. tostring(buffer:bitfield(14, 6)) .. ":" .. tostring(buffer:bitfield(20, 6)))
    node:add(f_msg_id_sgw_id, buffer:bitfield(26, 22))
    node:add(f_msg_id_sequence, buffer:bitfield(48, 16))
end

-- 解码短信内容:根据编码方式解码短信内容
local function decode_content(buf, length, format)
    if (format == 8) then
        return buf(0, length):ustring();
    elseif (format == 0) then
        return buf(0, length):string();
    elseif(format == 15) then
        return buf(0, length):stringz();
    else
        return "API无法解码该编码的内容"
    end
end

-- 处理短信内容:根据长短信标识及编码方式处理短信内容
local function process_content(buf, pos, length, udhi, encoding, t)
    local node = t:add(f_msg_content, buf(pos, length))
    local head_length
    if (udhi == 1) then
        head_length = buf(pos, 1):uint() + 1
        node:add(f_msg_content_header, buf(pos, head_length))
    else
        head_length = 0
    end
    node:add(f_msg_content_decoded, "Decoded(解码后内容): " .. decode_content(buf(pos + head_length), length - head_length, encoding))
end

-- 解析connect
local function parse_connect(buf, t)
    t:add(f_source_addr, buf(12, 6))
    t:add(f_authenticator_source, buf(18, 16))
    t:add(f_version, buf(34, 1))
    t:add(f_timestamp, buf(35, 4))
end

-- 解析connect_resp
local function parse_connect_resp(buf, t)
    t:add(f_status, buf(12, 4))
    t:add(f_authenticator_ismg, buf(16, 16))
    t:add(f_version, buf(32, 1))
end

-- 解析submit
local function parse_submit(buf, t)
    process_message_id(f_message_id, buf(12, 8), t)
    t:add(f_pk_total, buf(20, 1))
    t:add(f_pk_number, buf(21, 1))
    t:add(f_registered_delivery, buf(22, 1))
    t:add(f_message_level, buf(23, 1))
    t:add(f_service_id, buf(24, 10))
    t:add(f_fee_user_type, buf(34, 1))
    t:add(f_fee_terminal_id, buf(35, 32))
    t:add(f_fee_terminal_type, buf(67, 1))
    t:add(f_tp_pid, buf(68, 1))
    t:add(f_tp_udhi, buf(69, 1))
    t:add(f_msg_fmt, buf(70, 1))
    t:add(f_message_src, buf(71, 6))
    t:add(f_fee_type, buf(77, 2))
    t:add(f_fee_value, buf(79, 6))
    t:add(f_valid_time, buf(85, 17))
    t:add(f_at_time, buf(102, 17))
    t:add(f_src_id, buf(119, 21))
    t:add(f_dest_user_count, buf(140, 1))

    local user_num = buf(140, 1):uint();
    local pos = 141
    for i = 1, user_num do
        t:add(f_dest_terminal_id, buf(pos, 32))
        pos = pos + 32
    end
    t:add(f_dest_terminal_type, buf(pos, 1))
    pos = pos + 1
    t:add(f_message_length, buf(pos, 1))
    local length = buf(pos, 1):uint()
    process_content(buf, pos + 1, length, buf(69, 1):uint(), buf(70, 1):uint(), t)
    t:add(f_reserved, buf(pos + 1 + length, 20))
end

-- 解析deliver
local function parse_deliver(buf, t)
    -- 处理MessageId
    process_message_id(f_message_id, buf(12, 8), t)
    t:add(f_dest_id, buf(20, 21))
    t:add(f_service_id, buf(41, 10))
    t:add(f_tp_pid, buf(51, 1))
    t:add(f_tp_udhi, buf(52, 1))
    t:add(f_msg_fmt, buf(53, 1))
    t:add(f_SrcTerminalId, buf(54, 32))
    t:add(f_is_delivery_report, buf(86, 1))
    t:add(f_dest_terminal_type, buf(87, 1))
    t:add(f_message_length, buf(88, 1))
    local length = buf(88, 1):uint()

    if (length > 0) then
        if (buf(86, 1):uint() == 1) then
            local content = t:add(f_msg_content, buf(89, length))
            process_message_id(f_content_msg_id, buf(89, 8), content)
            content:add(f_content_stat, buf(97, 7))
            content:add(f_content_submit_time, buf(104, 10))
            content:add(f_content_done_time, buf(114, 10))
            content:add(f_content_dest_terminal_id, buf(124, 32))
            content:add(f_content_sequence, buf(156, 4))
        else
            process_content(buf, 89, length, buf(52, 1):uint(), buf(53, 1):uint(), t);
        end
    end
    t:add(f_reserved, buf(89 + length, 20))
end

-- 解析响应
local function parse_response(buf, t)
    process_message_id(f_message_id, buf(12, 8), t)
    t:add(f_result, buf(20, 1))
end

local function CMPPv3_dissector(buf,pkt,root)
    local buf_len = buf:len();
    local count = 0;
    while(buf_len > 8)do
        if buf_len < 8 then return false end
    pkt.cols.protocol = "CMPPv3"
    local v_length = buf(0,4)
    local len = v_length:uint()
    local t = root:add(p_CMPPv3, buf(0, len))
    t:add(f_length, v_length)
    t:add(f_command_id, buf(4,4))
    t:add(f_sequence_id, buf(8,4))

    local v_command = buf(4,4):uint()
    if v_command == 1 then
        parse_connect(buf, t)
    elseif v_command == 4 then
        parse_submit(buf, t)
    elseif v_command == 5 then
        parse_deliver(buf, t)
    elseif v_command == 0x80000004 or v_command == 0x80000005 then
        parse_response(buf, t)
    elseif v_command == 0x80000001 then
        parse_connect_resp(buf, t)
    else
        if (buf_len > 12) then
            t:add(f_data, buf(12, len))
        end
    end
      count = count+1;
      if(count > 10)then
        break
      end
      if buf_len > len then
        buf = buf(len,buf_len-len)
        buf_len = buf:len();
      else
        break;
      end
  end
  return true
end

function p_CMPPv3.dissector(buf,pkt,root)
    -- 解析 CMPPv3
    if not CMPPv3_dissector(buf,pkt,root) then
        -- 使用默认输出
        Dissector.get("data"):call(buf, pkt, root)
    end
end

DissectorTable.get("tcp.port"):add(7890, p_CMPPv3)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值