MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-linx.c
blob42661312ca8aec9610c0908f5acb84b694349561
1 /* packet-linx.c
2 * Routines for LINX packet dissection
4 * Copyright 2006, Martin Peylo <martin.peylo@siemens.com>
6 * $Id$
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
31 * Fits currently to
32 * Enea LINX for Linux
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
45 #include "config.h"
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;
56 /* ALL */
57 static int hf_linx_nexthdr = -1;
59 /* MULTICORE */
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;
66 /* MAIN */
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;
73 /* UDATA */
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;
83 /* ACK */
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;
89 /* CONN */
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;
98 /* FRAG */
99 static int hf_linx_frag_reserved = -1;
100 static int hf_linx_frag_morefrags = -1;
101 static int hf_linx_frag_fragno = -1;
103 /* NACK */
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;
109 /* RLNH */
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;
121 /* TCP CM */
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"},
166 { ETHCM_ACK, "ACK"},
167 { ETHCM_NACK, "NACK"},
168 { ETHCM_NONE, "NONE"},
169 { 0, NULL}
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"},
177 { ETHCM_ACK, "Ack"},
178 { ETHCM_NACK, "Nack"},
179 { ETHCM_NONE, "None"},
180 { 0, NULL}
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"},
193 {0, NULL}
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"},
201 {0, NULL}
204 /* RLNH version 1 */
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
210 #define RLNH_INIT 5
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"},
223 { 0, NULL}
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"},
235 { 0, NULL}
238 static const value_string linx_rlnh_reply[] = {
239 { 0, "Version supported"},
240 { 1, "Version NOT supported"},
241 { 0, NULL}
244 static const value_string linx_boolean[] = {
245 { 0, "No"},
246 { 1, "Yes"},
247 { 0, NULL}
250 static const value_string linx_nofragment[] = {
251 { 0x7fff, "No Fragment"},
252 { 0, NULL}
255 static const value_string linx_coreid[]= {
256 {0xff, "None"},
257 {0, NULL}
260 #define CONN_RESET 1
261 #define CONN_CONNECT 2
262 #define CONN_CONNECT_ACK 3
263 #define CONN_ACK 4
265 static const value_string linx_conn_cmd[] = {
266 { CONN_RESET, "Reset"},
267 { CONN_CONNECT, "Connect"},
268 { CONN_CONNECT_ACK, "Connect_Ack"},
269 { CONN_ACK, "Ack"},
270 { 0, NULL}
273 static void
274 dissect_linx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
276 guint32 dword;
277 int offset = 0;
278 int nexthdr;
279 int thishdr;
280 int size;
281 int pkgsize;
282 int payloadsize;
283 int version;
284 int conntype;
285 proto_item *item;
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;
294 tvbuff_t *linx_tvb;
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 */
319 0 1 2 3
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);
331 offset += 4;
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);
347 /* main header */
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);
351 /* Main header */
353 0 1 2 3
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);
366 offset += 4;
368 while (nexthdr != ETHCM_NONE) {
370 dword = tvb_get_ntohl(linx_tvb, offset);
371 thishdr = nexthdr;
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"));
381 switch (thishdr) {
383 case ETHCM_CONN:
384 /* Connect header */
386 0 1 2 3
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);
410 offset += 4;
411 /* MEDIA ADDRESS */
412 if (size == 6) {
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);
418 offset += (2*size);
419 /* Feature Negotiation String */
420 if(version > 2) {
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);
424 break;
426 case ETHCM_NACK:
427 /* Nack header */
429 0 1 2 3
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);
449 offset += 4;
450 break;
452 case ETHCM_UDATA:
453 /* User data / fragment header => Version 3 */
455 0 1 2 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460 | Destination |
461 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
462 | Source |
463 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465 * User data / fragment header => Version 2
467 0 1 2 3
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
472 | Reserved |
473 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
474 | Dst | Src |
475 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
477 - fragments (not first fragment)
479 0 1 2 3
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);
493 offset += 4;
494 /* signo removed in version 3 and linkaddresses extended to 32 bits */
495 if(version == 2) {
496 proto_tree_add_item(udata_header_tree, hf_linx_udata_signo , linx_tvb, offset, 4, ENC_BIG_ENDIAN);
497 offset += 4;
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);
501 } else {
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);
504 offset += 4;
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) {
507 dword = 0;
508 } else {
509 dword = 1;
512 offset += 4;
513 if (dword == 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);
525 if(version == 1) {
526 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_msg_type32, linx_tvb, offset, 4, ENC_BIG_ENDIAN);
527 offset += 4;
528 } else {
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);
532 offset += 4;
535 switch (dword) {
536 case RLNH_LINK_ADDR:
537 /* XXX what is this? */
538 break;
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);
541 offset += 4;
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);
544 break;
545 case RLNH_PUBLISH:
546 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, linx_tvb, offset, 4, ENC_BIG_ENDIAN);
547 offset += 4;
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);
550 break;
551 case RLNH_UNPUBLISH:
552 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, linx_tvb, offset, 4, ENC_BIG_ENDIAN);
553 offset += 4;
554 break;
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);
557 offset += 4;
558 break;
559 case RLNH_INIT:
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);
563 offset += 4;
564 break;
565 case RLNH_INIT_REPLY:
566 proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_status, linx_tvb, offset, 4, ENC_BIG_ENDIAN);
567 offset += 4;
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);
572 break;
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);
575 offset += 4;
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);
578 break;
579 default:
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);
583 break;
585 } else {
586 /* Is there payload? */
587 /* anything better to do with that? */
588 payloadsize = pkgsize-offset;
589 if (payloadsize) {
590 proto_tree_add_text(linx_tree, linx_tvb, offset, payloadsize,"%u bytes data", payloadsize);
593 break;
595 case ETHCM_ACK:
596 /* Reliable header */
598 0 1 2 3
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);
611 offset += 4;
612 break;
614 case ETHCM_FRAG:
616 - fragments (not first fragment)
618 0 1 2 3
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);
631 offset += 4;
632 break;
634 default:
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 */
637 break;
645 /* Protocol Initialisation */
646 void
647 proto_register_linx(void)
650 /* Registering Data Structures */
652 static hf_register_info hf[] = {
653 { &hf_linx_nexthdr,
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 },
765 /* RLNH */
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 },
775 #if 0
776 { &hf_linx_rlnh_linkaddr, /* in RLNH */
777 { "RLNH linkaddr", "linx.rlnh_linkaddr", FT_UINT32, BASE_DEC, NULL, 0xffffffff, "RLNH linkaddress", HFILL },
779 #endif
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[] = {
802 &ett_linx,
803 &ett_linx_multicore,
804 &ett_linx_main,
805 &ett_linx_error,
806 &ett_linx_udata,
807 &ett_linx_ack
810 proto_linx = proto_register_protocol (
811 "ENEA LINX", /* name */
812 "LINX", /* short name */
813 "linx" /* abbrev */
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 */
823 void
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
836 static void
837 dissect_linx_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
839 guint32 dword;
840 tvbuff_t *linx_tcp_tvb;
841 int offset = 0;
842 proto_item *item;
843 proto_item *ti;
844 proto_tree *linx_tcp_tree;
845 proto_tree *tcp_header_tree;
846 proto_tree *rlnh_header_tree;
847 int payloadsize;
848 int version;
849 int size;
850 int type;
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 */
863 size = 16;
865 if (type == 0x55) {
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);
878 if (version != 3) {
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);
892 offset += 16;
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);
907 if(version == 1) {
908 proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_msg_type32, linx_tcp_tvb, offset, 4, ENC_BIG_ENDIAN);
909 offset += 4;
910 } else {
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);
917 offset += 4;
920 switch (dword) {
921 case RLNH_LINK_ADDR:
922 break;
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);
925 offset += 4;
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);*/
928 break;
929 case RLNH_PUBLISH:
930 proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, linx_tcp_tvb, offset, 4, ENC_BIG_ENDIAN);
931 offset += 4;
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);*/
934 break;
935 case RLNH_UNPUBLISH:
936 proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, linx_tcp_tvb, offset, 4, ENC_BIG_ENDIAN);
937 /*offset += 4;*/
938 break;
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);
941 /*offset += 4;*/
942 break;
943 case RLNH_INIT:
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);
946 /*offset += 4;*/
947 break;
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);
950 offset += 4;
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);*/
955 break;
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);
958 offset += 4;
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);*/
961 break;
962 default:
963 /* No known Message type */
964 proto_tree_add_text(rlnh_header_tree, linx_tcp_tvb, offset, 0, "ERROR: Header \"%u\" not recognized", dword);
965 break;
967 } else {
968 /* User payload */
969 payloadsize = size-offset;
970 if (payloadsize) {
971 proto_tree_add_text(linx_tcp_tree, linx_tcp_tvb, offset, payloadsize, "%u bytes data", payloadsize);
977 void
978 proto_register_linx_tcp(void)
980 static hf_register_info hf[] = {
981 #if 0
982 { &hf_linx_tcp_reserved,
983 { "Reserved", "linxtcp.reserved", FT_UINT32, BASE_DEC, NULL, 0x00007FFF, "TCP CM reserved", HFILL },
985 #endif
986 { &hf_linx_tcp_oob,
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 },
992 { &hf_linx_tcp_type,
993 { "Type", "linxtcp.type", FT_UINT32, BASE_HEX, VALS(linx_long_tcp_names), 0xFF000000, "TCP CM type", HFILL },
995 { &hf_linx_tcp_src,
996 { "Source", "linxtcp.src", FT_UINT32, BASE_DEC, NULL, 0xFFFFFFFF, "TCP CM source", HFILL },
998 { &hf_linx_tcp_dst,
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 },
1005 /* RLNH */
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 },
1015 #if 0
1016 { &hf_linx_tcp_rlnh_linkaddr,
1017 { "RLNH linkaddr", "linxtcp.rlnh_linkaddr", FT_UINT32, BASE_DEC, NULL, 0xffffffff, "RLNH linkaddress", HFILL },
1019 #endif
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[] = {
1042 &ett_linx_tcp,
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));
1049 void
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);