2 * Routines for LINX packet dissection
4 * Copyright 2006, Martin Peylo <martin.peylo@siemens.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 /* The used document is:
28 * ENEA Link Protocol Specification available at
29 * http://linx.sourceforge.net
33 * Version: 2.5.0, May 16, 2011
35 * Added support for LINX ETHCM version 3 and LINX RLNH version 2.
36 * Mattias Wallin, linx@enea.com, September 23, 2007
38 * Added support for LINX TCP CM.
39 * Dejan Bucar, linx@enea.com, June 21, 2011
41 * Added support for LINX ETHCM Multicore header.
42 * Dejan Bucar, linx@enea.com, June 21, 2011
47 #include <epan/packet.h>
48 #include <epan/etypes.h>
50 /* forward reference */
51 static void dissect_linx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
53 static int proto_linx
= -1;
54 static int proto_linx_tcp
= -1;
57 static int hf_linx_nexthdr
= -1;
60 static int hf_linx_multicore_scoreid
= -1;
61 static int hf_linx_multicore_dcoreid
= -1;
62 static int hf_linx_multicore_reserved
= -1;
63 static int hf_linx_multicore_reserved1
= -1;
67 static int hf_linx_main_version
= -1;
68 static int hf_linx_main_reserved
= -1;
69 static int hf_linx_main_connection
= -1;
70 static int hf_linx_main_bundle
= -1;
71 static int hf_linx_main_pkgsize
= -1;
74 static int hf_linx_udata_reserved
= -1;
75 static int hf_linx_udata_morefrags
= -1;
76 static int hf_linx_udata_fragno
= -1;
77 static int hf_linx_udata_signo
= -1;
78 static int hf_linx_udata_dstaddr16
= -1;
79 static int hf_linx_udata_dstaddr32
= -1;
80 static int hf_linx_udata_srcaddr16
= -1;
81 static int hf_linx_udata_srcaddr32
= -1;
84 static int hf_linx_ack_reserved
= -1;
85 static int hf_linx_ack_request
= -1;
86 static int hf_linx_ack_ackno
= -1;
87 static int hf_linx_ack_seqno
= -1;
90 static int hf_linx_conn_cmd
= -1;
91 static int hf_linx_conn_size
= -1;
92 static int hf_linx_conn_reserved
= -1;
93 static int hf_linx_conn_srcmac
= -1;
94 static int hf_linx_conn_dstmac
= -1;
95 static int hf_linx_conn_winsize
= -1;
96 static int hf_linx_conn_publcid
= -1;
97 static int hf_linx_conn_feat_neg_str
= -1;
99 static int hf_linx_frag_reserved
= -1;
100 static int hf_linx_frag_morefrags
= -1;
101 static int hf_linx_frag_fragno
= -1;
104 static int hf_linx_nack_reserv1
= -1;
105 static int hf_linx_nack_reserv2
= -1;
106 static int hf_linx_nack_count
= -1;
107 static int hf_linx_nack_seqno
= -1;
110 static int hf_linx_rlnh_msg_type32
= -1;
111 static int hf_linx_rlnh_msg_type8
= -1;
112 /* static int hf_linx_rlnh_linkaddr = -1; */
113 static int hf_linx_rlnh_src_linkaddr
= -1;
114 static int hf_linx_rlnh_version
= -1;
115 static int hf_linx_rlnh_status
= -1;
116 static int hf_linx_rlnh_name
= -1;
117 static int hf_linx_rlnh_peer_linkaddr
= -1;
118 static int hf_linx_rlnh_feat_neg_str
= -1;
119 static int hf_linx_rlnh_msg_reserved
= -1;
122 /* static int hf_linx_tcp_reserved = -1; */
123 static int hf_linx_tcp_oob
= -1;
124 static int hf_linx_tcp_version
= -1;
125 static int hf_linx_tcp_type
= -1;
126 static int hf_linx_tcp_src
= -1;
127 static int hf_linx_tcp_dst
= -1;
128 static int hf_linx_tcp_size
= -1;
129 static int hf_linx_tcp_rlnh_msg_type32
= -1;
130 static int hf_linx_tcp_rlnh_msg_type8
= -1;
131 /* static int hf_linx_tcp_rlnh_linkaddr = -1; */
132 static int hf_linx_tcp_rlnh_src_linkaddr
= -1;
133 static int hf_linx_tcp_rlnh_version
= -1;
134 static int hf_linx_tcp_rlnh_status
= -1;
135 static int hf_linx_tcp_rlnh_name
= -1;
136 static int hf_linx_tcp_rlnh_peer_linkaddr
= -1;
137 static int hf_linx_tcp_rlnh_feat_neg_str
= -1;
138 static int hf_linx_tcp_rlnh_msg_reserved
= -1;
141 static int rlnh_version
= 0;
143 static gint ett_linx
= -1;
144 static gint ett_linx_multicore
= -1;
145 static gint ett_linx_main
= -1;
146 static gint ett_linx_error
= -1;
147 static gint ett_linx_udata
= -1;
148 static gint ett_linx_ack
= -1;
149 static gint ett_linx_tcp
= -1;
151 /* Definition and Names */
153 #define ETHCM_MAIN 0x0
154 #define ETHCM_CONN 0x1
155 #define ETHCM_UDATA 0x2
156 #define ETHCM_FRAG 0x3
157 #define ETHCM_ACK 0x4
158 #define ETHCM_NACK 0x5
159 #define ETHCM_NONE 0xf
161 static const value_string linx_short_header_names
[]={
162 { ETHCM_MAIN
, "MAIN"},
163 { ETHCM_CONN
, "CONN"},
164 { ETHCM_UDATA
, "UDATA"},
165 { ETHCM_FRAG
, "FRAG"},
167 { ETHCM_NACK
, "NACK"},
168 { ETHCM_NONE
, "NONE"},
172 static const value_string linx_long_header_names
[] = {
173 { ETHCM_MAIN
, "Main"},
174 { ETHCM_CONN
, "Connection"},
175 { ETHCM_UDATA
, "Udata"},
176 { ETHCM_FRAG
, "Fragmentation"},
178 { ETHCM_NACK
, "Nack"},
179 { ETHCM_NONE
, "None"},
183 #define TCP_CM_CONN 0x43
184 #define TCP_CM_UDATA 0x55
185 #define TCP_CM_PING 0x50
186 #define TCP_CM_PONG 0x51
188 static const value_string linx_short_tcp_names
[] = {
189 {TCP_CM_CONN
, "conn"},
190 {TCP_CM_UDATA
, "udata"},
191 {TCP_CM_PING
, "ping"},
192 {TCP_CM_PONG
, "pong"},
196 static const value_string linx_long_tcp_names
[] = {
197 {TCP_CM_CONN
, "Connection msg"},
198 {TCP_CM_UDATA
, "User data"},
199 {TCP_CM_PING
, "Ping msg"},
200 {TCP_CM_PONG
, "Pong msg"},
205 #define RLNH_LINK_ADDR 0
206 #define RLNH_QUERY_NAME 1
207 #define RLNH_PUBLISH 2
208 #define RLNH_UNPUBLISH 3
209 #define RLNH_UNPUBLISH_ACK 4
211 #define RLNH_INIT_REPLY 6
212 #define RLNH_PUBLISH_PEER 7
214 static const value_string linx_short_rlnh_names
[]={
215 { RLNH_LINK_ADDR
, "link_addr"},
216 { RLNH_QUERY_NAME
, "query_name"},
217 { RLNH_PUBLISH
, "publish"},
218 { RLNH_UNPUBLISH
, "unpublish"},
219 { RLNH_UNPUBLISH_ACK
, "unpublish_ack"},
220 { RLNH_INIT
, "init"},
221 { RLNH_INIT_REPLY
, "init_reply"},
222 { RLNH_PUBLISH_PEER
, "publish_peer"},
226 static const value_string linx_long_rlnh_names
[]={
227 { RLNH_LINK_ADDR
, "Link Address"},
228 { RLNH_QUERY_NAME
, "Query Name"},
229 { RLNH_PUBLISH
, "Publish"},
230 { RLNH_UNPUBLISH
, "Unpublish"},
231 { RLNH_UNPUBLISH_ACK
, "Unpublish Ack"},
232 { RLNH_INIT
, "Init"},
233 { RLNH_INIT_REPLY
, "Init Reply"},
234 { RLNH_PUBLISH_PEER
, "Publish Peer"},
238 static const value_string linx_rlnh_reply
[] = {
239 { 0, "Version supported"},
240 { 1, "Version NOT supported"},
244 static const value_string linx_boolean
[] = {
250 static const value_string linx_nofragment
[] = {
251 { 0x7fff, "No Fragment"},
255 static const value_string linx_coreid
[]= {
261 #define CONN_CONNECT 2
262 #define CONN_CONNECT_ACK 3
265 static const value_string linx_conn_cmd
[] = {
266 { CONN_RESET
, "Reset"},
267 { CONN_CONNECT
, "Connect"},
268 { CONN_CONNECT_ACK
, "Connect_Ack"},
274 dissect_linx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
286 proto_tree
*multicore_header_tree
;
287 proto_tree
*main_header_tree
;
288 proto_tree
*conn_header_tree
;
289 proto_tree
*ack_header_tree
;
290 proto_tree
*udata_header_tree
;
291 proto_tree
*nack_header_tree
;
292 proto_tree
*frag_header_tree
;
293 proto_tree
*rlnh_header_tree
;
296 /* Show name in protocol column */
297 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LINX");
298 /* Clear out stuff in the info column */
299 col_clear(pinfo
->cinfo
, COL_INFO
);
301 { /* Work out the details */
302 proto_item
*ti
= NULL
;
303 proto_tree
*linx_tree
= NULL
;
305 ti
= proto_tree_add_item(tree
, proto_linx
, tvb
, 0, -1, ENC_NA
);
306 linx_tree
= proto_item_add_subtree(ti
, ett_linx
);
308 dword
= tvb_get_ntohl(tvb
, offset
);
309 nexthdr
= (dword
>> 28) & 0xf;
311 /* check if we have multicore header*/
312 if (nexthdr
== ETHCM_MAIN
)
314 item
= proto_tree_add_text(linx_tree
, tvb
, 0, 4, "Multicore Header");
315 multicore_header_tree
= proto_item_add_subtree(item
, ett_linx_multicore
);
317 /* Multicore header */
320 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
321 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
322 | Next | R | Dest Coreid | Source Coreid | R |
323 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
325 proto_tree_add_item(multicore_header_tree
, hf_linx_nexthdr
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
326 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_reserved
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
327 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_dcoreid
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
328 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_scoreid
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
329 proto_tree_add_item(multicore_header_tree
, hf_linx_multicore_reserved1
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
332 /* read main header*/
333 dword
= tvb_get_ntohl(tvb
, offset
);
336 version
= (dword
>> 25) & 0x7;
337 nexthdr
= (dword
>> 28) & 0xf;
338 pkgsize
= dword
& 0x3fff;
339 linx_tvb
= tvb_new_subset(tvb
, 0, pkgsize
, pkgsize
);
340 tvb_set_reported_length(tvb
, pkgsize
);
342 /* Supports version 2 and 3 so far */
343 if (version
< 2 || version
> 3) {
344 proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 0, "Version %u in not yet supported and might be dissected incorrectly!", version
);
348 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 4, "Main Header");
349 main_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
354 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
355 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356 | Next | Ver | R | Connection |R| Packet size |
357 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
360 proto_tree_add_item(main_header_tree
, hf_linx_nexthdr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
361 proto_tree_add_item(main_header_tree
, hf_linx_main_version
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
362 proto_tree_add_item(main_header_tree
, hf_linx_main_reserved
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
363 proto_tree_add_item(main_header_tree
, hf_linx_main_connection
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
364 proto_tree_add_item(main_header_tree
, hf_linx_main_bundle
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
365 proto_tree_add_item(main_header_tree
, hf_linx_main_pkgsize
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
368 while (nexthdr
!= ETHCM_NONE
) {
370 dword
= tvb_get_ntohl(linx_tvb
, offset
);
372 nexthdr
= (dword
>>28) & 0xf;
373 conntype
= (dword
>>24) & 0xf;
374 /* Write non trivial header name to info column */
375 if ((thishdr
!= ETHCM_NONE
) && (thishdr
!= ETHCM_MAIN
)) {
376 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(thishdr
, linx_short_header_names
, "unknown"));
377 if(thishdr
== ETHCM_CONN
)
378 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(conntype
, linx_conn_cmd
, "unknown"));
387 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
388 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
389 | Next | Type |Size |Winsize| Reserved |Publish conn id|
390 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
392 : dst hw addr followed by src hw addr :
394 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
396 : Feature negotiation string (null terminated) :
398 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
401 size
= (dword
>>21) & 0x7;
402 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, (4+2*size
), "Connection Header");
403 conn_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
404 proto_tree_add_item(conn_header_tree
, hf_linx_nexthdr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
405 proto_tree_add_item(conn_header_tree
, hf_linx_conn_cmd
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
406 proto_tree_add_item(conn_header_tree
, hf_linx_conn_size
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
407 proto_tree_add_item(conn_header_tree
, hf_linx_conn_winsize
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
408 proto_tree_add_item(conn_header_tree
, hf_linx_conn_reserved
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
409 proto_tree_add_item(conn_header_tree
, hf_linx_conn_publcid
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
413 /* Most likely ETHERNET */
414 proto_tree_add_item(conn_header_tree
, hf_linx_conn_dstmac
, linx_tvb
, offset
, 6, ENC_NA
);
415 proto_tree_add_item(conn_header_tree
, hf_linx_conn_srcmac
, linx_tvb
, offset
+ 6, 6, ENC_NA
);
419 /* Feature Negotiation String */
421 proto_tree_add_item(conn_header_tree
, hf_linx_conn_feat_neg_str
, linx_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
422 offset
+= tvb_strnlen(linx_tvb
, offset
, -1);
430 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
431 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
432 | Next | Res | Count | Res | Seqno |
433 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
436 /* how many sequence numbers will be there? */
437 /* this is not implemented due to a lack of documentation with */
438 /* longer seqence numbers. */
439 /* guess there will be padding if the Seqno doesn't reach */
440 /* a 32bit boundary */
442 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 4, "NACK Header");
443 nack_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
444 proto_tree_add_item(nack_header_tree
, hf_linx_nexthdr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
445 proto_tree_add_item(nack_header_tree
, hf_linx_nack_reserv1
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
446 proto_tree_add_item(nack_header_tree
, hf_linx_nack_count
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
447 proto_tree_add_item(nack_header_tree
, hf_linx_nack_reserv2
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
448 proto_tree_add_item(nack_header_tree
, hf_linx_nack_seqno
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
453 /* User data / fragment header => Version 3 */
456 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
457 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458 | Next | Reserved |M| Frag no |
459 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
461 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465 * User data / fragment header => Version 2
468 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
469 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
470 | Next | Reserved |M| Frag no |
471 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
473 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
475 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
477 - fragments (not first fragment)
480 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
481 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
482 | Next | Reserved |M| Frag no |
483 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
487 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 12, "Udata Header");
488 udata_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
489 proto_tree_add_item(udata_header_tree
, hf_linx_nexthdr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
490 proto_tree_add_item(udata_header_tree
, hf_linx_udata_reserved
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
491 proto_tree_add_item(udata_header_tree
, hf_linx_udata_morefrags
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
492 proto_tree_add_item(udata_header_tree
, hf_linx_udata_fragno
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
494 /* signo removed in version 3 and linkaddresses extended to 32 bits */
496 proto_tree_add_item(udata_header_tree
, hf_linx_udata_signo
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
498 proto_tree_add_item(udata_header_tree
, hf_linx_udata_dstaddr16
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
499 proto_tree_add_item(udata_header_tree
, hf_linx_udata_srcaddr16
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
500 dword
= tvb_get_ntohl(linx_tvb
, offset
);
502 proto_tree_add_item(udata_header_tree
, hf_linx_udata_dstaddr32
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
503 dword
= tvb_get_ntohl(linx_tvb
, offset
);
505 proto_tree_add_item(udata_header_tree
, hf_linx_udata_srcaddr32
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
506 if(dword
== 0 && tvb_get_ntohl(linx_tvb
, offset
) == 0) {
514 /* (dstaddr == srcaddr == 0) -> RLNH Protocol Message */
516 dword
= tvb_get_ntohl(linx_tvb
, offset
);
518 /* Write to info column */
519 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "rlnh:%s ", val_to_str_const(dword
, linx_short_rlnh_names
, "unknown"));
521 /* create new paragraph for RLNH */
522 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 4, "RLNH");
523 rlnh_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
526 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_msg_type32
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
529 /* in version 2 of the rlnh protocol the length of the message type is restricted to 8 bits */
530 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_msg_reserved
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
531 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_msg_type8
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
537 /* XXX what is this? */
539 case RLNH_QUERY_NAME
:
540 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
542 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_name
, linx_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
543 offset
+= tvb_strnlen(linx_tvb
, offset
, -1);
546 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
548 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_name
, linx_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
549 offset
+= tvb_strnlen(linx_tvb
, offset
, -1);
552 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
555 case RLNH_UNPUBLISH_ACK
:
556 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
560 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_version
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
561 /* This is not working if nodes are at different versions. Only the latest value will be saved in rlnh_version */
562 rlnh_version
= tvb_get_ntohl(linx_tvb
, offset
);
565 case RLNH_INIT_REPLY
:
566 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_status
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
568 if(rlnh_version
> 1) {
569 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_feat_neg_str
, linx_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
570 offset
+= tvb_strnlen(linx_tvb
, offset
, -1);
573 case RLNH_PUBLISH_PEER
:
574 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_src_linkaddr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
576 proto_tree_add_item(rlnh_header_tree
, hf_linx_rlnh_peer_linkaddr
, linx_tvb
, offset
, -1, ENC_BIG_ENDIAN
);
577 offset
+= tvb_strnlen(linx_tvb
, offset
, -1);
580 /* no known Message type... */
581 /* this could be done better */
582 proto_tree_add_text(rlnh_header_tree
, linx_tvb
, offset
, 0,"ERROR: Header \"%u\" not recognized", dword
);
586 /* Is there payload? */
587 /* anything better to do with that? */
588 payloadsize
= pkgsize
-offset
;
590 proto_tree_add_text(linx_tree
, linx_tvb
, offset
, payloadsize
,"%u bytes data", payloadsize
);
596 /* Reliable header */
599 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
600 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
601 | Next |R| Res.| Ackno | Seqno |
602 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
604 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 4, "Ack Header");
605 ack_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
606 proto_tree_add_item(ack_header_tree
, hf_linx_nexthdr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
607 proto_tree_add_item(ack_header_tree
, hf_linx_ack_request
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
608 proto_tree_add_item(ack_header_tree
, hf_linx_ack_reserved
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
609 proto_tree_add_item(ack_header_tree
, hf_linx_ack_ackno
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
610 proto_tree_add_item(ack_header_tree
, hf_linx_ack_seqno
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
616 - fragments (not first fragment)
619 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
620 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
621 | Next | Reserved |M| Frag no |
622 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
625 item
= proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 4, "Fragmentation Header");
626 frag_header_tree
= proto_item_add_subtree(item
, ett_linx_main
);
627 proto_tree_add_item(frag_header_tree
, hf_linx_nexthdr
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
628 proto_tree_add_item(frag_header_tree
, hf_linx_frag_reserved
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
629 proto_tree_add_item(frag_header_tree
, hf_linx_frag_morefrags
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
630 proto_tree_add_item(frag_header_tree
, hf_linx_frag_fragno
, linx_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
635 proto_tree_add_text(linx_tree
, linx_tvb
, offset
, 4,"ERROR: Header \"%u\" not recognized", thishdr
);
636 nexthdr
= ETHCM_NONE
; /* avoid endless loop with faulty packages */
645 /* Protocol Initialisation */
647 proto_register_linx(void)
650 /* Registering Data Structures */
652 static hf_register_info hf
[] = {
654 { "Next Header", "linx.nexthdr", FT_UINT32
, BASE_DEC
, VALS(linx_long_header_names
), 0xf0000000, NULL
, HFILL
},
656 { &hf_linx_multicore_scoreid
, /* in ETHCM_MULTICORE */
657 { "Source coreid", "linx.scoreid", FT_UINT32
, BASE_DEC
, VALS(linx_coreid
), 0x0000ff00, "Multicore source core id", HFILL
},
659 { &hf_linx_multicore_dcoreid
, /* in ETHCM_MULTICORE */
660 { "Destination coreid", "linx.dcoreid", FT_UINT32
, BASE_DEC
, VALS(linx_coreid
), 0x00ff0000, "Multicore destination core id", HFILL
},
662 { &hf_linx_multicore_reserved
, /* in ETHCM_MULTICORE */
663 { "Reserved", "linx.reserved8", FT_UINT32
, BASE_DEC
, NULL
, 0x0f000000, "Multicore Hdr Reserved", HFILL
},
665 { &hf_linx_multicore_reserved1
, /* in ETHCM_MULTICORE */
666 { "Reserved", "linx.reserved9", FT_UINT32
, BASE_DEC
, NULL
, 0x000000ff, "Multicore Hdr Reserved", HFILL
},
668 { &hf_linx_main_version
, /* in ETHCM_MAIN */
669 { "Version", "linx.version", FT_UINT32
, BASE_DEC
, NULL
, 0x0e000000, "LINX Version", HFILL
},
671 { &hf_linx_main_reserved
, /* in ETHCM_MAIN */
672 { "Reserved", "linx.reserved1", FT_UINT32
, BASE_DEC
, NULL
, 0x01800000, "Main Hdr Reserved", HFILL
},
674 { &hf_linx_main_connection
, /* in ETHCM_MAIN */
675 { "Connection", "linx.connection", FT_UINT32
, BASE_DEC
, NULL
, 0x007f8000, NULL
, HFILL
},
677 { &hf_linx_main_bundle
, /* in ETHCM_MAIN */
678 { "Bundle", "linx.bundle", FT_UINT32
, BASE_DEC
, VALS(linx_boolean
), 0x00004000, NULL
, HFILL
},
680 { &hf_linx_main_pkgsize
, /* in ETHCM_MAIN */
681 { "Package Size", "linx.pcksize", FT_UINT32
, BASE_DEC
, NULL
, 0x00003fff, NULL
, HFILL
},
683 { &hf_linx_udata_reserved
, /* in ETHCM_UDATA */
684 { "Reserved", "linx.reserved5", FT_UINT32
, BASE_DEC
, NULL
, 0x0fff0000, "Udata Hdr Reserved", HFILL
},
686 { &hf_linx_udata_morefrags
, /* in ETHCM_UDATA */
687 { "More Fragments", "linx.morefra", FT_UINT32
, BASE_DEC
, VALS(linx_boolean
), 0x00008000, "More fragments follow", HFILL
},
689 { &hf_linx_udata_fragno
, /* in ETHCM_UDATA */
690 { "Fragment Number", "linx.fragno", FT_UINT32
, BASE_DEC
, VALS(linx_nofragment
), 0x00007fff, NULL
, HFILL
},
692 { &hf_linx_udata_signo
, /* in ETHCM_UDATA */
693 { "Signal Number", "linx.signo", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, NULL
, HFILL
},
695 { &hf_linx_udata_dstaddr16
, /* in ETHCM_UDATA - protocol version 2 */
696 { "Receiver Address", "linx.dstaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffff0000, NULL
, HFILL
},
698 { &hf_linx_udata_dstaddr32
, /* in ETHCM_UDATA - protocol version 3 */
699 { "Receiver Address", "linx.dstaddr32", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, NULL
, HFILL
},
701 { &hf_linx_udata_srcaddr16
, /* in ETHCM_UDATA - protocol version 2 */
702 { "Sender Address", "linx.srcaddr", FT_UINT32
, BASE_DEC
, NULL
, 0x0000ffff, NULL
, HFILL
},
704 { &hf_linx_udata_srcaddr32
, /* in ETHCM_UDATA - protocol version 3 */
705 { "Sender Address", "linx.srcaddr32", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, NULL
, HFILL
},
707 { &hf_linx_ack_request
, /* in ETHCM_ACK */
708 { "ACK-request", "linx.ackreq", FT_UINT32
, BASE_DEC
, VALS(linx_boolean
), 0x08000000, NULL
, HFILL
},
710 { &hf_linx_ack_reserved
, /* in ETHCM_ACK */
711 { "Reserved", "linx.reserved7", FT_UINT32
, BASE_DEC
, NULL
, 0x07000000, "ACK Hdr Reserved", HFILL
},
713 { &hf_linx_ack_ackno
, /* in ETHCM_ACK */
714 { "ACK Number", "linx.ackno", FT_UINT32
, BASE_DEC
, NULL
, 0x00fff000, NULL
, HFILL
},
716 { &hf_linx_ack_seqno
, /* in ETHCM_ACK */
717 { "Sequence Number", "linx.seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x00000fff, NULL
, HFILL
},
719 { &hf_linx_conn_cmd
, /* in ETHCM_CONN */
720 { "Command", "linx.cmd", FT_UINT32
, BASE_DEC
, VALS(linx_conn_cmd
), 0x0f000000, NULL
, HFILL
},
722 { &hf_linx_conn_size
, /* in ETHCM_CONN */
723 { "Size", "linx.size", FT_UINT32
, BASE_DEC
, NULL
, 0x00e00000, NULL
, HFILL
},
725 { &hf_linx_conn_winsize
, /* in ETHCM_CONN */
726 { "WinSize", "linx.winsize", FT_UINT32
, BASE_DEC
, NULL
, 0x001e0000, "Window Size", HFILL
},
728 { &hf_linx_conn_reserved
, /* in ETHCM_CONN */
729 { "Reserved", "linx.reserved3", FT_UINT32
, BASE_DEC
, NULL
, 0x0001ff00, "Conn Hdr Reserved", HFILL
},
731 { &hf_linx_conn_publcid
, /* in ETHCM_CONN */
732 { "Publish Conn ID", "linx.publcid", FT_UINT32
, BASE_DEC
, NULL
, 0x000000ff, NULL
, HFILL
},
734 { &hf_linx_conn_srcmac
, /* in ETHCM_CONN */
735 { "Source", "linx.srcmaddr_ether", FT_ETHER
, BASE_NONE
, NULL
, 0x0, "Source Media Address (ethernet)", HFILL
},
737 { &hf_linx_conn_dstmac
, /* in ETHCM_CONN */
738 { "Destination", "linx.destmaddr_ether", FT_ETHER
, BASE_NONE
, NULL
, 0x0, "Destination Media Address (ethernet)", HFILL
},
740 { &hf_linx_conn_feat_neg_str
, /* in ETHCM_CONN */
741 { "Feature Negotiation String", "linx.feat_neg_str", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
743 { &hf_linx_frag_reserved
, /* in ETHCM_FRAG */
744 { "Reserved", "linx.reserved6", FT_UINT32
, BASE_DEC
, NULL
, 0x0fff0000, "Frag Hdr Reserved", HFILL
},
746 { &hf_linx_frag_morefrags
, /* in ETHCM_FRAG */
747 { "More Fragments", "linx.morefr2", FT_UINT32
, BASE_DEC
, VALS(linx_boolean
), 0x00008000, NULL
, HFILL
},
749 { &hf_linx_frag_fragno
, /* in ETHCM_FRAG */
750 { "Fragment Number", "linx.fragno2", FT_UINT32
, BASE_DEC
, NULL
, 0x00007fff, NULL
, HFILL
},
752 { &hf_linx_nack_reserv1
, /* in ETHCM_NACK */
753 { "Reserved", "linx.nack_reserv", FT_UINT32
, BASE_DEC
, NULL
, 0x0f000000, "Nack Hdr Reserved", HFILL
},
755 { &hf_linx_nack_count
, /* in ETHCM_NACK */
756 { "Count", "linx.nack_count", FT_UINT32
, BASE_DEC
, NULL
, 0x00ff0000, NULL
, HFILL
},
758 { &hf_linx_nack_reserv2
, /* in ETHCM_NACK */
759 { "Reserved", "linx.nack_reserv", FT_UINT32
, BASE_DEC
, NULL
, 0x0000f000, "Nack Hdr Reserved", HFILL
},
761 { &hf_linx_nack_seqno
, /* in ETHCM_NACK */
762 { "Sequence Number", "linx.nack_seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x00000fff, NULL
, HFILL
},
766 { &hf_linx_rlnh_msg_type32
, /* in RLNH */
767 { "RLNH msg type", "linx.rlnh_msg_type", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0xffffffff, "RLNH message type", HFILL
},
769 { &hf_linx_rlnh_msg_type8
, /* in RLNH */
770 { "RLNH msg type", "linx.rlnh_msg_type8", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0x000000ff, "RLNH message type", HFILL
},
772 { &hf_linx_rlnh_msg_reserved
, /* in RLNH */
773 { "RLNH msg reserved", "linx.rlnh_msg_reserved", FT_UINT32
, BASE_DEC
, NULL
, 0xffffff00, "RLNH message reserved", HFILL
},
776 { &hf_linx_rlnh_linkaddr
, /* in RLNH */
777 { "RLNH linkaddr", "linx.rlnh_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, "RLNH linkaddress", HFILL
},
780 { &hf_linx_rlnh_src_linkaddr
, /* in RLNH */
781 { "RLNH src linkaddr", "linx.rlnh_src_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, "RLNH source linkaddress", HFILL
},
783 { &hf_linx_rlnh_peer_linkaddr
, /* in RLNH */
784 { "RLNH peer linkaddr", "linx.rlnh_peer_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, "RLNH peer linkaddress", HFILL
},
786 { &hf_linx_rlnh_version
, /* in RLNH */
787 { "RLNH version", "linx.rlnh_version", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, NULL
, HFILL
},
789 { &hf_linx_rlnh_status
, /* in RLNH */
790 { "RLNH reply", "linx.rlnh_status", FT_UINT32
, BASE_DEC
, VALS(linx_rlnh_reply
), 0xffffffff, NULL
, HFILL
},
792 { &hf_linx_rlnh_name
, /* in RLNH */
793 { "RLNH name", "linx.rlnh_name", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
795 { &hf_linx_rlnh_feat_neg_str
, /* in RLNH */
796 { "RLNH Feature Negotiation String", "linx.rlnh_feat_neg_str", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
800 /* Setup protocol subtree array */
801 static gint
*ett
[] = {
810 proto_linx
= proto_register_protocol (
811 "ENEA LINX", /* name */
812 "LINX", /* short name */
816 /* Protocol Registering data structures. */
817 proto_register_field_array(proto_linx
, hf
, array_length(hf
));
818 proto_register_subtree_array(ett
, array_length(ett
));
822 /* Protocol Handoff */
824 proto_reg_handoff_linx(void)
826 dissector_handle_t linx_handle
;
828 linx_handle
= create_dissector_handle(dissect_linx
, proto_linx
);
829 dissector_add_uint("ethertype", ETHERTYPE_LINX
, linx_handle
);
832 /************ TCP CM **************/
834 #define TCP_PORT_LINX 19790
837 dissect_linx_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
840 tvbuff_t
*linx_tcp_tvb
;
844 proto_tree
*linx_tcp_tree
;
845 proto_tree
*tcp_header_tree
;
846 proto_tree
*rlnh_header_tree
;
852 /* Show name in protocol column */
853 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LINX/TCP");
855 /* Clear out stuff in the info column */
856 col_clear(pinfo
->cinfo
, COL_INFO
);
858 dword
= tvb_get_ntohl(tvb
, 0);
859 version
= (dword
>> 16) & 0xFF;
860 type
= (dword
>> 24) & 0xFF;
862 /* size of linx tcp cm header */
866 dword
= tvb_get_ntohl(tvb
, 12);
867 size
+= (dword
& 0xFFFFFFFF);
870 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "tcpcm:%s ", val_to_str_const(type
, linx_short_tcp_names
, "unknown"));
872 tvb_set_reported_length(tvb
, size
);
873 linx_tcp_tvb
= tvb_new_subset(tvb
, 0, size
, size
);
875 ti
= proto_tree_add_item(tree
, proto_linx_tcp
, linx_tcp_tvb
, 0, -1, ENC_NA
);
876 linx_tcp_tree
= proto_item_add_subtree(ti
, ett_linx_tcp
);
879 proto_tree_add_text(linx_tcp_tree
, linx_tcp_tvb
, 0, 0, "Version %u not yet supported and might be dissected incorrectly!", version
);
882 item
= proto_tree_add_text(linx_tcp_tree
, linx_tcp_tvb
, 0, 16, "TCP CM Header");
883 tcp_header_tree
= proto_item_add_subtree(item
, ett_linx_tcp
);
885 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_type
, linx_tcp_tvb
, 0, 4, ENC_BIG_ENDIAN
);
886 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_version
, linx_tcp_tvb
, 0, 4, ENC_BIG_ENDIAN
);
887 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_oob
, linx_tcp_tvb
, 0, 4, ENC_BIG_ENDIAN
);
888 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_src
, linx_tcp_tvb
, 4, 4, ENC_BIG_ENDIAN
);
889 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_dst
, linx_tcp_tvb
, 8, 4, ENC_BIG_ENDIAN
);
890 proto_tree_add_item(tcp_header_tree
, hf_linx_tcp_size
, linx_tcp_tvb
, 12, 4, ENC_BIG_ENDIAN
);
894 if (type
== 0x55) { /* UDATA */
895 dword
= tvb_get_ntohl(linx_tcp_tvb
, 8);
896 if (dword
== 0) { /* RLNH Message*/
898 dword
= tvb_get_ntohl(linx_tcp_tvb
, offset
);
900 /* Write to info column */
901 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "rlnh:%s ", val_to_str_const(dword
, linx_short_rlnh_names
, "unknown"));
903 /* create new paragraph for RLNH */
904 item
= proto_tree_add_text(linx_tcp_tree
, linx_tcp_tvb
, offset
, 4, "RLNH");
905 rlnh_header_tree
= proto_item_add_subtree(item
, ett_linx_tcp
);
908 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_msg_type32
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
912 * In version 2 of the rlnh protocol the length of the message type is
913 * restricted to 8 bits.
915 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_msg_reserved
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
916 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_msg_type8
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
923 case RLNH_QUERY_NAME
:
924 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
926 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_name
, linx_tcp_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
927 /*offset += tvb_strnlen(linx_tcp_tvb, offset, -1);*/
930 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
932 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_name
, linx_tcp_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
933 /*offset += tvb_strnlen(linx_tcp_tvb, offset, -1);*/
936 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
939 case RLNH_UNPUBLISH_ACK
:
940 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
944 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_version
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
945 rlnh_version
= tvb_get_ntohl(linx_tcp_tvb
, offset
);
948 case RLNH_INIT_REPLY
:
949 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_status
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
951 if(rlnh_version
> 1) {
952 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_feat_neg_str
, linx_tcp_tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
953 /*offset += tvb_strnlen(linx_tcp_tvb, offset, -1);*/
956 case RLNH_PUBLISH_PEER
:
957 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_src_linkaddr
, linx_tcp_tvb
, offset
, 4, ENC_BIG_ENDIAN
);
959 proto_tree_add_item(rlnh_header_tree
, hf_linx_tcp_rlnh_peer_linkaddr
, linx_tcp_tvb
, offset
, -1, ENC_BIG_ENDIAN
);
960 /*offset += tvb_strnlen(linx_tcp_tvb, offset, -1);*/
963 /* No known Message type */
964 proto_tree_add_text(rlnh_header_tree
, linx_tcp_tvb
, offset
, 0, "ERROR: Header \"%u\" not recognized", dword
);
969 payloadsize
= size
-offset
;
971 proto_tree_add_text(linx_tcp_tree
, linx_tcp_tvb
, offset
, payloadsize
, "%u bytes data", payloadsize
);
978 proto_register_linx_tcp(void)
980 static hf_register_info hf
[] = {
982 { &hf_linx_tcp_reserved
,
983 { "Reserved", "linxtcp.reserved", FT_UINT32
, BASE_DEC
, NULL
, 0x00007FFF, "TCP CM reserved", HFILL
},
987 { "Out-of-band", "linxtcp.oob", FT_UINT32
, BASE_DEC
, NULL
, 0x00008000, "TCP CM oob", HFILL
},
989 { &hf_linx_tcp_version
,
990 { "Version", "linxtcp.version", FT_UINT32
, BASE_DEC
, NULL
, 0x00FF0000, "TCP CM version", HFILL
},
993 { "Type", "linxtcp.type", FT_UINT32
, BASE_HEX
, VALS(linx_long_tcp_names
), 0xFF000000, "TCP CM type", HFILL
},
996 { "Source", "linxtcp.src", FT_UINT32
, BASE_DEC
, NULL
, 0xFFFFFFFF, "TCP CM source", HFILL
},
999 { "Destination", "linxtcp.dst", FT_UINT32
, BASE_DEC
, NULL
, 0xFFFFFFFF, "TCP CM destination", HFILL
},
1001 { &hf_linx_tcp_size
,
1002 { "Size", "linxtcp.size", FT_UINT32
, BASE_DEC
, NULL
, 0xFFFFFFFF, "TCP CM size", HFILL
},
1006 { &hf_linx_tcp_rlnh_msg_type32
,
1007 { "RLNH msg type", "linxtcp.rlnh_msg_type", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0xffffffff, "RLNH message type", HFILL
},
1009 { &hf_linx_tcp_rlnh_msg_type8
,
1010 { "RLNH msg type", "linxtcp.rlnh_msg_type8", FT_UINT32
, BASE_DEC
, VALS(linx_long_rlnh_names
), 0x000000ff, "RLNH message type", HFILL
},
1012 { &hf_linx_tcp_rlnh_msg_reserved
,
1013 { "RLNH msg reserved", "linxtcp.rlnh_msg_reserved", FT_UINT32
, BASE_DEC
, NULL
, 0xffffff00, "RLNH message reserved", HFILL
},
1016 { &hf_linx_tcp_rlnh_linkaddr
,
1017 { "RLNH linkaddr", "linxtcp.rlnh_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, "RLNH linkaddress", HFILL
},
1020 { &hf_linx_tcp_rlnh_src_linkaddr
,
1021 { "RLNH src linkaddr", "linxtcp.rlnh_src_linkaddr", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, "RLNH source linkaddress", HFILL
},
1023 { &hf_linx_tcp_rlnh_peer_linkaddr
,
1024 { "RLNH peer linkaddr", "linxtcp.rlnh_peer_linkaddr", FT_UINT32
,
1025 BASE_DEC
, NULL
, 0xffffffff, "RLNH peer linkaddress", HFILL
},
1027 { &hf_linx_tcp_rlnh_version
,
1028 { "RLNH version", "linxtcp.rlnh_version", FT_UINT32
, BASE_DEC
, NULL
, 0xffffffff, NULL
, HFILL
},
1030 { &hf_linx_tcp_rlnh_status
,
1031 { "RLNH reply", "linxtcp.rlnh_status", FT_UINT32
, BASE_DEC
, VALS(linx_rlnh_reply
), 0xffffffff, NULL
, HFILL
},
1033 { &hf_linx_tcp_rlnh_name
,
1034 { "RLNH name", "linxtcp.rlnh_name", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
1036 { &hf_linx_tcp_rlnh_feat_neg_str
,
1037 { "RLNH Feature Negotiation String", "linxtcp.rlnh_feat_neg_str", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
1041 static gint
*ett
[] = {
1044 proto_linx_tcp
= proto_register_protocol("ENEA LINX over TCP", "LINX/TCP", "linxtcp");
1045 proto_register_field_array(proto_linx_tcp
, hf
, array_length(hf
));
1046 proto_register_subtree_array(ett
, array_length(ett
));
1050 proto_reg_handoff_linx_tcp(void)
1052 dissector_handle_t linx_tcp_handle
;
1053 linx_tcp_handle
= create_dissector_handle(dissect_linx_tcp
, proto_linx_tcp
);
1054 dissector_add_uint("tcp.port", TCP_PORT_LINX
, linx_tcp_handle
);