Additional RAP error code for password changes sent to a BDC, from Devin
[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.17 2002/03/27 20:29:05 guy 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-frame.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 /* Dissect a single SCCP PDU */
832 static void dissect_skinny_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
833 {
834   int offset = 0;
835
836   /* Header fields */
837   guint32 hdr_data_length;
838   guint32 hdr_reserved;
839   guint32 data_messageid;
840   gchar   *messageid_str;
841   /*  guint32 data_size; */
842
843   guint32 unknownLong = 0;
844
845   guint i = 0;
846   int j = 0;
847
848   guint32 capCount;
849   guint32 softKeyCount;
850   guint32 softKeySetCount;
851   guint16 validKeyMask;
852   
853   /* Set up structures we will need to add the protocol subtree and manage it */
854   proto_item *ti;
855   proto_tree *skinny_tree = NULL;
856   
857   proto_item *skm = NULL;
858   proto_item *skm_tree = NULL;
859
860   hdr_data_length = tvb_get_letohl(tvb, offset);
861   hdr_reserved    = tvb_get_letohl(tvb, offset+4);
862   data_messageid  = tvb_get_letohl(tvb, offset+8);
863
864   /* In the interest of speed, if "tree" is NULL, don't do any work not
865    * necessary to generate protocol tree items. */
866   if (tree) {
867     ti = proto_tree_add_item(tree, proto_skinny, tvb, offset, hdr_data_length+8, FALSE); 
868     skinny_tree = proto_item_add_subtree(ti, ett_skinny);
869     proto_tree_add_uint(skinny_tree, hf_skinny_data_length, tvb, offset, 4, hdr_data_length);  
870     proto_tree_add_uint(skinny_tree, hf_skinny_reserved, tvb, offset+4, 4, hdr_reserved);
871   }
872
873   messageid_str = val_to_str(data_messageid, message_id, "0x%08X (Unknown)");
874
875   if (check_col(pinfo->cinfo, COL_INFO)) {
876     col_add_str(pinfo->cinfo, COL_INFO, messageid_str);
877   }
878
879   if (tree) {
880     proto_tree_add_uint(skinny_tree, hf_skinny_messageid, tvb,offset+8, 4, data_messageid );
881   }
882
883   if (tree) {
884     switch(data_messageid) {
885
886     /* cases that do not need to be decoded */
887     case 0x0 :    /* keepAlive */
888       break;
889
890     case 0x6 :    /* offHook */
891       break;
892
893     case 0x7 :    /* onHook    */
894       break;
895
896     case 0x8 :    /* hookFlash */
897       break;
898       
899     case 0xc :    /* configStateReqMessage */
900       break;
901       
902     case 0xd :    /* timeDateReqMessage */
903       break;
904
905     case 0xe :    /* buttoneTemplateReqMessage */
906       break;
907
908     case 0xf :    /* stationVersionReqMessage */
909       break;
910       
911     case 0x12 :   /* stationServerReqMessage */
912       break;
913       
914     case 0x25 :   /* softKeySetReqMessage */
915       break;
916
917     case 0x27 :   /* unregisterMessage */
918       break;
919
920     case 0x28 :   /* softKeyTemplateRequest */
921       break;
922
923     case 0x83 :   /* stopTone */
924       break;
925
926     case 0x9a :   /* clearDisplay */
927       break;
928
929     case 0x9b :   /* capabilitiesReqMessage */
930       break;
931
932     case 0x100 :    /* keepAliveAck */
933       break;
934
935     case 0x115 :  /* clearNotifyDisplay */
936       break;
937
938     case 0x117 :  /* deactivateCallPlane */
939       break;
940
941     case 0x11a :  /* registerTokenAck */
942       break;
943
944     /*
945      ** cases that need decode
946      **
947      */
948
949     case 0x1 :   /* register message */
950       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, StationMaxDeviceNameSize, TRUE);
951       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, offset+28, 4, TRUE);
952       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, offset+32, 4, TRUE);
953       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+36, 4, TRUE);
954       proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, offset+40, 4, TRUE);
955       proto_tree_add_item(skinny_tree, hf_skinny_maxStreams, tvb, offset+44, 4, TRUE);
956       break;
957
958     case 0x2 :  /* ipPortMessage */
959       proto_tree_add_item(skinny_tree, hf_skinny_stationIpPort, tvb, offset+12, 2, FALSE);
960       break;
961
962     case 0x3 :  /* keyPadButtonMessage */
963       proto_tree_add_item(skinny_tree, hf_skinny_stationKeypadButton, tvb, offset+12, 4, TRUE);
964       break;
965
966     case 0x4 :  /* stationEnblocCallMessage -- This decode NOT verified*/
967       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12, StationMaxDirnumSize, TRUE);
968       break;
969       
970     case 0x5 : /* stationStimulusMessage */
971       proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
972       proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
973       break;
974
975     case 0x9  : /* stationForwardStatReqMessage */
976       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
977       break;
978       
979     case 0xa :  /* speedDialStatReqMessage */
980       proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
981       break;
982
983     case 0xb :  /* LineStatReqMessage */
984       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
985       break;
986
987     case 0x10 :  /* capabilitiesResMessage  - VERIFIED AS IS*/
988       /* FIXME -- we are only going to decode the first 7 protocol fields for now cuz that's all it sent me
989        * on the phone i was working with. I should probably skip the struct decode and use a more piece
990        * type method using the capCount definition to control the decode loop
991        *
992        * basically changing StationMaxCapabilities definition
993        *
994        */       
995       capCount = tvb_get_letohl(tvb, offset+12);
996       proto_tree_add_uint(skinny_tree, hf_skinny_capCount, tvb, offset+12, 4, capCount);
997       for (i = 0; i < capCount; i++) {
998         proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+(i*16)+16, 4, TRUE);
999         proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+(i*16)+20, 2, TRUE);
1000         /* FIXME -- decode the union under here as required, is always 0 on my equipment */
1001       }
1002       break;
1003
1004     case 0x11 : /* mediaPortList */
1005       break;
1006
1007     case 0x20 :   /* stationAlarmMessage */
1008       proto_tree_add_item(skinny_tree, hf_skinny_alarmSeverity, tvb, offset+12, 4, TRUE);
1009       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxAlarmMessageSize, TRUE);
1010       proto_tree_add_item(skinny_tree, hf_skinny_alarmParam1, tvb, offset+96, 4, TRUE);
1011       proto_tree_add_item(skinny_tree, hf_skinny_alarmParam2, tvb, offset+100, 4, TRUE);
1012       break;
1013
1014     case 0x21 : /* stationMulticastMediaReceptionAck - This decode NOT verified*/
1015       proto_tree_add_item(skinny_tree, hf_skinny_receptionStatus, tvb, offset+12, 4, TRUE);
1016       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1017       break;
1018       
1019     case 0x22 : /* stationOpenReceiveChannelAck */
1020       proto_tree_add_item(skinny_tree, hf_skinny_ORCStatus, tvb, offset+12, 4, TRUE);
1021       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+16, 4, TRUE);
1022       proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+20, 4, TRUE);
1023       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+24, 4, TRUE);
1024       break;    
1025
1026     case 0x23    :  /* stationConnectionStatisticsRes */
1027       proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, offset+12, StationMaxDirnumSize, TRUE);
1028       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+36, 4, TRUE);
1029       proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, offset+40, 4, TRUE);
1030       proto_tree_add_item(skinny_tree, hf_skinny_packetsSent, tvb, offset+44, 4, TRUE);
1031       proto_tree_add_item(skinny_tree, hf_skinny_octetsSent, tvb, offset+48, 4, TRUE);
1032       proto_tree_add_item(skinny_tree, hf_skinny_packetsRecv, tvb, offset+52, 4, TRUE);
1033       proto_tree_add_item(skinny_tree, hf_skinny_octetsRecv, tvb, offset+56, 4, TRUE);
1034       proto_tree_add_item(skinny_tree, hf_skinny_packetsLost, tvb, offset+60, 4, TRUE);
1035       proto_tree_add_item(skinny_tree, hf_skinny_jitter, tvb, offset+64, 4, TRUE);
1036       proto_tree_add_item(skinny_tree, hf_skinny_latency, tvb, offset+68, 4, TRUE);
1037       break;
1038
1039     case 0x24 : /* offHookWithCgpn */
1040       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12,StationMaxDirnumSize, TRUE); 
1041       break;
1042
1043     case 0x26 :  /* softKeyEventMessage */
1044       proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+12, 4, TRUE);
1045       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
1046       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
1047       break;
1048
1049     case 0x29 : /* registerTokenREq */
1050       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, 4, TRUE);
1051       i = offset+12+StationMaxDeviceNameSize;
1052       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
1053       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i+4, 4, TRUE);
1054       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, i+8, 4, TRUE);
1055       proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, i+12, 4, TRUE);
1056       break;
1057
1058       /*
1059        *
1060        * message not in the spec
1061        *
1062        */
1063     case 0x2b :  /* unknownClientMessage1 */
1064       break;
1065
1066     case 0x2d :  /* unknownClientMessage2 */
1067       break;
1068
1069       /* 
1070        *
1071        *  Call manager -> client messages start here(ish)
1072        *
1073        */
1074     case 0x81 :  /* registerAck */
1075       proto_tree_add_item(skinny_tree, hf_skinny_keepAliveInterval, tvb, offset+12, 4, TRUE);
1076       proto_tree_add_item(skinny_tree, hf_skinny_dateTemplate, tvb, offset+16, StationDateTemplateSize, TRUE);
1077       proto_tree_add_item(skinny_tree, hf_skinny_secondaryKeepAliveInterval, tvb, offset+24, 4, TRUE);
1078       break;
1079
1080     case 0x82 :  /* startTone */
1081       proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, offset+12, 4, TRUE);
1082       break;
1083
1084     case 0x85 : /* setRingerMessage */
1085       proto_tree_add_item(skinny_tree, hf_skinny_ringType, tvb, offset+12, 4, TRUE);
1086       break;
1087         
1088     case 0x86 : /* setLampMessage */
1089       proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
1090       proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
1091       proto_tree_add_item(skinny_tree, hf_skinny_lampMode, tvb, offset+20, 4, TRUE);
1092       break;
1093
1094     case 0x87 : /* stationHookFlashDetectMode */
1095       proto_tree_add_item(skinny_tree, hf_skinny_hookFlashDetectMode, tvb, offset+12, 4, TRUE);
1096       proto_tree_add_item(skinny_tree, hf_skinny_detectInterval, tvb, offset+16, 4, TRUE);
1097       break;
1098
1099     case 0x88 : /* setSpeakerMode */
1100       
1101       proto_tree_add_item(skinny_tree, hf_skinny_speakerMode, tvb, offset+12, 4, TRUE);
1102       break;
1103
1104     case 0x89 : /* setMicroMode */
1105       proto_tree_add_item(skinny_tree, hf_skinny_microphoneMode, tvb, offset+12, 4, TRUE);
1106       break;
1107
1108     case 0x8a : /* startMediaTransmistion */     
1109       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID,          tvb, offset+12, 4, TRUE);
1110       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID,       tvb, offset+16, 4, TRUE);
1111       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,          tvb, offset+20, 4, TRUE);
1112       proto_tree_add_item(skinny_tree, hf_skinny_remotePortNumber,      tvb, offset+24, 4, TRUE);
1113       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1114       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability,     tvb, offset+32, 4, TRUE);
1115       proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue,       tvb, offset+36, 4, TRUE);
1116       proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression,    tvb, offset+40, 4, TRUE);
1117       proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket,    tvb, offset+44, 2, TRUE);
1118       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate,           tvb, offset+48, 4, TRUE);
1119       break;
1120
1121     case 0x8b :  /* stopMediaTransmission */
1122      
1123       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);      
1124       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1125       break;
1126
1127     case 0x8c : /* startMediaReception */
1128       break;
1129
1130     case 0x8d : /* stopMediaReception */
1131       break;
1132
1133     case 0x8e : /* reservered */
1134       break;
1135
1136     case 0x8f : /* callInfo */
1137       i = offset+12;
1138       proto_tree_add_item(skinny_tree, hf_skinny_callingPartyName, tvb, i, StationMaxNameSize, TRUE);
1139       i += StationMaxNameSize;
1140       proto_tree_add_item(skinny_tree, hf_skinny_callingParty, tvb, i, StationMaxDirnumSize, TRUE);
1141       i += StationMaxDirnumSize;
1142       proto_tree_add_item(skinny_tree, hf_skinny_calledPartyName, tvb, i, StationMaxNameSize, TRUE);
1143       i += StationMaxNameSize;
1144       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, i, StationMaxDirnumSize, TRUE);
1145       i += StationMaxDirnumSize;
1146       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, i, 4, TRUE);
1147       i += 4;
1148       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
1149       i += 4;
1150       proto_tree_add_item(skinny_tree, hf_skinny_callType, tvb, i, 4, TRUE);
1151       i += 4;
1152       proto_tree_add_item(skinny_tree, hf_skinny_originalCalledPartyName, tvb, i, StationMaxNameSize, TRUE);
1153       i += StationMaxNameSize;
1154       proto_tree_add_item(skinny_tree, hf_skinny_originalCalledParty, tvb, i, StationMaxDirnumSize, TRUE);
1155       break;
1156
1157     case 0x90 : /* forwardStat */
1158       proto_tree_add_item(skinny_tree, hf_skinny_activeForward, tvb, offset+12, 4, TRUE);
1159       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+16, 4, TRUE);
1160       proto_tree_add_item(skinny_tree, hf_skinny_forwardAllActive, tvb, offset+20, 4, TRUE);
1161       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, offset+24, StationMaxDirnumSize, TRUE);
1162       i = offset+24+StationMaxDirnumSize;
1163       proto_tree_add_item(skinny_tree, hf_skinny_forwardBusyActive, tvb, i, 4, TRUE);
1164       i += 4;
1165       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
1166       i += StationMaxDirnumSize;
1167       proto_tree_add_item(skinny_tree, hf_skinny_forwardNoAnswerActive, tvb, i, 4, TRUE);
1168       i += 4;
1169       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
1170       break;
1171
1172     case 0x91 : /* speedDialStatMessage */
1173       proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
1174       proto_tree_add_item(skinny_tree, hf_skinny_speedDialDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
1175       proto_tree_add_item(skinny_tree, hf_skinny_speedDialDisplayName, tvb, offset+40, StationMaxNameSize, TRUE);
1176       break;
1177
1178     case 0x92 : /* lineStatMessage */
1179       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
1180       proto_tree_add_item(skinny_tree, hf_skinny_lineDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
1181       proto_tree_add_item(skinny_tree, hf_skinny_lineFullyQualifiedDisplayName, tvb, offset+16+StationMaxDirnumSize, StationMaxNameSize, TRUE);
1182       break;
1183
1184     case 0x93 : /* configStat */
1185       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, 4, TRUE);
1186       i = offset+12+StationMaxDeviceNameSize;
1187       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
1188       i += 4;
1189       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i, 4, TRUE);
1190       i += 4;
1191       proto_tree_add_item(skinny_tree, hf_skinny_userName, tvb, i, StationMaxNameSize, TRUE);
1192       i += StationMaxNameSize;
1193       proto_tree_add_item(skinny_tree, hf_skinny_serverName, tvb, i, StationMaxNameSize, TRUE);
1194       i += StationMaxNameSize;
1195       proto_tree_add_item(skinny_tree, hf_skinny_numberLines, tvb, i, 4, TRUE);
1196       proto_tree_add_item(skinny_tree, hf_skinny_numberSpeedDials, tvb, i+4, 4, TRUE);
1197       break;
1198
1199     case 0x94 : /* stationDefineTimeDate */
1200       proto_tree_add_item(skinny_tree, hf_skinny_dateYear,   tvb, offset+12, 4, TRUE);
1201       proto_tree_add_item(skinny_tree, hf_skinny_dateMonth,  tvb, offset+16, 4, TRUE);
1202       proto_tree_add_item(skinny_tree, hf_skinny_dayOfWeek,  tvb, offset+20, 4, TRUE);
1203       proto_tree_add_item(skinny_tree, hf_skinny_dateDay,    tvb, offset+24, 4, TRUE);
1204       proto_tree_add_item(skinny_tree, hf_skinny_dateHour,   tvb, offset+28, 4, TRUE);
1205       proto_tree_add_item(skinny_tree, hf_skinny_dateMinute, tvb, offset+32, 4, TRUE);
1206       proto_tree_add_item(skinny_tree, hf_skinny_dateSeconds,tvb, offset+36, 4, TRUE);
1207       proto_tree_add_item(skinny_tree, hf_skinny_dateMilliseconds,tvb, offset+40, 4, TRUE);
1208       proto_tree_add_item(skinny_tree, hf_skinny_timeStamp, tvb, offset+44, 4, TRUE);
1209       break;
1210
1211     case 0x95 : /* startSessionTransmission */
1212       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,  tvb, offset+12, 4, TRUE);
1213       proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
1214       break;
1215
1216     case 0x96 : /* stopSessionTransmission */
1217       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,  tvb, offset+12, 4, TRUE);
1218       proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
1219       break;
1220
1221     case 0x97 :  /* buttonTemplateMessage  */
1222       /*
1223        * FIXME
1224        * This decode prints out oogly subtree maybe? or something besides the VALS...
1225        * note to self: uint8 != 4 kk thx info ^_^
1226        *
1227        */
1228       proto_tree_add_item(skinny_tree, hf_skinny_buttonOffset, tvb, offset+12, 4, TRUE);
1229       proto_tree_add_item(skinny_tree, hf_skinny_buttonCount,  tvb, offset+16, 4, TRUE);
1230       proto_tree_add_item(skinny_tree, hf_skinny_totalButtonCount, tvb, offset+20, 4, TRUE);
1231       for (i = 0; i < StationMaxButtonTemplateSize; i++) {
1232         proto_tree_add_item(skinny_tree, hf_skinny_buttonInstanceNumber, tvb, offset+(i*2)+24, 1, TRUE);
1233         proto_tree_add_item(skinny_tree, hf_skinny_buttonDefinition, tvb, offset+(i*2)+25, 1, TRUE);
1234       }
1235       break;
1236
1237     case 0x98 : /* version */
1238       proto_tree_add_item(skinny_tree, hf_skinny_version, tvb, offset+12, StationMaxVersionSize, TRUE);
1239       break;
1240
1241     case 0x99 :  /* displayTextMessage */
1242       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);           
1243       break;
1244
1245     case 0x9c : /* enunciatorCommand */
1246       proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, offset+12, 4, TRUE);
1247       for (i = 0; i < StationMaxDirnumSize; i++) {
1248         proto_tree_add_item(skinny_tree, hf_skinny_unknown, tvb, offset+16+(i*4), 4, TRUE);
1249       }
1250       i = offset+16+StationMaxDirnumSize;
1251       proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, i, 4, TRUE);
1252       break;
1253
1254     case 0x9d : /* stationRegisterReject */
1255       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);
1256       break;
1257       
1258     case 0x9e : /* serverRes */
1259       for (i = 0; i < StationMaxServers; i++) {
1260         proto_tree_add_item(skinny_tree, hf_skinny_serverIdentifier, tvb, offset+12+(i*StationMaxServers), StationMaxServers, TRUE);
1261       }
1262       j = offset+12+(i*StationMaxServers);
1263       for (i = 0; i < StationMaxServers; i++) {
1264         proto_tree_add_item(skinny_tree, hf_skinny_serverListenPort, tvb, j+(i*4), 4,  TRUE);
1265       }
1266       j = j+(i*4);
1267       for (i = 0; i < StationMaxServers; i++) {
1268         proto_tree_add_item(skinny_tree, hf_skinny_serverIpAddress, tvb, j+(i*4), 4, TRUE);
1269       }
1270       break;
1271
1272     case 0x9f :   /* reset */
1273       proto_tree_add_item(skinny_tree, hf_skinny_deviceResetType, tvb, offset+12, 4, TRUE);
1274       break;
1275
1276     case 0x101 : /* startMulticastMediaReception*/
1277       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1278       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1279       proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
1280       proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
1281       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1282       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
1283       proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType, tvb, offset+36, 4, TRUE);
1284       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+40, 4, TRUE);
1285       break;
1286
1287     case 0x102 : /* startMulticateMediaTermination*/
1288       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1289       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1290       proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
1291       proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
1292       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1293       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
1294       proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue, tvb, offset+36, 4, TRUE);
1295       proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression, tvb, offset+40, 4, TRUE);
1296       proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+44, 2, TRUE);
1297       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+48, 4, TRUE);
1298       break;
1299
1300     case 0x103 : /* stopMulticastMediaReception*/
1301       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1302       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1303       break;
1304
1305     case 0x104 : /* stopMulticastMediaTermination*/
1306       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1307       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1308       break;
1309
1310     case 0x105 : /* open receive channel */
1311       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID,            tvb, offset+12, 4, TRUE);
1312       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID,         tvb, offset+16, 4, TRUE);
1313       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize,   tvb, offset+20, 4, TRUE);
1314       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability,       tvb, offset+24, 4, TRUE);
1315       proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType,          tvb, offset+28, 4, TRUE);
1316       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate,             tvb, offset+32, 4, TRUE);
1317       break;
1318
1319     case 0x106 :  /* closeReceiveChannel */
1320       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1321       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1322       break;
1323
1324     case 0x107 :  /* connectionStatisticsReq */
1325
1326       i = 12;
1327       proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, i, StationMaxDirnumSize, TRUE);
1328       i = 12 + StationMaxDirnumSize;
1329       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
1330       i = i+4;
1331       proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, i, 4, TRUE);
1332       break;
1333
1334     case 0x108 :   /* softkeyTemplateResMessage */
1335       proto_tree_add_item(skinny_tree, hf_skinny_softKeyOffset, tvb, offset+12, 4, TRUE);
1336       softKeyCount = tvb_get_letohl(tvb, offset+16);
1337       proto_tree_add_uint(skinny_tree, hf_skinny_softKeyCount, tvb, offset+16, 4, softKeyCount);
1338       proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeyCount, tvb, offset+20, 4, TRUE);
1339       for (i = 0; ((i < StationMaxSoftKeyDefinition) && (i < softKeyCount)); i++){
1340         proto_tree_add_item(skinny_tree, hf_skinny_softKeyLabel, tvb, offset+(i*20)+24, StationMaxSoftKeyLabelSize, TRUE);
1341         proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+(i*20)+40, 4, TRUE);
1342       }
1343       /* there is more data here, but it doesn't make a whole lot of sense, I imagine
1344        * it's just some not zero'd out stuff in the packet or... 
1345        */
1346       break;
1347
1348     case 0x109 : /* softkeysetres */
1349       proto_tree_add_item(skinny_tree, hf_skinny_softKeySetOffset, tvb, offset+12, 4, TRUE);
1350       softKeySetCount = tvb_get_letohl(tvb, offset+16);
1351       proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetCount, tvb, offset+16, 4, softKeySetCount);
1352       proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeySetCount, tvb, offset+20, 4, TRUE);
1353       for (i = 0; ((i < StationMaxSoftKeySetDefinition) && (i < softKeySetCount)); i++) {
1354         proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+24+(i*48) , 1, i);
1355         for (j = 0; j < StationMaxSoftKeyIndex; j++) {
1356           proto_tree_add_item(skinny_tree, hf_skinny_softKeyTemplateIndex, tvb, offset+24+(i*48)+j, 1, TRUE);
1357         }
1358         for (j = 0; j < StationMaxSoftKeyIndex; j++) {
1359           proto_tree_add_item(skinny_tree, hf_skinny_softKeyInfoIndex, tvb, offset+24+(i*48)+StationMaxSoftKeyIndex+(j*2), 2, TRUE);
1360         }
1361       }
1362       break;
1363       
1364     case 0x110 : /* selectSoftKeys */
1365       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1366       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1367       proto_tree_add_item(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+20, 4, TRUE);
1368       validKeyMask = tvb_get_letohs(tvb, offset + 24);
1369       skm = proto_tree_add_uint(skinny_tree, hf_skinny_softKeyMap, tvb, offset + 24, 1, validKeyMask);
1370       skm_tree = proto_item_add_subtree(skm, ett_skinny_softKeyMap);
1371       proto_tree_add_boolean(skm_tree, hf_skinny_softKey0,  tvb, offset + 24, 1, validKeyMask);
1372       proto_tree_add_boolean(skm_tree, hf_skinny_softKey1,  tvb, offset + 24, 1, validKeyMask);
1373       proto_tree_add_boolean(skm_tree, hf_skinny_softKey2,  tvb, offset + 24, 1, validKeyMask);
1374       proto_tree_add_boolean(skm_tree, hf_skinny_softKey3,  tvb, offset + 24, 1, validKeyMask);
1375       proto_tree_add_boolean(skm_tree, hf_skinny_softKey4,  tvb, offset + 24, 1, validKeyMask);
1376       proto_tree_add_boolean(skm_tree, hf_skinny_softKey5,  tvb, offset + 24, 1, validKeyMask);
1377       proto_tree_add_boolean(skm_tree, hf_skinny_softKey6,  tvb, offset + 24, 1, validKeyMask);
1378       proto_tree_add_boolean(skm_tree, hf_skinny_softKey7,  tvb, offset + 24, 1, validKeyMask);
1379       proto_tree_add_boolean(skm_tree, hf_skinny_softKey8,  tvb, offset + 24, 1, validKeyMask);
1380       proto_tree_add_boolean(skm_tree, hf_skinny_softKey9,  tvb, offset + 24, 1, validKeyMask);
1381       proto_tree_add_boolean(skm_tree, hf_skinny_softKey10, tvb, offset + 24, 1, validKeyMask);
1382       proto_tree_add_boolean(skm_tree, hf_skinny_softKey11, tvb, offset + 24, 1, validKeyMask);
1383       proto_tree_add_boolean(skm_tree, hf_skinny_softKey12, tvb, offset + 24, 1, validKeyMask);
1384       proto_tree_add_boolean(skm_tree, hf_skinny_softKey13, tvb, offset + 24, 1, validKeyMask);
1385       proto_tree_add_boolean(skm_tree, hf_skinny_softKey14, tvb, offset + 24, 1, validKeyMask);
1386       proto_tree_add_boolean(skm_tree, hf_skinny_softKey15, tvb, offset + 24, 1, validKeyMask);
1387       break;
1388       
1389     case 0x111 : /* callState */
1390       proto_tree_add_item(skinny_tree, hf_skinny_callState, tvb, offset+12, 4, TRUE);
1391       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
1392       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
1393       break;
1394       
1395     case 0x112 : /* displayPromptStatus */
1396       proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
1397       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayPromptStatusSize, TRUE);
1398       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+48, 4, TRUE);
1399       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+52, 4, TRUE);
1400       break;
1401       
1402     case 0x113: /* clearPrompt */
1403       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance  , tvb, offset+12, 4, TRUE);
1404       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1405       break;
1406       
1407     case 0x114 : /* displayNotify */
1408       proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
1409       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayNotifySize , TRUE);
1410       break;
1411       
1412     case 0x116 : /* activateCallPlane */
1413       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1414       break;
1415
1416     case 0x118 :    /* unregisterAckMessage */
1417       proto_tree_add_item(skinny_tree, hf_skinny_deviceUnregisterStatus, tvb, offset+12, 4, TRUE);
1418       break;
1419
1420     case 0x119 : /* backSpaceReq */
1421       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1422       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1423       break;
1424
1425     case 0x11B : /* registerTokenReject */
1426       proto_tree_add_item(skinny_tree, hf_skinny_tokenRejWaitTime, tvb, offset+12, 4, TRUE);
1427       break;
1428
1429     case 0x11D : /* new message */
1430       unknownLong       = tvb_get_letohl(tvb, offset+36);
1431       proto_tree_add_uint(skinny_tree, hf_skinny_unknown, tvb, offset+36, 4, unknownLong);
1432       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+40, 4, TRUE);
1433       break;
1434       
1435
1436
1437     default:
1438       break;
1439     }
1440   }
1441 }
1442
1443 /* Code to actually dissect the packets */
1444 static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1445 {
1446   /* The general structure of a packet: {IP-Header|TCP-Header|n*SKINNY}
1447    * SKINNY-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
1448    */
1449   
1450   volatile int offset = 0;
1451   int length_remaining;
1452   int length;
1453   tvbuff_t *next_tvb;
1454
1455   /* Header fields */
1456   volatile guint32 hdr_data_length;
1457   guint32 hdr_reserved;
1458
1459   /* check, if this is really an SKINNY packet, they start with a length + 0 */
1460   
1461   /* get relevant header information */
1462   hdr_data_length = tvb_get_letohl(tvb, 0);
1463   hdr_reserved    = tvb_get_letohl(tvb, 4);
1464
1465   /*  data_size       = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
1466   
1467   /* hdr_data_length > 1024 is just a heuristic. Better values/checks welcome */
1468   if (hdr_data_length < 4 || hdr_data_length > 1024 || hdr_reserved != 0) {
1469     /* Not an SKINNY packet, just happened to use the same port */
1470     call_dissector(data_handle,tvb, pinfo, tree);
1471     return;
1472   }
1473   
1474   /* Make entries in Protocol column and Info column on summary display */
1475   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1476     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY");
1477   }
1478   
1479   if (check_col(pinfo->cinfo, COL_INFO)) {
1480     col_set_str(pinfo->cinfo, COL_INFO, "Skinny Client Control Protocol");
1481   }
1482   
1483   while (tvb_reported_length_remaining(tvb, offset) != 0) {
1484     length_remaining = tvb_length_remaining(tvb, offset);
1485
1486     /*
1487      * Can we do reassembly?
1488      */
1489     if (skinny_desegment && pinfo->can_desegment) {
1490       /*
1491        * Yes - is the length field in the SCCP header split across
1492        * segment boundaries?
1493        */
1494       if (length_remaining < 4) {
1495         /*
1496          * Yes.  Tell the TCP dissector where the data for this message
1497          * starts in the data it handed us, and how many more bytes we
1498          * need, and return.
1499          */
1500         pinfo->desegment_offset = offset;
1501         pinfo->desegment_len = 4 - length_remaining;
1502         return;
1503       }
1504     }
1505
1506     /*
1507      * Get the length of the SCCP packet.
1508      */
1509     hdr_data_length = tvb_get_letohl(tvb, offset);
1510
1511     /*
1512      * Can we do reassembly?
1513      */
1514     if (skinny_desegment && pinfo->can_desegment) {
1515       /*
1516        * Yes - is the SCCP packet split across segment boundaries?
1517        */
1518       if ((guint32)length_remaining < hdr_data_length + 8) {
1519         /*
1520          * Yes.  Tell the TCP dissector where the data for this message
1521          * starts in the data it handed us, and how many more bytes we
1522          * need, and return.
1523          */
1524         pinfo->desegment_offset = offset;
1525         pinfo->desegment_len = (hdr_data_length + 8) - length_remaining;
1526         return;
1527       }
1528     }
1529
1530     /*
1531      * Construct a tvbuff containing the amount of the payload we have
1532      * available.  Make its reported length the amount of data in the
1533      * SCCP packet.
1534      *
1535      * XXX - if reassembly isn't enabled. the subdissector will throw a
1536      * BoundsError exception, rather than a ReportedBoundsError exception.
1537      * We really want a tvbuff where the length is "length", the reported
1538      * length is "hdr_data_length + 8", and the "if the snapshot length
1539      * were infinite" length is the minimum of the reported length of
1540      * the tvbuff handed to us and "hdr_data_length + 8", with a new type
1541      * of exception thrown if the offset is within the reported length but
1542      * beyond that third length, with that exception getting the
1543      * "Unreassembled Packet" error.
1544      */
1545     length = length_remaining;
1546     if ((guint32)length > hdr_data_length + 8)
1547       length = hdr_data_length + 8;
1548     next_tvb = tvb_new_subset(tvb, offset, length, hdr_data_length + 8);
1549
1550     /*
1551      * Dissect the SCCP packet.
1552      *
1553      * Catch the ReportedBoundsError exception; if this particular message
1554      * happens to get a ReportedBoundsError exception, that doesn't mean
1555      * that we should stop dissecting SCCP messages within this frame or
1556      * chunk of reassembled data.
1557      *
1558      * If it gets a BoundsError, we can stop, as there's nothing more to
1559      * see, so we just re-throw it.
1560      */
1561     TRY {
1562       dissect_skinny_pdu(next_tvb, pinfo, tree);
1563     }
1564     CATCH(BoundsError) {
1565       RETHROW;
1566     }
1567     CATCH(ReportedBoundsError) {
1568       show_reported_bounds_error(tvb, pinfo, tree);
1569     }
1570     ENDTRY;
1571
1572     /*
1573      * Skip the SCCP header and the payload.
1574      */
1575     offset += hdr_data_length + 8;
1576   }
1577 }
1578
1579 /* Register the protocol with Ethereal */
1580 void 
1581 proto_register_skinny(void)
1582 {                 
1583   
1584   /* Setup list of header fields */
1585   static hf_register_info hf[] = {
1586     { &hf_skinny_data_length,
1587       { "Data Length", "skinny.data_length",
1588         FT_UINT32, BASE_DEC, NULL, 0x0,
1589         "Number of bytes in the data portion.",
1590         HFILL }
1591     },
1592     { &hf_skinny_reserved,
1593       { "Reserved", "skinny.reserved",
1594         FT_UINT32, BASE_HEX, NULL, 0x0,
1595         "Reserved for future(?) use.",
1596         HFILL }
1597     },
1598     /* FIXME: Enable use of message name ???  */
1599     { &hf_skinny_messageid,
1600       { "Message ID", "skinny.messageid",
1601         FT_UINT32, BASE_HEX, VALS(message_id), 0x0,
1602         "The function requested/done with this message.",
1603         HFILL }
1604     },
1605
1606     { &hf_skinny_deviceName,
1607       { "DeviceName", "skinny.deviceName",
1608         FT_STRING, BASE_NONE, NULL, 0x0,
1609         "The device name of the phone.",
1610         HFILL }
1611     },
1612
1613     { &hf_skinny_stationUserId,
1614       { "StationUserId", "skinny.stationUserId",
1615         FT_UINT32, BASE_DEC, NULL, 0x0,
1616         "The station user id.",
1617         HFILL }
1618     },
1619
1620     { &hf_skinny_stationInstance,
1621       { "StationInstance", "skinny.stationInstance",
1622         FT_UINT32, BASE_DEC, NULL, 0x0,
1623         "The stations instance.",
1624         HFILL }
1625     },
1626
1627     { &hf_skinny_deviceType,
1628       { "DeviceType", "skinny.deviceType",
1629         FT_UINT32, BASE_DEC, VALS(deviceTypes), 0x0,
1630         "DeviceType of the station.",
1631         HFILL }
1632     },
1633
1634     { &hf_skinny_maxStreams,
1635       { "MaxStreams", "skinny.maxStreams",
1636         FT_UINT32, BASE_DEC, NULL, 0x0,
1637         "32 bit unsigned integer indicating the maximum number of simultansous RTP duplex streams that the client can handle.",
1638         HFILL }
1639     },
1640
1641     { &hf_skinny_stationIpPort,
1642       { "StationIpPort", "skinny.stationIpPort",
1643         FT_UINT16, BASE_DEC, NULL, 0x0,
1644         "The station IP port",
1645         HFILL }
1646     },
1647
1648     { &hf_skinny_stationKeypadButton,
1649       { "KeypadButton", "skinny.stationKeypadButton",
1650         FT_UINT32, BASE_HEX, VALS(keypadButtons), 0x0,
1651         "The button pressed on the phone.",
1652         HFILL }
1653     },
1654
1655     { &hf_skinny_calledParty,
1656       { "CalledParty", "skinny.calledParty",
1657         FT_STRING, BASE_NONE, NULL, 0x0,
1658         "The number called.",
1659         HFILL }
1660     },
1661
1662     { &hf_skinny_stimulus,
1663       { "Stimulus", "skinny.stimulus",
1664         FT_UINT32, BASE_HEX, VALS(deviceStimuli), 0x0,
1665         "Reason for the device stimulus message.",
1666         HFILL }
1667     },
1668
1669     { &hf_skinny_stimulusInstance,
1670       { "StimulusInstance", "skinny.stimulusInstance",
1671         FT_UINT32, BASE_DEC, NULL, 0x0,
1672         "The instance of the stimulus",
1673         HFILL }
1674     },
1675
1676     { &hf_skinny_lineNumber,
1677       { "LineNumber", "skinny.lineNumber",
1678         FT_UINT32, BASE_DEC, NULL, 0x0,
1679         "Line Number",
1680         HFILL }
1681     },
1682
1683     { &hf_skinny_speedDialNumber,
1684       { "SpeedDialNumber", "skinny.speedDialNumber",
1685         FT_UINT32, BASE_DEC, NULL, 0x0,
1686         "Which speed dial number",
1687         HFILL }
1688     },
1689
1690     { &hf_skinny_capCount,
1691       { "CapCount", "skinny.capCount",
1692         FT_UINT32, BASE_DEC, NULL, 0x0,
1693         "How many capabilities",
1694         HFILL }
1695     },
1696
1697     { &hf_skinny_payloadCapability,
1698       { "PayloadCapability", "skinny.payloadCapability",
1699         FT_UINT32, BASE_DEC, VALS(mediaPayloads), 0x0,
1700         "The payload capability for this media capability structure.",
1701         HFILL }
1702     },
1703
1704     { &hf_skinny_maxFramesPerPacket,
1705       { "MaxFramesPerPacket", "skinny.maxFramesPerPacket",
1706         FT_UINT16, BASE_DEC, NULL, 0x0,
1707         "Max frames per packet",
1708         HFILL }
1709     },
1710
1711     { &hf_skinny_alarmSeverity,
1712       { "AlarmSeverity", "skinny.alarmSeverity",
1713         FT_UINT32, BASE_DEC, VALS(alarmSeverities), 0x0,
1714         "The severity of the reported alarm.",
1715         HFILL }
1716     },
1717
1718     { &hf_skinny_alarmParam1,
1719       { "AlarmParam1", "skinny.alarmParam1",
1720         FT_UINT32, BASE_HEX, NULL, 0x0,
1721         "An as yet undecoded param1 value from the alarm message",
1722         HFILL }
1723     },
1724
1725     { &hf_skinny_alarmParam2,
1726       { "AlarmParam2", "skinny.alarmParam2",
1727         FT_IPv4, BASE_NONE, NULL, 0x0,
1728         "This is the second alarm parameter i think it's an ip address",
1729         HFILL }
1730     },
1731
1732     { &hf_skinny_receptionStatus,
1733       { "ReceptionStatus", "skinny.receptionStatus",
1734         FT_UINT32, BASE_DEC, VALS(multicastMediaReceptionStatus), 0x0,
1735         "The current status of the multicast media.",
1736         HFILL }
1737     },
1738
1739     { &hf_skinny_passThruPartyID,
1740       { "PassThruPartyID", "skinny.passThruPartyID",
1741         FT_UINT32, BASE_DEC, NULL, 0x0,
1742         "The pass thru party id",
1743         HFILL }
1744     },
1745
1746     { &hf_skinny_ORCStatus,
1747       { "OpenReceiveChannelStatus", "skinny.openReceiveChannelStatus",
1748         FT_UINT32, BASE_DEC, VALS(openReceiveChanStatus), 0x0,
1749         "The status of the opened receive channel.",
1750         HFILL }
1751     },
1752
1753     { &hf_skinny_ipAddress,
1754       { "IP Address", "skinny.ipAddress",
1755         FT_IPv4, BASE_NONE, NULL, 0x0,
1756         "An IP address",
1757         HFILL }
1758     },
1759
1760     { &hf_skinny_portNumber,
1761       { "Port Number", "skinny.portNumber",
1762         FT_UINT32, BASE_DEC, NULL, 0x0,
1763         "A port number",
1764         HFILL }
1765     },
1766
1767     { &hf_skinny_statsProcessingType,
1768       { "StatsProcessingType", "skinny.statsProcessingType",
1769         FT_UINT32, BASE_DEC, VALS(statsProcessingTypes), 0x0,
1770         "What do do after you send the stats.",
1771         HFILL }
1772     },
1773
1774     { &hf_skinny_callIdentifier,
1775       { "Call Identifier", "skinny.callIdentifier",
1776         FT_UINT32, BASE_DEC, NULL, 0x0,
1777         "Call identifier for this call.",
1778         HFILL }
1779     },
1780
1781     { &hf_skinny_packetsSent,
1782       { "Packets Sent", "skinny.packetsSent",
1783         FT_UINT32, BASE_DEC, NULL, 0x0,
1784         "Packets Sent during the call.",
1785         HFILL }
1786     },
1787
1788     { &hf_skinny_octetsSent,
1789       { "Octets Sent", "skinny.octetsSent",
1790         FT_UINT32, BASE_DEC, NULL, 0x0,
1791         "Octets sent during the call.",
1792         HFILL }
1793     },
1794
1795     { &hf_skinny_packetsRecv,
1796       { "Packets Received", "skinny.packetsRecv",
1797         FT_UINT32, BASE_DEC, NULL, 0x0,
1798         "Packets received during the call.",
1799         HFILL }
1800     },
1801
1802     { &hf_skinny_octetsRecv,
1803       { "Octets Received", "skinny.octetsRecv",
1804         FT_UINT32, BASE_DEC, NULL, 0x0,
1805         "Octets received during the call.",
1806         HFILL }
1807     },
1808
1809     { &hf_skinny_packetsLost,
1810       { "Packets Lost", "skinny.packetsLost",
1811         FT_UINT32, BASE_DEC, NULL, 0x0,
1812         "Packets lost during the call.",
1813         HFILL }
1814     },
1815
1816     { &hf_skinny_latency,
1817       { "Latency(ms)", "skinny.latency",
1818         FT_UINT32, BASE_DEC, NULL, 0x0,
1819         "Average packet latency during the call.",
1820         HFILL }
1821     },
1822
1823     { &hf_skinny_jitter,
1824       { "Jitter", "skinny.jitter",
1825         FT_UINT32, BASE_DEC, NULL, 0x0,
1826         "Average jitter during the call.",
1827         HFILL }
1828     },
1829
1830     { &hf_skinny_directoryNumber,
1831       { "Directory Number", "skinny.directoryNumber",
1832         FT_STRING, BASE_NONE, NULL, 0x0,
1833         "The number we are reporting statistics for.",
1834         HFILL }
1835     },
1836
1837     { &hf_skinny_lineInstance,
1838       { "Line Instance", "skinny.lineInstance",
1839         FT_UINT32, BASE_DEC, NULL, 0x0,
1840         "The display call plane associated with this call.",
1841         HFILL }
1842     },
1843
1844     { &hf_skinny_softKeyEvent,
1845       { "SoftKeyEvent", "skinny.softKeyEvent",
1846         FT_UINT32, BASE_DEC, VALS(softKeyEvents), 0x0,
1847         "Which softkey event is being reported.",
1848         HFILL }
1849     },
1850
1851     { &hf_skinny_keepAliveInterval,
1852       { "KeepAliveInterval", "skinny.keepAliveInterval",
1853         FT_UINT32, BASE_DEC, NULL, 0x0,
1854         "How often are keep alives exchanges between the client and the call manager.",
1855         HFILL }
1856     },
1857
1858     { &hf_skinny_secondaryKeepAliveInterval,
1859       { "SecondaryKeepAliveInterval", "skinny.secondaryKeepAliveInterval",
1860         FT_UINT32, BASE_DEC, NULL, 0x0,
1861         "How often are keep alives exchanges between the client and the secondary call manager.",
1862         HFILL }
1863     },
1864
1865     { &hf_skinny_dateTemplate,
1866       { "DateTemplate", "skinny.dateTemplate",
1867         FT_STRING, BASE_NONE, NULL, 0x0,
1868         "The display format for the date/time on the phone.",
1869         HFILL }
1870     },
1871
1872     { &hf_skinny_buttonOffset,
1873       { "ButtonOffset", "skinny.buttonOffset",
1874         FT_UINT32, BASE_DEC, NULL, 0x0,
1875         "Offset is the number of the first button referenced by this message.",
1876         HFILL }
1877     },
1878
1879     { &hf_skinny_buttonCount,
1880       { "ButtonCount", "skinny.buttonCount",
1881         FT_UINT32, BASE_DEC, NULL, 0x0,
1882         "Number of (VALID) button definitions in this message.",
1883         HFILL }
1884     },
1885
1886     { &hf_skinny_totalButtonCount,
1887       { "TotalButtonCount", "skinny.totalButtonCount",
1888         FT_UINT32, BASE_DEC, NULL, 0x0,
1889         "The total number of buttons defined for this phone.",
1890         HFILL }
1891     },
1892
1893     { &hf_skinny_buttonInstanceNumber,
1894       { "InstanceNumber", "skinny.buttonInstanceNumber",
1895         FT_UINT8, BASE_HEX, VALS(keypadButtons), 0x0,
1896         "The button instance number for a button or the StationKeyPad value, repeats allowed.",
1897         HFILL }
1898     },
1899
1900     { &hf_skinny_buttonDefinition,
1901       { "ButtonDefinition", "skinny.buttonDefinition",
1902         FT_UINT8, BASE_HEX, VALS(buttonDefinitions), 0x0,
1903         "The button type for this instance (ie line, speed dial, ....",
1904         HFILL }
1905     },
1906
1907     { &hf_skinny_softKeyOffset,
1908       { "SoftKeyOffset", "skinny.softKeyOffset",
1909         FT_UINT32, BASE_DEC, NULL, 0x0,
1910         "The offset for the first soft key in this message.",
1911         HFILL }
1912     },
1913
1914     { &hf_skinny_softKeyCount,
1915       { "SoftKeyCount", "skinny.softKeyCount",
1916         FT_UINT32, BASE_DEC, NULL, 0x0,
1917         "The number of valid softkeys in this message.",
1918         HFILL }
1919     },
1920
1921     { &hf_skinny_totalSoftKeyCount,
1922       { "TotalSoftKeyCount", "skinny.totalSoftKeyCount",
1923         FT_UINT32, BASE_DEC, NULL, 0x0,
1924         "The total number of softkeys for this device.",
1925         HFILL }
1926     },
1927
1928     { &hf_skinny_softKeyLabel,
1929       { "SoftKeyLabel", "skinny.softKeyLabel",
1930         FT_STRING, BASE_NONE, NULL, 0x0,
1931         "The text label for this soft key.",
1932         HFILL }
1933     },
1934
1935     { &hf_skinny_softKeySetOffset,
1936       { "SoftKeySetOffset", "skinny.softKeySetOffset",
1937         FT_UINT32, BASE_DEC, NULL, 0x0,
1938         "The offset for the first soft key set in this message.",
1939         HFILL }
1940     },
1941
1942     { &hf_skinny_softKeySetCount,
1943       { "SoftKeySetCount", "skinny.softKeySetCount",
1944         FT_UINT32, BASE_DEC, NULL, 0x0,
1945         "The number of valid softkey sets in this message.",
1946         HFILL }
1947     },
1948
1949     { &hf_skinny_totalSoftKeySetCount,
1950       { "TotalSoftKeySetCount", "skinny.totalSoftKeySetCount",
1951         FT_UINT32, BASE_DEC, NULL, 0x0,
1952         "The total number of softkey sets for this device.",
1953         HFILL }
1954     },
1955
1956     { &hf_skinny_softKeyTemplateIndex,
1957       { "SoftKeyTemplateIndex", "skinny.softKeyTemplateIndex",
1958         FT_UINT8, BASE_DEC, VALS(softKeyEvents), 0x0,
1959         "Array of size 16 8-bit unsigned ints containing an index into the softKeyTemplate.",
1960         HFILL }
1961     },
1962
1963     { &hf_skinny_softKeyInfoIndex,
1964       { "SoftKeyInfoIndex", "skinny.softKeyInfoIndex",
1965         FT_UINT16, BASE_DEC, VALS(softKeyIndexes), 0x0,
1966         "Array of size 16 16-bit unsigned integers containing an index into the soft key description information.",
1967         HFILL }
1968     },
1969
1970     { &hf_skinny_softKeySetDescription,
1971       { "SoftKeySet", "skinny.softKeySetDescription",
1972         FT_UINT8, BASE_DEC, VALS(keySetNames), 0x0,
1973         "A text description of what this softkey when this softkey set is displayed",
1974         HFILL }
1975     },
1976
1977     { &hf_skinny_softKeyMap,
1978       { "SoftKeyMap","skinny.softKeyMap", 
1979         FT_UINT16, BASE_HEX, NULL, 0x0,
1980         "", 
1981         HFILL }
1982     },
1983     
1984     { &hf_skinny_softKey0,
1985       { "SoftKey0", "skinny.softKeyMap.0", 
1986         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY0,
1987         "", 
1988         HFILL }
1989     },
1990
1991     { &hf_skinny_softKey1,
1992       { "SoftKey1", "skinny.softKeyMap.1", 
1993         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY1,
1994         "", 
1995         HFILL }
1996     },
1997
1998     { &hf_skinny_softKey2,
1999       { "SoftKey2", "skinny.softKeyMap.2", 
2000         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY2,
2001         "", 
2002         HFILL }
2003     },
2004
2005     { &hf_skinny_softKey3,
2006       { "SoftKey3", "skinny.softKeyMap.3",
2007         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY3,
2008         "", 
2009         HFILL }
2010     },
2011
2012     { &hf_skinny_softKey4,
2013       { "SoftKey4", "skinny.softKeyMap.4", 
2014         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY4,
2015         "", 
2016         HFILL }
2017     },
2018
2019     { &hf_skinny_softKey5,
2020       { "SoftKey5", "skinny.softKeyMap.5", 
2021         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY5,
2022         "", 
2023         HFILL }
2024     },
2025
2026     { &hf_skinny_softKey6,
2027       { "SoftKey6", "skinny.softKeyMap.6", 
2028         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY6,
2029         "", 
2030         HFILL }
2031     },
2032
2033     { &hf_skinny_softKey7,
2034       { "SoftKey7", "skinny.softKeyMap.7", 
2035         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY7,
2036         "", 
2037         HFILL }
2038     },
2039
2040     { &hf_skinny_softKey8,
2041       { "SoftKey8", "skinny.softKeyMap.8", 
2042         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY8,
2043         "", 
2044         HFILL }
2045     },
2046
2047     { &hf_skinny_softKey9,
2048       { "SoftKey9", "skinny.softKeyMap.9", 
2049         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY9,
2050         "", 
2051         HFILL }
2052     },
2053
2054     { &hf_skinny_softKey10,
2055       { "SoftKey10", "skinny.softKeyMap.10", 
2056         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY10,
2057         "", 
2058         HFILL }
2059     },
2060
2061     { &hf_skinny_softKey11,
2062       { "SoftKey11", "skinny.softKeyMap.11", 
2063         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY11,
2064         "", 
2065         HFILL }
2066     },
2067
2068     { &hf_skinny_softKey12,
2069       { "SoftKey12", "skinny.softKeyMap.12", 
2070         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY12,
2071         "", 
2072         HFILL }
2073     },
2074
2075     { &hf_skinny_softKey13,
2076       { "SoftKey13", "skinny.softKeyMap.13", 
2077         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY13,
2078         "", 
2079         HFILL }
2080     },
2081
2082     { &hf_skinny_softKey14,
2083       { "SoftKey14", "skinny.softKeyMap.14", 
2084         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY14,
2085         "", 
2086         HFILL }
2087     },
2088
2089     { &hf_skinny_softKey15,
2090       { "SoftKey15", "skinny.softKeyMap.15", 
2091         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY15,
2092         "", 
2093         HFILL }
2094     },
2095
2096     { &hf_skinny_lampMode,
2097       { "LampMode", "skinny.lampMode", 
2098         FT_UINT32, BASE_DEC, VALS(stationLampModes), 0x0,
2099         "The lamp mode", 
2100         HFILL }
2101     },
2102
2103     { &hf_skinny_messageTimeOutValue,
2104       { "Message Timeout", "skinny.messageTimeOutValue", 
2105         FT_UINT32, BASE_DEC, NULL, 0x0,
2106         "The timeout in seconds for this message", 
2107         HFILL }
2108     },
2109
2110     { &hf_skinny_displayMessage,
2111       { "DisplayMessage", "skinny.displayMessage",
2112         FT_STRING, BASE_NONE, NULL, 0x0,
2113         "The message displayed on the phone.",
2114         HFILL }
2115     },
2116
2117     { &hf_skinny_lineDirNumber,
2118       { "Line Dir Number", "skinny.lineDirNumber",
2119         FT_STRING, BASE_NONE, NULL, 0x0,
2120         "The directory number for this line.",
2121         HFILL }
2122     },
2123
2124     { &hf_skinny_lineFullyQualifiedDisplayName,
2125       { "DisplayName", "skinny.fqdn",
2126         FT_STRING, BASE_NONE, NULL, 0x0,
2127         "The full display name for this line.",
2128         HFILL }
2129     },
2130
2131     { &hf_skinny_speedDialDirNumber,
2132       { "SpeedDial Number", "skinny.speedDialDirNum",
2133         FT_STRING, BASE_NONE, NULL, 0x0,
2134         "the number to dial for this speed dial.",
2135         HFILL }
2136     },
2137
2138     { &hf_skinny_speedDialDisplayName,
2139       { "SpeedDial Display", "skinny.speedDialDisplay",
2140         FT_STRING, BASE_NONE, NULL, 0x0,
2141         "The text to display for this speed dial.",
2142         HFILL }
2143     },
2144
2145     { &hf_skinny_dateYear,
2146       { "Year", "skinny.year",
2147         FT_UINT32, BASE_DEC, NULL, 0x0,
2148         "The current year",
2149         HFILL }
2150     },
2151
2152     { &hf_skinny_dateMonth,
2153       { "Month", "skinny.month",
2154         FT_UINT32, BASE_DEC, NULL, 0x0,
2155         "The current month",
2156         HFILL }
2157     },
2158
2159     { &hf_skinny_dayOfWeek,
2160       { "DayOfWeek", "skinny.dayOfWeek",
2161         FT_UINT32, BASE_DEC, NULL, 0x0,
2162         "The day of the week",
2163         HFILL }
2164     },
2165
2166     { &hf_skinny_dateDay,
2167       { "Day", "skinny.day",
2168         FT_UINT32, BASE_DEC, NULL, 0x0,
2169         "The day of the current month",
2170         HFILL }
2171     },
2172
2173     { &hf_skinny_dateHour,
2174       { "Hour", "skinny.hour",
2175         FT_UINT32, BASE_DEC, NULL, 0x0,
2176         "Hour of the day",
2177         HFILL }
2178     },
2179
2180     { &hf_skinny_dateMinute,
2181       { "Minute", "skinny.minute",
2182         FT_UINT32, BASE_DEC, NULL, 0x0,
2183         "Minute",
2184         HFILL }
2185     },
2186
2187     { &hf_skinny_dateSeconds,
2188       { "Seconds", "skinny.dateSeconds",
2189         FT_UINT32, BASE_DEC, NULL, 0x0,
2190         "Seconds",
2191         HFILL }
2192     },
2193
2194     { &hf_skinny_dateMilliseconds,
2195       { "Milliseconds", "skinny.dateMilliseconds",
2196         FT_UINT32, BASE_DEC, NULL, 0x0,
2197         "Milliseconds",
2198         HFILL }
2199     },
2200
2201     { &hf_skinny_timeStamp,
2202       { "Timestamp", "skinny.timeStamp",
2203         FT_UINT32, BASE_DEC, NULL, 0x0,
2204         "Time stamp for the call reference",
2205         HFILL }
2206     },
2207     { &hf_skinny_callState,
2208       { "CallState", "skinny.callState", 
2209         FT_UINT32, BASE_DEC, VALS(skinny_stationCallStates), 0x0,
2210         "The D channel call state of the call", 
2211         HFILL }
2212     },
2213
2214     { &hf_skinny_deviceTone,
2215       { "Tone", "skinny.deviceTone", 
2216         FT_UINT32, BASE_HEX, VALS(skinny_deviceTones), 0x0,
2217         "Which tone to play", 
2218         HFILL }
2219     },
2220
2221     { &hf_skinny_callingPartyName,
2222       { "Calling Party Name", "skinny.callingPartyName",
2223         FT_STRING, BASE_NONE, NULL, 0x0,
2224         "The passed name of the calling party.",
2225         HFILL }
2226     },
2227
2228     { &hf_skinny_callingParty,
2229       { "Calling Party", "skinny.callingPartyName",
2230         FT_STRING, BASE_NONE, NULL, 0x0,
2231         "The passed number of the calling party.",
2232         HFILL }
2233     },
2234
2235     { &hf_skinny_calledPartyName,
2236       { "Called Party Name", "skinny.calledPartyName",
2237         FT_STRING, BASE_NONE, NULL, 0x0,
2238         "The name of the party we are calling.",
2239         HFILL }
2240     },
2241
2242     { &hf_skinny_callType,
2243       { "Call Type", "skinny.callType", 
2244         FT_UINT32, BASE_DEC, VALS(skinny_callTypes), 0x0,
2245         "What type of call, in/out/etc", 
2246         HFILL }
2247     },
2248
2249     { &hf_skinny_originalCalledPartyName,
2250       { "Original Called Party Name", "skinny.originalCalledPartyName",
2251         FT_STRING, BASE_NONE, NULL, 0x0,
2252         "name of the original person who placed the call.",
2253         HFILL }
2254     },
2255
2256     { &hf_skinny_originalCalledParty,
2257       { "Original Called Party", "skinny.originalCalledParty",
2258         FT_STRING, BASE_NONE, NULL, 0x0,
2259         "The number of the original calling party.",
2260         HFILL }
2261     },
2262
2263     { &hf_skinny_ringType,
2264       { "Ring Type", "skinny.ringType", 
2265         FT_UINT32, BASE_HEX, VALS(skinny_ringTypes), 0x0,
2266         "What type of ring to play", 
2267         HFILL }
2268     },
2269
2270     { &hf_skinny_speakerMode,
2271       { "Speaker", "skinny.speakerMode", 
2272         FT_UINT32, BASE_HEX, VALS(skinny_speakerModes), 0x0,
2273         "This message sets the speaker mode on/off", 
2274         HFILL }
2275     },
2276
2277     { &hf_skinny_remoteIpAddr,
2278       { "Remote Ip Address", "skinny.remoteIpAddr",
2279         FT_IPv4, BASE_NONE, NULL, 0x0,
2280         "The remote end ip address for this stream",
2281         HFILL }
2282     },
2283
2284     { &hf_skinny_remotePortNumber,
2285       { "Remote Port", "skinny.remotePortNumber",
2286         FT_UINT32, BASE_DEC, NULL, 0x0,
2287         "The remote port number listening for this stream",
2288         HFILL }
2289     },
2290
2291     { &hf_skinny_millisecondPacketSize,
2292       { "MS/Packet", "skinny.millisecondPacketSize",
2293         FT_UINT32, BASE_DEC, NULL, 0x0,
2294         "The number of milliseconds of conversation in each packet",
2295         HFILL }
2296     },
2297
2298     { &hf_skinny_precedenceValue,
2299       { "Precedence", "skinny.precedenceValue",
2300         FT_UINT32, BASE_DEC, NULL, 0x0,
2301         "Precedence value",
2302         HFILL }
2303     },
2304
2305     { &hf_skinny_silenceSuppression,
2306       { "Silence Suppression", "skinny.silenceSuppression", 
2307         FT_UINT32, BASE_HEX, VALS(skinny_silenceSuppressionModes), 0x0,
2308         "Mode for silence suppression", 
2309         HFILL }
2310     },
2311
2312     { &hf_skinny_g723BitRate,
2313       { "G723 BitRate", "skinny.g723BitRate", 
2314         FT_UINT32, BASE_DEC, VALS(skinny_g723BitRates), 0x0,
2315         "The G723 bit rate for this stream/JUNK if not g723 stream", 
2316         HFILL }
2317     },
2318
2319     { &hf_skinny_conferenceID,
2320       { "Conference ID", "skinny.conferenceID",
2321         FT_UINT32, BASE_DEC, NULL, 0x0,
2322         "The conference ID",
2323         HFILL }
2324     },
2325
2326     { &hf_skinny_deviceResetType,
2327       { "Reset Type", "skinny.deviceResetType", 
2328         FT_UINT32, BASE_DEC, VALS(skinny_deviceResetTypes), 0x0,
2329         "How the devices it to be reset (reset/restart)", 
2330         HFILL }
2331     },
2332
2333     { &hf_skinny_echoCancelType,
2334       { "Echo Cancel Type", "skinny.echoCancelType", 
2335         FT_UINT32, BASE_DEC, VALS(skinny_echoCancelTypes), 0x0,
2336         "Is echo cancelling enabled or not", 
2337         HFILL }
2338     },
2339
2340     { &hf_skinny_deviceUnregisterStatus,
2341       { "Unregister Status", "skinny.deviceUnregisterStatus", 
2342         FT_UINT32, BASE_DEC, VALS(skinny_deviceUnregisterStatusTypes), 0x0,
2343         "The status of the device unregister request (*CAN* be refused)", 
2344         HFILL }
2345     },
2346
2347     { &hf_skinny_hookFlashDetectMode,
2348       { "Hook Flash Mode", "skinny.hookFlashDetectMode", 
2349         FT_UINT32, BASE_DEC, VALS(skinny_hookFlashDetectModes), 0x0,
2350         "Which method to use to detect that a hook flash has occured", 
2351         HFILL }
2352     },
2353
2354     { &hf_skinny_detectInterval,
2355       { "HF Detect Interval", "skinny.detectInterval",
2356         FT_UINT32, BASE_DEC, NULL, 0x0,
2357         "The number of milliseconds that determines a hook flash has occured",
2358         HFILL }
2359     },
2360
2361     { &hf_skinny_microphoneMode,
2362       { "Microphone Mode", "skinny.microphoneMode", 
2363         FT_UINT32, BASE_DEC, VALS(skinny_microphoneModes), 0x0,
2364         "Turns on and off the microphone on the set", 
2365         HFILL }
2366     },
2367
2368     { &hf_skinny_activeForward,
2369       { "Active Forward", "skinny.activeForward",
2370         FT_UINT32, BASE_DEC, NULL, 0x0,
2371         "This is non zero to indicate that a forward is active on the line",
2372         HFILL }
2373     },
2374
2375     { &hf_skinny_forwardAllActive,
2376       { "Forward All", "skinny.forwardAllActive",
2377         FT_UINT32, BASE_DEC, NULL, 0x0,
2378         "Forward all calls",
2379         HFILL }
2380     },
2381
2382     { &hf_skinny_forwardBusyActive,
2383       { "Forward Busy", "skinny.forwardBusyActive",
2384         FT_UINT32, BASE_DEC, NULL, 0x0,
2385         "Forward calls when busy",
2386         HFILL }
2387     },
2388
2389     { &hf_skinny_forwardNoAnswerActive,
2390       { "Forward NoAns", "skinny.forwardNoAnswerActive",
2391         FT_UINT32, BASE_DEC, NULL, 0x0,
2392         "Forward only when no answer",
2393         HFILL }
2394     },
2395
2396     { &hf_skinny_forwardNumber,
2397       { "Forward Number", "skinny.forwardNumber",
2398         FT_STRING, BASE_NONE, NULL, 0x0,
2399         "The number to forward calls to.",
2400         HFILL }
2401     },
2402
2403     { &hf_skinny_userName,
2404       { "Username", "skinny.userName",
2405         FT_STRING, BASE_NONE, NULL, 0x0,
2406         "Username for this device.",
2407         HFILL }
2408     },
2409
2410     { &hf_skinny_serverName,
2411       { "Server Name", "skinny.serverName",
2412         FT_STRING, BASE_NONE, NULL, 0x0,
2413         "The server name for this device.",
2414         HFILL }
2415     },
2416
2417     { &hf_skinny_numberLines,
2418       { "Number of Lines", "skinny.numberLines",
2419         FT_UINT32, BASE_DEC, NULL, 0x0,
2420         "How many lines this device has",
2421         HFILL }
2422     },
2423
2424     { &hf_skinny_numberSpeedDials,
2425       { "Number of SpeedDials", "skinny.numberSpeedDials",
2426         FT_UINT32, BASE_DEC, NULL, 0x0,
2427         "The number of speed dials this device has",
2428         HFILL }
2429     },
2430
2431     { &hf_skinny_sessionType,
2432       { "Session Type", "skinny.sessionType", 
2433         FT_UINT32, BASE_DEC, VALS(skinny_sessionTypes), 0x0,
2434         "The type of this session.", 
2435         HFILL }
2436     },
2437
2438     { &hf_skinny_version,
2439       { "Version", "skinny.version",
2440         FT_STRING, BASE_NONE, NULL, 0x0,
2441         "Version.",
2442         HFILL }
2443     },
2444
2445     { &hf_skinny_mediaEnunciationType,
2446       { "Enunciation Type", "skinny.mediaEnunciationType", 
2447         FT_UINT32, BASE_DEC, VALS(skinny_mediaEnunciationTypes), 0x0,
2448         "No clue.", 
2449         HFILL }
2450     },
2451
2452     { &hf_skinny_serverIdentifier,
2453       { "Server Identifier", "skinny.serverIdentifier",
2454         FT_STRING, BASE_NONE, NULL, 0x0,
2455         "Server Identifier.",
2456         HFILL }
2457     },
2458
2459     { &hf_skinny_serverListenPort,
2460       { "Server Port", "skinny.serverListenPort", 
2461         FT_UINT32, BASE_DEC, NULL, 0x0,
2462         "The port the server listens on.", 
2463         HFILL }
2464     },
2465
2466     { &hf_skinny_serverIpAddress,
2467       { "Server Ip Address", "skinny.serverIpAddress",
2468         FT_IPv4, BASE_NONE, NULL, 0x0,
2469         "The IP address for this server",
2470         HFILL }
2471     },
2472
2473     { &hf_skinny_multicastPort,
2474       { "Multicast Port", "skinny.multicastPort", 
2475         FT_UINT32, BASE_DEC, NULL, 0x0,
2476         "The multicast port the to listens on.", 
2477         HFILL }
2478     },
2479
2480     { &hf_skinny_multicastIpAddress,
2481       { "Multicast Ip Address", "skinny.multicastIpAddress",
2482         FT_IPv4, BASE_NONE, NULL, 0x0,
2483         "The multicast address for this conference",
2484         HFILL }
2485     },
2486
2487     { &hf_skinny_tokenRejWaitTime,
2488       { "Retry Wait Time", "skinny.tokenRejWaitTime", 
2489         FT_UINT32, BASE_DEC, NULL, 0x0,
2490         "The time to wait before retrying this token request.", 
2491         HFILL }
2492     },
2493
2494     { &hf_skinny_unknown,
2495       { "Data", "skinny.unknown", 
2496         FT_UINT32, BASE_HEX, NULL, 0x0,
2497         "Place holder for unknown data.", 
2498         HFILL }
2499     },
2500
2501   };
2502   
2503   /* Setup protocol subtree array */
2504   static gint *ett[] = {
2505     &ett_skinny,
2506     &ett_skinny_softKeyMap,
2507   };
2508
2509   module_t *skinny_module;
2510
2511   /* Register the protocol name and description */
2512   proto_skinny = proto_register_protocol("Skinny Client Control Protocol",
2513                                          "SKINNY", "skinny");
2514   
2515   /* Required function calls to register the header fields and subtrees used */
2516   proto_register_field_array(proto_skinny, hf, array_length(hf));
2517   proto_register_subtree_array(ett, array_length(ett));
2518
2519   skinny_module = prefs_register_protocol(proto_skinny, NULL);
2520   prefs_register_bool_preference(skinny_module, "desegment",
2521     "Desegment all SCCP messages spanning multiple TCP segments",
2522     "Whether the SCCP dissector should desegment all messages spanning multiple TCP segments",
2523     &skinny_desegment);
2524 };
2525
2526 void
2527 proto_reg_handoff_skinny(void)
2528 {
2529   dissector_handle_t skinny_handle;
2530
2531   data_handle = find_dissector("data");
2532   skinny_handle = create_dissector_handle(dissect_skinny, proto_skinny);
2533   dissector_add("tcp.port", TCP_PORT_SKINNY, skinny_handle);
2534 }
2535
2536 /*
2537  * FIXME:
2538  *
2539  * This is the status of this decode.
2540  * Items marked as N/A in the decode field have no params to test
2541  * implemented for N/A means they exist in the switch statement
2542  * S = stubbed
2543  *
2544  *  id     message                     implemented  decode tested (via capture)
2545  *  ---------------------------------------------------------------------------
2546  *  0x0    keepAlive                       Y        N/A 
2547  *  0x1    register                        Y        Y
2548  *  0x2    ipPort                          Y        Y
2549  *  0x3    keypadButton                    Y        Y
2550  *  0x4    enblocCall                      Y        N
2551  *  0x5    stimulus                        Y        N
2552  *  0x6    offHook                         Y        N/A
2553  *  0x7    onHook                          Y        N/A
2554  *  0x8    hookFlash                       Y        N/A
2555  *  0x9    forwardStatReq                  Y        N
2556  *  0xa    speedDialStatReq                Y        Y
2557  *  0xb    lineStatReq                     Y        Y
2558  *  0xc    configStatReq                   Y        N/A
2559  *  0xd    timeDateReq                     Y        N/A
2560  *  0xe    buttonTemplateReq               Y        N/A
2561  *  0xf    versionReq                      Y        N/A
2562  *  0x10   capabilitiesRes                 Y        Y -- would like more decodes
2563  *  0x11   mediaPortList                   S        N -- no info 
2564  *  0x12   serverReq                       Y        N/A
2565  *  0x20   alarmMessage                    Y        Y
2566  *  0x21   multicastMediaReceptionAck      Y        N
2567  *  0x22   openReceiveChannelAck           Y        Y
2568  *  0x23   connectionStatisticsRes         Y        Y
2569  *  0x24   offHookWithCgpn                 Y        N
2570  *  0x25   softKeySetReq                   Y        N/A
2571  *  0x26   softKeyEvent                    Y        Y
2572  *  0x27   unregister                      Y        N/A
2573  *  0x28   softKeytemplateReq              Y        N/A
2574  *  0x29   registerTokenReq                Y        N
2575  *******************************
2576  *  0x2b   unknownClientMessage1           S        N
2577  *  0x2d   unknownClientMessage2           S        N
2578  *******************************
2579  *  0x81   registerAck                     Y        Y
2580  *  0x82   startTone                       Y        Y
2581  *  0x83   stopTone                        Y        N/A
2582  *  0x85   setRinger                       Y        Y
2583  *  0x86   setLamp                         Y        Y
2584  *  0x87   setHkFDetect                    Y        N
2585  *  0x88   setSpeakerMode                  Y        Y
2586  *  0x89   setMicroMode                    Y        N
2587  *  0x8A   startMediaTransmission          Y        Y
2588  *  0x8B   stopMediaTransmission           Y        Y
2589  *  0x8C   startMediaReception             S        N
2590  *  0x8D   stopMediaReception              S        N
2591  *  0x8E   *reserved*                      S        *
2592  *  0x8F   callInfo                        Y        Y
2593  *  0x90   forwardStat                     Y        N
2594  *  0x91   speedDialStat                   Y        Y
2595  *  0x92   lineStat                        Y        Y
2596  *  0x93   configStat                      Y        N
2597  *  0x94   defineTimeDate                  Y        Y
2598  *  0x95   startSessionTransmission        Y        N
2599  *  0x96   stopSessionTransmission         Y        N
2600  *  0x97   buttonTemplate                  Y        Y -- ugly =)
2601  *  0x98   version                         Y        N
2602  *  0x99   displayText                     Y        Y
2603  *  0x9A   clearDisplay                    Y        N/A
2604  *  0x9B   capabilitiesReq                 Y        N/A
2605  *  0x9C   enunciatorCommand               Y        N (inner loop unknown)
2606  *  0x9D   registerReject                  Y        N
2607  *  0x9E   serverRes                       Y        N
2608  *  0x9F   reset                           Y        Y
2609  *  0x100  keepAliveAck                    Y        N/A
2610  *  0x101  startMulticastMediaReception    Y        N
2611  *  0x102  startMulticastMediaTransmission Y        N
2612  *  0x103  stopMulticastMediaReception     Y        N
2613  *  0x104  stopMulticastMediaTransmission  Y        N
2614  *  0x105  openreceiveChannel              Y        Y
2615  *  0x106  closeReceiveChannel             Y        Y
2616  *  0x107  connectionStatisticsReq         Y        Y
2617  *  0x108  softKeyTemplateRes              Y        Y
2618  *  0x109  softKeySetRes                   Y        Y
2619  *  0x110  selectSoftKeys                  Y        Y
2620  *  0x111  callState                       Y        Y
2621  *  0x112  displayPromptStatus             Y        Y
2622  *  0x113  clearPromptStatus               Y        Y
2623  *  0x114  displayNotify                   Y        Y
2624  *  0x115  clearNotify                     Y        Y
2625  *  0x116  activateCallPlane               Y        Y
2626  *  0x117  deactivateCallPlane             Y        N/A
2627  *  0x118  unregisterAck                   Y        Y
2628  *  0x119  backSpaceReq                    Y        Y
2629  *  0x11A  registerTokenAck                Y        N
2630  *  0x11B  registerTokenReject             Y        N
2631  *******************************
2632  *  0x11D  unknownForwardMessage           NC       N
2633  *******************************
2634  *
2635  *
2636  */