From Todd Sabin: allocate the buffer for the decrypted payload, rather
[obnox/wireshark/wip.git] / packet-skinny.c
1 /* packet-skinny.c
2  *
3  * Dissector for the Skinny Client Control Protocol
4  *   (The "D-Channel"-Protocol for Cisco Systems' IP-Phones)
5  * Copyright 2001, Joerg Mayer (email: see AUTHORS file)
6  *
7  * Paul E. Erkkila (pee@erkkila.org) - fleshed out the decode
8  * skeleton to report values for most message/message fields.
9  * Much help from Guy Harris on figuring out the ethereal api.
10  *
11  * This file is based on packet-aim.c, which is
12  * Copyright 2000, Ralf Hoelzer <ralf@well.com>
13  *
14  * $Id: packet-skinny.c,v 1.21 2002/09/21 03:14:10 gerald Exp $
15  *
16  * Ethereal - Network traffic analyzer
17  * By Gerald Combs <gerald@ethereal.com>
18  * Copyright 1998 Gerald Combs
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33  */
34
35 /* This implementation is based on a draft version of the 3.0
36  * specification
37  */
38
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42
43 #include <string.h>
44
45 #include <epan/packet.h>
46 #include "prefs.h"
47
48 #include "packet-tcp.h"
49
50 #define TCP_PORT_SKINNY 2000
51
52 #define SKINNY_SOFTKEY0  0x01
53 #define SKINNY_SOFTKEY1  0x02
54 #define SKINNY_SOFTKEY2  0x04
55 #define SKINNY_SOFTKEY3  0x08
56 #define SKINNY_SOFTKEY4  0x10
57 #define SKINNY_SOFTKEY5  0x20
58 #define SKINNY_SOFTKEY6  0x40
59 #define SKINNY_SOFTKEY7  0x80
60 #define SKINNY_SOFTKEY8  0x100
61 #define SKINNY_SOFTKEY9  0x200
62 #define SKINNY_SOFTKEY10 0x400
63 #define SKINNY_SOFTKEY11 0x800
64 #define SKINNY_SOFTKEY12 0x1000
65 #define SKINNY_SOFTKEY13 0x2000
66 #define SKINNY_SOFTKEY14 0x4000
67 #define SKINNY_SOFTKEY15 0x8000
68
69 /* KeyMap Show/No Show */
70 static const true_false_string softKeyMapValues = {
71   "Show",
72   "Do Not Show"
73 };
74
75
76 /* I will probably need this again when I change things
77  * to function pointers, but let me use the existing
78  * infrastructure for now
79  *
80  * typedef struct {
81  *   guint32    id;
82  *   char *     name;
83  * } message_id_t;
84  */
85
86 static const value_string  message_id[] = {
87
88   /* Station -> Callmanager */
89   {0x0000, "KeepAliveMessage"},
90   {0x0001, "RegisterMessage"},
91   {0x0002, "IpPortMessage"},
92   {0x0003, "KeypadButtonMessage"},
93   {0x0004, "EnblocCallMessage"},
94   {0x0005, "StimulusMessage"},
95   {0x0006, "OffHookMessage"},
96   {0x0007, "OnHookMessage"},
97   {0x0008, "HookFlashMessage"},
98   {0x0009, "ForwardStatReqMessage"},
99   {0x000A, "SpeedDialStatReqMessage"},
100   {0x000B, "LineStatReqMessage"},
101   {0x000C, "ConfigStatReqMessage"},
102   {0x000D, "TimeDateReqMessage"},
103   {0x000E, "ButtonTemplateReqMessage"},
104   {0x000F, "VersionReqMessage"},
105   {0x0010, "CapabilitiesResMessage"},
106   {0x0011, "MediaPortListMessage"},
107   {0x0012, "ServerReqMessage"},
108   {0x0020, "AlarmMessage"},
109   {0x0021, "MulticastMediaReceptionAck"},
110   {0x0022, "OpenReceiveChannelAck"},
111   {0x0023, "ConnectionStatisticsRes"},
112   {0x0024, "OffHookWithCgpnMessage"},
113   {0x0025, "SoftKeySetReqMessage"},
114   {0x0026, "SoftKeyEventMessage"},
115   {0x0027, "UnregisterMessage"},
116   {0x0028, "SoftKeyTemplateReqMessage"},
117   {0x0029, "RegisterTokenReq"},
118   {0x002B, "unknownClientMessage1"},
119   {0x002D, "unknownClientMessage2"},
120
121   /* Callmanager -> Station */
122   /* 0x0000, 0x0003? */
123   {0x0081, "RegisterAckMessage"},
124   {0x0082, "StartToneMessage"},
125   {0x0083, "StopToneMessage"},
126   {0x0085, "SetRingerMessage"},
127   {0x0086, "SetLampMessage"},
128   {0x0087, "SetHkFDetectMessage"},
129   {0x0088, "SetSpeakerModeMessage"},
130   {0x0089, "SetMicroModeMessage"},
131   {0x008A, "StartMediaTransmission"},
132   {0x008B, "StopMediaTransmission"},
133   {0x008C, "StartMediaReception"},
134   {0x008D, "StopMediaReception"},
135   {0x008F, "CallInfoMessage"},
136   {0x0090, "ForwardStatMessage"},
137   {0x0091, "SpeedDialStatMessage"},
138   {0x0092, "LineStatMessage"},
139   {0x0093, "ConfigStatMessage"},
140   {0x0094, "DefineTimeDate"},
141   {0x0095, "StartSessionTransmission"},
142   {0x0096, "StopSessionTransmission"},
143   {0x0097, "ButtonTemplateMessage"},
144   {0x0098, "VersionMessage"},
145   {0x0099, "DisplayTextMessage"},
146   {0x009A, "ClearDisplay"},
147   {0x009B, "CapabilitiesReqMessage"},
148   {0x009C, "EnunciatorCommandMessage"},
149   {0x009D, "RegisterRejectMessage"},
150   {0x009E, "ServerResMessage"},
151   {0x009F, "Reset"},
152   {0x0100, "KeepAliveAckMessage"},
153   {0x0101, "StartMulticastMediaReception"},
154   {0x0102, "StartMulticastMediaTransmission"},
155   {0x0103, "StopMulticastMediaReception"},
156   {0x0104, "StopMulticastMediaTransmission"},
157   {0x0105, "OpenReceiveChannel"},
158   {0x0106, "CloseReceiveChannel"},
159   {0x0107, "ConnectionStatisticsReq"},
160   {0x0108, "SoftKeyTemplateResMessage"},
161   {0x0109, "SoftKeySetResMessage"},
162   {0x0110, "SelectSoftKeysMessage"},
163   {0x0111, "CallStateMessage"},
164   {0x0112, "DisplayPromptStatusMessage"},
165   {0x0113, "ClearPromptStatusMessage"},
166   {0x0114, "DisplayNotifyMessage"},
167   {0x0115, "ClearNotifyMessage"},
168   {0x0116, "ActivateCallPlaneMessage"},
169   {0x0117, "DeactivateCallPlaneMessage"},
170   {0x0118, "UnregisterAckMessage"},
171   {0x0119, "BackSpaceReqMessage"},
172   {0x011A, "RegisterTokenAck"},
173   {0x011B, "RegisterTokenReject"},
174   {0x011D, "unknownForwardMessage1"},
175
176   {0     , NULL}        /* terminator */
177 };
178
179 /*
180  * Device type to text conversion table
181  */
182 static const value_string  deviceTypes[] = {
183   {1  , "30SPplus"},
184   {2  , "12SPplus"},
185   {3  , "12SP"},
186   {4  , "12"},
187   {5  , "30VIP"},
188   {6  , "Telecaster"},
189   {7  , "TelecasterMgr"},
190   {8  , "TelecasterBus"},
191   {20 , "Virtual30SPplus"},
192   {21 , "PhoneApplication"},
193   {30 , "AnalogAccess"},
194   {40 , "DigitalAccessPRI"},
195   {41 , "DigitalAccessT1"},
196   {42 , "DigitalAccessTitan2"},
197   {47 , "AnalogAccessElvis"},
198   {49 , "DigitalAccessLennon"},
199   {50 , "ConferenceBridge"},
200   {51 , "ConferenceBridgeYoko"},
201   {60 , "H225"},
202   {61 , "H323Phone"},
203   {62 , "H323Trunk"},
204   {70 , "MusicOnHold"},
205   {71 , "Pilot"},
206   {72 , "TapiPort"},
207   {73 , "TapiRoutePoint"},
208   {80 , "VoiceInBox"},
209   {81 , "VoiceInboxAdmin"},
210   {82 , "LineAnnunciator"},
211   {90 , "RouteList"},
212   {100, "LoadSimulator"},
213   {110, "MediaTerminationPoint"},
214   {111, "MediaTerminationPointYoko"},
215   {120, "MGCPStation"},
216   {121, "MGCPTrunk"},
217   {122, "RASProxy"},
218   {255, "NotDefined"},
219   { 0    , NULL}
220 };
221
222 /*
223  * keypad button -> text conversion
224  */
225 static const value_string keypadButtons[] = {
226   {0x0   , "Zero"},
227   {0x1   , "One"},
228   {0x2   , "Two"},
229   {0x3   , "Three"},
230   {0x4   , "Four"},
231   {0x5   , "Five"},
232   {0x6   , "Six"},
233   {0x7   , "Seven"},
234   {0x8   , "Eight"},
235   {0x9   , "Nine"},
236   {0xa   , "A"},
237   {0xb   , "B"},
238   {0xc   , "C"},
239   {0xd   , "D"},
240   {0xe   , "Star"},
241   {0xf   , "Pound"},
242   {0     , NULL}
243 };
244
245 static const value_string deviceStimuli[] = {
246   {1    , "LastNumberRedial"},
247   {2    , "SpeedDial"},
248   {3    , "Hold"},
249   {4    , "Transfer"},
250   {5    , "ForwardAll"},
251   {6    , "ForwardBusy"},
252   {7    , "ForwardNoAnswer"},
253   {8    , "Display"},
254   {9    , "Line"},
255   {0xa  , "T120Chat"},
256   {0xb  , "T120Whiteboard"},
257   {0xc  , "T120ApplicationSharing"},
258   {0xd  , "T120FileTransfer"},
259   {0xe  , "Video"},
260   {0xf  , "VoiceMail"},
261   {0x11 , "AutoAnswer"},
262   {0x21 , "GenericAppB1"},
263   {0x22 , "GenericAppB2"},
264   {0x23 , "GenericAppB3"},
265   {0x24 , "GenericAppB4"},
266   {0x25 , "GenericAppB5"},
267   {0x7b , "MeetMeConference"},
268   {0x7d , "Conference=0x7d"},
269   {0x7e , "CallPark=0x7e"},
270   {0x7f , "CallPickup"},
271   {0x80 , "GroupCallPickup=80"},
272   {0,NULL}
273 };
274
275
276 /* Note i'm only using 7 later on cuz i'm lazy ;) */
277 #define DeviceMaxCapabilities 18 /* max capabilities allowed in Cap response message */
278
279 static const value_string mediaPayloads[] = {
280   {1   , "Non-standard codec"},
281   {2   , "G.711 A-law 64k"},
282   {3   , "G.711 A-law 56k"},
283   {4   , "G.711 u-law 64k"},
284   {5   , "G.711 u-law 56k"},
285   {6   , "G.722 64k"},
286   {7   , "G.722 56k"},
287   {8   , "G.722 48k"},
288   {9   , "G.723.1"},
289   {10  , "G.728"},
290   {11  , "G.729"},
291   {12  , "G.729 Annex A"},
292   {13  , "IS11172 AudioCap"},   /* IS11172 is an ISO MPEG standard */
293   {14  , "IS13818 AudioCap"},   /* IS13818 is an ISO MPEG standard */
294   {15  , "G.729 Annex B"},
295   {16  , "G.729 Annex A+Annex B"},
296   {18  , "GSM Full Rate"},
297   {19  , "GSM Half Rate"},
298   {20  , "GSM Enhanced Full Rate"},
299   {25  , "Wideband 256k"},
300   {32  , "Data 64k"},
301   {33  , "Data 56k"},
302   {80  , "GSM"},
303   {81  , "ActiveVoice"},
304   {82  , "G.726 32K"},
305   {83  , "G.726 24K"},
306   {84  , "G.726 16K"},
307   {85  , "G.729B"},
308   {86  , "G.729B Low Complexity"},
309   {0  , NULL}
310 };
311
312 static const value_string alarmSeverities[] = {
313   {0   , "Critical"},
314   {1   , "Warning"},
315   {2   , "Informational"},
316   {4   , "Unknown"},
317   {7   , "Major"},
318   {8   , "Minor"},
319   {10  , "Marginal"},
320   {20  , "TraceInfo"},
321   {0  , NULL}
322 };
323
324 static const value_string multicastMediaReceptionStatus[] = {
325   {0  , "Ok"},
326   {1  , "Error"},
327   {0  , NULL}
328 };
329
330 static const value_string openReceiveChanStatus[] = {
331   {0   , "orcOk"},
332   {1   , "orcError"},
333   {0   , NULL}
334 };
335
336
337 static const value_string statsProcessingTypes[] = {
338   {0   , "clearStats"},
339   {1   , "doNotClearStats"},
340   {0   , NULL}
341 };
342
343 #define SkMaxSoftKeyCount 18 /* this value should be the same as the max soft key value */
344 static const value_string softKeyEvents[] = {
345   {1   , "Redial"},
346   {2   , "NewCall"},
347   {3   , "Hold"},
348   {4   , "Trnsfer"},
349   {5   , "CFwdAll"},
350   {6   , "CFwdBusy"},
351   {7   , "CFwdNoAnswer"},
352   {8   , "BackSpace"},
353   {9   , "EndCall"},
354   {10  , "Resume"},
355   {11  , "Answer"},
356   {12  , "Info"},
357   {13  , "Confrn"},
358   {14  , "Park"},
359   {15  , "Join"},
360   {16  , "MeetMeConfrn"},
361   {17  , "CallPickUp"},
362   {18  , "GrpCallPickUp"},
363   {0   , NULL}
364 };
365
366 /* Define info index for each softkey event for Telecaster station. */
367 static const value_string softKeyIndexes[] = {
368   {301  , "RedialInfoIndex"},
369   {302  , "NewCallInfoIndex"},
370   {303  , "HoldInfoIndex"},
371   {304  , "TrnsferInfoIndex"},
372   {305  , "CFwdAllInfoIndex"},
373   {306  , "CFwdBusyInfoIndex"},     /* not used yet */
374   {307  , "CFwdNoAnswerInfoIndex"}, /* not used yet */
375   {308  , "BackSpaceInfoIndex"},
376   {309  , "EndCallInfoIndex"},
377   {310  , "ResumeInfoIndex"},
378   {311  , "AnswerInfoIndex"},
379   {312  , "InfoInfoIndex"},
380   {313  , "ConfrnInfoIndex"},
381   {314  , "ParkInfoIndex"},
382   {315  , "JoinInfoIndex"},
383   {316  , "MeetMeConfrnInfoIndex"},
384   {317  , "CallPickUpInfoIndex"},
385   {318  , "GrpCallPickUpInfoIndex"},
386   {0   , NULL}
387 };
388
389
390 static const value_string buttonDefinitions[] = {
391   {1    , "LastNumberRedial"},
392   {2    , "SpeedDial"},
393   {3    , "Hold"},
394   {4    , "Transfer"},
395   {5    , "ForwardAll"},
396   {6    , "ForwardBusy"},
397   {7    , "ForwardNoAnswer"},
398   {8    , "Display"},
399   {9    , "Line"},
400   {0xa  , "T120Chat"},
401   {0xb  , "T120Whiteboard"},
402   {0xc  , "T120ApplicationSharing"},
403   {0xd  , "T120FileTransfer"},
404   {0xe  , "Video"},
405   {0x10 , "AnswerRelease"},
406   {0xf0 , "Keypad"},
407   {0xfd , "AEC"},
408   {0xff , "Undefined"},
409   {0   , NULL}
410 };
411
412 #define StationTotalSoftKeySets 10 /* total number of the soft key sets */
413 static const value_string keySetNames[] = {
414   {0   , "OnHook"},
415   {1   , "Connected"},
416   {2   , "OnHold"},
417   {3   , "RingIn"},
418   {4   , "OffHook"},
419   {5   , "Connected with transfer"},
420   {6   , "Digits after dialing first digit"},
421   {7   , "Connected with conference"},
422   {8   , "RingOut"},
423   {9   , "OffHook with features"},
424   {0   , NULL}
425 };
426
427 /* Define soft key labels for the Telecaster station */
428 static const value_string softKeyLabel[] = {
429   {0   , "undefined"},
430   {1   , "Redial"},
431   {2   , "NewCall"},
432   {3   , "Hold"},
433   {4   , "Trnsfer"},
434   {5   , "CFwdAll"},
435   {6   , "CFwdBusy"},
436   {7   , "CFwdNoAnswer"},
437   {8   , "<<"},
438   {9   , "EndCall"},
439   {10  , "Resume"},
440   {11  , "Answer"},
441   {12  , "Info"},
442   {13  , "Confrn"},
443   {14  , "Park"},
444   {15  , "Join"},
445   {16  , "MeetMe"},
446   {17  , "PickUp"},
447   {18  , "GPickUp"},
448   {0   , NULL}
449 };
450
451
452 /*
453  * define lamp modes;
454  * lamp cadence is defined as follows
455  * Wink (on 80%) = 448msec on / 64msec off
456  * Flash (fast flash) = 32msec on / 32msec off
457  * Blink (on 50%) = 512msec on / 512msec off
458  * On (on steady)
459  */
460 static const value_string stationLampModes[] = {
461   {0   , "Undefined"},
462   {0x1 , "Off"},
463   {0x2 , "On"},
464   {0x3 , "Wink"},
465   {0x4 , "Flash"},
466   {0x5 , "Blink"},
467   {0   , NULL}
468 };
469
470 /* Defined the Call States to be sent to the Telecaste station.
471  * These are NOT the call states used in CM internally. Instead,
472  * they are the call states sent from CM and understood by the Telecaster station
473  */
474 static const value_string skinny_stationCallStates[] = {
475   {1   , "OffHook"},
476   {2   , "OnHook"},
477   {3   , "RingOut"},
478   {4   , "RingIn"},
479   {5   , "Connected"},
480   {6   , "Busy"},
481   {7   , "Congestion"},
482   {8   , "Hold"},
483   {9   , "CallWaiting"},
484   {10  , "CallTransfer"},
485   {11  , "CallPark"},
486   {12  , "Proceed"},
487   {13  , "CallRemoteMultiline"},
488   {14  , "InvalidNumber"},
489   {0   , NULL}
490 };
491
492 /* Defined Call Type */
493 static const value_string skinny_callTypes[] = {
494   {1   , "InBoundCall"},
495   {2   , "OutBoundCall"},
496   {3   , "ForwardCall"},
497   {0   , NULL}
498 };
499
500 /*
501  * define station-playable tones;
502  * for tone definitions see SR-TSV-002275, "BOC Notes on the LEC Networks -- 1994"
503  */
504 static const value_string skinny_deviceTones[] = {
505   {0    , "Silence"},
506   {1    , "Dtmf1"},
507   {2    , "Dtmf2"},
508   {3    , "Dtmf3"},
509   {4    , "Dtmf4"},
510   {5    , "Dtmf5"},
511   {6    , "Dtmf6"},
512   {7    , "Dtmf7"},
513   {8    , "Dtmf8"},
514   {9    , "Dtmf9"},
515   {0xa  , "Dtmf0"},
516   {0xe  , "DtmfStar"},
517   {0xf  , "DtmfPound"},
518   {0x10 , "DtmfA"},
519   {0x11 , "DtmfB"},
520   {0x12 , "DtmfC"},
521   {0x13 , "DtmfD"},
522   {0x21 , "InsideDialTone"},
523   {0x22 , "OutsideDialTone"},
524   {0x23 , "LineBusyTone"},
525   {0x24 , "AlertingTone"},
526   {0x25 , "ReorderTone"},
527   {0x26 , "RecorderWarningTone"},
528   {0x27 , "RecorderDetectedTone"},
529   {0x28 , "RevertingTone"},
530   {0x29 , "ReceiverOffHookTone"},
531   {0x2a , "PartialDialTone"},
532   {0x2b , "NoSuchNumberTone"},
533   {0x2c , "BusyVerificationTone"},
534   {0x2d , "CallWaitingTone"},
535   {0x2e , "ConfirmationTone"},
536   {0x2f , "CampOnIndicationTone"},
537   {0x30 , "RecallDialTone"},
538   {0x31 , "ZipZip"},
539   {0x32 , "Zip"},
540   {0x33 , "BeepBonk"},
541   {0x34 , "MusicTone"},
542   {0x35 , "HoldTone"},
543   {0x36 , "TestTone"},
544   {0x40 , "AddCallWaiting"},
545   {0x41 , "PriorityCallWait"},
546   {0x42 , "RecallDial"},
547   {0x43 , "BargIn"},
548   {0x44 , "DistinctAlert"},
549   {0x45 , "PriorityAlert"},
550   {0x46 , "ReminderRing"},
551   {0x50 , "MF1"},
552   {0x51 , "MF2"},
553   {0x52 , "MF3"},
554   {0x53 , "MF4"},
555   {0x54 , "MF5"},
556   {0x55 , "MF6"},
557   {0x56 , "MF7"},
558   {0x57 , "MF8"},
559   {0x58 , "MF9"},
560   {0x59 , "MF0"},
561   {0x5a , "MFKP1"},
562   {0x5b , "MFST"},
563   {0x5c , "MFKP2"},
564   {0x5d , "MFSTP"},
565   {0x5e , "MFST3P"},
566   {0x5f , "MILLIWATT"},
567   {0x60 , "MILLIWATTTEST"},
568   {0x61 , "HIGHTONE"},
569   {0x62 , "FLASHOVERRIDE"},
570   {0x63 , "FLASH"},
571   {0x64 , "PRIORITY"},
572   {0x65 , "IMMEDIATE"},
573   {0x66 , "PREAMPWARN"},
574   {0x67 , "2105HZ"},
575   {0x68 , "2600HZ"},
576   {0x69 , "440HZ"},
577   {0x6a , "300HZ"},
578   {0x7f , "NoTone"},
579   {0   , NULL}
580 };
581
582 /* define ring types */
583 static const value_string skinny_ringTypes[] = {
584   {0x1  , "RingOff"},
585   {0x2  , "InsideRing"},
586   {0x3  , "OutsideRing"},
587   {0x4  , "FeatureRing"},
588   {0   , NULL}
589 };
590
591 static const value_string skinny_speakerModes[] = {
592   {1   , "SpeakerOn"},
593   {2   , "SpeakerOff"},
594   {0   , NULL}
595 };
596
597 static const value_string skinny_silenceSuppressionModes[] = {
598   {0   , "Media_SilenceSuppression_Off"},
599   {1   , "Media_SilenceSuppression_On"},
600   {0   , NULL}
601 };
602
603 static const value_string skinny_g723BitRates[] = {
604   {1   , "Media_G723BRate_5_3"},
605   {2   , "Media_G723BRate_6_4"},
606   {0   , NULL}
607 };
608
609 /* define device reset types  */
610 static const value_string skinny_deviceResetTypes[] = {
611   {1   , "DEVICE_RESET"},
612   {2   , "DEVICE_RESTART"},
613   {0   , NULL}
614 };
615
616 static const value_string skinny_echoCancelTypes[] = {
617   {0    , "Media_EchoCancellation_Off"},
618   {1    , "Media_EchoCancellation_On"},
619   {0    , NULL}
620 };
621
622 static const value_string skinny_deviceUnregisterStatusTypes[] = {
623   {0   , "Ok"},
624   {1   , "Error"},
625   {2   , "NAK"}, /* Unregister request is rejected for reaso n such as existence of a call */
626   {0   , NULL}
627 };
628
629 /* define hook flash detection mode */
630 static const value_string skinny_hookFlashDetectModes[] = {
631   {1   , "HookFlashOn"},
632   {2   , "HookFlashOff"},
633   {0   , NULL}
634 };
635
636 /* define station microphone modes;
637  * Mic On - The speakerphone's microphone is turned on ONLY if the phone is in the "Speaker On (Off Hook)"
638  * state (see above).
639  * Mic Off - The microphone is turned off or, if it's not on, the command is ignored.
640  */
641 static const value_string skinny_microphoneModes[] = {
642   {1   , "MicOn"},
643   {2   , "MicOff"},
644   {0   , NULL}
645 };
646
647 /* define the session request types */
648 static const value_string skinny_sessionTypes[] = {
649   {1   , "Chat"},
650   {2   , "Whiteboard"},
651   {4   , "ApplicationSharing"},
652   {8   , "FileTransfer"},
653   {10  , "Video"},
654   {0   , NULL}
655 };
656
657 static const value_string skinny_mediaEnunciationTypes[] = {
658   {1  , "None"},
659   {2  , "CallPark"},
660   {0  , NULL}
661 };
662
663 #define StationMaxDirnumSize 24         /* max size of calling or called party dirnum  */
664 #define StationMaxNameSize 40           /* max size of calling party's name  */
665 #define StationMaxDeviceNameSize 16     /* max size of station's IP name  */
666 #define StationMaxSpeedDials 10         /* max number of speed dial numbers allowed on a station */
667 #define StationMaxVersionSize 16        /* max chars in version string  */
668 #define StationMaxButtonTemplateSize 42 /* max button template size */
669 #define StationMaxDisplayTextSize 33    /* max text size in DisplayText message */
670 #define StationMaxPorts 10              /* max number of ports on one device */
671 #define StationDateTemplateSize 6       /* date template in the form M/D/Y, D/M/Y, ... */
672 #define StationMaxServerNameSize 48     /* max size of server name */
673 #define StationMaxServers 5             /* max servers */
674 #define StationMaxDeviceDirnums 1024    /* max dir numbers per SCM device */
675 #define StationMaxDirnums 64            /* max dir numbers per physical station (also used in db request msg); */
676 #define StationMaxSoftKeyLabelSize 16   /* max label size in the message */
677 #define StationMaxSoftKeyDefinition 32       /* max number of soft key definition in the message */
678 #define StationMaxSoftKeySetDefinition 16    /* max number of soft key set definition in the message */
679 #define StationMaxSoftKeyIndex 16            /* max number of soft key indices in a station soft key set */
680 #define StationMaxDisplayPromptStatusSize 32 /* max status text size in the display status message */
681 #define StationMaxDisplayNotifySize 32       /* max prompt text size in the display prompt message */
682 #define StationMaxAlarmMessageSize 80        /* max size for an alarm message */
683
684 static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
685
686 /* Initialize the protocol and registered fields */
687 static int proto_skinny          = -1;
688 static int hf_skinny_data_length = -1;
689 static int hf_skinny_reserved    = -1;
690 static int hf_skinny_messageid   = -1;
691 static int hf_skinny_deviceName  = -1;
692 static int hf_skinny_stationUserId = -1;
693 static int hf_skinny_stationInstance = -1;
694 static int hf_skinny_deviceType = -1;
695 static int hf_skinny_maxStreams = -1;
696 static int hf_skinny_stationIpPort = -1;
697 static int hf_skinny_stationKeypadButton = -1;
698 static int hf_skinny_calledParty = -1;
699 static int hf_skinny_stimulus = -1;
700 static int hf_skinny_stimulusInstance = -1;
701 static int hf_skinny_lineNumber = -1;
702 static int hf_skinny_speedDialNumber = -1;
703 static int hf_skinny_capCount = -1;
704 static int hf_skinny_payloadCapability = -1;
705 static int hf_skinny_maxFramesPerPacket = -1;
706 static int hf_skinny_alarmSeverity = -1;
707 static int hf_skinny_alarmParam1 = -1;
708 static int hf_skinny_alarmParam2 = -1;
709 static int hf_skinny_receptionStatus = -1;
710 static int hf_skinny_passThruPartyID = -1;
711 static int hf_skinny_ORCStatus = -1;
712 static int hf_skinny_ipAddress = -1;
713 static int hf_skinny_portNumber = -1;
714 static int hf_skinny_statsProcessingType = -1;
715 static int hf_skinny_callIdentifier = -1;
716 static int hf_skinny_packetsSent = -1;
717 static int hf_skinny_octetsSent  = -1;
718 static int hf_skinny_packetsRecv = -1;
719 static int hf_skinny_octetsRecv  = -1;
720 static int hf_skinny_packetsLost = -1;
721 static int hf_skinny_latency     = -1;
722 static int hf_skinny_jitter      = -1;
723 static int hf_skinny_directoryNumber = -1;
724 static int hf_skinny_softKeyEvent = -1;
725 static int hf_skinny_lineInstance = -1;
726 static int hf_skinny_keepAliveInterval = -1;
727 static int hf_skinny_dateTemplate = -1;
728 static int hf_skinny_secondaryKeepAliveInterval = -1;
729 static int hf_skinny_buttonOffset = -1;
730 static int hf_skinny_buttonCount = -1;
731 static int hf_skinny_totalButtonCount = -1;
732 static int hf_skinny_buttonInstanceNumber = -1;
733 static int hf_skinny_buttonDefinition = -1;
734 static int hf_skinny_softKeyOffset = -1;
735 static int hf_skinny_softKeyCount = -1;
736 static int hf_skinny_totalSoftKeyCount = -1;
737 static int hf_skinny_softKeyLabel = -1;
738 static int hf_skinny_softKeySetOffset = -1;
739 static int hf_skinny_softKeySetCount = -1;
740 static int hf_skinny_totalSoftKeySetCount = -1;
741 static int hf_skinny_softKeyTemplateIndex = -1;
742 static int hf_skinny_softKeyInfoIndex = -1;
743 static int hf_skinny_softKeySetDescription = -1;
744 static int hf_skinny_softKeyMap = -1;
745 static int hf_skinny_softKey0 = -1;
746 static int hf_skinny_softKey1 = -1;
747 static int hf_skinny_softKey2 = -1;
748 static int hf_skinny_softKey3 = -1;
749 static int hf_skinny_softKey4 = -1;
750 static int hf_skinny_softKey5 = -1;
751 static int hf_skinny_softKey6 = -1;
752 static int hf_skinny_softKey7 = -1;
753 static int hf_skinny_softKey8 = -1;
754 static int hf_skinny_softKey9 = -1;
755 static int hf_skinny_softKey10 = -1;
756 static int hf_skinny_softKey11 = -1;
757 static int hf_skinny_softKey12 = -1;
758 static int hf_skinny_softKey13 = -1;
759 static int hf_skinny_softKey14 = -1;
760 static int hf_skinny_softKey15 = -1;
761 static int hf_skinny_lampMode = -1;
762 static int hf_skinny_messageTimeOutValue = -1;
763 static int hf_skinny_displayMessage = -1;
764 static int hf_skinny_lineDirNumber = -1;
765 static int hf_skinny_lineFullyQualifiedDisplayName = -1;
766 static int hf_skinny_speedDialDirNumber = -1;
767 static int hf_skinny_speedDialDisplayName = -1;
768 static int hf_skinny_dateYear = -1;
769 static int hf_skinny_dateMonth = -1;
770 static int hf_skinny_dayOfWeek = -1;
771 static int hf_skinny_dateDay = -1;
772 static int hf_skinny_dateHour = -1;
773 static int hf_skinny_dateMinute = -1;
774 static int hf_skinny_dateSeconds = -1;
775 static int hf_skinny_dateMilliseconds = -1;
776 static int hf_skinny_timeStamp = -1;
777 static int hf_skinny_callState = -1;
778 static int hf_skinny_deviceTone = -1;
779 static int hf_skinny_callingPartyName = -1;
780 static int hf_skinny_callingParty = -1;
781 static int hf_skinny_calledPartyName = -1;
782 static int hf_skinny_callType = -1;
783 static int hf_skinny_originalCalledPartyName = -1;
784 static int hf_skinny_originalCalledParty = -1;
785 static int hf_skinny_ringType = -1;
786 static int hf_skinny_speakerMode = -1;
787 static int hf_skinny_remoteIpAddr = -1;
788 static int hf_skinny_remotePortNumber = -1;
789 static int hf_skinny_millisecondPacketSize = -1;
790 static int hf_skinny_precedenceValue = -1;
791 static int hf_skinny_silenceSuppression = -1;
792 static int hf_skinny_g723BitRate = -1;
793 static int hf_skinny_conferenceID = -1;
794 static int hf_skinny_deviceResetType = -1;
795 static int hf_skinny_echoCancelType = -1;
796 static int hf_skinny_deviceUnregisterStatus = -1;
797 static int hf_skinny_hookFlashDetectMode = -1;
798 static int hf_skinny_detectInterval = -1;
799 static int hf_skinny_microphoneMode = -1;
800 static int hf_skinny_unknown = -1;
801 static int hf_skinny_activeForward = -1;
802 static int hf_skinny_forwardAllActive = -1;
803 static int hf_skinny_forwardBusyActive = -1;
804 static int hf_skinny_forwardNoAnswerActive = -1;
805 static int hf_skinny_forwardNumber = -1;
806 static int hf_skinny_serverName = -1;
807 static int hf_skinny_numberLines = -1;
808 static int hf_skinny_numberSpeedDials = -1;
809 static int hf_skinny_userName = -1;
810 static int hf_skinny_sessionType = -1;
811 static int hf_skinny_version = -1;
812 static int hf_skinny_mediaEnunciationType = -1;
813 static int hf_skinny_serverIdentifier = -1;
814 static int hf_skinny_serverListenPort = -1;
815 static int hf_skinny_serverIpAddress = -1;
816 static int hf_skinny_multicastIpAddress = -1;
817 static int hf_skinny_multicastPort = -1;
818 static int hf_skinny_tokenRejWaitTime = -1;
819
820
821
822 /* Initialize the subtree pointers */
823 static gint ett_skinny          = -1;
824 static gint ett_skinny_softKeyMap = -1;
825
826 /* desegmentation of SCCP */
827 static gboolean skinny_desegment = TRUE;
828
829 static dissector_handle_t data_handle;
830
831 /* Get the length of a single SCCP PDU */
832 static guint get_skinny_pdu_len(tvbuff_t *tvb, int offset)
833 {
834   guint32 hdr_data_length;
835
836   /*
837    * Get the length of the SCCP packet.
838    */
839   hdr_data_length = tvb_get_letohl(tvb, offset);
840
841   /*
842    * That length doesn't include the length of the header itself;
843    * add that in.
844    */
845   return hdr_data_length + 8;
846 }
847
848 /* Dissect a single SCCP PDU */
849 static void dissect_skinny_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
850 {
851   int offset = 0;
852
853   /* Header fields */
854   guint32 hdr_data_length;
855   guint32 hdr_reserved;
856   guint32 data_messageid;
857   gchar   *messageid_str;
858   /*  guint32 data_size; */
859
860   guint32 unknownLong = 0;
861
862   guint i = 0;
863   int j = 0;
864
865   guint32 capCount;
866   guint32 softKeyCount;
867   guint32 softKeySetCount;
868   guint16 validKeyMask;
869
870   /* Set up structures we will need to add the protocol subtree and manage it */
871   proto_item *ti;
872   proto_tree *skinny_tree = NULL;
873
874   proto_item *skm = NULL;
875   proto_item *skm_tree = NULL;
876
877   hdr_data_length = tvb_get_letohl(tvb, offset);
878   hdr_reserved    = tvb_get_letohl(tvb, offset+4);
879   data_messageid  = tvb_get_letohl(tvb, offset+8);
880
881   /* In the interest of speed, if "tree" is NULL, don't do any work not
882    * necessary to generate protocol tree items. */
883   if (tree) {
884     ti = proto_tree_add_item(tree, proto_skinny, tvb, offset, hdr_data_length+8, FALSE);
885     skinny_tree = proto_item_add_subtree(ti, ett_skinny);
886     proto_tree_add_uint(skinny_tree, hf_skinny_data_length, tvb, offset, 4, hdr_data_length);
887     proto_tree_add_uint(skinny_tree, hf_skinny_reserved, tvb, offset+4, 4, hdr_reserved);
888   }
889
890   messageid_str = val_to_str(data_messageid, message_id, "0x%08X (Unknown)");
891
892   if (check_col(pinfo->cinfo, COL_INFO)) {
893     col_add_str(pinfo->cinfo, COL_INFO, messageid_str);
894   }
895
896   if (tree) {
897     proto_tree_add_uint(skinny_tree, hf_skinny_messageid, tvb,offset+8, 4, data_messageid );
898   }
899
900   if (tree) {
901     switch(data_messageid) {
902
903     /* cases that do not need to be decoded */
904     case 0x0 :    /* keepAlive */
905       break;
906
907     case 0x6 :    /* offHook */
908       break;
909
910     case 0x7 :    /* onHook    */
911       break;
912
913     case 0x8 :    /* hookFlash */
914       break;
915
916     case 0xc :    /* configStateReqMessage */
917       break;
918
919     case 0xd :    /* timeDateReqMessage */
920       break;
921
922     case 0xe :    /* buttoneTemplateReqMessage */
923       break;
924
925     case 0xf :    /* stationVersionReqMessage */
926       break;
927
928     case 0x12 :   /* stationServerReqMessage */
929       break;
930
931     case 0x25 :   /* softKeySetReqMessage */
932       break;
933
934     case 0x27 :   /* unregisterMessage */
935       break;
936
937     case 0x28 :   /* softKeyTemplateRequest */
938       break;
939
940     case 0x83 :   /* stopTone */
941       break;
942
943     case 0x9a :   /* clearDisplay */
944       break;
945
946     case 0x9b :   /* capabilitiesReqMessage */
947       break;
948
949     case 0x100 :    /* keepAliveAck */
950       break;
951
952     case 0x115 :  /* clearNotifyDisplay */
953       break;
954
955     case 0x117 :  /* deactivateCallPlane */
956       break;
957
958     case 0x11a :  /* registerTokenAck */
959       break;
960
961     /*
962      ** cases that need decode
963      **
964      */
965
966     case 0x1 :   /* register message */
967       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, StationMaxDeviceNameSize, TRUE);
968       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, offset+28, 4, TRUE);
969       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, offset+32, 4, TRUE);
970       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+36, 4, TRUE);
971       proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, offset+40, 4, TRUE);
972       proto_tree_add_item(skinny_tree, hf_skinny_maxStreams, tvb, offset+44, 4, TRUE);
973       break;
974
975     case 0x2 :  /* ipPortMessage */
976       proto_tree_add_item(skinny_tree, hf_skinny_stationIpPort, tvb, offset+12, 2, FALSE);
977       break;
978
979     case 0x3 :  /* keyPadButtonMessage */
980       proto_tree_add_item(skinny_tree, hf_skinny_stationKeypadButton, tvb, offset+12, 4, TRUE);
981       break;
982
983     case 0x4 :  /* stationEnblocCallMessage -- This decode NOT verified*/
984       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12, StationMaxDirnumSize, TRUE);
985       break;
986
987     case 0x5 : /* stationStimulusMessage */
988       proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
989       proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
990       break;
991
992     case 0x9  : /* stationForwardStatReqMessage */
993       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
994       break;
995
996     case 0xa :  /* speedDialStatReqMessage */
997       proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
998       break;
999
1000     case 0xb :  /* LineStatReqMessage */
1001       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
1002       break;
1003
1004     case 0x10 :  /* capabilitiesResMessage  - VERIFIED AS IS*/
1005       /* FIXME -- we are only going to decode the first 7 protocol fields for now cuz that's all it sent me
1006        * on the phone i was working with. I should probably skip the struct decode and use a more piece
1007        * type method using the capCount definition to control the decode loop
1008        *
1009        * basically changing StationMaxCapabilities definition
1010        *
1011        */
1012       capCount = tvb_get_letohl(tvb, offset+12);
1013       proto_tree_add_uint(skinny_tree, hf_skinny_capCount, tvb, offset+12, 4, capCount);
1014       for (i = 0; i < capCount; i++) {
1015         proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+(i*16)+16, 4, TRUE);
1016         proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+(i*16)+20, 2, TRUE);
1017         /* FIXME -- decode the union under here as required, is always 0 on my equipment */
1018       }
1019       break;
1020
1021     case 0x11 : /* mediaPortList */
1022       break;
1023
1024     case 0x20 :   /* stationAlarmMessage */
1025       proto_tree_add_item(skinny_tree, hf_skinny_alarmSeverity, tvb, offset+12, 4, TRUE);
1026       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxAlarmMessageSize, TRUE);
1027       proto_tree_add_item(skinny_tree, hf_skinny_alarmParam1, tvb, offset+96, 4, TRUE);
1028       proto_tree_add_item(skinny_tree, hf_skinny_alarmParam2, tvb, offset+100, 4, TRUE);
1029       break;
1030
1031     case 0x21 : /* stationMulticastMediaReceptionAck - This decode NOT verified*/
1032       proto_tree_add_item(skinny_tree, hf_skinny_receptionStatus, tvb, offset+12, 4, TRUE);
1033       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1034       break;
1035
1036     case 0x22 : /* stationOpenReceiveChannelAck */
1037       proto_tree_add_item(skinny_tree, hf_skinny_ORCStatus, tvb, offset+12, 4, TRUE);
1038       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+16, 4, TRUE);
1039       proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+20, 4, TRUE);
1040       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+24, 4, TRUE);
1041       break;
1042
1043     case 0x23    :  /* stationConnectionStatisticsRes */
1044       proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, offset+12, StationMaxDirnumSize, TRUE);
1045       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+36, 4, TRUE);
1046       proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, offset+40, 4, TRUE);
1047       proto_tree_add_item(skinny_tree, hf_skinny_packetsSent, tvb, offset+44, 4, TRUE);
1048       proto_tree_add_item(skinny_tree, hf_skinny_octetsSent, tvb, offset+48, 4, TRUE);
1049       proto_tree_add_item(skinny_tree, hf_skinny_packetsRecv, tvb, offset+52, 4, TRUE);
1050       proto_tree_add_item(skinny_tree, hf_skinny_octetsRecv, tvb, offset+56, 4, TRUE);
1051       proto_tree_add_item(skinny_tree, hf_skinny_packetsLost, tvb, offset+60, 4, TRUE);
1052       proto_tree_add_item(skinny_tree, hf_skinny_jitter, tvb, offset+64, 4, TRUE);
1053       proto_tree_add_item(skinny_tree, hf_skinny_latency, tvb, offset+68, 4, TRUE);
1054       break;
1055
1056     case 0x24 : /* offHookWithCgpn */
1057       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12,StationMaxDirnumSize, TRUE);
1058       break;
1059
1060     case 0x26 :  /* softKeyEventMessage */
1061       proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+12, 4, TRUE);
1062       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
1063       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
1064       break;
1065
1066     case 0x29 : /* registerTokenREq */
1067       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, 4, TRUE);
1068       i = offset+12+StationMaxDeviceNameSize;
1069       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
1070       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i+4, 4, TRUE);
1071       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, i+8, 4, TRUE);
1072       proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, i+12, 4, TRUE);
1073       break;
1074
1075       /*
1076        *
1077        * message not in the spec
1078        *
1079        */
1080     case 0x2b :  /* unknownClientMessage1 */
1081       break;
1082
1083     case 0x2d :  /* unknownClientMessage2 */
1084       break;
1085
1086       /*
1087        *
1088        *  Call manager -> client messages start here(ish)
1089        *
1090        */
1091     case 0x81 :  /* registerAck */
1092       proto_tree_add_item(skinny_tree, hf_skinny_keepAliveInterval, tvb, offset+12, 4, TRUE);
1093       proto_tree_add_item(skinny_tree, hf_skinny_dateTemplate, tvb, offset+16, StationDateTemplateSize, TRUE);
1094       proto_tree_add_item(skinny_tree, hf_skinny_secondaryKeepAliveInterval, tvb, offset+24, 4, TRUE);
1095       break;
1096
1097     case 0x82 :  /* startTone */
1098       proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, offset+12, 4, TRUE);
1099       break;
1100
1101     case 0x85 : /* setRingerMessage */
1102       proto_tree_add_item(skinny_tree, hf_skinny_ringType, tvb, offset+12, 4, TRUE);
1103       break;
1104
1105     case 0x86 : /* setLampMessage */
1106       proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
1107       proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
1108       proto_tree_add_item(skinny_tree, hf_skinny_lampMode, tvb, offset+20, 4, TRUE);
1109       break;
1110
1111     case 0x87 : /* stationHookFlashDetectMode */
1112       proto_tree_add_item(skinny_tree, hf_skinny_hookFlashDetectMode, tvb, offset+12, 4, TRUE);
1113       proto_tree_add_item(skinny_tree, hf_skinny_detectInterval, tvb, offset+16, 4, TRUE);
1114       break;
1115
1116     case 0x88 : /* setSpeakerMode */
1117
1118       proto_tree_add_item(skinny_tree, hf_skinny_speakerMode, tvb, offset+12, 4, TRUE);
1119       break;
1120
1121     case 0x89 : /* setMicroMode */
1122       proto_tree_add_item(skinny_tree, hf_skinny_microphoneMode, tvb, offset+12, 4, TRUE);
1123       break;
1124
1125     case 0x8a : /* startMediaTransmistion */
1126       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID,          tvb, offset+12, 4, TRUE);
1127       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID,       tvb, offset+16, 4, TRUE);
1128       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,          tvb, offset+20, 4, TRUE);
1129       proto_tree_add_item(skinny_tree, hf_skinny_remotePortNumber,      tvb, offset+24, 4, TRUE);
1130       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1131       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability,     tvb, offset+32, 4, TRUE);
1132       proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue,       tvb, offset+36, 4, TRUE);
1133       proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression,    tvb, offset+40, 4, TRUE);
1134       proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket,    tvb, offset+44, 2, TRUE);
1135       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate,           tvb, offset+48, 4, TRUE);
1136       break;
1137
1138     case 0x8b :  /* stopMediaTransmission */
1139
1140       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1141       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1142       break;
1143
1144     case 0x8c : /* startMediaReception */
1145       break;
1146
1147     case 0x8d : /* stopMediaReception */
1148       break;
1149
1150     case 0x8e : /* reservered */
1151       break;
1152
1153     case 0x8f : /* callInfo */
1154       i = offset+12;
1155       proto_tree_add_item(skinny_tree, hf_skinny_callingPartyName, tvb, i, StationMaxNameSize, TRUE);
1156       i += StationMaxNameSize;
1157       proto_tree_add_item(skinny_tree, hf_skinny_callingParty, tvb, i, StationMaxDirnumSize, TRUE);
1158       i += StationMaxDirnumSize;
1159       proto_tree_add_item(skinny_tree, hf_skinny_calledPartyName, tvb, i, StationMaxNameSize, TRUE);
1160       i += StationMaxNameSize;
1161       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, i, StationMaxDirnumSize, TRUE);
1162       i += StationMaxDirnumSize;
1163       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, i, 4, TRUE);
1164       i += 4;
1165       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
1166       i += 4;
1167       proto_tree_add_item(skinny_tree, hf_skinny_callType, tvb, i, 4, TRUE);
1168       i += 4;
1169       proto_tree_add_item(skinny_tree, hf_skinny_originalCalledPartyName, tvb, i, StationMaxNameSize, TRUE);
1170       i += StationMaxNameSize;
1171       proto_tree_add_item(skinny_tree, hf_skinny_originalCalledParty, tvb, i, StationMaxDirnumSize, TRUE);
1172       break;
1173
1174     case 0x90 : /* forwardStat */
1175       proto_tree_add_item(skinny_tree, hf_skinny_activeForward, tvb, offset+12, 4, TRUE);
1176       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+16, 4, TRUE);
1177       proto_tree_add_item(skinny_tree, hf_skinny_forwardAllActive, tvb, offset+20, 4, TRUE);
1178       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, offset+24, StationMaxDirnumSize, TRUE);
1179       i = offset+24+StationMaxDirnumSize;
1180       proto_tree_add_item(skinny_tree, hf_skinny_forwardBusyActive, tvb, i, 4, TRUE);
1181       i += 4;
1182       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
1183       i += StationMaxDirnumSize;
1184       proto_tree_add_item(skinny_tree, hf_skinny_forwardNoAnswerActive, tvb, i, 4, TRUE);
1185       i += 4;
1186       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
1187       break;
1188
1189     case 0x91 : /* speedDialStatMessage */
1190       proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
1191       proto_tree_add_item(skinny_tree, hf_skinny_speedDialDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
1192       proto_tree_add_item(skinny_tree, hf_skinny_speedDialDisplayName, tvb, offset+40, StationMaxNameSize, TRUE);
1193       break;
1194
1195     case 0x92 : /* lineStatMessage */
1196       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
1197       proto_tree_add_item(skinny_tree, hf_skinny_lineDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
1198       proto_tree_add_item(skinny_tree, hf_skinny_lineFullyQualifiedDisplayName, tvb, offset+16+StationMaxDirnumSize, StationMaxNameSize, TRUE);
1199       break;
1200
1201     case 0x93 : /* configStat */
1202       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, StationMaxDeviceNameSize, TRUE);
1203       i = offset+12+StationMaxDeviceNameSize;
1204       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
1205       i += 4;
1206       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i, 4, TRUE);
1207       i += 4;
1208       proto_tree_add_item(skinny_tree, hf_skinny_userName, tvb, i, StationMaxNameSize, TRUE);
1209       i += StationMaxNameSize;
1210       proto_tree_add_item(skinny_tree, hf_skinny_serverName, tvb, i, StationMaxNameSize, TRUE);
1211       i += StationMaxNameSize;
1212       proto_tree_add_item(skinny_tree, hf_skinny_numberLines, tvb, i, 4, TRUE);
1213       proto_tree_add_item(skinny_tree, hf_skinny_numberSpeedDials, tvb, i+4, 4, TRUE);
1214       break;
1215
1216     case 0x94 : /* stationDefineTimeDate */
1217       proto_tree_add_item(skinny_tree, hf_skinny_dateYear,   tvb, offset+12, 4, TRUE);
1218       proto_tree_add_item(skinny_tree, hf_skinny_dateMonth,  tvb, offset+16, 4, TRUE);
1219       proto_tree_add_item(skinny_tree, hf_skinny_dayOfWeek,  tvb, offset+20, 4, TRUE);
1220       proto_tree_add_item(skinny_tree, hf_skinny_dateDay,    tvb, offset+24, 4, TRUE);
1221       proto_tree_add_item(skinny_tree, hf_skinny_dateHour,   tvb, offset+28, 4, TRUE);
1222       proto_tree_add_item(skinny_tree, hf_skinny_dateMinute, tvb, offset+32, 4, TRUE);
1223       proto_tree_add_item(skinny_tree, hf_skinny_dateSeconds,tvb, offset+36, 4, TRUE);
1224       proto_tree_add_item(skinny_tree, hf_skinny_dateMilliseconds,tvb, offset+40, 4, TRUE);
1225       proto_tree_add_item(skinny_tree, hf_skinny_timeStamp, tvb, offset+44, 4, TRUE);
1226       break;
1227
1228     case 0x95 : /* startSessionTransmission */
1229       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,  tvb, offset+12, 4, TRUE);
1230       proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
1231       break;
1232
1233     case 0x96 : /* stopSessionTransmission */
1234       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,  tvb, offset+12, 4, TRUE);
1235       proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
1236       break;
1237
1238     case 0x97 :  /* buttonTemplateMessage  */
1239       /*
1240        * FIXME
1241        * This decode prints out oogly subtree maybe? or something besides the VALS...
1242        * note to self: uint8 != 4 kk thx info ^_^
1243        *
1244        */
1245       proto_tree_add_item(skinny_tree, hf_skinny_buttonOffset, tvb, offset+12, 4, TRUE);
1246       proto_tree_add_item(skinny_tree, hf_skinny_buttonCount,  tvb, offset+16, 4, TRUE);
1247       proto_tree_add_item(skinny_tree, hf_skinny_totalButtonCount, tvb, offset+20, 4, TRUE);
1248       for (i = 0; i < StationMaxButtonTemplateSize; i++) {
1249         proto_tree_add_item(skinny_tree, hf_skinny_buttonInstanceNumber, tvb, offset+(i*2)+24, 1, TRUE);
1250         proto_tree_add_item(skinny_tree, hf_skinny_buttonDefinition, tvb, offset+(i*2)+25, 1, TRUE);
1251       }
1252       break;
1253
1254     case 0x98 : /* version */
1255       proto_tree_add_item(skinny_tree, hf_skinny_version, tvb, offset+12, StationMaxVersionSize, TRUE);
1256       break;
1257
1258     case 0x99 :  /* displayTextMessage */
1259       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);
1260       break;
1261
1262     case 0x9c : /* enunciatorCommand */
1263       proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, offset+12, 4, TRUE);
1264       for (i = 0; i < StationMaxDirnumSize; i++) {
1265         proto_tree_add_item(skinny_tree, hf_skinny_unknown, tvb, offset+16+(i*4), 4, TRUE);
1266       }
1267       i = offset+16+StationMaxDirnumSize;
1268       proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, i, 4, TRUE);
1269       break;
1270
1271     case 0x9d : /* stationRegisterReject */
1272       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);
1273       break;
1274
1275     case 0x9e : /* serverRes */
1276       for (i = 0; i < StationMaxServers; i++) {
1277         proto_tree_add_item(skinny_tree, hf_skinny_serverIdentifier, tvb, offset+12+(i*StationMaxServers), StationMaxServerNameSize, TRUE);
1278       }
1279       j = offset+12+(i*StationMaxServers);
1280       for (i = 0; i < StationMaxServers; i++) {
1281         proto_tree_add_item(skinny_tree, hf_skinny_serverListenPort, tvb, j+(i*4), 4,  TRUE);
1282       }
1283       j = j+(i*4);
1284       for (i = 0; i < StationMaxServers; i++) {
1285         proto_tree_add_item(skinny_tree, hf_skinny_serverIpAddress, tvb, j+(i*4), 4, TRUE);
1286       }
1287       break;
1288
1289     case 0x9f :   /* reset */
1290       proto_tree_add_item(skinny_tree, hf_skinny_deviceResetType, tvb, offset+12, 4, TRUE);
1291       break;
1292
1293     case 0x101 : /* startMulticastMediaReception*/
1294       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1295       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1296       proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
1297       proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
1298       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1299       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
1300       proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType, tvb, offset+36, 4, TRUE);
1301       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+40, 4, TRUE);
1302       break;
1303
1304     case 0x102 : /* startMulticateMediaTermination*/
1305       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1306       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1307       proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
1308       proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
1309       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1310       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
1311       proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue, tvb, offset+36, 4, TRUE);
1312       proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression, tvb, offset+40, 4, TRUE);
1313       proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+44, 2, TRUE);
1314       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+48, 4, TRUE);
1315       break;
1316
1317     case 0x103 : /* stopMulticastMediaReception*/
1318       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1319       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1320       break;
1321
1322     case 0x104 : /* stopMulticastMediaTermination*/
1323       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1324       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1325       break;
1326
1327     case 0x105 : /* open receive channel */
1328       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID,            tvb, offset+12, 4, TRUE);
1329       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID,         tvb, offset+16, 4, TRUE);
1330       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize,   tvb, offset+20, 4, TRUE);
1331       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability,       tvb, offset+24, 4, TRUE);
1332       proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType,          tvb, offset+28, 4, TRUE);
1333       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate,             tvb, offset+32, 4, TRUE);
1334       break;
1335
1336     case 0x106 :  /* closeReceiveChannel */
1337       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1338       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1339       break;
1340
1341     case 0x107 :  /* connectionStatisticsReq */
1342
1343       i = 12;
1344       proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, i, StationMaxDirnumSize, TRUE);
1345       i = 12 + StationMaxDirnumSize;
1346       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
1347       i = i+4;
1348       proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, i, 4, TRUE);
1349       break;
1350
1351     case 0x108 :   /* softkeyTemplateResMessage */
1352       proto_tree_add_item(skinny_tree, hf_skinny_softKeyOffset, tvb, offset+12, 4, TRUE);
1353       softKeyCount = tvb_get_letohl(tvb, offset+16);
1354       proto_tree_add_uint(skinny_tree, hf_skinny_softKeyCount, tvb, offset+16, 4, softKeyCount);
1355       proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeyCount, tvb, offset+20, 4, TRUE);
1356       for (i = 0; ((i < StationMaxSoftKeyDefinition) && (i < softKeyCount)); i++){
1357         proto_tree_add_item(skinny_tree, hf_skinny_softKeyLabel, tvb, offset+(i*20)+24, StationMaxSoftKeyLabelSize, TRUE);
1358         proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+(i*20)+40, 4, TRUE);
1359       }
1360       /* there is more data here, but it doesn't make a whole lot of sense, I imagine
1361        * it's just some not zero'd out stuff in the packet or...
1362        */
1363       break;
1364
1365     case 0x109 : /* softkeysetres */
1366       proto_tree_add_item(skinny_tree, hf_skinny_softKeySetOffset, tvb, offset+12, 4, TRUE);
1367       softKeySetCount = tvb_get_letohl(tvb, offset+16);
1368       proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetCount, tvb, offset+16, 4, softKeySetCount);
1369       proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeySetCount, tvb, offset+20, 4, TRUE);
1370       for (i = 0; ((i < StationMaxSoftKeySetDefinition) && (i < softKeySetCount)); i++) {
1371         proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+24+(i*48) , 1, i);
1372         for (j = 0; j < StationMaxSoftKeyIndex; j++) {
1373           proto_tree_add_item(skinny_tree, hf_skinny_softKeyTemplateIndex, tvb, offset+24+(i*48)+j, 1, TRUE);
1374         }
1375         for (j = 0; j < StationMaxSoftKeyIndex; j++) {
1376           proto_tree_add_item(skinny_tree, hf_skinny_softKeyInfoIndex, tvb, offset+24+(i*48)+StationMaxSoftKeyIndex+(j*2), 2, TRUE);
1377         }
1378       }
1379       break;
1380
1381     case 0x110 : /* selectSoftKeys */
1382       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1383       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1384       proto_tree_add_item(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+20, 4, TRUE);
1385       validKeyMask = tvb_get_letohs(tvb, offset + 24);
1386       skm = proto_tree_add_uint(skinny_tree, hf_skinny_softKeyMap, tvb, offset + 24, 1, validKeyMask);
1387       skm_tree = proto_item_add_subtree(skm, ett_skinny_softKeyMap);
1388       proto_tree_add_boolean(skm_tree, hf_skinny_softKey0,  tvb, offset + 24, 1, validKeyMask);
1389       proto_tree_add_boolean(skm_tree, hf_skinny_softKey1,  tvb, offset + 24, 1, validKeyMask);
1390       proto_tree_add_boolean(skm_tree, hf_skinny_softKey2,  tvb, offset + 24, 1, validKeyMask);
1391       proto_tree_add_boolean(skm_tree, hf_skinny_softKey3,  tvb, offset + 24, 1, validKeyMask);
1392       proto_tree_add_boolean(skm_tree, hf_skinny_softKey4,  tvb, offset + 24, 1, validKeyMask);
1393       proto_tree_add_boolean(skm_tree, hf_skinny_softKey5,  tvb, offset + 24, 1, validKeyMask);
1394       proto_tree_add_boolean(skm_tree, hf_skinny_softKey6,  tvb, offset + 24, 1, validKeyMask);
1395       proto_tree_add_boolean(skm_tree, hf_skinny_softKey7,  tvb, offset + 24, 1, validKeyMask);
1396       proto_tree_add_boolean(skm_tree, hf_skinny_softKey8,  tvb, offset + 24, 1, validKeyMask);
1397       proto_tree_add_boolean(skm_tree, hf_skinny_softKey9,  tvb, offset + 24, 1, validKeyMask);
1398       proto_tree_add_boolean(skm_tree, hf_skinny_softKey10, tvb, offset + 24, 1, validKeyMask);
1399       proto_tree_add_boolean(skm_tree, hf_skinny_softKey11, tvb, offset + 24, 1, validKeyMask);
1400       proto_tree_add_boolean(skm_tree, hf_skinny_softKey12, tvb, offset + 24, 1, validKeyMask);
1401       proto_tree_add_boolean(skm_tree, hf_skinny_softKey13, tvb, offset + 24, 1, validKeyMask);
1402       proto_tree_add_boolean(skm_tree, hf_skinny_softKey14, tvb, offset + 24, 1, validKeyMask);
1403       proto_tree_add_boolean(skm_tree, hf_skinny_softKey15, tvb, offset + 24, 1, validKeyMask);
1404       break;
1405
1406     case 0x111 : /* callState */
1407       proto_tree_add_item(skinny_tree, hf_skinny_callState, tvb, offset+12, 4, TRUE);
1408       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
1409       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
1410       break;
1411
1412     case 0x112 : /* displayPromptStatus */
1413       proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
1414       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayPromptStatusSize, TRUE);
1415       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+48, 4, TRUE);
1416       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+52, 4, TRUE);
1417       break;
1418
1419     case 0x113: /* clearPrompt */
1420       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance  , tvb, offset+12, 4, TRUE);
1421       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1422       break;
1423
1424     case 0x114 : /* displayNotify */
1425       proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
1426       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayNotifySize , TRUE);
1427       break;
1428
1429     case 0x116 : /* activateCallPlane */
1430       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1431       break;
1432
1433     case 0x118 :    /* unregisterAckMessage */
1434       proto_tree_add_item(skinny_tree, hf_skinny_deviceUnregisterStatus, tvb, offset+12, 4, TRUE);
1435       break;
1436
1437     case 0x119 : /* backSpaceReq */
1438       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1439       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1440       break;
1441
1442     case 0x11B : /* registerTokenReject */
1443       proto_tree_add_item(skinny_tree, hf_skinny_tokenRejWaitTime, tvb, offset+12, 4, TRUE);
1444       break;
1445
1446     case 0x11D : /* new message */
1447       unknownLong       = tvb_get_letohl(tvb, offset+36);
1448       proto_tree_add_uint(skinny_tree, hf_skinny_unknown, tvb, offset+36, 4, unknownLong);
1449       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+40, 4, TRUE);
1450       break;
1451
1452
1453
1454     default:
1455       break;
1456     }
1457   }
1458 }
1459
1460 /* Code to actually dissect the packets */
1461 static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1462 {
1463   /* The general structure of a packet: {IP-Header|TCP-Header|n*SKINNY}
1464    * SKINNY-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
1465    */
1466   /* Header fields */
1467   volatile guint32 hdr_data_length;
1468   guint32 hdr_reserved;
1469
1470   /* check, if this is really an SKINNY packet, they start with a length + 0 */
1471
1472   /* get relevant header information */
1473   hdr_data_length = tvb_get_letohl(tvb, 0);
1474   hdr_reserved    = tvb_get_letohl(tvb, 4);
1475
1476   /*  data_size       = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
1477
1478   /* hdr_data_length > 1024 is just a heuristic. Better values/checks welcome */
1479   if (hdr_data_length < 4 || hdr_data_length > 1024 || hdr_reserved != 0) {
1480     /* Not an SKINNY packet, just happened to use the same port */
1481     call_dissector(data_handle,tvb, pinfo, tree);
1482     return;
1483   }
1484
1485   /* Make entries in Protocol column and Info column on summary display */
1486   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1487     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY");
1488   }
1489
1490   if (check_col(pinfo->cinfo, COL_INFO)) {
1491     col_set_str(pinfo->cinfo, COL_INFO, "Skinny Client Control Protocol");
1492   }
1493
1494   tcp_dissect_pdus(tvb, pinfo, tree, skinny_desegment, 4,
1495         get_skinny_pdu_len, dissect_skinny_pdu);
1496 }
1497
1498 /* Register the protocol with Ethereal */
1499 void
1500 proto_register_skinny(void)
1501 {
1502
1503   /* Setup list of header fields */
1504   static hf_register_info hf[] = {
1505     { &hf_skinny_data_length,
1506       { "Data Length", "skinny.data_length",
1507         FT_UINT32, BASE_DEC, NULL, 0x0,
1508         "Number of bytes in the data portion.",
1509         HFILL }
1510     },
1511     { &hf_skinny_reserved,
1512       { "Reserved", "skinny.reserved",
1513         FT_UINT32, BASE_HEX, NULL, 0x0,
1514         "Reserved for future(?) use.",
1515         HFILL }
1516     },
1517     /* FIXME: Enable use of message name ???  */
1518     { &hf_skinny_messageid,
1519       { "Message ID", "skinny.messageid",
1520         FT_UINT32, BASE_HEX, VALS(message_id), 0x0,
1521         "The function requested/done with this message.",
1522         HFILL }
1523     },
1524
1525     { &hf_skinny_deviceName,
1526       { "DeviceName", "skinny.deviceName",
1527         FT_STRING, BASE_NONE, NULL, 0x0,
1528         "The device name of the phone.",
1529         HFILL }
1530     },
1531
1532     { &hf_skinny_stationUserId,
1533       { "StationUserId", "skinny.stationUserId",
1534         FT_UINT32, BASE_DEC, NULL, 0x0,
1535         "The station user id.",
1536         HFILL }
1537     },
1538
1539     { &hf_skinny_stationInstance,
1540       { "StationInstance", "skinny.stationInstance",
1541         FT_UINT32, BASE_DEC, NULL, 0x0,
1542         "The stations instance.",
1543         HFILL }
1544     },
1545
1546     { &hf_skinny_deviceType,
1547       { "DeviceType", "skinny.deviceType",
1548         FT_UINT32, BASE_DEC, VALS(deviceTypes), 0x0,
1549         "DeviceType of the station.",
1550         HFILL }
1551     },
1552
1553     { &hf_skinny_maxStreams,
1554       { "MaxStreams", "skinny.maxStreams",
1555         FT_UINT32, BASE_DEC, NULL, 0x0,
1556         "32 bit unsigned integer indicating the maximum number of simultansous RTP duplex streams that the client can handle.",
1557         HFILL }
1558     },
1559
1560     { &hf_skinny_stationIpPort,
1561       { "StationIpPort", "skinny.stationIpPort",
1562         FT_UINT16, BASE_DEC, NULL, 0x0,
1563         "The station IP port",
1564         HFILL }
1565     },
1566
1567     { &hf_skinny_stationKeypadButton,
1568       { "KeypadButton", "skinny.stationKeypadButton",
1569         FT_UINT32, BASE_HEX, VALS(keypadButtons), 0x0,
1570         "The button pressed on the phone.",
1571         HFILL }
1572     },
1573
1574     { &hf_skinny_calledParty,
1575       { "CalledParty", "skinny.calledParty",
1576         FT_STRING, BASE_NONE, NULL, 0x0,
1577         "The number called.",
1578         HFILL }
1579     },
1580
1581     { &hf_skinny_stimulus,
1582       { "Stimulus", "skinny.stimulus",
1583         FT_UINT32, BASE_HEX, VALS(deviceStimuli), 0x0,
1584         "Reason for the device stimulus message.",
1585         HFILL }
1586     },
1587
1588     { &hf_skinny_stimulusInstance,
1589       { "StimulusInstance", "skinny.stimulusInstance",
1590         FT_UINT32, BASE_DEC, NULL, 0x0,
1591         "The instance of the stimulus",
1592         HFILL }
1593     },
1594
1595     { &hf_skinny_lineNumber,
1596       { "LineNumber", "skinny.lineNumber",
1597         FT_UINT32, BASE_DEC, NULL, 0x0,
1598         "Line Number",
1599         HFILL }
1600     },
1601
1602     { &hf_skinny_speedDialNumber,
1603       { "SpeedDialNumber", "skinny.speedDialNumber",
1604         FT_UINT32, BASE_DEC, NULL, 0x0,
1605         "Which speed dial number",
1606         HFILL }
1607     },
1608
1609     { &hf_skinny_capCount,
1610       { "CapCount", "skinny.capCount",
1611         FT_UINT32, BASE_DEC, NULL, 0x0,
1612         "How many capabilities",
1613         HFILL }
1614     },
1615
1616     { &hf_skinny_payloadCapability,
1617       { "PayloadCapability", "skinny.payloadCapability",
1618         FT_UINT32, BASE_DEC, VALS(mediaPayloads), 0x0,
1619         "The payload capability for this media capability structure.",
1620         HFILL }
1621     },
1622
1623     { &hf_skinny_maxFramesPerPacket,
1624       { "MaxFramesPerPacket", "skinny.maxFramesPerPacket",
1625         FT_UINT16, BASE_DEC, NULL, 0x0,
1626         "Max frames per packet",
1627         HFILL }
1628     },
1629
1630     { &hf_skinny_alarmSeverity,
1631       { "AlarmSeverity", "skinny.alarmSeverity",
1632         FT_UINT32, BASE_DEC, VALS(alarmSeverities), 0x0,
1633         "The severity of the reported alarm.",
1634         HFILL }
1635     },
1636
1637     { &hf_skinny_alarmParam1,
1638       { "AlarmParam1", "skinny.alarmParam1",
1639         FT_UINT32, BASE_HEX, NULL, 0x0,
1640         "An as yet undecoded param1 value from the alarm message",
1641         HFILL }
1642     },
1643
1644     { &hf_skinny_alarmParam2,
1645       { "AlarmParam2", "skinny.alarmParam2",
1646         FT_IPv4, BASE_NONE, NULL, 0x0,
1647         "This is the second alarm parameter i think it's an ip address",
1648         HFILL }
1649     },
1650
1651     { &hf_skinny_receptionStatus,
1652       { "ReceptionStatus", "skinny.receptionStatus",
1653         FT_UINT32, BASE_DEC, VALS(multicastMediaReceptionStatus), 0x0,
1654         "The current status of the multicast media.",
1655         HFILL }
1656     },
1657
1658     { &hf_skinny_passThruPartyID,
1659       { "PassThruPartyID", "skinny.passThruPartyID",
1660         FT_UINT32, BASE_DEC, NULL, 0x0,
1661         "The pass thru party id",
1662         HFILL }
1663     },
1664
1665     { &hf_skinny_ORCStatus,
1666       { "OpenReceiveChannelStatus", "skinny.openReceiveChannelStatus",
1667         FT_UINT32, BASE_DEC, VALS(openReceiveChanStatus), 0x0,
1668         "The status of the opened receive channel.",
1669         HFILL }
1670     },
1671
1672     { &hf_skinny_ipAddress,
1673       { "IP Address", "skinny.ipAddress",
1674         FT_IPv4, BASE_NONE, NULL, 0x0,
1675         "An IP address",
1676         HFILL }
1677     },
1678
1679     { &hf_skinny_portNumber,
1680       { "Port Number", "skinny.portNumber",
1681         FT_UINT32, BASE_DEC, NULL, 0x0,
1682         "A port number",
1683         HFILL }
1684     },
1685
1686     { &hf_skinny_statsProcessingType,
1687       { "StatsProcessingType", "skinny.statsProcessingType",
1688         FT_UINT32, BASE_DEC, VALS(statsProcessingTypes), 0x0,
1689         "What do do after you send the stats.",
1690         HFILL }
1691     },
1692
1693     { &hf_skinny_callIdentifier,
1694       { "Call Identifier", "skinny.callIdentifier",
1695         FT_UINT32, BASE_DEC, NULL, 0x0,
1696         "Call identifier for this call.",
1697         HFILL }
1698     },
1699
1700     { &hf_skinny_packetsSent,
1701       { "Packets Sent", "skinny.packetsSent",
1702         FT_UINT32, BASE_DEC, NULL, 0x0,
1703         "Packets Sent during the call.",
1704         HFILL }
1705     },
1706
1707     { &hf_skinny_octetsSent,
1708       { "Octets Sent", "skinny.octetsSent",
1709         FT_UINT32, BASE_DEC, NULL, 0x0,
1710         "Octets sent during the call.",
1711         HFILL }
1712     },
1713
1714     { &hf_skinny_packetsRecv,
1715       { "Packets Received", "skinny.packetsRecv",
1716         FT_UINT32, BASE_DEC, NULL, 0x0,
1717         "Packets received during the call.",
1718         HFILL }
1719     },
1720
1721     { &hf_skinny_octetsRecv,
1722       { "Octets Received", "skinny.octetsRecv",
1723         FT_UINT32, BASE_DEC, NULL, 0x0,
1724         "Octets received during the call.",
1725         HFILL }
1726     },
1727
1728     { &hf_skinny_packetsLost,
1729       { "Packets Lost", "skinny.packetsLost",
1730         FT_UINT32, BASE_DEC, NULL, 0x0,
1731         "Packets lost during the call.",
1732         HFILL }
1733     },
1734
1735     { &hf_skinny_latency,
1736       { "Latency(ms)", "skinny.latency",
1737         FT_UINT32, BASE_DEC, NULL, 0x0,
1738         "Average packet latency during the call.",
1739         HFILL }
1740     },
1741
1742     { &hf_skinny_jitter,
1743       { "Jitter", "skinny.jitter",
1744         FT_UINT32, BASE_DEC, NULL, 0x0,
1745         "Average jitter during the call.",
1746         HFILL }
1747     },
1748
1749     { &hf_skinny_directoryNumber,
1750       { "Directory Number", "skinny.directoryNumber",
1751         FT_STRING, BASE_NONE, NULL, 0x0,
1752         "The number we are reporting statistics for.",
1753         HFILL }
1754     },
1755
1756     { &hf_skinny_lineInstance,
1757       { "Line Instance", "skinny.lineInstance",
1758         FT_UINT32, BASE_DEC, NULL, 0x0,
1759         "The display call plane associated with this call.",
1760         HFILL }
1761     },
1762
1763     { &hf_skinny_softKeyEvent,
1764       { "SoftKeyEvent", "skinny.softKeyEvent",
1765         FT_UINT32, BASE_DEC, VALS(softKeyEvents), 0x0,
1766         "Which softkey event is being reported.",
1767         HFILL }
1768     },
1769
1770     { &hf_skinny_keepAliveInterval,
1771       { "KeepAliveInterval", "skinny.keepAliveInterval",
1772         FT_UINT32, BASE_DEC, NULL, 0x0,
1773         "How often are keep alives exchanges between the client and the call manager.",
1774         HFILL }
1775     },
1776
1777     { &hf_skinny_secondaryKeepAliveInterval,
1778       { "SecondaryKeepAliveInterval", "skinny.secondaryKeepAliveInterval",
1779         FT_UINT32, BASE_DEC, NULL, 0x0,
1780         "How often are keep alives exchanges between the client and the secondary call manager.",
1781         HFILL }
1782     },
1783
1784     { &hf_skinny_dateTemplate,
1785       { "DateTemplate", "skinny.dateTemplate",
1786         FT_STRING, BASE_NONE, NULL, 0x0,
1787         "The display format for the date/time on the phone.",
1788         HFILL }
1789     },
1790
1791     { &hf_skinny_buttonOffset,
1792       { "ButtonOffset", "skinny.buttonOffset",
1793         FT_UINT32, BASE_DEC, NULL, 0x0,
1794         "Offset is the number of the first button referenced by this message.",
1795         HFILL }
1796     },
1797
1798     { &hf_skinny_buttonCount,
1799       { "ButtonCount", "skinny.buttonCount",
1800         FT_UINT32, BASE_DEC, NULL, 0x0,
1801         "Number of (VALID) button definitions in this message.",
1802         HFILL }
1803     },
1804
1805     { &hf_skinny_totalButtonCount,
1806       { "TotalButtonCount", "skinny.totalButtonCount",
1807         FT_UINT32, BASE_DEC, NULL, 0x0,
1808         "The total number of buttons defined for this phone.",
1809         HFILL }
1810     },
1811
1812     { &hf_skinny_buttonInstanceNumber,
1813       { "InstanceNumber", "skinny.buttonInstanceNumber",
1814         FT_UINT8, BASE_HEX, VALS(keypadButtons), 0x0,
1815         "The button instance number for a button or the StationKeyPad value, repeats allowed.",
1816         HFILL }
1817     },
1818
1819     { &hf_skinny_buttonDefinition,
1820       { "ButtonDefinition", "skinny.buttonDefinition",
1821         FT_UINT8, BASE_HEX, VALS(buttonDefinitions), 0x0,
1822         "The button type for this instance (ie line, speed dial, ....",
1823         HFILL }
1824     },
1825
1826     { &hf_skinny_softKeyOffset,
1827       { "SoftKeyOffset", "skinny.softKeyOffset",
1828         FT_UINT32, BASE_DEC, NULL, 0x0,
1829         "The offset for the first soft key in this message.",
1830         HFILL }
1831     },
1832
1833     { &hf_skinny_softKeyCount,
1834       { "SoftKeyCount", "skinny.softKeyCount",
1835         FT_UINT32, BASE_DEC, NULL, 0x0,
1836         "The number of valid softkeys in this message.",
1837         HFILL }
1838     },
1839
1840     { &hf_skinny_totalSoftKeyCount,
1841       { "TotalSoftKeyCount", "skinny.totalSoftKeyCount",
1842         FT_UINT32, BASE_DEC, NULL, 0x0,
1843         "The total number of softkeys for this device.",
1844         HFILL }
1845     },
1846
1847     { &hf_skinny_softKeyLabel,
1848       { "SoftKeyLabel", "skinny.softKeyLabel",
1849         FT_STRING, BASE_NONE, NULL, 0x0,
1850         "The text label for this soft key.",
1851         HFILL }
1852     },
1853
1854     { &hf_skinny_softKeySetOffset,
1855       { "SoftKeySetOffset", "skinny.softKeySetOffset",
1856         FT_UINT32, BASE_DEC, NULL, 0x0,
1857         "The offset for the first soft key set in this message.",
1858         HFILL }
1859     },
1860
1861     { &hf_skinny_softKeySetCount,
1862       { "SoftKeySetCount", "skinny.softKeySetCount",
1863         FT_UINT32, BASE_DEC, NULL, 0x0,
1864         "The number of valid softkey sets in this message.",
1865         HFILL }
1866     },
1867
1868     { &hf_skinny_totalSoftKeySetCount,
1869       { "TotalSoftKeySetCount", "skinny.totalSoftKeySetCount",
1870         FT_UINT32, BASE_DEC, NULL, 0x0,
1871         "The total number of softkey sets for this device.",
1872         HFILL }
1873     },
1874
1875     { &hf_skinny_softKeyTemplateIndex,
1876       { "SoftKeyTemplateIndex", "skinny.softKeyTemplateIndex",
1877         FT_UINT8, BASE_DEC, VALS(softKeyEvents), 0x0,
1878         "Array of size 16 8-bit unsigned ints containing an index into the softKeyTemplate.",
1879         HFILL }
1880     },
1881
1882     { &hf_skinny_softKeyInfoIndex,
1883       { "SoftKeyInfoIndex", "skinny.softKeyInfoIndex",
1884         FT_UINT16, BASE_DEC, VALS(softKeyIndexes), 0x0,
1885         "Array of size 16 16-bit unsigned integers containing an index into the soft key description information.",
1886         HFILL }
1887     },
1888
1889     { &hf_skinny_softKeySetDescription,
1890       { "SoftKeySet", "skinny.softKeySetDescription",
1891         FT_UINT8, BASE_DEC, VALS(keySetNames), 0x0,
1892         "A text description of what this softkey when this softkey set is displayed",
1893         HFILL }
1894     },
1895
1896     { &hf_skinny_softKeyMap,
1897       { "SoftKeyMap","skinny.softKeyMap",
1898         FT_UINT16, BASE_HEX, NULL, 0x0,
1899         "",
1900         HFILL }
1901     },
1902
1903     { &hf_skinny_softKey0,
1904       { "SoftKey0", "skinny.softKeyMap.0",
1905         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY0,
1906         "",
1907         HFILL }
1908     },
1909
1910     { &hf_skinny_softKey1,
1911       { "SoftKey1", "skinny.softKeyMap.1",
1912         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY1,
1913         "",
1914         HFILL }
1915     },
1916
1917     { &hf_skinny_softKey2,
1918       { "SoftKey2", "skinny.softKeyMap.2",
1919         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY2,
1920         "",
1921         HFILL }
1922     },
1923
1924     { &hf_skinny_softKey3,
1925       { "SoftKey3", "skinny.softKeyMap.3",
1926         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY3,
1927         "",
1928         HFILL }
1929     },
1930
1931     { &hf_skinny_softKey4,
1932       { "SoftKey4", "skinny.softKeyMap.4",
1933         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY4,
1934         "",
1935         HFILL }
1936     },
1937
1938     { &hf_skinny_softKey5,
1939       { "SoftKey5", "skinny.softKeyMap.5",
1940         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY5,
1941         "",
1942         HFILL }
1943     },
1944
1945     { &hf_skinny_softKey6,
1946       { "SoftKey6", "skinny.softKeyMap.6",
1947         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY6,
1948         "",
1949         HFILL }
1950     },
1951
1952     { &hf_skinny_softKey7,
1953       { "SoftKey7", "skinny.softKeyMap.7",
1954         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY7,
1955         "",
1956         HFILL }
1957     },
1958
1959     { &hf_skinny_softKey8,
1960       { "SoftKey8", "skinny.softKeyMap.8",
1961         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY8,
1962         "",
1963         HFILL }
1964     },
1965
1966     { &hf_skinny_softKey9,
1967       { "SoftKey9", "skinny.softKeyMap.9",
1968         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY9,
1969         "",
1970         HFILL }
1971     },
1972
1973     { &hf_skinny_softKey10,
1974       { "SoftKey10", "skinny.softKeyMap.10",
1975         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY10,
1976         "",
1977         HFILL }
1978     },
1979
1980     { &hf_skinny_softKey11,
1981       { "SoftKey11", "skinny.softKeyMap.11",
1982         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY11,
1983         "",
1984         HFILL }
1985     },
1986
1987     { &hf_skinny_softKey12,
1988       { "SoftKey12", "skinny.softKeyMap.12",
1989         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY12,
1990         "",
1991         HFILL }
1992     },
1993
1994     { &hf_skinny_softKey13,
1995       { "SoftKey13", "skinny.softKeyMap.13",
1996         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY13,
1997         "",
1998         HFILL }
1999     },
2000
2001     { &hf_skinny_softKey14,
2002       { "SoftKey14", "skinny.softKeyMap.14",
2003         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY14,
2004         "",
2005         HFILL }
2006     },
2007
2008     { &hf_skinny_softKey15,
2009       { "SoftKey15", "skinny.softKeyMap.15",
2010         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY15,
2011         "",
2012         HFILL }
2013     },
2014
2015     { &hf_skinny_lampMode,
2016       { "LampMode", "skinny.lampMode",
2017         FT_UINT32, BASE_DEC, VALS(stationLampModes), 0x0,
2018         "The lamp mode",
2019         HFILL }
2020     },
2021
2022     { &hf_skinny_messageTimeOutValue,
2023       { "Message Timeout", "skinny.messageTimeOutValue",
2024         FT_UINT32, BASE_DEC, NULL, 0x0,
2025         "The timeout in seconds for this message",
2026         HFILL }
2027     },
2028
2029     { &hf_skinny_displayMessage,
2030       { "DisplayMessage", "skinny.displayMessage",
2031         FT_STRING, BASE_NONE, NULL, 0x0,
2032         "The message displayed on the phone.",
2033         HFILL }
2034     },
2035
2036     { &hf_skinny_lineDirNumber,
2037       { "Line Dir Number", "skinny.lineDirNumber",
2038         FT_STRING, BASE_NONE, NULL, 0x0,
2039         "The directory number for this line.",
2040         HFILL }
2041     },
2042
2043     { &hf_skinny_lineFullyQualifiedDisplayName,
2044       { "DisplayName", "skinny.fqdn",
2045         FT_STRING, BASE_NONE, NULL, 0x0,
2046         "The full display name for this line.",
2047         HFILL }
2048     },
2049
2050     { &hf_skinny_speedDialDirNumber,
2051       { "SpeedDial Number", "skinny.speedDialDirNum",
2052         FT_STRING, BASE_NONE, NULL, 0x0,
2053         "the number to dial for this speed dial.",
2054         HFILL }
2055     },
2056
2057     { &hf_skinny_speedDialDisplayName,
2058       { "SpeedDial Display", "skinny.speedDialDisplay",
2059         FT_STRING, BASE_NONE, NULL, 0x0,
2060         "The text to display for this speed dial.",
2061         HFILL }
2062     },
2063
2064     { &hf_skinny_dateYear,
2065       { "Year", "skinny.year",
2066         FT_UINT32, BASE_DEC, NULL, 0x0,
2067         "The current year",
2068         HFILL }
2069     },
2070
2071     { &hf_skinny_dateMonth,
2072       { "Month", "skinny.month",
2073         FT_UINT32, BASE_DEC, NULL, 0x0,
2074         "The current month",
2075         HFILL }
2076     },
2077
2078     { &hf_skinny_dayOfWeek,
2079       { "DayOfWeek", "skinny.dayOfWeek",
2080         FT_UINT32, BASE_DEC, NULL, 0x0,
2081         "The day of the week",
2082         HFILL }
2083     },
2084
2085     { &hf_skinny_dateDay,
2086       { "Day", "skinny.day",
2087         FT_UINT32, BASE_DEC, NULL, 0x0,
2088         "The day of the current month",
2089         HFILL }
2090     },
2091
2092     { &hf_skinny_dateHour,
2093       { "Hour", "skinny.hour",
2094         FT_UINT32, BASE_DEC, NULL, 0x0,
2095         "Hour of the day",
2096         HFILL }
2097     },
2098
2099     { &hf_skinny_dateMinute,
2100       { "Minute", "skinny.minute",
2101         FT_UINT32, BASE_DEC, NULL, 0x0,
2102         "Minute",
2103         HFILL }
2104     },
2105
2106     { &hf_skinny_dateSeconds,
2107       { "Seconds", "skinny.dateSeconds",
2108         FT_UINT32, BASE_DEC, NULL, 0x0,
2109         "Seconds",
2110         HFILL }
2111     },
2112
2113     { &hf_skinny_dateMilliseconds,
2114       { "Milliseconds", "skinny.dateMilliseconds",
2115         FT_UINT32, BASE_DEC, NULL, 0x0,
2116         "Milliseconds",
2117         HFILL }
2118     },
2119
2120     { &hf_skinny_timeStamp,
2121       { "Timestamp", "skinny.timeStamp",
2122         FT_UINT32, BASE_DEC, NULL, 0x0,
2123         "Time stamp for the call reference",
2124         HFILL }
2125     },
2126     { &hf_skinny_callState,
2127       { "CallState", "skinny.callState",
2128         FT_UINT32, BASE_DEC, VALS(skinny_stationCallStates), 0x0,
2129         "The D channel call state of the call",
2130         HFILL }
2131     },
2132
2133     { &hf_skinny_deviceTone,
2134       { "Tone", "skinny.deviceTone",
2135         FT_UINT32, BASE_HEX, VALS(skinny_deviceTones), 0x0,
2136         "Which tone to play",
2137         HFILL }
2138     },
2139
2140     { &hf_skinny_callingPartyName,
2141       { "Calling Party Name", "skinny.callingPartyName",
2142         FT_STRING, BASE_NONE, NULL, 0x0,
2143         "The passed name of the calling party.",
2144         HFILL }
2145     },
2146
2147     { &hf_skinny_callingParty,
2148       { "Calling Party", "skinny.callingPartyName",
2149         FT_STRING, BASE_NONE, NULL, 0x0,
2150         "The passed number of the calling party.",
2151         HFILL }
2152     },
2153
2154     { &hf_skinny_calledPartyName,
2155       { "Called Party Name", "skinny.calledPartyName",
2156         FT_STRING, BASE_NONE, NULL, 0x0,
2157         "The name of the party we are calling.",
2158         HFILL }
2159     },
2160
2161     { &hf_skinny_callType,
2162       { "Call Type", "skinny.callType",
2163         FT_UINT32, BASE_DEC, VALS(skinny_callTypes), 0x0,
2164         "What type of call, in/out/etc",
2165         HFILL }
2166     },
2167
2168     { &hf_skinny_originalCalledPartyName,
2169       { "Original Called Party Name", "skinny.originalCalledPartyName",
2170         FT_STRING, BASE_NONE, NULL, 0x0,
2171         "name of the original person who placed the call.",
2172         HFILL }
2173     },
2174
2175     { &hf_skinny_originalCalledParty,
2176       { "Original Called Party", "skinny.originalCalledParty",
2177         FT_STRING, BASE_NONE, NULL, 0x0,
2178         "The number of the original calling party.",
2179         HFILL }
2180     },
2181
2182     { &hf_skinny_ringType,
2183       { "Ring Type", "skinny.ringType",
2184         FT_UINT32, BASE_HEX, VALS(skinny_ringTypes), 0x0,
2185         "What type of ring to play",
2186         HFILL }
2187     },
2188
2189     { &hf_skinny_speakerMode,
2190       { "Speaker", "skinny.speakerMode",
2191         FT_UINT32, BASE_HEX, VALS(skinny_speakerModes), 0x0,
2192         "This message sets the speaker mode on/off",
2193         HFILL }
2194     },
2195
2196     { &hf_skinny_remoteIpAddr,
2197       { "Remote Ip Address", "skinny.remoteIpAddr",
2198         FT_IPv4, BASE_NONE, NULL, 0x0,
2199         "The remote end ip address for this stream",
2200         HFILL }
2201     },
2202
2203     { &hf_skinny_remotePortNumber,
2204       { "Remote Port", "skinny.remotePortNumber",
2205         FT_UINT32, BASE_DEC, NULL, 0x0,
2206         "The remote port number listening for this stream",
2207         HFILL }
2208     },
2209
2210     { &hf_skinny_millisecondPacketSize,
2211       { "MS/Packet", "skinny.millisecondPacketSize",
2212         FT_UINT32, BASE_DEC, NULL, 0x0,
2213         "The number of milliseconds of conversation in each packet",
2214         HFILL }
2215     },
2216
2217     { &hf_skinny_precedenceValue,
2218       { "Precedence", "skinny.precedenceValue",
2219         FT_UINT32, BASE_DEC, NULL, 0x0,
2220         "Precedence value",
2221         HFILL }
2222     },
2223
2224     { &hf_skinny_silenceSuppression,
2225       { "Silence Suppression", "skinny.silenceSuppression",
2226         FT_UINT32, BASE_HEX, VALS(skinny_silenceSuppressionModes), 0x0,
2227         "Mode for silence suppression",
2228         HFILL }
2229     },
2230
2231     { &hf_skinny_g723BitRate,
2232       { "G723 BitRate", "skinny.g723BitRate",
2233         FT_UINT32, BASE_DEC, VALS(skinny_g723BitRates), 0x0,
2234         "The G723 bit rate for this stream/JUNK if not g723 stream",
2235         HFILL }
2236     },
2237
2238     { &hf_skinny_conferenceID,
2239       { "Conference ID", "skinny.conferenceID",
2240         FT_UINT32, BASE_DEC, NULL, 0x0,
2241         "The conference ID",
2242         HFILL }
2243     },
2244
2245     { &hf_skinny_deviceResetType,
2246       { "Reset Type", "skinny.deviceResetType",
2247         FT_UINT32, BASE_DEC, VALS(skinny_deviceResetTypes), 0x0,
2248         "How the devices it to be reset (reset/restart)",
2249         HFILL }
2250     },
2251
2252     { &hf_skinny_echoCancelType,
2253       { "Echo Cancel Type", "skinny.echoCancelType",
2254         FT_UINT32, BASE_DEC, VALS(skinny_echoCancelTypes), 0x0,
2255         "Is echo cancelling enabled or not",
2256         HFILL }
2257     },
2258
2259     { &hf_skinny_deviceUnregisterStatus,
2260       { "Unregister Status", "skinny.deviceUnregisterStatus",
2261         FT_UINT32, BASE_DEC, VALS(skinny_deviceUnregisterStatusTypes), 0x0,
2262         "The status of the device unregister request (*CAN* be refused)",
2263         HFILL }
2264     },
2265
2266     { &hf_skinny_hookFlashDetectMode,
2267       { "Hook Flash Mode", "skinny.hookFlashDetectMode",
2268         FT_UINT32, BASE_DEC, VALS(skinny_hookFlashDetectModes), 0x0,
2269         "Which method to use to detect that a hook flash has occured",
2270         HFILL }
2271     },
2272
2273     { &hf_skinny_detectInterval,
2274       { "HF Detect Interval", "skinny.detectInterval",
2275         FT_UINT32, BASE_DEC, NULL, 0x0,
2276         "The number of milliseconds that determines a hook flash has occured",
2277         HFILL }
2278     },
2279
2280     { &hf_skinny_microphoneMode,
2281       { "Microphone Mode", "skinny.microphoneMode",
2282         FT_UINT32, BASE_DEC, VALS(skinny_microphoneModes), 0x0,
2283         "Turns on and off the microphone on the set",
2284         HFILL }
2285     },
2286
2287     { &hf_skinny_activeForward,
2288       { "Active Forward", "skinny.activeForward",
2289         FT_UINT32, BASE_DEC, NULL, 0x0,
2290         "This is non zero to indicate that a forward is active on the line",
2291         HFILL }
2292     },
2293
2294     { &hf_skinny_forwardAllActive,
2295       { "Forward All", "skinny.forwardAllActive",
2296         FT_UINT32, BASE_DEC, NULL, 0x0,
2297         "Forward all calls",
2298         HFILL }
2299     },
2300
2301     { &hf_skinny_forwardBusyActive,
2302       { "Forward Busy", "skinny.forwardBusyActive",
2303         FT_UINT32, BASE_DEC, NULL, 0x0,
2304         "Forward calls when busy",
2305         HFILL }
2306     },
2307
2308     { &hf_skinny_forwardNoAnswerActive,
2309       { "Forward NoAns", "skinny.forwardNoAnswerActive",
2310         FT_UINT32, BASE_DEC, NULL, 0x0,
2311         "Forward only when no answer",
2312         HFILL }
2313     },
2314
2315     { &hf_skinny_forwardNumber,
2316       { "Forward Number", "skinny.forwardNumber",
2317         FT_STRING, BASE_NONE, NULL, 0x0,
2318         "The number to forward calls to.",
2319         HFILL }
2320     },
2321
2322     { &hf_skinny_userName,
2323       { "Username", "skinny.userName",
2324         FT_STRING, BASE_NONE, NULL, 0x0,
2325         "Username for this device.",
2326         HFILL }
2327     },
2328
2329     { &hf_skinny_serverName,
2330       { "Server Name", "skinny.serverName",
2331         FT_STRING, BASE_NONE, NULL, 0x0,
2332         "The server name for this device.",
2333         HFILL }
2334     },
2335
2336     { &hf_skinny_numberLines,
2337       { "Number of Lines", "skinny.numberLines",
2338         FT_UINT32, BASE_DEC, NULL, 0x0,
2339         "How many lines this device has",
2340         HFILL }
2341     },
2342
2343     { &hf_skinny_numberSpeedDials,
2344       { "Number of SpeedDials", "skinny.numberSpeedDials",
2345         FT_UINT32, BASE_DEC, NULL, 0x0,
2346         "The number of speed dials this device has",
2347         HFILL }
2348     },
2349
2350     { &hf_skinny_sessionType,
2351       { "Session Type", "skinny.sessionType",
2352         FT_UINT32, BASE_DEC, VALS(skinny_sessionTypes), 0x0,
2353         "The type of this session.",
2354         HFILL }
2355     },
2356
2357     { &hf_skinny_version,
2358       { "Version", "skinny.version",
2359         FT_STRING, BASE_NONE, NULL, 0x0,
2360         "Version.",
2361         HFILL }
2362     },
2363
2364     { &hf_skinny_mediaEnunciationType,
2365       { "Enunciation Type", "skinny.mediaEnunciationType",
2366         FT_UINT32, BASE_DEC, VALS(skinny_mediaEnunciationTypes), 0x0,
2367         "No clue.",
2368         HFILL }
2369     },
2370
2371     { &hf_skinny_serverIdentifier,
2372       { "Server Identifier", "skinny.serverIdentifier",
2373         FT_STRING, BASE_NONE, NULL, 0x0,
2374         "Server Identifier.",
2375         HFILL }
2376     },
2377
2378     { &hf_skinny_serverListenPort,
2379       { "Server Port", "skinny.serverListenPort",
2380         FT_UINT32, BASE_DEC, NULL, 0x0,
2381         "The port the server listens on.",
2382         HFILL }
2383     },
2384
2385     { &hf_skinny_serverIpAddress,
2386       { "Server Ip Address", "skinny.serverIpAddress",
2387         FT_IPv4, BASE_NONE, NULL, 0x0,
2388         "The IP address for this server",
2389         HFILL }
2390     },
2391
2392     { &hf_skinny_multicastPort,
2393       { "Multicast Port", "skinny.multicastPort",
2394         FT_UINT32, BASE_DEC, NULL, 0x0,
2395         "The multicast port the to listens on.",
2396         HFILL }
2397     },
2398
2399     { &hf_skinny_multicastIpAddress,
2400       { "Multicast Ip Address", "skinny.multicastIpAddress",
2401         FT_IPv4, BASE_NONE, NULL, 0x0,
2402         "The multicast address for this conference",
2403         HFILL }
2404     },
2405
2406     { &hf_skinny_tokenRejWaitTime,
2407       { "Retry Wait Time", "skinny.tokenRejWaitTime",
2408         FT_UINT32, BASE_DEC, NULL, 0x0,
2409         "The time to wait before retrying this token request.",
2410         HFILL }
2411     },
2412
2413     { &hf_skinny_unknown,
2414       { "Data", "skinny.unknown",
2415         FT_UINT32, BASE_HEX, NULL, 0x0,
2416         "Place holder for unknown data.",
2417         HFILL }
2418     },
2419
2420   };
2421
2422   /* Setup protocol subtree array */
2423   static gint *ett[] = {
2424     &ett_skinny,
2425     &ett_skinny_softKeyMap,
2426   };
2427
2428   module_t *skinny_module;
2429
2430   /* Register the protocol name and description */
2431   proto_skinny = proto_register_protocol("Skinny Client Control Protocol",
2432                                          "SKINNY", "skinny");
2433
2434   /* Required function calls to register the header fields and subtrees used */
2435   proto_register_field_array(proto_skinny, hf, array_length(hf));
2436   proto_register_subtree_array(ett, array_length(ett));
2437
2438   skinny_module = prefs_register_protocol(proto_skinny, NULL);
2439   prefs_register_bool_preference(skinny_module, "desegment",
2440     "Desegment all SCCP messages spanning multiple TCP segments",
2441     "Whether the SCCP dissector should desegment all messages spanning multiple TCP segments",
2442     &skinny_desegment);
2443 }
2444
2445 void
2446 proto_reg_handoff_skinny(void)
2447 {
2448   dissector_handle_t skinny_handle;
2449
2450   data_handle = find_dissector("data");
2451   skinny_handle = create_dissector_handle(dissect_skinny, proto_skinny);
2452   dissector_add("tcp.port", TCP_PORT_SKINNY, skinny_handle);
2453 }
2454
2455 /*
2456  * FIXME:
2457  *
2458  * This is the status of this decode.
2459  * Items marked as N/A in the decode field have no params to test
2460  * implemented for N/A means they exist in the switch statement
2461  * S = stubbed
2462  *
2463  *  id     message                     implemented  decode tested (via capture)
2464  *  ---------------------------------------------------------------------------
2465  *  0x0    keepAlive                       Y        N/A
2466  *  0x1    register                        Y        Y
2467  *  0x2    ipPort                          Y        Y
2468  *  0x3    keypadButton                    Y        Y
2469  *  0x4    enblocCall                      Y        N
2470  *  0x5    stimulus                        Y        N
2471  *  0x6    offHook                         Y        N/A
2472  *  0x7    onHook                          Y        N/A
2473  *  0x8    hookFlash                       Y        N/A
2474  *  0x9    forwardStatReq                  Y        N
2475  *  0xa    speedDialStatReq                Y        Y
2476  *  0xb    lineStatReq                     Y        Y
2477  *  0xc    configStatReq                   Y        N/A
2478  *  0xd    timeDateReq                     Y        N/A
2479  *  0xe    buttonTemplateReq               Y        N/A
2480  *  0xf    versionReq                      Y        N/A
2481  *  0x10   capabilitiesRes                 Y        Y -- would like more decodes
2482  *  0x11   mediaPortList                   S        N -- no info
2483  *  0x12   serverReq                       Y        N/A
2484  *  0x20   alarmMessage                    Y        Y
2485  *  0x21   multicastMediaReceptionAck      Y        N
2486  *  0x22   openReceiveChannelAck           Y        Y
2487  *  0x23   connectionStatisticsRes         Y        Y
2488  *  0x24   offHookWithCgpn                 Y        N
2489  *  0x25   softKeySetReq                   Y        N/A
2490  *  0x26   softKeyEvent                    Y        Y
2491  *  0x27   unregister                      Y        N/A
2492  *  0x28   softKeytemplateReq              Y        N/A
2493  *  0x29   registerTokenReq                Y        N
2494  *******************************
2495  *  0x2b   unknownClientMessage1           S        N
2496  *  0x2d   unknownClientMessage2           S        N
2497  *******************************
2498  *  0x81   registerAck                     Y        Y
2499  *  0x82   startTone                       Y        Y
2500  *  0x83   stopTone                        Y        N/A
2501  *  0x85   setRinger                       Y        Y
2502  *  0x86   setLamp                         Y        Y
2503  *  0x87   setHkFDetect                    Y        N
2504  *  0x88   setSpeakerMode                  Y        Y
2505  *  0x89   setMicroMode                    Y        N
2506  *  0x8A   startMediaTransmission          Y        Y
2507  *  0x8B   stopMediaTransmission           Y        Y
2508  *  0x8C   startMediaReception             S        N
2509  *  0x8D   stopMediaReception              S        N
2510  *  0x8E   *reserved*                      S        *
2511  *  0x8F   callInfo                        Y        Y
2512  *  0x90   forwardStat                     Y        N
2513  *  0x91   speedDialStat                   Y        Y
2514  *  0x92   lineStat                        Y        Y
2515  *  0x93   configStat                      Y        N
2516  *  0x94   defineTimeDate                  Y        Y
2517  *  0x95   startSessionTransmission        Y        N
2518  *  0x96   stopSessionTransmission         Y        N
2519  *  0x97   buttonTemplate                  Y        Y -- ugly =)
2520  *  0x98   version                         Y        N
2521  *  0x99   displayText                     Y        Y
2522  *  0x9A   clearDisplay                    Y        N/A
2523  *  0x9B   capabilitiesReq                 Y        N/A
2524  *  0x9C   enunciatorCommand               Y        N (inner loop unknown)
2525  *  0x9D   registerReject                  Y        N
2526  *  0x9E   serverRes                       Y        N
2527  *  0x9F   reset                           Y        Y
2528  *  0x100  keepAliveAck                    Y        N/A
2529  *  0x101  startMulticastMediaReception    Y        N
2530  *  0x102  startMulticastMediaTransmission Y        N
2531  *  0x103  stopMulticastMediaReception     Y        N
2532  *  0x104  stopMulticastMediaTransmission  Y        N
2533  *  0x105  openreceiveChannel              Y        Y
2534  *  0x106  closeReceiveChannel             Y        Y
2535  *  0x107  connectionStatisticsReq         Y        Y
2536  *  0x108  softKeyTemplateRes              Y        Y
2537  *  0x109  softKeySetRes                   Y        Y
2538  *  0x110  selectSoftKeys                  Y        Y
2539  *  0x111  callState                       Y        Y
2540  *  0x112  displayPromptStatus             Y        Y
2541  *  0x113  clearPromptStatus               Y        Y
2542  *  0x114  displayNotify                   Y        Y
2543  *  0x115  clearNotify                     Y        Y
2544  *  0x116  activateCallPlane               Y        Y
2545  *  0x117  deactivateCallPlane             Y        N/A
2546  *  0x118  unregisterAck                   Y        Y
2547  *  0x119  backSpaceReq                    Y        Y
2548  *  0x11A  registerTokenAck                Y        N
2549  *  0x11B  registerTokenReject             Y        N
2550  *******************************
2551  *  0x11D  unknownForwardMessage           NC       N
2552  *******************************
2553  *
2554  *
2555  */