MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-uaudp.c
blob2bbbb99b3d6d9f9003f7b9eb9639e5e29b2781bd
1 /* packet-uaudp.c
2 * Routines for UA/UDP (Universal Alcatel over UDP) packet dissection.
3 * Copyright 2012, Alcatel-Lucent Enterprise <lars.ruoff@alcatel-lucent.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
30 #include "epan/packet.h"
31 #include "epan/prefs.h"
32 #include "epan/tap.h"
34 #include "packet-uaudp.h"
36 /* GLOBALS */
38 #if 0
39 static dissector_table_t uaudp_opcode_dissector_table;
40 #endif
42 #if 0
43 static int uaudp_tap = -1;
44 #endif
46 static tap_struct_uaudp ua_tap_info;
48 static int proto_uaudp = -1;
50 static int hf_uaudp_opcode = -1;
51 static int hf_uaudp_version = -1;
52 static int hf_uaudp_window_size = -1;
53 static int hf_uaudp_mtu = -1;
54 static int hf_uaudp_udp_lost = -1;
55 static int hf_uaudp_udp_lost_reinit = -1;
56 static int hf_uaudp_keepalive = -1;
57 static int hf_uaudp_qos_ip_tos = -1;
58 static int hf_uaudp_qos_8021_vlid = -1;
59 static int hf_uaudp_qos_8021_pri = -1;
60 static int hf_uaudp_expseq = -1;
61 static int hf_uaudp_sntseq = -1;
63 static gint ett_uaudp = -1;
65 /* pref */
66 static guint8 sys_ip[4];
67 static const char* pref_sys_ip_s = "";
69 static gboolean use_sys_ip = FALSE;
70 static gboolean decode_ua = TRUE;
72 static const value_string uaudp_opcode_str[] =
74 { UAUDP_CONNECT, "Connect" },
75 { UAUDP_CONNECT_ACK, "Connect ACK" },
76 { UAUDP_RELEASE, "Release" },
77 { UAUDP_RELEASE_ACK, "Release ACK" },
78 { UAUDP_KEEPALIVE, "Keepalive" },
79 { UAUDP_KEEPALIVE_ACK, "Keepalive ACK" },
80 { UAUDP_NACK, "NACK" },
81 { UAUDP_DATA, "Data" },
82 { 0, NULL }
84 value_string_ext uaudp_opcode_str_ext = VALUE_STRING_EXT_INIT(uaudp_opcode_str);
86 #if 0 /* XXX: Unused ? */
87 static const value_string uaudp_connect_vals[] =
89 { UAUDP_CONNECT_VERSION, "Version" },
90 { UAUDP_CONNECT_WINDOW_SIZE, "Window Size" },
91 { UAUDP_CONNECT_MTU, "MTU" },
92 { UAUDP_CONNECT_UDP_LOST, "UDP lost" },
93 { UAUDP_CONNECT_UDP_LOST_REINIT,"UDP lost reinit" },
94 { UAUDP_CONNECT_KEEPALIVE, "Keepalive" },
95 { UAUDP_CONNECT_QOS_IP_TOS, "QoS IP TOS" },
96 { UAUDP_CONNECT_QOS_8021_VLID, "QoS 802.1 VLID" },
97 { UAUDP_CONNECT_QOS_8021_PRI, "QoS 802.1 PRI"},
98 { 0, NULL }
100 value_string_ext uaudp_connect_vals_ext = VALUE_STRING_EXT_INIT(uaudp_connect_vals);
101 #endif
103 static dissector_handle_t ua_sys_to_term_handle;
104 static dissector_handle_t ua_term_to_sys_handle;
106 typedef struct
108 const char *name;
109 const char *text;
110 guint port;
111 guint last_port;
112 } prefs_uaudp_t;
114 static prefs_uaudp_t ports[] =
116 {"port1", "Terminal UDP port (setting 1)", 32000, 32000},
117 {"port2", "Terminal UDP port (setting 2)", 32512, 32512},
118 {"port3", "Terminal UDP port (setting 3)", 0, 0},
119 {"port4", "Terminal UDP port (setting 4)", 0, 0},
120 #if 0
121 {"port5", "Terminal UDP port (setting 5)", 0, 0},
122 {"port6", "Terminal UDP port (setting 6)", 0, 0},
123 {"port7", "Terminal UDP port (setting 7)", 0, 0},
124 {"port8", "Terminal UDP port (setting 8)", 0, 0}
125 #endif
127 #define MAX_TERMINAL_PORTS (signed)(array_length(ports))
129 static gboolean find_terminal_port(guint port)
131 int i;
132 for (i=0; i<MAX_TERMINAL_PORTS; i++)
133 if (ports[i].port == port)
134 return TRUE;
135 return FALSE;
139 static void rV(proto_tree *tree, int *V, tvbuff_t *tvb, gint offset, gint8 L)
141 switch(L)
143 case 1:
144 proto_tree_add_uint(tree,
146 tvb,
147 offset,
148 L+2,
149 tvb_get_guint8(tvb, offset+2));
150 break;
151 case 2:
152 proto_tree_add_uint(tree,
154 tvb,
155 offset,
156 L+2,
157 tvb_get_ntohs(tvb, offset+2));
158 break;
159 case 3:
160 proto_tree_add_uint(tree,
162 tvb,
163 offset,
164 L+2,
165 tvb_get_ntoh24(tvb, offset+2));
166 break;
167 case 4:
168 proto_tree_add_uint(tree,
170 tvb,
171 offset,
172 L+2,
173 tvb_get_ntohl(tvb, offset+2));
174 break;
179 /* UA/UDP DISSECTOR */
180 static void _dissect_uaudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
181 e_ua_direction direction)
183 gint offset = 0;
184 guint8 opcode;
185 proto_item *uaudp_item;
186 proto_tree *uaudp_tree;
188 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UAUDP");
190 /* get the identifier; it means operation code */
191 opcode = tvb_get_guint8(tvb, offset);
192 offset += 1;
194 ua_tap_info.opcode = opcode;
195 ua_tap_info.expseq = 0;
196 ua_tap_info.sntseq = 0;
198 /* print in "INFO" column the type of UAUDP message */
199 col_add_fstr(pinfo->cinfo,
200 COL_INFO,
201 "%s",
202 val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));
204 uaudp_item = proto_tree_add_protocol_format(tree, proto_uaudp, tvb, 0, 5,
205 "Universal Alcatel/UDP Encapsulation Protocol, %s",
206 val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));
208 uaudp_tree = proto_item_add_subtree(uaudp_item, ett_uaudp);
210 /* print the identifier */
211 proto_tree_add_uint(uaudp_tree, hf_uaudp_opcode, tvb, 0, 1, opcode);
213 switch(opcode)
215 case UAUDP_CONNECT:
217 if (!tree)
218 break;
219 while (tvb_offset_exists(tvb, offset))
221 guint8 T = tvb_get_guint8(tvb, offset+0);
222 guint8 L = tvb_get_guint8(tvb, offset+1);
224 switch(T)
226 case UAUDP_CONNECT_VERSION:
227 rV(uaudp_tree, &hf_uaudp_version , tvb, offset, L);
228 break;
229 case UAUDP_CONNECT_WINDOW_SIZE:
230 rV(uaudp_tree, &hf_uaudp_window_size , tvb, offset, L);
231 break;
232 case UAUDP_CONNECT_MTU:
233 rV(uaudp_tree, &hf_uaudp_mtu , tvb, offset, L);
234 break;
235 case UAUDP_CONNECT_UDP_LOST:
236 rV(uaudp_tree, &hf_uaudp_udp_lost , tvb, offset, L);
237 break;
238 case UAUDP_CONNECT_UDP_LOST_REINIT:
239 rV(uaudp_tree, &hf_uaudp_udp_lost_reinit, tvb, offset, L);
240 break;
241 case UAUDP_CONNECT_KEEPALIVE:
242 rV(uaudp_tree, &hf_uaudp_keepalive , tvb, offset, L);
243 break;
244 case UAUDP_CONNECT_QOS_IP_TOS:
245 rV(uaudp_tree, &hf_uaudp_qos_ip_tos , tvb, offset, L);
246 break;
247 case UAUDP_CONNECT_QOS_8021_VLID:
248 rV(uaudp_tree, &hf_uaudp_qos_8021_vlid , tvb, offset, L);
249 break;
250 case UAUDP_CONNECT_QOS_8021_PRI:
251 rV(uaudp_tree, &hf_uaudp_qos_8021_pri , tvb, offset, L);
252 break;
254 offset += (2 + L);
256 break;
259 case UAUDP_NACK:
261 proto_tree_add_uint(uaudp_tree,
262 hf_uaudp_expseq,
263 tvb,
264 offset,
266 tvb_get_ntohs(tvb, offset));
267 break;
270 case UAUDP_DATA:
272 int datalen;
274 proto_tree_add_uint(uaudp_tree,
275 hf_uaudp_expseq,
276 tvb,
277 offset+0,
279 tvb_get_ntohs(tvb, offset+0));
281 proto_tree_add_uint(uaudp_tree,
282 hf_uaudp_sntseq,
283 tvb,
284 offset+2,
286 tvb_get_ntohs(tvb, offset+2));
288 ua_tap_info.expseq = hf_uaudp_expseq;
289 ua_tap_info.sntseq = hf_uaudp_sntseq;
291 offset += 4;
292 datalen = tvb_reported_length(tvb) - offset;
294 /* if there is remaining data, call the UA dissector */
295 if (datalen > 0)
297 if (direction == SYS_TO_TERM)
298 call_dissector(ua_sys_to_term_handle,
299 tvb_new_subset(tvb, offset, datalen, datalen),
300 pinfo,
301 tree);
302 else if (direction == TERM_TO_SYS)
303 call_dissector(ua_term_to_sys_handle,
304 tvb_new_subset(tvb, offset, datalen, datalen),
305 pinfo,
306 tree);
307 else {
308 /* XXX: expert ?? */
309 col_set_str(pinfo->cinfo,
310 COL_INFO,
311 "Data - Couldn't resolve direction. Check UAUDP Preferences.");
313 ua_tap_info.expseq = hf_uaudp_expseq;
315 else {
316 /* print in "INFO" column */
317 col_set_str(pinfo->cinfo,
318 COL_INFO,
319 "Data ACK");
321 break;
323 default:
324 break;
326 #if 0
327 tap_queue_packet(uaudp_tap, pinfo, &ua_tap_info);
328 #endif
331 #if 0
332 /* XXX: The following are never actually used ?? */
333 static void dissect_uaudp_dir_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
335 _dissect_uaudp(tvb, pinfo, tree, DIR_UNKNOWN);
338 static void dissect_uaudp_term_to_serv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
340 _dissect_uaudp(tvb, pinfo, tree, TERM_TO_SYS);
343 static void dissect_uaudp_serv_to_term(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
345 _dissect_uaudp(tvb, pinfo, tree, SYS_TO_TERM);
347 #endif
350 * UA/UDP DISSECTOR
351 Wireshark packet dissector entry point
353 static void dissect_uaudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
355 /* server address, if present, has precedence on ports */
356 if (use_sys_ip) {
357 /* use server address to find direction*/
358 if (memcmp((pinfo->src).data, sys_ip, 4*sizeof(guint8)) == 0)
360 _dissect_uaudp(tvb, pinfo, tree, SYS_TO_TERM);
361 return;
363 else if (memcmp((pinfo->dst).data, sys_ip, 4*sizeof(guint8)) == 0)
365 _dissect_uaudp(tvb, pinfo, tree, TERM_TO_SYS);
366 return;
370 /* use ports to find direction */
371 if (find_terminal_port(pinfo->srcport))
373 _dissect_uaudp(tvb, pinfo, tree, TERM_TO_SYS);
374 return;
376 else if (find_terminal_port(pinfo->destport))
378 _dissect_uaudp(tvb, pinfo, tree, SYS_TO_TERM);
379 return;
382 _dissect_uaudp(tvb, pinfo, tree, DIR_UNKNOWN);
385 /* XXX: Presumably there's a util fcn for this ... */
386 static gboolean str_to_addr_ip(const gchar *addr, guint8 *ad)
388 int i;
389 const gchar *p = addr;
390 guint32 value;
392 if (addr == NULL)
393 return FALSE;
395 for (i=0; i<4; i++)
397 value = 0;
398 while (*p != '.' && *p != '\0')
400 value = value * 10 + (*p - '0');
401 p++;
403 if (value > 255)
405 return FALSE;
407 ad[i] = value;
408 p++;
411 return TRUE;
415 /* Register the protocol with Wireshark */
416 void proto_reg_handoff_uaudp(void);
418 void proto_register_uaudp(void)
420 module_t *uaudp_module;
421 int i;
423 /* Setup list of header fields. See Section 1.6.1 for details */
424 static hf_register_info hf_uaudp[] = {
426 &hf_uaudp_opcode,
428 "Opcode",
429 "uaudp.opcode",
430 FT_UINT8,
431 BASE_DEC | BASE_EXT_STRING,
432 &uaudp_opcode_str_ext,
433 0x0,
434 "UA/UDP Opcode",
435 HFILL
439 &hf_uaudp_version,
441 "Version",
442 "uaudp.version",
443 FT_UINT8,
444 BASE_DEC,
445 NULL, 0x0,
446 "UA/UDP Version",
447 HFILL
451 &hf_uaudp_window_size,
453 "Window Size",
454 "uaudp.window_size",
455 FT_UINT8,
456 BASE_DEC,
457 NULL,
458 0x0,
459 "UA/UDP Window Size",
460 HFILL
464 &hf_uaudp_mtu,
466 "MTU",
467 "uaudp.mtu",
468 FT_UINT8,
469 BASE_DEC,
470 NULL,
471 0x0,
472 "UA/UDP MTU",
473 HFILL
477 &hf_uaudp_udp_lost,
479 "UDP Lost",
480 "uaudp.udp_lost",
481 FT_UINT8,
482 BASE_DEC,
483 NULL,
484 0x0,
485 "UA/UDP Lost",
486 HFILL
490 &hf_uaudp_udp_lost_reinit,
492 "UDP lost reinit",
493 "uaudp.udp_lost_reinit",
494 FT_UINT8,
495 BASE_DEC,
496 NULL, 0x0,
497 "UA/UDP Lost Re-Init",
498 HFILL
502 &hf_uaudp_keepalive,
504 "Keepalive",
505 "uaudp.keepalive",
506 FT_UINT8,
507 BASE_DEC,
508 NULL,
509 0x0,
510 "UA/UDP Keepalive",
511 HFILL
515 &hf_uaudp_qos_ip_tos,
517 "QoS IP TOS",
518 "uaudp.qos_ip_tos",
519 FT_UINT8,
520 BASE_DEC,
521 NULL,
522 0x0,
523 "UA/UDP QoS IP TOS",
524 HFILL
528 &hf_uaudp_qos_8021_vlid,
530 "QoS 802.1 VLID",
531 "uaudp.qos_8021_vlid",
532 FT_UINT8,
533 BASE_DEC,
534 NULL,
535 0x0,
536 "UA/UDP QoS 802.1 VLID",
537 HFILL
541 &hf_uaudp_qos_8021_pri,
543 "QoS 802.1 PRI",
544 "uaudp.qos_8021_pri",
545 FT_UINT8,
546 BASE_DEC,
547 NULL,
548 0x0,
549 "UA/UDP QoS 802.1 PRI",
550 HFILL
554 &hf_uaudp_expseq,
556 "Sequence Number (expected)",
557 "uaudp.expseq",
558 FT_UINT16,
559 BASE_DEC,
560 NULL,
561 0x0,
562 "UA/UDP Expected Sequence Number",
563 HFILL
567 &hf_uaudp_sntseq,
569 "Sequence Number (sent)",
570 "uaudp.sntseq",
571 FT_UINT16,
572 BASE_DEC,
573 NULL,
574 0x0,
575 "UA/UDP Sent Sequence Number",
576 HFILL
581 /* Setup protocol subtree array */
582 static gint *ett[] =
584 &ett_uaudp,
587 /* Register the protocol name and description */
588 proto_uaudp = proto_register_protocol("UA/UDP Encapsulation Protocol",
589 "UAUDP",
590 "uaudp");
592 register_dissector("uaudp", dissect_uaudp, proto_uaudp);
593 #if 0 /* XXX: Not used ?? */
594 register_dissector("uaudp_dir_unknown", dissect_uaudp_dir_unknown, proto_uaudp);
595 register_dissector("uaudp_term_to_serv", dissect_uaudp_term_to_serv, proto_uaudp);
596 register_dissector("uaudp_serv_to_term", dissect_uaudp_serv_to_term, proto_uaudp);
597 #endif
599 proto_register_field_array(proto_uaudp, hf_uaudp, array_length(hf_uaudp));
600 proto_register_subtree_array(ett, array_length(ett));
602 /* Register preferences */
603 uaudp_module = prefs_register_protocol(proto_uaudp, proto_reg_handoff_uaudp);
605 #if 0
606 prefs_register_bool_preference(uaudp_module, "enable",
607 "Enable UA/UDP decoding based on preferences",
608 "Enable UA/UDP decoding based on preferences",
609 &decode_ua);
610 #endif
611 for (i=0; i<MAX_TERMINAL_PORTS; i++) {
612 prefs_register_uint_preference(uaudp_module,
613 ports[i].name,
614 ports[i].text,
615 ports[i].text,
617 &ports[i].port);
619 prefs_register_string_preference(uaudp_module, "system_ip",
620 "System IP Address (optional)",
621 "IPv4 address of the DHS3 system."
622 " (Used only in case of identical source and destination ports)",
623 &pref_sys_ip_s);
625 #if 0
626 /* Register tap */
627 uaudp_tap = register_tap("uaudp");*/
628 #endif
632 void proto_reg_handoff_uaudp(void)
634 static gboolean prefs_initialized = FALSE;
635 static dissector_handle_t uaudp_handle;
636 int i;
638 if (!prefs_initialized)
640 uaudp_handle = find_dissector("uaudp");
641 ua_sys_to_term_handle = find_dissector("ua_sys_to_term");
642 ua_term_to_sys_handle = find_dissector("ua_term_to_sys");
643 #if 0
644 uaudp_opcode_dissector_table =
645 register_dissector_table("uaudp.opcode",
646 "UAUDP opcode",
647 FT_UINT8,
648 BASE_DEC);
649 #endif
650 prefs_initialized = TRUE;
652 else
654 for (i=0; i<MAX_TERMINAL_PORTS; i++)
656 if (ports[i].last_port)
657 dissector_delete_uint("udp.port", ports[i].last_port, uaudp_handle);
659 if (str_to_addr_ip(pref_sys_ip_s, sys_ip))
661 use_sys_ip = TRUE;
663 else
665 use_sys_ip = FALSE;
666 pref_sys_ip_s = "";
670 if (decode_ua)
672 int no_ports_registered = TRUE;
674 for (i=0; i < MAX_TERMINAL_PORTS; i++)
676 if (ports[i].port)
678 dissector_add_uint("udp.port", ports[i].port, uaudp_handle);
679 no_ports_registered = FALSE;
681 ports[i].last_port = ports[i].port;
684 if (no_ports_registered)
686 /* If all ports are set to 0, then just register the handle so
687 * at least "Decode As..." will work. */
688 dissector_add_handle("udp.port", uaudp_handle);