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.
28 #include <epan/packet.h>
29 #include <epan/wmem/wmem.h>
30 #include <epan/dissectors/packet-tcp.h>
32 #define CMPP_FIX_HEADER_LENGTH 12
33 #define CMPP_DELIVER_REPORT_LEN 71
35 /* These are not registered with IANA */
36 #define CMPP_SP_LONG_PORT 7890
37 #define CMPP_SP_SHORT_PORT 7900
38 #define CMPP_ISMG_LONG_PORT 7930
39 #define CMPP_ISMG_SHORT_PORT 9168
41 void proto_register_cmpp(void);
42 void proto_reg_handoff_cmpp(void);
44 /* Initialize the protocol and registered fields */
45 static gint proto_cmpp
= -1;
47 /* These are the fix header field */
48 static gint hf_cmpp_Total_Length
= -1;
49 static gint hf_cmpp_Command_Id
= -1;
50 static gint hf_cmpp_Sequence_Id
= -1;
53 static gint hf_cmpp_connect_Source_Addr
= -1;
54 static gint hf_cmpp_connect_AuthenticatorSource
= -1;
55 static gint hf_cmpp_Version
= -1;
56 static gint hf_cmpp_connect_Timestamp
= -1;
58 /* CMPP_CONNECT_RESP */
59 static gint hf_cmpp_connect_resp_status
= -1;
60 static gint hf_cmpp_connect_resp_AuthenticatorISMG
= -1;
63 static gint hf_cmpp_submit_pk_total
= -1;
64 static gint hf_cmpp_submit_pk_number
= -1;
65 static gint hf_cmpp_submit_Msg_level
= -1;
66 static gint hf_cmpp_submit_Fee_UserType
= -1;
67 static gint hf_cmpp_submit_Fee_terminal_Id
= -1;
68 static gint hf_cmpp_submit_Fee_terminal_type
= -1;
69 static gint hf_cmpp_submit_Msg_src
= -1;
70 static gint hf_cmpp_submit_FeeType
= -1;
71 static gint hf_cmpp_submit_FeeCode
= -1;
72 static gint hf_cmpp_submit_Valld_Time
= -1;
73 static gint hf_cmpp_submit_At_Time
= -1;
74 static gint hf_cmpp_submit_Src_Id
= -1;
75 static gint hf_cmpp_submit_DestUsr_tl
= -1;
76 static gint hf_cmpp_submit_Dest_terminal_type
= -1;
77 static gint hf_cmpp_submit_Registered_Delivery
= -1;
79 /* Field common in CMPP_SUBMIT and CMPP_DELIVER */
80 static gint hf_cmpp_Dest_terminal_Id
= -1;
81 static gint hf_cmpp_Service_Id
= -1;
82 static gint hf_cmpp_TP_pId
= -1;
83 static gint hf_cmpp_TP_udhi
= -1;
84 static gint hf_cmpp_Msg_Fmt
= -1;
85 static gint hf_cmpp_Msg_Length
= -1;
86 static gint hf_cmpp_Msg_Content
= -1;
87 static gint hf_cmpp_LinkID
= -1;
89 /* CMPP_SUBMIT_RESP */
90 static gint hf_cmpp_submit_resp_Result
= -1;
94 /* TODO implement CMPP_QUERY and CMPP_QUERY_RESP */
97 static gint hf_cmpp_deliver_Dest_Id
= -1;
98 static gint hf_cmpp_deliver_Src_terminal_Id
= -1;
99 static gint hf_cmpp_deliver_Src_terminal_type
= -1;
100 static gint hf_cmpp_deliver_Registered_Delivery
= -1;
102 static gint hf_cmpp_deliver_resp_Result
= -1;
104 /* CMPP Deliver Report */
105 static gint hf_cmpp_deliver_Report
= -1;
106 static gint hf_cmpp_deliver_Report_Stat
= -1;
107 static gint hf_cmpp_deliver_Report_Submit_time
= -1;
108 static gint hf_cmpp_deliver_Report_Done_time
= -1;
109 static gint hf_cmpp_deliver_Report_SMSC_sequence
= -1;
112 static gint hf_cmpp_msg_id
= -1;
113 static gint hf_msg_id_timestamp
= -1;
114 static gint hf_msg_id_ismg_code
= -1;
115 static gint hf_msg_id_sequence_id
= -1;
117 static gboolean cmpp_desegment
= TRUE
;
120 * Value-arrays for field-contents
122 #define CMPP_CONNECT 0x00000001
123 #define CMPP_CONNECT_RESP 0x80000001
124 #define CMPP_TERMINATE 0x00000002
125 #define CMPP_TERMINATE_RESP 0x80000002
126 #define CMPP_SUBMIT 0x00000004
127 #define CMPP_SUBMIT_RESP 0x80000004
128 #define CMPP_DELIVER 0x00000005
129 #define CMPP_DELIVER_RESP 0x80000005
130 #define CMPP_QUERY 0x00000006
131 #define CMPP_QUERY_RESP 0x80000006
132 #define CMPP_CANCEL 0x00000007
133 #define CMPP_CANCEL_RESP 0x80000007
134 #define CMPP_ACTIVE_TEST 0x00000008
135 #define CMPP_ACTIVE_TEST_RESP 0x80000008
136 #define CMPP_FWD 0x00000009
137 #define CMPP_FWD_RESP 0x80000009
138 #define CMPP_MT_ROUTE 0x00000010
139 #define CMPP_MO_ROUTE 0x00000011
140 #define CMPP_GET_MT_ROUTE 0x00000012
141 #define CMPP_MT_ROUTE_UPDATE 0x00000013
142 #define CMPP_MO_ROUTE_UPDATE 0x00000014
143 #define CMPP_PUSH_MT_ROUTE_UPDATE 0x00000015
144 #define CMPP_PUSH_MO_ROUTE_UPDATE 0x00000016
145 #define CMPP_GET_MO_ROUTE 0x00000017
146 #define CMPP_MT_ROUTE_RESP 0x80000010
147 #define CMPP_MO_ROUTE_RESP 0x80000011
148 #define CMPP_GET_MT_ROUTE_RESP 0x80000012
149 #define CMPP_MT_ROUTE_UPDATE_RESP 0x80000013
150 #define CMPP_MO_ROUTE_UPDATE_RESP 0x80000014
151 #define CMPP_PUSH_MT_ROUTE_UPDATE_RESP 0x80000015
152 #define CMPP_PUSH_MO_ROUTE_UPDATE_RESP 0x80000016
153 #define CMPP_GET_MO_ROUTE_RESP 0x80000017
154 static const value_string vals_command_Id
[] = { /* Operation */
155 { CMPP_CONNECT
, "CMPP_CONNECT" },
156 { CMPP_CONNECT_RESP
, "CMPP_CONNECT_RESP" },
157 { CMPP_TERMINATE
, "CMPP_TERMINATE" },
158 { CMPP_TERMINATE_RESP
, "CMPP_TERMINATE_RESP" },
159 { CMPP_SUBMIT
, "CMPP_SUBMIT" },
160 { CMPP_SUBMIT_RESP
, "CMPP_SUBMIT_RESP" },
161 { CMPP_DELIVER
, "CMPP_DELIVER" },
162 { CMPP_DELIVER_RESP
, "CMPP_DELIVER_RESP" },
163 { CMPP_QUERY
, "CMPP_QUERY" },
164 { CMPP_QUERY_RESP
, "CMPP_QUERY" },
165 { CMPP_CANCEL
, "CMPP_CANCEL" },
166 { CMPP_CANCEL_RESP
, "CMPP_CANCEL_RESP" },
167 { CMPP_ACTIVE_TEST
, "CMPP_ACTIVE_TEST" },
168 { CMPP_ACTIVE_TEST_RESP
, "CMPP_ACTIVE_TEST_RESP" },
169 { CMPP_FWD
, "CMPP_FWD" },
170 { CMPP_FWD_RESP
, "CMPP_FWD_RESP" },
171 { CMPP_MT_ROUTE
, "CMPP_MT_ROUTE" },
172 { CMPP_MO_ROUTE
, "CMPP_MO_ROUTE" },
173 { CMPP_GET_MT_ROUTE
, "CMPP_GET_MT_ROUTE" },
174 { CMPP_MT_ROUTE_UPDATE
, "CMPP_MT_ROUTE_UPDATE" },
175 { CMPP_MO_ROUTE_UPDATE
, "CMPP_MO_ROUTE_UPDATE" },
176 { CMPP_PUSH_MT_ROUTE_UPDATE
, "CMPP_PUSH_MT_ROUTE_UPDATE" },
177 { CMPP_PUSH_MO_ROUTE_UPDATE
, "CMPP_PUSH_MO_ROUTE_UPDATE" },
178 { CMPP_GET_MO_ROUTE
, "CMPP_GET_MO_ROUTE" },
179 { CMPP_MT_ROUTE_RESP
, "CMPP_MT_ROUTE_RESP" },
180 { CMPP_MO_ROUTE_RESP
, "CMPP_MO_ROUTE_RESP" },
181 { CMPP_GET_MT_ROUTE_RESP
, "CMPP_GET_MT_ROUTE_RESP" },
182 { CMPP_MT_ROUTE_UPDATE_RESP
, "CMPP_MT_ROUTE_UPDATE_RESP" },
183 { CMPP_MO_ROUTE_UPDATE_RESP
, "CMPP_MO_ROUTE_UPDATE_RESP" },
184 { CMPP_PUSH_MT_ROUTE_UPDATE_RESP
, "CMPP_PUSH_MT_ROUTE_UPDATE_RESP" },
185 { CMPP_PUSH_MO_ROUTE_UPDATE_RESP
, "CMPP_PUSH_MO_ROUTE_UPDATE_RESP" },
186 { CMPP_GET_MO_ROUTE_RESP
, "CMPP_GET_MO_ROUTE_RESP" },
190 static const value_string vals_connect_resp_status
[] = { /* Connection Status */
192 { 1, "Message structure error" },
193 { 2, "Illegal source address" },
194 { 3, "Authenticate error" },
195 { 4, "Version too high" },
199 static const value_string vals_submit_Fee_UserType
[] = { /* Submit Fee_UserType */
200 { 0, "Charging destination MSISDN" },
201 { 1, "Charging source MSISDN" },
202 { 2, "Charging SP" },
203 { 3, "Unuse, Charge info from Fee_terminal_Id" },
207 static const value_string vals_Msg_Fmt
[] = { /* Message Format */
209 { 3, "Short message card" }, /* TODO find the correct string of this value */
210 { 4, "Binary data" },
211 { 8, "UCS2 encoding" },
212 {15, "GB encoding" },
216 /* Submit Response Result */
217 static const value_string vals_Submit_Resp_Result
[] = {
219 { 1, "Message format error" },
220 { 2, "Command error" },
221 { 3, "Repeat sequence id" },
222 { 4, "Incorrect message length" },
223 { 5, "Incorrect fee code" },
224 { 6, "Message too long" },
225 { 7, "Incorrect service id" },
226 { 8, "Bandwidth error" },
227 { 9, "Gateway does not service this charging number" },
228 {10, "Incorrect Src_Id" },
229 {11, "Incorrect Msg_src" },
230 {12, "Incorrect Fee_terminal_Id" },
231 {13, "Incorrect Dest_terminal_Id" },
235 /* Deliver Response Result */
236 static const value_string vals_Deliver_Resp_Result
[] = {
238 { 1, "Message format error" },
239 { 2, "Command error" },
240 { 3, "Repeat sequence id" },
241 { 4, "Incorrect message length" },
242 { 5, "Incorrect fee code" },
243 { 6, "Message too long" },
244 { 7, "Incorrect service id" },
245 { 8, "Bandwidth error" },
249 /* Initialize the subtree pointers */
250 static gint ett_cmpp
= -1;
251 static gint ett_msg_id
= -1;
252 static gint ett_deliver_report
= -1;
254 /* Helper functions */
257 cmpp_octet_string(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
, gint length
)
261 display
= (char *)tvb_get_string(wmem_packet_scope(), tvb
, offset
, length
);
262 proto_tree_add_string(tree
, field
, tvb
, offset
, length
, display
);
267 cmpp_version(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
269 gint8 version
, major
, minor
;
272 version
= tvb_get_guint8(tvb
, offset
);
273 minor
= version
& 0x0F;
274 major
= (version
& 0xF0) >> 4;
275 strval
= wmem_strdup_printf(wmem_packet_scope(), "%02u.%02u", major
, minor
);
276 /* TODO: the version should be added as a uint_format */
277 proto_tree_add_string(tree
, field
, tvb
, offset
, 1, strval
);
282 cmpp_timestamp(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
284 gint8 month
, day
, hour
, minute
, second
;
288 timevalue
= tvb_get_ntohl(tvb
, offset
);
289 second
= timevalue
% 100;
291 minute
= timevalue
% 100;
293 hour
= timevalue
% 100;
295 day
= timevalue
% 100;
296 month
= timevalue
/ 100;
297 strval
= wmem_strdup_printf(wmem_packet_scope(), "%02u/%02u %02u:%02u:%02u", month
, day
,
298 hour
, minute
, second
);
299 proto_tree_add_string(tree
, field
, tvb
, offset
, 4, strval
);
303 /* TODO: most calls to these (except those that use the return value) should
304 * be replaced by calls to proto_tree_add_item().
307 cmpp_uint1(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
310 value
= tvb_get_guint8(tvb
, offset
);
311 proto_tree_add_uint(tree
, field
, tvb
, offset
, 1, value
);
316 cmpp_uint2(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
319 value
= tvb_get_ntohs(tvb
, offset
);
320 proto_tree_add_uint(tree
, field
, tvb
, offset
, 2, value
);
325 cmpp_uint4(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
328 value
= tvb_get_ntohl(tvb
, offset
);
329 proto_tree_add_uint(tree
, field
, tvb
, offset
, 4, value
);
334 cmpp_boolean(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
337 value
= tvb_get_guint8(tvb
, offset
);
338 proto_tree_add_boolean(tree
, field
, tvb
, offset
, 1, value
);
345 cmpp_msg_id(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, gint offset
)
347 guint8 month
,day
,hour
,minute
,second
;
350 proto_tree
*sub_tree
;
353 pi
= proto_tree_add_item(tree
, field
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
354 sub_tree
= proto_item_add_subtree(pi
, ett_msg_id
);
356 month
= (tvb_get_guint8(tvb
, offset
) & 0xF0) >> 4;
357 day
= (tvb_get_ntohs(tvb
, offset
) & 0x0F80) >> 7;
358 hour
= (tvb_get_guint8(tvb
, offset
+ 1) & 0x7C) >> 2;
359 minute
= (tvb_get_ntohs(tvb
, offset
+ 1) & 0x03F0) >> 4;
360 second
= (tvb_get_ntohs(tvb
, offset
+ 2) & 0x0FC0) >> 6;
361 strval
= wmem_strdup_printf(wmem_packet_scope(), "%02u/%02u %02u:%02u:%02u", month
, day
,
362 hour
, minute
, second
);
364 ismg_code
= (tvb_get_ntohl(tvb
, offset
+ 3) & 0x3FFFFF00) >> 16;
366 proto_tree_add_string(sub_tree
, hf_msg_id_timestamp
, tvb
, offset
, 4, strval
);
367 proto_tree_add_uint(sub_tree
, hf_msg_id_ismg_code
, tvb
, offset
+ 3, 3, ismg_code
);
368 cmpp_uint2(sub_tree
, tvb
, hf_msg_id_sequence_id
, offset
+ 6);
372 cmpp_connect(proto_tree
*tree
, tvbuff_t
*tvb
)
375 offset
= CMPP_FIX_HEADER_LENGTH
;
376 cmpp_octet_string(tree
, tvb
, hf_cmpp_connect_Source_Addr
, offset
, 6);
378 proto_tree_add_string(tree
, hf_cmpp_connect_AuthenticatorSource
, tvb
, offset
, 16, "MD5 Hash");
380 cmpp_version(tree
, tvb
, hf_cmpp_Version
, offset
);
382 cmpp_timestamp(tree
, tvb
, hf_cmpp_connect_Timestamp
, offset
);
387 cmpp_connect_resp(proto_tree
*tree
, tvbuff_t
*tvb
)
390 offset
= CMPP_FIX_HEADER_LENGTH
;
391 cmpp_uint4(tree
, tvb
, hf_cmpp_connect_resp_status
, offset
);
393 proto_tree_add_string(tree
, hf_cmpp_connect_resp_AuthenticatorISMG
, tvb
, offset
, 16, "MD5 Hash");
395 cmpp_version(tree
, tvb
, hf_cmpp_Version
, offset
);
399 cmpp_submit(proto_tree
*tree
, tvbuff_t
*tvb
)
402 guint8 destUsr
, msgLen
;
403 offset
= CMPP_FIX_HEADER_LENGTH
;
404 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
406 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_pk_total
, offset
);
408 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_pk_number
, offset
);
410 cmpp_boolean(tree
, tvb
, hf_cmpp_submit_Registered_Delivery
, offset
);
412 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_Msg_level
, offset
);
414 cmpp_octet_string(tree
, tvb
, hf_cmpp_Service_Id
, offset
, 10);
416 cmpp_uint1(tree
, tvb
, hf_cmpp_submit_Fee_UserType
, offset
);
418 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Fee_terminal_Id
, offset
, 32);
420 cmpp_boolean(tree
, tvb
, hf_cmpp_submit_Fee_terminal_type
, offset
);
422 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_pId
, offset
);
424 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_udhi
, offset
);
426 cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Fmt
, offset
);
428 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Msg_src
, offset
, 6);
430 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_FeeType
, offset
, 2);
432 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_FeeCode
, offset
, 6);
435 /* TODO create function to handle SMPP time format */
436 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Valld_Time
, offset
, 17);
438 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_At_Time
, offset
, 17);
441 cmpp_octet_string(tree
, tvb
, hf_cmpp_submit_Src_Id
, offset
, 17);
443 destUsr
= cmpp_uint1(tree
, tvb
, hf_cmpp_submit_DestUsr_tl
, offset
);
446 /* Loop through each destination address */
447 for(i
= 0; i
< destUsr
; i
++)
449 cmpp_octet_string(tree
, tvb
, hf_cmpp_Dest_terminal_Id
, offset
, 32);
453 cmpp_boolean(tree
, tvb
, hf_cmpp_submit_Dest_terminal_type
, offset
);
455 msgLen
= cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Length
, offset
);
457 proto_tree_add_string(tree
, hf_cmpp_Msg_Content
, tvb
, offset
, msgLen
, "SMS Messages");
459 cmpp_octet_string(tree
, tvb
, hf_cmpp_LinkID
, offset
, 20);
463 cmpp_submit_resp(proto_tree
*tree
, tvbuff_t
*tvb
)
466 offset
= CMPP_FIX_HEADER_LENGTH
;
467 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
469 cmpp_uint4(tree
, tvb
, hf_cmpp_submit_resp_Result
, offset
);
473 cmpp_deliver_report(proto_tree
*tree
, tvbuff_t
*tvb
, gint field
, guint offset
)
476 proto_tree
*sub_tree
;
478 pi
= proto_tree_add_item(tree
, field
, tvb
, offset
, CMPP_DELIVER_REPORT_LEN
, ENC_BIG_ENDIAN
);
479 sub_tree
= proto_item_add_subtree(pi
, ett_deliver_report
);
480 cmpp_msg_id(sub_tree
, tvb
, hf_cmpp_msg_id
, offset
);
482 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_deliver_Report_Stat
, offset
, 7);
484 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_deliver_Report_Submit_time
, offset
, 10);
486 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_deliver_Report_Done_time
, offset
, 10);
488 cmpp_octet_string(sub_tree
, tvb
, hf_cmpp_Dest_terminal_Id
, offset
, 32);
490 cmpp_uint4(sub_tree
, tvb
, hf_cmpp_deliver_Report_SMSC_sequence
, offset
);
494 cmpp_deliver(proto_tree
*tree
, tvbuff_t
*tvb
)
496 guint offset
, msgLen
;
498 offset
= CMPP_FIX_HEADER_LENGTH
;
499 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
501 cmpp_octet_string(tree
, tvb
, hf_cmpp_deliver_Dest_Id
, offset
, 21);
503 cmpp_octet_string(tree
, tvb
, hf_cmpp_Service_Id
, offset
, 10);
505 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_pId
, offset
);
507 cmpp_uint1(tree
, tvb
, hf_cmpp_TP_udhi
, offset
);
509 cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Fmt
, offset
);
511 cmpp_octet_string(tree
, tvb
, hf_cmpp_deliver_Src_terminal_Id
, offset
, 32);
513 cmpp_boolean(tree
, tvb
, hf_cmpp_deliver_Src_terminal_type
, offset
);
515 report
= cmpp_boolean(tree
, tvb
, hf_cmpp_deliver_Registered_Delivery
, offset
);
517 msgLen
= cmpp_uint1(tree
, tvb
, hf_cmpp_Msg_Length
, offset
);
520 proto_tree_add_string(tree
, hf_cmpp_Msg_Content
, tvb
, offset
, msgLen
, "SMS Messages");
522 cmpp_deliver_report(tree
, tvb
, hf_cmpp_deliver_Report
, offset
);
524 cmpp_octet_string(tree
, tvb
, hf_cmpp_LinkID
, offset
, 20);
528 cmpp_deliver_resp(proto_tree
*tree
, tvbuff_t
*tvb
)
531 offset
= CMPP_FIX_HEADER_LENGTH
;
532 cmpp_msg_id(tree
, tvb
, hf_cmpp_msg_id
, offset
);
534 /* TODO implement the result field here */
535 cmpp_uint4(tree
, tvb
, hf_cmpp_deliver_resp_Result
, offset
);
538 /* Code to actually dissect the packets */
540 dissect_cmpp_tcp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
543 /* Set up structures needed to add the protocol subtree and manage it */
545 proto_tree
*cmpp_tree
;
549 const gchar
*command_str
; /* Header command string */
551 /* Get the length of the PDU */
552 tvb_len
= tvb_length(tvb
);
553 /* if the length of the tvb is shorder then the cmpp header length exit */
554 if (tvb_len
< CMPP_FIX_HEADER_LENGTH
)
557 total_length
= tvb_get_ntohl(tvb
, 0); /* Get the pdu length */
558 command_id
= tvb_get_ntohl(tvb
, 4); /* get the pdu command id */
560 if (try_val_to_str(command_id
, vals_command_Id
) == NULL
)
562 /* Should never happen: we checked this in dissect_cmpp() */
566 command_str
= val_to_str(command_id
, vals_command_Id
,
567 "(Unknown CMPP Operation 0x%08X)");
569 /* tvb has less data then the PDU Header status, return */
570 if (tvb_len
< total_length
)
572 /* Should never happen: TCP should have desegmented for us */
576 /* Make entries in Protocol column and Info column on summary display */
577 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "CMPP");
579 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s. ", command_str
);
583 ti
= proto_tree_add_item(tree
, proto_cmpp
, tvb
, 0, -1, ENC_NA
);
585 cmpp_tree
= proto_item_add_subtree(ti
, ett_cmpp
);
587 /* Add the fix header informations to the tree */
588 cmpp_uint4(cmpp_tree
, tvb
, hf_cmpp_Total_Length
, 0);
589 cmpp_uint4(cmpp_tree
, tvb
, hf_cmpp_Command_Id
, 4);
590 cmpp_uint4(cmpp_tree
, tvb
, hf_cmpp_Sequence_Id
, 8);
595 cmpp_connect(cmpp_tree
, tvb
);
597 case CMPP_CONNECT_RESP
:
598 cmpp_connect_resp(cmpp_tree
, tvb
);
600 /* CMPP_TERMINATE and CMPP_TERMINATE_RESP don't have msg body */
602 case CMPP_TERMINATE_RESP
:
605 cmpp_submit(cmpp_tree
, tvb
);
607 case CMPP_SUBMIT_RESP
:
608 cmpp_submit_resp(cmpp_tree
, tvb
);
611 cmpp_deliver(cmpp_tree
, tvb
);
613 case CMPP_DELIVER_RESP
:
614 cmpp_deliver_resp(cmpp_tree
, tvb
);
617 /* Implement the rest of the protocol here */
622 return tvb_length(tvb
);
626 /* Get the CMPP PDU Length */
628 get_cmpp_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, gint offset
)
630 return tvb_get_ntohl(tvb
, offset
);
635 dissect_cmpp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
637 guint total_length
, command_id
, tvb_len
;
638 /* Check that there's enough data */
639 tvb_len
= tvb_length(tvb
);
640 if (tvb_len
< CMPP_FIX_HEADER_LENGTH
)
643 /* Get some values from the packet header, probably using tvb_get_*() */
644 total_length
= tvb_get_ntohl(tvb
, 0); /* Get the pdu length */
645 command_id
= tvb_get_ntohl(tvb
, 4); /* get the pdu command id */
647 /* Looking at this protocol, it seems unlikely that the messages would
648 * get as big as a couple hundred bytes but that's not certain; just
649 * added a hopefully-way-too-big number to strengthen the heuristics.
651 if (total_length
< CMPP_FIX_HEADER_LENGTH
|| total_length
> 1000)
654 if (try_val_to_str(command_id
, vals_command_Id
) == NULL
)
657 col_clear(pinfo
->cinfo
, COL_INFO
);
659 tcp_dissect_pdus(tvb
, pinfo
, tree
, cmpp_desegment
, CMPP_FIX_HEADER_LENGTH
,
660 get_cmpp_pdu_len
, dissect_cmpp_tcp_pdu
, data
);
662 /* Return the amount of data this dissector was able to dissect */
663 return tvb_length(tvb
);
667 /* Register the protocol with Wireshark */
670 proto_register_cmpp(void) {
672 /* Setup list of header fields See Section 1.6.1 for details*/
673 static hf_register_info hf
[] = {
674 { &hf_cmpp_Total_Length
,
675 { "Total Length", "cmpp.Total_Length",
676 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
677 "Total length of the CMPP PDU.",
680 { &hf_cmpp_Command_Id
,
681 { "Command Id", "cmpp.Command_Id",
682 FT_UINT32
, BASE_HEX
, VALS(vals_command_Id
), 0x00,
683 "Command Id of the CMPP messages",
686 { &hf_cmpp_Sequence_Id
,
687 { "Sequence Id", "cmpp.Sequence_Id",
688 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
689 "Sequence Id of the CMPP messages",
692 { &hf_cmpp_connect_Source_Addr
,
693 { "Source Addr", "cmpp.connect.Source_Addr",
694 FT_STRING
, BASE_NONE
, NULL
, 0x00,
695 "Source Address, the SP_Id",
698 { &hf_cmpp_connect_AuthenticatorSource
,
699 { "Authenticator Source", "cmpp.connect.AuthenticatorSource",
700 FT_STRING
, BASE_NONE
, NULL
, 0x00,
701 "Authenticator source, MD5(Source_addr + 9 zero + shared secret + timestamp)",
706 { "Version", "cmpp.Version",
707 FT_STRING
, BASE_NONE
, NULL
, 0x00,
711 { &hf_cmpp_connect_Timestamp
,
712 { "Timestamp", "cmpp.connect.Timestamp",
713 FT_STRING
, BASE_NONE
, NULL
, 0x00,
714 "Timestamp MM/DD HH:MM:SS",
717 { &hf_cmpp_connect_resp_status
,
718 { "Connect Response Status", "cmpp.connect_resp.Status",
719 FT_UINT32
, BASE_DEC
, VALS(vals_connect_resp_status
), 0x00,
720 "Response Status, Value higher then 4 means other error",
723 { &hf_cmpp_connect_resp_AuthenticatorISMG
,
724 { "SIMG Authenticate result", "cmpp.connect_resp.AuthenticatorISMG",
725 FT_STRING
, BASE_NONE
, NULL
, 0x00,
726 "Authenticator result, MD5(Status + AuthenticatorSource + shared secret)",
730 { "Msg_Id", "cmpp.Msg_Id",
731 FT_UINT64
, BASE_HEX
, NULL
, 0x00,
735 { &hf_cmpp_submit_pk_total
,
736 { "Number of Part", "cmpp.submit.Pk_total",
737 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
738 "Total number of parts of the message with the same Msg_Id, start from 1",
741 { &hf_cmpp_submit_pk_number
,
742 { "Part Number", "cmpp.submit.Pk_number",
743 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
744 "Part number of the message with the same Msg_Id, start from 1",
747 { &hf_msg_id_timestamp
,
748 { "Timestamp", "cmpp.Msg_Id.timestamp",
749 FT_STRING
, BASE_NONE
, NULL
, 0x00,
750 "Timestamp MM/DD HH:MM:SS Bit 64 ~ 39",
753 { &hf_msg_id_ismg_code
,
754 { "ISMG Code", "cmpp.Msg_Id.ismg_code",
755 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
756 "ISMG Code, bit 38 ~ 17",
759 { &hf_msg_id_sequence_id
,
760 { "Msg_Id sequence Id", "cmpp.Msg_Id.sequence_id",
761 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
762 "Msg_Id sequence Id, bit 16 ~ 1",
765 { &hf_cmpp_submit_Registered_Delivery
,
766 { "Registered Delivery", "cmpp.submit.Registered_Delivery",
767 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
768 "Registered Delivery flag",
771 { &hf_cmpp_submit_Msg_level
,
772 { "Message Level", "cmpp.submit.Msg_level",
773 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
777 { &hf_cmpp_Service_Id
,
778 { "Service ID", "cmpp.Servicd_Id",
779 FT_STRING
, BASE_NONE
, NULL
, 0x00,
780 "Service ID, a mix of characters, numbers and symbol",
783 { &hf_cmpp_submit_Fee_UserType
,
784 { "Charging Informations", "cmpp.submit.Fee_UserType",
785 FT_UINT8
, BASE_DEC
, VALS(vals_submit_Fee_UserType
), 0x00,
786 "Charging Informations, if value is 3, this field will not be used",
789 { &hf_cmpp_submit_Fee_terminal_Id
,
790 { "Fee Terminal ID", "cmpp.submit.Fee_terminal_Id",
791 FT_STRING
, BASE_NONE
, NULL
, 0x00,
792 "Fee Terminal ID, Valid only when Fee_UserType is 3",
795 { &hf_cmpp_submit_Fee_terminal_type
,
796 { "Fake Fee Terminal", "cmpp.submit.Fee_terminal_type",
797 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
798 "Fee terminal type, 0 is real, 1 is fake",
802 { "TP pId", "cmpp.TP_pId",
803 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
808 { "TP udhi", "cmpp.TP_udhi",
809 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
814 { "Message Format", "cmpp.Msg_Fmt",
815 FT_UINT8
, BASE_DEC
, VALS(vals_Msg_Fmt
), 0x00,
819 { &hf_cmpp_submit_Msg_src
,
820 { "Message Source SP_Id", "cmpp.submit.Msg_src",
821 FT_STRING
, BASE_NONE
, NULL
, 0x00,
822 "Message source SP ID",
825 { &hf_cmpp_submit_FeeType
, /* TODO Replace this with a vals_string*/
826 { "Fee Type", "cmpp.submit.FeeType",
827 FT_STRING
, BASE_NONE
, NULL
, 0x00,
831 { &hf_cmpp_submit_FeeCode
,
832 { "Fee Code", "cmpp.submit.FeeCode",
833 FT_STRING
, BASE_NONE
, NULL
, 0x00,
837 { &hf_cmpp_submit_Valld_Time
,
838 { "Valid time", "cmpp.submit.Valld_Time",
839 FT_STRING
, BASE_NONE
, NULL
, 0x00,
840 "Message Valid Time, format follow SMPP 3.3",
843 { &hf_cmpp_submit_At_Time
,
844 { "Send time", "cmpp.submit.At_time",
845 FT_STRING
, BASE_NONE
, NULL
, 0x00,
846 "Message send time, format following SMPP 3.3",
849 { &hf_cmpp_submit_Src_Id
,
850 { "Source ID", "cmpp.submit.Src_Id",
851 FT_STRING
, BASE_NONE
, NULL
, 0x00,
852 "This value matches SMPP submit_sm source_addr field",
855 { &hf_cmpp_submit_DestUsr_tl
,
856 { "Destination Address Count", "cmpp.submit.DestUsr_tl",
857 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
858 "Number of destination address, must smaller then 100",
861 { &hf_cmpp_Dest_terminal_Id
,
862 { "Destination Address", "cmpp.Dest_terminal_Id",
863 FT_STRING
, BASE_NONE
, NULL
, 0x00,
864 "MSISDN number which receive the SMS",
867 { &hf_cmpp_submit_Dest_terminal_type
,
868 { "Fake Destination Terminal", "cmpp.submit.Dest_terminal_type",
869 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
870 "destination terminal type, 0 is real, 1 is fake",
873 { &hf_cmpp_Msg_Length
,
874 { "Message length", "cmpp.Msg_Length",
875 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
876 "SMS Message length, ASCII must be <= 160 bytes, other must be <= 140 bytes",
879 { &hf_cmpp_Msg_Content
,
880 { "Message Content", "cmpp.Msg_Content",
881 FT_STRING
, BASE_NONE
, NULL
, 0x00,
886 { "Link ID", "cmpp.LinkID",
887 FT_STRING
, BASE_NONE
, NULL
, 0x00,
891 { &hf_cmpp_submit_resp_Result
,
892 { "Result", "cmpp.submit_resp.Result",
893 FT_UINT32
, BASE_DEC
, VALS(vals_Submit_Resp_Result
), 0x00,
897 { &hf_cmpp_deliver_Dest_Id
,
898 { "Destination ID", "cmpp.deliver.Dest_Id",
899 FT_STRING
, BASE_NONE
, NULL
, 0x00,
900 "SP Service ID or server number",
903 { &hf_cmpp_deliver_Src_terminal_Id
,
904 { "Src_terminal_Id", "cmpp.deliver.Src_terminal_Id",
905 FT_STRING
, BASE_NONE
, NULL
, 0x00,
906 "Source MSISDN number, if it is deliver report, this will be the CMPP_SUBMIT destination number",
909 { &hf_cmpp_deliver_Src_terminal_type
,
910 { "Fake source terminal type", "cmpp.deliver.Src_terminal_type",
911 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
912 "Type of the source terminal, can be 0 (real) or 1 (fake)",
915 { &hf_cmpp_deliver_Registered_Delivery
,
916 { "Deliver Report", "cmpp.deliver.Registered_Delivery",
917 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
918 "The message is a deliver report if this value = 1",
921 { &hf_cmpp_deliver_Report
,
922 { "Detail Deliver Report", "cmpp.deliver.Report",
923 FT_NONE
, BASE_NONE
, NULL
, 0x00,
927 { &hf_cmpp_deliver_Report_Stat
,
928 { "Deliver Status", "cmpp.deliver.Report.Status",
929 FT_STRING
, BASE_NONE
, NULL
, 0x00,
933 { &hf_cmpp_deliver_Report_Submit_time
,
934 { "Submit_time", "cmpp.deliver.Report.Submit_time",
935 FT_STRING
, BASE_NONE
, NULL
, 0x00,
939 { &hf_cmpp_deliver_Report_Done_time
,
940 { "Done_time", "cmpp.deliver.Report.Done_time",
941 FT_STRING
, BASE_NONE
, NULL
, 0x00,
945 { &hf_cmpp_deliver_Report_SMSC_sequence
,
946 { "SMSC_sequence", "cmpp.Report.SMSC_sequence",
947 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
951 { &hf_cmpp_deliver_resp_Result
,
952 { "Result", "cmpp.deliver_resp.Result",
953 FT_UINT32
, BASE_DEC
, VALS(vals_Deliver_Resp_Result
), 0x00,
959 /* Setup protocol subtree array */
960 static gint
*ett
[] = {
966 /* Register the protocol name and description */
967 proto_cmpp
= proto_register_protocol("China Mobile Point to Point Protocol",
970 /* Required function calls to register the header fields and subtrees used */
971 proto_register_field_array(proto_cmpp
, hf
, array_length(hf
));
972 proto_register_subtree_array(ett
, array_length(ett
));
978 proto_reg_handoff_cmpp(void)
980 dissector_handle_t cmpp_handle
;
982 cmpp_handle
= new_create_dissector_handle(dissect_cmpp
, proto_cmpp
);
983 dissector_add_uint("tcp.port", CMPP_SP_LONG_PORT
, cmpp_handle
);
984 dissector_add_uint("tcp.port", CMPP_SP_SHORT_PORT
, cmpp_handle
);
985 dissector_add_uint("tcp.port", CMPP_ISMG_LONG_PORT
, cmpp_handle
);
986 dissector_add_uint("tcp.port", CMPP_ISMG_SHORT_PORT
, cmpp_handle
);