Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-linx.c
blobd5903fd538734c5e1b54bfd5f81ebe527706cfcb
1 /* packet-linx.c
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
17 * Fits currently to
18 * Enea LINX for Linux
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
31 #include "config.h"
33 #include <epan/packet.h>
34 #include <epan/expert.h>
35 #include <epan/etypes.h>
36 #include <epan/tfs.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;
49 /* ALL */
50 static int hf_linx_nexthdr;
52 /* MULTICORE */
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;
59 /* MAIN */
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;
66 /* UDATA */
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;
77 /* ACK */
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;
83 /* CONN */
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;
92 /* FRAG */
93 static int hf_linx_frag_reserved;
94 static int hf_linx_frag_morefrags;
95 static int hf_linx_frag_fragno;
97 /* NACK */
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;
103 /* RLNH */
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;
115 /* TCP CM */
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;
138 static int ett_linx;
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"},
170 { ETHCM_ACK, "ACK"},
171 { ETHCM_NACK, "NACK"},
172 { ETHCM_NONE, "NONE"},
173 { 0, NULL}
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"},
181 { ETHCM_ACK, "Ack"},
182 { ETHCM_NACK, "Nack"},
183 { ETHCM_NONE, "None"},
184 { 0, NULL}
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"},
197 {0, NULL}
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"},
205 {0, NULL}
208 /* RLNH version 1 */
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
214 #define RLNH_INIT 5
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"},
227 { 0, NULL}
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"},
239 { 0, NULL}
242 static const value_string linx_rlnh_reply[] = {
243 { 0, "Version supported"},
244 { 1, "Version NOT supported"},
245 { 0, NULL}
248 static const value_string linx_nofragment[] = {
249 { 0x7fff, "No Fragment"},
250 { 0, NULL}
253 static const value_string linx_coreid[]= {
254 {0xff, "None"},
255 {0, NULL}
258 #define CONN_RESET 1
259 #define CONN_CONNECT 2
260 #define CONN_CONNECT_ACK 3
261 #define CONN_ACK 4
263 static const value_string linx_conn_cmd[] = {
264 { CONN_RESET, "Reset"},
265 { CONN_CONNECT, "Connect"},
266 { CONN_CONNECT_ACK, "Connect_Ack"},
267 { CONN_ACK, "Ack"},
268 { 0, NULL}
271 static int
272 dissect_linx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
274 uint32_t dword;
275 int offset = 0;
276 int nexthdr;
277 int thishdr;
278 int size;
279 int pkgsize;
280 int payloadsize;
281 int version;
282 int conntype;
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 */
315 0 1 2 3
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);
327 offset += 4;
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;
336 /* Main header */
337 main_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 4, ett_linx_main, NULL, "Main Header");
340 0 1 2 3
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);
353 offset += 4;
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);
363 thishdr = nexthdr;
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"));
373 switch (thishdr) {
375 case ETHCM_CONN:
376 /* Connect header */
378 0 1 2 3
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);
401 offset += 4;
402 /* MEDIA ADDRESS */
403 if (size == 6) {
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);
409 offset += (2*size);
410 /* Feature Negotiation String */
411 if(version > 2) {
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);
415 break;
417 case ETHCM_NACK:
418 /* Nack header */
420 0 1 2 3
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);
439 offset += 4;
440 break;
442 case ETHCM_UDATA:
443 /* User data / fragment header => Version 3 */
445 0 1 2 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
450 | Destination |
451 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
452 | Source |
453 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
455 * User data / fragment header => Version 2
457 0 1 2 3
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
462 | Reserved |
463 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
464 | Dst | Src |
465 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467 - fragments (not first fragment)
469 0 1 2 3
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);
482 offset += 4;
483 /* signo removed in version 3 and linkaddresses extended to 32 bits */
484 if(version == 2) {
485 proto_tree_add_item(udata_header_tree, hf_linx_udata_signo , tvb, offset, 4, ENC_BIG_ENDIAN);
486 offset += 4;
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);
490 } else {
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);
493 offset += 4;
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) {
496 dword = 0;
497 } else {
498 dword = 1;
501 offset += 4;
502 if (dword == 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");
513 if(version == 1) {
514 msg_item = proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_msg_type32, tvb, offset, 4, ENC_BIG_ENDIAN);
515 offset += 4;
516 } else {
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);
520 offset += 4;
523 switch (dword) {
524 case RLNH_LINK_ADDR:
525 /* XXX what is this? */
526 break;
527 case RLNH_QUERY_NAME:
528 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
529 offset += 4;
530 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_name, tvb, offset, -1, ENC_ASCII);
531 offset += tvb_strnlen(tvb, offset, -1);
532 break;
533 case RLNH_PUBLISH:
534 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
535 offset += 4;
536 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_name, tvb, offset, -1, ENC_ASCII);
537 offset += tvb_strnlen(tvb, offset, -1);
538 break;
539 case RLNH_UNPUBLISH:
540 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
541 offset += 4;
542 break;
543 case RLNH_UNPUBLISH_ACK:
544 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
545 offset += 4;
546 break;
547 case RLNH_INIT:
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);
551 offset += 4;
552 break;
553 case RLNH_INIT_REPLY:
554 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_status, tvb, offset, 4, ENC_BIG_ENDIAN);
555 offset += 4;
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);
560 break;
561 case RLNH_PUBLISH_PEER:
562 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
563 offset += 4;
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);
566 break;
567 default:
568 /* no known Message type... */
569 expert_add_info(pinfo, msg_item, &ei_linx_rlnh_msg);
570 break;
572 } else {
573 /* Is there payload? */
574 /* anything better to do with that? */
575 payloadsize = pkgsize-offset;
576 if (payloadsize) {
577 proto_tree_add_item(linx_tree, hf_linx_udata_payload, tvb, offset, payloadsize, ENC_NA);
580 break;
582 case ETHCM_ACK:
583 /* Reliable header */
585 0 1 2 3
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);
597 offset += 4;
598 break;
600 case ETHCM_FRAG:
602 - fragments (not first fragment)
604 0 1 2 3
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);
616 offset += 4;
617 break;
619 default:
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 */
622 break;
627 return tvb_captured_length(tvb);
631 /* Protocol Initialisation */
632 void
633 proto_register_linx(void)
636 /* Registering Data Structures */
638 static hf_register_info hf[] = {
639 { &hf_linx_nexthdr,
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 },
754 /* RLNH */
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 },
764 #if 0
765 { &hf_linx_rlnh_linkaddr, /* in RLNH */
766 { "RLNH linkaddr", "linx.rlnh_linkaddr", FT_UINT32, BASE_DEC, NULL, 0xffffffff, "RLNH linkaddress", HFILL },
768 #endif
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[] = {
791 &ett_linx,
792 &ett_linx_multicore,
793 &ett_linx_main,
794 &ett_linx_error,
795 &ett_linx_udata,
796 &ett_linx_ack
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 */
810 "linx" /* abbrev */
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 */
825 void
826 proto_reg_handoff_linx(void)
828 dissector_add_uint("ethertype", ETHERTYPE_LINX, linx_handle);
831 /************ TCP CM **************/
833 static int
834 dissect_linx_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
836 uint32_t dword;
837 int offset = 0;
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;
842 int payloadsize;
843 int version;
844 int size;
845 int type;
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 */
858 size = 16;
860 if (type == 0x55) {
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);
879 if (version != 3) {
880 expert_add_info(pinfo, ver_item, &ei_linx_tcp_version);
883 offset += 16;
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");
897 if(version == 1) {
898 msg_item = proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_msg_type32, tvb, offset, 4, ENC_BIG_ENDIAN);
899 offset += 4;
900 } else {
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);
907 offset += 4;
910 switch (dword) {
911 case RLNH_LINK_ADDR:
912 break;
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);
915 offset += 4;
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);*/
918 break;
919 case RLNH_PUBLISH:
920 proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
921 offset += 4;
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);*/
924 break;
925 case RLNH_UNPUBLISH:
926 proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
927 /*offset += 4;*/
928 break;
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);
931 /*offset += 4;*/
932 break;
933 case RLNH_INIT:
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);
936 /*offset += 4;*/
937 break;
938 case RLNH_INIT_REPLY:
939 proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_status, tvb, offset, 4, ENC_BIG_ENDIAN);
940 offset += 4;
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);*/
945 break;
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);
948 offset += 4;
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);*/
951 break;
952 default:
953 /* No known Message type */
954 expert_add_info(pinfo, msg_item, &ei_linx_tcp_rlnh_msg);
955 break;
957 } else {
958 /* User payload */
959 payloadsize = size-offset;
960 if (payloadsize) {
961 proto_tree_add_item(linx_tcp_tree, hf_linx_tcp_payload, tvb, offset, payloadsize, ENC_NA);
965 return tvb_captured_length(tvb);
968 void
969 proto_register_linx_tcp(void)
971 static hf_register_info hf[] = {
972 #if 0
973 { &hf_linx_tcp_reserved,
974 { "Reserved", "linxtcp.reserved", FT_UINT32, BASE_DEC, NULL, 0x00007FFF, "TCP CM reserved", HFILL },
976 #endif
977 { &hf_linx_tcp_oob,
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 },
983 { &hf_linx_tcp_type,
984 { "Type", "linxtcp.type", FT_UINT32, BASE_HEX, VALS(linx_long_tcp_names), 0xFF000000, "TCP CM type", HFILL },
986 { &hf_linx_tcp_src,
987 { "Source", "linxtcp.src", FT_UINT32, BASE_DEC, NULL, 0x0, "TCP CM source", HFILL },
989 { &hf_linx_tcp_dst,
990 { "Destination", "linxtcp.dst", FT_UINT32, BASE_DEC, NULL, 0x0, "TCP CM destination", HFILL },
992 { &hf_linx_tcp_size,
993 { "Size", "linxtcp.size", FT_UINT32, BASE_DEC, NULL, 0x0, "TCP CM size", HFILL },
996 /* RLNH */
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 },
1006 #if 0
1007 { &hf_linx_tcp_rlnh_linkaddr,
1008 { "RLNH linkaddr", "linxtcp.rlnh_linkaddr", FT_UINT32, BASE_DEC, NULL, 0x0, "RLNH linkaddress", HFILL },
1010 #endif
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[] = {
1036 &ett_linx_tcp,
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));
1053 void
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
1066 * Local variables:
1067 * c-basic-offset: 8
1068 * tab-width: 8
1069 * indent-tabs-mode: t
1070 * End:
1072 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1073 * :indentSize=8:tabSize=8:noTabs=false: