HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-cimd.c
blob99074c398636961b1deacbb769792c5cdf4fa2b4
1 /* packet-cimd.c
3 * Routines for Computer Interface to Message Distribution (CIMD) version 2 dissection
5 * Copyright : 2005 Viorel Suman <vsuman[AT]avmob.ro>, Lucian Piros <lpiros[AT]avmob.ro>
6 * In association with Avalanche Mobile BV, http://www.avmob.com
8 * $Id$
10 * Refer to the AUTHORS file or the AUTHORS section in the man page
11 * for contacting the author(s) of this file.
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include "config.h"
33 #include <glib.h>
35 #include <epan/packet.h>
36 #include <epan/to_str.h>
37 #include <epan/wmem/wmem.h>
39 #define CIMD_STX 0x02 /* Start of CIMD PDU */
40 #define CIMD_ETX 0x03 /* End of CIMD PDU */
41 #define CIMD_COLON 0x3A /* CIMD colon */
42 #define CIMD_DELIM 0x09 /* CIMD Delimiter */
44 #define CIMD_OC_OFFSET 1 /* CIMD Operation Code Offset */
45 #define CIMD_OC_LENGTH 2 /* CIMD Operation Code Length */
46 #define CIMD_PN_OFFSET 4 /* CIMD Packet Number Offset */
47 #define CIMD_PN_LENGTH 3 /* CIMD Packet Number Length */
48 #define CIMD_PC_LENGTH 3 /* CIMD Parameter Code Length */
49 #define CIMD_MIN_LENGTH 9 /* CIMD Minimal packet length : STX(1) + OC(2) + COLON(1) + PN(3) + DELIM(1) + ETX(1)*/
51 /* define CIMD2 operation code */
53 #define CIMD_Login 1
54 #define CIMD_LoginResp 51
55 #define CIMD_Logout 2
56 #define CIMD_LogoutResp 52
57 #define CIMD_SubmitMessage 3
58 #define CIMD_SubmitMessageResp 53
59 #define CIMD_EnqMessageStatus 4
60 #define CIMD_EnqMessageStatusResp 54
61 #define CIMD_DeliveryRequest 5
62 #define CIMD_DeliveryRequestResp 55
63 #define CIMD_CancelMessage 6
64 #define CIMD_CancelMessageResp 56
65 #define CIMD_SetMessage 8
66 #define CIMD_SetMessageResp 58
67 #define CIMD_GetMessage 9
68 #define CIMD_GetMessageResp 59
69 #define CIMD_Alive 40
70 #define CIMD_AliveResp 90
71 #define CIMD_GeneralErrorResp 98
72 #define CIMD_NACK 99
73 /* SC2App */
74 #define CIMD_DeliveryMessage 20
75 #define CIMD_DeliveryMessageResp 70
76 #define CIMD_DeliveryStatusReport 23
77 #define CIMD_DeliveryStatusReportResp 73
79 /* define CIMD2 operation's parameter codes */
81 #define CIMD_UserIdentity 10
82 #define CIMD_Password 11
83 #define CIMD_Subaddress 12
84 #define CIMD_WindowSize 19
85 #define CIMD_DestinationAddress 21
86 #define CIMD_OriginatingAddress 23
87 #define CIMD_OriginatingImsi 26
88 #define CIMD_AlphaOriginatingAddr 27
89 #define CIMD_OriginatedVisitedMSCAd 28
90 #define CIMD_DataCodingScheme 30
91 #define CIMD_UserDataHeader 32
92 #define CIMD_UserData 33
93 #define CIMD_UserDataBinary 34
94 #define CIMD_MoreMessagesToSend 44
95 #define CIMD_ValidityPeriodRelative 50
96 #define CIMD_ValidityPeriodAbsolute 51
97 #define CIMD_ProtocolIdentifier 52
98 #define CIMD_FirstDeliveryTimeRel 53
99 #define CIMD_FirstDeliveryTimeAbs 54
100 #define CIMD_ReplyPath 55
101 #define CIMD_StatusReportRequest 56
102 #define CIMD_CancelEnabled 58
103 #define CIMD_CancelMode 59
104 #define CIMD_SCTimeStamp 60
105 #define CIMD_StatusCode 61
106 #define CIMD_StatusErrorCode 62
107 #define CIMD_DischargeTime 63
108 #define CIMD_TariffClass 64
109 #define CIMD_ServiceDescription 65
110 #define CIMD_MessageCount 66
111 #define CIMD_Priority 67
112 #define CIMD_DeliveryRequestMode 68
113 #define CIMD_SCAddress 69
114 #define CIMD_GetParameter 500
115 #define CIMD_SMSCTime 501
116 #define CIMD_ErrorCode 900
117 #define CIMD_ErrorText 901
119 #define MAXPARAMSCOUNT 37
121 typedef struct cimd_parameter_t cimd_parameter_t;
123 typedef void (*cimd_pdissect)(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset);
125 struct cimd_parameter_t {
126 cimd_pdissect diss;
127 gint *ett_p;
128 gint *hf_p;
131 void proto_register_cimd(void);
132 void proto_reg_handoff_cimd(void);
133 static void dissect_cimd_parameter(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset);
134 static void dissect_cimd_ud(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset);
135 static void dissect_cimd_dcs(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset);
137 static int proto_cimd = -1;
138 /* Initialize the subtree pointers */
139 static gint ett_cimd = -1;
141 /* Initialize the protocol and registered fields */
142 static int hf_cimd_opcode_indicator = -1;
143 static int hf_cimd_packet_number_indicator = -1;
144 static int hf_cimd_checksum_indicator = -1;
145 static int hf_cimd_pcode_indicator = -1;
147 static int hf_cimd_dcs_coding_group_indicator = -1;
148 static int hf_cimd_dcs_compressed_indicator = -1;
149 static int hf_cimd_dcs_message_class_meaning_indicator = -1;
150 static int hf_cimd_dcs_message_class_indicator = -1;
151 static int hf_cimd_dcs_character_set_indicator = -1;
152 static int hf_cimd_dcs_indication_sense = -1;
153 static int hf_cimd_dcs_indication_type = -1;
155 static const value_string vals_hdr_OC[] = {
156 /* operation codes array */
157 {CIMD_Login, "Login"},
158 {CIMD_LoginResp, "Login Resp"},
159 {CIMD_Logout, "Logout"},
160 {CIMD_LogoutResp, "Logout Resp"},
161 {CIMD_SubmitMessage, "Submit message"},
162 {CIMD_SubmitMessageResp, "Submit message Resp"},
163 {CIMD_EnqMessageStatus, "Enquire message status"},
164 {CIMD_EnqMessageStatusResp, "Enquire message status Resp"},
165 {CIMD_DeliveryRequest, "Delivery request"},
166 {CIMD_DeliveryRequestResp, "Delivery request Resp"},
167 {CIMD_CancelMessage, "Cancel message"},
168 {CIMD_CancelMessageResp, "Cancel message Resp"},
169 {CIMD_SetMessage, "Set message"},
170 {CIMD_SetMessageResp, "Set message Resp"},
171 {CIMD_GetMessage, "Get message"},
172 {CIMD_GetMessageResp, "Get message Resp"},
173 {CIMD_Alive, "Alive"},
174 {CIMD_AliveResp, "Alive Resp"},
175 {CIMD_GeneralErrorResp, "General error Resp"},
176 {CIMD_NACK, "Nack"},
177 /* SC2App */
178 {CIMD_DeliveryMessage, "Deliver message"},
179 {CIMD_DeliveryMessageResp, "Deliver message Resp"},
180 {CIMD_DeliveryStatusReport, "Deliver status report"},
181 {CIMD_DeliveryStatusReportResp, "Deliver status report Resp"},
182 {0, NULL}
185 static const value_string cimd_vals_PC[] = {
186 /* parameter codes array */
187 {CIMD_UserIdentity, "User Identity"},
188 {CIMD_Password, "Password"},
189 {CIMD_Subaddress, "Subaddr"},
190 {CIMD_WindowSize, "Window Size"},
191 {CIMD_DestinationAddress, "Destination Address"},
192 {CIMD_OriginatingAddress, "Originating Address"},
193 {CIMD_OriginatingImsi, "Originating IMSI"},
194 {CIMD_AlphaOriginatingAddr, "Alphanumeric Originating Address"},
195 {CIMD_OriginatedVisitedMSCAd, "Originated Visited MSC Address"},
196 {CIMD_DataCodingScheme, "Data Coding Scheme"},
197 {CIMD_UserDataHeader, "User Data Header"},
198 {CIMD_UserData, "User Data"},
199 {CIMD_UserDataBinary, "User Data Binary"},
200 {CIMD_MoreMessagesToSend, "More Messages To Send"},
201 {CIMD_ValidityPeriodRelative, "Validity Period Relative"},
202 {CIMD_ValidityPeriodAbsolute, "Validity Period Absolute"},
203 {CIMD_ProtocolIdentifier, "Protocol Identifier"},
204 {CIMD_FirstDeliveryTimeRel, "First Delivery Time Relative"},
205 {CIMD_FirstDeliveryTimeAbs, "First Delivery Time Absolute"},
206 {CIMD_ReplyPath, "Reply Path"},
207 {CIMD_StatusReportRequest, "Status Report Request"},
208 {CIMD_CancelEnabled, "Cancel Enabled"},
209 {CIMD_CancelMode, "Cancel Mode"},
210 {CIMD_SCTimeStamp, "Service Centre Time Stamp"},
211 {CIMD_StatusCode, "Status Code"},
212 {CIMD_StatusErrorCode, "Status Error Code"},
213 {CIMD_DischargeTime, "Discharge Time"},
214 {CIMD_TariffClass, "Tariff Class"},
215 {CIMD_ServiceDescription, "Service Description"},
216 {CIMD_MessageCount, "Message Count"},
217 {CIMD_Priority, "Priority"},
218 {CIMD_DeliveryRequestMode, "Delivery Request Mode"},
219 {CIMD_SCAddress, "Service Center Address"},
220 {CIMD_GetParameter, "Get Parameter"},
221 {CIMD_SMSCTime, "SMS Center Time"},
222 {CIMD_ErrorCode, "Error Code"},
223 {CIMD_ErrorText, "Error Text"},
224 {0, NULL}
227 static const value_string cimd_dcs_coding_groups[] = {
228 {0x00, "General Data Coding indication"},
229 {0x01, "General Data Coding indication"},
230 {0x02, "General Data Coding indication"},
231 {0x03, "General Data Coding indication"},
232 {0x04, "Message Marked for Automatic Deletion Group"},
233 {0x05, "Message Marked for Automatic Deletion Group"},
234 {0x06, "Message Marked for Automatic Deletion Group"},
235 {0x07, "Message Marked for Automatic Deletion Group"},
236 {0x08, "Reserved coding group"},
237 {0x09, "Reserved coding group"},
238 {0x0A, "Reserved coding group"},
239 {0x0B, "Reserved coding group"},
240 {0x0C, "Message Waiting Indication Group: Discard Message (7-bit encoded)"},
241 {0x0D, "Message Waiting Indication Group: Store Message (7-bit encoded)"},
242 {0x0E, "Message Waiting Indication Group: Store Message (uncompressed UCS2 encoded)"},
243 {0x0F, "Data coding/message class"},
244 {0, NULL}
247 static const value_string cimd_dcs_compressed[] = {
248 {0x00, "Text is uncompressed"},
249 {0x01, "Text is compressed"},
250 {0, NULL}
253 static const value_string cimd_dcs_message_class_meaning[] = {
254 {0x00, "Reserved, bits 1 to 0 have no message class meaning"},
255 {0x01, "Bits 1 to 0 have message class meaning"},
256 {0, NULL}
259 static const value_string cimd_dcs_message_class[] = {
260 {0x00, "Class 0"},
261 {0x01, "Class 1 Default meaning: ME-specific"},
262 {0x02, "Class 2 (U)SIM specific message"},
263 {0x03, "Class 3 Default meaning: TE-specific"},
264 {0, NULL}
267 static const value_string cimd_dcs_character_set[] = {
268 {0x00, "GSM 7 bit default alphabet"},
269 {0x01, "8 bit data"},
270 {0x02, "UCS2 (16bit)"},
271 {0x03, "Reserved"},
272 {0, NULL}
275 static const value_string cimd_dcs_indication_sense[] = {
276 {0x00, "Set Indication Inactive"},
277 {0x01, "Set Indication Active"},
278 {0, NULL}
281 static const value_string cimd_dcs_indication_type[] = {
282 {0x00, "Voicemail Message Waiting"},
283 {0x01, "Fax Message Waiting"},
284 {0x02, "Electronic Mail Message Waiting"},
285 {0x03, "Other Message Waiting"},
286 {0, NULL}
289 static const cimd_pdissect cimd_pc_handles[] = {
290 /* function handles for parsing cimd parameters */
291 dissect_cimd_parameter,
292 dissect_cimd_parameter,
293 dissect_cimd_parameter,
294 dissect_cimd_parameter,
295 dissect_cimd_parameter,
296 dissect_cimd_parameter,
297 dissect_cimd_parameter,
298 dissect_cimd_parameter,
299 dissect_cimd_parameter,
300 dissect_cimd_dcs,
301 dissect_cimd_parameter,
302 dissect_cimd_ud,
303 dissect_cimd_parameter,
304 dissect_cimd_parameter,
305 dissect_cimd_parameter,
306 dissect_cimd_parameter,
307 dissect_cimd_parameter,
308 dissect_cimd_parameter,
309 dissect_cimd_parameter,
310 dissect_cimd_parameter,
311 dissect_cimd_parameter,
312 dissect_cimd_parameter,
313 dissect_cimd_parameter,
314 dissect_cimd_parameter,
315 dissect_cimd_parameter,
316 dissect_cimd_parameter,
317 dissect_cimd_parameter,
318 dissect_cimd_parameter,
319 dissect_cimd_parameter,
320 dissect_cimd_parameter,
321 dissect_cimd_parameter,
322 dissect_cimd_parameter,
323 dissect_cimd_parameter,
324 dissect_cimd_parameter,
325 dissect_cimd_parameter,
326 dissect_cimd_parameter,
327 dissect_cimd_parameter
330 /* Parameters */
331 static cimd_parameter_t vals_hdr_PC[MAXPARAMSCOUNT + 1];
332 static gint ett_index[MAXPARAMSCOUNT];
333 static gint hf_index[MAXPARAMSCOUNT];
336 * Convert ASCII-hex character to binary equivalent. No checks, assume
337 * is valid hex character.
339 #define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F))
341 static guint
342 decimal_int_value(tvbuff_t *tvb, int offset, int length)
344 guint value = 0;
345 int i;
347 for (i=0; i<length; i++, offset++)
349 value = 10 * value + tvb_get_guint8(tvb, offset) - '0';
351 return value;
354 static void dissect_cimd_parameter(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset)
356 /* Set up structures needed to add the param subtree and manage it */
357 proto_item *param_item = NULL;
358 proto_tree *param_tree = NULL;
360 param_item = proto_tree_add_text(tree, tvb,
361 startOffset + 1, endOffset - (startOffset + 1),
362 "%s", cimd_vals_PC[pindex].strptr
364 param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p));
365 proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb,
366 startOffset + 1, CIMD_PC_LENGTH,
367 tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH)
369 proto_tree_add_string(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb,
370 startOffset + 1 + CIMD_PC_LENGTH + 1, endOffset - (startOffset + 1 + CIMD_PC_LENGTH + 1),
371 tvb_format_text(tvb, startOffset + 1 + CIMD_PC_LENGTH + 1, endOffset - (startOffset + 1 + CIMD_PC_LENGTH + 1))
375 static void dissect_cimd_ud(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset)
377 /* Set up structures needed to add the param subtree and manage it */
378 proto_item *param_item;
379 proto_tree *param_tree;
381 gchar *payloadText, *tmpBuffer, *tmpBuffer1;
382 int loop,i,poz, bufPoz = 0, bufPoz1 = 0, size, size1, resch;
383 gint g_offset, g_size;
384 gchar token[4];
385 gchar ch;
386 static const char* mapping[128] = {
387 "_Oa" , "_L-", "" , "_Y-", "_e`", "_e'", "_u`", "_i`", "_o`", "_C,", /*10*/
388 "" , "_O/", "_o/" , "" , "_A*", "_a*", "_gd", "_--", "_gf", "_gg", "_gl", /*21*/
389 "_go" , "_gp", "_gi" , "_gs", "_gt", "_gx", "_XX", "_AE", "_ae", "_ss", "_E'", /*32*/
390 "" , "" , "_qq" , "" , "_ox", "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "",
391 "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "",
392 "_!!" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "",
393 "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "_A\"", "_O\"", "_N~",
394 "_U\"", "_so", "_??" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
395 "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "", "_a\"",
396 "_o\"", "_n~", "_n\"","_a`"
399 param_item = proto_tree_add_text(tree, tvb,
400 startOffset + 1, endOffset - (startOffset + 1),
401 "%s", cimd_vals_PC[pindex].strptr
403 param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p));
404 proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb,
405 startOffset + 1, CIMD_PC_LENGTH, tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH)
408 g_offset = startOffset + 1 + CIMD_PC_LENGTH + 1;
409 g_size = endOffset - g_offset;
411 payloadText = tvb_format_text(tvb, g_offset, g_size);
412 size = (int)strlen(payloadText);
413 tmpBuffer = (gchar*)wmem_alloc(wmem_packet_scope(), size+1);
414 for (loop = 0; loop < size; loop++)
416 if (payloadText[loop] == '_')
418 if (loop < size - 2)
420 token[0] = payloadText[loop++];
421 token[1] = payloadText[loop++];
422 token[2] = payloadText[loop];
423 token[3] = '\0';
424 poz = -1;
425 for (i = 0; i < 128; i++)
427 if (strcmp(token, mapping[i]) == 0)
429 poz = i;
430 break;
433 if (poz > 0)
435 tmpBuffer[bufPoz++] = poz;
437 else
439 tmpBuffer[bufPoz++] = payloadText[loop-2];
440 tmpBuffer[bufPoz++] = payloadText[loop-1];
441 tmpBuffer[bufPoz++] = payloadText[loop];
444 else
446 if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++];
447 if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++];
448 if (loop < size) tmpBuffer[bufPoz++] = payloadText[loop++];
451 else
453 tmpBuffer[bufPoz++] = payloadText[loop];
456 tmpBuffer[bufPoz] = '\0';
458 size1 = (int)strlen(tmpBuffer);
459 tmpBuffer1 = (gchar*)wmem_alloc(wmem_packet_scope(), size1+1);
460 for (loop=0; loop<size1; loop++)
462 ch = tmpBuffer[loop];
463 switch ((gint)ch)
465 case 0x40: resch = 0x0040; break;
466 case 0x01: resch = 0x00A3; break;
467 case 0x02: resch = 0x0024; break;
468 case 0x03: resch = 0x00A5; break;
469 case 0x04: resch = 0x00E8; break;
470 case 0x05: resch = 0x00E9; break;
471 case 0x06: resch = 0x00F9; break;
472 case 0x07: resch = 0x00EC; break;
473 case 0x08: resch = 0x00F2; break;
474 case 0x09: resch = 0x00E7; break;
475 case 0x0B: resch = 0x00D8; break;
476 case 0x0C: resch = 0x00F8; break;
477 case 0x0E: resch = 0x00C5; break;
478 case 0x0F: resch = 0x00E5; break;
479 case 0x11: resch = 0x005F; break;
480 /* case 0x1B14: resch = 0x005E; break; */
481 /* case 0x1B28: resch = 0x007B; break; */
482 /* case 0x1B29: resch = 0x007D; break; */
483 /* case 0x1B2F: resch = 0x005C; break; */
484 /* case 0x1B3C: resch = 0x005B; break; */
485 /* case 0x1B3D: resch = 0x007E; break; */
486 /* case 0x1B3E: resch = 0x005D; break; */
487 /* case 0x1B40: resch = 0x007C; break; */
488 case 0x1C: resch = 0x00C6; break;
489 case 0x1D: resch = 0x00E6; break;
490 case 0x1E: resch = 0x00DF; break;
491 case 0x1F: resch = 0x00C9; break;
492 case 0x20: resch = 0x0020; break;
493 case 0x21: resch = 0x0021; break;
494 case 0x22: resch = 0x0022; break;
495 case 0x23: resch = 0x0023; break;
496 case 0xA4: resch = 0x00A4; break;
497 case 0x25: resch = 0x0025; break;
498 case 0x26: resch = 0x0026; break;
499 case 0x27: resch = 0x0027; break;
500 case 0x28: resch = 0x0028; break;
501 case 0x29: resch = 0x0029; break;
502 case 0x2A: resch = 0x002A; break;
503 case 0x2B: resch = 0x002B; break;
504 case 0x2C: resch = 0x002C; break;
505 case 0x2D: resch = 0x002D; break;
506 case 0x2E: resch = 0x002E; break;
507 case 0x2F: resch = 0x002F; break;
508 case 0x30: resch = 0x0030; break;
509 case 0x31: resch = 0x0031; break;
510 case 0x32: resch = 0x0032; break;
511 case 0x33: resch = 0x0033; break;
512 case 0x34: resch = 0x0034; break;
513 case 0x35: resch = 0x0035; break;
514 case 0x36: resch = 0x0036; break;
515 case 0x37: resch = 0x0037; break;
516 case 0x38: resch = 0x0038; break;
517 case 0x39: resch = 0x0039; break;
518 case 0x3A: resch = 0x003A; break;
519 case 0x3B: resch = 0x003B; break;
520 case 0x3C: resch = 0x003C; break;
521 case 0x3D: resch = 0x003D; break;
522 case 0x3E: resch = 0x003E; break;
523 case 0x3F: resch = 0x003F; break;
524 /* case 0x40: resch = 0x00A1; break; */
525 case 0x41: resch = 0x0041; break;
526 case 0x42: resch = 0x0042; break;
527 /* case 0x42: resch = 0x0392; break; */
528 case 0x43: resch = 0x0043; break;
529 case 0x44: resch = 0x0044; break;
530 case 0x45: resch = 0x0045; break;
531 case 0x46: resch = 0x0046; break;
532 case 0x47: resch = 0x0047; break;
533 case 0x48: resch = 0x0048; break;
534 case 0x49: resch = 0x0049; break;
535 case 0x4A: resch = 0x004A; break;
536 case 0x4B: resch = 0x004B; break;
537 case 0x4C: resch = 0x004C; break;
538 case 0x4D: resch = 0x004D; break;
539 case 0x4E: resch = 0x004E; break;
540 case 0x4F: resch = 0x004F; break;
541 case 0x50: resch = 0x0050; break;
542 case 0x51: resch = 0x0051; break;
543 case 0x52: resch = 0x0052; break;
544 case 0x53: resch = 0x0053; break;
545 case 0x54: resch = 0x0054; break;
546 case 0x55: resch = 0x0055; break;
547 case 0x56: resch = 0x0056; break;
548 case 0x57: resch = 0x0057; break;
549 case 0x58: resch = 0x0058; break;
550 case 0x59: resch = 0x0059; break;
551 case 0x5A: resch = 0x005A; break;
552 case 0x5B: resch = 0x00C4; break;
553 case 0x5C: resch = 0x00D6; break;
554 case 0x5D: resch = 0x00D1; break;
555 case 0x5E: resch = 0x00DC; break;
556 case 0x5F: resch = 0x00A7; break;
557 case 0x60: resch = 0x00BF; break;
558 case 0x61: resch = 0x0061; break;
559 case 0x62: resch = 0x0062; break;
560 case 0x63: resch = 0x0063; break;
561 case 0x64: resch = 0x0064; break;
562 case 0x65: resch = 0x0065; break;
563 case 0x66: resch = 0x0066; break;
564 case 0x67: resch = 0x0067; break;
565 case 0x68: resch = 0x0068; break;
566 case 0x69: resch = 0x0069; break;
567 case 0x6A: resch = 0x006A; break;
568 case 0x6B: resch = 0x006B; break;
569 case 0x6C: resch = 0x006C; break;
570 case 0x6D: resch = 0x006D; break;
571 case 0x6E: resch = 0x006E; break;
572 case 0x6F: resch = 0x006F; break;
573 case 0x70: resch = 0x0070; break;
574 case 0x71: resch = 0x0071; break;
575 case 0x72: resch = 0x0072; break;
576 case 0x73: resch = 0x0073; break;
577 case 0x74: resch = 0x0074; break;
578 case 0x75: resch = 0x0075; break;
579 case 0x76: resch = 0x0076; break;
580 case 0x77: resch = 0x0077; break;
581 case 0x78: resch = 0x0078; break;
582 case 0x79: resch = 0x0079; break;
583 case 0x7A: resch = 0x007A; break;
584 case 0x7B: resch = 0x00E4; break;
585 case 0x7C: resch = 0x00F6; break;
586 case 0x7D: resch = 0x00F1; break;
587 case 0x7F: resch = 0x00E0; break;
588 default:resch = ch; break;
590 tmpBuffer1[bufPoz1++] = (gchar)resch;
593 tmpBuffer1[bufPoz1] = '\0';
594 proto_tree_add_string(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, g_offset, g_size, tmpBuffer1);
597 static void dissect_cimd_dcs(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset)
599 /* Set up structures needed to add the param subtree and manage it */
600 proto_item *param_item;
601 proto_tree *param_tree;
602 gint offset;
603 guint dcs;
604 guint dcs_cg; /* coding group */
605 guint dcs_cf; /* compressed flag */
606 guint dcs_mcm; /* message class meaning flag */
607 guint dcs_chs; /* character set */
608 guint dcs_mc; /* message class */
609 guint dcs_is; /* indication sense */
610 guint dcs_it; /* indication type */
612 gchar* bigbuf = (gchar*)wmem_alloc(wmem_packet_scope(), 1024);
614 param_item = proto_tree_add_text(tree, tvb,
615 startOffset + 1, endOffset - (startOffset + 1),
616 "%s", cimd_vals_PC[pindex].strptr
618 param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p));
619 proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb,
620 startOffset + 1, CIMD_PC_LENGTH,
621 tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH)
624 offset = startOffset + 1 + CIMD_PC_LENGTH + 1;
625 dcs = decimal_int_value(tvb, offset, endOffset - offset);
626 proto_tree_add_uint(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, offset, endOffset - offset, dcs);
628 dcs_cg = (dcs & 0xF0) >> 4;
629 other_decode_bitfield_value(bigbuf, dcs, (dcs_cg <= 0x07 ? 0xC0 : 0xF0), 8);
630 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_coding_group_indicator, tvb, offset, 1,
631 dcs_cg, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_coding_group_indicator)->name,
632 val_to_str(dcs_cg, cimd_dcs_coding_groups, "Unknown (%d)"), dcs_cg
635 if (dcs_cg <= 0x07)
637 dcs_cf = (dcs & 0x20) >> 5;
638 other_decode_bitfield_value(bigbuf, dcs, 0x20, 8);
639 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_compressed_indicator, tvb, offset, 1,
640 dcs_cf, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_compressed_indicator)->name,
641 val_to_str(dcs_cf, cimd_dcs_compressed, "Unknown (%d)"), dcs_cf
644 dcs_mcm = (dcs & 0x10) >> 4;
645 other_decode_bitfield_value(bigbuf, dcs, 0x10, 8);
646 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_meaning_indicator, tvb, offset, 1,
647 dcs_mcm, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_meaning_indicator)->name,
648 val_to_str(dcs_mcm, cimd_dcs_message_class_meaning, "Unknown (%d)"), dcs_mcm
651 dcs_chs = (dcs & 0x0C) >> 2;
652 other_decode_bitfield_value(bigbuf, dcs, 0x0C, 8);
653 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_character_set_indicator, tvb, offset, 1,
654 dcs_chs, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_character_set_indicator)->name,
655 val_to_str(dcs_chs, cimd_dcs_character_set, "Unknown (%d)"), dcs_chs
658 if (dcs_mcm)
660 dcs_mc = (dcs & 0x03);
661 other_decode_bitfield_value(bigbuf, dcs, 0x03, 8);
662 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_indicator, tvb, offset, 1,
663 dcs_mc, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_indicator)->name,
664 val_to_str(dcs_mc, cimd_dcs_message_class, "Unknown (%d)"), dcs_mc
668 else if (dcs_cg >= 0x0C && dcs_cg <= 0x0E)
670 dcs_is = (dcs & 0x04) >> 2;
671 other_decode_bitfield_value(bigbuf, dcs, 0x04, 8);
672 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_indication_sense, tvb, offset, 1,
673 dcs_is, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_indication_sense)->name,
674 val_to_str(dcs_is, cimd_dcs_indication_sense, "Unknown (%d)"), dcs_is
677 dcs_it = (dcs & 0x03);
678 other_decode_bitfield_value(bigbuf, dcs, 0x03, 8);
679 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_indication_type, tvb, offset, 1,
680 dcs_it, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_indication_type)->name,
681 val_to_str(dcs_it, cimd_dcs_indication_type, "Unknown (%d)"), dcs_it
684 else if (dcs_cg == 0x0F)
686 dcs_chs = (dcs & 0x04) >> 2;
687 other_decode_bitfield_value(bigbuf, dcs, 0x04, 8);
688 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_character_set_indicator, tvb, offset, 1,
689 dcs_chs, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_character_set_indicator)->name,
690 val_to_str(dcs_chs, cimd_dcs_character_set, "Unknown (%d)"), dcs_chs
693 dcs_mc = (dcs & 0x03);
694 other_decode_bitfield_value(bigbuf, dcs, 0x03, 8);
695 proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_indicator, tvb, offset, 1,
696 dcs_mc, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_indicator)->name,
697 val_to_str(dcs_mc, cimd_dcs_message_class, "Unknown (%d)"), dcs_mc
702 static void
703 dissect_cimd_operation(tvbuff_t *tvb, proto_tree *tree, gint etxp, guint16 checksum, guint8 last1,guint8 OC, guint8 PN)
705 guint PC = 0; /* Parameter code */
706 gint idx;
707 gint offset = 0;
708 gint endOffset = 0;
709 proto_item *cimd_item = NULL;
710 proto_tree *cimd_tree = NULL;
712 if (tree)
714 /* create display subtree for the protocol */
715 cimd_item = proto_tree_add_item(tree, proto_cimd, tvb, 0, etxp + 1, ENC_NA);
716 cimd_tree = proto_item_add_subtree(cimd_item, ett_cimd);
717 proto_tree_add_uint(cimd_tree, hf_cimd_opcode_indicator, tvb, CIMD_OC_OFFSET, CIMD_OC_LENGTH, OC);
718 proto_tree_add_uint(cimd_tree, hf_cimd_packet_number_indicator, tvb, CIMD_PN_OFFSET, CIMD_PN_LENGTH, PN);
721 offset = CIMD_PN_OFFSET + CIMD_PN_LENGTH;
722 while (offset < etxp && tvb_get_guint8(tvb, offset) == CIMD_DELIM)
724 endOffset = tvb_find_guint8(tvb, offset + 1, etxp, CIMD_DELIM);
725 if (endOffset == -1)
726 break;
728 PC = decimal_int_value(tvb, offset + 1, CIMD_PC_LENGTH);
729 try_val_to_str_idx(PC, cimd_vals_PC, &idx);
730 if (idx != -1 && tree)
732 (vals_hdr_PC[idx].diss)(tvb, cimd_tree, idx, offset, endOffset);
734 offset = endOffset;
737 if (tree && last1 != CIMD_DELIM)
739 /* Checksum is present */
740 proto_tree_add_uint(cimd_tree, hf_cimd_checksum_indicator, tvb, etxp - 2, 2, checksum);
744 static void
745 dissect_cimd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
747 guint8 OC = 0; /* Operation Code */
748 guint8 PN = 0; /* Packet number */
749 guint16 checksum = 0; /* Checksum */
750 guint16 pkt_check = 0;
751 gint etxp = 0; /* ETX position */
752 gint offset = 0;
753 /*gint endOffset = 0;*/
754 gboolean checksumIsValid = TRUE;
755 guint8 last1, last2, last3;
757 etxp = tvb_find_guint8(tvb, CIMD_PN_OFFSET + CIMD_PN_LENGTH, -1, CIMD_ETX);
758 if (etxp == -1) return;
760 OC = decimal_int_value(tvb, CIMD_OC_OFFSET, CIMD_OC_LENGTH);
761 PN = decimal_int_value(tvb, CIMD_PN_OFFSET, CIMD_PN_LENGTH);
763 last1 = tvb_get_guint8(tvb, etxp - 1);
764 last2 = tvb_get_guint8(tvb, etxp - 2);
765 last3 = tvb_get_guint8(tvb, etxp - 3);
767 if (last1 == CIMD_DELIM) {
768 /* valid packet, CC is missing */
769 } else if (last1 != CIMD_DELIM && last2 != CIMD_DELIM && last3 == CIMD_DELIM) {
770 /* looks valid, it would be nice to check that last1 and last2 are HEXA */
771 /* CC is present */
772 checksum = (AHex2Bin(tvb_get_guint8(tvb, etxp - 2)) << 4) + AHex2Bin(tvb_get_guint8(tvb, etxp - 1));
773 for (; offset < (etxp - 2); offset++)
775 pkt_check += tvb_get_guint8(tvb, offset);
776 pkt_check &= 0xFF;
778 checksumIsValid = (checksum == pkt_check);
779 } else {
780 checksumIsValid = FALSE;
783 /* Make entries in Protocol column on summary display */
784 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIMD");
786 if (checksumIsValid)
787 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(OC, vals_hdr_OC, "Unknown (%d)"));
788 else
789 col_add_fstr(pinfo->cinfo, COL_INFO, "%s - %s", val_to_str(OC, vals_hdr_OC, "Unknown (%d)"), "invalid checksum");
791 dissect_cimd_operation(tvb, tree, etxp, checksum, last1, OC, PN);
795 * A 'heuristic dissector' that attemtps to establish whether we have
796 * a CIMD MSU here.
798 static gboolean
799 dissect_cimd_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
801 int etxp;
802 guint8 opcode = 0; /* Operation code */
804 if (tvb_length(tvb) < CIMD_MIN_LENGTH)
805 return FALSE;
807 if (tvb_get_guint8(tvb, 0) != CIMD_STX)
808 return FALSE;
810 etxp = tvb_find_guint8(tvb, CIMD_OC_OFFSET, -1, CIMD_ETX);
811 if (etxp == -1)
812 { /* XXX - should we have an option to request reassembly? */
813 return FALSE;
816 /* Try getting the operation-code */
817 opcode = decimal_int_value(tvb, CIMD_OC_OFFSET, CIMD_OC_LENGTH);
818 if (try_val_to_str(opcode, vals_hdr_OC) == NULL)
819 return FALSE;
821 if (tvb_get_guint8(tvb, CIMD_OC_OFFSET + CIMD_OC_LENGTH) != CIMD_COLON)
822 return FALSE;
824 if (tvb_get_guint8(tvb, CIMD_PN_OFFSET + CIMD_PN_LENGTH) != CIMD_DELIM)
825 return FALSE;
827 /* Ok, looks like a valid packet, go dissect. */
828 dissect_cimd(tvb, pinfo, tree);
829 return TRUE;
832 void
833 proto_register_cimd(void)
835 static hf_register_info hf[] = {
836 { &hf_cimd_opcode_indicator,
837 { "Operation Code", "cimd.opcode",
838 FT_UINT8, BASE_DEC, NULL, 0x00,
839 NULL, HFILL }
841 { &hf_cimd_packet_number_indicator,
842 { "Packet Number", "cimd.pnumber",
843 FT_UINT8, BASE_DEC, NULL, 0x00,
844 NULL, HFILL }
846 { &hf_cimd_pcode_indicator,
847 { "Parameter Code", "cimd.pcode",
848 FT_STRING, BASE_NONE, NULL, 0x00,
849 NULL, HFILL }
851 { &hf_cimd_checksum_indicator,
852 { "Checksum", "cimd.chksum",
853 FT_UINT8, BASE_HEX, NULL, 0x00,
854 NULL, HFILL }
856 { &hf_cimd_dcs_coding_group_indicator,
857 { "DCS Coding Group", "cimd.dcs.cg",
858 FT_UINT8, BASE_DEC, NULL, 0x00,
859 NULL, HFILL }
861 { &hf_cimd_dcs_compressed_indicator,
862 { "DCS Compressed Flag", "cimd.dcs.cf",
863 FT_UINT8, BASE_DEC, NULL, 0x00,
864 NULL, HFILL }
866 { &hf_cimd_dcs_message_class_meaning_indicator,
867 { "DCS Message Class Meaning", "cimd.dcs.mcm",
868 FT_UINT8, BASE_DEC, NULL, 0x00,
869 NULL, HFILL }
871 { &hf_cimd_dcs_message_class_indicator,
872 { "DCS Message Class", "cimd.dcs.mc",
873 FT_UINT8, BASE_DEC, NULL, 0x00,
874 NULL, HFILL }
876 { &hf_cimd_dcs_character_set_indicator,
877 { "DCS Character Set", "cimd.dcs.chs",
878 FT_UINT8, BASE_DEC, NULL, 0x00,
879 NULL, HFILL }
881 { &hf_cimd_dcs_indication_sense,
882 { "DCS Indication Sense", "cimd.dcs.is",
883 FT_UINT8, BASE_DEC, NULL, 0x00,
884 NULL, HFILL }
886 { &hf_cimd_dcs_indication_type,
887 { "DCS Indication Type", "cimd.dcs.it",
888 FT_UINT8, BASE_DEC, NULL, 0x00,
889 NULL, HFILL }
891 { &hf_index[0],
892 { "User Identity", "cimd.ui",
893 FT_STRING, BASE_NONE, NULL, 0x00,
894 NULL, HFILL }
896 { &hf_index[1],
897 { "Password", "cimd.passwd",
898 FT_STRING, BASE_NONE, NULL, 0x00,
899 NULL, HFILL }
901 { &hf_index[2],
902 { "Subaddress", "cimd.saddr",
903 FT_STRING, BASE_NONE, NULL, 0x00,
904 NULL, HFILL }
906 { &hf_index[3],
907 { "Window Size", "cimd.ws",
908 FT_STRING, BASE_NONE, NULL, 0x00,
909 NULL, HFILL }
911 { &hf_index[4],
912 { "Destination Address", "cimd.da",
913 FT_STRING, BASE_NONE, NULL, 0x00,
914 NULL, HFILL }
916 { &hf_index[5],
917 { "Originating Address", "cimd.oa",
918 FT_STRING, BASE_NONE, NULL, 0x00,
919 NULL, HFILL }
921 { &hf_index[6],
922 { "Originating IMSI", "cimd.oimsi",
923 FT_STRING, BASE_NONE, NULL, 0x00,
924 NULL, HFILL }
926 { &hf_index[7],
927 { "Alphanumeric Originating Address", "cimd.aoi",
928 FT_STRING, BASE_NONE, NULL, 0x00,
929 NULL, HFILL }
931 { &hf_index[8],
932 { "Originated Visited MSC Address", "cimd.ovma",
933 FT_STRING, BASE_NONE, NULL, 0x00,
934 NULL, HFILL }
936 { &hf_index[9],
937 { "Data Coding Scheme", "cimd.dcs",
938 FT_UINT8, BASE_HEX, NULL, 0x00,
939 NULL, HFILL }
941 { &hf_index[10],
942 { "User Data Header", "cimd.udh",
943 FT_STRING, BASE_NONE, NULL, 0x00,
944 NULL, HFILL }
946 { &hf_index[11],
947 { "User Data", "cimd.ud",
948 FT_STRING, BASE_NONE, NULL, 0x00,
949 NULL, HFILL }
951 { &hf_index[12],
952 { "User Data Binary", "cimd.udb",
953 FT_STRING, BASE_NONE, NULL, 0x00,
954 NULL, HFILL }
956 { &hf_index[13],
957 { "More Messages To Send", "cimd.mms",
958 FT_STRING, BASE_NONE, NULL, 0x00,
959 NULL, HFILL }
961 { &hf_index[14],
962 { "Validity Period Relative", "cimd.vpr",
963 FT_STRING, BASE_NONE, NULL, 0x00,
964 NULL, HFILL }
966 { &hf_index[15],
967 { "Validity Period Absolute", "cimd.vpa",
968 FT_STRING, BASE_NONE, NULL, 0x00,
969 NULL, HFILL }
971 { &hf_index[16],
972 { "Protocol Identifier", "cimd.pi",
973 FT_STRING, BASE_NONE, NULL, 0x00,
974 NULL, HFILL }
976 { &hf_index[17],
977 { "First Delivery Time Relative", "cimd.fdtr",
978 FT_STRING, BASE_NONE, NULL, 0x00,
979 NULL, HFILL }
981 { &hf_index[18],
982 { "First Delivery Time Absolute", "cimd.fdta",
983 FT_STRING, BASE_NONE, NULL, 0x00,
984 NULL, HFILL }
986 { &hf_index[19],
987 { "Reply Path", "cimd.rpath",
988 FT_STRING, BASE_NONE, NULL, 0x00,
989 NULL, HFILL }
991 { &hf_index[20],
992 { "Status Report Request", "cimd.srr",
993 FT_STRING, BASE_NONE, NULL, 0x00,
994 NULL, HFILL }
996 { &hf_index[21],
997 { "Cancel Enabled", "cimd.ce",
998 FT_STRING, BASE_NONE, NULL, 0x00,
999 NULL, HFILL }
1001 { &hf_index[22],
1002 { "Cancel Mode", "cimd.cm",
1003 FT_STRING, BASE_NONE, NULL, 0x00,
1004 NULL, HFILL }
1006 { &hf_index[23],
1007 { "Service Center Time Stamp", "cimd.scts",
1008 FT_STRING, BASE_NONE, NULL, 0x00,
1009 NULL, HFILL }
1011 { &hf_index[24],
1012 { "Status Code", "cimd.stcode",
1013 FT_STRING, BASE_NONE, NULL, 0x00,
1014 NULL, HFILL }
1016 { &hf_index[25],
1017 { "Status Error Code", "cimd.sterrcode",
1018 FT_STRING, BASE_NONE, NULL, 0x00,
1019 NULL, HFILL }
1021 { &hf_index[26],
1022 { "Discharge Time", "cimd.dt",
1023 FT_STRING, BASE_NONE, NULL, 0x00,
1024 NULL, HFILL }
1026 { &hf_index[27],
1027 { "Tariff Class", "cimd.tclass",
1028 FT_STRING, BASE_NONE, NULL, 0x00,
1029 NULL, HFILL }
1031 { &hf_index[28],
1032 { "Service Description", "cimd.sdes",
1033 FT_STRING, BASE_NONE, NULL, 0x00,
1034 NULL, HFILL }
1036 { &hf_index[29],
1037 { "Message Count", "cimd.mcount",
1038 FT_STRING, BASE_NONE, NULL, 0x00,
1039 NULL, HFILL }
1041 { &hf_index[30],
1042 { "Priority", "cimd.priority",
1043 FT_STRING, BASE_NONE, NULL, 0x00,
1044 NULL, HFILL }
1046 { &hf_index[31],
1047 { "Delivery Request Mode", "cimd.drmode",
1048 FT_STRING, BASE_NONE, NULL, 0x00,
1049 NULL, HFILL }
1051 { &hf_index[32],
1052 { "Service Center Address", "cimd.scaddr",
1053 FT_STRING, BASE_NONE, NULL, 0x00,
1054 NULL, HFILL }
1056 { &hf_index[33],
1057 { "Get Parameter", "cimd.gpar",
1058 FT_STRING, BASE_NONE, NULL, 0x00,
1059 NULL, HFILL }
1061 { &hf_index[34],
1062 { "SMS Center Time", "cimd.smsct",
1063 FT_STRING, BASE_NONE, NULL, 0x00,
1064 NULL, HFILL }
1066 { &hf_index[35],
1067 { "Error Code", "cimd.errcode",
1068 FT_STRING, BASE_NONE, NULL, 0x00,
1069 NULL, HFILL }
1071 { &hf_index[36],
1072 { "Error Text", "cimd.errtext",
1073 FT_STRING, BASE_NONE, NULL, 0x00,
1074 NULL, HFILL }
1078 /* Setup protocol subtree array */
1079 gint *ett[MAXPARAMSCOUNT + 1];
1080 int i;
1082 ett[0] = &ett_cimd;
1084 for(i=0;i<MAXPARAMSCOUNT;i++)
1086 ett_index[i] = -1;
1087 ett[i + 1] = &(ett_index[i]);
1088 vals_hdr_PC[i].ett_p = &(ett_index[i]);
1089 vals_hdr_PC[i].hf_p = &(hf_index[i]);
1090 vals_hdr_PC[i].diss = cimd_pc_handles[i];
1093 /* Register the protocol name and description */
1094 proto_cimd = proto_register_protocol("Computer Interface to Message Distribution", "CIMD", "cimd");
1095 /* Required function calls to register the header fields and subtrees used */
1096 proto_register_field_array(proto_cimd, hf, array_length(hf));
1097 proto_register_subtree_array(ett, array_length(ett));
1100 void
1101 proto_reg_handoff_cimd(void)
1103 dissector_handle_t cimd_handle;
1106 * CIMD can be spoken on any port so, when not on a specific port, try this
1107 * one whenever TCP is spoken.
1109 heur_dissector_add("tcp", dissect_cimd_heur, proto_cimd);
1112 * Also register as one that can be selected by a TCP port number.
1114 cimd_handle = create_dissector_handle(dissect_cimd, proto_cimd);
1115 dissector_add_handle("tcp.port", cimd_handle);