132abb80e5fd095df4592dc57625add5f02a5f68
[obnox/wireshark/wip.git] / epan / dissectors / packet-ua.c
1 /* packet-ua.c
2 * Routines for UA (Universal Alcatel) packet dissection.
3 * Copyright 2011, Marek Tews <marek@trx.com.pl>
4 *
5 * $Id$
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
10 *
11 * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
12 * is a dissector file; if you just copied this from README.developer,
13 * don't bother with the "Copied from" - you don't even need to put
14 * in a "Copied from" if you copied an existing dissector, especially
15 * if the bulk of the code in the new dissector is your code)
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_NETINET_IN_H
41 #include <netinet/in.h>
42 #endif
43
44 #include <epan/packet.h>
45
46 static void DissectNOE(tvbuff_t *pTvb, proto_tree *pRootUA);
47 static void DissectNOE_type(tvbuff_t *pTvb, proto_tree *pNoeItem);
48 static void DissectNOE_voicemode(tvbuff_t *pTvb, proto_tree *pNoeItem);
49 static void DissectNOE_callserver(tvbuff_t *pTvb, proto_tree *pNoeItem);
50 static void DissectNOE_ip(tvbuff_t *pTvb, proto_tree *pNoeItem);
51 static void DissectNOE_ip_startrtp(tvbuff_t *pTvb, proto_tree *pNoeItem);
52 static void DissectNOE_ip_startrtp_properties(tvbuff_t *pTvb, proto_tree *pNoeItem);
53
54 static void DissectTLV(tvbuff_t *pTvb, proto_tree *pNoeItem, gboolean bIsArrIndex);
55 static void DissectTLV_data(tvbuff_t *pTvb, proto_tree *pTlv, guint8 u8Property);
56
57 /*
58 * Here are the global variables associated with
59 * the various user definable characteristics of the dissection
60 */
61
62 /* Define the UA proto */
63 static int proto_ua = -1;
64
65 /* Define many header fields for UA (Universal Alcatel Protocol) */
66 static int hf_noe = -1;
67 static int hf_noe_length = -1;
68 static int hf_noe_type = -1;
69 static int hf_noe_method = -1;
70 static int hf_noe_class = -1;
71 static int hf_noe_objid = -1;
72 static int hf_noe_event = -1;
73 static int hf_noe_keychar = -1;
74 static int hf_noe_action = -1;
75 static int hf_noe_reserved = -1;
76 static int hf_noe_property = -1;
77 static int hf_noe_id = -1;
78 static int hf_noe_size = -1;
79 static int hf_noe_local_port = -1;
80 static int hf_noe_remote_ip = -1;
81 static int hf_noe_remote_port = -1;
82 static int hf_noe_data = -1;
83 static int hf_noe_compressor = -1;
84 static int hf_noe_typeofservice = -1;
85 static int hf_noe_payloadconcat = -1;
86 static int hf_noe_voicemode = -1;
87
88 static int hf_tlv = -1;
89 static int hf_tlv_property = -1;
90 static int hf_tlv_arrindex = -1;
91 static int hf_tlv_propsize = -1;
92 static int hf_tlv_label = -1;
93 static int hf_tlv_data = -1;
94 static int hf_tlv_year = -1;
95 static int hf_tlv_number = -1;
96
97 /* Define the trees for UA (Universal Alcatel Protocol) */
98 static int ett_ua = -1;
99
100 static int ett_noe = -1;
101 static int ett_noe_property = -1;
102
103 static int ett_tlv = -1;
104 static int ett_tlv_sub = -1;
105
106
107 /************************************************************
108 * Value Strings
109 ************************************************************/
110
111 /**
112 * NOE
113 */
114 static const value_string szNoeType[] =
115 {
116     { 0x00, "Unknown" },
117     { 0x01, "HandsetOffHook" },
118     { 0x02, "HandsetOnHook" },
119     { 0x03, "DigitDialed" },
120     { 0x13, "IP" },
121     { 0x15, "CallServer" },
122     { 0x20, "KeyPushed" },
123     { 0x21, "LedCmd" },
124     { 0x27, "WriteLine1" },
125     { 0x28, "WriteLine2" },
126     { 0x29, "VoiceMode" },
127     { 0x31, "SetClockComd" },
128     { 0x35, "CursorBlink" },
129     { 0x38, "ClockTimerPosition" },
130     { 0x3a, "Error_0x3a" },
131     { 0x3d, "SideTone" },
132     { 0x3f, "Mute" },
133     { 0x46, "AllIconsOff" },
134     { 0x47, "IconsCmd" },
135     { 0x48, "AmplifiedHandset" },
136     { 0x49, "DPIConfiguration" },
137     { 0x4a, "AudioPaddedPath" },
138     { 0x4f, "Error_0x4f" },
139     { 0, NULL }
140 };
141
142 static const value_string szCallServerMethod[] =
143 {
144     { 0x00, "Create" },
145     { 0x01, "Delete" },
146     { 0x02, "SetProperty" },
147     { 0x04, "Notify" },
148     { 0, NULL }
149 };
150
151 static const value_string szCallServerClass[] =
152 {
153     { 1,   "Terminal" },
154     { 5,   "Leds" },
155     { 6,   "Screen" },
156     { 7,   "Date" },
157     { 8,   "AOMV" },
158     { 12,  "CallState" },
159     { 128, "FrameBox" },
160     { 129, "TabBox" },
161     { 130, "ListBox" },
162     { 132, "TextBox" },
163     { 133, "ActionBox" },
164     { 136, "DataBox" },
165     { 137, "TimerBox" },
166     { 144, "AOMVBox" },
167     { 145, "TelephonicBox" },
168     { 146, "KeyboardContext" },
169     { 151, "TelephonicBoxItem" },
170     { 158, "HeaderBox" },
171     { 0, NULL }
172 };
173
174 static const value_string szCallServerEvent[] =
175 {
176     { 2,   "KeyPress" },
177     { 4,   "KeyShortPress" },
178     { 6,   "OnHook" },
179     { 7,   "OffHook" },
180     { 128, "TabBox" },
181     { 133, "ActionBox" },
182     { 152, "DialogBoxDismissed" },
183     { 0, NULL }
184 };
185
186 static const value_string szStartRtpPropID[] =
187 {
188     { 0x00, "LocalUDPPort" },
189     { 0x01, "RemoteIP" },
190     { 0x02, "RemoteUDPPort" },
191     { 0x03, "TypeOfService" },
192     { 0x04, "Payload" },
193     { 0x05, "PayloadConcatenation" }, /* in ms */
194     { 0x06, "EchoCancelationEnabler" },
195     { 0x07, "SilenceCompression" },
196     { 0x08, "_802_1QUserPriority" },
197     { 0x0A, "PostFiltering" },
198     { 0x0B, "HighPassFilter" },
199     { 0, NULL }
200 };
201
202 static const value_string szStartRtpPayload[] =
203 {
204     { 0,    "G.711 A-law" },
205     { 1,    "G.711 mu-law" },
206     { 2,    "G.723.1 5.3 kbps" },
207     { 3,    "G.723.1 6.3 kbps" },
208     { 0x11, "G.729A 8kbps"},
209     { 0, NULL }
210 };
211
212 static const value_string szNoeAction[] =
213 {
214     { 0x01, "Start RTP" },
215     { 0x02, "Stop RTP" },
216     { 0, NULL }
217 };
218
219 static const value_string szNoeVoiceMode[] =
220 {
221     { 0x10, "Disable" },
222     { 0x11, "Handset" },
223     { 0x13, "Speaker" },
224     { 0, NULL }
225 };
226
227 /**
228 * TLV PROPERTY
229 */
230 static const value_string szTlvProperty[] =
231 {
232     { 8,   "Count" },
233     { 11,  "NavigatorOwnerShip" },
234     { 15,  "NumpadEvent" },
235     { 16,  "Format_16" },
236     { 18,  "W" },
237     { 19,  "Hour" },
238     { 24,  "Year" },
239     { 25,  "Month" },
240     { 26,  "Day" },
241     { 27,  "Minutes" },
242     { 28,  "Seconds" },
243     { 36,  "AnchorID" },
244     { 39,  "Y" },
245     { 40,  "Visible" },
246     { 42,  "FontID" },
247     { 44,  "HAlign" },
248     { 54,  "Icon_54" },
249     { 55,  "Label" },
250     { 56,  "Value" },
251     { 61,  "Focus" },
252     { 62,  "State_62" },
253     { 63,  "Format_63" },
254     { 76,  "VSplit" },
255     { 78,  "RealCount" },
256     { 79,  "Start" },
257     { 95,  "_95" },
258     { 131, "Key Ownership" },
259     { 134, "Mode" },
260     { 135, "Color" },
261     { 137, "Icon_137" },
262     { 138, "Label_138" },
263     { 141, "State_141" },
264     { 142, "Name" },
265     { 143, "Number" },
266     { 147, "Today" },
267     { 148, "Tomorrow" },
268     { 0, NULL }
269 };
270
271 /************************************************************
272 * Check whether it can be protocol data
273 ************************************************************/
274 gboolean is_ua(tvbuff_t *tvb)
275 {
276     gint nLen, iOffs;
277     gint nNoeLen;
278
279     nLen = tvb_length(tvb);
280     for(iOffs = 0; iOffs < nLen; )
281     {
282         nNoeLen = tvb_get_letohs(tvb, iOffs) +2;
283         if(nNoeLen > nLen -iOffs)
284             return FALSE;
285         iOffs += nNoeLen;
286     }
287     return TRUE;
288 }
289
290 /************************************************************
291 * Dissectors
292 ************************************************************/
293
294 /*
295 * DissectUA - The dissector for UA (Universal Alcatel Protocol)
296 */
297 static int DissectUA(tvbuff_t *pTvb, packet_info *pInfo, proto_tree *pTree)
298 {
299     gint        nLen, iOffs;
300     guint       nNoeLen;
301     proto_item *pRootUA;
302     proto_tree *pSubTreeUA;
303     tvbuff_t   *pTvbNoe;
304
305     /* Check whether it can be protocol data */
306     if(!is_ua(pTvb))
307         return 0;
308
309     /* INFO column */
310     col_append_str(pInfo->cinfo, COL_INFO, " - UA");
311
312     nLen = tvb_length(pTvb);
313     if(pTree)
314     {
315         /* root element "UA Protocol, ..." */
316         pRootUA = proto_tree_add_item(pTree, proto_ua, pTvb, 0, -1, ENC_NA);
317         pSubTreeUA = proto_item_add_subtree(pRootUA, ett_ua);
318
319         /* NOE items */
320         for(iOffs = 0; iOffs < nLen; )
321         {
322             nNoeLen = tvb_get_letohs(pTvb, iOffs);
323             nNoeLen += 2;
324
325             pTvbNoe = tvb_new_subset(pTvb, iOffs, nNoeLen, nNoeLen);
326             DissectNOE(pTvbNoe, pSubTreeUA);
327
328             iOffs += nNoeLen;
329         }
330     }
331
332     return nLen;
333 }
334
335
336 /**********************************************
337 * NOE section
338 ***********************************************
339 Noe
340 NoeVoiceMode
341 NoeMute
342 NoeIP
343 NoeIPStartRTP
344 NoeCallServer
345 NoeCallServerCreate
346 NoeCallServerSetProperty
347 NoeCallServerNotify
348 NoeCallServerNotifyKeyPress
349 NoeCallServerNotifyKeyShortPress
350 ***********************************************/
351 static void DissectNOE(tvbuff_t *pTvb, proto_tree *pRootUA)
352 {
353     proto_item *pNoeItem = proto_tree_add_item(pRootUA, hf_noe, pTvb, 0, -1, ENC_NA);
354     if(pNoeItem)
355     {
356         proto_tree* pSubTreeNOE;
357
358         pSubTreeNOE = proto_item_add_subtree(pNoeItem, ett_noe);
359         proto_tree_add_item(pSubTreeNOE, hf_noe_length, pTvb, 0, 2, ENC_LITTLE_ENDIAN);
360         DissectNOE_type(tvb_new_subset_remaining(pTvb, 2), pSubTreeNOE);
361     }
362 }
363
364 static void DissectNOE_type(tvbuff_t *pTvb, proto_tree *pNoeItem)
365 {
366     proto_item_append_text(pNoeItem, ": %s", val_to_str_const(tvb_get_guint8(pTvb, 0), szNoeType, "Unknown"));
367     proto_tree_add_item(pNoeItem, hf_noe_type, pTvb, 0, 1, ENC_NA);
368
369     switch(tvb_get_guint8(pTvb, 0))
370     {
371     case 0x13: /*IP*/
372         {
373             DissectNOE_ip(tvb_new_subset_remaining(pTvb, 1), pNoeItem);
374             break;
375         }
376     case 0x15: /*CallServer*/
377         {
378             DissectNOE_callserver(tvb_new_subset_remaining(pTvb, 1), pNoeItem);
379             break;
380         }
381     case 0x29: /*VoiceMode*/
382         {
383             DissectNOE_voicemode(tvb_new_subset_remaining(pTvb, 1), pNoeItem);
384             break;
385         }
386     }
387 }
388
389 static void DissectNOE_voicemode(tvbuff_t *pTvb, proto_tree *pNoeItem)
390 {
391     proto_tree_add_item(pNoeItem, hf_noe_voicemode, pTvb, 0, 1, ENC_NA);
392     if(tvb_length(pTvb) > 1)
393         proto_tree_add_item(pNoeItem, hf_noe_data, pTvb, 1, -1, ENC_NA);
394 }
395
396 static void DissectNOE_callserver(tvbuff_t *pTvb, proto_tree *pNoeItem)
397 {
398     tvbuff_t *pTvbTlv;
399
400     gint nLen;
401     guint8 u8Method;
402
403     nLen = tvb_length(pTvb);
404     u8Method = tvb_get_guint8(pTvb, 0);
405
406     proto_item_append_text(pNoeItem, ", %s", val_to_str(u8Method, szCallServerMethod, "Unknown"));
407     proto_tree_add_item(pNoeItem, hf_noe_method, pTvb, 0, 1, ENC_NA);
408
409     switch(u8Method)
410     {
411     case 0x00: /*Create*/
412     case 0x01: /*Delete*/
413     case 0x02: /*SetProperty*/
414         {
415             guint8 u8Class; gint iOffs;
416
417             u8Class = tvb_get_guint8(pTvb, 1);
418             proto_item_append_text(pNoeItem, ", %s", val_to_str(u8Class, szCallServerClass, "Unknown"));
419             proto_tree_add_item(pNoeItem, hf_noe_class, pTvb, 1, 1, ENC_NA);
420
421             iOffs = 2;
422             if(u8Class >= 100)
423             {
424                 proto_item_append_text(pNoeItem, ", Id(0x%04x)", tvb_get_ntohs(pTvb, 2));
425                 proto_tree_add_item(pNoeItem, hf_noe_objid, pTvb, 2, 2, ENC_LITTLE_ENDIAN);
426                 iOffs += 2;
427             }
428
429             /* TLV items */
430             for(; iOffs < nLen; )
431             {
432                 guint    nTlvLen;
433                 guint8   nTlvProperty;
434                 gboolean bIsArrIndex;
435
436                 nTlvProperty = tvb_get_guint8(pTvb, iOffs);
437                 /* for property of more than 100 and equal 120 before the field is still arrindex propsize */
438                 if((nTlvProperty < 100) || (nTlvProperty == 120))
439                 {
440                     nTlvLen = tvb_get_guint8(pTvb, iOffs+1);
441                     nTlvLen += 2;
442                     bIsArrIndex = FALSE;
443                 }
444                 else
445                 {
446                     nTlvLen = tvb_get_guint8(pTvb, iOffs+2);
447                     nTlvLen += 3;
448                     bIsArrIndex = TRUE;
449                 }
450                 pTvbTlv = tvb_new_subset(pTvb, iOffs, nTlvLen, nTlvLen);
451                 DissectTLV(pTvbTlv, pNoeItem, bIsArrIndex);
452
453                 iOffs += nTlvLen;
454             }
455             break;
456         }
457     case 0x04: /*Notify*/
458         {
459             guint8 u8Event;
460
461             u8Event = tvb_get_guint8(pTvb, 1);
462             proto_tree_add_item(pNoeItem, hf_noe_event, pTvb, 1, 1, ENC_NA);
463
464             switch(u8Event)
465             {
466             case 2: /*KeyPress*/
467                 {
468                     proto_tree_add_item(pNoeItem, hf_noe_keychar, pTvb, 2, -1, ENC_NA);
469                     break;
470                 }
471             case 4: /*KeyShortPress*/
472                 {
473                     proto_tree_add_item(pNoeItem, hf_noe_keychar, pTvb, 2, 2, ENC_NA);
474                     break;
475                 }
476             }
477             break;
478         }
479     }
480 }
481
482 static void DissectNOE_ip(tvbuff_t *pTvb, proto_tree *pNoeItem)
483 {
484     guint8 u8Action;
485
486     /* Action */
487     u8Action = tvb_get_guint8(pTvb, 0);
488     proto_item_append_text(pNoeItem, " %s", val_to_str(u8Action, szNoeAction, "Unknown"));
489     proto_tree_add_item(pNoeItem, hf_noe_action, pTvb, 0, 1, ENC_NA);
490
491     switch(u8Action)
492     {
493     case 0x01: /*Start RTP*/
494         {
495             DissectNOE_ip_startrtp(tvb_new_subset_remaining(pTvb, 1), pNoeItem);
496             break;
497         }
498     case 0x02: /*Stop RTP*/
499         {
500             break;
501         }
502     }
503 }
504
505 static void DissectNOE_ip_startrtp(tvbuff_t *pTvb, proto_tree *pNoeItem)
506 {
507     gint nLen, iOffs;
508     nLen = tvb_length(pTvb);
509
510     /*Reserved*/
511     proto_tree_add_item(pNoeItem, hf_noe_reserved, pTvb, 0, 1, ENC_NA);
512
513     /*Properties*/
514     for(iOffs = 1; iOffs < nLen; )
515     {
516         guint     u8PropSize;
517         tvbuff_t *pTvbTlv;
518
519         u8PropSize = tvb_get_guint8(pTvb, iOffs+1) + 2;
520         pTvbTlv = tvb_new_subset(pTvb, iOffs, u8PropSize, u8PropSize);
521
522         DissectNOE_ip_startrtp_properties(pTvbTlv, pNoeItem);
523         iOffs += u8PropSize;
524     }
525 }
526
527 static void DissectNOE_ip_startrtp_properties(tvbuff_t *pTvb, proto_tree *pNoeItem)
528 {
529     proto_item *pProp;
530
531     pProp = proto_tree_add_item(pNoeItem, hf_noe_property, pTvb, 0, -1, ENC_NA);
532     if(pProp)
533     {
534         guint8 u8ID, u8Size;
535         proto_tree* pSubTreeProp;
536
537         pSubTreeProp = proto_item_add_subtree(pProp, ett_noe_property);
538         /*ID*/
539         u8ID = tvb_get_guint8(pTvb, 0);
540         proto_item_append_text(pProp, " - %25s", val_to_str(u8ID, szStartRtpPropID, "Unknown"));
541         proto_tree_add_item(pSubTreeProp, hf_noe_id, pTvb, 0, 1, ENC_NA);
542
543         /*SIZE*/
544         u8Size = tvb_get_guint8(pTvb, 1);
545         proto_tree_add_item(pSubTreeProp, hf_noe_size, pTvb, 1, 1, ENC_NA);
546
547         /*data*/
548         switch(u8ID)
549         {
550         default:
551             {
552                 proto_item_append_text(pProp, ": %s", tvb_bytes_to_str(pTvb, 2, u8Size));
553                 proto_tree_add_item(pSubTreeProp, hf_noe_data, pTvb, 2, -1, ENC_NA);
554                 break;
555             }
556         case 0x00: /*LocalUDPPort*/
557             {
558                 proto_item_append_text(pProp, ": %u", tvb_get_ntohs(pTvb, 2));
559                 proto_tree_add_item(pSubTreeProp, hf_noe_local_port, pTvb, 2, -1, ENC_LITTLE_ENDIAN);
560                 break;
561             }
562         case 0x01: /*RemoteIP*/
563             {
564                 proto_item_append_text(pProp, ": %s", tvb_ip_to_str(pTvb, 2));
565                 proto_tree_add_item(pSubTreeProp, hf_noe_remote_ip, pTvb, 2, -1, ENC_NA);
566                 break;
567             }
568         case 0x02: /*RemoteUDPPort*/
569             {
570                 proto_item_append_text(pProp, ": %u", tvb_get_ntohs(pTvb, 2));
571                 proto_tree_add_item(pSubTreeProp, hf_noe_remote_port, pTvb, 2, -1, ENC_LITTLE_ENDIAN);
572                 break;
573             }
574         case 0x03: /*TypeOfService*/
575             {
576                 proto_item_append_text(pProp, ": %u", tvb_get_guint8(pTvb, 2));
577                 proto_tree_add_item(pSubTreeProp, hf_noe_typeofservice, pTvb, 2, -1, ENC_NA);
578                 break;
579             }
580         case 0x04: /*Payload*/
581             {
582                 proto_item_append_text(pProp, ": %s", val_to_str_const(tvb_get_guint8(pTvb, 2), szStartRtpPayload, "Unknown"));
583                 proto_tree_add_item(pSubTreeProp, hf_noe_compressor, pTvb, 2, -1, ENC_NA);
584                 break;
585             }
586         case 0x05: /*PayloadConcatenation*/
587             {
588                 proto_item_append_text(pProp, ": %u ms", tvb_get_guint8(pTvb, 2));
589                 proto_tree_add_item(pSubTreeProp, hf_noe_payloadconcat, pTvb, 2, -1, ENC_NA);
590                 break;
591             }
592         }
593     }
594 }
595
596 /***********************************************
597 * TLV section
598 ***********************************************/
599 static void DissectTLV(tvbuff_t *pTvb, proto_tree *pNoeItem, gboolean bIsArrIndex)
600 {
601     proto_item *pTlv;
602
603     pTlv = proto_tree_add_item(pNoeItem, hf_tlv, pTvb, 0, -1, ENC_NA);
604     if(pTlv)
605     {
606         gint iOffs;
607         guint8 u8Property, u8PropSize;
608         proto_tree* pSubTreeTLV;
609
610         iOffs = 0;
611         pSubTreeTLV = proto_item_add_subtree(pTlv, ett_tlv);
612         u8Property = tvb_get_guint8(pTvb, iOffs);
613         proto_item_append_text(pTlv, "%u %s ", u8Property, val_to_str(u8Property, szTlvProperty, "Unknown"));
614         proto_tree_add_item(pSubTreeTLV, hf_tlv_property, pTvb, iOffs++, 1, ENC_NA);
615
616         if(bIsArrIndex)
617             proto_tree_add_item(pTlv, hf_tlv_arrindex, pTvb, iOffs++, 1, ENC_NA);
618
619         u8PropSize = tvb_get_guint8(pTvb, iOffs);
620         proto_tree_add_item(pSubTreeTLV, hf_tlv_propsize, pTvb, iOffs++, 1, ENC_NA);
621
622         if(u8PropSize > 0)
623             DissectTLV_data(tvb_new_subset(pTvb, iOffs, u8PropSize, u8PropSize), pSubTreeTLV, u8Property);
624     }
625 }
626
627 /* TLV DATA */
628 static void DissectTLV_data(tvbuff_t *pTvb, proto_tree *pTlv, guint8 u8Property)
629 {
630     proto_tree* pNoeItem;
631     switch(u8Property)
632     {
633     default:
634         {
635             proto_item_append_text(pTlv, "%s", tvb_bytes_to_str(pTvb, 0, tvb_length(pTvb)));
636             proto_tree_add_item(pTlv, hf_tlv_data, pTvb, 0, -1, ENC_NA);
637             break;
638         }
639
640     case 24: /*Year*/
641         {
642             proto_item_append_text(pTlv, "%u", tvb_get_ntohs(pTvb, 0));
643             proto_tree_add_item(pTlv, hf_tlv_year, pTvb, 0, 2, ENC_BIG_ENDIAN);
644             break;
645         }
646
647     case 55: /*Label*/
648     case 138: /*Label_138*/
649         {
650             proto_item_append_text(pTlv, "'%s'", tvb_get_string(pTvb, 0, tvb_length(pTvb)));
651             proto_tree_add_item(pTlv, hf_tlv_label, pTvb, 0, -1, ENC_ASCII|ENC_NA);
652
653             /* append text on NOE level */
654             pNoeItem = proto_item_get_parent(pTlv);
655             proto_item_append_text(pNoeItem, ", Label='%s'", tvb_get_string(pTvb, 0, tvb_length(pTvb)));
656             break;
657         }
658
659     case 143: /*Phone number*/
660         {
661             proto_item_append_text(pTlv, "%s", tvb_get_string(pTvb, 0, tvb_length(pTvb)));
662             proto_tree_add_item(pTlv, hf_tlv_number, pTvb, 0, -1, ENC_NA);
663             break;
664         }
665
666     case 147: /*Today*/
667     case 148: /*Tomorrow*/
668         {
669             proto_item_append_text(pTlv, "'%s'", tvb_get_string(pTvb, 0, tvb_length(pTvb)));
670             proto_tree_add_item(pTlv, hf_tlv_data, pTvb, 0, -1, ENC_NA);
671             break;
672         }
673     }
674 }
675
676
677
678 /* Register all the bits needed by the filtering engine */
679 void proto_register_ua(void)
680 {
681     static hf_register_info hf[] =
682     {
683         { &hf_noe,
684           { "NOE", "ua.noe",
685             FT_NONE, BASE_NONE, NULL, 0x0,
686             NULL, HFILL }},
687         { &hf_noe_length,
688           { "Length", "ua.noe.length",
689             FT_UINT16, BASE_DEC, NULL, 0x0,
690             "NOE item length (without 2 bytes containing the length)", HFILL }},
691         { &hf_noe_type,
692           { "Type", "ua.noe.type",
693             FT_UINT8, BASE_DEC, VALS(szNoeType), 0x0,
694             "NOE item type", HFILL }},
695         { &hf_noe_method,
696           { "Method", "ua.noe.method",
697             FT_UINT8, BASE_DEC, VALS(szCallServerMethod), 0x0,
698             "Call Server method", HFILL }},
699         { &hf_noe_class,
700           { "Class", "ua.noe.class",
701             FT_UINT8, BASE_DEC,             VALS(szCallServerClass), 0x0,
702             "Call Server class", HFILL }},
703         { &hf_noe_objid,
704           { "ObjectID", "ua.noe.objid",
705             FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
706             "Call Server object id", HFILL }},
707         { &hf_noe_event,
708           { "Event", "ua.noe.event",
709             FT_UINT8, BASE_DEC, VALS(szCallServerEvent), 0x0,
710             "Call Server event", HFILL }},
711         { &hf_noe_keychar,
712           { "KeyChar", "ua.noe.event.keychar",
713             FT_BYTES, BASE_NONE, NULL, 0x0,
714             "Event key char", HFILL }},
715         { &hf_noe_voicemode,
716           { "VoiceMode", "ua.noe.voicemode",
717             FT_UINT8, BASE_DEC, VALS(szNoeVoiceMode), 0x0,
718             NULL, HFILL }},
719
720         { &hf_noe_action,
721           { "Action", "ua.noe.action",
722             FT_UINT8, BASE_DEC, VALS(szNoeAction), 0x0,
723             "IP action", HFILL }},
724         { &hf_noe_reserved,
725           { "Reserved", "ua.noe.action.startrtp.reserved",
726             FT_UINT8, BASE_DEC, NULL, 0x0,
727             "IP start rtp reserved", HFILL }},
728         { &hf_noe_property,
729           { "Property", "ua.noe.action.startrtp.property",
730             FT_NONE, BASE_NONE, NULL, 0x0,
731             "IP property", HFILL }},
732         { &hf_noe_id,
733           { "ID", "ua.noe.action.startrtp.property.id",
734             FT_UINT8, BASE_DEC, VALS(szStartRtpPropID), 0x0,
735             "IP property id", HFILL }},
736         { &hf_noe_size,
737           { "Size", "ua.noe.action.startrtp.property.size",
738             FT_UINT8, BASE_DEC, NULL, 0x0,
739             "IP property size", HFILL }},
740         { &hf_noe_data,
741           { "Data", "ua.noe.action.startrtp.data",
742             FT_BYTES, BASE_NONE, NULL, 0x0,
743             NULL, HFILL }},
744
745         { &hf_noe_local_port,
746           { "LocalPort", "ua.noe.action.startrtp.localport",
747             FT_UINT16, BASE_DEC, NULL, 0x0,
748             "IP start rtp property localport", HFILL }},
749         { &hf_noe_remote_ip,
750           { "RemoteIP", "ua.noe.action.startrtp.remoteip",
751             FT_IPv4, BASE_NONE, NULL, 0x0,
752             "IP start rtp property remote ipv4", HFILL }},
753         { &hf_noe_remote_port,
754           { "RemotePort", "ua.noe.action.startrtp.remoteport",
755             FT_UINT16, BASE_DEC, NULL, 0x0,
756             "IP start rtp property remoteport", HFILL }},
757         { &hf_noe_compressor,
758           { "Payload", "ua.noe.action.startrtp.payload",
759             FT_UINT8, BASE_DEC, VALS(szStartRtpPayload), 0x0,
760             "IP start rtp property payload", HFILL }},
761         { &hf_noe_typeofservice,
762           { "TypeOfService", "ua.noe.action.startrtp.typeofservice",
763             FT_UINT8, BASE_DEC, NULL, 0x0,
764             "IP start rtp property type of service", HFILL }},
765         { &hf_noe_payloadconcat,
766           { "Payld Concat", "ua.noe.action.startrtp.payldconcat",
767             FT_UINT8, BASE_DEC, NULL, 0x0,
768             "IP start rtp property payload concatenation (in ms)", HFILL }},
769
770         { &hf_tlv,
771           { "TLV", "ua.noe.tlv",
772             FT_NONE, BASE_NONE, NULL, 0x0,
773             NULL, HFILL }},
774         { &hf_tlv_property,
775           { "Property", "ua.noe.tlv.property",
776             FT_UINT8, BASE_DEC, VALS(szTlvProperty), 0x0,
777             "TLV property", HFILL }},
778         { &hf_tlv_arrindex,
779           { "ArrIndex", "ua.noe.tlv.arrindex",
780             FT_UINT8, BASE_DEC, NULL, 0x0,
781             "TLV array index", HFILL }},
782         { &hf_tlv_propsize,
783           { "PropSize", "ua.noe.tlv.propsize",
784             FT_UINT8, BASE_DEC, NULL, 0x0,
785             "TLV property size", HFILL }},
786         { &hf_tlv_data,
787           { "Data", "ua.noe.tlv.data",
788             FT_BYTES, BASE_NONE, NULL, 0x0,
789             "TLV data", HFILL }},
790         { &hf_tlv_label,
791           { "Label", "ua.noe.tlv.label",
792             FT_STRING, BASE_NONE, NULL, 0x0,
793             "TLV label", HFILL }},
794         { &hf_tlv_year,
795           { "Year", "ua.noe.tlv.year",
796             FT_UINT16, BASE_DEC, NULL, 0x0,
797             "TLV year", HFILL }},
798         { &hf_tlv_number,
799           { "Number", "ua.noe.tlv.number",
800             FT_STRING, BASE_NONE, NULL, 0x0,
801             "TLV remote phone number", HFILL }},
802     };
803     static gint *ett[] =
804     {
805         &ett_ua,
806         &ett_noe,
807         &ett_noe_property,
808         &ett_tlv,
809         &ett_tlv_sub,
810     };
811
812     proto_ua = proto_register_protocol("UA Protocol (Universal Alcatel Protocol)", "UA", "ua");
813     proto_register_field_array(proto_ua, hf, array_length(hf));
814     proto_register_subtree_array(ett, array_length(ett));
815 }
816
817
818 /* The registration hand-off routine is called at startup */
819 void proto_reg_handoff_ua(void)
820 {
821     dissector_handle_t hDis = new_create_dissector_handle(DissectUA, proto_ua);
822     dissector_add_uint("uaudp.opcode", 7, hDis);
823 }
824 /*
825 * Editor modelines - http://www.wireshark.org/tools/modelines.html
826 *
827 * Local variables:
828 * c-basic-offset: 4
829 * tab-width: 8
830 * indent-tabs-mode: nil
831 * End:
832 *
833 * ex: set shiftwidth=4 tabstop=8 expandtab:
834 * :indentSize=4:tabSize=8:noTabs=true:
835 */