2 * Routines for UA/UDP (Universal Alcatel over UDP) packet dissection.
3 * Copyright 2012, Alcatel-Lucent Enterprise <lars.ruoff@alcatel-lucent.com>
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.
30 #include "epan/packet.h"
31 #include "epan/prefs.h"
34 #include "packet-uaudp.h"
39 static dissector_table_t uaudp_opcode_dissector_table
;
43 static int uaudp_tap
= -1;
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;
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" },
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"},
100 value_string_ext uaudp_connect_vals_ext
= VALUE_STRING_EXT_INIT(uaudp_connect_vals
);
103 static dissector_handle_t ua_sys_to_term_handle
;
104 static dissector_handle_t ua_term_to_sys_handle
;
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},
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}
127 #define MAX_TERMINAL_PORTS (signed)(array_length(ports))
129 static gboolean
find_terminal_port(guint port
)
132 for (i
=0; i
<MAX_TERMINAL_PORTS
; i
++)
133 if (ports
[i
].port
== port
)
139 static void rV(proto_tree
*tree
, int *V
, tvbuff_t
*tvb
, gint offset
, gint8 L
)
144 proto_tree_add_uint(tree
,
149 tvb_get_guint8(tvb
, offset
+2));
152 proto_tree_add_uint(tree
,
157 tvb_get_ntohs(tvb
, offset
+2));
160 proto_tree_add_uint(tree
,
165 tvb_get_ntoh24(tvb
, offset
+2));
168 proto_tree_add_uint(tree
,
173 tvb_get_ntohl(tvb
, offset
+2));
179 /* UA/UDP DISSECTOR */
180 static void _dissect_uaudp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
181 e_ua_direction direction
)
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
);
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
,
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
);
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);
226 case UAUDP_CONNECT_VERSION
:
227 rV(uaudp_tree
, &hf_uaudp_version
, tvb
, offset
, L
);
229 case UAUDP_CONNECT_WINDOW_SIZE
:
230 rV(uaudp_tree
, &hf_uaudp_window_size
, tvb
, offset
, L
);
232 case UAUDP_CONNECT_MTU
:
233 rV(uaudp_tree
, &hf_uaudp_mtu
, tvb
, offset
, L
);
235 case UAUDP_CONNECT_UDP_LOST
:
236 rV(uaudp_tree
, &hf_uaudp_udp_lost
, tvb
, offset
, L
);
238 case UAUDP_CONNECT_UDP_LOST_REINIT
:
239 rV(uaudp_tree
, &hf_uaudp_udp_lost_reinit
, tvb
, offset
, L
);
241 case UAUDP_CONNECT_KEEPALIVE
:
242 rV(uaudp_tree
, &hf_uaudp_keepalive
, tvb
, offset
, L
);
244 case UAUDP_CONNECT_QOS_IP_TOS
:
245 rV(uaudp_tree
, &hf_uaudp_qos_ip_tos
, tvb
, offset
, L
);
247 case UAUDP_CONNECT_QOS_8021_VLID
:
248 rV(uaudp_tree
, &hf_uaudp_qos_8021_vlid
, tvb
, offset
, L
);
250 case UAUDP_CONNECT_QOS_8021_PRI
:
251 rV(uaudp_tree
, &hf_uaudp_qos_8021_pri
, tvb
, offset
, L
);
261 proto_tree_add_uint(uaudp_tree
,
266 tvb_get_ntohs(tvb
, offset
));
274 proto_tree_add_uint(uaudp_tree
,
279 tvb_get_ntohs(tvb
, offset
+0));
281 proto_tree_add_uint(uaudp_tree
,
286 tvb_get_ntohs(tvb
, offset
+2));
288 ua_tap_info
.expseq
= hf_uaudp_expseq
;
289 ua_tap_info
.sntseq
= hf_uaudp_sntseq
;
292 datalen
= tvb_reported_length(tvb
) - offset
;
294 /* if there is remaining data, call the UA dissector */
297 if (direction
== SYS_TO_TERM
)
298 call_dissector(ua_sys_to_term_handle
,
299 tvb_new_subset(tvb
, offset
, datalen
, datalen
),
302 else if (direction
== TERM_TO_SYS
)
303 call_dissector(ua_term_to_sys_handle
,
304 tvb_new_subset(tvb
, offset
, datalen
, datalen
),
309 col_set_str(pinfo
->cinfo
,
311 "Data - Couldn't resolve direction. Check UAUDP Preferences.");
313 ua_tap_info
.expseq
= hf_uaudp_expseq
;
316 /* print in "INFO" column */
317 col_set_str(pinfo
->cinfo
,
327 tap_queue_packet(uaudp_tap
, pinfo
, &ua_tap_info
);
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
);
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 */
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
);
363 else if (memcmp((pinfo
->dst
).data
, sys_ip
, 4*sizeof(guint8
)) == 0)
365 _dissect_uaudp(tvb
, pinfo
, tree
, TERM_TO_SYS
);
370 /* use ports to find direction */
371 if (find_terminal_port(pinfo
->srcport
))
373 _dissect_uaudp(tvb
, pinfo
, tree
, TERM_TO_SYS
);
376 else if (find_terminal_port(pinfo
->destport
))
378 _dissect_uaudp(tvb
, pinfo
, tree
, SYS_TO_TERM
);
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
)
389 const gchar
*p
= addr
;
398 while (*p
!= '.' && *p
!= '\0')
400 value
= value
* 10 + (*p
- '0');
415 /* Register the protocol with Wireshark */
416 void proto_reg_handoff_uaudp(void);
418 void proto_register_uaudp(void)
420 module_t
*uaudp_module
;
423 /* Setup list of header fields. See Section 1.6.1 for details */
424 static hf_register_info hf_uaudp
[] = {
431 BASE_DEC
| BASE_EXT_STRING
,
432 &uaudp_opcode_str_ext
,
451 &hf_uaudp_window_size
,
459 "UA/UDP Window Size",
490 &hf_uaudp_udp_lost_reinit
,
493 "uaudp.udp_lost_reinit",
497 "UA/UDP Lost Re-Init",
515 &hf_uaudp_qos_ip_tos
,
528 &hf_uaudp_qos_8021_vlid
,
531 "uaudp.qos_8021_vlid",
536 "UA/UDP QoS 802.1 VLID",
541 &hf_uaudp_qos_8021_pri
,
544 "uaudp.qos_8021_pri",
549 "UA/UDP QoS 802.1 PRI",
556 "Sequence Number (expected)",
562 "UA/UDP Expected Sequence Number",
569 "Sequence Number (sent)",
575 "UA/UDP Sent Sequence Number",
581 /* Setup protocol subtree array */
587 /* Register the protocol name and description */
588 proto_uaudp
= proto_register_protocol("UA/UDP Encapsulation Protocol",
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
);
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
);
606 prefs_register_bool_preference(uaudp_module
, "enable",
607 "Enable UA/UDP decoding based on preferences",
608 "Enable UA/UDP decoding based on preferences",
611 for (i
=0; i
<MAX_TERMINAL_PORTS
; i
++) {
612 prefs_register_uint_preference(uaudp_module
,
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)",
627 uaudp_tap
= register_tap("uaudp");*/
632 void proto_reg_handoff_uaudp(void)
634 static gboolean prefs_initialized
= FALSE
;
635 static dissector_handle_t uaudp_handle
;
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");
644 uaudp_opcode_dissector_table
=
645 register_dissector_table("uaudp.opcode",
650 prefs_initialized
= TRUE
;
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
))
672 int no_ports_registered
= TRUE
;
674 for (i
=0; i
< MAX_TERMINAL_PORTS
; i
++)
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
);