2 * Routines for China Mobile Point to Point dissection
3 * Copyright 2007, Andy Chu <chu.dev@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include "packet-tcp.h"
17 #define CMPP_FIX_HEADER_LENGTH 12
18 #define CMPP_DELIVER_REPORT_LEN 71
20 /* These are not registered with IANA */
21 #define CMPP_PORT_RANGE "7890,7900,7930,9168"
23 void proto_register_cmpp(void);
24 void proto_reg_handoff_cmpp(void);
26 static dissector_handle_t cmpp_handle
;
28 /* Initialize the protocol and registered fields */
29 static int proto_cmpp
;
31 /* These are the fix header field */
32 static int hf_cmpp_Total_Length
;
33 static int hf_cmpp_Command_Id
;
34 static int hf_cmpp_Sequence_Id
;
37 static int hf_cmpp_connect_Source_Addr
;
38 static int hf_cmpp_connect_AuthenticatorSource
;
39 static int hf_cmpp_Version
;
40 static int hf_cmpp_connect_Timestamp
;
42 /* CMPP_CONNECT_RESP */
43 static int hf_cmpp_connect_resp_status
;
44 static int hf_cmpp_connect_resp_AuthenticatorISMG
;
47 static int hf_cmpp_submit_pk_total
;
48 static int hf_cmpp_submit_pk_number
;
49 static int hf_cmpp_submit_Msg_level
;
50 static int hf_cmpp_submit_Fee_UserType
;
51 static int hf_cmpp_submit_Fee_terminal_Id
;
52 static int hf_cmpp_submit_Fee_terminal_type
;
53 static int hf_cmpp_submit_Msg_src
;
54 static int hf_cmpp_submit_FeeType
;
55 static int hf_cmpp_submit_FeeCode
;
56 static int hf_cmpp_submit_Valld_Time
;
57 static int hf_cmpp_submit_At_Time
;
58 static int hf_cmpp_submit_Src_Id
;
59 static int hf_cmpp_submit_DestUsr_tl
;
60 static int hf_cmpp_submit_Dest_terminal_type
;
61 static int hf_cmpp_submit_Registered_Delivery
;
63 /* Field common in CMPP_SUBMIT and CMPP_DELIVER */
64 static int hf_cmpp_Dest_terminal_Id
;
65 static int hf_cmpp_Service_Id
;
66 static int hf_cmpp_TP_pId
;
67 static int hf_cmpp_TP_udhi
;
68 static int hf_cmpp_Msg_Fmt
;
69 static int hf_cmpp_Msg_Length
;
70 static int hf_cmpp_Msg_Content
;
71 static int hf_cmpp_LinkID
;
73 /* CMPP_SUBMIT_RESP */
74 static int hf_cmpp_submit_resp_Result
;
78 /* TODO implement CMPP_QUERY and CMPP_QUERY_RESP */
81 static int hf_cmpp_deliver_Dest_Id
;
82 static int hf_cmpp_deliver_Src_terminal_Id
;
83 static int hf_cmpp_deliver_Src_terminal_type
;
84 static int hf_cmpp_deliver_Registered_Delivery
;
86 static int hf_cmpp_deliver_resp_Result
;
88 /* CMPP Deliver Report */
89 static int hf_cmpp_deliver_Report
;
90 static int hf_cmpp_deliver_Report_Stat
;
91 static int hf_cmpp_deliver_Report_Submit_time
;
92 static int hf_cmpp_deliver_Report_Done_time
;
93 static int hf_cmpp_deliver_Report_SMSC_sequence
;
96 static int hf_cmpp_msg_id
;
97 static int hf_msg_id_timestamp
;
98 static int hf_msg_id_ismg_code
;
99 static int hf_msg_id_sequence_id
;
101 static bool cmpp_desegment
= true;
104 * Value-arrays for field-contents
106 #define CMPP_CONNECT 0x00000001
107 #define CMPP_CONNECT_RESP 0x80000001
108 #define CMPP_TERMINATE 0x00000002
109 #define CMPP_TERMINATE_RESP 0x80000002
110 #define CMPP_SUBMIT 0x00000004
111 #define CMPP_SUBMIT_RESP 0x80000004
112 #define CMPP_DELIVER 0x00000005
113 #define CMPP_DELIVER_RESP 0x80000005
114 #define CMPP_QUERY 0x00000006
115 #define CMPP_QUERY_RESP 0x80000006
116 #define CMPP_CANCEL 0x00000007
117 #define CMPP_CANCEL_RESP 0x80000007
118 #define CMPP_ACTIVE_TEST 0x00000008
119 #define CMPP_ACTIVE_TEST_RESP 0x80000008
120 #define CMPP_FWD 0x00000009
121 #define CMPP_FWD_RESP 0x80000009
122 #define CMPP_MT_ROUTE 0x00000010
123 #define CMPP_MO_ROUTE 0x00000011
124 #define CMPP_GET_MT_ROUTE 0x00000012
125 #define CMPP_MT_ROUTE_UPDATE 0x00000013
126 #define CMPP_MO_ROUTE_UPDATE 0x00000014
127 #define CMPP_PUSH_MT_ROUTE_UPDATE 0x00000015
128 #define CMPP_PUSH_MO_ROUTE_UPDATE 0x00000016
129 #define CMPP_GET_MO_ROUTE 0x00000017
130 #define CMPP_MT_ROUTE_RESP 0x80000010
131 #define CMPP_MO_ROUTE_RESP 0x80000011
132 #define CMPP_GET_MT_ROUTE_RESP 0x80000012
133 #define CMPP_MT_ROUTE_UPDATE_RESP 0x80000013
134 #define CMPP_MO_ROUTE_UPDATE_RESP 0x80000014
135 #define CMPP_PUSH_MT_ROUTE_UPDATE_RESP 0x80000015
136 #define CMPP_PUSH_MO_ROUTE_UPDATE_RESP 0x80000016
137 #define CMPP_GET_MO_ROUTE_RESP 0x80000017
139 static const value_string vals_command_Id
[] = { /* Operation */
140 { CMPP_CONNECT
, "CMPP_CONNECT" },
141 { CMPP_CONNECT_RESP
, "CMPP_CONNECT_RESP" },
142 { CMPP_TERMINATE
, "CMPP_TERMINATE" },
143 { CMPP_TERMINATE_RESP
, "CMPP_TERMINATE_RESP" },
144 { CMPP_SUBMIT
, "CMPP_SUBMIT" },
145 { CMPP_SUBMIT_RESP
, "CMPP_SUBMIT_RESP" },
146 { CMPP_DELIVER
, "CMPP_DELIVER" },
147 { CMPP_DELIVER_RESP
, "CMPP_DELIVER_RESP" },
148 { CMPP_QUERY
, "CMPP_QUERY" },
149 { CMPP_QUERY_RESP
, "CMPP_QUERY" },
150 { CMPP_CANCEL
, "CMPP_CANCEL" },
151 { CMPP_CANCEL_RESP
, "CMPP_CANCEL_RESP" },
152 { CMPP_ACTIVE_TEST
, "CMPP_ACTIVE_TEST" },
153 { CMPP_ACTIVE_TEST_RESP
, "CMPP_ACTIVE_TEST_RESP" },
154 { CMPP_FWD
, "CMPP_FWD" },
155 { CMPP_FWD_RESP
, "CMPP_FWD_RESP" },
156 { CMPP_MT_ROUTE
, "CMPP_MT_ROUTE" },
157 { CMPP_MO_ROUTE
, "CMPP_MO_ROUTE" },
158 { CMPP_GET_MT_ROUTE
, "CMPP_GET_MT_ROUTE" },
159 { CMPP_MT_ROUTE_UPDATE
, "CMPP_MT_ROUTE_UPDATE" },
160 { CMPP_MO_ROUTE_UPDATE
, "CMPP_MO_ROUTE_UPDATE" },
161 { CMPP_PUSH_MT_ROUTE_UPDATE
, "CMPP_PUSH_MT_ROUTE_UPDATE" },
162 { CMPP_PUSH_MO_ROUTE_UPDATE
, "CMPP_PUSH_MO_ROUTE_UPDATE" },
163 { CMPP_GET_MO_ROUTE
, "CMPP_GET_MO_ROUTE" },
164 { CMPP_MT_ROUTE_RESP
, "CMPP_MT_ROUTE_RESP" },
165 { CMPP_MO_ROUTE_RESP
, "CMPP_MO_ROUTE_RESP" },
166 { CMPP_GET_MT_ROUTE_RESP
, "CMPP_GET_MT_ROUTE_RESP" },
167 { CMPP_MT_ROUTE_UPDATE_RESP
, "CMPP_MT_ROUTE_UPDATE_RESP" },
168 { CMPP_MO_ROUTE_UPDATE_RESP
, "CMPP_MO_ROUTE_UPDATE_RESP" },
169 { CMPP_PUSH_MT_ROUTE_UPDATE_RESP
, "CMPP_PUSH_MT_ROUTE_UPDATE_RESP" },
170 { CMPP_PUSH_MO_ROUTE_UPDATE_RESP
, "CMPP_PUSH_MO_ROUTE_UPDATE_RESP" },
171 { CMPP_GET_MO_ROUTE_RESP
, "CMPP_GET_MO_ROUTE_RESP" },
175 static const value_string vals_connect_resp_status
[] = { /* Connection Status */
177 { 1, "Message structure error" },
178 { 2, "Illegal source address" },
179 { 3, "Authenticate error" },
180 { 4, "Version too high" },
184 static const value_string vals_submit_Fee_UserType
[] = { /* Submit Fee_UserType */
185 { 0, "Charging destination MSISDN" },
186 { 1, "Charging source MSISDN" },
187 { 2, "Charging SP" },
188 { 3, "Unuse, Charge info from Fee_terminal_Id" },
192 static const value_string vals_Msg_Fmt
[] = { /* Message Format */
194 { 3, "Short message card" }, /* TODO find the correct string of this value */
195 { 4, "Binary data" },
196 { 8, "UCS2 encoding" },
197 {15, "GB encoding" },
201 /* Submit Response Result */
202 static const value_string vals_Submit_Resp_Result
[] = {
204 { 1, "Message format error" },
205 { 2, "Command error" },
206 { 3, "Repeat sequence id" },
207 { 4, "Incorrect message length" },
208 { 5, "Incorrect fee code" },
209 { 6, "Message too long" },
210 { 7, "Incorrect service id" },
211 { 8, "Bandwidth error" },
212 { 9, "Gateway does not service this charging number" },
213 {10, "Incorrect Src_Id" },
214 {11, "Incorrect Msg_src" },
215 {12, "Incorrect Fee_terminal_Id" },
216 {13, "Incorrect Dest_terminal_Id" },
220 /* Deliver Response Result */
221 static const value_string vals_Deliver_Resp_Result
[] = {
223 { 1, "Message format error" },
224 { 2, "Command error" },
225 { 3, "Repeat sequence id" },
226 { 4, "Incorrect message length" },
227 { 5, "Incorrect fee code" },
228 { 6, "Message too long" },
229 { 7, "Incorrect service id" },
230 { 8, "Bandwidth error" },
234 /* Initialize the subtree pointers */
236 static int ett_msg_id
;
237 static int ett_deliver_report
;
239 /* Helper functions */
241 static const uint8_t*
242 cmpp_octet_string(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
, int length
)
244 const uint8_t *display
;
246 proto_tree_add_item_ret_string(tree
, field
, tvb
, offset
, length
, ENC_ASCII
, wmem_packet_scope(), &display
);
251 cmpp_version(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
253 int8_t version
, major
, minor
;
256 version
= tvb_get_uint8(tvb
, offset
);
257 minor
= version
& 0x0F;
258 major
= (version
& 0xF0) >> 4;
259 strval
= wmem_strdup_printf(wmem_packet_scope(), "%02u.%02u", major
, minor
);
260 /* TODO: the version should be added as a uint_format */
261 proto_tree_add_string(tree
, field
, tvb
, offset
, 1, strval
);
266 cmpp_timestamp(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
268 int8_t month
, day
, hour
, minute
, second
;
272 timevalue
= tvb_get_ntohl(tvb
, offset
);
273 second
= timevalue
% 100;
275 minute
= timevalue
% 100;
277 hour
= timevalue
% 100;
279 day
= timevalue
% 100;
280 month
= timevalue
/ 100;
281 strval
= wmem_strdup_printf(wmem_packet_scope(), "%02u/%02u %02u:%02u:%02u", month
, day
,
282 hour
, minute
, second
);
283 proto_tree_add_string(tree
, field
, tvb
, offset
, 4, strval
);
287 /* TODO: most calls to these (except those that use the return value) should
288 * be replaced by calls to proto_tree_add_item().
291 cmpp_uint1(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
294 value
= tvb_get_uint8(tvb
, offset
);
295 proto_tree_add_uint(tree
, field
, tvb
, offset
, 1, value
);
300 cmpp_uint2(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
303 value
= tvb_get_ntohs(tvb
, offset
);
304 proto_tree_add_uint(tree
, field
, tvb
, offset
, 2, value
);
309 cmpp_uint4(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
312 value
= tvb_get_ntohl(tvb
, offset
);
313 proto_tree_add_uint(tree
, field
, tvb
, offset
, 4, value
);
318 cmpp_boolean(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
321 value
= tvb_get_uint8(tvb
, offset
);
322 proto_tree_add_boolean(tree
, field
, tvb
, offset
, 1, value
);
329 cmpp_msg_id(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, int offset
)
331 uint8_t month
,day
,hour
,minute
,second
;
334 proto_tree
*sub_tree
;
337 pi
= proto_tree_add_item(tree
, field
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
338 sub_tree
= proto_item_add_subtree(pi
, ett_msg_id
);
340 month
= (tvb_get_uint8(tvb
, offset
) & 0xF0) >> 4;
341 day
= (tvb_get_ntohs(tvb
, offset
) & 0x0F80) >> 7;
342 hour
= (tvb_get_uint8(tvb
, offset
+ 1) & 0x7C) >> 2;
343 minute
= (tvb_get_ntohs(tvb
, offset
+ 1) & 0x03F0) >> 4;
344 second
= (tvb_get_ntohs(tvb
, offset
+ 2) & 0x0FC0) >> 6;
345 strval
= wmem_strdup_printf(wmem_packet_scope(), "%02u/%02u %02u:%02u:%02u", month
, day
,
346 hour
, minute
, second
);
348 ismg_code
= (tvb_get_ntohl(tvb
, offset
+ 3) & 0x3FFFFF00) >> 16;
350 proto_tree_add_string(sub_tree
, hf_msg_id_timestamp
, tvb
, offset
, 4, strval
);
351 proto_tree_add_uint(sub_tree
, hf_msg_id_ismg_code
, tvb
, offset
+ 3, 3, ismg_code
);
352 cmpp_uint2(sub_tree
, tvb
, hf_msg_id_sequence_id
, offset
+ 6);
356 cmpp_connect(proto_tree
*tree
, tvbuff_t
*tvb
)
359 offset
= CMPP_FIX_HEADER_LENGTH
;
360 cmpp_octet_string(tree
, tvb
, hf_cmpp_connect_Source_Addr
, offset
, 6);
362 proto_tree_add_string(tree
, hf_cmpp_connect_AuthenticatorSource
, tvb
, offset
, 16, "MD5 Hash");
364 cmpp_version(tree
, tvb
, hf_cmpp_Version
, offset
);
366 cmpp_timestamp(tree
, tvb
, hf_cmpp_connect_Timestamp
, offset
);
371 cmpp_connect_resp(proto_tree
*tree
, tvbuff_t
*tvb
)
374 offset
= CMPP_FIX_HEADER_LENGTH
;
375 cmpp_uint4(tree
, tvb
, hf_cmpp_connect_resp_status
, offset
);
377 proto_tree_add_string(tree
, hf_cmpp_connect_resp_AuthenticatorISMG
, tvb
, offset
, 16, "MD5 Hash");
379 cmpp_version(tree
, tvb
, hf_cmpp_Version
, offset
);
383 cmpp_submit(proto_tree
*tree
, tvbuff_t
*tvb
)
386 uint8_t destUsr
, msgLen
;
387 offset
= CMPP_FIX_HEADER_LENGTH
;
388 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
390 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_pk_total
, offset
);
392 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_pk_number
, offset
);
394 cmpp_boolean(tree
, tvb
, hf_cmpp_submit_Registered_Delivery
, offset
);
396 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_Msg_level
, offset
);
398 cmpp_octet_string(tree
, tvb
, hf_cmpp_Service_Id
, offset
, 10);
400 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_Fee_UserType
, offset
);
402 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Fee_terminal_Id
, offset
, 32);
404 cmpp_boolean(tree
, tvb
, hf_cmpp_submit_Fee_terminal_type
, offset
);
406 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_pId
, offset
);
408 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_udhi
, offset
);
410 cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Fmt
, offset
);
412 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Msg_src
, offset
, 6);
414 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_FeeType
, offset
, 2);
416 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_FeeCode
, offset
, 6);
419 /* TODO create function to handle SMPP time format */
420 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Valld_Time
, offset
, 17);
422 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_At_Time
, offset
, 17);
425 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Src_Id
, offset
, 17);
427 destUsr
= cmpp_uint1(tree
, tvb
, hf_cmpp_submit_DestUsr_tl
, offset
);
430 /* Loop through each destination address */
431 for(i
= 0; i
< destUsr
; i
++)
433 cmpp_octet_string(tree
, tvb
, hf_cmpp_Dest_terminal_Id
, offset
, 32);
437 cmpp_boolean(tree
, tvb
, hf_cmpp_submit_Dest_terminal_type
, offset
);
439 msgLen
= cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Length
, offset
);
441 proto_tree_add_string(tree
, hf_cmpp_Msg_Content
, tvb
, offset
, msgLen
, "SMS Messages");
443 cmpp_octet_string(tree
, tvb
, hf_cmpp_LinkID
, offset
, 20);
447 cmpp_submit_resp(proto_tree
*tree
, tvbuff_t
*tvb
)
450 offset
= CMPP_FIX_HEADER_LENGTH
;
451 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
453 cmpp_uint4(tree
, tvb
, hf_cmpp_submit_resp_Result
, offset
);
457 cmpp_deliver_report(proto_tree
*tree
, tvbuff_t
*tvb
, int field
, unsigned offset
)
460 proto_tree
*sub_tree
;
462 pi
= proto_tree_add_item(tree
, field
, tvb
, offset
, CMPP_DELIVER_REPORT_LEN
, ENC_BIG_ENDIAN
);
463 sub_tree
= proto_item_add_subtree(pi
, ett_deliver_report
);
464 cmpp_msg_id(sub_tree
, tvb
, hf_cmpp_msg_id
, offset
);
466 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_deliver_Report_Stat
, offset
, 7);
468 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_deliver_Report_Submit_time
, offset
, 10);
470 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_deliver_Report_Done_time
, offset
, 10);
472 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_Dest_terminal_Id
, offset
, 32);
474 cmpp_uint4(sub_tree
, tvb
, hf_cmpp_deliver_Report_SMSC_sequence
, offset
);
478 cmpp_deliver(proto_tree
*tree
, tvbuff_t
*tvb
)
480 unsigned offset
, msgLen
;
482 offset
= CMPP_FIX_HEADER_LENGTH
;
483 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
485 cmpp_octet_string(tree
, tvb
, hf_cmpp_deliver_Dest_Id
, offset
, 21);
487 cmpp_octet_string(tree
, tvb
, hf_cmpp_Service_Id
, offset
, 10);
489 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_pId
, offset
);
491 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_udhi
, offset
);
493 cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Fmt
, offset
);
495 cmpp_octet_string(tree
, tvb
, hf_cmpp_deliver_Src_terminal_Id
, offset
, 32);
497 cmpp_boolean(tree
, tvb
, hf_cmpp_deliver_Src_terminal_type
, offset
);
499 report
= cmpp_boolean(tree
, tvb
, hf_cmpp_deliver_Registered_Delivery
, offset
);
501 msgLen
= cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Length
, offset
);
504 proto_tree_add_string(tree
, hf_cmpp_Msg_Content
, tvb
, offset
, msgLen
, "SMS Messages");
506 cmpp_deliver_report(tree
, tvb
, hf_cmpp_deliver_Report
, offset
);
508 cmpp_octet_string(tree
, tvb
, hf_cmpp_LinkID
, offset
, 20);
512 cmpp_deliver_resp(proto_tree
*tree
, tvbuff_t
*tvb
)
515 offset
= CMPP_FIX_HEADER_LENGTH
;
516 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
518 /* TODO implement the result field here */
519 cmpp_uint4(tree
, tvb
, hf_cmpp_deliver_resp_Result
, offset
);
522 /* Code to actually dissect the packets */
524 dissect_cmpp_tcp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
527 /* Set up structures needed to add the protocol subtree and manage it */
529 proto_tree
*cmpp_tree
;
532 unsigned total_length
;
533 const char *command_str
; /* Header command string */
535 /* Get the length of the PDU */
536 tvb_len
= tvb_captured_length(tvb
);
537 /* if the length of the tvb is shorder then the cmpp header length exit */
538 if (tvb_len
< CMPP_FIX_HEADER_LENGTH
)
541 total_length
= tvb_get_ntohl(tvb
, 0); /* Get the pdu length */
542 command_id
= tvb_get_ntohl(tvb
, 4); /* get the pdu command id */
544 if (try_val_to_str(command_id
, vals_command_Id
) == NULL
)
546 /* Should never happen: we checked this in dissect_cmpp() */
550 command_str
= val_to_str(command_id
, vals_command_Id
,
551 "(Unknown CMPP Operation 0x%08X)");
553 /* tvb has less data then the PDU Header status, return */
554 if (tvb_len
< total_length
)
556 /* Should never happen: TCP should have desegmented for us */
560 /* Make entries in Protocol column and Info column on summary display */
561 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "CMPP");
563 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s. ", command_str
);
567 ti
= proto_tree_add_item(tree
, proto_cmpp
, tvb
, 0, -1, ENC_NA
);
569 cmpp_tree
= proto_item_add_subtree(ti
, ett_cmpp
);
571 /* Add the fix header informations to the tree */
572 cmpp_uint4(cmpp_tree
, tvb
, hf_cmpp_Total_Length
, 0);
573 cmpp_uint4(cmpp_tree
, tvb
, hf_cmpp_Command_Id
, 4);
574 cmpp_uint4(cmpp_tree
, tvb
, hf_cmpp_Sequence_Id
, 8);
579 cmpp_connect(cmpp_tree
, tvb
);
581 case CMPP_CONNECT_RESP
:
582 cmpp_connect_resp(cmpp_tree
, tvb
);
584 /* CMPP_TERMINATE and CMPP_TERMINATE_RESP don't have msg body */
586 case CMPP_TERMINATE_RESP
:
589 cmpp_submit(cmpp_tree
, tvb
);
591 case CMPP_SUBMIT_RESP
:
592 cmpp_submit_resp(cmpp_tree
, tvb
);
595 cmpp_deliver(cmpp_tree
, tvb
);
597 case CMPP_DELIVER_RESP
:
598 cmpp_deliver_resp(cmpp_tree
, tvb
);
601 /* Implement the rest of the protocol here */
606 return tvb_reported_length(tvb
);
610 /* Get the CMPP PDU Length */
612 get_cmpp_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
614 return tvb_get_ntohl(tvb
, offset
);
619 dissect_cmpp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
621 unsigned total_length
, command_id
, tvb_len
;
622 /* Check that there's enough data */
623 tvb_len
= tvb_captured_length(tvb
);
624 if (tvb_len
< CMPP_FIX_HEADER_LENGTH
)
627 /* Get some values from the packet header, probably using tvb_get_*() */
628 total_length
= tvb_get_ntohl(tvb
, 0); /* Get the pdu length */
629 command_id
= tvb_get_ntohl(tvb
, 4); /* get the pdu command id */
631 /* Looking at this protocol, it seems unlikely that the messages would
632 * get as big as a couple hundred bytes but that's not certain; just
633 * added a hopefully-way-too-big number to strengthen the heuristics.
635 if (total_length
< CMPP_FIX_HEADER_LENGTH
|| total_length
> 1000)
638 if (try_val_to_str(command_id
, vals_command_Id
) == NULL
)
641 col_clear(pinfo
->cinfo
, COL_INFO
);
643 tcp_dissect_pdus(tvb
, pinfo
, tree
, cmpp_desegment
, CMPP_FIX_HEADER_LENGTH
,
644 get_cmpp_pdu_len
, dissect_cmpp_tcp_pdu
, data
);
646 /* Return the amount of data this dissector was able to dissect */
647 return tvb_reported_length(tvb
);
651 /* Register the protocol with Wireshark */
654 proto_register_cmpp(void) {
656 /* Setup list of header fields See Section 1.6.1 for details*/
657 static hf_register_info hf
[] = {
658 { &hf_cmpp_Total_Length
,
659 { "Total Length", "cmpp.Total_Length",
660 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
661 "Total length of the CMPP PDU.",
664 { &hf_cmpp_Command_Id
,
665 { "Command Id", "cmpp.Command_Id",
666 FT_UINT32
, BASE_HEX
, VALS(vals_command_Id
), 0x00,
667 "Command Id of the CMPP messages",
670 { &hf_cmpp_Sequence_Id
,
671 { "Sequence Id", "cmpp.Sequence_Id",
672 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
673 "Sequence Id of the CMPP messages",
676 { &hf_cmpp_connect_Source_Addr
,
677 { "Source Addr", "cmpp.connect.Source_Addr",
678 FT_STRING
, BASE_NONE
, NULL
, 0x00,
679 "Source Address, the SP_Id",
682 { &hf_cmpp_connect_AuthenticatorSource
,
683 { "Authenticator Source", "cmpp.connect.AuthenticatorSource",
684 FT_STRING
, BASE_NONE
, NULL
, 0x00,
685 "Authenticator source, MD5(Source_addr + 9 zero + shared secret + timestamp)",
690 { "Version", "cmpp.Version",
691 FT_STRING
, BASE_NONE
, NULL
, 0x00,
695 { &hf_cmpp_connect_Timestamp
,
696 { "Timestamp", "cmpp.connect.Timestamp",
697 FT_STRING
, BASE_NONE
, NULL
, 0x00,
698 "Timestamp MM/DD HH:MM:SS",
701 { &hf_cmpp_connect_resp_status
,
702 { "Connect Response Status", "cmpp.connect_resp.Status",
703 FT_UINT32
, BASE_DEC
, VALS(vals_connect_resp_status
), 0x00,
704 "Response Status, Value higher then 4 means other error",
707 { &hf_cmpp_connect_resp_AuthenticatorISMG
,
708 { "SIMG Authenticate result", "cmpp.connect_resp.AuthenticatorISMG",
709 FT_STRING
, BASE_NONE
, NULL
, 0x00,
710 "Authenticator result, MD5(Status + AuthenticatorSource + shared secret)",
714 { "Msg_Id", "cmpp.Msg_Id",
715 FT_UINT64
, BASE_HEX
, NULL
, 0x00,
719 { &hf_cmpp_submit_pk_total
,
720 { "Number of Part", "cmpp.submit.Pk_total",
721 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
722 "Total number of parts of the message with the same Msg_Id, start from 1",
725 { &hf_cmpp_submit_pk_number
,
726 { "Part Number", "cmpp.submit.Pk_number",
727 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
728 "Part number of the message with the same Msg_Id, start from 1",
731 { &hf_msg_id_timestamp
,
732 { "Timestamp", "cmpp.Msg_Id.timestamp",
733 FT_STRING
, BASE_NONE
, NULL
, 0x00,
734 "Timestamp MM/DD HH:MM:SS Bit 64 ~ 39",
737 { &hf_msg_id_ismg_code
,
738 { "ISMG Code", "cmpp.Msg_Id.ismg_code",
739 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
740 "ISMG Code, bit 38 ~ 17",
743 { &hf_msg_id_sequence_id
,
744 { "Msg_Id sequence Id", "cmpp.Msg_Id.sequence_id",
745 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
746 "Msg_Id sequence Id, bit 16 ~ 1",
749 { &hf_cmpp_submit_Registered_Delivery
,
750 { "Registered Delivery", "cmpp.submit.Registered_Delivery",
751 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
752 "Registered Delivery flag",
755 { &hf_cmpp_submit_Msg_level
,
756 { "Message Level", "cmpp.submit.Msg_level",
757 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
761 { &hf_cmpp_Service_Id
,
762 { "Service ID", "cmpp.Servicd_Id",
763 FT_STRING
, BASE_NONE
, NULL
, 0x00,
764 "Service ID, a mix of characters, numbers and symbol",
767 { &hf_cmpp_submit_Fee_UserType
,
768 { "Charging Informations", "cmpp.submit.Fee_UserType",
769 FT_UINT8
, BASE_DEC
, VALS(vals_submit_Fee_UserType
), 0x00,
770 "Charging Informations, if value is 3, this field will not be used",
773 { &hf_cmpp_submit_Fee_terminal_Id
,
774 { "Fee Terminal ID", "cmpp.submit.Fee_terminal_Id",
775 FT_STRING
, BASE_NONE
, NULL
, 0x00,
776 "Fee Terminal ID, Valid only when Fee_UserType is 3",
779 { &hf_cmpp_submit_Fee_terminal_type
,
780 { "Fake Fee Terminal", "cmpp.submit.Fee_terminal_type",
781 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
782 "Fee terminal type, 0 is real, 1 is fake",
786 { "TP pId", "cmpp.TP_pId",
787 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
792 { "TP udhi", "cmpp.TP_udhi",
793 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
798 { "Message Format", "cmpp.Msg_Fmt",
799 FT_UINT8
, BASE_DEC
, VALS(vals_Msg_Fmt
), 0x00,
803 { &hf_cmpp_submit_Msg_src
,
804 { "Message Source SP_Id", "cmpp.submit.Msg_src",
805 FT_STRING
, BASE_NONE
, NULL
, 0x00,
806 "Message source SP ID",
809 { &hf_cmpp_submit_FeeType
, /* TODO Replace this with a vals_string*/
810 { "Fee Type", "cmpp.submit.FeeType",
811 FT_STRING
, BASE_NONE
, NULL
, 0x00,
815 { &hf_cmpp_submit_FeeCode
,
816 { "Fee Code", "cmpp.submit.FeeCode",
817 FT_STRING
, BASE_NONE
, NULL
, 0x00,
821 { &hf_cmpp_submit_Valld_Time
,
822 { "Valid time", "cmpp.submit.Valld_Time",
823 FT_STRING
, BASE_NONE
, NULL
, 0x00,
824 "Message Valid Time, format follow SMPP 3.3",
827 { &hf_cmpp_submit_At_Time
,
828 { "Send time", "cmpp.submit.At_time",
829 FT_STRING
, BASE_NONE
, NULL
, 0x00,
830 "Message send time, format following SMPP 3.3",
833 { &hf_cmpp_submit_Src_Id
,
834 { "Source ID", "cmpp.submit.Src_Id",
835 FT_STRING
, BASE_NONE
, NULL
, 0x00,
836 "This value matches SMPP submit_sm source_addr field",
839 { &hf_cmpp_submit_DestUsr_tl
,
840 { "Destination Address Count", "cmpp.submit.DestUsr_tl",
841 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
842 "Number of destination address, must smaller then 100",
845 { &hf_cmpp_Dest_terminal_Id
,
846 { "Destination Address", "cmpp.Dest_terminal_Id",
847 FT_STRING
, BASE_NONE
, NULL
, 0x00,
848 "MSISDN number which receive the SMS",
851 { &hf_cmpp_submit_Dest_terminal_type
,
852 { "Fake Destination Terminal", "cmpp.submit.Dest_terminal_type",
853 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
854 "destination terminal type, 0 is real, 1 is fake",
857 { &hf_cmpp_Msg_Length
,
858 { "Message length", "cmpp.Msg_Length",
859 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
860 "SMS Message length, ASCII must be <= 160 bytes, other must be <= 140 bytes",
863 { &hf_cmpp_Msg_Content
,
864 { "Message Content", "cmpp.Msg_Content",
865 FT_STRING
, BASE_NONE
, NULL
, 0x00,
870 { "Link ID", "cmpp.LinkID",
871 FT_STRING
, BASE_NONE
, NULL
, 0x00,
875 { &hf_cmpp_submit_resp_Result
,
876 { "Result", "cmpp.submit_resp.Result",
877 FT_UINT32
, BASE_DEC
, VALS(vals_Submit_Resp_Result
), 0x00,
881 { &hf_cmpp_deliver_Dest_Id
,
882 { "Destination ID", "cmpp.deliver.Dest_Id",
883 FT_STRING
, BASE_NONE
, NULL
, 0x00,
884 "SP Service ID or server number",
887 { &hf_cmpp_deliver_Src_terminal_Id
,
888 { "Src_terminal_Id", "cmpp.deliver.Src_terminal_Id",
889 FT_STRING
, BASE_NONE
, NULL
, 0x00,
890 "Source MSISDN number, if it is deliver report, this will be the CMPP_SUBMIT destination number",
893 { &hf_cmpp_deliver_Src_terminal_type
,
894 { "Fake source terminal type", "cmpp.deliver.Src_terminal_type",
895 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
896 "Type of the source terminal, can be 0 (real) or 1 (fake)",
899 { &hf_cmpp_deliver_Registered_Delivery
,
900 { "Deliver Report", "cmpp.deliver.Registered_Delivery",
901 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
902 "The message is a deliver report if this value = 1",
905 { &hf_cmpp_deliver_Report
,
906 { "Detail Deliver Report", "cmpp.deliver.Report",
907 FT_NONE
, BASE_NONE
, NULL
, 0x00,
911 { &hf_cmpp_deliver_Report_Stat
,
912 { "Deliver Status", "cmpp.deliver.Report.Status",
913 FT_STRING
, BASE_NONE
, NULL
, 0x00,
917 { &hf_cmpp_deliver_Report_Submit_time
,
918 { "Submit_time", "cmpp.deliver.Report.Submit_time",
919 FT_STRING
, BASE_NONE
, NULL
, 0x00,
923 { &hf_cmpp_deliver_Report_Done_time
,
924 { "Done_time", "cmpp.deliver.Report.Done_time",
925 FT_STRING
, BASE_NONE
, NULL
, 0x00,
929 { &hf_cmpp_deliver_Report_SMSC_sequence
,
930 { "SMSC_sequence", "cmpp.Report.SMSC_sequence",
931 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
935 { &hf_cmpp_deliver_resp_Result
,
936 { "Result", "cmpp.deliver_resp.Result",
937 FT_UINT32
, BASE_DEC
, VALS(vals_Deliver_Resp_Result
), 0x00,
943 /* Setup protocol subtree array */
944 static int *ett
[] = {
950 /* Register the protocol name and description */
951 proto_cmpp
= proto_register_protocol("China Mobile Point to Point Protocol",
954 /* Required function calls to register the header fields and subtrees used */
955 proto_register_field_array(proto_cmpp
, hf
, array_length(hf
));
956 proto_register_subtree_array(ett
, array_length(ett
));
958 cmpp_handle
= register_dissector("cmpp", dissect_cmpp
, proto_cmpp
);
963 proto_reg_handoff_cmpp(void)
965 dissector_add_uint_range_with_preference("tcp.port", CMPP_PORT_RANGE
, cmpp_handle
);
969 * Editor modelines - https://www.wireshark.org/tools/modelines.html
974 * indent-tabs-mode: t
977 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
978 * :indentSize=8:tabSize=8:noTabs=false: