Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-cmpp.c
blob12c68d76f7c64ec0b5e85553b2623f066a19c3af
1 /* packet-cmpp.c
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
12 #include "config.h"
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;
36 /* CMPP_CONNECT */
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;
46 /* CMPP_SUBMIT */
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;
76 /* CMPP_QUERY */
77 /* CMPP_QUERY_RESP */
78 /* TODO implement CMPP_QUERY and CMPP_QUERY_RESP */
80 /* CMPP_DELIVER */
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;
95 /* Msg_Id field */
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" },
172 { 0, NULL }
175 static const value_string vals_connect_resp_status[] = { /* Connection Status */
176 { 0, "Correct" },
177 { 1, "Message structure error" },
178 { 2, "Illegal source address" },
179 { 3, "Authenticate error" },
180 { 4, "Version too high" },
181 { 0, NULL }
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" },
189 { 0, NULL }
192 static const value_string vals_Msg_Fmt[] = { /* Message Format */
193 { 0, "ASCII" },
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" },
198 { 0, NULL }
201 /* Submit Response Result */
202 static const value_string vals_Submit_Resp_Result[] = {
203 { 0, "Correct" },
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" },
217 { 0, NULL }
220 /* Deliver Response Result */
221 static const value_string vals_Deliver_Resp_Result[] = {
222 { 0, "Correct" },
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 { 0, NULL }
234 /* Initialize the subtree pointers */
235 static int ett_cmpp;
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);
247 return display;
250 static char*
251 cmpp_version(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
253 int8_t version, major, minor;
254 char *strval;
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);
262 return strval;
265 static char*
266 cmpp_timestamp(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
268 int8_t month, day, hour, minute, second;
269 int32_t timevalue;
270 char *strval;
272 timevalue = tvb_get_ntohl(tvb, offset);
273 second = timevalue % 100;
274 timevalue /= 100;
275 minute = timevalue % 100;
276 timevalue /= 100;
277 hour = timevalue % 100;
278 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);
284 return 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().
290 static uint8_t
291 cmpp_uint1(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
293 uint8_t value;
294 value = tvb_get_uint8(tvb, offset);
295 proto_tree_add_uint(tree, field, tvb, offset, 1, value);
296 return value;
299 static uint16_t
300 cmpp_uint2(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
302 uint16_t value;
303 value = tvb_get_ntohs(tvb, offset);
304 proto_tree_add_uint(tree, field, tvb, offset, 2, value);
305 return value;
308 static int32_t
309 cmpp_uint4(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
311 int32_t value;
312 value = tvb_get_ntohl(tvb, offset);
313 proto_tree_add_uint(tree, field, tvb, offset, 4, value);
314 return value;
317 static bool
318 cmpp_boolean(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
320 int8_t value;
321 value = tvb_get_uint8(tvb, offset);
322 proto_tree_add_boolean(tree, field, tvb, offset, 1, value);
323 if (value == 1)
324 return true;
325 return false;
328 static void
329 cmpp_msg_id(proto_tree *tree, tvbuff_t *tvb, int field, int offset)
331 uint8_t month,day,hour,minute,second;
332 uint32_t ismg_code;
333 proto_item *pi;
334 proto_tree *sub_tree;
335 char *strval;
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);
355 static void
356 cmpp_connect(proto_tree *tree, tvbuff_t *tvb)
358 int offset;
359 offset = CMPP_FIX_HEADER_LENGTH;
360 cmpp_octet_string(tree, tvb, hf_cmpp_connect_Source_Addr, offset, 6);
361 offset += 6;
362 proto_tree_add_string(tree, hf_cmpp_connect_AuthenticatorSource, tvb, offset, 16, "MD5 Hash");
363 offset += 16;
364 cmpp_version(tree, tvb, hf_cmpp_Version, offset);
365 offset += 1;
366 cmpp_timestamp(tree, tvb, hf_cmpp_connect_Timestamp, offset);
370 static void
371 cmpp_connect_resp(proto_tree *tree, tvbuff_t *tvb)
373 int offset;
374 offset = CMPP_FIX_HEADER_LENGTH;
375 cmpp_uint4(tree, tvb, hf_cmpp_connect_resp_status, offset);
376 offset += 4;
377 proto_tree_add_string(tree, hf_cmpp_connect_resp_AuthenticatorISMG, tvb, offset, 16, "MD5 Hash");
378 offset += 16;
379 cmpp_version(tree, tvb, hf_cmpp_Version, offset);
382 static void
383 cmpp_submit(proto_tree *tree, tvbuff_t *tvb)
385 int offset, i;
386 uint8_t destUsr, msgLen;
387 offset = CMPP_FIX_HEADER_LENGTH;
388 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
389 offset += 8;
390 cmpp_uint1(tree, tvb, hf_cmpp_submit_pk_total, offset);
391 offset++;
392 cmpp_uint1(tree, tvb, hf_cmpp_submit_pk_number, offset);
393 offset++;
394 cmpp_boolean(tree, tvb, hf_cmpp_submit_Registered_Delivery, offset);
395 offset++;
396 cmpp_uint1(tree, tvb, hf_cmpp_submit_Msg_level, offset);
397 offset++;
398 cmpp_octet_string(tree, tvb, hf_cmpp_Service_Id, offset, 10);
399 offset += 10;
400 cmpp_uint1(tree, tvb, hf_cmpp_submit_Fee_UserType, offset);
401 offset++;
402 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Fee_terminal_Id, offset, 32);
403 offset+=32;
404 cmpp_boolean(tree, tvb, hf_cmpp_submit_Fee_terminal_type, offset);
405 offset++;
406 cmpp_uint1(tree, tvb, hf_cmpp_TP_pId, offset);
407 offset++;
408 cmpp_uint1(tree, tvb, hf_cmpp_TP_udhi, offset);
409 offset++;
410 cmpp_uint1(tree, tvb, hf_cmpp_Msg_Fmt, offset);
411 offset++;
412 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Msg_src, offset, 6);
413 offset += 6;
414 cmpp_octet_string(tree, tvb, hf_cmpp_submit_FeeType, offset, 2);
415 offset += 2;
416 cmpp_octet_string(tree, tvb, hf_cmpp_submit_FeeCode, offset, 6);
417 offset += 6;
419 /* TODO create function to handle SMPP time format */
420 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Valld_Time, offset, 17);
421 offset += 17;
422 cmpp_octet_string(tree, tvb, hf_cmpp_submit_At_Time, offset, 17);
423 offset += 17;
425 cmpp_octet_string(tree, tvb, hf_cmpp_submit_Src_Id, offset, 17);
426 offset += 21;
427 destUsr = cmpp_uint1(tree, tvb, hf_cmpp_submit_DestUsr_tl, offset);
428 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);
434 offset += 32;
437 cmpp_boolean(tree, tvb, hf_cmpp_submit_Dest_terminal_type, offset);
438 offset++;
439 msgLen = cmpp_uint1(tree, tvb, hf_cmpp_Msg_Length, offset);
440 offset++;
441 proto_tree_add_string(tree, hf_cmpp_Msg_Content, tvb, offset, msgLen, "SMS Messages");
442 offset += msgLen;
443 cmpp_octet_string(tree, tvb, hf_cmpp_LinkID, offset, 20);
446 static void
447 cmpp_submit_resp(proto_tree *tree, tvbuff_t *tvb)
449 int offset;
450 offset = CMPP_FIX_HEADER_LENGTH;
451 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
452 offset += 8;
453 cmpp_uint4(tree, tvb, hf_cmpp_submit_resp_Result, offset);
456 static void
457 cmpp_deliver_report(proto_tree *tree, tvbuff_t *tvb, int field, unsigned offset)
459 proto_item *pi;
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);
465 offset += 8;
466 cmpp_octet_string(sub_tree, tvb, hf_cmpp_deliver_Report_Stat, offset, 7);
467 offset += 7;
468 cmpp_octet_string(sub_tree, tvb, hf_cmpp_deliver_Report_Submit_time, offset, 10);
469 offset += 10;
470 cmpp_octet_string(sub_tree, tvb, hf_cmpp_deliver_Report_Done_time, offset, 10);
471 offset += 10;
472 cmpp_octet_string(sub_tree, tvb, hf_cmpp_Dest_terminal_Id, offset, 32);
473 offset += 32;
474 cmpp_uint4(sub_tree, tvb, hf_cmpp_deliver_Report_SMSC_sequence, offset);
477 static void
478 cmpp_deliver(proto_tree *tree, tvbuff_t *tvb)
480 unsigned offset, msgLen;
481 bool report;
482 offset = CMPP_FIX_HEADER_LENGTH;
483 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
484 offset += 8;
485 cmpp_octet_string(tree, tvb, hf_cmpp_deliver_Dest_Id, offset, 21);
486 offset += 21;
487 cmpp_octet_string(tree, tvb, hf_cmpp_Service_Id, offset, 10);
488 offset += 10;
489 cmpp_uint1(tree, tvb, hf_cmpp_TP_pId, offset);
490 offset++;
491 cmpp_uint1(tree, tvb, hf_cmpp_TP_udhi, offset);
492 offset++;
493 cmpp_uint1(tree, tvb, hf_cmpp_Msg_Fmt, offset);
494 offset++;
495 cmpp_octet_string(tree, tvb, hf_cmpp_deliver_Src_terminal_Id, offset, 32);
496 offset += 32;
497 cmpp_boolean(tree, tvb, hf_cmpp_deliver_Src_terminal_type, offset);
498 offset++;
499 report = cmpp_boolean(tree, tvb, hf_cmpp_deliver_Registered_Delivery, offset);
500 offset++;
501 msgLen = cmpp_uint1(tree, tvb, hf_cmpp_Msg_Length, offset);
502 offset++;
503 if (report == false)
504 proto_tree_add_string(tree, hf_cmpp_Msg_Content, tvb, offset, msgLen, "SMS Messages");
505 else
506 cmpp_deliver_report(tree, tvb, hf_cmpp_deliver_Report, offset);
507 offset += msgLen;
508 cmpp_octet_string(tree, tvb, hf_cmpp_LinkID, offset, 20);
511 static void
512 cmpp_deliver_resp(proto_tree *tree, tvbuff_t *tvb)
514 int offset;
515 offset = CMPP_FIX_HEADER_LENGTH;
516 cmpp_msg_id(tree, tvb, hf_cmpp_msg_id, offset);
517 offset += 8;
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 */
523 static int
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 */
528 proto_item *ti;
529 proto_tree *cmpp_tree;
530 unsigned command_id;
531 unsigned tvb_len;
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)
539 return 0;
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() */
547 return 0;
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 */
557 return 0;
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);
565 if (tree)
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);
576 switch(command_id)
578 case CMPP_CONNECT:
579 cmpp_connect(cmpp_tree, tvb);
580 break;
581 case CMPP_CONNECT_RESP:
582 cmpp_connect_resp(cmpp_tree, tvb);
583 break;
584 /* CMPP_TERMINATE and CMPP_TERMINATE_RESP don't have msg body */
585 case CMPP_TERMINATE:
586 case CMPP_TERMINATE_RESP:
587 break;
588 case CMPP_SUBMIT:
589 cmpp_submit(cmpp_tree, tvb);
590 break;
591 case CMPP_SUBMIT_RESP:
592 cmpp_submit_resp(cmpp_tree, tvb);
593 break;
594 case CMPP_DELIVER:
595 cmpp_deliver(cmpp_tree, tvb);
596 break;
597 case CMPP_DELIVER_RESP:
598 cmpp_deliver_resp(cmpp_tree, tvb);
599 break;
600 default:
601 /* Implement the rest of the protocol here */
602 break;
606 return tvb_reported_length(tvb);
610 /* Get the CMPP PDU Length */
611 static unsigned
612 get_cmpp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
614 return tvb_get_ntohl(tvb, offset);
618 static int
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)
625 return 0;
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)
636 return 0;
638 if (try_val_to_str(command_id, vals_command_Id) == NULL)
639 return 0;
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 */
653 void
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.",
662 HFILL }
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",
668 HFILL }
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",
674 HFILL }
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",
680 HFILL }
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)",
686 HFILL }
689 { &hf_cmpp_Version,
690 { "Version", "cmpp.Version",
691 FT_STRING, BASE_NONE, NULL, 0x00,
692 "CMPP Version",
693 HFILL }
695 { &hf_cmpp_connect_Timestamp,
696 { "Timestamp", "cmpp.connect.Timestamp",
697 FT_STRING, BASE_NONE, NULL, 0x00,
698 "Timestamp MM/DD HH:MM:SS",
699 HFILL }
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",
705 HFILL }
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)",
711 HFILL }
713 { &hf_cmpp_msg_id,
714 { "Msg_Id", "cmpp.Msg_Id",
715 FT_UINT64, BASE_HEX, NULL, 0x00,
716 "Message ID",
717 HFILL }
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",
723 HFILL }
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",
729 HFILL }
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",
735 HFILL }
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",
741 HFILL }
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",
747 HFILL }
749 { &hf_cmpp_submit_Registered_Delivery,
750 { "Registered Delivery", "cmpp.submit.Registered_Delivery",
751 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
752 "Registered Delivery flag",
753 HFILL }
755 { &hf_cmpp_submit_Msg_level,
756 { "Message Level", "cmpp.submit.Msg_level",
757 FT_UINT8, BASE_DEC, NULL, 0x00,
758 NULL,
759 HFILL }
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",
765 HFILL }
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",
771 HFILL }
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",
777 HFILL }
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",
783 HFILL }
785 { &hf_cmpp_TP_pId,
786 { "TP pId", "cmpp.TP_pId",
787 FT_UINT8, BASE_DEC, NULL, 0x00,
788 "GSM TP pId Field",
789 HFILL }
791 { &hf_cmpp_TP_udhi,
792 { "TP udhi", "cmpp.TP_udhi",
793 FT_UINT8, BASE_DEC, NULL, 0x00,
794 "GSM TP udhi field",
795 HFILL }
797 { &hf_cmpp_Msg_Fmt,
798 { "Message Format", "cmpp.Msg_Fmt",
799 FT_UINT8, BASE_DEC, VALS(vals_Msg_Fmt), 0x00,
800 NULL,
801 HFILL }
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",
807 HFILL }
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,
812 NULL,
813 HFILL }
815 { &hf_cmpp_submit_FeeCode,
816 { "Fee Code", "cmpp.submit.FeeCode",
817 FT_STRING, BASE_NONE, NULL, 0x00,
818 NULL,
819 HFILL }
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",
825 HFILL }
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",
831 HFILL }
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",
837 HFILL }
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",
843 HFILL }
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",
849 HFILL }
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",
855 HFILL }
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",
861 HFILL }
863 { &hf_cmpp_Msg_Content,
864 { "Message Content", "cmpp.Msg_Content",
865 FT_STRING, BASE_NONE, NULL, 0x00,
866 NULL,
867 HFILL }
869 { &hf_cmpp_LinkID,
870 { "Link ID", "cmpp.LinkID",
871 FT_STRING, BASE_NONE, NULL, 0x00,
872 NULL,
873 HFILL }
875 { &hf_cmpp_submit_resp_Result,
876 { "Result", "cmpp.submit_resp.Result",
877 FT_UINT32, BASE_DEC, VALS(vals_Submit_Resp_Result), 0x00,
878 "Submit Result",
879 HFILL }
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",
885 HFILL }
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",
891 HFILL }
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)",
897 HFILL }
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",
903 HFILL }
905 { &hf_cmpp_deliver_Report,
906 { "Detail Deliver Report", "cmpp.deliver.Report",
907 FT_NONE, BASE_NONE, NULL, 0x00,
908 "The detail report",
909 HFILL }
911 { &hf_cmpp_deliver_Report_Stat,
912 { "Deliver Status", "cmpp.deliver.Report.Status",
913 FT_STRING, BASE_NONE, NULL, 0x00,
914 NULL,
915 HFILL }
917 { &hf_cmpp_deliver_Report_Submit_time,
918 { "Submit_time", "cmpp.deliver.Report.Submit_time",
919 FT_STRING, BASE_NONE, NULL, 0x00,
920 "Format YYMMDDHHMM",
921 HFILL }
923 { &hf_cmpp_deliver_Report_Done_time,
924 { "Done_time", "cmpp.deliver.Report.Done_time",
925 FT_STRING, BASE_NONE, NULL, 0x00,
926 "Format YYMMDDHHMM",
927 HFILL }
929 { &hf_cmpp_deliver_Report_SMSC_sequence,
930 { "SMSC_sequence", "cmpp.Report.SMSC_sequence",
931 FT_UINT32, BASE_DEC, NULL, 0x00,
932 "Sequence number",
933 HFILL }
935 { &hf_cmpp_deliver_resp_Result,
936 { "Result", "cmpp.deliver_resp.Result",
937 FT_UINT32, BASE_DEC, VALS(vals_Deliver_Resp_Result), 0x00,
938 "Deliver Result",
939 HFILL }
943 /* Setup protocol subtree array */
944 static int *ett[] = {
945 &ett_cmpp,
946 &ett_msg_id,
947 &ett_deliver_report,
950 /* Register the protocol name and description */
951 proto_cmpp = proto_register_protocol("China Mobile Point to Point Protocol",
952 "CMPP", "cmpp");
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);
962 void
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
971 * Local variables:
972 * c-basic-offset: 8
973 * tab-width: 8
974 * indent-tabs-mode: t
975 * End:
977 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
978 * :indentSize=8:tabSize=8:noTabs=false: