2 * Routines for LBM PDM-over-TCP Packet dissection
4 * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
18 #include "packet-tcp.h"
19 #include "packet-lbm.h"
21 void proto_register_lbmpdm_tcp(void);
22 void proto_reg_handoff_lbmpdm_tcp(void);
25 static int lbmpdm_tcp_protocol_handle
= -1;
27 /* Dissector handle */
28 static dissector_handle_t lbmpdm_tcp_dissector_handle
;
30 /*----------------------------------------------------------------------------*/
31 /* LBM-TCP transport management. */
32 /*----------------------------------------------------------------------------*/
43 static void lbmtcp_order_key(lbmtcp_transport_t
* transport
)
48 /* Order the key so that addr1:port1 <= addr2:port2 */
49 compare
= cmp_address(&(transport
->addr1
), &(transport
->addr2
));
54 else if (compare
== 0)
56 if (transport
->port1
> transport
->port2
)
66 copy_address_shallow(&addr
, &(transport
->addr1
));
67 copy_address_shallow(&(transport
->addr2
), &(transport
->addr1
));
68 copy_address_shallow(&(transport
->addr1
), &addr
);
69 port
= transport
->port2
;
70 transport
->port2
= transport
->port1
;
71 transport
->port1
= port
;
75 static lbmtcp_transport_t
* lbmtcp_transport_add(const address
* address1
, uint16_t port1
, const address
* address2
, uint16_t port2
, uint32_t frame
)
77 lbmtcp_transport_t
* entry
;
78 conversation_t
* conv
= NULL
;
80 conv
= find_conversation(frame
, address1
, address2
, CONVERSATION_TCP
, port1
, port2
, 0);
83 conv
= conversation_new(frame
, address1
, address2
, CONVERSATION_TCP
, port1
, port2
, 0);
85 entry
= (lbmtcp_transport_t
*) conversation_get_proto_data(conv
, lbmpdm_tcp_protocol_handle
);
90 entry
= wmem_new(wmem_file_scope(), lbmtcp_transport_t
);
91 copy_address_wmem(wmem_file_scope(), &(entry
->addr1
), address1
);
93 copy_address_wmem(wmem_file_scope(), &(entry
->addr2
), address2
);
95 lbmtcp_order_key(entry
);
96 entry
->channel
= lbm_channel_assign(LBM_CHANNEL_TCP
);
97 conversation_add_proto_data(conv
, lbmpdm_tcp_protocol_handle
, (void *) entry
);
101 /*----------------------------------------------------------------------------*/
103 /*----------------------------------------------------------------------------*/
105 /* Preferences default values. */
106 #define LBMPDM_TCP_DEFAULT_PORT_LOW 14371
107 #define LBMPDM_TCP_DEFAULT_PORT_HIGH 14390
109 /* Global preferences variables (altered by the preferences dialog). */
110 static uint32_t global_lbmpdm_tcp_port_low
= LBMPDM_TCP_DEFAULT_PORT_LOW
;
111 static uint32_t global_lbmpdm_tcp_port_high
= LBMPDM_TCP_DEFAULT_PORT_HIGH
;
112 static bool global_lbmpdm_tcp_use_tag
;
114 /* Local preferences variables (used by the dissector). */
115 static uint32_t lbmpdm_tcp_port_low
= LBMPDM_TCP_DEFAULT_PORT_LOW
;
116 static uint32_t lbmpdm_tcp_port_high
= LBMPDM_TCP_DEFAULT_PORT_HIGH
;
117 static bool lbmpdm_tcp_use_tag
;
119 /* Tag definitions. */
125 } lbmpdm_tcp_tag_entry_t
;
127 static lbmpdm_tcp_tag_entry_t
* lbmpdm_tcp_tag_entry
;
128 static unsigned lbmpdm_tcp_tag_count
;
130 UAT_CSTRING_CB_DEF(lbmpdm_tcp_tag
, name
, lbmpdm_tcp_tag_entry_t
)
131 UAT_DEC_CB_DEF(lbmpdm_tcp_tag
, port_low
, lbmpdm_tcp_tag_entry_t
)
132 UAT_DEC_CB_DEF(lbmpdm_tcp_tag
, port_high
, lbmpdm_tcp_tag_entry_t
)
133 static uat_field_t lbmpdm_tcp_tag_array
[] =
135 UAT_FLD_CSTRING(lbmpdm_tcp_tag
, name
, "Tag name", "Tag name"),
136 UAT_FLD_DEC(lbmpdm_tcp_tag
, port_low
, "Port low", "Port low"),
137 UAT_FLD_DEC(lbmpdm_tcp_tag
, port_high
, "Port high", "Port high"),
141 /*----------------------------------------------------------------------------*/
142 /* UAT callback functions. */
143 /*----------------------------------------------------------------------------*/
144 static bool lbmpdm_tcp_tag_update_cb(void * record
, char * * error_string
)
146 lbmpdm_tcp_tag_entry_t
* tag
= (lbmpdm_tcp_tag_entry_t
*)record
;
148 if (tag
->name
== NULL
)
150 *error_string
= g_strdup("Tag name can't be empty");
155 g_strstrip(tag
->name
);
156 if (tag
->name
[0] == 0)
158 *error_string
= g_strdup("Tag name can't be empty");
165 static void * lbmpdm_tcp_tag_copy_cb(void * destination
, const void * source
, size_t length _U_
)
167 const lbmpdm_tcp_tag_entry_t
* src
= (const lbmpdm_tcp_tag_entry_t
*)source
;
168 lbmpdm_tcp_tag_entry_t
* dest
= (lbmpdm_tcp_tag_entry_t
*)destination
;
170 dest
->name
= g_strdup(src
->name
);
171 dest
->port_low
= src
->port_low
;
172 dest
->port_high
= src
->port_high
;
176 static void lbmpdm_tcp_tag_free_cb(void * record
)
178 lbmpdm_tcp_tag_entry_t
* tag
= (lbmpdm_tcp_tag_entry_t
*)record
;
180 if (tag
->name
!= NULL
)
187 static const lbmpdm_tcp_tag_entry_t
* lbmpdm_tcp_tag_locate(packet_info
* pinfo
)
190 const lbmpdm_tcp_tag_entry_t
* tag
= NULL
;
192 if (!lbmpdm_tcp_use_tag
)
197 for (idx
= 0; idx
< lbmpdm_tcp_tag_count
; ++idx
)
199 tag
= &(lbmpdm_tcp_tag_entry
[idx
]);
200 if (((pinfo
->srcport
>= tag
->port_low
) && (pinfo
->srcport
<= tag
->port_high
))
201 || ((pinfo
->destport
>= tag
->port_low
) && (pinfo
->destport
<= tag
->port_high
)))
209 static char * lbmpdm_tcp_tag_find(packet_info
* pinfo
)
211 const lbmpdm_tcp_tag_entry_t
* tag
= NULL
;
213 if (!lbmpdm_tcp_use_tag
)
218 tag
= lbmpdm_tcp_tag_locate(pinfo
);
226 /*----------------------------------------------------------------------------*/
227 /* Handles of all types. */
228 /*----------------------------------------------------------------------------*/
230 /* Dissector tree handles */
231 static int ett_lbmpdm_tcp
;
233 /* Dissector field handles */
234 static int hf_lbmpdm_tcp_tag
;
235 static int hf_lbmpdm_tcp_channel
;
237 static unsigned get_lbmpdm_tcp_pdu_length(packet_info
* pinfo _U_
, tvbuff_t
* tvb
,
238 int offset
, void *data _U_
)
244 if (!lbmpdm_verify_payload(tvb
, offset
, &encoding
, &packet_len
))
251 static int dissect_lbmpdm_tcp_pdu(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * dissector_data _U_
)
253 proto_tree
* lbmpdm_tcp_tree
= NULL
;
254 proto_item
* ti
= NULL
;
255 lbmtcp_transport_t
* transport
= NULL
;
256 char * tag_name
= NULL
;
257 uint64_t channel
= LBM_CHANNEL_NO_CHANNEL
;
259 if (lbmpdm_tcp_use_tag
)
261 tag_name
= lbmpdm_tcp_tag_find(pinfo
);
263 if (tag_name
!= NULL
)
265 ti
= proto_tree_add_protocol_format(tree
, lbmpdm_tcp_protocol_handle
, tvb
, 0, -1, "LBMPDM-TCP Protocol (Tag: %s)", tag_name
);
269 ti
= proto_tree_add_protocol_format(tree
, lbmpdm_tcp_protocol_handle
, tvb
, 0, -1, "LBMPDM-TCP Protocol");
271 lbmpdm_tcp_tree
= proto_item_add_subtree(ti
, ett_lbmpdm_tcp
);
273 transport
= lbmtcp_transport_add(&(pinfo
->src
), pinfo
->srcport
, &(pinfo
->dst
), pinfo
->destport
, pinfo
->num
);
274 if (transport
!= NULL
)
276 channel
= transport
->channel
;
278 if (tag_name
!= NULL
)
280 proto_item
* item
= NULL
;
282 item
= proto_tree_add_string(lbmpdm_tcp_tree
, hf_lbmpdm_tcp_tag
, tvb
, 0, 0, tag_name
);
283 proto_item_set_generated(item
);
285 if (channel
!= LBM_CHANNEL_NO_CHANNEL
)
287 proto_item
* item
= NULL
;
289 item
= proto_tree_add_uint64(lbmpdm_tcp_tree
, hf_lbmpdm_tcp_channel
, tvb
, 0, 0, channel
);
290 proto_item_set_generated(item
);
292 return (lbmpdm_dissect_lbmpdm_payload(tvb
, 0, pinfo
, tree
, channel
));
296 * dissect_lbmpdm_tcp - The dissector for LBMPDM over TCP
298 static int dissect_lbmpdm_tcp(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
300 char * tag_name
= NULL
;
302 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LBMPDM-TCP");
303 col_clear(pinfo
->cinfo
, COL_INFO
);
304 if (lbmpdm_tcp_use_tag
)
306 tag_name
= lbmpdm_tcp_tag_find(pinfo
);
308 if (tag_name
!= NULL
)
310 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "[Tag: %s]", tag_name
);
312 col_set_fence(pinfo
->cinfo
, COL_INFO
);
313 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, lbmpdm_get_minimum_length(), /* Need at least the msglen */
314 get_lbmpdm_tcp_pdu_length
, dissect_lbmpdm_tcp_pdu
, NULL
);
315 return tvb_captured_length(tvb
);
318 static bool test_lbmpdm_tcp_packet(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * user_data _U_
)
323 /* Must be a TCP packet. */
324 if (pinfo
->ptype
!= PT_TCP
)
328 /* Destination address must be IPV4 and 4 bytes in length. */
329 if ((pinfo
->dst
.type
!= AT_IPv4
) || (pinfo
->dst
.len
!= 4))
333 if (!lbmpdm_verify_payload(tvb
, 0, &encoding
, &packet_len
))
337 if (lbmpdm_tcp_use_tag
)
339 if (lbmpdm_tcp_tag_find(pinfo
) != NULL
)
341 dissect_lbmpdm_tcp(tvb
, pinfo
, tree
, user_data
);
350 /* Source port or destination port must be in the specified range. */
351 if (!(((pinfo
->srcport
>= lbmpdm_tcp_port_low
) && (pinfo
->srcport
<= lbmpdm_tcp_port_high
))
352 || ((pinfo
->destport
>= lbmpdm_tcp_port_low
) && (pinfo
->destport
<= lbmpdm_tcp_port_high
))))
356 /* One of ours. Probably. */
357 dissect_lbmpdm_tcp(tvb
, pinfo
, tree
, user_data
);
361 /* Register all the bits needed with the filtering engine */
362 void proto_register_lbmpdm_tcp(void)
364 static hf_register_info hf
[] =
366 { &hf_lbmpdm_tcp_tag
,
367 { "Tag", "lbmpdm_tcp.tag", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
368 { &hf_lbmpdm_tcp_channel
,
369 { "Channel ID", "lbmpdm_tcp.channel", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
375 module_t
* lbmpdm_tcp_module
;
378 lbmpdm_tcp_protocol_handle
= proto_register_protocol("LBMPDM over TCP Protocol", "LBMPDM-TCP", "lbmpdm_tcp");
380 proto_register_field_array(lbmpdm_tcp_protocol_handle
, hf
, array_length(hf
));
381 proto_register_subtree_array(ett
, array_length(ett
));
383 lbmpdm_tcp_module
= prefs_register_protocol_subtree("29West", lbmpdm_tcp_protocol_handle
, proto_reg_handoff_lbmpdm_tcp
);
384 prefs_register_uint_preference(lbmpdm_tcp_module
,
386 "Port range low (default " MAKESTRING(LBMPDM_TCP_DEFAULT_PORT_LOW
)")",
387 "Set the low end of the TCP port range",
389 &global_lbmpdm_tcp_port_low
);
391 prefs_register_uint_preference(lbmpdm_tcp_module
,
393 "Port range high (default " MAKESTRING(LBMPDM_TCP_DEFAULT_PORT_HIGH
)")",
394 "Set the high end of the port range",
396 &global_lbmpdm_tcp_port_high
);
398 prefs_register_bool_preference(lbmpdm_tcp_module
,
399 "use_lbmpdm_tcp_domain",
400 "Use LBMPDM-TCP tag table",
401 "Use table of LBMPDM-TCP tags to decode the packet instead of above values",
402 &global_lbmpdm_tcp_use_tag
);
403 tag_uat
= uat_new("LBMPDM-TCP tag definitions",
404 sizeof(lbmpdm_tcp_tag_entry_t
),
405 "lbmpdm_tcp_domains",
407 (void * *)&lbmpdm_tcp_tag_entry
,
408 &lbmpdm_tcp_tag_count
,
409 UAT_AFFECTS_DISSECTION
,
411 lbmpdm_tcp_tag_copy_cb
,
412 lbmpdm_tcp_tag_update_cb
,
413 lbmpdm_tcp_tag_free_cb
,
416 lbmpdm_tcp_tag_array
);
417 prefs_register_uat_preference(lbmpdm_tcp_module
,
418 "tnw_lbmpdm_tcp_tags",
420 "A table to define LBMPDM-TCP tags",
423 lbmpdm_tcp_dissector_handle
= register_dissector("lbmpdm_tcp", dissect_lbmpdm_tcp
, lbmpdm_tcp_protocol_handle
);
426 /* The registration hand-off routine */
427 void proto_reg_handoff_lbmpdm_tcp(void)
429 static bool already_registered
= false;
431 if (!already_registered
)
433 dissector_add_for_decode_as_with_preference("tcp.port", lbmpdm_tcp_dissector_handle
);
434 heur_dissector_add("tcp", test_lbmpdm_tcp_packet
, "LBMPDM over TCP", "lbmpdm_tcp", lbmpdm_tcp_protocol_handle
, HEURISTIC_ENABLE
);
437 /* Make sure the port low is <= the port high. If not, don't change them. */
438 if (global_lbmpdm_tcp_port_low
<= global_lbmpdm_tcp_port_high
)
440 lbmpdm_tcp_port_low
= global_lbmpdm_tcp_port_low
;
441 lbmpdm_tcp_port_high
= global_lbmpdm_tcp_port_high
;
444 lbmpdm_tcp_use_tag
= global_lbmpdm_tcp_use_tag
;
446 already_registered
= true;
450 * Editor modelines - https://www.wireshark.org/tools/modelines.html
455 * indent-tabs-mode: nil
458 * vi: set shiftwidth=4 tabstop=8 expandtab:
459 * :indentSize=4:tabSize=8:noTabs=true: