2 * Routines for China Mobile Point to Point dissection
3 * Copyright 2007, Andy Chu <chu.dev@gmail.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34 #include <epan/packet.h>
35 #include <epan/dissectors/packet-tcp.h>
37 #define CMPP_VERSIONBUF 6
38 #define CMPP_TIMESTAMPBUFF 15
39 #define CMPP_FIX_HEADER_LENGTH 12
40 #define CMPP_DELIVER_REPORT_LEN 71
42 /* These are not registered with IANA */
43 #define CMPP_SP_LONG_PORT 7890
44 #define CMPP_SP_SHORT_PORT 7900
45 #define CMPP_ISMG_LONG_PORT 7930
46 #define CMPP_ISMG_SHORT_PORT 9168
48 /* Initialize the protocol and registered fields */
49 static gint proto_cmpp = -1;
51 /* These are the fix header field */
52 static gint hf_cmpp_Total_Length = -1;
53 static gint hf_cmpp_Command_Id = -1;
54 static gint hf_cmpp_Sequence_Id = -1;
57 static gint hf_cmpp_connect_Source_Addr = -1;
58 static gint hf_cmpp_connect_AuthenticatorSource = -1;
59 static gint hf_cmpp_Version = -1;
60 static gint hf_cmpp_connect_Timestamp = -1;
62 /* CMPP_CONNECT_RESP */
63 static gint hf_cmpp_connect_resp_status = -1;
64 static gint hf_cmpp_connect_resp_AuthenticatorISMG = -1;
67 static gint hf_cmpp_submit_pk_total = -1;
68 static gint hf_cmpp_submit_pk_number = -1;
69 static gint hf_cmpp_submit_Msg_level = -1;
70 static gint hf_cmpp_submit_Fee_UserType = -1;
71 static gint hf_cmpp_submit_Fee_terminal_Id = -1;
72 static gint hf_cmpp_submit_Fee_terminal_type = -1;
73 static gint hf_cmpp_submit_Msg_src = -1;
74 static gint hf_cmpp_submit_FeeType = -1;
75 static gint hf_cmpp_submit_FeeCode = -1;
76 static gint hf_cmpp_submit_Valld_Time = -1;
77 static gint hf_cmpp_submit_At_Time = -1;
78 static gint hf_cmpp_submit_Src_Id = -1;
79 static gint hf_cmpp_submit_DestUsr_tl = -1;
80 static gint hf_cmpp_submit_Dest_terminal_type = -1;
81 static gint hf_cmpp_submit_Registered_Delivery = -1;
83 /* Field common in CMPP_SUBMIT and CMPP_DELIVER */
84 static gint hf_cmpp_Dest_terminal_Id = -1;
85 static gint hf_cmpp_Service_Id = -1;
86 static gint hf_cmpp_TP_pId = -1;
87 static gint hf_cmpp_TP_udhi = -1;
88 static gint hf_cmpp_Msg_Fmt = -1;
89 static gint hf_cmpp_Msg_Length = -1;
90 static gint hf_cmpp_Msg_Content = -1;
91 static gint hf_cmpp_LinkID = -1;
93 /* CMPP_SUBMIT_RESP */
94 static gint hf_cmpp_submit_resp_Result = -1;
98 /* TODO implement CMPP_QUERY and CMPP_QUERY_RESP */
101 static gint hf_cmpp_deliver_Dest_Id = -1;
102 static gint hf_cmpp_deliver_Src_terminal_Id = -1;
103 static gint hf_cmpp_deliver_Src_terminal_type = -1;
104 static gint hf_cmpp_deliver_Registered_Delivery = -1;
106 static gint hf_cmpp_deliver_resp_Result = -1;
108 /* CMPP Deliver Report */
109 static gint hf_cmpp_deliver_Report = -1;
110 static gint hf_cmpp_deliver_Report_Stat = -1;
111 static gint hf_cmpp_deliver_Report_Submit_time = -1;
112 static gint hf_cmpp_deliver_Report_Done_time = -1;
113 static gint hf_cmpp_deliver_Report_SMSC_sequence = -1;
116 static gint hf_cmpp_msg_id = -1;
117 static gint hf_msg_id_timestamp = -1;
118 static gint hf_msg_id_ismg_code = -1;
119 static gint hf_msg_id_sequence_id = -1;
121 static gboolean cmpp_desegment = TRUE;
124 * Value-arrays for field-contents
126 #define CMPP_CONNECT 0x00000001
127 #define CMPP_CONNECT_RESP 0x80000001
128 #define CMPP_TERMINATE 0x00000002
129 #define CMPP_TERMINATE_RESP 0x80000002
130 #define CMPP_SUBMIT 0x00000004
131 #define CMPP_SUBMIT_RESP 0x80000004
132 #define CMPP_DELIVER 0x00000005
133 #define CMPP_DELIVER_RESP 0x80000005
134 #define CMPP_QUERY 0x00000006
135 #define CMPP_QUERY_RESP 0x80000006
136 #define CMPP_CANCEL 0x00000007
137 #define CMPP_CANCEL_RESP 0x80000007
138 #define CMPP_ACTIVE_TEST 0x00000008
139 #define CMPP_ACTIVE_TEST_RESP 0x80000008
140 #define CMPP_FWD 0x00000009
141 #define CMPP_FWD_RESP 0x80000009
142 #define CMPP_MT_ROUTE 0x00000010
143 #define CMPP_MO_ROUTE 0x00000011
144 #define CMPP_GET_MT_ROUTE 0x00000012
145 #define CMPP_MT_ROUTE_UPDATE 0x00000013
146 #define CMPP_MO_ROUTE_UPDATE 0x00000014
147 #define CMPP_PUSH_MT_ROUTE_UPDATE 0x00000015
148 #define CMPP_PUSH_MO_ROUTE_UPDATE 0x00000016
149 #define CMPP_GET_MO_ROUTE 0x00000017
150 #define CMPP_MT_ROUTE_RESP 0x80000010
151 #define CMPP_MO_ROUTE_RESP 0x80000011
152 #define CMPP_GET_MT_ROUTE_RESP 0x80000012
153 #define CMPP_MT_ROUTE_UPDATE_RESP 0x80000013
154 #define CMPP_MO_ROUTE_UPDATE_RESP 0x80000014
155 #define CMPP_PUSH_MT_ROUTE_UPDATE_RESP 0x80000015
156 #define CMPP_PUSH_MO_ROUTE_UPDATE_RESP 0x80000016
157 #define CMPP_GET_MO_ROUTE_RESP 0x80000017
158 static const value_string vals_command_Id[] = { /* Operation */
159 { CMPP_CONNECT, "CMPP_CONNECT" },
160 { CMPP_CONNECT_RESP, "CMPP_CONNECT_RESP" },
161 { CMPP_TERMINATE, "CMPP_TERMINATE" },
162 { CMPP_TERMINATE_RESP, "CMPP_TERMINATE_RESP" },
163 { CMPP_SUBMIT, "CMPP_SUBMIT" },
164 { CMPP_SUBMIT_RESP, "CMPP_SUBMIT_RESP" },
165 { CMPP_DELIVER, "CMPP_DELIVER" },
166 { CMPP_DELIVER_RESP, "CMPP_DELIVER_RESP" },
167 { CMPP_QUERY, "CMPP_QUERY" },
168 { CMPP_QUERY_RESP, "CMPP_QUERY" },
169 { CMPP_CANCEL, "CMPP_CANCEL" },
170 { CMPP_CANCEL_RESP, "CMPP_CANCEL_RESP" },
171 { CMPP_ACTIVE_TEST, "CMPP_ACTIVE_TEST" },
172 { CMPP_ACTIVE_TEST_RESP, "CMPP_ACTIVE_TEST_RESP" },
173 { CMPP_FWD, "CMPP_FWD" },
174 { CMPP_FWD_RESP, "CMPP_FWD_RESP" },
175 { CMPP_MT_ROUTE, "CMPP_MT_ROUTE" },
176 { CMPP_MO_ROUTE, "CMPP_MO_ROUTE" },
177 { CMPP_GET_MT_ROUTE, "CMPP_GET_MT_ROUTE" },
178 { CMPP_MT_ROUTE_UPDATE, "CMPP_MT_ROUTE_UPDATE" },
179 { CMPP_MO_ROUTE_UPDATE, "CMPP_MO_ROUTE_UPDATE" },
180 { CMPP_PUSH_MT_ROUTE_UPDATE, "CMPP_PUSH_MT_ROUTE_UPDATE" },
181 { CMPP_PUSH_MO_ROUTE_UPDATE, "CMPP_PUSH_MO_ROUTE_UPDATE" },
182 { CMPP_GET_MO_ROUTE, "CMPP_GET_MO_ROUTE" },
183 { CMPP_MT_ROUTE_RESP, "CMPP_MT_ROUTE_RESP" },
184 { CMPP_MO_ROUTE_RESP, "CMPP_MO_ROUTE_RESP" },
185 { CMPP_GET_MT_ROUTE_RESP, "CMPP_GET_MT_ROUTE_RESP" },
186 { CMPP_MT_ROUTE_UPDATE_RESP, "CMPP_MT_ROUTE_UPDATE_RESP" },
187 { CMPP_MO_ROUTE_UPDATE_RESP, "CMPP_MO_ROUTE_UPDATE_RESP" },
188 { CMPP_PUSH_MT_ROUTE_UPDATE_RESP, "CMPP_PUSH_MT_ROUTE_UPDATE_RESP" },
189 { CMPP_PUSH_MO_ROUTE_UPDATE_RESP, "CMPP_PUSH_MO_ROUTE_UPDATE_RESP" },
190 { CMPP_GET_MO_ROUTE_RESP, "CMPP_GET_MO_ROUTE_RESP" },
194 static const value_string vals_connect_resp_status[] = { /* Connection Status */
196 { 1, "Message structure error" },
197 { 2, "Illegal source address" },
198 { 3, "Authenticate error" },
199 { 4, "Version too high" },
203 static const value_string vals_submit_Fee_UserType[] = { /* Submit Fee_UserType */
204 { 0, "Charging destination MSISDN" },
205 { 1, "Charging source MSISDN" },
206 { 2, "Charging SP" },
207 { 3, "Unuse, Charge info from Fee_terminal_Id" },
211 static const value_string vals_Msg_Fmt[] = { /* Message Format */
213 { 3, "Short message card" }, /* TODO find the correct string of this value */
214 { 4, "Binary data" },
215 { 8, "UCS2 encoding" },
216 {15, "GB encoding" },
220 /* Submit Response Result */
221 static const value_string vals_Submit_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" },
231 { 9, "Gateway does not service this charging number" },
232 {10, "Incorrect Src_Id" },
233 {11, "Incorrect Msg_src" },
234 {12, "Incorrect Fee_terminal_Id" },
235 {13, "Incorrect Dest_terminal_Id" },
239 /* Deliver Response Result */
240 static const value_string vals_Deliver_Resp_Result[] = {
242 { 1, "Message format error" },
243 { 2, "Command error" },
244 { 3, "Repeat sequence id" },
245 { 4, "Incorrect message length" },
246 { 5, "Incorrect fee code" },
247 { 6, "Message too long" },
248 { 7, "Incorrect service id" },
249 { 8, "Bandwidth error" },
253 /* Initialize the subtree pointers */
254 static gint ett_cmpp = -1;
255 static gint ett_msg_id = -1;
256 static gint ett_deliver_report = -1;
258 /* Helper functions */
261 cmpp_octet_string(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset, gint length)
265 display = (char *)tvb_get_ephemeral_string(tvb, offset, length);
266 proto_tree_add_string(tree, field, tvb, offset, length, display);
271 cmpp_version(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
273 gint8 version, major, minor;
276 version = tvb_get_guint8(tvb, offset);
277 minor = version & 0x0F;
278 major = (version & 0xF0) >> 4;
279 strval = ep_alloc(CMPP_VERSIONBUF);
280 g_snprintf(strval, CMPP_VERSIONBUF, "%02u.%02u", major, minor);
281 /* TODO: the version should be added as a uint_format */
282 proto_tree_add_string(tree, field, tvb, offset, 1, strval);
287 cmpp_timestamp(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
289 gint8 month, day, hour, minute, second;
293 timevalue = tvb_get_ntohl(tvb, offset);
294 second = timevalue % 100;
296 minute = timevalue % 100;
298 hour = timevalue % 100;
300 day = timevalue % 100;
301 month = timevalue / 100;
302 strval = ep_alloc(CMPP_TIMESTAMPBUFF);
303 g_snprintf(strval, CMPP_TIMESTAMPBUFF, "%02u/%02u %02u:%02u:%02u", month, day,
304 hour, minute, second);
305 proto_tree_add_string(tree, field, tvb, offset, 4, strval);
309 /* TODO: most calls to these (except those that use the return value) should
310 * be replaced by calls to proto_tree_add_item().
313 cmpp_uint1(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
316 value = tvb_get_guint8(tvb, offset);
317 proto_tree_add_uint(tree, field, tvb, offset, 1, value);
322 cmpp_uint2(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
325 value = tvb_get_ntohs(tvb, offset);
326 proto_tree_add_uint(tree, field, tvb, offset, 2, value);
331 cmpp_uint4(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
334 value = tvb_get_ntohl(tvb, offset);
335 proto_tree_add_uint(tree, field, tvb, offset, 4, value);
340 cmpp_boolean(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
343 value = tvb_get_guint8(tvb, offset);
344 proto_tree_add_boolean(tree, field, tvb, offset, 1, value);
351 cmpp_msg_id(proto_tree *tree, tvbuff_t *tvb, gint field, gint offset)
353 guint8 month,day,hour,minute,second;
355 proto_item *sub_tree;
358 sub_tree = proto_tree_add_item(tree, field, tvb, offset, 8, FALSE);
359 proto_item_add_subtree(sub_tree, ett_msg_id);
361 month = (tvb_get_guint8(tvb, offset) & 0xF0) >> 4;
362 day = (tvb_get_ntohs(tvb, offset) & 0x0F80) >> 7;
363 hour = (tvb_get_guint8(tvb, offset + 1) & 0x7C) >> 2;
364 minute = (tvb_get_ntohs(tvb, offset + 1) & 0x03F0) >> 4;
365 second = (tvb_get_ntohs(tvb, offset + 2) & 0x0FC0) >> 6;
366 strval = ep_alloc(CMPP_TIMESTAMPBUFF);
367 g_snprintf(strval, CMPP_TIMESTAMPBUFF, "%02u/%02u %02u:%02u:%02u", month, day,
368 hour, minute, second);
370 ismg_code = (tvb_get_ntohl(tvb, offset + 3) & 0x3FFFFF00) >> 16;
372 proto_tree_add_string(sub_tree, hf_msg_id_timestamp, tvb, offset, 4, strval);
373 proto_tree_add_uint(sub_tree, hf_msg_id_ismg_code, tvb, offset + 3, 3, ismg_code);
374 cmpp_uint2(sub_tree, tvb, hf_msg_id_sequence_id, offset + 6);
378 cmpp_connect(proto_tree *tree, tvbuff_t *tvb)
381 offset = CMPP_FIX_HEADER_LENGTH;
382 cmpp_octet_string(tree, tvb, hf_cmpp_connect_Source_Addr, offset, 6);
384 proto_tree_add_string(tree, hf_cmpp_connect_AuthenticatorSource, tvb, offset, 16, "MD5 Hash");
386 cmpp_version(tree, tvb, hf_cmpp_Version, offset);
388 cmpp_timestamp(tree, tvb, hf_cmpp_connect_Timestamp, offset);
393 cmpp_connect_resp(proto_tree *tree, tvbuff_t *tvb)
396 offset = CMPP_FIX_HEADER_LENGTH;
397 cmpp_uint4(tree, tvb, hf_cmpp_connect_resp_status, offset);
399 proto_tree_add_string(tree, hf_cmpp_connect_resp_AuthenticatorISMG, tvb, offset, 16, "MD5 Hash");
401 cmpp_version(tree, tvb, hf_cmpp_Version, offset);
405 cmpp_submit(proto_tree *tree, tvbuff_t *tvb)
408 guint8 msg_format, destUsr, msgLen;
409 offset = CMPP_FIX_HEADER_LENGTH;
410 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
412 cmpp_uint1(tree, tvb, hf_cmpp_submit_pk_total, offset);
414 cmpp_uint1(tree, tvb, hf_cmpp_submit_pk_number, offset);
416 cmpp_boolean(tree, tvb, hf_cmpp_submit_Registered_Delivery, offset);
418 cmpp_uint1(tree, tvb, hf_cmpp_submit_Msg_level, offset);
420 cmpp_octet_string(tree, tvb, hf_cmpp_Service_Id, offset, 10);
422 cmpp_uint1(tree, tvb, hf_cmpp_submit_Fee_UserType, offset);
424 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Fee_terminal_Id, offset, 32);
426 cmpp_boolean(tree, tvb, hf_cmpp_submit_Fee_terminal_type, offset);
428 cmpp_uint1(tree, tvb, hf_cmpp_TP_pId, offset);
430 cmpp_uint1(tree, tvb, hf_cmpp_TP_udhi, offset);
432 msg_format = cmpp_uint1(tree, tvb, hf_cmpp_Msg_Fmt, offset);
434 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Msg_src, offset, 6);
436 cmpp_octet_string(tree, tvb, hf_cmpp_submit_FeeType, offset, 2);
438 cmpp_octet_string(tree, tvb, hf_cmpp_submit_FeeCode, offset, 6);
441 /* TODO create function to handle SMPP time format */
442 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Valld_Time, offset, 17);
444 cmpp_octet_string(tree, tvb, hf_cmpp_submit_At_Time, offset, 17);
447 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Src_Id, offset, 17);
449 destUsr = cmpp_uint1(tree, tvb, hf_cmpp_submit_DestUsr_tl, offset);
452 /* Loop through each destination address */
453 for(i = 0; i < destUsr; i++)
455 cmpp_octet_string(tree, tvb, hf_cmpp_Dest_terminal_Id, offset, 32);
459 cmpp_boolean(tree, tvb, hf_cmpp_submit_Dest_terminal_type, offset);
461 msgLen = cmpp_uint1(tree, tvb, hf_cmpp_Msg_Length, offset);
463 proto_tree_add_string(tree, hf_cmpp_Msg_Content, tvb, offset, msgLen, "SMS Messages");
465 cmpp_octet_string(tree, tvb, hf_cmpp_LinkID, offset, 20);
469 cmpp_submit_resp(proto_tree *tree, tvbuff_t *tvb)
472 offset = CMPP_FIX_HEADER_LENGTH;
473 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
475 cmpp_uint4(tree, tvb, hf_cmpp_submit_resp_Result, offset);
479 cmpp_deliver_report(proto_tree *tree, tvbuff_t *tvb, gint field, guint offset)
481 proto_item *sub_tree;
482 sub_tree = proto_tree_add_item(tree, field, tvb, offset, CMPP_DELIVER_REPORT_LEN, FALSE);
483 proto_item_add_subtree(sub_tree, ett_deliver_report);
484 cmpp_msg_id(sub_tree, tvb, hf_cmpp_msg_id, offset);
486 cmpp_octet_string(sub_tree, tvb, hf_cmpp_deliver_Report_Stat, offset, 7);
488 cmpp_octet_string(sub_tree, tvb, hf_cmpp_deliver_Report_Submit_time, offset, 10);
490 cmpp_octet_string(sub_tree, tvb, hf_cmpp_deliver_Report_Done_time, offset, 10);
492 cmpp_octet_string(sub_tree, tvb, hf_cmpp_Dest_terminal_Id, offset, 32);
494 cmpp_uint4(sub_tree, tvb, hf_cmpp_deliver_Report_SMSC_sequence, offset);
498 cmpp_deliver(proto_tree *tree, tvbuff_t *tvb)
500 guint offset, msgLen;
502 offset = CMPP_FIX_HEADER_LENGTH;
503 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
505 cmpp_octet_string(tree, tvb, hf_cmpp_deliver_Dest_Id, offset, 21);
507 cmpp_octet_string(tree, tvb, hf_cmpp_Service_Id, offset, 10);
509 cmpp_uint1(tree, tvb, hf_cmpp_TP_pId, offset);
511 cmpp_uint1(tree, tvb, hf_cmpp_TP_udhi, offset);
513 cmpp_uint1(tree, tvb, hf_cmpp_Msg_Fmt, offset);
515 cmpp_octet_string(tree, tvb, hf_cmpp_deliver_Src_terminal_Id, offset, 32);
517 cmpp_boolean(tree, tvb, hf_cmpp_deliver_Src_terminal_type, offset);
519 report = cmpp_boolean(tree, tvb, hf_cmpp_deliver_Registered_Delivery, offset);
521 msgLen = cmpp_uint1(tree, tvb, hf_cmpp_Msg_Length, offset);
524 proto_tree_add_string(tree, hf_cmpp_Msg_Content, tvb, offset, msgLen, "SMS Messages");
526 cmpp_deliver_report(tree, tvb, hf_cmpp_deliver_Report, offset);
528 cmpp_octet_string(tree, tvb, hf_cmpp_LinkID, offset, 20);
532 cmpp_deliver_resp(proto_tree *tree, tvbuff_t *tvb)
535 offset = CMPP_FIX_HEADER_LENGTH;
536 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
538 /* TODO implement the result field here */
539 cmpp_uint4(tree, tvb, hf_cmpp_deliver_resp_Result, offset);
542 /* Code to actually dissect the packets */
544 dissect_cmpp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
547 /* Set up structures needed to add the protocol subtree and manage it */
549 proto_tree *cmpp_tree;
553 const gchar *command_str; /* Header command string */
555 /* Get the length of the PDU */
556 tvb_len = tvb_length(tvb);
557 /* if the length of the tvb is shorder then the cmpp header length exit */
558 if (tvb_len < CMPP_FIX_HEADER_LENGTH)
561 total_length = tvb_get_ntohl(tvb, 0); /* Get the pdu length */
562 command_id = tvb_get_ntohl(tvb, 4); /* get the pdu command id */
564 if (match_strval(command_id, vals_command_Id) == NULL)
566 /* Should never happen: we checked this in dissect_cmpp() */
570 command_str = val_to_str(command_id, vals_command_Id,
571 "(Unknown CMPP Operation 0x%08X)");
573 /* tvb has less data then the PDU Header status, return */
574 if (tvb_len < total_length)
576 /* Should never happen: TCP should have desegmented for us */
580 /* Make entries in Protocol column and Info column on summary display */
581 if (check_col(pinfo->cinfo, COL_PROTOCOL))
582 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMPP");
584 if (check_col(pinfo->cinfo, COL_INFO))
586 col_append_fstr(pinfo->cinfo, COL_INFO, "%s. ", command_str);
591 ti = proto_tree_add_item(tree, proto_cmpp, tvb, 0, -1, FALSE);
593 cmpp_tree = proto_item_add_subtree(ti, ett_cmpp);
595 /* Add the fix header informations to the tree */
596 cmpp_uint4(cmpp_tree, tvb, hf_cmpp_Total_Length, 0);
597 cmpp_uint4(cmpp_tree, tvb, hf_cmpp_Command_Id, 4);
598 cmpp_uint4(cmpp_tree, tvb, hf_cmpp_Sequence_Id, 8);
603 cmpp_connect(cmpp_tree, tvb);
605 case CMPP_CONNECT_RESP:
606 cmpp_connect_resp(cmpp_tree, tvb);
608 /* CMPP_TERMINATE and CMPP_TERMINATE_RESP don't have msg body */
610 case CMPP_TERMINATE_RESP:
613 cmpp_submit(cmpp_tree, tvb);
615 case CMPP_SUBMIT_RESP:
616 cmpp_submit_resp(cmpp_tree, tvb);
619 cmpp_deliver(cmpp_tree, tvb);
621 case CMPP_DELIVER_RESP:
622 cmpp_deliver_resp(cmpp_tree, tvb);
625 /* Implement the rest of the protocol here */
632 /* Get the CMPP PDU Length */
634 get_cmpp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, gint offset)
636 return tvb_get_ntohl(tvb, offset);
641 dissect_cmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
643 guint total_length, command_id, tvb_len;
644 /* Check that there's enough data */
645 tvb_len = tvb_length(tvb);
646 if (tvb_len < CMPP_FIX_HEADER_LENGTH)
649 /* Get some values from the packet header, probably using tvb_get_*() */
650 total_length = tvb_get_ntohl(tvb, 0); /* Get the pdu length */
651 command_id = tvb_get_ntohl(tvb, 4); /* get the pdu command id */
653 /* Looking at this protocol, it seems unlikely that the messages would
654 * get as big as a couple hundred bytes but that's not certain; just
655 * added a hopefully-way-too-big number to strengthen the heuristics.
657 if (total_length < CMPP_FIX_HEADER_LENGTH || total_length > 1000)
660 if (match_strval(command_id, vals_command_Id) == NULL)
663 if (check_col(pinfo->cinfo, COL_INFO))
664 col_clear(pinfo->cinfo, COL_INFO);
666 tcp_dissect_pdus(tvb, pinfo, tree, cmpp_desegment, CMPP_FIX_HEADER_LENGTH,
667 get_cmpp_pdu_len, dissect_cmpp_tcp_pdu);
669 /* Return the amount of data this dissector was able to dissect */
670 return tvb_length(tvb);
674 /* Register the protocol with Wireshark */
676 /* this format is require because a script is used to build the C function
677 that calls all the protocol registration.
680 proto_register_cmpp(void) {
682 /* Setup list of header fields See Section 1.6.1 for details*/
683 static hf_register_info hf[] = {
684 { &hf_cmpp_Total_Length,
685 { "Total Length", "cmpp.Total_Length",
686 FT_UINT32, BASE_DEC, NULL, 0x00,
687 "Total length of the CMPP PDU.",
690 { &hf_cmpp_Command_Id,
691 { "Command Id", "cmpp.Command_Id",
692 FT_UINT32, BASE_HEX, VALS(vals_command_Id), 0x00,
693 "Command Id of the CMPP messages",
696 { &hf_cmpp_Sequence_Id,
697 { "Sequence Id", "cmpp.Sequence_Id",
698 FT_UINT32, BASE_DEC, NULL, 0x00,
699 "Sequence Id of the CMPP messages",
702 { &hf_cmpp_connect_Source_Addr,
703 { "Source Addr", "cmpp.connect.Source_Addr",
704 FT_STRING, BASE_NONE, NULL, 0x00,
705 "Source Address, the SP_Id",
708 { &hf_cmpp_connect_AuthenticatorSource,
709 { "Authenticator Source", "cmpp.connect.AuthenticatorSource",
710 FT_STRING, BASE_NONE, NULL, 0x00,
711 "Authenticator source, MD5(Source_addr + 9 zero + shared secret + timestamp)",
716 { "Version", "cmpp.Version",
717 FT_STRING, BASE_NONE, NULL, 0x00,
721 { &hf_cmpp_connect_Timestamp,
722 { "Timestamp", "cmpp.connect.Timestamp",
723 FT_STRING, BASE_NONE, NULL, 0x00,
724 "Timestamp MM/DD HH:MM:SS",
727 { &hf_cmpp_connect_resp_status,
728 { "Connect Response Status", "cmpp.connect_resp.Status",
729 FT_UINT32, BASE_DEC, VALS(vals_connect_resp_status), 0x00,
730 "Response Status, Value higher then 4 means other error",
733 { &hf_cmpp_connect_resp_AuthenticatorISMG,
734 { "SIMG Authenticate result", "cmpp.connect_resp.AuthenticatorISMG",
735 FT_STRING, BASE_NONE, NULL, 0x00,
736 "Authenticator result, MD5(Status + AuthenticatorSource + shared secret)",
740 { "Msg_Id", "cmpp.Msg_Id",
741 FT_UINT64, BASE_HEX, NULL, 0x00,
745 { &hf_cmpp_submit_pk_total,
746 { "Number of Part", "cmpp.submit.Pk_total",
747 FT_UINT8, BASE_DEC, NULL, 0x00,
748 "Total number of parts of the message with the same Msg_Id, start from 1",
751 { &hf_cmpp_submit_pk_number,
752 { "Part Number", "cmpp.submit.Pk_number",
753 FT_UINT8, BASE_DEC, NULL, 0x00,
754 "Part number of the message with the same Msg_Id, start from 1",
757 { &hf_msg_id_timestamp,
758 { "Timestamp", "cmpp.Msg_Id.timestamp",
759 FT_STRING, BASE_NONE, NULL, 0x00,
760 "Timestamp MM/DD HH:MM:SS Bit 64 ~ 39",
763 { &hf_msg_id_ismg_code,
764 { "ISMG Code", "cmpp.Msg_Id.ismg_code",
765 FT_UINT32, BASE_DEC, NULL, 0x00,
766 "ISMG Code, bit 38 ~ 17",
769 { &hf_msg_id_sequence_id,
770 { "Msg_Id sequence Id", "cmpp.Msg_Id.sequence_id",
771 FT_UINT16, BASE_DEC, NULL, 0x00,
772 "Msg_Id sequence Id, bit 16 ~ 1",
775 { &hf_cmpp_submit_Registered_Delivery,
776 { "Registered Delivery", "cmpp.submit.Registered_Delivery",
777 FT_BOOLEAN, BASE_DEC, NULL, 0x00,
778 "Registered Delivery flag",
781 { &hf_cmpp_submit_Msg_level,
782 { "Message Level", "cmpp.submit.Msg_level",
783 FT_UINT8, BASE_DEC, NULL, 0x00,
787 { &hf_cmpp_Service_Id,
788 { "Service ID", "cmpp.Servicd_Id",
789 FT_STRING, BASE_NONE, NULL, 0x00,
790 "Service ID, a mix of characters, numbers and symbol",
793 { &hf_cmpp_submit_Fee_UserType,
794 { "Charging Informations", "cmpp.submit.Fee_UserType",
795 FT_UINT8, BASE_DEC, VALS(vals_submit_Fee_UserType), 0x00,
796 "Charging Informations, if value is 3, this field will not be used",
799 { &hf_cmpp_submit_Fee_terminal_Id,
800 { "Fee Terminal ID", "cmpp.submit.Fee_terminal_Id",
801 FT_STRING, BASE_NONE, NULL, 0x00,
802 "Fee Terminal ID, Valid only when Fee_UserType is 3",
805 { &hf_cmpp_submit_Fee_terminal_type,
806 { "Fake Fee Terminal", "cmpp.submit.Fee_terminal_type",
807 FT_BOOLEAN, BASE_DEC, NULL, 0x00,
808 "Fee terminal type, 0 is real, 1 is fake",
812 { "TP pId", "cmpp.TP_pId",
813 FT_UINT8, BASE_DEC, NULL, 0x00,
818 { "TP udhi", "cmpp.TP_udhi",
819 FT_UINT8, BASE_DEC, NULL, 0x00,
824 { "Message Format", "cmpp.Msg_Fmt",
825 FT_UINT8, BASE_DEC, VALS(vals_Msg_Fmt), 0x00,
829 { &hf_cmpp_submit_Msg_src,
830 { "Message Source SP_Id", "cmpp.submit.Msg_src",
831 FT_STRING, BASE_NONE, NULL, 0x00,
832 "Message source SP ID",
835 { &hf_cmpp_submit_FeeType, /* TODO Replace this with a vals_string*/
836 { "Fee Type", "cmpp.submit.FeeType",
837 FT_STRING, BASE_NONE, NULL, 0x00,
841 { &hf_cmpp_submit_FeeCode,
842 { "Fee Code", "cmpp.submit.FeeCode",
843 FT_STRING, BASE_NONE, NULL, 0x00,
847 { &hf_cmpp_submit_Valld_Time,
848 { "Valid time", "cmpp.submit.Valld_Time",
849 FT_STRING, BASE_NONE, NULL, 0x00,
850 "Message Valid Time, format follow SMPP 3.3",
853 { &hf_cmpp_submit_At_Time,
854 { "Send time", "cmpp.submit.At_time",
855 FT_STRING, BASE_NONE, NULL, 0x00,
856 "Message send time, format following SMPP 3.3",
859 { &hf_cmpp_submit_Src_Id,
860 { "Source ID", "cmpp.submit.Src_Id",
861 FT_STRING, BASE_NONE, NULL, 0x00,
862 "This value matches SMPP submit_sm source_addr field",
865 { &hf_cmpp_submit_DestUsr_tl,
866 { "Destination Address Count", "cmpp.submit.DestUsr_tl",
867 FT_UINT8, BASE_DEC, NULL, 0x00,
868 "Number of destination address, must smaller then 100",
871 { &hf_cmpp_Dest_terminal_Id,
872 { "Destination Address", "cmpp.Dest_terminal_Id",
873 FT_STRING, BASE_NONE, NULL, 0x00,
874 "MSISDN number which receive the SMS",
877 { &hf_cmpp_submit_Dest_terminal_type,
878 { "Fake Destination Terminal", "cmpp.submit.Dest_terminal_type",
879 FT_BOOLEAN, BASE_DEC, NULL, 0x00,
880 "destination terminal type, 0 is real, 1 is fake",
883 { &hf_cmpp_Msg_Length,
884 { "Message length", "cmpp.Msg_Length",
885 FT_UINT8, BASE_DEC, NULL, 0x00,
886 "SMS Message length, ASCII must be <= 160 bytes, other must be <= 140 bytes",
889 { &hf_cmpp_Msg_Content,
890 { "Message Content", "cmpp.Msg_Content",
891 FT_STRING, BASE_NONE, NULL, 0x00,
896 { "Link ID", "cmpp.LinkID",
897 FT_STRING, BASE_NONE, NULL, 0x00,
901 { &hf_cmpp_submit_resp_Result,
902 { "Result", "cmpp.submit_resp.Result",
903 FT_UINT32, BASE_DEC, VALS(vals_Submit_Resp_Result), 0x00,
907 { &hf_cmpp_deliver_Dest_Id,
908 { "Destination ID", "cmpp.deliver.Dest_Id",
909 FT_STRING, BASE_NONE, NULL, 0x00,
910 "SP Service ID or server number",
913 { &hf_cmpp_deliver_Src_terminal_Id,
914 { "Src_terminal_Id", "cmpp.deliver.Src_terminal_Id",
915 FT_STRING, BASE_NONE, NULL, 0x00,
916 "Source MSISDN number, if it is deliver report, this will be the CMPP_SUBMIT destination number",
919 { &hf_cmpp_deliver_Src_terminal_type,
920 { "Fake source terminal type", "cmpp.deliver.Src_terminal_type",
921 FT_BOOLEAN, BASE_DEC, NULL, 0x00,
922 "Type of the source terminal, can be 0 (real) or 1 (fake)",
925 { &hf_cmpp_deliver_Registered_Delivery,
926 { "Deliver Report", "cmpp.deliver.Registered_Delivery",
927 FT_BOOLEAN, BASE_DEC, NULL, 0x00,
928 "The message is a deliver report if this value = 1",
931 { &hf_cmpp_deliver_Report,
932 { "Detail Deliver Report", "cmpp.deliver.Report",
933 FT_NONE, BASE_NONE, NULL, 0x00,
937 { &hf_cmpp_deliver_Report_Stat,
938 { "Deliver Status", "cmpp.deliver.Report.Status",
939 FT_STRING, BASE_NONE, NULL, 0x00,
943 { &hf_cmpp_deliver_Report_Submit_time,
944 { "Submit_time", "cmpp.deliver.Report.Submit_time",
945 FT_STRING, BASE_NONE, NULL, 0x00,
949 { &hf_cmpp_deliver_Report_Done_time,
950 { "Done_time", "cmpp.deliver.Report.Done_time",
951 FT_STRING, BASE_NONE, NULL, 0x00,
955 { &hf_cmpp_deliver_Report_SMSC_sequence,
956 { "SMSC_sequence", "cmpp.Report.SMSC_sequence",
957 FT_UINT32, BASE_DEC, NULL, 0x00,
961 { &hf_cmpp_deliver_resp_Result,
962 { "Result", "cmpp.deliver_resp.Result",
963 FT_UINT32, BASE_DEC, VALS(vals_Deliver_Resp_Result), 0x00,
969 /* Setup protocol subtree array */
970 static gint *ett[] = {
976 /* Register the protocol name and description */
977 proto_cmpp = proto_register_protocol("China Mobile Point to Point Protocol",
980 /* Required function calls to register the header fields and subtrees used */
981 proto_register_field_array(proto_cmpp, hf, array_length(hf));
982 proto_register_subtree_array(ett, array_length(ett));
988 proto_reg_handoff_cmpp(void)
990 dissector_handle_t cmpp_handle;
992 cmpp_handle = new_create_dissector_handle(dissect_cmpp, proto_cmpp);
993 dissector_add("tcp.port", CMPP_SP_LONG_PORT, cmpp_handle);
994 dissector_add("tcp.port", CMPP_SP_SHORT_PORT, cmpp_handle);
995 dissector_add("tcp.port", CMPP_ISMG_LONG_PORT, cmpp_handle);
996 dissector_add("tcp.port", CMPP_ISMG_SHORT_PORT, cmpp_handle);