1 /* packet-lon.c
2 * Traffic analyzer for Lontalk/EIA-709.1 networks
3 * Daniel Willmann <daniel@totalueberwachung.de>
4 * (c) 2011 Daniel Willmann
5 *
6 * Used some code by habibi_khalid <khalidhabibi@gmx.de> and
7 * Honorine_KEMGNE_NGUIFFO <honorinekemgne@yahoo.fr> from
8 * https://gitlab.com/wireshark/wireshark/-/issues/4704
9 *
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
13 *
14 * SPDX-License-Identifier: GPL-2.0-or-later
15 */
16
17 #include "config.h"
18
19 #include <epan/packet.h>
20 #include <epan/expert.h>
21
22 void proto_register_lon(void);
23 void proto_reg_handoff_lon(void);
24
25 static const value_string pdu_fmt_vs[]=
26 {
27 {0x00, "TPDU"},
28 {0x01, "SPDU"},
29 {0x02, "AuthPDU"},
30 {0x03, "APDU"},
31 {0, NULL}
32 };
33
34 static const value_string addr_fmt_vs[]=
35 {
36 {0x00, "Broadcast (0)"},
37 {0x01, "Multicast (1)"},
38 {0x02, "Unicast (2a)/Multicast (2b)"},
39 {0x03, "Unicast (3)"},
40 {0, NULL}
41 };
42
43 static const value_string domain_length_vs[]=
44 {
45 {0x00, "0 bit"},
46 {0x01, "8 bit"},
47 {0x02, "24 bit"},
48 {0x03, "48 bit"},
49 {0, NULL}
50 };
51
52 static const value_string tpdu_type_vs[]=
53 {
54 {0x00, "ACKD"},
55 {0x01, "UnACKD_RPT"},
56 {0x02, "ACK"},
57 {0x04, "REMINDER"},
58 {0x05, "REM/MSG"},
59 {0, NULL}
60 };
61
62 static const value_string spdu_type_vs[]=
63 {
64 {0x00, "REQUEST"},
65 {0x02, "RESPONSE"},
66 {0x04, "REMINDER"},
67 {0x05, "REM/MSG"},
68 {0, NULL}
69 };
70
71 static const value_string authpdu_type_vs[]=
72 {
73 {0x00, "CHALLENGE"},
74 {0x02, "REPLY"},
75 {0, NULL}
76 };
77
78 static const value_string nm_code_vs[]=
79 {
80 {0x61, "NM_QUERY_ID"},
81 {0x62, "NM_RESPOND_TO_QUERY"},
82 {0x63, "NM_UPDATE_DOMAIN"},
83 {0x64, "NM_LEAVE_DOMAIN"},
84 {0x65, "NM_UPDATE_KEY"},
85 {0x66, "NM_UPDATE_ADDR"},
86 {0x67, "NM_QUERY_ADDR"},
87 {0x68, "NM_QUERY_NV_CNFG"},
88 {0x69, "NM_UPDATE_GROUP_ADDR"},
89 {0x6A, "NM_QUERY_DOMAIN"},
90 {0x6B, "NM_UPDATE_NV_CNFG"},
91 {0x6C, "NM_SET_NODE_MODE"},
92 {0x6D, "NM_READ_MEMORY"},
93 {0x6E, "NM_WRITE_MEMORY"},
94 {0x6F, "NM_CHECKSUM_RECALC"},
95 {0x70, "NM_WINK"},
96 {0x71, "NM_MEMORY_REFRESH"},
97 {0x72, "NM_QUERY_SNVT"},
98 {0x73, "NM_NV_FETCH"},
99 {0x7F, "NM_MANUAL_SERVICE_REQUEST"},
100 { 0, NULL}
101 };
102
103 static const value_string nd_code_vs[]=
104 {
105 {0x51, "ND_QUERY_STATUS"},
106 {0x52, "ND_PROXY_COMMAND"},
107 {0x53, "ND_CLEAR_STATUS"},
108 {0x54, "ND_QUERY_XCVR"},
109 {0, NULL}
110 };
111
112 static gint hf_lon_ppdu = -1;
113 static gint hf_lon_ppdu_prio = -1;
114 static gint hf_lon_ppdu_alt = -1;
115 static gint hf_lon_ppdu_deltabl = -1;
116 static gint hf_lon_npdu = -1;
117 static gint hf_lon_npdu_version = -1;
118 static gint hf_lon_npdu_pdu_fmt = -1;
119 static gint hf_lon_npdu_addr_fmt = -1;
120 static gint hf_lon_npdu_dom_len = -1;
121 static gint hf_lon_addr_srcsub = -1;
122 static gint hf_lon_addr_srcnode = -1;
123 static gint hf_lon_addr_dstsub = -1;
124 static gint hf_lon_addr_dstgrp = -1;
125 static gint hf_lon_addr_dstnode = -1;
126 static gint hf_lon_addr_grp = -1;
127 static gint hf_lon_addr_grpmem = -1;
128 static gint hf_lon_addr_uid = -1;
129 static gint hf_lon_name = -1;
130 static gint hf_lon_domain = -1;
131 static gint hf_lon_tpdu = -1;
132 static gint hf_lon_auth = -1;
133 static gint hf_lon_tpdu_tpdu_type = -1;
134 static gint hf_lon_trans_no = -1;
135 static gint hf_lon_spdu = -1;
136 static gint hf_lon_spdu_spdu_type = -1;
137 static gint hf_lon_mlen = -1;
138 static gint hf_lon_mlist = -1;
139 static gint hf_lon_authpdu = -1;
140 static gint hf_lon_authpdu_fmt = -1;
141 static gint hf_lon_authpdu_authpdu_type = -1;
142 static gint hf_lon_nv_dir = -1;
143 static gint hf_lon_nv_selector = -1;
144 static gint hf_lon_app_code = -1;
145 static gint hf_lon_nm_code = -1;
146 static gint hf_lon_nd_code = -1;
147 static gint hf_lon_ff_code = -1;
148 static gint hf_lon_nv = -1;
149 static gint hf_lon_app = -1;
150 static gint hf_lon_nm = -1;
151 static gint hf_lon_nd = -1;
152 static gint hf_lon_ff = -1;
153 /* static gint hf_lon_checksum = -1; */
154 static gint proto_lon = -1;
155
156
157 static gint ett_lon = -1;
158 static gint ett_ppdu = -1;
159 static gint ett_npdu = -1;
160 static gint ett_tpdu = -1;
161 static gint ett_spdu = -1;
162 static gint ett_authpdu = -1;
163 static gint ett_apdu = -1;
164 static gint ett_nv = -1;
165 static gint ett_app = -1;
166 static gint ett_nm = -1;
167 static gint ett_nd = -1;
168 static gint ett_ff = -1;
169
170 static gint ett_address = -1;
171
172 static expert_field ei_lon_tpdu_tpdu_type_unknown = EI_INIT;
173 static expert_field ei_lon_tpdu_spdu_type_unknown = EI_INIT;
174 static expert_field ei_lon_tpdu_authpdu_type_unknown = EI_INIT;
175 static expert_field ei_lon_tpdu_apdu_dest_type = EI_INIT;
176
177 static gint dissect_apdu(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
178 gint offset);
179
180 static gint
dissect_lon(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)181 dissect_lon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
182 {
183 gint offset = 0;
184
185 gint pdu_fmt, addr_fmt, dom_len, pdutype, length;
186 gint addr_a;
187
188 proto_tree *ti;
189 proto_tree *lon_tree;
190 gint npdu, type;
191
192 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LON");
193 col_clear(pinfo->cinfo, COL_INFO);
194
195 npdu = tvb_get_guint8(tvb, 0);
196 type = tvb_get_guint8(tvb, 1);
197 type = (type&0x30)>>4;
198 col_add_fstr(pinfo->cinfo, COL_INFO,
199 "%sDelta_BL: %i Type: %s",
200 npdu&0x80?"Priority ":"",
201 npdu&0x3F,
202 val_to_str_const(type, pdu_fmt_vs, "Unknown"));
203
204 ti = proto_tree_add_item(tree, proto_lon, tvb, offset, -1, ENC_NA);
205 lon_tree = proto_item_add_subtree(ti, ett_lon);
206
207 {
208 static int * const ppdu_fields[] = {
209 &hf_lon_ppdu_prio,
210 &hf_lon_ppdu_alt,
211 &hf_lon_ppdu_deltabl,
212 NULL
213 };
214 proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_ppdu,
215 ett_ppdu, ppdu_fields, ENC_BIG_ENDIAN);
216 offset++;
217 }
218 {
219 static int * const npdu_fields[] = {
220 &hf_lon_npdu_version,
221 &hf_lon_npdu_pdu_fmt,
222 &hf_lon_npdu_addr_fmt,
223 &hf_lon_npdu_dom_len,
224 NULL
225 };
226 proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_npdu,
227 ett_npdu, npdu_fields, ENC_BIG_ENDIAN);
228
229 pdu_fmt = (tvb_get_guint8(tvb, offset) >> 4) & 0x03;
230 addr_fmt = (tvb_get_guint8(tvb, offset) >> 2) & 0x03;
231 dom_len = tvb_get_guint8(tvb, offset) & 0x03;
232 offset++;
233 }
234 /* Address part */
235 switch(addr_fmt)
236 {
237 case 0: /* Broadcast */
238 ti = proto_tree_add_subtree(lon_tree, tvb, offset, 3, ett_address, NULL, "Address type 0 (broadcast)");
239 proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
240 proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
241 proto_tree_add_item(ti, hf_lon_addr_dstsub, tvb, offset+2, 1, ENC_BIG_ENDIAN);
242 offset += 3;
243 break;
244 case 1: /* Multicast */
245 ti = proto_tree_add_subtree(lon_tree, tvb, offset, 3, ett_address, NULL, "Address type 1 (multicast)");
246 proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
247 proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
248 proto_tree_add_item(ti, hf_lon_addr_dstgrp, tvb, offset+2, 1, ENC_BIG_ENDIAN);
249 offset += 3;
250 break;
251 case 2: /* Unicast/Multicast */
252 addr_a = tvb_get_guint8(tvb, offset+1) >> 7;
253 if (addr_a) { /* Type 2a */
254 ti = proto_tree_add_subtree(lon_tree, tvb, offset, 4, ett_address, NULL, "Address type 2a (unicast)");
255 proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
256 proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
257 proto_tree_add_item(ti, hf_lon_addr_dstsub, tvb, offset+2, 1, ENC_BIG_ENDIAN);
258 proto_tree_add_item(ti, hf_lon_addr_dstnode, tvb, offset+3, 1, ENC_BIG_ENDIAN);
259 offset += 4;
260 } else { /* Type 2b */
261 ti = proto_tree_add_subtree(lon_tree, tvb, offset, 6, ett_address, NULL, "Address type 2b (multicast)");
262 proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
263 proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
264 proto_tree_add_item(ti, hf_lon_addr_dstgrp, tvb, offset+2, 1, ENC_BIG_ENDIAN);
265 proto_tree_add_item(ti, hf_lon_addr_dstnode, tvb, offset+3, 1, ENC_BIG_ENDIAN);
266 proto_tree_add_item(ti, hf_lon_addr_grp, tvb, offset+4, 1, ENC_BIG_ENDIAN);
267 proto_tree_add_item(ti, hf_lon_addr_grpmem, tvb, offset+5, 1, ENC_BIG_ENDIAN);
268 offset += 6;
269 }
270 break;
271 case 3: /* UID */
272 ti = proto_tree_add_subtree(lon_tree, tvb, offset, 9, ett_address, NULL, "Address type 3 (UID)");
273 proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
274 proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
275 proto_tree_add_item(ti, hf_lon_addr_dstsub, tvb, offset+2, 1, ENC_BIG_ENDIAN);
276 proto_tree_add_item(ti, hf_lon_addr_uid, tvb, offset+3, 6, ENC_NA);
277 offset += 9;
278 break;
279 }
280 /* END Address part */
281 /* Domain */
282 switch(dom_len)
283 {
284 case 0: /* Domain-wide */
285 proto_tree_add_bytes_format(lon_tree, hf_lon_domain, tvb, offset, 0, NULL, "Domain wide addressing");
286 break;
287 case 1:
288 proto_tree_add_item(lon_tree, hf_lon_domain, tvb, offset, 1, ENC_NA);
289 offset++;
290 break;
291 case 2:
292 proto_tree_add_item(lon_tree, hf_lon_domain, tvb, offset, 3, ENC_NA);
293 offset += 3;
294 break;
295 case 3:
296 proto_tree_add_item(lon_tree, hf_lon_domain, tvb, offset, 6, ENC_NA);
297 offset += 6;
298 break;
299 }
300 /* END Domain */
301 /* *PDU */
302 switch(pdu_fmt)
303 {
304 case 0: /* TPDU */
305 {
306 static int * const tpdu_fields[] = {
307 &hf_lon_auth,
308 &hf_lon_tpdu_tpdu_type,
309 &hf_lon_trans_no,
310 NULL
311 };
312 proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_tpdu,
313 ett_tpdu, tpdu_fields, ENC_BIG_ENDIAN);
314
315 pdutype = (tvb_get_guint8(tvb, offset)>>4)& 0x07;
316 offset++;
317 switch(pdutype)
318 {
319 case 0:
320 case 1: /* ACKD and UnACKD_RPT */
321 offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
322 break;
323 case 2: /* ACK */
324 break;
325 case 4: /* REMINDER */
326 length = tvb_get_guint8(tvb, offset);
327 proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
328 offset++;
329 proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
330 offset += length;
331 break;
332 case 5: /* REM/MSG */
333 length = tvb_get_guint8(tvb, offset);
334 proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
335 offset++;
336 if (length > 0)
337 proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
338 offset += length;
339 offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
340 break;
341 default:
342 expert_add_info_format(pinfo, lon_tree, &ei_lon_tpdu_tpdu_type_unknown, "Unexpected TPDU type %i", pdutype);
343 break;
344 }
345 }
346 break;
347 case 1: /* SPDU */
348 {
349 static int * const spdu_fields[] = {
350 &hf_lon_auth,
351 &hf_lon_spdu_spdu_type,
352 &hf_lon_trans_no,
353 NULL
354 };
355 proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_spdu,
356 ett_spdu, spdu_fields, ENC_BIG_ENDIAN);
357 pdutype = (tvb_get_guint8(tvb, offset)>>4)& 0x07;
358 offset++;
359 switch(pdutype)
360 {
361 case 0: /* REQUEST */
362 offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
363 break;
364 case 2: /* RESPONSE */
365 offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
366 break;
367 case 4: /* REMINDER */
368 length = tvb_get_guint8(tvb, offset);
369 proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
370 offset++;
371 proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
372 offset += length;
373 break;
374 case 5: /* REM/MSG */
375 length = tvb_get_guint8(tvb, offset);
376 proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
377 offset++;
378 if (length > 0)
379 proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
380 offset += length;
381 offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
382 break;
383 default:
384 expert_add_info_format(pinfo, lon_tree, &ei_lon_tpdu_spdu_type_unknown, "Unexpected SPDU type %i", pdutype);
385 break;
386 }
387 }
388 break;
389 case 2: /* AuthPDU */
390 {
391 static int * const authpdu_fields[] = {
392 &hf_lon_authpdu_fmt,
393 &hf_lon_authpdu_authpdu_type,
394 &hf_lon_trans_no,
395 NULL
396 };
397 proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_authpdu,
398 ett_authpdu, authpdu_fields, ENC_BIG_ENDIAN);
399
400 pdutype = (tvb_get_guint8(tvb, offset)>>4)& 0x03;
401 offset++;
402 switch(pdutype)
403 {
404 case 0: /* CHALLENGE */
405 case 2: /* REPLY */
406 offset += 9;
407 break;
408 default:
409 expert_add_info_format(pinfo, lon_tree, &ei_lon_tpdu_authpdu_type_unknown, "Unexpected AuthPDU type %i", pdutype);
410 break;
411 }
412 }
413 break;
414 case 3: /* APDU */
415 offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
416 break;
417 }
418 /* END *PDU */
419
420 return offset;
421 }
422
423 static gint
dissect_apdu(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,gint offset)424 dissect_apdu(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
425 gint offset)
426 {
427 tvbuff_t *next_tvb;
428 gint old_offset = offset, dest_type;
429
430 dest_type = tvb_get_guint8(tvb, offset);
431
432 if ((dest_type&0x80) == 0x80) { /* Network variable */
433 static int * const nv_fields[] = {
434 &hf_lon_nv_dir,
435 &hf_lon_nv_selector,
436 NULL
437 };
438 proto_tree_add_bitmask(tree, tvb, offset, hf_lon_nv,
439 ett_nv, nv_fields, ENC_BIG_ENDIAN);
440 offset += 2;
441 } else if ((dest_type&0xc0) == 0) { /* Application */
442 static int * const app_fields[] = {
443 &hf_lon_app_code,
444 NULL
445 };
446 proto_tree_add_bitmask(tree, tvb, offset, hf_lon_app,
447 ett_app, app_fields, ENC_BIG_ENDIAN);
448 offset++;
449 } else if ((dest_type&0xe0) == 0x60) { /* Network Management */
450 static int * const nm_fields[] = {
451 &hf_lon_nm_code,
452 NULL
453 };
454 proto_tree_add_bitmask(tree, tvb, offset, hf_lon_nm,
455 ett_nm, nm_fields, ENC_BIG_ENDIAN);
456 offset++;
457
458 if (dest_type == 0x7F) {
459 proto_tree_add_item(tree, hf_lon_addr_uid, tvb, offset, 6, ENC_NA);
460 offset += 6;
461 proto_tree_add_item(tree, hf_lon_name, tvb, offset, 8, ENC_NA);
462 offset += 8;
463 }
464
465 } else if ((dest_type&0xf0) == 0x50) { /* Network Diagnostic */
466 static int * const nd_fields[] = {
467 &hf_lon_nd_code,
468 NULL
469 };
470 proto_tree_add_bitmask(tree, tvb, offset, hf_lon_nd,
471 ett_nd, nd_fields, ENC_BIG_ENDIAN);
472 offset++;
473 } else if ((dest_type&0xf0) == 0x40) { /* Foreign Frame */
474 static int * const ff_fields[] = {
475 &hf_lon_ff_code,
476 NULL
477 };
478 proto_tree_add_bitmask(tree, tvb, offset, hf_lon_ff,
479 ett_ff, ff_fields, ENC_BIG_ENDIAN);
480 offset++;
481 } else { /* Shouldn't get here */
482 expert_add_info_format(pinfo, tree, &ei_lon_tpdu_apdu_dest_type, "Malformed APDU destin&type %i", dest_type);
483 }
484
485 next_tvb = tvb_new_subset_remaining(tvb, offset);
486
487 return offset - old_offset + call_data_dissector(next_tvb, pinfo, tree);
488 }
489
490 void
proto_register_lon(void)491 proto_register_lon(void)
492 {
493 static hf_register_info hf[] =
494 {
495 {&hf_lon_ppdu,
496 {"PPDU", "lon.ppdu",
497 FT_UINT8, BASE_HEX, NULL, 0,
498 NULL, HFILL }
499 },
500 {&hf_lon_ppdu_prio,
501 {"Priority", "lon.prio",
502 FT_UINT8, BASE_DEC, NULL, 0x80,
503 "Priority packet", HFILL }
504 },
505 {&hf_lon_ppdu_alt,
506 {"Alt path", "lon.alt_path",
507 FT_UINT8, BASE_DEC, NULL, 0x40,
508 "Alternate path", HFILL }
509 },
510 {&hf_lon_ppdu_deltabl,
511 {"Delta BL", "lon.delta_bl",
512 FT_UINT8, BASE_DEC, NULL, 0x3f,
513 "How many packets to expect from this one", HFILL }
514 },
515 {&hf_lon_npdu,
516 {"NPDU", "lon.npdu",
517 FT_UINT8, BASE_DEC, NULL, 0,
518 NULL, HFILL }
519 },
520 {&hf_lon_npdu_version,
521 {"version", "lon.vers",
522 FT_UINT8, BASE_HEX, NULL, 0xc0,
523 "LON protocol version", HFILL }
524 },
525 {&hf_lon_npdu_pdu_fmt,
526 {"PDU format", "lon.pdufmt",
527 FT_UINT8, BASE_HEX, VALS(pdu_fmt_vs), 0x30,
528 NULL, HFILL }
529 },
530 {&hf_lon_npdu_addr_fmt,
531 {"Address format", "lon.addrfmt",
532 FT_UINT8, BASE_HEX, VALS(addr_fmt_vs), 0x0c,
533 NULL, HFILL }
534 },
535 {&hf_lon_npdu_dom_len,
536 {"Domain length", "lon.domainlen",
537 FT_UINT8, BASE_HEX, VALS(domain_length_vs), 0x03,
538 NULL, HFILL }
539 },
540 {&hf_lon_addr_srcsub,
541 {"Source subnet", "lon.srcnet",
542 FT_UINT8, BASE_HEX, NULL, 0,
543 NULL, HFILL }
544 },
545 {&hf_lon_addr_srcnode,
546 {"Source node", "lon.srcnode",
547 FT_UINT8, BASE_HEX, NULL, 0x7f,
548 NULL, HFILL }
549 },
550 {&hf_lon_addr_dstsub,
551 {"Destination subnet", "lon.dstnet",
552 FT_UINT8, BASE_HEX, NULL, 0,
553 NULL, HFILL }
554 },
555 {&hf_lon_addr_dstgrp,
556 {"Destination group", "lon.dstgrp",
557 FT_UINT8, BASE_HEX, NULL, 0,
558 NULL, HFILL }
559 },
560 {&hf_lon_addr_dstnode,
561 {"Destination node", "lon.dstnode",
562 FT_UINT8, BASE_HEX, NULL, 0x7f,
563 NULL, HFILL }
564 },
565 {&hf_lon_addr_grp,
566 {"Group", "lon.grp",
567 FT_UINT8, BASE_HEX, NULL, 0,
568 NULL, HFILL }
569 },
570 {&hf_lon_addr_grpmem,
571 {"Group member", "lon.grpmem",
572 FT_UINT8, BASE_HEX, NULL, 0,
573 NULL, HFILL }
574 },
575 {&hf_lon_addr_uid,
576 {"Unique node ID", "lon.uid",
577 FT_BYTES, BASE_NONE, NULL, 0,
578 NULL, HFILL }
579 },
580 {&hf_lon_domain,
581 {"Domain", "lon.domain",
582 FT_BYTES, BASE_NONE, NULL , 0,
583 NULL, HFILL }
584 },
585 {&hf_lon_tpdu,
586 {"TPDU", "lon.tpdu",
587 FT_UINT8, BASE_HEX, NULL, 0,
588 NULL, HFILL }
589 },
590 {&hf_lon_auth,
591 {"Auth", "lon.auth",
592 FT_UINT8, BASE_HEX, NULL, 0x80,
593 NULL, HFILL }
594 },
595 {&hf_lon_tpdu_tpdu_type,
596 {"TPDU type", "lon.tpdu_type",
597 FT_UINT8, BASE_HEX, VALS(tpdu_type_vs), 0x70,
598 NULL, HFILL }
599 },
600 {&hf_lon_trans_no,
601 {"Transaction number", "lon.trans_no",
602 FT_UINT8, BASE_HEX, NULL, 0x0f,
603 NULL, HFILL }
604 },
605 {&hf_lon_spdu,
606 {"SPDU", "lon.spdu",
607 FT_UINT8, BASE_HEX, NULL, 0,
608 NULL, HFILL }
609 },
610 {&hf_lon_spdu_spdu_type,
611 {"SPDU type", "lon.spdu_type",
612 FT_UINT8, BASE_HEX, VALS(spdu_type_vs), 0x70,
613 NULL, HFILL }
614 },
615 {&hf_lon_mlen,
616 {"Length of M_List", "lon.spdu.mlen",
617 FT_UINT8, BASE_HEX, NULL, 0,
618 NULL, HFILL }
619 },
620 {&hf_lon_mlist,
621 {"M_List", "lon.spdu.mlist",
622 FT_UINT8, BASE_HEX, NULL, 0,
623 NULL, HFILL }
624 },
625 {&hf_lon_authpdu,
626 {"AuthPDU", "lon.authpdu",
627 FT_UINT8, BASE_HEX, NULL, 0,
628 NULL, HFILL }
629 },
630 {&hf_lon_authpdu_fmt,
631 {"FMT (same as AddrFmt)", "lon.authpdu_addrfmt",
632 FT_UINT8, BASE_HEX, NULL, 0xc,
633 NULL, HFILL }
634 },
635 {&hf_lon_authpdu_authpdu_type,
636 {"AuthPDU type", "lon.authpdu_type",
637 FT_UINT8, BASE_HEX, VALS(authpdu_type_vs), 0x2,
638 NULL, HFILL }
639 },
640 {&hf_lon_nv,
641 {"Network Variable", "lon.nv",
642 FT_UINT16, BASE_HEX, NULL, 0,
643 NULL, HFILL }
644 },
645 {&hf_lon_nv_dir,
646 {"NV direction", "lon.nv.dir",
647 FT_UINT16, BASE_HEX, NULL, 0x4000,
648 NULL, HFILL }
649 },
650 {&hf_lon_nv_selector,
651 {"NV selector", "lon.nv.selector",
652 FT_UINT16, BASE_HEX, NULL, 0x3fff,
653 NULL, HFILL }
654 },
655 {&hf_lon_app,
656 {"Application", "lon.application",
657 FT_UINT8, BASE_HEX, NULL, 0,
658 NULL, HFILL }
659 },
660 {&hf_lon_app_code,
661 {"Code", "lon.code",
662 FT_UINT8, BASE_HEX, NULL, 0x3f,
663 NULL, HFILL }
664 },
665 {&hf_lon_nm,
666 {"Network Management", "lon.nm",
667 FT_UINT8, BASE_HEX, NULL, 0,
668 NULL, HFILL }
669 },
670 {&hf_lon_nm_code,
671 {"Code", "lon.code",
672 FT_UINT8, BASE_HEX, VALS(nm_code_vs), 0xff,
673 NULL, HFILL }
674 },
675 {&hf_lon_nd,
676 {"Network Diagnostic", "lon.nd",
677 FT_UINT8, BASE_HEX, NULL, 0,
678 NULL, HFILL }
679 },
680 {&hf_lon_nd_code,
681 {"Code", "lon.code",
682 FT_UINT8, BASE_HEX, VALS(nd_code_vs), 0xff,
683 NULL, HFILL }
684 },
685 {&hf_lon_ff,
686 {"Foreign Frame", "lon.ff",
687 FT_UINT8, BASE_HEX, NULL, 0,
688 NULL, HFILL }
689 },
690 {&hf_lon_ff_code,
691 {"Code", "lon.code",
692 FT_UINT8, BASE_HEX, NULL, 0x0f,
693 NULL, HFILL }
694 },
695 {&hf_lon_name,
696 {"Node name", "lon.name",
697 FT_BYTES, BASE_NONE, NULL, 0,
698 NULL, HFILL }
699 },
700 #if 0
701 {&hf_lon_checksum,
702 {"Checksum", "lon.chksum",
703 FT_BYTES, BASE_NONE, NULL, 0,
704 NULL, HFILL }
705 }
706 #endif
707 };
708
709 static gint *ett[] =
710 {
711 &ett_lon,
712 &ett_address,
713 &ett_ppdu,
714 &ett_npdu,
715 &ett_tpdu,
716 &ett_spdu,
717 &ett_authpdu,
718 &ett_apdu,
719 &ett_nv,
720 &ett_app,
721 &ett_nm,
722 &ett_nd,
723 &ett_ff
724 };
725
726 static ei_register_info ei[] = {
727 { &ei_lon_tpdu_tpdu_type_unknown, { "lon.tpdu_type.unknown", PI_PROTOCOL, PI_WARN, "Unexpected TPDU type", EXPFILL }},
728 { &ei_lon_tpdu_spdu_type_unknown, { "lon.spdu_type.unknown", PI_PROTOCOL, PI_WARN, "Unexpected SPDU type", EXPFILL }},
729 { &ei_lon_tpdu_authpdu_type_unknown, { "lon.authpdu_type.unknown", PI_PROTOCOL, PI_WARN, "Unexpected AuthPDU type", EXPFILL }},
730 { &ei_lon_tpdu_apdu_dest_type, { "lon.authpdu_dest_type.unknown", PI_PROTOCOL, PI_WARN, "Malformed APDU destin&type", EXPFILL }},
731 };
732
733 expert_module_t* expert_lon;
734
735 proto_lon = proto_register_protocol("Local Operating Network",
736 "LON", "lon");
737
738 proto_register_field_array (proto_lon, hf, array_length (hf));
739 proto_register_subtree_array (ett, array_length (ett));
740 expert_lon = expert_register_protocol(proto_lon);
741 expert_register_field_array(expert_lon, ei, array_length(ei));
742 }
743
744
745 void
proto_reg_handoff_lon(void)746 proto_reg_handoff_lon(void)
747 {
748 dissector_handle_t lon_handle;
749
750 lon_handle = create_dissector_handle(dissect_lon, proto_lon);
751
752 dissector_add_uint("cnip.protocol", 0, lon_handle);
753 }
754
755 /*
756 * Editor modelines - https://www.wireshark.org/tools/modelines.html
757 *
758 * Local variables:
759 * c-basic-offset: 8
760 * tab-width: 8
761 * indent-tabs-mode: t
762 * End:
763 *
764 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
765 * :indentSize=8:tabSize=8:noTabs=false:
766 */
767