Updates from Paul Erkkila.
[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.14 2002/03/20 23:32:54 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   , "NonStandard"},
281   {2   , "G711Alaw64k"},
282   {3   , "G711Alaw56k"},
283   {4   , "G711Ulaw64k"},
284   {5   , "G711Ulaw56k"},
285   {6   , "G722_64k"},
286   {7   , "G722_56k"},
287   {8   , "G722_48k"},
288   {9   , "G7231"},
289   {10  , "G728"},
290   {11  , "G729"},
291   {12  , "G729AnnexA"},
292   {13  , "Is11172AudioCap"},
293   {14  , "Is13818AudioCap"},
294   {15  , "G729AnnexB"},
295   {16  , "G729AnnexAwAnnexB"},
296   {32  , "Data64"},
297   {33  , "Data56"},
298   {80  , "GSM"},
299   {81  , "ActiveVoice"},
300   {82  , "G726_32K"},
301   {83  , "G726_24K"},
302   {84  , "G726_16K"},
303   {85  , "G729_B"},
304   {86  , "G729_B_LOW_COMPLEXITY"},
305   {0  , NULL}
306 };
307
308 static const value_string alarmSeverities[] = {
309   {0   , "Critical"},
310   {1   , "Warning"},
311   {2   , "Informational"},
312   {4   , "Unknown"},
313   {7   , "Major"},
314   {8   , "Minor"},
315   {10  , "Marginal"},
316   {20  , "TraceInfo"},
317   {0  , NULL}
318 };
319
320 static const value_string multicastMediaReceptionStatus[] = {
321   {0  , "Ok"},
322   {1  , "Error"},
323   {0  , NULL}
324 };
325
326 static const value_string openReceiveChanStatus[] = {
327   {0   , "orcOk"},
328   {1   , "orcError"},
329   {0   , NULL}
330 };
331
332
333 static const value_string statsProcessingTypes[] = {
334   {0   , "clearStats"},
335   {1   , "doNotClearStats"},
336   {0   , NULL}
337 };
338
339 #define SkMaxSoftKeyCount 18 /* this value should be the same as the max soft key value */
340 static const value_string softKeyEvents[] = {
341   {1   , "Redial"},
342   {2   , "NewCall"},
343   {3   , "Hold"},
344   {4   , "Trnsfer"},
345   {5   , "CFwdAll"},
346   {6   , "CFwdBusy"},
347   {7   , "CFwdNoAnswer"},
348   {8   , "BackSpace"},
349   {9   , "EndCall"},
350   {10  , "Resume"},
351   {11  , "Answer"},
352   {12  , "Info"},
353   {13  , "Confrn"},
354   {14  , "Park"},
355   {15  , "Join"},
356   {16  , "MeetMeConfrn"},
357   {17  , "CallPickUp"},
358   {18  , "GrpCallPickUp"},
359   {0   , NULL}
360 };
361
362 /* Define info index for each softkey event for Telecaster station. */
363 static const value_string softKeyIndexes[] = {
364   {301  , "RedialInfoIndex"},
365   {302  , "NewCallInfoIndex"},
366   {303  , "HoldInfoIndex"},
367   {304  , "TrnsferInfoIndex"},
368   {305  , "CFwdAllInfoIndex"},
369   {306  , "CFwdBusyInfoIndex"},     /* not used yet */
370   {307  , "CFwdNoAnswerInfoIndex"}, /* not used yet */
371   {308  , "BackSpaceInfoIndex"},
372   {309  , "EndCallInfoIndex"},
373   {310  , "ResumeInfoIndex"},
374   {311  , "AnswerInfoIndex"},
375   {312  , "InfoInfoIndex"},
376   {313  , "ConfrnInfoIndex"},
377   {314  , "ParkInfoIndex"},
378   {315  , "JoinInfoIndex"},
379   {316  , "MeetMeConfrnInfoIndex"},
380   {317  , "CallPickUpInfoIndex"},
381   {318  , "GrpCallPickUpInfoIndex"},
382   {0   , NULL}
383 };
384
385
386 static const value_string buttonDefinitions[] = {
387   {1    , "LastNumberRedial"},
388   {2    , "SpeedDial"},
389   {3    , "Hold"},
390   {4    , "Transfer"},
391   {5    , "ForwardAll"},
392   {6    , "ForwardBusy"},
393   {7    , "ForwardNoAnswer"},
394   {8    , "Display"},
395   {9    , "Line"},
396   {0xa  , "T120Chat"},
397   {0xb  , "T120Whiteboard"},
398   {0xc  , "T120ApplicationSharing"},
399   {0xd  , "T120FileTransfer"},
400   {0xe  , "Video"},
401   {0x10 , "AnswerRelease"},
402   {0xf0 , "Keypad"},
403   {0xfd , "AEC"},
404   {0xff , "Undefined"},
405   {0   , NULL}
406 };
407
408 #define StationTotalSoftKeySets 10 /* total number of the soft key sets */
409 static const value_string keySetNames[] = {
410   {0   , "OnHook"},
411   {1   , "Connected"},
412   {2   , "OnHold"},
413   {3   , "RingIn"},
414   {4   , "OffHook"},
415   {5   , "Connected with transfer"},
416   {6   , "Digits after dialing first digit"},
417   {7   , "Connected with conference"},
418   {8   , "RingOut"},
419   {9   , "OffHook with features"},
420   {0   , NULL}
421 };
422
423 /* Define soft key labels for the Telecaster station */
424 static const value_string softKeyLabel[] = { 
425   {0   , "undefined"},
426   {1   , "Redial"},
427   {2   , "NewCall"},
428   {3   , "Hold"},
429   {4   , "Trnsfer"},
430   {5   , "CFwdAll"},
431   {6   , "CFwdBusy"},
432   {7   , "CFwdNoAnswer"},
433   {8   , "<<"},
434   {9   , "EndCall"},
435   {10  , "Resume"},
436   {11  , "Answer"},
437   {12  , "Info"},
438   {13  , "Confrn"},
439   {14  , "Park"},
440   {15  , "Join"},
441   {16  , "MeetMe"},
442   {17  , "PickUp"},
443   {18  , "GPickUp"},
444   {0   , NULL}
445 }; 
446
447
448 /* 
449  * define lamp modes; 
450  * lamp cadence is defined as follows 
451  * Wink (on 80%) = 448msec on / 64msec off 
452  * Flash (fast flash) = 32msec on / 32msec off 
453  * Blink (on 50%) = 512msec on / 512msec off 
454  * On (on steady) 
455  */
456 static const value_string stationLampModes[] = {
457   {0   , "Undefined"},
458   {0x1 , "LampOff"},
459   {0x2 , "LampOn"},
460   {0x3 , "LampWink"},
461   {0x4 , "LampFlash"},
462   {0x5 , "LampBlink"},
463   {0   , NULL}
464 }; 
465
466 /* Defined the Call States to be sent to the Telecaste station. 
467  * These are NOT the call states used in CM internally. Instead, 
468  * they are the call states sent from CM and understood by the Telecaster station 
469  */
470 static const value_string skinny_stationCallStates[] = {
471   {1   , "OffHook"},
472   {2   , "OnHook"},
473   {3   , "RingOut"},
474   {4   , "RingIn"}, 
475   {5   , "Connected"}, 
476   {6   , "Busy"}, 
477   {7   , "Congestion"}, 
478   {8   , "Hold"}, 
479   {9   , "CallWaiting"}, 
480   {10  , "CallTransfer"}, 
481   {11  , "CallPark"}, 
482   {12  , "Proceed"}, 
483   {13  , "CallRemoteMultiline"}, 
484   {14  , "InvalidNumber"}, 
485   {0   , NULL}
486 };
487
488 /* Defined Call Type */
489 static const value_string skinny_callTypes[] = { 
490   {1   , "TsInBoundCall"},
491   {2   , "TsOutBoundCall"}, 
492   {3   , "TsForwardCall"}, 
493   {0   , NULL}
494 }; 
495
496 /* 
497  * define station-playable tones; 
498  * for tone definitions see SR-TSV-002275, "BOC Notes on the LEC Networks -- 1994" 
499  */
500 static const value_string skinny_deviceTones[] = {
501   {0    , "DtSilence"},
502   {1    , "DtDtmf1"},
503   {2    , "DtDtmf2"},
504   {3    , "DtDtmf3"},
505   {4    , "DtDtmf4"},
506   {5    , "DtDtmf5"},
507   {6    , "DtDtmf6"},
508   {7    , "DtDtmf7"},
509   {8    , "DtDtmf8"},
510   {9    , "DtDtmf9"},
511   {0xa  , "DtDtmf0"},
512   {0xe  , "DtDtmfStar"},
513   {0xf  , "DtDtmfPound"},
514   {0x10 , "DtDtmfA"},
515   {0x11 , "DtDtmfB"},
516   {0x12 , "DtDtmfC"},
517   {0x13 , "DtDtmfD"},
518   {0x21 , "DtInsideDialTone"},
519   {0x22 , "DtOutsideDialTone"},
520   {0x23 , "DtLineBusyTone"},
521   {0x24 , "DtAlertingTone"},
522   {0x25 , "DtReorderTone"},
523   {0x26 , "DtRecorderWarningTone"},
524   {0x27 , "DtRecorderDetectedTone"},
525   {0x28 , "DtRevertingTone"},
526   {0x29 , "DtReceiverOffHookTone"},
527   {0x2a , "DtPartialDialTone"},
528   {0x2b , "DtNoSuchNumberTone"},
529   {0x2c , "DtBusyVerificationTone"},
530   {0x2d , "DtCallWaitingTone"},
531   {0x2e , "DtConfirmationTone"},
532   {0x2f , "DtCampOnIndicationTone"},
533   {0x30 , "DtRecallDialTone"},
534   {0x31 , "DtZipZip"},
535   {0x32 , "DtZip"},
536   {0x33 , "DtBeepBonk"},
537   {0x34 , "DtMusicTone"},
538   {0x35 , "DtHoldTone"},
539   {0x36 , "DtTestTone"},
540   {0x40 , "Dt_AddCallWaiting"},
541   {0x41 , "Dt_PriorityCallWait"},
542   {0x42 , "Dt_RecallDial"},
543   {0x43 , "Dt_BargIn"},
544   {0x44 , "Dt_DistinctAlert"},
545   {0x45 , "Dt_PriorityAlert"},
546   {0x46 , "Dt_ReminderRing"},
547   {0x50 , "Dt_MF1"},
548   {0x51 , "Dt_MF2"},
549   {0x52 , "Dt_MF3"},
550   {0x53 , "Dt_MF4"},
551   {0x54 , "Dt_MF5"},
552   {0x55 , "Dt_MF6"},
553   {0x56 , "Dt_MF7"},
554   {0x57 , "Dt_MF8"},
555   {0x58 , "Dt_MF9"},
556   {0x59 , "Dt_MF0"},
557   {0x5a , "Dt_MFKP1"},
558   {0x5b , "Dt_MFST"},
559   {0x5c , "Dt_MFKP2"},
560   {0x5d , "Dt_MFSTP"},
561   {0x5e , "Dt_MFST3P"},
562   {0x5f , "Dt_MILLIWATT"},
563   {0x60 , "Dt_MILLIWATTTEST"},
564   {0x61 , "Dt_HIGHTONE"},
565   {0x62 , "Dt_FLASHOVERRIDE"},
566   {0x63 , "Dt_FLASH"},
567   {0x64 , "Dt_PRIORITY"},
568   {0x65 , "Dt_IMMEDIATE"},
569   {0x66 , "Dt_PREAMPWARN"},
570   {0x67 , "Dt_2105HZ"},
571   {0x68 , "Dt_2600HZ"},
572   {0x69 , "Dt_440HZ"},
573   {0x6a , "Dt_300HZ"},
574   {0x7f , "Dt_NoTone"},
575   {0   , NULL}
576 };
577
578 /* define ring types */
579 static const value_string skinny_ringTypes[] = {
580   {0x1  , "StationRingOff"},
581   {0x2  , "StationInsideRing"},
582   {0x3  , "StationOutsideRing"},
583   {0x4  , "StationFeatureRing"},
584   {0   , NULL}
585 };
586
587 static const value_string skinny_speakerModes[] = {
588   {1   , "StationSpeakerOn"},
589   {2   , "StationSpeakerOff"},
590   {0   , NULL}
591 };
592
593 static const value_string skinny_silenceSuppressionModes[] = {
594   {0   , "Media_SilenceSuppression_Off"},
595   {1   , "Media_SilenceSuppression_On"},
596   {0   , NULL}
597 }; 
598
599 static const value_string skinny_g723BitRates[] = {
600   {1   , "Media_G723BRate_5_3"},
601   {2   , "Media_G723BRate_6_4"},
602   {0   , NULL}
603 };
604
605 /* define device reset types  */
606 static const value_string skinny_deviceResetTypes[] = {
607   {1   , "DEVICE_RESET"},
608   {2   , "DEVICE_RESTART"},
609   {0   , NULL}
610 }; 
611
612 static const value_string skinny_echoCancelTypes[] = {
613   {0    , "Media_EchoCancellation_Off"},
614   {1    , "Media_EchoCancellation_On"},
615   {0    , NULL}
616 }; 
617
618 static const value_string skinny_deviceUnregisterStatusTypes[] = {
619   {0   , "UnregisterOk"},
620   {1   , "UnregisterError"},
621   {2   , "UnregisterNAK"}, /* Unregister request is rejected for reaso n such as existence of a call */
622   {0   , NULL}
623 };
624
625 /* define hook flash detection mode */
626 static const value_string skinny_hookFlashDetectModes[] = {
627   {1   , "StationHookFlashOn"},
628   {2   , "StationHookFlashOff"},
629   {0   , NULL}
630 }; 
631
632 /* define station microphone modes; 
633  * Mic On - The speakerphone's microphone is turned on ONLY if the phone is in the "Speaker On (Off Hook)" 
634  * state (see above). 
635  * Mic Off - The microphone is turned off or, if it's not on, the command is ignored. 
636  */
637 static const value_string skinny_microphoneModes[] = {
638   {1   , "StationMicOn"},
639   {2   , "StationMicOff"}, 
640   {0   , NULL}
641 };
642
643 /* define the session request types */
644 static const value_string skinny_sessionTypes[] = {
645   {1   , "Chat"},
646   {2   , "Whiteboard"},
647   {4   , "ApplicationSharing"},
648   {8   , "FileTransfer"},
649   {10  , "Video"},
650   {0   , NULL}
651 };
652
653 static const value_string skinny_mediaEnunciationTypes[] = {
654   {1  , "None"},
655   {2  , "CallPark"},
656   {0  , NULL}
657 }; 
658
659 #define StationMaxDirnumSize 24         /* max size of calling or called party dirnum  */
660 #define StationMaxNameSize 40           /* max size of calling party's name  */
661 #define StationMaxDeviceNameSize 16     /* max size of station's IP name  */
662 #define StationMaxSpeedDials 10         /* max number of speed dial numbers allowed on a station */
663 #define StationMaxVersionSize 16        /* max chars in version string  */
664 #define StationMaxButtonTemplateSize 42 /* max button template size */ 
665 #define StationMaxDisplayTextSize 33    /* max text size in DisplayText message */
666 #define StationMaxPorts 10              /* max number of ports on one device */
667 #define StationDateTemplateSize 6       /* date template in the form M/D/Y, D/M/Y, ... */
668 #define StationMaxServerNameSize 48     /* max size of server name */
669 #define StationMaxServers 5             /* max servers */
670 #define StationMaxDeviceDirnums 1024    /* max dir numbers per SCM device */
671 #define StationMaxDirnums 64            /* max dir numbers per physical station (also used in db request msg); */
672 #define StationMaxSoftKeyLabelSize 16   /* max label size in the message */
673 #define StationMaxSoftKeyDefinition 32       /* max number of soft key definition in the message */
674 #define StationMaxSoftKeySetDefinition 16    /* max number of soft key set definition in the message */
675 #define StationMaxSoftKeyIndex 16            /* max number of soft key indices in a station soft key set */
676 #define StationMaxDisplayPromptStatusSize 32 /* max status text size in the display status message */
677 #define StationMaxDisplayNotifySize 32       /* max prompt text size in the display prompt message */
678
679 static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
680
681 /* Initialize the protocol and registered fields */
682 static int proto_skinny          = -1;
683 static int hf_skinny_data_length = -1;
684 static int hf_skinny_reserved    = -1;
685 static int hf_skinny_messageid   = -1;
686 static int hf_skinny_deviceName  = -1;
687 static int hf_skinny_stationUserId = -1;
688 static int hf_skinny_stationInstance = -1;
689 static int hf_skinny_deviceType = -1;
690 static int hf_skinny_maxStreams = -1;
691 static int hf_skinny_stationIpPort = -1;
692 static int hf_skinny_stationKeypadButton = -1;
693 static int hf_skinny_calledParty = -1;
694 static int hf_skinny_stimulus = -1;
695 static int hf_skinny_stimulusInstance = -1;
696 static int hf_skinny_lineNumber = -1;
697 static int hf_skinny_speedDialNumber = -1;
698 static int hf_skinny_capCount = -1;
699 static int hf_skinny_payloadCapability = -1;
700 static int hf_skinny_maxFramesPerPacket = -1;
701 static int hf_skinny_alarmSeverity = -1;
702 static int hf_skinny_alarmParam1 = -1;
703 static int hf_skinny_alarmParam2 = -1;
704 static int hf_skinny_receptionStatus = -1;
705 static int hf_skinny_passThruPartyID = -1;
706 static int hf_skinny_ORCStatus = -1;
707 static int hf_skinny_ipAddress = -1;
708 static int hf_skinny_portNumber = -1;
709 static int hf_skinny_statsProcessingType = -1;
710 static int hf_skinny_callIdentifier = -1;
711 static int hf_skinny_packetsSent = -1;
712 static int hf_skinny_octetsSent  = -1;
713 static int hf_skinny_packetsRecv = -1;
714 static int hf_skinny_octetsRecv  = -1;
715 static int hf_skinny_packetsLost = -1;
716 static int hf_skinny_latency     = -1;
717 static int hf_skinny_jitter      = -1;
718 static int hf_skinny_directoryNumber = -1;
719 static int hf_skinny_softKeyEvent = -1;
720 static int hf_skinny_lineInstance = -1;
721 static int hf_skinny_keepAliveInterval = -1;
722 static int hf_skinny_dateTemplate = -1;
723 static int hf_skinny_secondaryKeepAliveInterval = -1;
724 static int hf_skinny_buttonOffset = -1;
725 static int hf_skinny_buttonCount = -1;
726 static int hf_skinny_totalButtonCount = -1;
727 static int hf_skinny_buttonInstanceNumber = -1;
728 static int hf_skinny_buttonDefinition = -1;
729 static int hf_skinny_softKeyOffset = -1;
730 static int hf_skinny_softKeyCount = -1;
731 static int hf_skinny_totalSoftKeyCount = -1;
732 static int hf_skinny_softKeyLabel = -1;
733 static int hf_skinny_softKeySetOffset = -1;
734 static int hf_skinny_softKeySetCount = -1;
735 static int hf_skinny_totalSoftKeySetCount = -1;
736 static int hf_skinny_softKeyTemplateIndex = -1;
737 static int hf_skinny_softKeyInfoIndex = -1;
738 static int hf_skinny_softKeySetDescription = -1;
739 static int hf_skinny_softKeyMap = -1;
740 static int hf_skinny_softKey0 = -1;
741 static int hf_skinny_softKey1 = -1;
742 static int hf_skinny_softKey2 = -1;
743 static int hf_skinny_softKey3 = -1;
744 static int hf_skinny_softKey4 = -1;
745 static int hf_skinny_softKey5 = -1;
746 static int hf_skinny_softKey6 = -1;
747 static int hf_skinny_softKey7 = -1;
748 static int hf_skinny_softKey8 = -1;
749 static int hf_skinny_softKey9 = -1;
750 static int hf_skinny_softKey10 = -1;
751 static int hf_skinny_softKey11 = -1;
752 static int hf_skinny_softKey12 = -1;
753 static int hf_skinny_softKey13 = -1;
754 static int hf_skinny_softKey14 = -1;
755 static int hf_skinny_softKey15 = -1;
756 static int hf_skinny_lampMode = -1;
757 static int hf_skinny_messageTimeOutValue = -1;
758 static int hf_skinny_displayMessage = -1;
759 static int hf_skinny_lineDirNumber = -1;
760 static int hf_skinny_lineFullyQualifiedDisplayName = -1;
761 static int hf_skinny_speedDialDirNumber = -1;
762 static int hf_skinny_speedDialDisplayName = -1;
763 static int hf_skinny_dateYear = -1;
764 static int hf_skinny_dateMonth = -1;
765 static int hf_skinny_dayOfWeek = -1;
766 static int hf_skinny_dateDay = -1;
767 static int hf_skinny_dateHour = -1;
768 static int hf_skinny_dateMinute = -1;
769 static int hf_skinny_dateSeconds = -1;
770 static int hf_skinny_dateMilliseconds = -1;
771 static int hf_skinny_timeStamp = -1;
772 static int hf_skinny_callState = -1;
773 static int hf_skinny_deviceTone = -1;
774 static int hf_skinny_callingPartyName = -1;
775 static int hf_skinny_callingParty = -1;
776 static int hf_skinny_calledPartyName = -1;
777 static int hf_skinny_callType = -1;
778 static int hf_skinny_originalCalledPartyName = -1;
779 static int hf_skinny_originalCalledParty = -1;
780 static int hf_skinny_ringType = -1;
781 static int hf_skinny_speakerMode = -1;
782 static int hf_skinny_remoteIpAddr = -1;
783 static int hf_skinny_remotePortNumber = -1;
784 static int hf_skinny_millisecondPacketSize = -1;
785 static int hf_skinny_precedenceValue = -1;
786 static int hf_skinny_silenceSuppression = -1;
787 static int hf_skinny_g723BitRate = -1;
788 static int hf_skinny_conferenceID = -1;
789 static int hf_skinny_deviceResetType = -1;
790 static int hf_skinny_echoCancelType = -1;
791 static int hf_skinny_deviceUnregisterStatus = -1;
792 static int hf_skinny_hookFlashDetectMode = -1;
793 static int hf_skinny_detectInterval = -1;
794 static int hf_skinny_microphoneMode = -1;
795 static int hf_skinny_unknown = -1;
796 static int hf_skinny_activeForward = -1;
797 static int hf_skinny_forwardAllActive = -1;
798 static int hf_skinny_forwardBusyActive = -1;
799 static int hf_skinny_forwardNoAnswerActive = -1;
800 static int hf_skinny_forwardNumber = -1;
801 static int hf_skinny_serverName = -1;
802 static int hf_skinny_numberLines = -1;
803 static int hf_skinny_numberSpeedDials = -1;
804 static int hf_skinny_userName = -1;
805 static int hf_skinny_sessionType = -1;
806 static int hf_skinny_version = -1;
807 static int hf_skinny_mediaEnunciationType = -1;
808 static int hf_skinny_serverIdentifier = -1;
809 static int hf_skinny_serverListenPort = -1;
810 static int hf_skinny_serverIpAddress = -1;
811 static int hf_skinny_multicastIpAddress = -1;
812 static int hf_skinny_multicastPort = -1;
813 static int hf_skinny_tokenRejWaitTime = -1;
814
815
816
817 /* Initialize the subtree pointers */
818 static gint ett_skinny          = -1;
819 static gint ett_skinny_softKeyMap = -1;
820
821 /* desegmentation of SCCP */
822 static gboolean skinny_desegment = TRUE;
823
824 static dissector_handle_t data_handle;
825
826 /* Dissect a single SCCP PDU */
827 static void dissect_skinny_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
828 {
829   int offset = 0;
830
831   /* Header fields */
832   guint32 hdr_data_length;
833   guint32 hdr_reserved;
834   guint32 data_messageid;
835   gchar   *messageid_str;
836   /*  guint32 data_size; */
837
838   guint32 unknownLong = 0;
839
840   guint i = 0;
841   int j = 0;
842
843   guint32 capCount;
844   guint32 softKeyCount;
845   guint32 softKeySetCount;
846   guint16 validKeyMask;
847   
848   /* Set up structures we will need to add the protocol subtree and manage it */
849   proto_item *ti;
850   proto_tree *skinny_tree = NULL;
851   
852   proto_item *skm = NULL;
853   proto_item *skm_tree = NULL;
854
855   hdr_data_length = tvb_get_letohl(tvb, offset);
856   hdr_reserved    = tvb_get_letohl(tvb, offset+4);
857   data_messageid  = tvb_get_letohl(tvb, offset+8);
858
859   /* In the interest of speed, if "tree" is NULL, don't do any work not
860    * necessary to generate protocol tree items. */
861   if (tree) {
862     ti = proto_tree_add_item(tree, proto_skinny, tvb, offset, hdr_data_length+8, FALSE); 
863     skinny_tree = proto_item_add_subtree(ti, ett_skinny);
864     proto_tree_add_uint(skinny_tree, hf_skinny_data_length, tvb, offset, 4, hdr_data_length);  
865     proto_tree_add_uint(skinny_tree, hf_skinny_reserved, tvb, offset+4, 4, hdr_reserved);
866   }
867
868   messageid_str = val_to_str(data_messageid, message_id, "0x%08X (Unknown)");
869
870   if (check_col(pinfo->cinfo, COL_INFO)) {
871     col_add_str(pinfo->cinfo, COL_INFO, messageid_str);
872   }
873
874   if (tree) {
875     proto_tree_add_uint(skinny_tree, hf_skinny_messageid, tvb,offset+8, 4, data_messageid );
876   }
877
878   if (tree) {
879     switch(data_messageid) {
880
881     /* cases that do not need to be decoded */
882     case 0x0 :    /* keepAlive */
883       break;
884
885     case 0x6 :    /* offHook */
886       break;
887
888     case 0x7 :    /* onHook    */
889       break;
890
891     case 0x8 :    /* hookFlash */
892       break;
893       
894     case 0xc :    /* configStateReqMessage */
895       break;
896       
897     case 0xd :    /* timeDateReqMessage */
898       break;
899
900     case 0xe :    /* buttoneTemplateReqMessage */
901       break;
902
903     case 0xf :    /* stationVersionReqMessage */
904       break;
905       
906     case 0x12 :   /* stationServerReqMessage */
907       break;
908       
909     case 0x25 :   /* softKeySetReqMessage */
910       break;
911
912     case 0x27 :   /* unregisterMessage */
913       break;
914
915     case 0x28 :   /* softKeyTemplateRequest */
916       break;
917
918     case 0x83 :   /* stopTone */
919       break;
920
921     case 0x9a :   /* clearDisplay */
922       break;
923
924     case 0x9b :   /* capabilitiesReqMessage */
925       break;
926
927     case 0x100 :    /* keepAliveAck */
928       break;
929
930     case 0x117 :  /* deactivateCallPlane */
931       break;
932
933     case 0x11a :  /* registerTokenAck */
934       break;
935
936     /*
937      ** cases that need decode
938      **
939      */
940
941     case 0x1 :   /* register message */
942       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, StationMaxDeviceNameSize, TRUE);
943       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, offset+28, 4, TRUE);
944       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, offset+32, 4, TRUE);
945       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+36, 4, TRUE);
946       proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, offset+40, 4, TRUE);
947       proto_tree_add_item(skinny_tree, hf_skinny_maxStreams, tvb, offset+44, 4, TRUE);
948       break;
949
950     case 0x2 :  /* ipPortMessage */
951       proto_tree_add_item(skinny_tree, hf_skinny_stationIpPort, tvb, offset+12, 2, FALSE);
952       break;
953
954     case 0x3 :  /* keyPadButtonMessage */
955       proto_tree_add_item(skinny_tree, hf_skinny_stationKeypadButton, tvb, offset+12, 4, TRUE);
956       break;
957
958     case 0x4 :  /* stationEnblocCallMessage -- This decode NOT verified*/
959       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12, StationMaxDirnumSize, TRUE);
960       break;
961       
962     case 0x5 : /* stationStimulusMessage */
963       proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
964       proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
965       break;
966
967     case 0x9  : /* stationForwardStatReqMessage */
968       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
969       break;
970       
971     case 0xa :  /* speedDialStatReqMessage */
972       proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
973       break;
974
975     case 0xb :  /* LineStatReqMessage */
976       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
977       break;
978
979     case 0x10 :  /* capabilitiesResMessage  - VERIFIED AS IS*/
980       /* FIXME -- we are only going to decode the first 7 protocol fields for now cuz that's all it sent me
981        * on the phone i was working with. I should probably skip the struct decode and use a more piece
982        * type method using the capCount definition to control the decode loop
983        *
984        * basically changing StationMaxCapabilities definition
985        *
986        */       
987       capCount = tvb_get_letohl(tvb, offset+12);
988       proto_tree_add_uint(skinny_tree, hf_skinny_capCount, tvb, offset+12, 4, capCount);
989       for (i = 0; i < capCount; i++) {
990         proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+(i*16)+16, 4, TRUE);
991         proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+(i*16)+20, 2, TRUE);
992         /* FIXME -- decode the union under here as required, is always 0 on my equipment */
993       }
994       break;
995
996     case 0x11 : /* mediaPortList */
997       break;
998
999     case 0x20 :   /* stationAlarmMessage */
1000       proto_tree_add_item(skinny_tree, hf_skinny_alarmSeverity, tvb, offset+12, 4, TRUE);
1001       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, 80, TRUE);
1002       proto_tree_add_item(skinny_tree, hf_skinny_alarmParam1, tvb, offset+96, 4, TRUE);
1003       proto_tree_add_item(skinny_tree, hf_skinny_alarmParam2, tvb, offset+100, 4, TRUE);
1004       break;
1005
1006     case 0x21 : /* stationMulticastMediaReceptionAck - This decode NOT verified*/
1007       proto_tree_add_item(skinny_tree, hf_skinny_receptionStatus, tvb, offset+12, 4, TRUE);
1008       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1009       break;
1010       
1011     case 0x22 : /* stationOpenReceiveChannelAck */
1012       proto_tree_add_item(skinny_tree, hf_skinny_ORCStatus, tvb, offset+12, 4, TRUE);
1013       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+16, 4, TRUE);
1014       proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+20, 4, TRUE);
1015       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+24, 4, TRUE);
1016       break;    
1017
1018     case 0x23    :  /* stationConnectionStatisticsRes */
1019       proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, offset+12, StationMaxDirnumSize, TRUE);
1020       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+36, 4, TRUE);
1021       proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, offset+40, 4, TRUE);
1022       proto_tree_add_item(skinny_tree, hf_skinny_packetsSent, tvb, offset+44, 4, TRUE);
1023       proto_tree_add_item(skinny_tree, hf_skinny_octetsSent, tvb, offset+48, 4, TRUE);
1024       proto_tree_add_item(skinny_tree, hf_skinny_packetsRecv, tvb, offset+52, 4, TRUE);
1025       proto_tree_add_item(skinny_tree, hf_skinny_octetsRecv, tvb, offset+56, 4, TRUE);
1026       proto_tree_add_item(skinny_tree, hf_skinny_packetsLost, tvb, offset+60, 4, TRUE);
1027       proto_tree_add_item(skinny_tree, hf_skinny_jitter, tvb, offset+64, 4, TRUE);
1028       proto_tree_add_item(skinny_tree, hf_skinny_latency, tvb, offset+68, 4, TRUE);
1029       break;
1030
1031     case 0x24 : /* offHookWithCgpn */
1032       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12,StationMaxDirnumSize, TRUE); 
1033       break;
1034
1035     case 0x26 :  /* softKeyEventMessage */
1036       proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+12, 4, TRUE);
1037       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
1038       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
1039       break;
1040
1041     case 0x29 : /* registerTokenREq */
1042       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, 4, TRUE);
1043       i = offset+12+StationMaxDeviceNameSize;
1044       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
1045       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i+4, 4, TRUE);
1046       proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, i+8, 4, TRUE);
1047       proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, i+12, 4, TRUE);
1048       break;
1049
1050       /*
1051        *
1052        * message not in the spec
1053        *
1054        */
1055     case 0x2b :  /* unknownClientMessage1 */
1056       break;
1057
1058     case 0x2d :  /* unknownClientMessage2 */
1059       break;
1060
1061       /* 
1062        *
1063        *  Call manager -> client messages start here(ish)
1064        *
1065        */
1066     case 0x81 :  /* registerAck */
1067       proto_tree_add_item(skinny_tree, hf_skinny_keepAliveInterval, tvb, offset+12, 4, TRUE);
1068       proto_tree_add_item(skinny_tree, hf_skinny_dateTemplate, tvb, offset+16, StationDateTemplateSize, TRUE);
1069       proto_tree_add_item(skinny_tree, hf_skinny_secondaryKeepAliveInterval, tvb, offset+24, 4, TRUE);
1070       break;
1071
1072     case 0x82 :  /* startTone */
1073       proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, offset+12, 4, TRUE);
1074       break;
1075
1076     case 0x85 : /* setRingerMessage */
1077       proto_tree_add_item(skinny_tree, hf_skinny_ringType, tvb, offset+12, 4, TRUE);
1078       break;
1079         
1080     case 0x86 : /* setLampMessage */
1081       proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
1082       proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
1083       proto_tree_add_item(skinny_tree, hf_skinny_lampMode, tvb, offset+20, 4, TRUE);
1084       break;
1085
1086     case 0x87 : /* stationHookFlashDetectMode */
1087       proto_tree_add_item(skinny_tree, hf_skinny_hookFlashDetectMode, tvb, offset+12, 4, TRUE);
1088       proto_tree_add_item(skinny_tree, hf_skinny_detectInterval, tvb, offset+16, 4, TRUE);
1089       break;
1090
1091     case 0x88 : /* setSpeakerMode */
1092       
1093       proto_tree_add_item(skinny_tree, hf_skinny_speakerMode, tvb, offset+12, 4, TRUE);
1094       break;
1095
1096     case 0x89 : /* setMicroMode */
1097       proto_tree_add_item(skinny_tree, hf_skinny_microphoneMode, tvb, offset+12, 4, TRUE);
1098       break;
1099
1100     case 0x8a : /* startMediaTransmistion */     
1101       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID,          tvb, offset+12, 4, TRUE);
1102       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID,       tvb, offset+16, 4, TRUE);
1103       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,          tvb, offset+20, 4, TRUE);
1104       proto_tree_add_item(skinny_tree, hf_skinny_remotePortNumber,      tvb, offset+24, 4, TRUE);
1105       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1106       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability,     tvb, offset+32, 4, TRUE);
1107       proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue,       tvb, offset+36, 4, TRUE);
1108       proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression,    tvb, offset+40, 4, TRUE);
1109       proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket,    tvb, offset+44, 2, TRUE);
1110       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate,           tvb, offset+48, 4, TRUE);
1111       break;
1112
1113     case 0x8b :  /* stopMediaTransmission */
1114      
1115       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);      
1116       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1117       break;
1118
1119     case 0x8c : /* startMediaReception */
1120       break;
1121
1122     case 0x8d : /* stopMediaReception */
1123       break;
1124
1125     case 0x8e : /* reservered */
1126       break;
1127
1128     case 0x8f : /* callInfo */
1129       i = offset+12;
1130       proto_tree_add_item(skinny_tree, hf_skinny_callingPartyName, tvb, i, StationMaxNameSize, TRUE);
1131       i += StationMaxNameSize;
1132       proto_tree_add_item(skinny_tree, hf_skinny_callingParty, tvb, i, StationMaxDirnumSize, TRUE);
1133       i += StationMaxDirnumSize;
1134       proto_tree_add_item(skinny_tree, hf_skinny_calledPartyName, tvb, i, StationMaxNameSize, TRUE);
1135       i += StationMaxNameSize;
1136       proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, i, StationMaxDirnumSize, TRUE);
1137       i += StationMaxDirnumSize;
1138       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, i, 4, TRUE);
1139       i += 4;
1140       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
1141       i += 4;
1142       proto_tree_add_item(skinny_tree, hf_skinny_callType, tvb, i, 4, TRUE);
1143       i += 4;
1144       proto_tree_add_item(skinny_tree, hf_skinny_originalCalledPartyName, tvb, i, StationMaxNameSize, TRUE);
1145       i += StationMaxNameSize;
1146       proto_tree_add_item(skinny_tree, hf_skinny_originalCalledParty, tvb, i, StationMaxDirnumSize, TRUE);
1147       break;
1148
1149     case 0x90 : /* forwardStat */
1150       proto_tree_add_item(skinny_tree, hf_skinny_activeForward, tvb, offset+12, 4, TRUE);
1151       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+16, 4, TRUE);
1152       proto_tree_add_item(skinny_tree, hf_skinny_forwardAllActive, tvb, offset+20, 4, TRUE);
1153       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, offset+24, StationMaxDirnumSize, TRUE);
1154       i = offset+24+StationMaxDirnumSize;
1155       proto_tree_add_item(skinny_tree, hf_skinny_forwardBusyActive, tvb, i, 4, TRUE);
1156       i += 4;
1157       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
1158       i += StationMaxDirnumSize;
1159       proto_tree_add_item(skinny_tree, hf_skinny_forwardNoAnswerActive, tvb, i, 4, TRUE);
1160       i += 4;
1161       proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
1162       break;
1163
1164     case 0x91 : /* speedDialStatMessage */
1165       proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
1166       proto_tree_add_item(skinny_tree, hf_skinny_speedDialDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
1167       proto_tree_add_item(skinny_tree, hf_skinny_speedDialDisplayName, tvb, offset+40, StationMaxNameSize, TRUE);
1168       break;
1169
1170     case 0x92 : /* lineStatMessage */
1171       proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
1172       proto_tree_add_item(skinny_tree, hf_skinny_lineDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
1173       proto_tree_add_item(skinny_tree, hf_skinny_lineFullyQualifiedDisplayName, tvb, offset+16+StationMaxDirnumSize, StationMaxNameSize, TRUE);
1174       break;
1175
1176     case 0x93 : /* configStat */
1177       proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, 4, TRUE);
1178       i = offset+12+StationMaxDeviceNameSize;
1179       proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
1180       i += 4;
1181       proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i, 4, TRUE);
1182       i += 4;
1183       proto_tree_add_item(skinny_tree, hf_skinny_userName, tvb, i, StationMaxNameSize, TRUE);
1184       i += StationMaxNameSize;
1185       proto_tree_add_item(skinny_tree, hf_skinny_serverName, tvb, i, StationMaxNameSize, TRUE);
1186       i += StationMaxNameSize;
1187       proto_tree_add_item(skinny_tree, hf_skinny_numberLines, tvb, i, 4, TRUE);
1188       proto_tree_add_item(skinny_tree, hf_skinny_numberSpeedDials, tvb, i+4, 4, TRUE);
1189       break;
1190
1191     case 0x94 : /* stationDefineTimeDate */
1192       proto_tree_add_item(skinny_tree, hf_skinny_dateYear,   tvb, offset+12, 4, TRUE);
1193       proto_tree_add_item(skinny_tree, hf_skinny_dateMonth,  tvb, offset+16, 4, TRUE);
1194       proto_tree_add_item(skinny_tree, hf_skinny_dayOfWeek,  tvb, offset+20, 4, TRUE);
1195       proto_tree_add_item(skinny_tree, hf_skinny_dateDay,    tvb, offset+24, 4, TRUE);
1196       proto_tree_add_item(skinny_tree, hf_skinny_dateHour,   tvb, offset+28, 4, TRUE);
1197       proto_tree_add_item(skinny_tree, hf_skinny_dateMinute, tvb, offset+32, 4, TRUE);
1198       proto_tree_add_item(skinny_tree, hf_skinny_dateSeconds,tvb, offset+36, 4, TRUE);
1199       proto_tree_add_item(skinny_tree, hf_skinny_dateMilliseconds,tvb, offset+40, 4, TRUE);
1200       proto_tree_add_item(skinny_tree, hf_skinny_timeStamp, tvb, offset+44, 4, TRUE);
1201       break;
1202
1203     case 0x95 : /* startSessionTransmission */
1204       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,  tvb, offset+12, 4, TRUE);
1205       proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
1206       break;
1207
1208     case 0x96 : /* stopSessionTransmission */
1209       proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr,  tvb, offset+12, 4, TRUE);
1210       proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
1211       break;
1212
1213     case 0x97 :  /* buttonTemplateMessage  */
1214       /*
1215        * FIXME
1216        * This decode prints out oogly subtree maybe? or something besides the VALS...
1217        * note to self: uint8 != 4 kk thx info ^_^
1218        *
1219        */
1220       proto_tree_add_item(skinny_tree, hf_skinny_buttonOffset, tvb, offset+12, 4, TRUE);
1221       proto_tree_add_item(skinny_tree, hf_skinny_buttonCount,  tvb, offset+16, 4, TRUE);
1222       proto_tree_add_item(skinny_tree, hf_skinny_totalButtonCount, tvb, offset+20, 4, TRUE);
1223       for (i = 0; i < StationMaxButtonTemplateSize; i++) {
1224         proto_tree_add_item(skinny_tree, hf_skinny_buttonInstanceNumber, tvb, offset+(i*2)+24, 1, TRUE);
1225         proto_tree_add_item(skinny_tree, hf_skinny_buttonDefinition, tvb, offset+(i*2)+25, 1, TRUE);
1226       }
1227       break;
1228
1229     case 0x98 : /* version */
1230       proto_tree_add_item(skinny_tree, hf_skinny_version, tvb, offset+12, StationMaxVersionSize, TRUE);
1231       break;
1232
1233     case 0x99 :  /* displayTextMessage */
1234       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);           
1235       break;
1236
1237     case 0x9c : /* enunciatorCommand */
1238       proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, offset+12, 4, TRUE);
1239       for (i = 0; i < StationMaxDirnumSize; i++) {
1240         proto_tree_add_item(skinny_tree, hf_skinny_unknown, tvb, offset+16+(i*4), 4, TRUE);
1241       }
1242       i = offset+16+StationMaxDirnumSize;
1243       proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, i, 4, TRUE);
1244       break;
1245
1246     case 0x9d : /* stationRegisterReject */
1247       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);
1248       break;
1249       
1250     case 0x9e : /* serverRes */
1251       for (i = 0; i < StationMaxServers; i++) {
1252         proto_tree_add_item(skinny_tree, hf_skinny_serverIdentifier, tvb, offset+12+(i*StationMaxServers), StationMaxServers, TRUE);
1253       }
1254       j = offset+12+(i*StationMaxServers);
1255       for (i = 0; i < StationMaxServers; i++) {
1256         proto_tree_add_item(skinny_tree, hf_skinny_serverListenPort, tvb, j+(i*4), 4,  TRUE);
1257       }
1258       j = j+(i*4);
1259       for (i = 0; i < StationMaxServers; i++) {
1260         proto_tree_add_item(skinny_tree, hf_skinny_serverIpAddress, tvb, j+(i*4), 4, TRUE);
1261       }
1262       break;
1263
1264     case 0x9f :   /* reset */
1265       proto_tree_add_item(skinny_tree, hf_skinny_deviceResetType, tvb, offset+12, 4, TRUE);
1266       break;
1267
1268     case 0x101 : /* startMulticastMediaReception*/
1269       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1270       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1271       proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
1272       proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
1273       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1274       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
1275       proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType, tvb, offset+36, 4, TRUE);
1276       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+40, 4, TRUE);
1277       break;
1278
1279     case 0x102 : /* startMulticateMediaTermination*/
1280       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1281       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1282       proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
1283       proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
1284       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
1285       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
1286       proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue, tvb, offset+36, 4, TRUE);
1287       proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression, tvb, offset+40, 4, TRUE);
1288       proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+44, 2, TRUE);
1289       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+48, 4, TRUE);
1290       break;
1291
1292     case 0x103 : /* stopMulticastMediaReception*/
1293       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1294       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1295       break;
1296
1297     case 0x104 : /* stopMulticastMediaTermination*/
1298       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1299       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1300       break;
1301
1302     case 0x105 : /* open receive channel */
1303       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID,            tvb, offset+12, 4, TRUE);
1304       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID,         tvb, offset+16, 4, TRUE);
1305       proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize,   tvb, offset+20, 4, TRUE);
1306       proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability,       tvb, offset+24, 4, TRUE);
1307       proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType,          tvb, offset+28, 4, TRUE);
1308       proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate,             tvb, offset+32, 4, TRUE);
1309       break;
1310
1311     case 0x106 :  /* closeReceiveChannel */
1312       proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
1313       proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
1314       break;
1315
1316     case 0x107 :  /* connectionStatisticsReq */
1317
1318       i = 12;
1319       proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, i, StationMaxDirnumSize, TRUE);
1320       i = 12 + StationMaxDirnumSize;
1321       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
1322       i = i+4;
1323       proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, i, 4, TRUE);
1324       break;
1325
1326     case 0x108 :   /* softkeyTemplateResMessage */
1327       proto_tree_add_item(skinny_tree, hf_skinny_softKeyOffset, tvb, offset+12, 4, TRUE);
1328       softKeyCount = tvb_get_letohl(tvb, offset+16);
1329       proto_tree_add_uint(skinny_tree, hf_skinny_softKeyCount, tvb, offset+16, 4, softKeyCount);
1330       proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeyCount, tvb, offset+20, 4, TRUE);
1331       for (i = 0; ((i < StationMaxSoftKeyDefinition) && (i < softKeyCount)); i++){
1332         proto_tree_add_item(skinny_tree, hf_skinny_softKeyLabel, tvb, offset+(i*20)+24, StationMaxSoftKeyLabelSize, TRUE);
1333         proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+(i*20)+40, 4, TRUE);
1334       }
1335       /* there is more data here, but it doesn't make a whole lot of sense, I imagine
1336        * it's just some not zero'd out stuff in the packet or... 
1337        */
1338       break;
1339
1340     case 0x109 : /* softkeysetres */
1341       proto_tree_add_item(skinny_tree, hf_skinny_softKeySetOffset, tvb, offset+12, 4, TRUE);
1342       softKeySetCount = tvb_get_letohl(tvb, offset+16);
1343       proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetCount, tvb, offset+16, 4, softKeySetCount);
1344       proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeySetCount, tvb, offset+20, 4, TRUE);
1345       for (i = 0; ((i < StationMaxSoftKeySetDefinition) && (i < softKeySetCount)); i++) {
1346         proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+24+(i*48) , 1, i);
1347         for (j = 0; j < StationMaxSoftKeyIndex; j++) {
1348           proto_tree_add_item(skinny_tree, hf_skinny_softKeyTemplateIndex, tvb, offset+24+(i*48)+j, 1, TRUE);
1349         }
1350         for (j = 0; j < StationMaxSoftKeyIndex; j++) {
1351           proto_tree_add_item(skinny_tree, hf_skinny_softKeyInfoIndex, tvb, offset+24+(i*48)+StationMaxSoftKeyIndex+(j*2), 2, TRUE);
1352         }
1353       }
1354       break;
1355       
1356     case 0x110 : /* selectSoftKeys */
1357       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1358       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1359       proto_tree_add_item(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+20, 4, TRUE);
1360       validKeyMask = tvb_get_letohs(tvb, offset + 24);
1361       skm = proto_tree_add_uint(skinny_tree, hf_skinny_softKeyMap, tvb, offset + 24, 1, validKeyMask);
1362       skm_tree = proto_item_add_subtree(skm, ett_skinny_softKeyMap);
1363       proto_tree_add_boolean(skm_tree, hf_skinny_softKey0,  tvb, offset + 24, 1, validKeyMask);
1364       proto_tree_add_boolean(skm_tree, hf_skinny_softKey1,  tvb, offset + 24, 1, validKeyMask);
1365       proto_tree_add_boolean(skm_tree, hf_skinny_softKey2,  tvb, offset + 24, 1, validKeyMask);
1366       proto_tree_add_boolean(skm_tree, hf_skinny_softKey3,  tvb, offset + 24, 1, validKeyMask);
1367       proto_tree_add_boolean(skm_tree, hf_skinny_softKey4,  tvb, offset + 24, 1, validKeyMask);
1368       proto_tree_add_boolean(skm_tree, hf_skinny_softKey5,  tvb, offset + 24, 1, validKeyMask);
1369       proto_tree_add_boolean(skm_tree, hf_skinny_softKey6,  tvb, offset + 24, 1, validKeyMask);
1370       proto_tree_add_boolean(skm_tree, hf_skinny_softKey7,  tvb, offset + 24, 1, validKeyMask);
1371       proto_tree_add_boolean(skm_tree, hf_skinny_softKey8,  tvb, offset + 24, 1, validKeyMask);
1372       proto_tree_add_boolean(skm_tree, hf_skinny_softKey9,  tvb, offset + 24, 1, validKeyMask);
1373       proto_tree_add_boolean(skm_tree, hf_skinny_softKey10, tvb, offset + 24, 1, validKeyMask);
1374       proto_tree_add_boolean(skm_tree, hf_skinny_softKey11, tvb, offset + 24, 1, validKeyMask);
1375       proto_tree_add_boolean(skm_tree, hf_skinny_softKey12, tvb, offset + 24, 1, validKeyMask);
1376       proto_tree_add_boolean(skm_tree, hf_skinny_softKey13, tvb, offset + 24, 1, validKeyMask);
1377       proto_tree_add_boolean(skm_tree, hf_skinny_softKey14, tvb, offset + 24, 1, validKeyMask);
1378       proto_tree_add_boolean(skm_tree, hf_skinny_softKey15, tvb, offset + 24, 1, validKeyMask);
1379       break;
1380       
1381     case 0x111 : /* callState */
1382       proto_tree_add_item(skinny_tree, hf_skinny_callState, tvb, offset+12, 4, TRUE);
1383       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
1384       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
1385       break;
1386       
1387     case 0x112 : /* displayPromptStatus */
1388       proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
1389       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayPromptStatusSize, TRUE);
1390       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+48, 4, TRUE);
1391       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+52, 4, TRUE);
1392       break;
1393       
1394     case 0x113: /* clearPrompt */
1395       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance  , tvb, offset+12, 4, TRUE);
1396       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1397       break;
1398       
1399     case 0x114 : /* displayNotify */
1400       proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
1401       proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayNotifySize , TRUE);
1402       break;
1403       
1404     case 0x115 : /* clearNotify */
1405       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1406       break;
1407
1408     case 0x116 : /* activateCallPlane */
1409       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1410       break;
1411
1412     case 0x118 :    /* unregisterAckMessage */
1413       proto_tree_add_item(skinny_tree, hf_skinny_deviceUnregisterStatus, tvb, offset+12, 4, TRUE);
1414       break;
1415
1416     case 0x119 : /* backSpaceReq */
1417       proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
1418       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
1419       break;
1420
1421     case 0x11B : /* registerTokenReject */
1422       proto_tree_add_item(skinny_tree, hf_skinny_tokenRejWaitTime, tvb, offset+12, 4, TRUE);
1423       break;
1424
1425     case 0x11D : /* new message */
1426       unknownLong       = tvb_get_letohl(tvb, offset+36);
1427       proto_tree_add_uint(skinny_tree, hf_skinny_unknown, tvb, offset+36, 4, unknownLong);
1428       proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+40, 4, TRUE);
1429       break;
1430       
1431
1432
1433     default:
1434       break;
1435     }
1436   }
1437 }
1438
1439 /* Code to actually dissect the packets */
1440 static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1441 {
1442   /* The general structure of a packet: {IP-Header|TCP-Header|n*SKINNY}
1443    * SKINNY-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
1444    */
1445   
1446   volatile int offset = 0;
1447   int length_remaining;
1448   int length;
1449   tvbuff_t *next_tvb;
1450
1451   /* Header fields */
1452   volatile guint32 hdr_data_length;
1453   guint32 hdr_reserved;
1454
1455   /* check, if this is really an SKINNY packet, they start with a length + 0 */
1456   
1457   /* get relevant header information */
1458   hdr_data_length = tvb_get_letohl(tvb, 0);
1459   hdr_reserved    = tvb_get_letohl(tvb, 4);
1460
1461   /*  data_size       = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
1462   
1463   /* hdr_data_length > 1024 is just a heuristic. Better values/checks welcome */
1464   if (hdr_data_length < 4 || hdr_data_length > 1024 || hdr_reserved != 0) {
1465     /* Not an SKINNY packet, just happened to use the same port */
1466     call_dissector(data_handle,tvb, pinfo, tree);
1467     return;
1468   }
1469   
1470   /* Make entries in Protocol column and Info column on summary display */
1471   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1472     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY");
1473   }
1474   
1475   if (check_col(pinfo->cinfo, COL_INFO)) {
1476     col_set_str(pinfo->cinfo, COL_INFO, "Skinny Client Control Protocol");
1477   }
1478   
1479   while (tvb_reported_length_remaining(tvb, offset) != 0) {
1480     length_remaining = tvb_length_remaining(tvb, offset);
1481
1482     /*
1483      * Can we do reassembly?
1484      */
1485     if (skinny_desegment && pinfo->can_desegment) {
1486       /*
1487        * Yes - is the length field in the SCCP header split across
1488        * segment boundaries?
1489        */
1490       if (length_remaining < 4) {
1491         /*
1492          * Yes.  Tell the TCP dissector where the data for this message
1493          * starts in the data it handed us, and how many more bytes we
1494          * need, and return.
1495          */
1496         pinfo->desegment_offset = offset;
1497         pinfo->desegment_len = 4 - length_remaining;
1498         return;
1499       }
1500     }
1501
1502     /*
1503      * Get the length of the SCCP packet.
1504      */
1505     hdr_data_length = tvb_get_letohl(tvb, offset);
1506
1507     /*
1508      * Can we do reassembly?
1509      */
1510     if (skinny_desegment && pinfo->can_desegment) {
1511       /*
1512        * Yes - is the SCCP packet split across segment boundaries?
1513        */
1514       if ((guint32)length_remaining < hdr_data_length + 8) {
1515         /*
1516          * Yes.  Tell the TCP dissector where the data for this message
1517          * starts in the data it handed us, and how many more bytes we
1518          * need, and return.
1519          */
1520         pinfo->desegment_offset = offset;
1521         pinfo->desegment_len = (hdr_data_length + 8) - length_remaining;
1522         return;
1523       }
1524     }
1525
1526     /*
1527      * Construct a tvbuff containing the amount of the payload we have
1528      * available.  Make its reported length the amount of data in the
1529      * SCCP packet.
1530      *
1531      * XXX - if reassembly isn't enabled. the subdissector will throw a
1532      * BoundsError exception, rather than a ReportedBoundsError exception.
1533      * We really want a tvbuff where the length is "length", the reported
1534      * length is "hdr_data_length + 8", and the "if the snapshot length
1535      * were infinite" length is the minimum of the reported length of
1536      * the tvbuff handed to us and "hdr_data_length + 8", with a new type
1537      * of exception thrown if the offset is within the reported length but
1538      * beyond that third length, with that exception getting the
1539      * "Unreassembled Packet" error.
1540      */
1541     length = length_remaining;
1542     if ((guint32)length > hdr_data_length + 8)
1543       length = hdr_data_length + 8;
1544     next_tvb = tvb_new_subset(tvb, offset, length, hdr_data_length + 8);
1545
1546     /*
1547      * Dissect the SCCP packet.
1548      *
1549      * Catch the ReportedBoundsError exception; if this particular message
1550      * happens to get a ReportedBoundsError exception, that doesn't mean
1551      * that we should stop dissecting SCCP messages within this frame or
1552      * chunk of reassembled data.
1553      *
1554      * If it gets a BoundsError, we can stop, as there's nothing more to
1555      * see, so we just re-throw it.
1556      */
1557     TRY {
1558       dissect_skinny_pdu(next_tvb, pinfo, tree);
1559     }
1560     CATCH(BoundsError) {
1561       RETHROW;
1562     }
1563     CATCH(ReportedBoundsError) {
1564       show_reported_bounds_error(tvb, pinfo, tree);
1565     }
1566     ENDTRY;
1567
1568     /*
1569      * Skip the SCCP header and the payload.
1570      */
1571     offset += hdr_data_length + 8;
1572   }
1573 }
1574
1575 /* Register the protocol with Ethereal */
1576 void 
1577 proto_register_skinny(void)
1578 {                 
1579   
1580   /* Setup list of header fields */
1581   static hf_register_info hf[] = {
1582     { &hf_skinny_data_length,
1583       { "Data Length", "skinny.data_length",
1584         FT_UINT32, BASE_DEC, NULL, 0x0,
1585         "Number of bytes in the data portion.",
1586         HFILL }
1587     },
1588     { &hf_skinny_reserved,
1589       { "Reserved", "skinny.reserved",
1590         FT_UINT32, BASE_HEX, NULL, 0x0,
1591         "Reserved for future(?) use.",
1592         HFILL }
1593     },
1594     /* FIXME: Enable use of message name ???  */
1595     { &hf_skinny_messageid,
1596       { "Message ID", "skinny.messageid",
1597         FT_UINT32, BASE_HEX, VALS(message_id), 0x0,
1598         "The function requested/done with this message.",
1599         HFILL }
1600     },
1601
1602     { &hf_skinny_deviceName,
1603       { "DeviceName", "skinny.deviceName",
1604         FT_STRING, BASE_NONE, NULL, 0x0,
1605         "The device name of the phone.",
1606         HFILL }
1607     },
1608
1609     { &hf_skinny_stationUserId,
1610       { "StationUserId", "skinny.stationUserId",
1611         FT_UINT32, BASE_DEC, NULL, 0x0,
1612         "The station user id.",
1613         HFILL }
1614     },
1615
1616     { &hf_skinny_stationInstance,
1617       { "StationInstance", "skinny.stationInstance",
1618         FT_UINT32, BASE_DEC, NULL, 0x0,
1619         "The stations instance.",
1620         HFILL }
1621     },
1622
1623     { &hf_skinny_deviceType,
1624       { "DeviceType", "skinny.deviceType",
1625         FT_UINT32, BASE_DEC, VALS(deviceTypes), 0x0,
1626         "DeviceType of the station.",
1627         HFILL }
1628     },
1629
1630     { &hf_skinny_maxStreams,
1631       { "MaxStreams", "skinny.maxStreams",
1632         FT_UINT32, BASE_DEC, NULL, 0x0,
1633         "32 bit unsigned integer indicating the maximum number of simultansous RTP duplex streams that the client can handle.",
1634         HFILL }
1635     },
1636
1637     { &hf_skinny_stationIpPort,
1638       { "StationIpPort", "skinny.stationIpPort",
1639         FT_UINT16, BASE_DEC, NULL, 0x0,
1640         "The station IP port",
1641         HFILL }
1642     },
1643
1644     { &hf_skinny_stationKeypadButton,
1645       { "KeypadButton", "skinny.stationKeypadButton",
1646         FT_UINT32, BASE_HEX, VALS(keypadButtons), 0x0,
1647         "The button pressed on the phone.",
1648         HFILL }
1649     },
1650
1651     { &hf_skinny_calledParty,
1652       { "CalledParty", "skinny.calledParty",
1653         FT_STRING, BASE_NONE, NULL, 0x0,
1654         "The number called.",
1655         HFILL }
1656     },
1657
1658     { &hf_skinny_stimulus,
1659       { "Stimulus", "skinny.stimulus",
1660         FT_UINT32, BASE_HEX, VALS(deviceStimuli), 0x0,
1661         "Reason for the device stimulus message.",
1662         HFILL }
1663     },
1664
1665     { &hf_skinny_stimulusInstance,
1666       { "StimulusInstance", "skinny.stimulusInstance",
1667         FT_UINT32, BASE_DEC, NULL, 0x0,
1668         "The instance of the stimulus",
1669         HFILL }
1670     },
1671
1672     { &hf_skinny_lineNumber,
1673       { "LineNumber", "skinny.lineNumber",
1674         FT_UINT32, BASE_DEC, NULL, 0x0,
1675         "Line Number",
1676         HFILL }
1677     },
1678
1679     { &hf_skinny_speedDialNumber,
1680       { "SpeedDialNumber", "skinny.speedDialNumber",
1681         FT_UINT32, BASE_DEC, NULL, 0x0,
1682         "Which speed dial number",
1683         HFILL }
1684     },
1685
1686     { &hf_skinny_capCount,
1687       { "CapCount", "skinny.capCount",
1688         FT_UINT32, BASE_DEC, NULL, 0x0,
1689         "How many capabilities",
1690         HFILL }
1691     },
1692
1693     { &hf_skinny_payloadCapability,
1694       { "PayloadCapability", "skinny.payloadCapability",
1695         FT_UINT32, BASE_DEC, VALS(mediaPayloads), 0x0,
1696         "The payload capability for this media capability structure.",
1697         HFILL }
1698     },
1699
1700     { &hf_skinny_maxFramesPerPacket,
1701       { "MaxFramesPerPacket", "skinny.maxFramesPerPacket",
1702         FT_UINT16, BASE_DEC, NULL, 0x0,
1703         "Max frames per packet",
1704         HFILL }
1705     },
1706
1707     { &hf_skinny_alarmSeverity,
1708       { "AlarmSeverity", "skinny.alarmSeverity",
1709         FT_UINT32, BASE_DEC, VALS(alarmSeverities), 0x0,
1710         "The severity of the reported alarm.",
1711         HFILL }
1712     },
1713
1714     { &hf_skinny_alarmParam1,
1715       { "AlarmParam1", "skinny.alarmParam1",
1716         FT_UINT32, BASE_HEX, NULL, 0x0,
1717         "An as yet undecoded param1 value from the alarm message",
1718         HFILL }
1719     },
1720
1721     { &hf_skinny_alarmParam2,
1722       { "AlarmParam2", "skinny.alarmParam2",
1723         FT_IPv4, BASE_NONE, NULL, 0x0,
1724         "This is the second alarm parameter i think it's an ip address",
1725         HFILL }
1726     },
1727
1728     { &hf_skinny_receptionStatus,
1729       { "ReceptionStatus", "skinny.receptionStatus",
1730         FT_UINT32, BASE_DEC, VALS(multicastMediaReceptionStatus), 0x0,
1731         "The current status of the multicast media.",
1732         HFILL }
1733     },
1734
1735     { &hf_skinny_passThruPartyID,
1736       { "PassThruPartyID", "skinny.passThruPartyID",
1737         FT_UINT32, BASE_DEC, NULL, 0x0,
1738         "The pass thru party id",
1739         HFILL }
1740     },
1741
1742     { &hf_skinny_ORCStatus,
1743       { "OpenReceiveChannelStatus", "skinny.openReceiveChannelStatus",
1744         FT_UINT32, BASE_DEC, VALS(openReceiveChanStatus), 0x0,
1745         "The status of the opened receive channel.",
1746         HFILL }
1747     },
1748
1749     { &hf_skinny_ipAddress,
1750       { "IP Address", "skinny.ipAddress",
1751         FT_IPv4, BASE_NONE, NULL, 0x0,
1752         "An IP address",
1753         HFILL }
1754     },
1755
1756     { &hf_skinny_portNumber,
1757       { "Port Number", "skinny.portNumber",
1758         FT_UINT32, BASE_DEC, NULL, 0x0,
1759         "A port number",
1760         HFILL }
1761     },
1762
1763     { &hf_skinny_statsProcessingType,
1764       { "StatsProcessingType", "skinny.statsProcessingType",
1765         FT_UINT32, BASE_DEC, VALS(statsProcessingTypes), 0x0,
1766         "What do do after you send the stats.",
1767         HFILL }
1768     },
1769
1770     { &hf_skinny_callIdentifier,
1771       { "Call Identifier", "skinny.callIdentifier",
1772         FT_UINT32, BASE_DEC, NULL, 0x0,
1773         "Call identifier for this call.",
1774         HFILL }
1775     },
1776
1777     { &hf_skinny_packetsSent,
1778       { "Packets Sent", "skinny.packetsSent",
1779         FT_UINT32, BASE_DEC, NULL, 0x0,
1780         "Packets Sent during the call.",
1781         HFILL }
1782     },
1783
1784     { &hf_skinny_octetsSent,
1785       { "Octets Sent", "skinny.octetsSent",
1786         FT_UINT32, BASE_DEC, NULL, 0x0,
1787         "Octets sent during the call.",
1788         HFILL }
1789     },
1790
1791     { &hf_skinny_packetsRecv,
1792       { "Packets Received", "skinny.packetsRecv",
1793         FT_UINT32, BASE_DEC, NULL, 0x0,
1794         "Packets received during the call.",
1795         HFILL }
1796     },
1797
1798     { &hf_skinny_octetsRecv,
1799       { "Octets Received", "skinny.octetsRecv",
1800         FT_UINT32, BASE_DEC, NULL, 0x0,
1801         "Octets received during the call.",
1802         HFILL }
1803     },
1804
1805     { &hf_skinny_packetsLost,
1806       { "Packets Lost", "skinny.packetsLost",
1807         FT_UINT32, BASE_DEC, NULL, 0x0,
1808         "Packets lost during the call.",
1809         HFILL }
1810     },
1811
1812     { &hf_skinny_latency,
1813       { "Latency(ms)", "skinny.latency",
1814         FT_UINT32, BASE_DEC, NULL, 0x0,
1815         "Average packet latency during the call.",
1816         HFILL }
1817     },
1818
1819     { &hf_skinny_jitter,
1820       { "Jitter", "skinny.jitter",
1821         FT_UINT32, BASE_DEC, NULL, 0x0,
1822         "Average jitter during the call.",
1823         HFILL }
1824     },
1825
1826     { &hf_skinny_directoryNumber,
1827       { "Directory Number", "skinny.directoryNumber",
1828         FT_STRING, BASE_NONE, NULL, 0x0,
1829         "The number we are reporting statistics for.",
1830         HFILL }
1831     },
1832
1833     { &hf_skinny_lineInstance,
1834       { "Line Instance", "skinny.lineInstance",
1835         FT_UINT32, BASE_DEC, NULL, 0x0,
1836         "The display call plane associated with this call.",
1837         HFILL }
1838     },
1839
1840     { &hf_skinny_softKeyEvent,
1841       { "SoftKeyEvent", "skinny.softKeyEvent",
1842         FT_UINT32, BASE_DEC, VALS(softKeyEvents), 0x0,
1843         "Which softkey event is being reported.",
1844         HFILL }
1845     },
1846
1847     { &hf_skinny_keepAliveInterval,
1848       { "KeepAliveInterval", "skinny.keepAliveInterval",
1849         FT_UINT32, BASE_DEC, NULL, 0x0,
1850         "How often are keep alives exchanges between the client and the call manager.",
1851         HFILL }
1852     },
1853
1854     { &hf_skinny_secondaryKeepAliveInterval,
1855       { "SecondaryKeepAliveInterval", "skinny.secondaryKeepAliveInterval",
1856         FT_UINT32, BASE_DEC, NULL, 0x0,
1857         "How often are keep alives exchanges between the client and the secondary call manager.",
1858         HFILL }
1859     },
1860
1861     { &hf_skinny_dateTemplate,
1862       { "DateTemplate", "skinny.dateTemplate",
1863         FT_STRING, BASE_NONE, NULL, 0x0,
1864         "The display format for the date/time on the phone.",
1865         HFILL }
1866     },
1867
1868     { &hf_skinny_buttonOffset,
1869       { "ButtonOffset", "skinny.buttonOffset",
1870         FT_UINT32, BASE_DEC, NULL, 0x0,
1871         "Offset is the number of the first button referenced by this message.",
1872         HFILL }
1873     },
1874
1875     { &hf_skinny_buttonCount,
1876       { "ButtonCount", "skinny.buttonCount",
1877         FT_UINT32, BASE_DEC, NULL, 0x0,
1878         "Number of (VALID) button definitions in this message.",
1879         HFILL }
1880     },
1881
1882     { &hf_skinny_totalButtonCount,
1883       { "TotalButtonCount", "skinny.totalButtonCount",
1884         FT_UINT32, BASE_DEC, NULL, 0x0,
1885         "The total number of buttons defined for this phone.",
1886         HFILL }
1887     },
1888
1889     { &hf_skinny_buttonInstanceNumber,
1890       { "InstanceNumber", "skinny.buttonInstanceNumber",
1891         FT_UINT8, BASE_HEX, VALS(keypadButtons), 0x0,
1892         "The button instance number for a button or the StationKeyPad value, repeats allowed.",
1893         HFILL }
1894     },
1895
1896     { &hf_skinny_buttonDefinition,
1897       { "ButtonDefinition", "skinny.buttonDefinition",
1898         FT_UINT8, BASE_HEX, VALS(buttonDefinitions), 0x0,
1899         "The button type for this instance (ie line, speed dial, ....",
1900         HFILL }
1901     },
1902
1903     { &hf_skinny_softKeyOffset,
1904       { "SoftKeyOffset", "skinny.softKeyOffset",
1905         FT_UINT32, BASE_DEC, NULL, 0x0,
1906         "The offset for the first soft key in this message.",
1907         HFILL }
1908     },
1909
1910     { &hf_skinny_softKeyCount,
1911       { "SoftKeyCount", "skinny.softKeyCount",
1912         FT_UINT32, BASE_DEC, NULL, 0x0,
1913         "The number of valid softkeys in this message.",
1914         HFILL }
1915     },
1916
1917     { &hf_skinny_totalSoftKeyCount,
1918       { "TotalSoftKeyCount", "skinny.totalSoftKeyCount",
1919         FT_UINT32, BASE_DEC, NULL, 0x0,
1920         "The total number of softkeys for this device.",
1921         HFILL }
1922     },
1923
1924     { &hf_skinny_softKeyLabel,
1925       { "SoftKeyLabel", "skinny.softKeyLabel",
1926         FT_STRING, BASE_NONE, NULL, 0x0,
1927         "The text label for this soft key.",
1928         HFILL }
1929     },
1930
1931     { &hf_skinny_softKeySetOffset,
1932       { "SoftKeySetOffset", "skinny.softKeySetOffset",
1933         FT_UINT32, BASE_DEC, NULL, 0x0,
1934         "The offset for the first soft key set in this message.",
1935         HFILL }
1936     },
1937
1938     { &hf_skinny_softKeySetCount,
1939       { "SoftKeySetCount", "skinny.softKeySetCount",
1940         FT_UINT32, BASE_DEC, NULL, 0x0,
1941         "The number of valid softkey sets in this message.",
1942         HFILL }
1943     },
1944
1945     { &hf_skinny_totalSoftKeySetCount,
1946       { "TotalSoftKeySetCount", "skinny.totalSoftKeySetCount",
1947         FT_UINT32, BASE_DEC, NULL, 0x0,
1948         "The total number of softkey sets for this device.",
1949         HFILL }
1950     },
1951
1952     { &hf_skinny_softKeyTemplateIndex,
1953       { "SoftKeyTemplateIndex", "skinny.softKeyTemplateIndex",
1954         FT_UINT8, BASE_DEC, VALS(softKeyEvents), 0x0,
1955         "Array of size 16 8-bit unsigned ints containing an index into the softKeyTemplate.",
1956         HFILL }
1957     },
1958
1959     { &hf_skinny_softKeyInfoIndex,
1960       { "SoftKeyInfoIndex", "skinny.softKeyInfoIndex",
1961         FT_UINT16, BASE_DEC, VALS(softKeyIndexes), 0x0,
1962         "Array of size 16 16-bit unsigned integers containing an index into the soft key description information.",
1963         HFILL }
1964     },
1965
1966     { &hf_skinny_softKeySetDescription,
1967       { "SoftKeySet", "skinny.softKeySetDescription",
1968         FT_UINT8, BASE_DEC, VALS(keySetNames), 0x0,
1969         "A text description of what this softkey when this softkey set is displayed",
1970         HFILL }
1971     },
1972
1973     { &hf_skinny_softKeyMap,
1974       { "SoftKeyMap","skinny.softKeyMap", 
1975         FT_UINT16, BASE_HEX, NULL, 0x0,
1976         "", 
1977         HFILL }
1978     },
1979     
1980     { &hf_skinny_softKey0,
1981       { "SoftKey0", "skinny.softKeyMap.0", 
1982         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY0,
1983         "", 
1984         HFILL }
1985     },
1986
1987     { &hf_skinny_softKey1,
1988       { "SoftKey1", "skinny.softKeyMap.1", 
1989         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY1,
1990         "", 
1991         HFILL }
1992     },
1993
1994     { &hf_skinny_softKey2,
1995       { "SoftKey2", "skinny.softKeyMap.2", 
1996         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY2,
1997         "", 
1998         HFILL }
1999     },
2000
2001     { &hf_skinny_softKey3,
2002       { "SoftKey3", "skinny.softKeyMap.3",
2003         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY3,
2004         "", 
2005         HFILL }
2006     },
2007
2008     { &hf_skinny_softKey4,
2009       { "SoftKey4", "skinny.softKeyMap.4", 
2010         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY4,
2011         "", 
2012         HFILL }
2013     },
2014
2015     { &hf_skinny_softKey5,
2016       { "SoftKey5", "skinny.softKeyMap.5", 
2017         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY5,
2018         "", 
2019         HFILL }
2020     },
2021
2022     { &hf_skinny_softKey6,
2023       { "SoftKey6", "skinny.softKeyMap.6", 
2024         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY6,
2025         "", 
2026         HFILL }
2027     },
2028
2029     { &hf_skinny_softKey7,
2030       { "SoftKey7", "skinny.softKeyMap.7", 
2031         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY7,
2032         "", 
2033         HFILL }
2034     },
2035
2036     { &hf_skinny_softKey8,
2037       { "SoftKey8", "skinny.softKeyMap.8", 
2038         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY8,
2039         "", 
2040         HFILL }
2041     },
2042
2043     { &hf_skinny_softKey9,
2044       { "SoftKey9", "skinny.softKeyMap.9", 
2045         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY9,
2046         "", 
2047         HFILL }
2048     },
2049
2050     { &hf_skinny_softKey10,
2051       { "SoftKey10", "skinny.softKeyMap.10", 
2052         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY10,
2053         "", 
2054         HFILL }
2055     },
2056
2057     { &hf_skinny_softKey11,
2058       { "SoftKey11", "skinny.softKeyMap.11", 
2059         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY11,
2060         "", 
2061         HFILL }
2062     },
2063
2064     { &hf_skinny_softKey12,
2065       { "SoftKey12", "skinny.softKeyMap.12", 
2066         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY12,
2067         "", 
2068         HFILL }
2069     },
2070
2071     { &hf_skinny_softKey13,
2072       { "SoftKey13", "skinny.softKeyMap.13", 
2073         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY13,
2074         "", 
2075         HFILL }
2076     },
2077
2078     { &hf_skinny_softKey14,
2079       { "SoftKey14", "skinny.softKeyMap.14", 
2080         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY14,
2081         "", 
2082         HFILL }
2083     },
2084
2085     { &hf_skinny_softKey15,
2086       { "SoftKey15", "skinny.softKeyMap.15", 
2087         FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY15,
2088         "", 
2089         HFILL }
2090     },
2091
2092     { &hf_skinny_lampMode,
2093       { "LampMode", "skinny.lampMode", 
2094         FT_UINT32, BASE_DEC, VALS(stationLampModes), 0x0,
2095         "The lamp mode", 
2096         HFILL }
2097     },
2098
2099     { &hf_skinny_messageTimeOutValue,
2100       { "Message Timeout", "skinny.messageTimeOutValue", 
2101         FT_UINT32, BASE_DEC, NULL, 0x0,
2102         "The timeout in seconds for this message", 
2103         HFILL }
2104     },
2105
2106     { &hf_skinny_displayMessage,
2107       { "DisplayMessage", "skinny.displayMessage",
2108         FT_STRING, BASE_NONE, NULL, 0x0,
2109         "The message displayed on the phone.",
2110         HFILL }
2111     },
2112
2113     { &hf_skinny_lineDirNumber,
2114       { "Line Dir Number", "skinny.lineDirNumber",
2115         FT_STRING, BASE_NONE, NULL, 0x0,
2116         "The directory number for this line.",
2117         HFILL }
2118     },
2119
2120     { &hf_skinny_lineFullyQualifiedDisplayName,
2121       { "DisplayName", "skinny.fqdn",
2122         FT_STRING, BASE_NONE, NULL, 0x0,
2123         "The full display name for this line.",
2124         HFILL }
2125     },
2126
2127     { &hf_skinny_speedDialDirNumber,
2128       { "SpeedDial Number", "skinny.speedDialDirNum",
2129         FT_STRING, BASE_NONE, NULL, 0x0,
2130         "the number to dial for this speed dial.",
2131         HFILL }
2132     },
2133
2134     { &hf_skinny_speedDialDisplayName,
2135       { "SpeedDial Display", "skinny.speedDialDisplay",
2136         FT_STRING, BASE_NONE, NULL, 0x0,
2137         "The text to display for this speed dial.",
2138         HFILL }
2139     },
2140
2141     { &hf_skinny_dateYear,
2142       { "Year", "skinny.year",
2143         FT_UINT32, BASE_DEC, NULL, 0x0,
2144         "The current year",
2145         HFILL }
2146     },
2147
2148     { &hf_skinny_dateMonth,
2149       { "Month", "skinny.month",
2150         FT_UINT32, BASE_DEC, NULL, 0x0,
2151         "The current month",
2152         HFILL }
2153     },
2154
2155     { &hf_skinny_dayOfWeek,
2156       { "DayOfWeek", "skinny.dayOfWeek",
2157         FT_UINT32, BASE_DEC, NULL, 0x0,
2158         "The day of the week",
2159         HFILL }
2160     },
2161
2162     { &hf_skinny_dateDay,
2163       { "Day", "skinny.day",
2164         FT_UINT32, BASE_DEC, NULL, 0x0,
2165         "The day of the current month",
2166         HFILL }
2167     },
2168
2169     { &hf_skinny_dateHour,
2170       { "Hour", "skinny.hour",
2171         FT_UINT32, BASE_DEC, NULL, 0x0,
2172         "Hour of the day",
2173         HFILL }
2174     },
2175
2176     { &hf_skinny_dateMinute,
2177       { "Minute", "skinny.minute",
2178         FT_UINT32, BASE_DEC, NULL, 0x0,
2179         "Minute",
2180         HFILL }
2181     },
2182
2183     { &hf_skinny_dateSeconds,
2184       { "Seconds", "skinny.dateSeconds",
2185         FT_UINT32, BASE_DEC, NULL, 0x0,
2186         "Seconds",
2187         HFILL }
2188     },
2189
2190     { &hf_skinny_dateMilliseconds,
2191       { "Milliseconds", "skinny.dateMilliseconds",
2192         FT_UINT32, BASE_DEC, NULL, 0x0,
2193         "Milliseconds",
2194         HFILL }
2195     },
2196
2197     { &hf_skinny_timeStamp,
2198       { "Timestamp", "skinny.timeStamp",
2199         FT_UINT32, BASE_DEC, NULL, 0x0,
2200         "Time stamp for the call reference",
2201         HFILL }
2202     },
2203     { &hf_skinny_callState,
2204       { "CallState", "skinny.callState", 
2205         FT_UINT32, BASE_DEC, VALS(skinny_stationCallStates), 0x0,
2206         "The D channel call state of the call", 
2207         HFILL }
2208     },
2209
2210     { &hf_skinny_deviceTone,
2211       { "Tone", "skinny.deviceTone", 
2212         FT_UINT32, BASE_HEX, VALS(skinny_deviceTones), 0x0,
2213         "Which tone to play", 
2214         HFILL }
2215     },
2216
2217     { &hf_skinny_callingPartyName,
2218       { "Calling Party Name", "skinny.callingPartyName",
2219         FT_STRING, BASE_NONE, NULL, 0x0,
2220         "The passed name of the calling party.",
2221         HFILL }
2222     },
2223
2224     { &hf_skinny_callingParty,
2225       { "Calling Party", "skinny.callingPartyName",
2226         FT_STRING, BASE_NONE, NULL, 0x0,
2227         "The passed number of the calling party.",
2228         HFILL }
2229     },
2230
2231     { &hf_skinny_calledPartyName,
2232       { "Called Party Name", "skinny.calledPartyName",
2233         FT_STRING, BASE_NONE, NULL, 0x0,
2234         "The name of the party we are calling.",
2235         HFILL }
2236     },
2237
2238     { &hf_skinny_callType,
2239       { "Call Type", "skinny.callType", 
2240         FT_UINT32, BASE_DEC, VALS(skinny_callTypes), 0x0,
2241         "What type of call, in/out/etc", 
2242         HFILL }
2243     },
2244
2245     { &hf_skinny_originalCalledPartyName,
2246       { "Original Called Party Name", "skinny.originalCalledPartyName",
2247         FT_STRING, BASE_NONE, NULL, 0x0,
2248         "name of the original person who placed the call.",
2249         HFILL }
2250     },
2251
2252     { &hf_skinny_originalCalledParty,
2253       { "Original Called Party", "skinny.originalCalledParty",
2254         FT_STRING, BASE_NONE, NULL, 0x0,
2255         "The number of the original calling party.",
2256         HFILL }
2257     },
2258
2259     { &hf_skinny_ringType,
2260       { "Ring Type", "skinny.ringType", 
2261         FT_UINT32, BASE_HEX, VALS(skinny_ringTypes), 0x0,
2262         "What type of ring to play", 
2263         HFILL }
2264     },
2265
2266     { &hf_skinny_speakerMode,
2267       { "Speaker", "skinny.speakerMode", 
2268         FT_UINT32, BASE_HEX, VALS(skinny_speakerModes), 0x0,
2269         "This message sets the speaker mode on/off", 
2270         HFILL }
2271     },
2272
2273     { &hf_skinny_remoteIpAddr,
2274       { "Remote Ip Address", "skinny.remoteIpAddr",
2275         FT_IPv4, BASE_NONE, NULL, 0x0,
2276         "The remote end ip address for this stream",
2277         HFILL }
2278     },
2279
2280     { &hf_skinny_remotePortNumber,
2281       { "Remote Port", "skinny.remotePortNumber",
2282         FT_UINT32, BASE_DEC, NULL, 0x0,
2283         "The remote port number listening for this stream",
2284         HFILL }
2285     },
2286
2287     { &hf_skinny_millisecondPacketSize,
2288       { "MS/Packet", "skinny.millisecondPacketSize",
2289         FT_UINT32, BASE_DEC, NULL, 0x0,
2290         "The number of milliseconds of conversation in each packet",
2291         HFILL }
2292     },
2293
2294     { &hf_skinny_precedenceValue,
2295       { "Precedence", "skinny.precedenceValue",
2296         FT_UINT32, BASE_DEC, NULL, 0x0,
2297         "Precedence value",
2298         HFILL }
2299     },
2300
2301     { &hf_skinny_silenceSuppression,
2302       { "Silence Suppression", "skinny.silenceSuppression", 
2303         FT_UINT32, BASE_HEX, VALS(skinny_silenceSuppressionModes), 0x0,
2304         "Mode for silence suppression", 
2305         HFILL }
2306     },
2307
2308     { &hf_skinny_g723BitRate,
2309       { "G723 BitRate", "skinny.g723BitRate", 
2310         FT_UINT32, BASE_DEC, VALS(skinny_g723BitRates), 0x0,
2311         "The G723 bit rate for this stream/JUNK if not g723 stream", 
2312         HFILL }
2313     },
2314
2315     { &hf_skinny_conferenceID,
2316       { "Conference ID", "skinny.conferenceID",
2317         FT_UINT32, BASE_DEC, NULL, 0x0,
2318         "The conference ID",
2319         HFILL }
2320     },
2321
2322     { &hf_skinny_deviceResetType,
2323       { "Reset Type", "skinny.deviceResetType", 
2324         FT_UINT32, BASE_DEC, VALS(skinny_deviceResetTypes), 0x0,
2325         "How the devices it to be reset (reset/restart)", 
2326         HFILL }
2327     },
2328
2329     { &hf_skinny_echoCancelType,
2330       { "Echo Cancel Type", "skinny.echoCancelType", 
2331         FT_UINT32, BASE_DEC, VALS(skinny_echoCancelTypes), 0x0,
2332         "Is echo cancelling enabled or not", 
2333         HFILL }
2334     },
2335
2336     { &hf_skinny_deviceUnregisterStatus,
2337       { "Unregister Status", "skinny.deviceUnregisterStatus", 
2338         FT_UINT32, BASE_DEC, VALS(skinny_deviceUnregisterStatusTypes), 0x0,
2339         "The status of the device unregister request (*CAN* be refused)", 
2340         HFILL }
2341     },
2342
2343     { &hf_skinny_hookFlashDetectMode,
2344       { "Hook Flash Mode", "skinny.hookFlashDetectMode", 
2345         FT_UINT32, BASE_DEC, VALS(skinny_hookFlashDetectModes), 0x0,
2346         "Which method to use to detect that a hook flash has occured", 
2347         HFILL }
2348     },
2349
2350     { &hf_skinny_detectInterval,
2351       { "HF Detect Interval", "skinny.detectInterval",
2352         FT_UINT32, BASE_DEC, NULL, 0x0,
2353         "The number of milliseconds that determines a hook flash has occured",
2354         HFILL }
2355     },
2356
2357     { &hf_skinny_microphoneMode,
2358       { "Microphone Mode", "skinny.microphoneMode", 
2359         FT_UINT32, BASE_DEC, VALS(skinny_microphoneModes), 0x0,
2360         "Turns on and off the microphone on the set", 
2361         HFILL }
2362     },
2363
2364     { &hf_skinny_activeForward,
2365       { "Active Forward", "skinny.activeForward",
2366         FT_UINT32, BASE_DEC, NULL, 0x0,
2367         "This is non zero to indicate that a forward is active on the line",
2368         HFILL }
2369     },
2370
2371     { &hf_skinny_forwardAllActive,
2372       { "Forward All", "skinny.forwardAllActive",
2373         FT_UINT32, BASE_DEC, NULL, 0x0,
2374         "Forward all calls",
2375         HFILL }
2376     },
2377
2378     { &hf_skinny_forwardBusyActive,
2379       { "Forward Busy", "skinny.forwardBusyActive",
2380         FT_UINT32, BASE_DEC, NULL, 0x0,
2381         "Forward calls when busy",
2382         HFILL }
2383     },
2384
2385     { &hf_skinny_forwardNoAnswerActive,
2386       { "Forward NoAns", "skinny.forwardNoAnswerActive",
2387         FT_UINT32, BASE_DEC, NULL, 0x0,
2388         "Forward only when no answer",
2389         HFILL }
2390     },
2391
2392     { &hf_skinny_forwardNumber,
2393       { "Forward Number", "skinny.forwardNumber",
2394         FT_STRING, BASE_NONE, NULL, 0x0,
2395         "The number to forward calls to.",
2396         HFILL }
2397     },
2398
2399     { &hf_skinny_userName,
2400       { "Username", "skinny.userName",
2401         FT_STRING, BASE_NONE, NULL, 0x0,
2402         "Username for this device.",
2403         HFILL }
2404     },
2405
2406     { &hf_skinny_serverName,
2407       { "Server Name", "skinny.serverName",
2408         FT_STRING, BASE_NONE, NULL, 0x0,
2409         "The server name for this device.",
2410         HFILL }
2411     },
2412
2413     { &hf_skinny_numberLines,
2414       { "Number of Lines", "skinny.numberLines",
2415         FT_UINT32, BASE_DEC, NULL, 0x0,
2416         "How many lines this device has",
2417         HFILL }
2418     },
2419
2420     { &hf_skinny_numberSpeedDials,
2421       { "Number of SpeedDials", "skinny.numberSpeedDials",
2422         FT_UINT32, BASE_DEC, NULL, 0x0,
2423         "The number of speed dials this device has",
2424         HFILL }
2425     },
2426
2427     { &hf_skinny_sessionType,
2428       { "Session Type", "skinny.sessionType", 
2429         FT_UINT32, BASE_DEC, VALS(skinny_sessionTypes), 0x0,
2430         "The type of this session.", 
2431         HFILL }
2432     },
2433
2434     { &hf_skinny_version,
2435       { "Version", "skinny.version",
2436         FT_STRING, BASE_NONE, NULL, 0x0,
2437         "Version.",
2438         HFILL }
2439     },
2440
2441     { &hf_skinny_mediaEnunciationType,
2442       { "Enunciation Type", "skinny.mediaEnunciationType", 
2443         FT_UINT32, BASE_DEC, VALS(skinny_mediaEnunciationTypes), 0x0,
2444         "No clue.", 
2445         HFILL }
2446     },
2447
2448     { &hf_skinny_serverIdentifier,
2449       { "Server Identifier", "skinny.serverIdentifier",
2450         FT_STRING, BASE_NONE, NULL, 0x0,
2451         "Server Identifier.",
2452         HFILL }
2453     },
2454
2455     { &hf_skinny_serverListenPort,
2456       { "Server Port", "skinny.serverListenPort", 
2457         FT_UINT32, BASE_DEC, NULL, 0x0,
2458         "The port the server listens on.", 
2459         HFILL }
2460     },
2461
2462     { &hf_skinny_serverIpAddress,
2463       { "Server Ip Address", "skinny.serverIpAddress",
2464         FT_IPv4, BASE_NONE, NULL, 0x0,
2465         "The IP address for this server",
2466         HFILL }
2467     },
2468
2469     { &hf_skinny_multicastPort,
2470       { "Multicast Port", "skinny.multicastPort", 
2471         FT_UINT32, BASE_DEC, NULL, 0x0,
2472         "The multicast port the to listens on.", 
2473         HFILL }
2474     },
2475
2476     { &hf_skinny_multicastIpAddress,
2477       { "Multicast Ip Address", "skinny.multicastIpAddress",
2478         FT_IPv4, BASE_NONE, NULL, 0x0,
2479         "The multicast address for this conference",
2480         HFILL }
2481     },
2482
2483     { &hf_skinny_tokenRejWaitTime,
2484       { "Retry Wait Time", "skinny.tokenRejWaitTime", 
2485         FT_UINT32, BASE_DEC, NULL, 0x0,
2486         "The time to wait before retrying this token request.", 
2487         HFILL }
2488     },
2489
2490     { &hf_skinny_unknown,
2491       { "Data", "skinny.unknown", 
2492         FT_UINT32, BASE_HEX, NULL, 0x0,
2493         "Place holder for unknown data.", 
2494         HFILL }
2495     },
2496
2497   };
2498   
2499   /* Setup protocol subtree array */
2500   static gint *ett[] = {
2501     &ett_skinny,
2502     &ett_skinny_softKeyMap,
2503   };
2504
2505   module_t *skinny_module;
2506
2507   /* Register the protocol name and description */
2508   proto_skinny = proto_register_protocol("Skinny Client Control Protocol",
2509                                          "SKINNY", "skinny");
2510   
2511   /* Required function calls to register the header fields and subtrees used */
2512   proto_register_field_array(proto_skinny, hf, array_length(hf));
2513   proto_register_subtree_array(ett, array_length(ett));
2514
2515   skinny_module = prefs_register_protocol(proto_skinny, NULL);
2516   prefs_register_bool_preference(skinny_module, "desegment",
2517     "Desegment all SCCP messages spanning multiple TCP segments",
2518     "Whether the SCCP dissector should desegment all messages spanning multiple TCP segments",
2519     &skinny_desegment);
2520 };
2521
2522 void
2523 proto_reg_handoff_skinny(void)
2524 {
2525   dissector_handle_t skinny_handle;
2526
2527   data_handle = find_dissector("data");
2528   skinny_handle = create_dissector_handle(dissect_skinny, proto_skinny);
2529   dissector_add("tcp.port", TCP_PORT_SKINNY, skinny_handle);
2530 }
2531
2532 /*
2533  * FIXME:
2534  *
2535  * This is the status of this decode.
2536  * Items marked as N/A in the decode field have no params to test
2537  * implemented for N/A means they exist in the switch statement
2538  * S = stubbed
2539  *
2540  *  id     message                     implemented  decode tested (via capture)
2541  *  ---------------------------------------------------------------------------
2542  *  0x0    keepAlive                       Y        N/A 
2543  *  0x1    register                        Y        Y
2544  *  0x2    ipPort                          Y        Y
2545  *  0x3    keypadButton                    Y        Y
2546  *  0x4    enblocCall                      Y        N
2547  *  0x5    stimulus                        Y        N
2548  *  0x6    offHook                         Y        N/A
2549  *  0x7    onHook                          Y        N/A
2550  *  0x8    hookFlash                       Y        N/A
2551  *  0x9    forwardStatReq                  Y        N
2552  *  0xa    speedDialStatReq                Y        Y
2553  *  0xb    lineStatReq                     Y        Y
2554  *  0xc    configStatReq                   Y        N/A
2555  *  0xd    timeDateReq                     Y        N/A
2556  *  0xe    buttonTemplateReq               Y        N/A
2557  *  0xf    versionReq                      Y        N/A
2558  *  0x10   capabilitiesRes                 Y        Y -- would like more decodes
2559  *  0x11   mediaPortList                   S        N -- no info 
2560  *  0x12   serverReq                       Y        N/A
2561  *  0x20   alarmMessage                    Y        Y
2562  *  0x21   multicastMediaReceptionAck      Y        N
2563  *  0x22   openReceiveChannelAck           Y        Y
2564  *  0x23   connectionStatisticsRes         Y        Y
2565  *  0x24   offHookWithCgpn                 Y        N
2566  *  0x25   softKeySetReq                   Y        N/A
2567  *  0x26   softKeyEvent                    Y        Y
2568  *  0x27   unregister                      Y        N/A
2569  *  0x28   softKeytemplateReq              Y        N/A
2570  *  0x29   registerTokenReq                Y        N
2571  *******************************
2572  *  0x2b   unknownClientMessage1           S        N
2573  *  0x2d   unknownClientMessage2           S        N
2574  *******************************
2575  *  0x81   registerAck                     Y        Y
2576  *  0x82   startTone                       Y        Y
2577  *  0x83   stopTone                        Y        N/A
2578  *  0x85   setRinger                       Y        Y
2579  *  0x86   setLamp                         Y        Y
2580  *  0x87   setHkFDetect                    Y        N
2581  *  0x88   setSpeakerMode                  Y        Y
2582  *  0x89   setMicroMode                    Y        N
2583  *  0x8A   startMediaTransmission          Y        Y
2584  *  0x8B   stopMediaTransmission           Y        Y
2585  *  0x8C   startMediaReception             S        N
2586  *  0x8D   stopMediaReception              S        N
2587  *  0x8E   *reserved*                      S        *
2588  *  0x8F   callInfo                        Y        Y
2589  *  0x90   forwardStat                     Y        N
2590  *  0x91   speedDialStat                   Y        Y
2591  *  0x92   lineStat                        Y        Y
2592  *  0x93   configStat                      Y        N
2593  *  0x94   defineTimeDate                  Y        Y
2594  *  0x95   startSessionTransmission        Y        N
2595  *  0x96   stopSessionTransmission         Y        N
2596  *  0x97   buttonTemplate                  Y        Y -- ugly =)
2597  *  0x98   version                         Y        N
2598  *  0x99   displayText                     Y        Y
2599  *  0x9A   clearDisplay                    Y        N/A
2600  *  0x9B   capabilitiesReq                 Y        N/A
2601  *  0x9C   enunciatorCommand               Y        N (inner loop unknown)
2602  *  0x9D   registerReject                  Y        N
2603  *  0x9E   serverRes                       Y        N
2604  *  0x9F   reset                           Y        Y
2605  *  0x100  keepAliveAck                    Y        N/A
2606  *  0x101  startMulticastMediaReception    Y        N
2607  *  0x102  startMulticastMediaTransmission Y        N
2608  *  0x103  stopMulticastMediaReception     Y        N
2609  *  0x104  stopMulticastMediaTransmission  Y        N
2610  *  0x105  openreceiveChannel              Y        Y
2611  *  0x106  closeReceiveChannel             Y        Y
2612  *  0x107  connectionStatisticsReq         Y        Y
2613  *  0x108  softKeyTemplateRes              Y        Y
2614  *  0x109  softKeySetRes                   Y        Y
2615  *  0x110  selectSoftKeys                  Y        Y
2616  *  0x111  callState                       Y        Y
2617  *  0x112  displayPromptStatus             Y        Y
2618  *  0x113  clearPromptStatus               Y        Y
2619  *  0x114  displayNotify                   Y        Y
2620  *  0x115  clearNotify                     Y        Y
2621  *  0x116  activateCallPlane               Y        Y
2622  *  0x117  deactivateCallPlane             Y        N/A
2623  *  0x118  unregisterAck                   Y        Y
2624  *  0x119  backSpaceReq                    Y        Y
2625  *  0x11A  registerTokenAck                Y        N
2626  *  0x11B  registerTokenReject             Y        N
2627  *******************************
2628  *  0x11D  unknownForwardMessage           NC       N
2629  *******************************
2630  *
2631  *
2632  */