本文有参考cmpp20协议lua插件,原文网址已遗失,抱歉!
-- CMPPv3.lua
-- author: adminlocal 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))
endlocal 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
endfunction p_CMPPv3.dissector(buf,pkt,root)
-- 解析 CMPPv3
if not CMPPv3_dissector(buf,pkt,root) then
-- 使用默认输出
Dissector.get("data"):call(buf, pkt, root)
end
endDissectorTable.get("tcp.port"):add(7890, p_CMPPv3)