2 * Routines for LINX packet dissection
4 * Copyright 2006, Martin Peylo <martin.peylo@siemens.com>
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
13 /* The used document is:
14 * ENEA Link Protocol Specification available at
15 * http://linx.sourceforge.net
19 * Version: 2.5.0, May 16, 2011
21 * Added support for LINX ETHCM version 3 and LINX RLNH version 2.
22 * Mattias Wallin, linx@enea.com, September 23, 2007
24 * Added support for LINX TCP CM.
25 * Dejan Bucar, linx@enea.com, June 21, 2011
27 * Added support for LINX ETHCM Multicore header.
28 * Dejan Bucar, linx@enea.com, June 21, 2011
33 #include <epan/packet.h>
34 #include <epan/expert.h>
35 #include <epan/etypes.h>
37 #include <wsutil/array.h>
39 void proto_register_linx(void);
40 void proto_reg_handoff_linx(void);
41 void proto_register_linx_tcp(void);
42 void proto_reg_handoff_linx_tcp(void);
44 static dissector_handle_t linx_handle
;
46 static int proto_linx
;
47 static int proto_linx_tcp
;
50 static int hf_linx_nexthdr
;
53 static int hf_linx_multicore_scoreid
;
54 static int hf_linx_multicore_dcoreid
;
55 static int hf_linx_multicore_reserved
;
56 static int hf_linx_multicore_reserved1
;
60 static int hf_linx_main_version
;
61 static int hf_linx_main_reserved
;
62 static int hf_linx_main_connection
;
63 static int hf_linx_main_bundle
;
64 static int hf_linx_main_pkg_size
;
67 static int hf_linx_udata_reserved
;
68 static int hf_linx_udata_morefrags
;
69 static int hf_linx_udata_fragno
;
70 static int hf_linx_udata_signo
;
71 static int hf_linx_udata_dstaddr16
;
72 static int hf_linx_udata_dstaddr32
;
73 static int hf_linx_udata_srcaddr16
;
74 static int hf_linx_udata_srcaddr32
;
75 static int hf_linx_udata_payload
;
78 static int hf_linx_ack_reserved
;
79 static int hf_linx_ack_request
;
80 static int hf_linx_ack_ackno
;
81 static int hf_linx_ack_seqno
;
84 static int hf_linx_conn_cmd
;
85 static int hf_linx_conn_size
;
86 static int hf_linx_conn_reserved
;
87 static int hf_linx_conn_srcmac
;
88 static int hf_linx_conn_dstmac
;
89 static int hf_linx_conn_winsize
;
90 static int hf_linx_conn_publcid
;
91 static int hf_linx_conn_feat_neg_str
;
93 static int hf_linx_frag_reserved
;
94 static int hf_linx_frag_morefrags
;
95 static int hf_linx_frag_fragno
;
98 static int hf_linx_nack_reserv1
;
99 static int hf_linx_nack_reserv2
;
100 static int hf_linx_nack_count
;
101 static int hf_linx_nack_seqno
;
104 static int hf_linx_rlnh_msg_type32
;
105 static int hf_linx_rlnh_msg_type8
;
106 /* static int hf_linx_rlnh_linkaddr; */
107 static int hf_linx_rlnh_src_linkaddr
;
108 static int hf_linx_rlnh_version
;
109 static int hf_linx_rlnh_status
;
110 static int hf_linx_rlnh_name
;
111 static int hf_linx_rlnh_peer_linkaddr
;
112 static int hf_linx_rlnh_feat_neg_str
;
113 static int hf_linx_rlnh_msg_reserved
;
116 /* static int hf_linx_tcp_reserved; */
117 static int hf_linx_tcp_oob
;
118 static int hf_linx_tcp_version
;
119 static int hf_linx_tcp_type
;
120 static int hf_linx_tcp_src
;
121 static int hf_linx_tcp_dst
;
122 static int hf_linx_tcp_size
;
123 static int hf_linx_tcp_rlnh_msg_type32
;
124 static int hf_linx_tcp_rlnh_msg_type8
;
125 /* static int hf_linx_tcp_rlnh_linkaddr; */
126 static int hf_linx_tcp_rlnh_src_linkaddr
;
127 static int hf_linx_tcp_rlnh_version
;
128 static int hf_linx_tcp_rlnh_status
;
129 static int hf_linx_tcp_rlnh_name
;
130 static int hf_linx_tcp_rlnh_peer_linkaddr
;
131 static int hf_linx_tcp_rlnh_feat_neg_str
;
132 static int hf_linx_tcp_rlnh_msg_reserved
;
133 static int hf_linx_tcp_payload
;
136 static int rlnh_version
;
139 static int ett_linx_multicore
;
140 static int ett_linx_main
;
141 static int ett_linx_error
;
142 static int ett_linx_udata
;
143 static int ett_linx_ack
;
144 static int ett_linx_tcp
;
146 static expert_field ei_linx_version
;
147 static expert_field ei_linx_rlnh_msg
;
148 static expert_field ei_linx_header
;
150 static expert_field ei_linx_tcp_version
;
151 static expert_field ei_linx_tcp_rlnh_msg
;
155 /* Definition and Names */
157 #define ETHCM_MAIN 0x0
158 #define ETHCM_CONN 0x1
159 #define ETHCM_UDATA 0x2
160 #define ETHCM_FRAG 0x3
161 #define ETHCM_ACK 0x4
162 #define ETHCM_NACK 0x5
163 #define ETHCM_NONE 0xf
165 static const value_string linx_short_header_names
[]={
166 { ETHCM_MAIN
, "MAIN"},
167 { ETHCM_CONN
, "CONN"},
168 { ETHCM_UDATA
, "UDATA"},
169 { ETHCM_FRAG
, "FRAG"},
171 { ETHCM_NACK
, "NACK"},
172 { ETHCM_NONE
, "NONE"},
176 static const value_string linx_long_header_names
[] = {
177 { ETHCM_MAIN
, "Main"},
178 { ETHCM_CONN
, "Connection"},
179 { ETHCM_UDATA
, "Udata"},
180 { ETHCM_FRAG
, "Fragmentation"},
182 { ETHCM_NACK
, "Nack"},
183 { ETHCM_NONE
, "None"},
187 #define TCP_CM_CONN 0x43
188 #define TCP_CM_UDATA 0x55
189 #define TCP_CM_PING 0x50
190 #define TCP_CM_PONG 0x51
192 static const value_string linx_short_tcp_names
[] = {
193 {TCP_CM_CONN
, "conn"},
194 {TCP_CM_UDATA
, "udata"},
195 {TCP_CM_PING
, "ping"},
196 {TCP_CM_PONG
, "pong"},
200 static const value_string linx_long_tcp_names
[] = {
201 {TCP_CM_CONN
, "Connection msg"},
202 {TCP_CM_UDATA
, "User data"},
203 {TCP_CM_PING
, "Ping msg"},
204 {TCP_CM_PONG
, "Pong msg"},
209 #define RLNH_LINK_ADDR 0
210 #define RLNH_QUERY_NAME 1
211 #define RLNH_PUBLISH 2
212 #define RLNH_UNPUBLISH 3
213 #define RLNH_UNPUBLISH_ACK 4
215 #define RLNH_INIT_REPLY 6
216 #define RLNH_PUBLISH_PEER 7
218 static const value_string linx_short_rlnh_names
[]={
219 { RLNH_LINK_ADDR
, "link_addr"},
220 { RLNH_QUERY_NAME
, "query_name"},
221 { RLNH_PUBLISH
, "publish"},
222 { RLNH_UNPUBLISH
, "unpublish"},
223 { RLNH_UNPUBLISH_ACK
, "unpublish_ack"},
224 { RLNH_INIT
, "init"},
225 { RLNH_INIT_REPLY
, "init_reply"},
226 { RLNH_PUBLISH_PEER
, "publish_peer"},
230 static const value_string linx_long_rlnh_names
[]={
231 { RLNH_LINK_ADDR
, "Link Address"},
232 { RLNH_QUERY_NAME
, "Query Name"},
233 { RLNH_PUBLISH
, "Publish"},
234 { RLNH_UNPUBLISH
, "Unpublish"},
235 { RLNH_UNPUBLISH_ACK
, "Unpublish Ack"},
236 { RLNH_INIT
, "Init"},
237 { RLNH_INIT_REPLY
, "Init Reply"},
238 { RLNH_PUBLISH_PEER
, "Publish Peer"},
242 static const value_string linx_rlnh_reply
[] = {
243 { 0, "Version supported"},
244 { 1, "Version NOT supported"},
248 static const value_string linx_nofragment
[] = {
249 { 0x7fff, "No Fragment"},
253 static const value_string linx_coreid
[]= {
259 #define CONN_CONNECT 2
260 #define CONN_CONNECT_ACK 3
263 static const value_string linx_conn_cmd
[] = {
264 { CONN_RESET
, "Reset"},
265 { CONN_CONNECT
, "Connect"},
266 { CONN_CONNECT_ACK
, "Connect_Ack"},
272 dissect_linx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
283 proto_tree
*multicore_header_tree
;
284 proto_tree
*main_header_tree
;
285 proto_tree
*conn_header_tree
;
286 proto_tree
*ack_header_tree
;
287 proto_tree
*udata_header_tree
;
288 proto_tree
*nack_header_tree
;
289 proto_tree
*frag_header_tree
;
290 proto_tree
*rlnh_header_tree
;
292 /* Show name in protocol column */
293 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LINX");
294 /* Clear out stuff in the info column */
295 col_clear(pinfo
->cinfo
, COL_INFO
);
297 { /* Work out the details */
298 proto_item
*ti
= NULL
;
299 proto_tree
*linx_tree
= NULL
;
300 proto_item
*ver_item
, *msg_item
;
302 ti
= proto_tree_add_item(tree
, proto_linx
, tvb
, 0, -1, ENC_NA
);
303 linx_tree
= proto_item_add_subtree(ti
, ett_linx
);
305 dword
= tvb_get_ntohl(tvb
, offset
);
306 nexthdr
= (dword
>> 28) & 0xf;
308 /* check if we have multicore header*/
309 if (nexthdr
== ETHCM_MAIN
)
311 multicore_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, 0, 4, ett_linx_multicore
, NULL
, "Multicore Header");
313 /* Multicore header */
316 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
317 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
318 | Next | R | Dest Coreid | Source Coreid | R |
319 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
321 proto_tree_add_item(multicore_header_tree
, hf_linx_nexthdr
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
322 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_reserved
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
323 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_dcoreid
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
324 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_scoreid
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
325 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_reserved1
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
328 /* read main header*/
329 dword
= tvb_get_ntohl(tvb
, offset
);
332 version
= (dword
>> 25) & 0x7;
333 nexthdr
= (dword
>> 28) & 0xf;
334 pkgsize
= dword
& 0x3fff;
337 main_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, 4, ett_linx_main
, NULL
, "Main Header");
341 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
342 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
343 | Next | Ver | R | Connection |R| Packet size |
344 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
347 proto_tree_add_item(main_header_tree
, hf_linx_nexthdr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
348 ver_item
= proto_tree_add_item(main_header_tree
, hf_linx_main_version
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
349 proto_tree_add_item(main_header_tree
, hf_linx_main_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
350 proto_tree_add_item(main_header_tree
, hf_linx_main_connection
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
351 proto_tree_add_item(main_header_tree
, hf_linx_main_bundle
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
352 proto_tree_add_item(main_header_tree
, hf_linx_main_pkg_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
355 /* Supports version 2 and 3 so far */
356 if (version
< 2 || version
> 3) {
357 expert_add_info(pinfo
, ver_item
, &ei_linx_version
);
360 while (nexthdr
!= ETHCM_NONE
) {
362 dword
= tvb_get_ntohl(tvb
, offset
);
364 nexthdr
= (dword
>>28) & 0xf;
365 conntype
= (dword
>>24) & 0xf;
366 /* Write non trivial header name to info column */
367 if ((thishdr
!= ETHCM_NONE
) && (thishdr
!= ETHCM_MAIN
)) {
368 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(thishdr
, linx_short_header_names
, "unknown"));
369 if(thishdr
== ETHCM_CONN
)
370 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(conntype
, linx_conn_cmd
, "unknown"));
379 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
380 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
381 | Next | Type |Size |Winsize| Reserved |Publish conn id|
382 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
384 : dst hw addr followed by src hw addr :
386 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
388 : Feature negotiation string (null terminated) :
390 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
393 size
= (dword
>>21) & 0x7;
394 conn_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, (4+2*size
), ett_linx_main
, NULL
, "Connection Header");
395 proto_tree_add_item(conn_header_tree
, hf_linx_nexthdr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
396 proto_tree_add_item(conn_header_tree
, hf_linx_conn_cmd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
397 proto_tree_add_item(conn_header_tree
, hf_linx_conn_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
398 proto_tree_add_item(conn_header_tree
, hf_linx_conn_winsize
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
399 proto_tree_add_item(conn_header_tree
, hf_linx_conn_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
400 proto_tree_add_item(conn_header_tree
, hf_linx_conn_publcid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
404 /* Most likely ETHERNET */
405 proto_tree_add_item(conn_header_tree
, hf_linx_conn_dstmac
, tvb
, offset
, 6, ENC_NA
);
406 proto_tree_add_item(conn_header_tree
, hf_linx_conn_srcmac
, tvb
, offset
+ 6, 6, ENC_NA
);
410 /* Feature Negotiation String */
412 proto_tree_add_item(conn_header_tree
, hf_linx_conn_feat_neg_str
, tvb
, offset
, -1, ENC_ASCII
);
413 offset
+= tvb_strnlen(tvb
, offset
, -1);
421 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
422 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
423 | Next | Res | Count | Res | Seqno |
424 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
427 /* how many sequence numbers will be there? */
428 /* this is not implemented due to a lack of documentation with */
429 /* longer sequence numbers. */
430 /* guess there will be padding if the Seqno doesn't reach */
431 /* a 32bit boundary */
433 nack_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, 4, ett_linx_main
, NULL
, "NACK Header");
434 proto_tree_add_item(nack_header_tree
, hf_linx_nexthdr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
435 proto_tree_add_item(nack_header_tree
, hf_linx_nack_reserv1
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
436 proto_tree_add_item(nack_header_tree
, hf_linx_nack_count
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
437 proto_tree_add_item(nack_header_tree
, hf_linx_nack_reserv2
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
438 proto_tree_add_item(nack_header_tree
, hf_linx_nack_seqno
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
443 /* User data / fragment header => Version 3 */
446 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
447 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
448 | Next | Reserved |M| Frag no |
449 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
451 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
453 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
455 * User data / fragment header => Version 2
458 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
459 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460 | Next | Reserved |M| Frag no |
461 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467 - fragments (not first fragment)
470 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
471 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
472 | Next | Reserved |M| Frag no |
473 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
477 udata_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, 12, ett_linx_main
, NULL
, "Udata Header");
478 proto_tree_add_item(udata_header_tree
, hf_linx_nexthdr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
479 proto_tree_add_item(udata_header_tree
, hf_linx_udata_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
480 proto_tree_add_item(udata_header_tree
, hf_linx_udata_morefrags
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
481 proto_tree_add_item(udata_header_tree
, hf_linx_udata_fragno
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
483 /* signo removed in version 3 and linkaddresses extended to 32 bits */
485 proto_tree_add_item(udata_header_tree
, hf_linx_udata_signo
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
487 proto_tree_add_item(udata_header_tree
, hf_linx_udata_dstaddr16
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
488 proto_tree_add_item(udata_header_tree
, hf_linx_udata_srcaddr16
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
489 dword
= tvb_get_ntohl(tvb
, offset
);
491 proto_tree_add_item(udata_header_tree
, hf_linx_udata_dstaddr32
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
492 dword
= tvb_get_ntohl(tvb
, offset
);
494 proto_tree_add_item(udata_header_tree
, hf_linx_udata_srcaddr32
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
495 if(dword
== 0 && tvb_get_ntohl(tvb
, offset
) == 0) {
503 /* (dstaddr == srcaddr == 0) -> RLNH Protocol Message */
505 dword
= tvb_get_ntohl(tvb
, offset
);
507 /* Write to info column */
508 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "rlnh:%s ", val_to_str_const(dword
, linx_short_rlnh_names
, "unknown"));
510 /* create new paragraph for RLNH */
511 rlnh_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, 4, ett_linx_main
, NULL
, "RLNH");
514 msg_item
= proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_msg_type32
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
517 /* in version 2 of the rlnh protocol the length of the message type is restricted to 8 bits */
518 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_msg_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
519 msg_item
= proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_msg_type8
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
525 /* XXX what is this? */
527 case RLNH_QUERY_NAME
:
528 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
530 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_name
, tvb
, offset
, -1, ENC_ASCII
);
531 offset
+= tvb_strnlen(tvb
, offset
, -1);
534 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
536 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_name
, tvb
, offset
, -1, ENC_ASCII
);
537 offset
+= tvb_strnlen(tvb
, offset
, -1);
540 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
543 case RLNH_UNPUBLISH_ACK
:
544 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
548 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_version
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
549 /* This is not working if nodes are at different versions. Only the latest value will be saved in rlnh_version */
550 rlnh_version
= tvb_get_ntohl(tvb
, offset
);
553 case RLNH_INIT_REPLY
:
554 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_status
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
556 if(rlnh_version
> 1) {
557 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_feat_neg_str
, tvb
, offset
, -1, ENC_ASCII
);
558 offset
+= tvb_strnlen(tvb
, offset
, -1);
561 case RLNH_PUBLISH_PEER
:
562 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
564 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_peer_linkaddr
, tvb
, offset
, -1, ENC_BIG_ENDIAN
);
565 offset
+= tvb_strnlen(tvb
, offset
, -1);
568 /* no known Message type... */
569 expert_add_info(pinfo
, msg_item
, &ei_linx_rlnh_msg
);
573 /* Is there payload? */
574 /* anything better to do with that? */
575 payloadsize
= pkgsize
-offset
;
577 proto_tree_add_item(linx_tree
, hf_linx_udata_payload
, tvb
, offset
, payloadsize
, ENC_NA
);
583 /* Reliable header */
586 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
587 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
588 | Next |R| Res.| Ackno | Seqno |
589 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591 ack_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, 4, ett_linx_main
, NULL
, "Ack Header");
592 proto_tree_add_item(ack_header_tree
, hf_linx_nexthdr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
593 proto_tree_add_item(ack_header_tree
, hf_linx_ack_request
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
594 proto_tree_add_item(ack_header_tree
, hf_linx_ack_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
595 proto_tree_add_item(ack_header_tree
, hf_linx_ack_ackno
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
596 proto_tree_add_item(ack_header_tree
, hf_linx_ack_seqno
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
602 - fragments (not first fragment)
605 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
606 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
607 | Next | Reserved |M| Frag no |
608 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
611 frag_header_tree
= proto_tree_add_subtree(linx_tree
, tvb
, offset
, 4, ett_linx_main
, NULL
, "Fragmentation Header");
612 proto_tree_add_item(frag_header_tree
, hf_linx_nexthdr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
613 proto_tree_add_item(frag_header_tree
, hf_linx_frag_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
614 proto_tree_add_item(frag_header_tree
, hf_linx_frag_morefrags
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
615 proto_tree_add_item(frag_header_tree
, hf_linx_frag_fragno
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
620 proto_tree_add_expert_format(linx_tree
, pinfo
, &ei_linx_header
, tvb
, offset
, 4, "ERROR: Header \"%u\" not recognized", thishdr
);
621 nexthdr
= ETHCM_NONE
; /* avoid endless loop with faulty packages */
627 return tvb_captured_length(tvb
);
631 /* Protocol Initialisation */
633 proto_register_linx(void)
636 /* Registering Data Structures */
638 static hf_register_info hf
[] = {
640 { "Next Header", "linx.nexthdr", FT_UINT32
, BASE_DEC
, VALS(linx_long_header_names
), 0xf0000000, NULL
, HFILL
},
642 { &hf_linx_multicore_scoreid
, /* in ETHCM_MULTICORE */
643 { "Source coreid", "linx.scoreid", FT_UINT32
, BASE_DEC
, VALS(linx_coreid
), 0x0000ff00, "Multicore source core id", HFILL
},
645 { &hf_linx_multicore_dcoreid
, /* in ETHCM_MULTICORE */
646 { "Destination coreid", "linx.dcoreid", FT_UINT32
, BASE_DEC
, VALS(linx_coreid
), 0x00ff0000, "Multicore destination core id", HFILL
},
648 { &hf_linx_multicore_reserved
, /* in ETHCM_MULTICORE */
649 { "Reserved", "linx.reserved8", FT_UINT32
, BASE_DEC
, NULL
, 0x0f000000, "Multicore Hdr Reserved", HFILL
},
651 { &hf_linx_multicore_reserved1
, /* in ETHCM_MULTICORE */
652 { "Reserved", "linx.reserved9", FT_UINT32
, BASE_DEC
, NULL
, 0x000000ff, "Multicore Hdr Reserved", HFILL
},
654 { &hf_linx_main_version
, /* in ETHCM_MAIN */
655 { "Version", "linx.version", FT_UINT32
, BASE_DEC
, NULL
, 0x0e000000, "LINX Version", HFILL
},
657 { &hf_linx_main_reserved
, /* in ETHCM_MAIN */
658 { "Reserved", "linx.reserved1", FT_UINT32
, BASE_DEC
, NULL
, 0x01800000, "Main Hdr Reserved", HFILL
},
660 { &hf_linx_main_connection
, /* in ETHCM_MAIN */
661 { "Connection", "linx.connection", FT_UINT32
, BASE_DEC
, NULL
, 0x007f8000, NULL
, HFILL
},
663 { &hf_linx_main_bundle
, /* in ETHCM_MAIN */
664 { "Bundle", "linx.bundle", FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00004000, NULL
, HFILL
},
666 { &hf_linx_main_pkg_size
, /* in ETHCM_MAIN */
667 { "Package Size", "linx.pcksize", FT_UINT32
, BASE_DEC
, NULL
, 0x00003fff, NULL
, HFILL
},
669 { &hf_linx_udata_reserved
, /* in ETHCM_UDATA */
670 { "Reserved", "linx.reserved5", FT_UINT32
, BASE_DEC
, NULL
, 0x0fff0000, "Udata Hdr Reserved", HFILL
},
672 { &hf_linx_udata_morefrags
, /* in ETHCM_UDATA */
673 { "More Fragments", "linx.morefra", FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00008000, "More fragments follow", HFILL
},
675 { &hf_linx_udata_fragno
, /* in ETHCM_UDATA */
676 { "Fragment Number", "linx.fragno", FT_UINT32
, BASE_DEC
, VALS(linx_nofragment
), 0x00007fff, NULL
, HFILL
},
678 { &hf_linx_udata_signo
, /* in ETHCM_UDATA */
679 { "Signal Number", "linx.signo", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
},
681 { &hf_linx_udata_dstaddr16
, /* in ETHCM_UDATA - protocol version 2 */
682 { "Receiver Address", "linx.dstaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffff0000, NULL
, HFILL
},
684 { &hf_linx_udata_dstaddr32
, /* in ETHCM_UDATA - protocol version 3 */
685 { "Receiver Address", "linx.dstaddr32", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
},
687 { &hf_linx_udata_srcaddr16
, /* in ETHCM_UDATA - protocol version 2 */
688 { "Sender Address", "linx.srcaddr", FT_UINT32
, BASE_DEC
, NULL
, 0x0000ffff, NULL
, HFILL
},
690 { &hf_linx_udata_srcaddr32
, /* in ETHCM_UDATA - protocol version 3 */
691 { "Sender Address", "linx.srcaddr32", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
},
693 { &hf_linx_udata_payload
, /* in ETHCM_UDATA */
694 { "Payload", "linx.payload", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
696 { &hf_linx_ack_request
, /* in ETHCM_ACK */
697 { "ACK-request", "linx.ackreq", FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x08000000, NULL
, HFILL
},
699 { &hf_linx_ack_reserved
, /* in ETHCM_ACK */
700 { "Reserved", "linx.reserved7", FT_UINT32
, BASE_DEC
, NULL
, 0x07000000, "ACK Hdr Reserved", HFILL
},
702 { &hf_linx_ack_ackno
, /* in ETHCM_ACK */
703 { "ACK Number", "linx.ackno", FT_UINT32
, BASE_DEC
, NULL
, 0x00fff000, NULL
, HFILL
},
705 { &hf_linx_ack_seqno
, /* in ETHCM_ACK */
706 { "Sequence Number", "linx.seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x00000fff, NULL
, HFILL
},
708 { &hf_linx_conn_cmd
, /* in ETHCM_CONN */
709 { "Command", "linx.cmd", FT_UINT32
, BASE_DEC
, VALS(linx_conn_cmd
), 0x0f000000, NULL
, HFILL
},
711 { &hf_linx_conn_size
, /* in ETHCM_CONN */
712 { "Size", "linx.size", FT_UINT32
, BASE_DEC
, NULL
, 0x00e00000, NULL
, HFILL
},
714 { &hf_linx_conn_winsize
, /* in ETHCM_CONN */
715 { "WinSize", "linx.winsize", FT_UINT32
, BASE_DEC
, NULL
, 0x001e0000, "Window Size", HFILL
},
717 { &hf_linx_conn_reserved
, /* in ETHCM_CONN */
718 { "Reserved", "linx.reserved3", FT_UINT32
, BASE_DEC
, NULL
, 0x0001ff00, "Conn Hdr Reserved", HFILL
},
720 { &hf_linx_conn_publcid
, /* in ETHCM_CONN */
721 { "Publish Conn ID", "linx.publcid", FT_UINT32
, BASE_DEC
, NULL
, 0x000000ff, NULL
, HFILL
},
723 { &hf_linx_conn_srcmac
, /* in ETHCM_CONN */
724 { "Source", "linx.srcmaddr_ether", FT_ETHER
, BASE_NONE
, NULL
, 0x0, "Source Media Address (ethernet)", HFILL
},
726 { &hf_linx_conn_dstmac
, /* in ETHCM_CONN */
727 { "Destination", "linx.destmaddr_ether", FT_ETHER
, BASE_NONE
, NULL
, 0x0, "Destination Media Address (ethernet)", HFILL
},
729 { &hf_linx_conn_feat_neg_str
, /* in ETHCM_CONN */
730 { "Feature Negotiation String", "linx.feat_neg_str", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
732 { &hf_linx_frag_reserved
, /* in ETHCM_FRAG */
733 { "Reserved", "linx.reserved6", FT_UINT32
, BASE_DEC
, NULL
, 0x0fff0000, "Frag Hdr Reserved", HFILL
},
735 { &hf_linx_frag_morefrags
, /* in ETHCM_FRAG */
736 { "More Fragments", "linx.morefr2", FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00008000, NULL
, HFILL
},
738 { &hf_linx_frag_fragno
, /* in ETHCM_FRAG */
739 { "Fragment Number", "linx.fragno2", FT_UINT32
, BASE_DEC
, NULL
, 0x00007fff, NULL
, HFILL
},
741 { &hf_linx_nack_reserv1
, /* in ETHCM_NACK */
742 { "Reserved", "linx.nack_reserv", FT_UINT32
, BASE_DEC
, NULL
, 0x0f000000, "Nack Hdr Reserved", HFILL
},
744 { &hf_linx_nack_count
, /* in ETHCM_NACK */
745 { "Count", "linx.nack_count", FT_UINT32
, BASE_DEC
, NULL
, 0x00ff0000, NULL
, HFILL
},
747 { &hf_linx_nack_reserv2
, /* in ETHCM_NACK */
748 { "Reserved", "linx.nack_reserv", FT_UINT32
, BASE_DEC
, NULL
, 0x0000f000, "Nack Hdr Reserved", HFILL
},
750 { &hf_linx_nack_seqno
, /* in ETHCM_NACK */
751 { "Sequence Number", "linx.nack_seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x00000fff, NULL
, HFILL
},
755 { &hf_linx_rlnh_msg_type32
, /* in RLNH */
756 { "RLNH msg type", "linx.rlnh_msg_type", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0x0, "RLNH message type", HFILL
},
758 { &hf_linx_rlnh_msg_type8
, /* in RLNH */
759 { "RLNH msg type", "linx.rlnh_msg_type8", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0x000000ff, "RLNH message type", HFILL
},
761 { &hf_linx_rlnh_msg_reserved
, /* in RLNH */
762 { "RLNH msg reserved", "linx.rlnh_msg_reserved", FT_UINT32
, BASE_DEC
, NULL
, 0xffffff00, "RLNH message reserved", HFILL
},
765 { &hf_linx_rlnh_linkaddr
, /* in RLNH */
766 { "RLNH linkaddr", "linx.rlnh_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, "RLNH linkaddress", HFILL
},
769 { &hf_linx_rlnh_src_linkaddr
, /* in RLNH */
770 { "RLNH src linkaddr", "linx.rlnh_src_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "RLNH source linkaddress", HFILL
},
772 { &hf_linx_rlnh_peer_linkaddr
, /* in RLNH */
773 { "RLNH peer linkaddr", "linx.rlnh_peer_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "RLNH peer linkaddress", HFILL
},
775 { &hf_linx_rlnh_version
, /* in RLNH */
776 { "RLNH version", "linx.rlnh_version", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
},
778 { &hf_linx_rlnh_status
, /* in RLNH */
779 { "RLNH reply", "linx.rlnh_status", FT_UINT32
, BASE_DEC
, VALS(linx_rlnh_reply
), 0x0, NULL
, HFILL
},
781 { &hf_linx_rlnh_name
, /* in RLNH */
782 { "RLNH name", "linx.rlnh_name", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
784 { &hf_linx_rlnh_feat_neg_str
, /* in RLNH */
785 { "RLNH Feature Negotiation String", "linx.rlnh_feat_neg_str", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
789 /* Setup protocol subtree array */
790 static int *ett
[] = {
799 static ei_register_info ei
[] = {
800 { &ei_linx_version
, { "linx.version.unknown", PI_PROTOCOL
, PI_WARN
, "Version not yet supported and might be dissected incorrectly!", EXPFILL
}},
801 { &ei_linx_rlnh_msg
, { "linx.rlnh_msg.unknown", PI_PROTOCOL
, PI_WARN
, "Message type not recognized", EXPFILL
}},
802 { &ei_linx_header
, { "linx.header_not_recognized", PI_PROTOCOL
, PI_WARN
, "Header not recognized", EXPFILL
}},
805 expert_module_t
* expert_linx
;
807 proto_linx
= proto_register_protocol (
808 "ENEA LINX", /* name */
809 "LINX", /* short name */
813 /* Protocol Registering data structures. */
814 proto_register_field_array(proto_linx
, hf
, array_length(hf
));
815 proto_register_subtree_array(ett
, array_length(ett
));
816 expert_linx
= expert_register_protocol(proto_linx
);
817 expert_register_field_array(expert_linx
, ei
, array_length(ei
));
819 /* Register the dissector */
820 linx_handle
= register_dissector("linx", dissect_linx
, proto_linx
);
824 /* Protocol Handoff */
826 proto_reg_handoff_linx(void)
828 dissector_add_uint("ethertype", ETHERTYPE_LINX
, linx_handle
);
831 /************ TCP CM **************/
834 dissect_linx_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
838 proto_item
*ti
, *ver_item
, *msg_item
;
839 proto_tree
*linx_tcp_tree
;
840 proto_tree
*tcp_header_tree
;
841 proto_tree
*rlnh_header_tree
;
847 /* Show name in protocol column */
848 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LINX/TCP");
850 /* Clear out stuff in the info column */
851 col_clear(pinfo
->cinfo
, COL_INFO
);
853 dword
= tvb_get_ntohl(tvb
, 0);
854 version
= (dword
>> 16) & 0xFF;
855 type
= (dword
>> 24) & 0xFF;
857 /* size of linx tcp cm header */
861 dword
= tvb_get_ntohl(tvb
, 12);
862 size
+= (dword
& 0xFFFFFFFF);
865 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "tcpcm:%s ", val_to_str_const(type
, linx_short_tcp_names
, "unknown"));
867 ti
= proto_tree_add_item(tree
, proto_linx_tcp
, tvb
, 0, -1, ENC_NA
);
868 linx_tcp_tree
= proto_item_add_subtree(ti
, ett_linx_tcp
);
870 tcp_header_tree
= proto_tree_add_subtree(linx_tcp_tree
, tvb
, 0, 16, ett_linx_tcp
, NULL
, "TCP CM Header");
872 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_type
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
873 ver_item
= proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_version
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
874 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_oob
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
875 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_src
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
876 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_dst
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
877 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_size
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
880 expert_add_info(pinfo
, ver_item
, &ei_linx_tcp_version
);
885 if (type
== 0x55) { /* UDATA */
886 dword
= tvb_get_ntohl(tvb
, 8);
887 if (dword
== 0) { /* RLNH Message*/
889 dword
= tvb_get_ntohl(tvb
, offset
);
891 /* Write to info column */
892 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "rlnh:%s ", val_to_str_const(dword
, linx_short_rlnh_names
, "unknown"));
894 /* create new paragraph for RLNH */
895 rlnh_header_tree
= proto_tree_add_subtree(linx_tcp_tree
, tvb
, offset
, 4, ett_linx_tcp
, NULL
, "RLNH");
898 msg_item
= proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_msg_type32
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
902 * In version 2 of the rlnh protocol the length of the message type is
903 * restricted to 8 bits.
905 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_msg_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
906 msg_item
= proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_msg_type8
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
913 case RLNH_QUERY_NAME
:
914 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
916 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_name
, tvb
, offset
, -1, ENC_ASCII
);
917 /*offset += tvb_strnlen(tvb, offset, -1);*/
920 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
922 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_name
, tvb
, offset
, -1, ENC_ASCII
);
923 /*offset += tvb_strnlen(tvb, offset, -1);*/
926 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
929 case RLNH_UNPUBLISH_ACK
:
930 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
934 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_version
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
935 rlnh_version
= tvb_get_ntohl(tvb
, offset
);
938 case RLNH_INIT_REPLY
:
939 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_status
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
941 if(rlnh_version
> 1) {
942 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_feat_neg_str
, tvb
, offset
, -1, ENC_ASCII
);
943 /*offset += tvb_strnlen(tvb, offset, -1);*/
946 case RLNH_PUBLISH_PEER
:
947 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
949 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_peer_linkaddr
, tvb
, offset
, -1, ENC_BIG_ENDIAN
);
950 /*offset += tvb_strnlen(tvb, offset, -1);*/
953 /* No known Message type */
954 expert_add_info(pinfo
, msg_item
, &ei_linx_tcp_rlnh_msg
);
959 payloadsize
= size
-offset
;
961 proto_tree_add_item(linx_tcp_tree
, hf_linx_tcp_payload
, tvb
, offset
, payloadsize
, ENC_NA
);
965 return tvb_captured_length(tvb
);
969 proto_register_linx_tcp(void)
971 static hf_register_info hf
[] = {
973 { &hf_linx_tcp_reserved
,
974 { "Reserved", "linxtcp.reserved", FT_UINT32
, BASE_DEC
, NULL
, 0x00007FFF, "TCP CM reserved", HFILL
},
978 { "Out-of-band", "linxtcp.oob", FT_UINT32
, BASE_DEC
, NULL
, 0x00008000, "TCP CM oob", HFILL
},
980 { &hf_linx_tcp_version
,
981 { "Version", "linxtcp.version", FT_UINT32
, BASE_DEC
, NULL
, 0x00FF0000, "TCP CM version", HFILL
},
984 { "Type", "linxtcp.type", FT_UINT32
, BASE_HEX
, VALS(linx_long_tcp_names
), 0xFF000000, "TCP CM type", HFILL
},
987 { "Source", "linxtcp.src", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "TCP CM source", HFILL
},
990 { "Destination", "linxtcp.dst", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "TCP CM destination", HFILL
},
993 { "Size", "linxtcp.size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "TCP CM size", HFILL
},
997 { &hf_linx_tcp_rlnh_msg_type32
,
998 { "RLNH msg type", "linxtcp.rlnh_msg_type", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0x0, "RLNH message type", HFILL
},
1000 { &hf_linx_tcp_rlnh_msg_type8
,
1001 { "RLNH msg type", "linxtcp.rlnh_msg_type8", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0x000000ff, "RLNH message type", HFILL
},
1003 { &hf_linx_tcp_rlnh_msg_reserved
,
1004 { "RLNH msg reserved", "linxtcp.rlnh_msg_reserved", FT_UINT32
, BASE_DEC
, NULL
, 0xffffff00, "RLNH message reserved", HFILL
},
1007 { &hf_linx_tcp_rlnh_linkaddr
,
1008 { "RLNH linkaddr", "linxtcp.rlnh_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "RLNH linkaddress", HFILL
},
1011 { &hf_linx_tcp_rlnh_src_linkaddr
,
1012 { "RLNH src linkaddr", "linxtcp.rlnh_src_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "RLNH source linkaddress", HFILL
},
1014 { &hf_linx_tcp_rlnh_peer_linkaddr
,
1015 { "RLNH peer linkaddr", "linxtcp.rlnh_peer_linkaddr", FT_UINT32
,
1016 BASE_DEC
, NULL
, 0x0, "RLNH peer linkaddress", HFILL
},
1018 { &hf_linx_tcp_rlnh_version
,
1019 { "RLNH version", "linxtcp.rlnh_version", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
},
1021 { &hf_linx_tcp_rlnh_status
,
1022 { "RLNH reply", "linxtcp.rlnh_status", FT_UINT32
, BASE_DEC
, VALS(linx_rlnh_reply
), 0x0, NULL
, HFILL
},
1024 { &hf_linx_tcp_rlnh_name
,
1025 { "RLNH name", "linxtcp.rlnh_name", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
1027 { &hf_linx_tcp_rlnh_feat_neg_str
,
1028 { "RLNH Feature Negotiation String", "linxtcp.rlnh_feat_neg_str", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
1030 { &hf_linx_tcp_payload
,
1031 { "Payload", "linxtcp.payload", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
1035 static int *ett
[] = {
1039 static ei_register_info ei
[] = {
1040 { &ei_linx_tcp_version
, { "linxtcp.version.unknown", PI_PROTOCOL
, PI_WARN
, "Version not yet supported and might be dissected incorrectly!", EXPFILL
}},
1041 { &ei_linx_tcp_rlnh_msg
, { "linxtcp.rlnh_msg.unknown", PI_PROTOCOL
, PI_WARN
, "Message type not recognized", EXPFILL
}},
1044 expert_module_t
* expert_linx_tcp
;
1046 proto_linx_tcp
= proto_register_protocol("ENEA LINX over TCP", "LINX/TCP", "linxtcp");
1047 proto_register_field_array(proto_linx_tcp
, hf
, array_length(hf
));
1048 proto_register_subtree_array(ett
, array_length(ett
));
1049 expert_linx_tcp
= expert_register_protocol(proto_linx_tcp
);
1050 expert_register_field_array(expert_linx_tcp
, ei
, array_length(ei
));
1054 proto_reg_handoff_linx_tcp(void)
1056 dissector_handle_t linx_tcp_handle
;
1058 linx_tcp_handle
= create_dissector_handle(dissect_linx_tcp
, proto_linx_tcp
);
1060 dissector_add_for_decode_as_with_preference("tcp.port", linx_tcp_handle
);
1064 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1069 * indent-tabs-mode: t
1072 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1073 * :indentSize=8:tabSize=8:noTabs=false: