/src/wireshark/epan/dissectors/packet-linx.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-linx.c |
2 | | * Routines for LINX packet dissection |
3 | | * |
4 | | * Copyright 2006, Martin Peylo <martin.peylo@siemens.com> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | /* The used document is: |
14 | | * ENEA Link Protocol Specification available at |
15 | | * http://linx.sourceforge.net |
16 | | * |
17 | | * Fits currently to |
18 | | * Enea LINX for Linux |
19 | | * Version: 2.5.0, May 16, 2011 |
20 | | * |
21 | | * Added support for LINX ETHCM version 3 and LINX RLNH version 2. |
22 | | * Mattias Wallin, linx@enea.com, September 23, 2007 |
23 | | * |
24 | | * Added support for LINX TCP CM. |
25 | | * Dejan Bucar, linx@enea.com, June 21, 2011 |
26 | | * |
27 | | * Added support for LINX ETHCM Multicore header. |
28 | | * Dejan Bucar, linx@enea.com, June 21, 2011 |
29 | | */ |
30 | | |
31 | | #include "config.h" |
32 | | |
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> |
38 | | |
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); |
43 | | |
44 | | static dissector_handle_t linx_handle; |
45 | | |
46 | | static int proto_linx; |
47 | | static int proto_linx_tcp; |
48 | | |
49 | | /* ALL */ |
50 | | static int hf_linx_nexthdr; |
51 | | |
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; |
57 | | |
58 | | |
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; |
65 | | |
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; |
76 | | |
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; |
82 | | |
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; |
96 | | |
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; |
102 | | |
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; |
114 | | |
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; |
134 | | |
135 | | |
136 | | static int rlnh_version; |
137 | | |
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; |
145 | | |
146 | | static expert_field ei_linx_version; |
147 | | static expert_field ei_linx_rlnh_msg; |
148 | | static expert_field ei_linx_header; |
149 | | |
150 | | static expert_field ei_linx_tcp_version; |
151 | | static expert_field ei_linx_tcp_rlnh_msg; |
152 | | |
153 | | |
154 | | |
155 | | /* Definition and Names */ |
156 | | |
157 | 392 | #define ETHCM_MAIN 0x0 |
158 | 380 | #define ETHCM_CONN 0x1 |
159 | 17 | #define ETHCM_UDATA 0x2 |
160 | 12 | #define ETHCM_FRAG 0x3 |
161 | 3 | #define ETHCM_ACK 0x4 |
162 | 251 | #define ETHCM_NACK 0x5 |
163 | 740 | #define ETHCM_NONE 0xf |
164 | | |
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} |
174 | | }; |
175 | | |
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} |
185 | | }; |
186 | | |
187 | | #define TCP_CM_CONN 0x43 |
188 | | #define TCP_CM_UDATA 0x55 |
189 | | #define TCP_CM_PING 0x50 |
190 | | #define TCP_CM_PONG 0x51 |
191 | | |
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} |
198 | | }; |
199 | | |
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} |
206 | | }; |
207 | | |
208 | | /* RLNH version 1 */ |
209 | 1 | #define RLNH_LINK_ADDR 0 |
210 | 0 | #define RLNH_QUERY_NAME 1 |
211 | 0 | #define RLNH_PUBLISH 2 |
212 | 0 | #define RLNH_UNPUBLISH 3 |
213 | 0 | #define RLNH_UNPUBLISH_ACK 4 |
214 | 0 | #define RLNH_INIT 5 |
215 | 0 | #define RLNH_INIT_REPLY 6 |
216 | 0 | #define RLNH_PUBLISH_PEER 7 |
217 | | |
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} |
228 | | }; |
229 | | |
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} |
240 | | }; |
241 | | |
242 | | static const value_string linx_rlnh_reply[] = { |
243 | | { 0, "Version supported"}, |
244 | | { 1, "Version NOT supported"}, |
245 | | { 0, NULL} |
246 | | }; |
247 | | |
248 | | static const value_string linx_nofragment[] = { |
249 | | { 0x7fff, "No Fragment"}, |
250 | | { 0, NULL} |
251 | | }; |
252 | | |
253 | | static const value_string linx_coreid[]= { |
254 | | {0xff, "None"}, |
255 | | {0, NULL} |
256 | | }; |
257 | | |
258 | | #define CONN_RESET 1 |
259 | | #define CONN_CONNECT 2 |
260 | | #define CONN_CONNECT_ACK 3 |
261 | | #define CONN_ACK 4 |
262 | | |
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} |
269 | | }; |
270 | | |
271 | | static int |
272 | | dissect_linx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
273 | 48 | { |
274 | 48 | uint32_t dword; |
275 | 48 | int offset = 0; |
276 | 48 | int nexthdr; |
277 | 48 | int thishdr; |
278 | 48 | int size; |
279 | 48 | int pkgsize; |
280 | 48 | int payloadsize; |
281 | 48 | int version; |
282 | 48 | int conntype; |
283 | 48 | proto_tree *multicore_header_tree; |
284 | 48 | proto_tree *main_header_tree; |
285 | 48 | proto_tree *conn_header_tree; |
286 | 48 | proto_tree *ack_header_tree; |
287 | 48 | proto_tree *udata_header_tree; |
288 | 48 | proto_tree *nack_header_tree; |
289 | 48 | proto_tree *frag_header_tree; |
290 | 48 | proto_tree *rlnh_header_tree; |
291 | | |
292 | | /* Show name in protocol column */ |
293 | 48 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LINX"); |
294 | | /* Clear out stuff in the info column */ |
295 | 48 | col_clear(pinfo->cinfo, COL_INFO); |
296 | | |
297 | 48 | { /* Work out the details */ |
298 | 48 | proto_item *ti = NULL; |
299 | 48 | proto_tree *linx_tree = NULL; |
300 | 48 | proto_item *ver_item, *msg_item; |
301 | | |
302 | 48 | ti = proto_tree_add_item(tree, proto_linx, tvb, 0, -1, ENC_NA); |
303 | 48 | linx_tree = proto_item_add_subtree(ti, ett_linx); |
304 | | |
305 | 48 | dword = tvb_get_ntohl(tvb, offset); |
306 | 48 | nexthdr = (dword >> 28) & 0xf; |
307 | | |
308 | | /* check if we have multicore header*/ |
309 | 48 | if (nexthdr == ETHCM_MAIN) |
310 | 29 | { |
311 | 29 | multicore_header_tree = proto_tree_add_subtree(linx_tree, tvb, 0, 4, ett_linx_multicore, NULL, "Multicore Header"); |
312 | | |
313 | | /* Multicore header */ |
314 | | /* |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
320 | | */ |
321 | 29 | proto_tree_add_item(multicore_header_tree, hf_linx_nexthdr, tvb, 0, 4, ENC_BIG_ENDIAN); |
322 | 29 | proto_tree_add_item(multicore_header_tree, hf_linx_multicore_reserved, tvb, 0, 4, ENC_BIG_ENDIAN); |
323 | 29 | proto_tree_add_item(multicore_header_tree, hf_linx_multicore_dcoreid, tvb, 0, 4, ENC_BIG_ENDIAN); |
324 | 29 | proto_tree_add_item(multicore_header_tree, hf_linx_multicore_scoreid, tvb, 0, 4, ENC_BIG_ENDIAN); |
325 | 29 | proto_tree_add_item(multicore_header_tree, hf_linx_multicore_reserved1, tvb, 0, 4, ENC_BIG_ENDIAN); |
326 | | |
327 | 29 | offset += 4; |
328 | | /* read main header*/ |
329 | 29 | dword = tvb_get_ntohl(tvb, offset); |
330 | 29 | } |
331 | | |
332 | 48 | version = (dword >> 25) & 0x7; |
333 | 48 | nexthdr = (dword >> 28) & 0xf; |
334 | 48 | pkgsize = dword & 0x3fff; |
335 | | |
336 | | /* Main header */ |
337 | 48 | main_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 4, ett_linx_main, NULL, "Main Header"); |
338 | | |
339 | | /* |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
345 | | */ |
346 | | |
347 | 48 | proto_tree_add_item(main_header_tree, hf_linx_nexthdr , tvb, offset, 4, ENC_BIG_ENDIAN); |
348 | 48 | ver_item = proto_tree_add_item(main_header_tree, hf_linx_main_version , tvb, offset, 4, ENC_BIG_ENDIAN); |
349 | 48 | proto_tree_add_item(main_header_tree, hf_linx_main_reserved , tvb, offset, 4, ENC_BIG_ENDIAN); |
350 | 48 | proto_tree_add_item(main_header_tree, hf_linx_main_connection, tvb, offset, 4, ENC_BIG_ENDIAN); |
351 | 48 | proto_tree_add_item(main_header_tree, hf_linx_main_bundle , tvb, offset, 4, ENC_BIG_ENDIAN); |
352 | 48 | proto_tree_add_item(main_header_tree, hf_linx_main_pkg_size , tvb, offset, 4, ENC_BIG_ENDIAN); |
353 | 48 | offset += 4; |
354 | | |
355 | | /* Supports version 2 and 3 so far */ |
356 | 48 | if (version < 2 || version > 3) { |
357 | 45 | expert_add_info(pinfo, ver_item, &ei_linx_version); |
358 | 45 | } |
359 | | |
360 | 371 | while (nexthdr != ETHCM_NONE) { |
361 | | |
362 | 352 | dword = tvb_get_ntohl(tvb, offset); |
363 | 352 | thishdr = nexthdr; |
364 | 352 | nexthdr = (dword >>28) & 0xf; |
365 | 352 | conntype = (dword >>24) & 0xf; |
366 | | /* Write non trivial header name to info column */ |
367 | 352 | if ((thishdr != ETHCM_NONE) && (thishdr != ETHCM_MAIN)) { |
368 | 336 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(thishdr, linx_short_header_names, "unknown")); |
369 | 336 | if(thishdr == ETHCM_CONN) |
370 | 44 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(conntype, linx_conn_cmd, "unknown")); |
371 | 336 | } |
372 | | |
373 | 352 | switch (thishdr) { |
374 | | |
375 | 44 | case ETHCM_CONN: |
376 | | /* Connect header */ |
377 | | /* |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
383 | | : : |
384 | | : dst hw addr followed by src hw addr : |
385 | | : : |
386 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
387 | | : : |
388 | | : Feature negotiation string (null terminated) : |
389 | | : : |
390 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
391 | | */ |
392 | | |
393 | 44 | size = (dword >>21) & 0x7; |
394 | 44 | conn_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, (4+2*size), ett_linx_main, NULL, "Connection Header"); |
395 | 44 | proto_tree_add_item(conn_header_tree, hf_linx_nexthdr , tvb, offset, 4, ENC_BIG_ENDIAN); |
396 | 44 | proto_tree_add_item(conn_header_tree, hf_linx_conn_cmd , tvb, offset, 4, ENC_BIG_ENDIAN); |
397 | 44 | proto_tree_add_item(conn_header_tree, hf_linx_conn_size , tvb, offset, 4, ENC_BIG_ENDIAN); |
398 | 44 | proto_tree_add_item(conn_header_tree, hf_linx_conn_winsize , tvb, offset, 4, ENC_BIG_ENDIAN); |
399 | 44 | proto_tree_add_item(conn_header_tree, hf_linx_conn_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); |
400 | 44 | proto_tree_add_item(conn_header_tree, hf_linx_conn_publcid , tvb, offset, 4, ENC_BIG_ENDIAN); |
401 | 44 | offset += 4; |
402 | | /* MEDIA ADDRESS */ |
403 | 44 | if (size == 6) { |
404 | | /* Most likely ETHERNET */ |
405 | 1 | proto_tree_add_item(conn_header_tree, hf_linx_conn_dstmac, tvb, offset, 6, ENC_NA); |
406 | 1 | proto_tree_add_item(conn_header_tree, hf_linx_conn_srcmac, tvb, offset + 6, 6, ENC_NA); |
407 | 1 | } |
408 | | |
409 | 44 | offset += (2*size); |
410 | | /* Feature Negotiation String */ |
411 | 44 | if(version > 2) { |
412 | 20 | proto_tree_add_item(conn_header_tree, hf_linx_conn_feat_neg_str, tvb, offset, -1, ENC_ASCII); |
413 | 20 | offset += tvb_strnlen(tvb, offset, -1); |
414 | 20 | } |
415 | 44 | break; |
416 | | |
417 | 251 | case ETHCM_NACK: |
418 | | /* Nack header */ |
419 | | /* |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
425 | | */ |
426 | | |
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 */ |
432 | | |
433 | 251 | nack_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 4, ett_linx_main, NULL, "NACK Header"); |
434 | 251 | proto_tree_add_item(nack_header_tree, hf_linx_nexthdr , tvb, offset, 4, ENC_BIG_ENDIAN); |
435 | 251 | proto_tree_add_item(nack_header_tree, hf_linx_nack_reserv1, tvb, offset, 4, ENC_BIG_ENDIAN); |
436 | 251 | proto_tree_add_item(nack_header_tree, hf_linx_nack_count , tvb, offset, 4, ENC_BIG_ENDIAN); |
437 | 251 | proto_tree_add_item(nack_header_tree, hf_linx_nack_reserv2, tvb, offset, 4, ENC_BIG_ENDIAN); |
438 | 251 | proto_tree_add_item(nack_header_tree, hf_linx_nack_seqno , tvb, offset, 4, ENC_BIG_ENDIAN); |
439 | 251 | offset += 4; |
440 | 251 | break; |
441 | | |
442 | 17 | case ETHCM_UDATA: |
443 | | /* User data / fragment header => Version 3 */ |
444 | | /* |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
454 | | |
455 | | * User data / fragment header => Version 2 |
456 | | |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
466 | | |
467 | | - fragments (not first fragment) |
468 | | |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
474 | | */ |
475 | | |
476 | | |
477 | 17 | udata_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 12, ett_linx_main, NULL, "Udata Header"); |
478 | 17 | proto_tree_add_item(udata_header_tree, hf_linx_nexthdr, tvb, offset, 4, ENC_BIG_ENDIAN); |
479 | 17 | proto_tree_add_item(udata_header_tree, hf_linx_udata_reserved , tvb, offset, 4, ENC_BIG_ENDIAN); |
480 | 17 | proto_tree_add_item(udata_header_tree, hf_linx_udata_morefrags, tvb, offset, 4, ENC_BIG_ENDIAN); |
481 | 17 | proto_tree_add_item(udata_header_tree, hf_linx_udata_fragno , tvb, offset, 4, ENC_BIG_ENDIAN); |
482 | 17 | offset += 4; |
483 | | /* signo removed in version 3 and linkaddresses extended to 32 bits */ |
484 | 17 | if(version == 2) { |
485 | 1 | proto_tree_add_item(udata_header_tree, hf_linx_udata_signo , tvb, offset, 4, ENC_BIG_ENDIAN); |
486 | 1 | offset += 4; |
487 | 1 | proto_tree_add_item(udata_header_tree, hf_linx_udata_dstaddr16, tvb, offset, 4, ENC_BIG_ENDIAN); |
488 | 1 | proto_tree_add_item(udata_header_tree, hf_linx_udata_srcaddr16, tvb, offset, 4, ENC_BIG_ENDIAN); |
489 | 1 | dword = tvb_get_ntohl(tvb, offset); |
490 | 16 | } else { |
491 | 16 | proto_tree_add_item(udata_header_tree, hf_linx_udata_dstaddr32, tvb, offset, 4, ENC_BIG_ENDIAN); |
492 | 16 | dword = tvb_get_ntohl(tvb, offset); |
493 | 16 | offset += 4; |
494 | 16 | proto_tree_add_item(udata_header_tree, hf_linx_udata_srcaddr32, tvb, offset, 4, ENC_BIG_ENDIAN); |
495 | 16 | if(dword == 0 && tvb_get_ntohl(tvb, offset) == 0) { |
496 | 1 | dword = 0; |
497 | 15 | } else { |
498 | 15 | dword = 1; |
499 | 15 | } |
500 | 16 | } |
501 | 17 | offset += 4; |
502 | 17 | if (dword == 0) { |
503 | | /* (dstaddr == srcaddr == 0) -> RLNH Protocol Message */ |
504 | | |
505 | 1 | dword = tvb_get_ntohl(tvb, offset); |
506 | | |
507 | | /* Write to info column */ |
508 | 1 | col_append_fstr(pinfo->cinfo, COL_INFO, "rlnh:%s ", val_to_str_const(dword, linx_short_rlnh_names, "unknown")); |
509 | | |
510 | | /* create new paragraph for RLNH */ |
511 | 1 | rlnh_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 4, ett_linx_main, NULL, "RLNH"); |
512 | | |
513 | 1 | if(version == 1) { |
514 | 0 | msg_item = proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_msg_type32, tvb, offset, 4, ENC_BIG_ENDIAN); |
515 | 0 | offset += 4; |
516 | 1 | } else { |
517 | | /* in version 2 of the rlnh protocol the length of the message type is restricted to 8 bits */ |
518 | 1 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_msg_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); |
519 | 1 | msg_item = proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_msg_type8, tvb, offset, 4, ENC_BIG_ENDIAN); |
520 | 1 | offset += 4; |
521 | 1 | } |
522 | | |
523 | 1 | switch (dword) { |
524 | 1 | case RLNH_LINK_ADDR: |
525 | | /* XXX what is this? */ |
526 | 1 | break; |
527 | 0 | case RLNH_QUERY_NAME: |
528 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
529 | 0 | offset += 4; |
530 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_name, tvb, offset, -1, ENC_ASCII); |
531 | 0 | offset += tvb_strnlen(tvb, offset, -1); |
532 | 0 | break; |
533 | 0 | case RLNH_PUBLISH: |
534 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
535 | 0 | offset += 4; |
536 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_name, tvb, offset, -1, ENC_ASCII); |
537 | 0 | offset += tvb_strnlen(tvb, offset, -1); |
538 | 0 | break; |
539 | 0 | case RLNH_UNPUBLISH: |
540 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
541 | 0 | offset += 4; |
542 | 0 | break; |
543 | 0 | case RLNH_UNPUBLISH_ACK: |
544 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
545 | 0 | offset += 4; |
546 | 0 | break; |
547 | 0 | case RLNH_INIT: |
548 | 0 | 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 | 0 | rlnh_version = tvb_get_ntohl(tvb, offset); |
551 | 0 | offset += 4; |
552 | 0 | break; |
553 | 0 | case RLNH_INIT_REPLY: |
554 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_status, tvb, offset, 4, ENC_BIG_ENDIAN); |
555 | 0 | offset += 4; |
556 | 0 | if(rlnh_version > 1) { |
557 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_feat_neg_str, tvb, offset, -1, ENC_ASCII); |
558 | 0 | offset += tvb_strnlen(tvb, offset, -1); |
559 | 0 | } |
560 | 0 | break; |
561 | 0 | case RLNH_PUBLISH_PEER: |
562 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
563 | 0 | offset += 4; |
564 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_rlnh_peer_linkaddr, tvb, offset, -1, ENC_BIG_ENDIAN); |
565 | 0 | offset += tvb_strnlen(tvb, offset, -1); |
566 | 0 | break; |
567 | 0 | default: |
568 | | /* no known Message type... */ |
569 | 0 | expert_add_info(pinfo, msg_item, &ei_linx_rlnh_msg); |
570 | 0 | break; |
571 | 1 | } |
572 | 16 | } else { |
573 | | /* Is there payload? */ |
574 | | /* anything better to do with that? */ |
575 | 16 | payloadsize = pkgsize-offset; |
576 | 16 | if (payloadsize) { |
577 | 16 | proto_tree_add_item(linx_tree, hf_linx_udata_payload, tvb, offset, payloadsize, ENC_NA); |
578 | 16 | } |
579 | 16 | } |
580 | 17 | break; |
581 | | |
582 | 17 | case ETHCM_ACK: |
583 | | /* Reliable header */ |
584 | | /* |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
590 | | */ |
591 | 3 | ack_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 4, ett_linx_main, NULL, "Ack Header"); |
592 | 3 | proto_tree_add_item(ack_header_tree, hf_linx_nexthdr , tvb, offset, 4, ENC_BIG_ENDIAN); |
593 | 3 | proto_tree_add_item(ack_header_tree, hf_linx_ack_request , tvb, offset, 4, ENC_BIG_ENDIAN); |
594 | 3 | proto_tree_add_item(ack_header_tree, hf_linx_ack_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); |
595 | 3 | proto_tree_add_item(ack_header_tree, hf_linx_ack_ackno , tvb, offset, 4, ENC_BIG_ENDIAN); |
596 | 3 | proto_tree_add_item(ack_header_tree, hf_linx_ack_seqno , tvb, offset, 4, ENC_BIG_ENDIAN); |
597 | 3 | offset += 4; |
598 | 3 | break; |
599 | | |
600 | 12 | case ETHCM_FRAG: |
601 | | /* |
602 | | - fragments (not first fragment) |
603 | | |
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 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
609 | | */ |
610 | | |
611 | 12 | frag_header_tree = proto_tree_add_subtree(linx_tree, tvb, offset, 4, ett_linx_main, NULL, "Fragmentation Header"); |
612 | 12 | proto_tree_add_item(frag_header_tree, hf_linx_nexthdr , tvb, offset, 4, ENC_BIG_ENDIAN); |
613 | 12 | proto_tree_add_item(frag_header_tree, hf_linx_frag_reserved , tvb, offset, 4, ENC_BIG_ENDIAN); |
614 | 12 | proto_tree_add_item(frag_header_tree, hf_linx_frag_morefrags, tvb, offset, 4, ENC_BIG_ENDIAN); |
615 | 12 | proto_tree_add_item(frag_header_tree, hf_linx_frag_fragno , tvb, offset, 4, ENC_BIG_ENDIAN); |
616 | 12 | offset += 4; |
617 | 12 | break; |
618 | | |
619 | 17 | default: |
620 | 17 | proto_tree_add_expert_format(linx_tree, pinfo, &ei_linx_header, tvb, offset, 4, "ERROR: Header \"%u\" not recognized", thishdr); |
621 | 17 | nexthdr = ETHCM_NONE; /* avoid endless loop with faulty packages */ |
622 | 17 | break; |
623 | 352 | } |
624 | 352 | } |
625 | | |
626 | 48 | } |
627 | 19 | return tvb_captured_length(tvb); |
628 | 48 | } |
629 | | |
630 | | |
631 | | /* Protocol Initialisation */ |
632 | | void |
633 | | proto_register_linx(void) |
634 | 14 | { |
635 | | |
636 | | /* Registering Data Structures */ |
637 | | |
638 | 14 | static hf_register_info hf[] = { |
639 | 14 | { &hf_linx_nexthdr, |
640 | 14 | { "Next Header", "linx.nexthdr", FT_UINT32, BASE_DEC, VALS(linx_long_header_names), 0xf0000000, NULL, HFILL }, |
641 | 14 | }, |
642 | 14 | { &hf_linx_multicore_scoreid, /* in ETHCM_MULTICORE */ |
643 | 14 | { "Source coreid", "linx.scoreid", FT_UINT32, BASE_DEC, VALS(linx_coreid), 0x0000ff00, "Multicore source core id", HFILL }, |
644 | 14 | }, |
645 | 14 | { &hf_linx_multicore_dcoreid, /* in ETHCM_MULTICORE */ |
646 | 14 | { "Destination coreid", "linx.dcoreid", FT_UINT32, BASE_DEC, VALS(linx_coreid), 0x00ff0000, "Multicore destination core id", HFILL}, |
647 | 14 | }, |
648 | 14 | { &hf_linx_multicore_reserved, /* in ETHCM_MULTICORE */ |
649 | 14 | { "Reserved", "linx.reserved8", FT_UINT32, BASE_DEC, NULL, 0x0f000000, "Multicore Hdr Reserved", HFILL}, |
650 | 14 | }, |
651 | 14 | { &hf_linx_multicore_reserved1, /* in ETHCM_MULTICORE */ |
652 | 14 | { "Reserved", "linx.reserved9", FT_UINT32, BASE_DEC, NULL, 0x000000ff, "Multicore Hdr Reserved", HFILL}, |
653 | 14 | }, |
654 | 14 | { &hf_linx_main_version, /* in ETHCM_MAIN */ |
655 | 14 | { "Version", "linx.version", FT_UINT32, BASE_DEC, NULL, 0x0e000000, "LINX Version", HFILL }, |
656 | 14 | }, |
657 | 14 | { &hf_linx_main_reserved, /* in ETHCM_MAIN */ |
658 | 14 | { "Reserved", "linx.reserved1", FT_UINT32, BASE_DEC, NULL, 0x01800000, "Main Hdr Reserved", HFILL }, |
659 | 14 | }, |
660 | 14 | { &hf_linx_main_connection, /* in ETHCM_MAIN */ |
661 | 14 | { "Connection", "linx.connection", FT_UINT32, BASE_DEC, NULL, 0x007f8000, NULL, HFILL }, |
662 | 14 | }, |
663 | 14 | { &hf_linx_main_bundle, /* in ETHCM_MAIN */ |
664 | 14 | { "Bundle", "linx.bundle", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00004000, NULL, HFILL }, |
665 | 14 | }, |
666 | 14 | { &hf_linx_main_pkg_size, /* in ETHCM_MAIN */ |
667 | 14 | { "Package Size", "linx.pcksize", FT_UINT32, BASE_DEC, NULL, 0x00003fff, NULL, HFILL }, |
668 | 14 | }, |
669 | 14 | { &hf_linx_udata_reserved, /* in ETHCM_UDATA */ |
670 | 14 | { "Reserved", "linx.reserved5", FT_UINT32, BASE_DEC, NULL, 0x0fff0000, "Udata Hdr Reserved", HFILL }, |
671 | 14 | }, |
672 | 14 | { &hf_linx_udata_morefrags, /* in ETHCM_UDATA */ |
673 | 14 | { "More Fragments", "linx.morefra", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00008000, "More fragments follow", HFILL }, |
674 | 14 | }, |
675 | 14 | { &hf_linx_udata_fragno, /* in ETHCM_UDATA */ |
676 | 14 | { "Fragment Number", "linx.fragno", FT_UINT32, BASE_DEC, VALS(linx_nofragment), 0x00007fff, NULL, HFILL }, |
677 | 14 | }, |
678 | 14 | { &hf_linx_udata_signo, /* in ETHCM_UDATA */ |
679 | 14 | { "Signal Number", "linx.signo", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }, |
680 | 14 | }, |
681 | 14 | { &hf_linx_udata_dstaddr16, /* in ETHCM_UDATA - protocol version 2 */ |
682 | 14 | { "Receiver Address", "linx.dstaddr", FT_UINT32, BASE_DEC, NULL, 0xffff0000, NULL, HFILL }, |
683 | 14 | }, |
684 | 14 | { &hf_linx_udata_dstaddr32, /* in ETHCM_UDATA - protocol version 3 */ |
685 | 14 | { "Receiver Address", "linx.dstaddr32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }, |
686 | 14 | }, |
687 | 14 | { &hf_linx_udata_srcaddr16, /* in ETHCM_UDATA - protocol version 2 */ |
688 | 14 | { "Sender Address", "linx.srcaddr", FT_UINT32, BASE_DEC, NULL, 0x0000ffff, NULL, HFILL }, |
689 | 14 | }, |
690 | 14 | { &hf_linx_udata_srcaddr32, /* in ETHCM_UDATA - protocol version 3 */ |
691 | 14 | { "Sender Address", "linx.srcaddr32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }, |
692 | 14 | }, |
693 | 14 | { &hf_linx_udata_payload, /* in ETHCM_UDATA */ |
694 | 14 | { "Payload", "linx.payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
695 | 14 | }, |
696 | 14 | { &hf_linx_ack_request, /* in ETHCM_ACK */ |
697 | 14 | { "ACK-request", "linx.ackreq", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x08000000, NULL, HFILL }, |
698 | 14 | }, |
699 | 14 | { &hf_linx_ack_reserved, /* in ETHCM_ACK */ |
700 | 14 | { "Reserved", "linx.reserved7", FT_UINT32, BASE_DEC, NULL, 0x07000000, "ACK Hdr Reserved", HFILL }, |
701 | 14 | }, |
702 | 14 | { &hf_linx_ack_ackno, /* in ETHCM_ACK */ |
703 | 14 | { "ACK Number", "linx.ackno", FT_UINT32, BASE_DEC, NULL, 0x00fff000, NULL, HFILL }, |
704 | 14 | }, |
705 | 14 | { &hf_linx_ack_seqno, /* in ETHCM_ACK */ |
706 | 14 | { "Sequence Number", "linx.seqno", FT_UINT32, BASE_DEC, NULL, 0x00000fff, NULL, HFILL }, |
707 | 14 | }, |
708 | 14 | { &hf_linx_conn_cmd, /* in ETHCM_CONN */ |
709 | 14 | { "Command", "linx.cmd", FT_UINT32, BASE_DEC, VALS(linx_conn_cmd), 0x0f000000, NULL, HFILL }, |
710 | 14 | }, |
711 | 14 | { &hf_linx_conn_size, /* in ETHCM_CONN */ |
712 | 14 | { "Size", "linx.size", FT_UINT32, BASE_DEC, NULL, 0x00e00000, NULL, HFILL }, |
713 | 14 | }, |
714 | 14 | { &hf_linx_conn_winsize, /* in ETHCM_CONN */ |
715 | 14 | { "WinSize", "linx.winsize", FT_UINT32, BASE_DEC, NULL, 0x001e0000, "Window Size", HFILL }, |
716 | 14 | }, |
717 | 14 | { &hf_linx_conn_reserved, /* in ETHCM_CONN */ |
718 | 14 | { "Reserved", "linx.reserved3", FT_UINT32, BASE_DEC, NULL, 0x0001ff00, "Conn Hdr Reserved", HFILL }, |
719 | 14 | }, |
720 | 14 | { &hf_linx_conn_publcid, /* in ETHCM_CONN */ |
721 | 14 | { "Publish Conn ID", "linx.publcid", FT_UINT32, BASE_DEC, NULL, 0x000000ff, NULL, HFILL }, |
722 | 14 | }, |
723 | 14 | { &hf_linx_conn_srcmac, /* in ETHCM_CONN */ |
724 | 14 | { "Source", "linx.srcmaddr_ether", FT_ETHER, BASE_NONE, NULL, 0x0, "Source Media Address (ethernet)", HFILL }, |
725 | 14 | }, |
726 | 14 | { &hf_linx_conn_dstmac, /* in ETHCM_CONN */ |
727 | 14 | { "Destination", "linx.destmaddr_ether", FT_ETHER, BASE_NONE, NULL, 0x0, "Destination Media Address (ethernet)", HFILL }, |
728 | 14 | }, |
729 | 14 | { &hf_linx_conn_feat_neg_str, /* in ETHCM_CONN */ |
730 | 14 | { "Feature Negotiation String", "linx.feat_neg_str", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
731 | 14 | }, |
732 | 14 | { &hf_linx_frag_reserved, /* in ETHCM_FRAG */ |
733 | 14 | { "Reserved", "linx.reserved6", FT_UINT32, BASE_DEC, NULL, 0x0fff0000, "Frag Hdr Reserved", HFILL }, |
734 | 14 | }, |
735 | 14 | { &hf_linx_frag_morefrags, /* in ETHCM_FRAG */ |
736 | 14 | { "More Fragments", "linx.morefr2", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00008000, NULL, HFILL }, |
737 | 14 | }, |
738 | 14 | { &hf_linx_frag_fragno, /* in ETHCM_FRAG */ |
739 | 14 | { "Fragment Number", "linx.fragno2", FT_UINT32, BASE_DEC, NULL, 0x00007fff, NULL, HFILL }, |
740 | 14 | }, |
741 | 14 | { &hf_linx_nack_reserv1, /* in ETHCM_NACK */ |
742 | 14 | { "Reserved", "linx.nack_reserv", FT_UINT32, BASE_DEC, NULL, 0x0f000000, "Nack Hdr Reserved", HFILL }, |
743 | 14 | }, |
744 | 14 | { &hf_linx_nack_count, /* in ETHCM_NACK */ |
745 | 14 | { "Count", "linx.nack_count", FT_UINT32, BASE_DEC, NULL, 0x00ff0000, NULL, HFILL }, |
746 | 14 | }, |
747 | 14 | { &hf_linx_nack_reserv2, /* in ETHCM_NACK */ |
748 | 14 | { "Reserved", "linx.nack_reserv", FT_UINT32, BASE_DEC, NULL, 0x0000f000, "Nack Hdr Reserved", HFILL }, |
749 | 14 | }, |
750 | 14 | { &hf_linx_nack_seqno, /* in ETHCM_NACK */ |
751 | 14 | { "Sequence Number", "linx.nack_seqno", FT_UINT32, BASE_DEC, NULL, 0x00000fff, NULL, HFILL }, |
752 | 14 | }, |
753 | | |
754 | | /* RLNH */ |
755 | 14 | { &hf_linx_rlnh_msg_type32, /* in RLNH */ |
756 | 14 | { "RLNH msg type", "linx.rlnh_msg_type", FT_UINT32, BASE_DEC, VALS(linx_long_rlnh_names), 0x0, "RLNH message type", HFILL }, |
757 | 14 | }, |
758 | 14 | { &hf_linx_rlnh_msg_type8, /* in RLNH */ |
759 | 14 | { "RLNH msg type", "linx.rlnh_msg_type8", FT_UINT32, BASE_DEC, VALS(linx_long_rlnh_names), 0x000000ff, "RLNH message type", HFILL }, |
760 | 14 | }, |
761 | 14 | { &hf_linx_rlnh_msg_reserved, /* in RLNH */ |
762 | 14 | { "RLNH msg reserved", "linx.rlnh_msg_reserved", FT_UINT32, BASE_DEC, NULL, 0xffffff00, "RLNH message reserved", HFILL }, |
763 | 14 | }, |
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 }, |
767 | | }, |
768 | | #endif |
769 | 14 | { &hf_linx_rlnh_src_linkaddr, /* in RLNH */ |
770 | 14 | { "RLNH src linkaddr", "linx.rlnh_src_linkaddr", FT_UINT32, BASE_DEC, NULL, 0x0, "RLNH source linkaddress", HFILL }, |
771 | 14 | }, |
772 | 14 | { &hf_linx_rlnh_peer_linkaddr, /* in RLNH */ |
773 | 14 | { "RLNH peer linkaddr", "linx.rlnh_peer_linkaddr", FT_UINT32, BASE_DEC, NULL, 0x0, "RLNH peer linkaddress", HFILL }, |
774 | 14 | }, |
775 | 14 | { &hf_linx_rlnh_version, /* in RLNH */ |
776 | 14 | { "RLNH version", "linx.rlnh_version", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }, |
777 | 14 | }, |
778 | 14 | { &hf_linx_rlnh_status, /* in RLNH */ |
779 | 14 | { "RLNH reply", "linx.rlnh_status", FT_UINT32, BASE_DEC, VALS(linx_rlnh_reply), 0x0, NULL, HFILL }, |
780 | 14 | }, |
781 | 14 | { &hf_linx_rlnh_name, /* in RLNH */ |
782 | 14 | { "RLNH name", "linx.rlnh_name", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
783 | 14 | }, |
784 | 14 | { &hf_linx_rlnh_feat_neg_str, /* in RLNH */ |
785 | 14 | { "RLNH Feature Negotiation String", "linx.rlnh_feat_neg_str", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
786 | 14 | } |
787 | 14 | }; |
788 | | |
789 | | /* Setup protocol subtree array */ |
790 | 14 | static int *ett[] = { |
791 | 14 | &ett_linx, |
792 | 14 | &ett_linx_multicore, |
793 | 14 | &ett_linx_main, |
794 | 14 | &ett_linx_error, |
795 | 14 | &ett_linx_udata, |
796 | 14 | &ett_linx_ack |
797 | 14 | }; |
798 | | |
799 | 14 | static ei_register_info ei[] = { |
800 | 14 | { &ei_linx_version, { "linx.version.unknown", PI_PROTOCOL, PI_WARN, "Version not yet supported and might be dissected incorrectly!", EXPFILL }}, |
801 | 14 | { &ei_linx_rlnh_msg, { "linx.rlnh_msg.unknown", PI_PROTOCOL, PI_WARN, "Message type not recognized", EXPFILL }}, |
802 | 14 | { &ei_linx_header, { "linx.header_not_recognized", PI_PROTOCOL, PI_WARN, "Header not recognized", EXPFILL }}, |
803 | 14 | }; |
804 | | |
805 | 14 | expert_module_t* expert_linx; |
806 | | |
807 | 14 | proto_linx = proto_register_protocol ( |
808 | 14 | "ENEA LINX", /* name */ |
809 | 14 | "LINX", /* short name */ |
810 | 14 | "linx" /* abbrev */ |
811 | 14 | ); |
812 | | |
813 | | /* Protocol Registering data structures. */ |
814 | 14 | proto_register_field_array(proto_linx, hf, array_length(hf)); |
815 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
816 | 14 | expert_linx = expert_register_protocol(proto_linx); |
817 | 14 | expert_register_field_array(expert_linx, ei, array_length(ei)); |
818 | | |
819 | | /* Register the dissector */ |
820 | 14 | linx_handle = register_dissector("linx", dissect_linx, proto_linx); |
821 | 14 | } |
822 | | |
823 | | |
824 | | /* Protocol Handoff */ |
825 | | void |
826 | | proto_reg_handoff_linx(void) |
827 | 14 | { |
828 | 14 | dissector_add_uint("ethertype", ETHERTYPE_LINX, linx_handle); |
829 | 14 | } |
830 | | |
831 | | /************ TCP CM **************/ |
832 | | |
833 | | static int |
834 | | dissect_linx_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
835 | 0 | { |
836 | 0 | uint32_t dword; |
837 | 0 | int offset = 0; |
838 | 0 | proto_item *ti, *ver_item, *msg_item; |
839 | 0 | proto_tree *linx_tcp_tree; |
840 | 0 | proto_tree *tcp_header_tree; |
841 | 0 | proto_tree *rlnh_header_tree; |
842 | 0 | int payloadsize; |
843 | 0 | int version; |
844 | 0 | int size; |
845 | 0 | int type; |
846 | | |
847 | | /* Show name in protocol column */ |
848 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LINX/TCP"); |
849 | | |
850 | | /* Clear out stuff in the info column */ |
851 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
852 | |
|
853 | 0 | dword = tvb_get_ntohl(tvb, 0); |
854 | 0 | version = (dword >> 16) & 0xFF; |
855 | 0 | type = (dword >> 24) & 0xFF; |
856 | | |
857 | | /* size of linx tcp cm header */ |
858 | 0 | size = 16; |
859 | |
|
860 | 0 | if (type == 0x55) { |
861 | 0 | dword = tvb_get_ntohl(tvb, 12); |
862 | 0 | size += (dword & 0xFFFFFFFF); |
863 | 0 | } |
864 | |
|
865 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "tcpcm:%s ", val_to_str_const(type, linx_short_tcp_names, "unknown")); |
866 | |
|
867 | 0 | ti = proto_tree_add_item(tree, proto_linx_tcp, tvb, 0, -1, ENC_NA); |
868 | 0 | linx_tcp_tree = proto_item_add_subtree(ti, ett_linx_tcp); |
869 | |
|
870 | 0 | tcp_header_tree = proto_tree_add_subtree(linx_tcp_tree, tvb, 0, 16, ett_linx_tcp, NULL, "TCP CM Header"); |
871 | |
|
872 | 0 | proto_tree_add_item(tcp_header_tree, hf_linx_tcp_type, tvb, 0, 4, ENC_BIG_ENDIAN); |
873 | 0 | ver_item = proto_tree_add_item(tcp_header_tree, hf_linx_tcp_version, tvb, 0, 4, ENC_BIG_ENDIAN); |
874 | 0 | proto_tree_add_item(tcp_header_tree, hf_linx_tcp_oob, tvb, 0, 4, ENC_BIG_ENDIAN); |
875 | 0 | proto_tree_add_item(tcp_header_tree, hf_linx_tcp_src, tvb, 4, 4, ENC_BIG_ENDIAN); |
876 | 0 | proto_tree_add_item(tcp_header_tree, hf_linx_tcp_dst, tvb, 8, 4, ENC_BIG_ENDIAN); |
877 | 0 | proto_tree_add_item(tcp_header_tree, hf_linx_tcp_size, tvb, 12, 4, ENC_BIG_ENDIAN); |
878 | |
|
879 | 0 | if (version != 3) { |
880 | 0 | expert_add_info(pinfo, ver_item, &ei_linx_tcp_version); |
881 | 0 | } |
882 | |
|
883 | 0 | offset += 16; |
884 | |
|
885 | 0 | if (type == 0x55) { /* UDATA */ |
886 | 0 | dword = tvb_get_ntohl(tvb, 8); |
887 | 0 | if (dword == 0) { /* RLNH Message*/ |
888 | |
|
889 | 0 | dword = tvb_get_ntohl(tvb, offset); |
890 | | |
891 | | /* Write to info column */ |
892 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "rlnh:%s ", val_to_str_const(dword, linx_short_rlnh_names, "unknown")); |
893 | | |
894 | | /* create new paragraph for RLNH */ |
895 | 0 | rlnh_header_tree = proto_tree_add_subtree(linx_tcp_tree, tvb, offset, 4, ett_linx_tcp, NULL, "RLNH"); |
896 | |
|
897 | 0 | if(version == 1) { |
898 | 0 | msg_item = proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_msg_type32, tvb, offset, 4, ENC_BIG_ENDIAN); |
899 | 0 | offset += 4; |
900 | 0 | } else { |
901 | | /* |
902 | | * In version 2 of the rlnh protocol the length of the message type is |
903 | | * restricted to 8 bits. |
904 | | */ |
905 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_msg_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); |
906 | 0 | msg_item = proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_msg_type8, tvb, offset, 4, ENC_BIG_ENDIAN); |
907 | 0 | offset += 4; |
908 | 0 | } |
909 | |
|
910 | 0 | switch (dword) { |
911 | 0 | case RLNH_LINK_ADDR: |
912 | 0 | break; |
913 | 0 | case RLNH_QUERY_NAME: |
914 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
915 | 0 | offset += 4; |
916 | 0 | 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 | 0 | break; |
919 | 0 | case RLNH_PUBLISH: |
920 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
921 | 0 | offset += 4; |
922 | 0 | 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 | 0 | break; |
925 | 0 | case RLNH_UNPUBLISH: |
926 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
927 | | /*offset += 4;*/ |
928 | 0 | break; |
929 | 0 | case RLNH_UNPUBLISH_ACK: |
930 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
931 | | /*offset += 4;*/ |
932 | 0 | break; |
933 | 0 | case RLNH_INIT: |
934 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_version, tvb, offset, 4, ENC_BIG_ENDIAN); |
935 | 0 | rlnh_version = tvb_get_ntohl(tvb, offset); |
936 | | /*offset += 4;*/ |
937 | 0 | break; |
938 | 0 | case RLNH_INIT_REPLY: |
939 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_status, tvb, offset, 4, ENC_BIG_ENDIAN); |
940 | 0 | offset += 4; |
941 | 0 | if(rlnh_version > 1) { |
942 | 0 | 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);*/ |
944 | 0 | } |
945 | 0 | break; |
946 | 0 | case RLNH_PUBLISH_PEER: |
947 | 0 | proto_tree_add_item(rlnh_header_tree, hf_linx_tcp_rlnh_src_linkaddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
948 | 0 | offset += 4; |
949 | 0 | 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 | 0 | break; |
952 | 0 | default: |
953 | | /* No known Message type */ |
954 | 0 | expert_add_info(pinfo, msg_item, &ei_linx_tcp_rlnh_msg); |
955 | 0 | break; |
956 | 0 | } |
957 | 0 | } else { |
958 | | /* User payload */ |
959 | 0 | payloadsize = size-offset; |
960 | 0 | if (payloadsize) { |
961 | 0 | proto_tree_add_item(linx_tcp_tree, hf_linx_tcp_payload, tvb, offset, payloadsize, ENC_NA); |
962 | 0 | } |
963 | 0 | } |
964 | 0 | } |
965 | 0 | return tvb_captured_length(tvb); |
966 | 0 | } |
967 | | |
968 | | void |
969 | | proto_register_linx_tcp(void) |
970 | 14 | { |
971 | 14 | 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 }, |
975 | | }, |
976 | | #endif |
977 | 14 | { &hf_linx_tcp_oob, |
978 | 14 | { "Out-of-band", "linxtcp.oob", FT_UINT32, BASE_DEC, NULL, 0x00008000, "TCP CM oob", HFILL }, |
979 | 14 | }, |
980 | 14 | { &hf_linx_tcp_version, |
981 | 14 | { "Version", "linxtcp.version", FT_UINT32, BASE_DEC, NULL, 0x00FF0000, "TCP CM version", HFILL }, |
982 | 14 | }, |
983 | 14 | { &hf_linx_tcp_type, |
984 | 14 | { "Type", "linxtcp.type", FT_UINT32, BASE_HEX, VALS(linx_long_tcp_names), 0xFF000000, "TCP CM type", HFILL }, |
985 | 14 | }, |
986 | 14 | { &hf_linx_tcp_src, |
987 | 14 | { "Source", "linxtcp.src", FT_UINT32, BASE_DEC, NULL, 0x0, "TCP CM source", HFILL }, |
988 | 14 | }, |
989 | 14 | { &hf_linx_tcp_dst, |
990 | 14 | { "Destination", "linxtcp.dst", FT_UINT32, BASE_DEC, NULL, 0x0, "TCP CM destination", HFILL }, |
991 | 14 | }, |
992 | 14 | { &hf_linx_tcp_size, |
993 | 14 | { "Size", "linxtcp.size", FT_UINT32, BASE_DEC, NULL, 0x0, "TCP CM size", HFILL }, |
994 | 14 | }, |
995 | | |
996 | | /* RLNH */ |
997 | 14 | { &hf_linx_tcp_rlnh_msg_type32, |
998 | 14 | { "RLNH msg type", "linxtcp.rlnh_msg_type", FT_UINT32, BASE_DEC, VALS(linx_long_rlnh_names), 0x0, "RLNH message type", HFILL }, |
999 | 14 | }, |
1000 | 14 | { &hf_linx_tcp_rlnh_msg_type8, |
1001 | 14 | { "RLNH msg type", "linxtcp.rlnh_msg_type8", FT_UINT32, BASE_DEC, VALS(linx_long_rlnh_names), 0x000000ff, "RLNH message type", HFILL }, |
1002 | 14 | }, |
1003 | 14 | { &hf_linx_tcp_rlnh_msg_reserved, |
1004 | 14 | { "RLNH msg reserved", "linxtcp.rlnh_msg_reserved", FT_UINT32, BASE_DEC, NULL, 0xffffff00, "RLNH message reserved", HFILL }, |
1005 | 14 | }, |
1006 | | #if 0 |
1007 | | { &hf_linx_tcp_rlnh_linkaddr, |
1008 | | { "RLNH linkaddr", "linxtcp.rlnh_linkaddr", FT_UINT32, BASE_DEC, NULL, 0x0, "RLNH linkaddress", HFILL }, |
1009 | | }, |
1010 | | #endif |
1011 | 14 | { &hf_linx_tcp_rlnh_src_linkaddr, |
1012 | 14 | { "RLNH src linkaddr", "linxtcp.rlnh_src_linkaddr", FT_UINT32, BASE_DEC, NULL, 0x0, "RLNH source linkaddress", HFILL }, |
1013 | 14 | }, |
1014 | 14 | { &hf_linx_tcp_rlnh_peer_linkaddr, |
1015 | 14 | { "RLNH peer linkaddr", "linxtcp.rlnh_peer_linkaddr", FT_UINT32, |
1016 | 14 | BASE_DEC, NULL, 0x0, "RLNH peer linkaddress", HFILL }, |
1017 | 14 | }, |
1018 | 14 | { &hf_linx_tcp_rlnh_version, |
1019 | 14 | { "RLNH version", "linxtcp.rlnh_version", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }, |
1020 | 14 | }, |
1021 | 14 | { &hf_linx_tcp_rlnh_status, |
1022 | 14 | { "RLNH reply", "linxtcp.rlnh_status", FT_UINT32, BASE_DEC, VALS(linx_rlnh_reply), 0x0, NULL, HFILL }, |
1023 | 14 | }, |
1024 | 14 | { &hf_linx_tcp_rlnh_name, |
1025 | 14 | { "RLNH name", "linxtcp.rlnh_name", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
1026 | 14 | }, |
1027 | 14 | { &hf_linx_tcp_rlnh_feat_neg_str, |
1028 | 14 | { "RLNH Feature Negotiation String", "linxtcp.rlnh_feat_neg_str", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
1029 | 14 | }, |
1030 | 14 | { &hf_linx_tcp_payload, |
1031 | 14 | { "Payload", "linxtcp.payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
1032 | 14 | } |
1033 | 14 | }; |
1034 | | |
1035 | 14 | static int *ett[] = { |
1036 | 14 | &ett_linx_tcp, |
1037 | 14 | }; |
1038 | | |
1039 | 14 | static ei_register_info ei[] = { |
1040 | 14 | { &ei_linx_tcp_version, { "linxtcp.version.unknown", PI_PROTOCOL, PI_WARN, "Version not yet supported and might be dissected incorrectly!", EXPFILL }}, |
1041 | 14 | { &ei_linx_tcp_rlnh_msg, { "linxtcp.rlnh_msg.unknown", PI_PROTOCOL, PI_WARN, "Message type not recognized", EXPFILL }}, |
1042 | 14 | }; |
1043 | | |
1044 | 14 | expert_module_t* expert_linx_tcp; |
1045 | | |
1046 | 14 | proto_linx_tcp = proto_register_protocol("ENEA LINX over TCP", "LINX/TCP", "linxtcp"); |
1047 | 14 | proto_register_field_array(proto_linx_tcp, hf, array_length(hf)); |
1048 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1049 | 14 | expert_linx_tcp = expert_register_protocol(proto_linx_tcp); |
1050 | 14 | expert_register_field_array(expert_linx_tcp, ei, array_length(ei)); |
1051 | 14 | } |
1052 | | |
1053 | | void |
1054 | | proto_reg_handoff_linx_tcp(void) |
1055 | 14 | { |
1056 | 14 | dissector_handle_t linx_tcp_handle; |
1057 | | |
1058 | 14 | linx_tcp_handle = create_dissector_handle(dissect_linx_tcp, proto_linx_tcp); |
1059 | | |
1060 | 14 | dissector_add_for_decode_as_with_preference("tcp.port", linx_tcp_handle); |
1061 | 14 | } |
1062 | | |
1063 | | /* |
1064 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1065 | | * |
1066 | | * Local variables: |
1067 | | * c-basic-offset: 8 |
1068 | | * tab-width: 8 |
1069 | | * indent-tabs-mode: t |
1070 | | * End: |
1071 | | * |
1072 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1073 | | * :indentSize=8:tabSize=8:noTabs=false: |
1074 | | */ |