Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-pdc.c
1 /* packet-pdc.c
2  * Routines for PDC dissection
3  * Copyright 2014, Antony Bridle <antony.bridle@nats.co.uk>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24
25 #include <glib.h>
26 #include <config.h>
27 #include <epan/prefs.h>
28 #include <epan/packet.h>
29 #include <epan/dissectors/packet-tcp.h>
30
31 void proto_register_pdc(void);
32 void proto_reg_handoff_pdc(void);
33
34 /*PDC Protocol*/
35 #define PDC_PROCOTOL "PDC"
36
37 /* PDC version */
38 #define PDC_VERSION 2
39
40 #define SIMPDU  1
41 #define RSMPDU  2
42 #define DRMPDU  3
43 #define DTMPDU  4
44 #define ADMPDU  5
45 #define EDMPDU  6
46 #define AKMPDU  8
47
48 /*Variable length Parameter Codes*/
49 #define PARAM_CODE_VERSION      2
50 #define PARAM_CODE_REFERENCES   3
51 #define PARAM_CODE_TRANSPORT    4
52
53 /* required for the TCP split packet combining */
54 #define PDC_MSG_SIZE_FIELD_LENGTH 2 /* minimum amount of data to find out how big the split packet should be when recombined */
55 #define FRAME_HEADER_LEN 8
56
57 /* global handle for calling asterix decoder if required */
58 static dissector_handle_t asterix_handle;
59
60 static int                proto_pdc          = -1;
61 static guint              gPREF_PORT_NUM_TCP = 0;
62
63 /*HF Declarations*/
64 static gint hf_pdc_len = -1;
65 static gint hf_pdc_mpdu_code = -1;
66 static gint hf_pdc_credit = -1;
67 static gint hf_pdc_simpdu_state = -1;
68 static gint hf_pdc_yr_admu_nr =-1;
69 static gint hf_pdc_akmpdu_mns = -1;
70 static gint hf_pdc_akmpdu_cdt = -1;
71 static gint hf_pdc_simpdu_var = -1;
72 static gint hf_pdc_simpdu_var_len = -1;
73 static gint hf_pdc_simpdu_param = -1;
74 static gint hf_pdc_simpdu_var_version = -1;
75 static gint hf_pdc_simpdu_var_REFSRC = -1;
76 static gint hf_pdc_simpdu_var_REFDEST = -1;
77 static gint hf_pdc_simpdu_var_TSEL = -1;
78 static gint hf_pdc_drmpdu_abort = -1;
79 static gint hf_pdc_drmpdu_reason = -1;
80 static gint hf_pdc_drmpdu_mode = -1;
81 static gint hf_pdc_drmpdu_init = -1;
82 static gint hf_pdc_dtmpdu_user_size =-1;
83 static gint hf_pdc_admpdu_admpdunr = -1;
84 static gint hf_pdc_admpdu_size = -1;
85
86 /*Tree Declarations*/
87 static gint ett_pdc = -1;
88 static gint ett_pdc_simpdu_var = -1;
89
90
91 /*Value String Declarations*/
92 static const value_string valstr_simpdu_state[] = {
93         { 1, "Operational" },
94         { 2, "Standby" },
95         { 3, "Master" },
96         { 4, "Slave" },
97         { 5, "Single" },
98         { 0, NULL }
99 };
100
101 static const value_string valstr_simpdu_param[] = {
102         { 2, "Version Number" },
103         { 3, "References" },
104         { 4, "Transport Selector" },
105         { 0, NULL }
106 };
107
108 static const value_string valstr_mpdus[] = {
109         { 1, "State Information" },
110         { 2, "Request State" },
111         { 3, "Disconnect Request" },
112         { 4, "Data" },
113         { 5, "Acknowledged Data" },
114         { 6, "Expedited Data" },
115         { 8, "Data Acknowledgement" },
116         { 0, NULL }
117 };
118
119 static const value_string valstr_drmpdu_abort[] = {
120         { 0, "Orderly Release" },
121         { 1, "Abortive Release" },
122         { 0, NULL }
123 };
124
125 static const value_string valstr_drmpdu_mode[] = {
126         { 0, "Node Shutdown" },
127         { 7, "PDC Release"},
128         { 0, NULL }
129 };
130
131 static const value_string valstr_drmpdu_initatior[] = {
132         { 0, "Server" },
133         { 15, "Client"},
134         { 0, NULL }
135 };
136
137 static const value_string valstr_drmpdu_reason[] = {
138         { 0, "Reason Not Specified" },
139         { 1, "Normal Disconnect Initiated by the MS-User" },
140         { 2, "Protocol Error" },
141         { 3, "Connection Request Refused" },
142         { 4, "The Remote Operational MS Entity Does Not Respond" },
143         { 5, "The Protocol Version Is Not Supported" },
144         { 6, "Mismatched References" },
145         { 0, NULL }
146 };
147
148 /* start of functions here */
149 static int dissect_simpdu(tvbuff_t *tvb, proto_tree *tree, guint16 offset, guint8 lenIndicator)
150 {
151         guint16     bytesProcessed;
152         guint8      paramCode;
153         proto_item *simpduItem;
154         proto_tree *simpduVarTree;
155         proto_tree *simpduVarTree1;
156
157         bytesProcessed = 0;
158
159         /*Add the Credit allocation*/
160         proto_tree_add_item(tree, hf_pdc_credit, tvb, offset, 1, ENC_BIG_ENDIAN);
161         bytesProcessed += 1;
162
163         /*Add the State*/
164         proto_tree_add_item(tree, hf_pdc_simpdu_state, tvb, offset + bytesProcessed , 1, ENC_BIG_ENDIAN);
165         bytesProcessed += 1;
166
167         /*Add the YR-ADMU-NR*/
168         proto_tree_add_item(tree, hf_pdc_yr_admu_nr, tvb, offset + bytesProcessed , 4, ENC_BIG_ENDIAN);
169         bytesProcessed += 4;
170
171         /*Determine what's in the variable part*/
172         if (lenIndicator > 7)
173         {
174                 /*Add the Variable Length Tree*/
175                 simpduItem = proto_tree_add_item (tree, hf_pdc_simpdu_var, tvb, offset + bytesProcessed, lenIndicator - 7, ENC_NA);
176                 simpduVarTree = proto_item_add_subtree (simpduItem, ett_pdc_simpdu_var);
177
178                 while ((offset + bytesProcessed) < ( lenIndicator + 1 ))
179                 {
180                         /*Get the parameter code*/
181                         paramCode  = tvb_get_guint8(tvb, offset + bytesProcessed);
182                         simpduItem = proto_tree_add_item (simpduVarTree, hf_pdc_simpdu_param, tvb, offset + bytesProcessed,      1, ENC_NA);
183                         simpduVarTree1 = proto_item_add_subtree (simpduItem, ett_pdc_simpdu_var);
184                         bytesProcessed += 1;
185                         switch (paramCode)
186                         {
187                         case PARAM_CODE_VERSION:
188                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_len,     tvb, offset + bytesProcessed,     1, ENC_NA);
189                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_version, tvb, offset + bytesProcessed + 1, 1, ENC_NA);
190                                 bytesProcessed += 2;
191                                 break;
192                         case PARAM_CODE_REFERENCES:
193                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_len,     tvb, offset + bytesProcessed,     1, ENC_NA);
194                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_REFSRC,  tvb, offset + bytesProcessed + 1, 2, ENC_NA);
195                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_REFDEST, tvb, offset + bytesProcessed + 3, 2, ENC_NA);
196                                 bytesProcessed += 5;
197                                 break;
198                         case PARAM_CODE_TRANSPORT:
199                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_len,     tvb, offset + bytesProcessed,     1, ENC_NA);
200                                 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_TSEL,    tvb, offset + bytesProcessed + 1, 2, ENC_NA);
201                                 bytesProcessed += 3;
202                                 break;
203                         }
204                 } /* end of whileloop */
205         }
206         return (bytesProcessed);
207 }
208
209 static int dissect_rsmpdu(void)
210 {
211         return (0);
212 }
213
214 static int dissect_drmpdu(tvbuff_t *tvb, proto_tree *tree, guint16 offset)
215 {
216         /*DR-MPDU*/
217         proto_tree_add_item(tree, hf_pdc_drmpdu_abort,  tvb, offset,     1, ENC_NA);
218         proto_tree_add_item(tree, hf_pdc_drmpdu_mode,   tvb, offset,     1, ENC_NA);
219         proto_tree_add_item(tree, hf_pdc_drmpdu_init,   tvb, offset,     1, ENC_NA);
220         proto_tree_add_item(tree, hf_pdc_drmpdu_reason, tvb, offset + 1, 1, ENC_NA);
221
222         return (2);
223 }
224
225 static int dissect_admpdu(tvbuff_t *tvb, proto_tree *parent_tree, proto_tree *tree, guint16 offset, packet_info *pinfo)
226 {
227         guint16   userDataLen;
228         guint16   returnLen;
229         tvbuff_t *asterixTVB;
230
231         /*Add the ad*/
232         proto_tree_add_item(tree, hf_pdc_admpdu_admpdunr, tvb, offset, 4, ENC_BIG_ENDIAN);
233         offset += 4;
234
235         if (PDC_VERSION == 2)
236         {
237                 proto_tree_add_item(tree, hf_pdc_admpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN);
238                 /* length of user data field */
239                 userDataLen = tvb_get_ntohs(tvb, offset);
240                 offset += 2;
241
242                 returnLen = userDataLen + 6;
243                 asterixTVB = tvb_new_subset_length(tvb, offset, userDataLen);
244
245                 if (asterix_handle != NULL)
246                         call_dissector(asterix_handle, asterixTVB, pinfo, parent_tree);
247
248                 return (returnLen);
249         }
250         return (2);
251 }
252
253 static int dissect_dtmpdu(tvbuff_t *tvb, proto_tree *parent_tree, proto_tree *tree, guint16 offset, packet_info *pinfo)
254 {
255         guint16   userDataLen;
256         guint16   returnLen;
257         tvbuff_t *asterixTVB;
258
259         if (PDC_VERSION == 2)
260         {
261                 proto_tree_add_item(tree, hf_pdc_dtmpdu_user_size, tvb, offset, 2, ENC_BIG_ENDIAN);
262                 /* length of user data field */
263                 userDataLen = tvb_get_ntohs(tvb, 2);
264                 returnLen  = userDataLen + 2;
265                 asterixTVB = tvb_new_subset_length(tvb, offset + 2, userDataLen);
266
267                 if (asterix_handle != NULL)
268                         call_dissector(asterix_handle, asterixTVB, pinfo, parent_tree);
269
270                 return (returnLen);
271         }
272         return (2);
273 }
274
275 static int dissect_edmpdu(tvbuff_t *tvb, proto_tree *parent_tree, proto_tree *tree, guint16 offset, packet_info *pinfo)
276 {
277         guint16   userDataLen;
278         guint16   returnLen;
279         tvbuff_t *asterixTVB;
280
281         if (PDC_VERSION == 2)
282         {
283                 proto_tree_add_item(tree, hf_pdc_dtmpdu_user_size, tvb, offset, 2, ENC_BIG_ENDIAN);
284                 /* length of user data field */
285                 userDataLen = tvb_get_ntohs(tvb, 2);
286                 returnLen   = userDataLen + 2;
287                 asterixTVB  = tvb_new_subset_length(tvb, offset + 2, userDataLen);
288
289                 if (asterix_handle != NULL)
290                         call_dissector(asterix_handle, asterixTVB, pinfo, parent_tree);
291
292                 return (returnLen);
293         }
294         return 2;
295 }
296
297 static int dissect_akmpdu(tvbuff_t *tvb, proto_tree *tree, guint16 offset)
298 {
299         proto_tree_add_item(tree, hf_pdc_akmpdu_mns, tvb, offset,     2, ENC_BIG_ENDIAN);
300         proto_tree_add_item(tree, hf_pdc_akmpdu_cdt, tvb, offset,     2, ENC_BIG_ENDIAN);
301         proto_tree_add_item(tree, hf_pdc_yr_admu_nr, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
302         return (6);
303 }
304
305 static int dissect_pdc_packet(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
306 {
307         guint       i = 0;
308         guint8      len_indicator;
309         guint8      mpduCode;
310         guint16     length;
311         proto_item *pdcPacketItem;
312         proto_tree *pdcPacketTree;
313
314         length = 0;
315
316         /*Get the length indictor and the MPDU Code*/
317         len_indicator  = tvb_get_guint8 (tvb, i);
318         mpduCode       = tvb_get_guint8 (tvb, i + 1);
319         length        += 2;
320
321         /*Add the PDC Tree*/
322         pdcPacketItem = proto_tree_add_item (tree, proto_pdc, tvb, i, len_indicator + 1, ENC_NA);
323         pdcPacketTree = proto_item_add_subtree (pdcPacketItem, ett_pdc);
324
325         /*Add the Length and packet type*/
326         proto_tree_add_item(pdcPacketTree, hf_pdc_len, tvb, i, 1, ENC_BIG_ENDIAN);
327         proto_tree_add_item(pdcPacketTree, hf_pdc_mpdu_code, tvb, i + 1, 1, ENC_BIG_ENDIAN);
328
329         /*Call the correct dissecting function*/
330         switch (mpduCode)
331         {
332         case SIMPDU:
333                 length += dissect_simpdu(tvb, pdcPacketTree, length, len_indicator);
334                 col_set_str(pinfo->cinfo, COL_INFO, "SIMPDU");
335                 break;
336         case RSMPDU:
337                 length += dissect_rsmpdu();
338                 col_set_str(pinfo->cinfo, COL_INFO, "RSMPDU");
339                 break;
340         case DRMPDU:
341                 length += dissect_drmpdu(tvb, pdcPacketTree, length);
342                 col_set_str(pinfo->cinfo, COL_INFO, "DRMPDU");
343                 break;
344         case DTMPDU:
345                 length += dissect_dtmpdu(tvb, tree, pdcPacketTree, length, pinfo);
346                 col_set_str(pinfo->cinfo, COL_INFO, "DTMPDU");
347                 break;
348         case ADMPDU:
349                 length += dissect_admpdu(tvb, tree, pdcPacketTree, length, pinfo);
350                 col_set_str(pinfo->cinfo, COL_INFO, "ADMPDU");
351                 break;
352         case EDMPDU:
353                 length += dissect_edmpdu(tvb, tree, pdcPacketTree, length, pinfo);
354                 col_set_str(pinfo->cinfo, COL_INFO, "EDMPDU");
355                 break;
356         case AKMPDU:
357                 length += dissect_akmpdu(tvb, pdcPacketTree, length);
358                 col_set_str(pinfo->cinfo, COL_INFO, "AKMPDU");
359                 break;
360         default:
361                 break;
362         };
363         return (length);  /* XXX: returned length ignored by caller: Remove keeping track of data rocessed ?         */
364                           /*      col_set_str() could then be done separately with 'if (tree)' around the dissection */
365 }
366
367 /* Actual dissector bits and bytes done here */
368 static int dissect_pdc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
369 {
370         /*Set the Column*/
371         col_set_str(pinfo->cinfo, COL_PROTOCOL, PDC_PROCOTOL );
372         col_clear(pinfo->cinfo, COL_INFO);
373
374         dissect_pdc_packet(tvb, tree, pinfo);
375
376         return tvb_reported_length(tvb);
377 }
378
379 /* function to provide TCP split packet combiner with size of packet */
380 static guint get_pdc_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
381 {
382         guint  size;
383         guint  extra;
384         guint8 mpdu_type;
385
386         mpdu_type = tvb_get_guint8(tvb, offset+1);
387         switch (mpdu_type)
388         {
389         case SIMPDU:
390                 size  = tvb_get_guint8(tvb, offset);
391                 extra = 1;
392                 break;
393         case RSMPDU:
394                 size  = tvb_get_guint8(tvb, offset);
395                 extra = 1;
396                 break;
397         case DRMPDU:
398                 size  = tvb_get_guint8(tvb, offset);
399                 extra = 1;
400                 break;
401         case DTMPDU:
402                 size  = tvb_get_ntohs(tvb, offset+2);
403                 extra = 4;
404                 break;
405         case ADMPDU:
406                 size  = tvb_get_ntohs(tvb, offset+6);
407                 extra = 8;
408                 break;
409         case EDMPDU:
410                 size  = tvb_get_guint8(tvb, offset);
411                 extra = 1;
412                 break;
413         case AKMPDU:
414                 size  = tvb_get_guint8(tvb, offset)+1;
415                 extra = 0;
416                 break;
417         default:
418                 size  = 0;
419                 extra = 0;
420         }
421         return size + extra;
422 }
423
424 /* top level call to recombine split tcp packets */
425
426 static void tcp_dissect_pdc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
427 {
428         guint8 mpdu_type;
429         guint8 minimum_bytes;
430
431         mpdu_type = tvb_get_guint8(tvb,1);
432         switch (mpdu_type)
433         {
434         case SIMPDU:
435                 minimum_bytes = 2;
436                 break;
437         case RSMPDU:
438                 minimum_bytes = 2;
439                 break;
440         case DRMPDU:
441                 minimum_bytes = 2;
442                 break;
443         case DTMPDU:
444                 minimum_bytes = 4;
445                 break;
446         case ADMPDU:
447                 minimum_bytes = 8;
448                 break;
449         case EDMPDU:
450                 minimum_bytes = 2;
451                 break;
452         case AKMPDU:
453                 minimum_bytes = 2;
454                 break;
455         default:
456                 minimum_bytes = 2;
457                 break;
458         }
459         tcp_dissect_pdus(tvb, pinfo, tree, TRUE, minimum_bytes, get_pdc_message_len, dissect_pdc, NULL);
460 }
461
462 void proto_register_pdc(void)
463 {
464         module_t *pdc_pref_module;
465
466         static hf_register_info hf[] =
467         {
468                 { &hf_pdc_len,
469                   { "Length Indicator", "pdc.li",
470                     FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
471
472                 { &hf_pdc_mpdu_code,
473                   { "MPDU code", "pdc.mpducode",
474                     FT_UINT8, BASE_DEC, VALS(valstr_mpdus), 0x0, NULL, HFILL }},
475
476                 { &hf_pdc_credit,
477                   { "Credit", "pdc.cdt",
478                     FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
479
480                 { &hf_pdc_yr_admu_nr,
481                   { "YR-ADMU-NR", "pdc.yradmunr",
482                     FT_UINT32, BASE_DEC, NULL, 0x0, NULL , HFILL }},
483
484                 { &hf_pdc_simpdu_state,
485                   { "State", "pdc.state",
486                     FT_UINT8, BASE_DEC, VALS(valstr_simpdu_state), 0x0, NULL, HFILL }},
487
488                 { &hf_pdc_akmpdu_mns,
489                   { "MNS", "pdc.akmpdu.mns",
490                     FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL }},
491
492                 { &hf_pdc_akmpdu_cdt,
493                   { "CDT", "pdc.akmpdu.cdt",
494                     FT_UINT16, BASE_DEC, NULL, 0x07FF, NULL, HFILL }},
495
496                 { &hf_pdc_simpdu_var,
497                   { "Variable Part", "pdc.simpdu.variable",
498                     FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
499
500                 { &hf_pdc_simpdu_param,
501                   { "Parameter", "pdc.simpdu.param",
502                     FT_UINT8, BASE_DEC, VALS(valstr_simpdu_param), 0x0, NULL, HFILL }},
503
504                 { &hf_pdc_simpdu_var_len,
505                   { "Length", "pdc.simpdu.variable.length",
506                     FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
507
508                 { &hf_pdc_simpdu_var_version,
509                   { "PDC Version Number", "pdc.simpdu.variable.version",
510                     FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
511
512                 { &hf_pdc_simpdu_var_REFSRC,
513                   { "Reference Source", "pdc.simpdu.variable.refsrc",
514                     FT_UINT32, BASE_DEC, NULL, 0x0,NULL, HFILL }},
515
516                 { &hf_pdc_simpdu_var_REFDEST,
517                   { "Reference Destination", "pdc.simpdu.variable.refdst",
518                     FT_UINT32, BASE_DEC, NULL, 0x0,NULL, HFILL }},
519
520                 { &hf_pdc_simpdu_var_TSEL,
521                   { "Transport Selector", "pdc.simpdu.tsel",
522                     FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
523
524                 { &hf_pdc_drmpdu_abort,
525                   { "Abort", "pdc.drmpdu.abort",
526                     FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_abort), 0x80, NULL, HFILL }},
527
528                 { &hf_pdc_drmpdu_reason,
529                   { "Reason", "pdc.drmpdu.reason",
530                     FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_reason), 0x0, NULL, HFILL }},
531
532                 { &hf_pdc_drmpdu_mode,
533                   { "Mode", "pdc.drmpdu.mode",
534                     FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_mode), 0x70, NULL, HFILL }},
535
536                 { &hf_pdc_drmpdu_init,
537                   { "Reason", "pdc.drmpdu.init",
538                     FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_initatior), 0x0F, NULL, HFILL }},
539
540                 { &hf_pdc_dtmpdu_user_size,
541                   { "User Data Length", "pdc.dtmpdu.usersize",
542                     FT_UINT16, BASE_DEC, NULL, 0x0, NULL , HFILL }},
543
544                 { &hf_pdc_admpdu_admpdunr,
545                   { "AD-MPDU-NR", "pdc.admpdu.admpdunr",
546                     FT_UINT32,  BASE_DEC, NULL, 0x0, NULL , HFILL }},
547
548                 { &hf_pdc_admpdu_size,
549                   { "User Data Size", "pdc.admpdu.usersize",
550                     FT_UINT16, BASE_DEC, NULL, 0x0, NULL , HFILL }},
551         };
552
553         /* Setup protocol subtree array */
554         static gint *ett[] = {
555                 &ett_pdc,
556                 &ett_pdc_simpdu_var
557         };
558
559         proto_pdc = proto_register_protocol (
560                 "PDC Protocol", /* name       */
561                 "PDC",          /* short name */
562                 "pdc"           /* abbrev     */
563                 );
564
565         /*Required Function Calls to register the header fields and subtrees used*/
566         proto_register_field_array(proto_pdc, hf, array_length(hf));
567         proto_register_subtree_array(ett, array_length(ett));
568
569         /*Register Preferences Module*/
570         pdc_pref_module = prefs_register_protocol(proto_pdc, proto_reg_handoff_pdc);
571
572         /*Register Preferences*/
573         prefs_register_uint_preference(pdc_pref_module, "tcp.port", "PDC Port", "PDC Port if other then the default", 10, &gPREF_PORT_NUM_TCP);
574 }
575
576 /* Function to add pdc dissector to tcp.port dissector table and to get handle for asterix dissector */
577 void proto_reg_handoff_pdc(void)
578 {
579         static dissector_handle_t pdc_tcp_handle;
580         static int                pdc_tcp_port;
581         static gboolean           initialized = FALSE;
582
583         if (! initialized)
584         {
585                 asterix_handle = find_dissector("asterix");
586                 pdc_tcp_handle = create_dissector_handle(tcp_dissect_pdc, proto_pdc);
587                 dissector_add_handle("tcp.port", pdc_tcp_handle); /* for "decode-as" */
588                 initialized    = TRUE;
589         }
590         else
591         {
592                 if (pdc_tcp_port != 0)
593                         dissector_delete_uint("tcp.port", pdc_tcp_port, pdc_tcp_handle);
594         }
595
596         pdc_tcp_port = gPREF_PORT_NUM_TCP;
597         if (pdc_tcp_port != 0)
598                 dissector_add_uint("tcp.port", pdc_tcp_port, pdc_tcp_handle);
599 }
600
601 /*
602  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
603  *
604  * Local variables:
605  * c-basic-offset: 8
606  * tab-width: 8
607  * indent-tabs-mode: t
608  * End:
609  *
610  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
611  * :indentSize=8:tabSize=8:noTabs=false:
612  */