2 * Routines for decoding isis complete & partial SNP and their payload
4 * Stuart Stanley <stuarts@mxmail.net>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/expert.h>
30 #include "packet-osi.h"
31 #include "packet-isis.h"
32 #include "packet-isis-clv.h"
34 void proto_register_isis_csnp(void);
35 void proto_reg_handoff_isis_csnp(void);
36 void proto_register_isis_psnp(void);
37 void proto_reg_handoff_isis_psnp(void);
38 void proto_register_isis_lsp(void);
39 void proto_reg_handoff_isis_lsp(void);
40 void proto_register_isis_hello(void);
41 void proto_reg_handoff_isis_hello(void);
43 static int proto_isis_csnp = -1;
44 static int proto_isis_psnp = -1;
47 static int hf_isis_csnp_pdu_length = -1;
48 static int hf_isis_csnp_source_id = -1;
49 static int hf_isis_csnp_start_lsp_id = -1;
50 static int hf_isis_csnp_end_lsp_id = -1;
51 static int hf_isis_csnp_lsp_id = -1;
52 static int hf_isis_csnp_lsp_seq_num = -1;
53 static int hf_isis_csnp_lsp_remain_life = -1;
54 static int hf_isis_csnp_lsp_checksum = -1;
55 static int hf_isis_csnp_checksum = -1;
56 static gint ett_isis_csnp = -1;
57 static gint ett_isis_csnp_clv_lsp_entries = -1;
58 static gint ett_isis_csnp_lsp_entry = -1;
59 static gint ett_isis_csnp_clv_authentication = -1;
60 static gint ett_isis_csnp_clv_ip_authentication = -1;
61 static gint ett_isis_csnp_clv_checksum = -1;
62 static gint ett_isis_csnp_clv_unknown = -1;
64 static expert_field ei_isis_csnp_short_packet = EI_INIT;
65 static expert_field ei_isis_csnp_long_packet = EI_INIT;
66 static expert_field ei_isis_csnp_authentication = EI_INIT;
69 static int hf_isis_psnp_pdu_length = -1;
70 static int hf_isis_psnp_source_id = -1;
71 static gint ett_isis_psnp = -1;
72 static gint ett_isis_psnp_clv_lsp_entries = -1;
73 static gint ett_isis_psnp_lsp_entry = -1;
74 static gint ett_isis_psnp_clv_authentication = -1;
75 static gint ett_isis_psnp_clv_ip_authentication = -1;
76 static gint ett_isis_psnp_clv_checksum = -1;
77 static gint ett_isis_psnp_clv_unknown = -1;
79 static expert_field ei_isis_psnp_short_packet = EI_INIT;
80 static expert_field ei_isis_psnp_long_packet = EI_INIT;
83 dissect_snp_authentication_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
84 int id_length _U_, int length)
86 isis_dissect_authentication_clv(tree, pinfo, tvb, &ei_isis_csnp_authentication, offset, length);
90 dissect_snp_ip_authentication_clv(tvbuff_t *tvb, packet_info* pinfo _U_, proto_tree *tree, int offset,
91 int id_length _U_, int length)
93 isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
97 * Name: dissect_snp_checksum_clv()
100 * dump and verify the optional checksum in TLV 12
103 dissect_snp_checksum_clv(tvbuff_t *tvb, packet_info* pinfo,
104 proto_tree *tree, int offset, int id_length _U_, int length) {
106 guint16 pdu_length,checksum, cacl_checksum=0;
110 proto_tree_add_expert_format(tree, pinfo, &ei_isis_csnp_short_packet, tvb, offset, -1,
111 "incorrect checksum length (%u), should be (2)", length );
115 ti = proto_tree_add_item( tree, hf_isis_csnp_checksum, tvb, offset, length, ENC_BIG_ENDIAN);
117 checksum = tvb_get_ntohs(tvb, offset);
119 /* the check_and_get_checksum() function needs to know how big
120 * the packet is. we can either pass through the pdu-len through several layers
121 * of dissectors and wrappers or extract the PDU length field from the PDU specific header
122 * which is offseted 8 bytes (relative to the beginning of the IS-IS packet) in SNPs */
124 pdu_length = tvb_get_ntohs(tvb, 8);
126 /* unlike the LSP checksum verification which starts at an offset of 12 we start at offset 0*/
127 switch (check_and_get_checksum(tvb, 0, pdu_length, checksum, offset, &cacl_checksum))
130 proto_item_append_text(ti, " [unused]");
133 expert_add_info_format(pinfo, ti, &ei_isis_csnp_long_packet,
134 "Packet length %d went beyond packet", tvb_length(tvb));
137 proto_item_append_text(ti, " [incorrect, should be 0x%04x]", cacl_checksum);
140 proto_item_append_text(ti, " [correct]");
146 * Name: dissect_snp_lsp_entries_clv()
149 * All the snp packets use a common payload format. We have up
150 * to n entries (based on length), which are made of:
151 * 2 : remaining life time
153 * 4 : sequence number
157 dissect_snp_lsp_entries_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
158 int id_length, int length)
163 while ( length > 0 ) {
164 if ( length < 2+id_length+2+4+2 ) {
165 proto_tree_add_expert_format(tree, pinfo, &ei_isis_csnp_short_packet, tvb, offset, -1,
166 "Short SNP header entry (%d vs %d)", length, 2+id_length+2+4+2 );
170 ti = proto_tree_add_text(tree, tvb, offset, 2+id_length+2+4+2, "LSP Entry");
171 subtree = proto_item_add_subtree(ti,ett_isis_csnp_lsp_entry);
173 proto_tree_add_item(tree, hf_isis_csnp_lsp_id, tvb, offset+2, id_length+2, ENC_NA);
175 proto_tree_add_item(subtree, hf_isis_csnp_lsp_seq_num, tvb, offset+2+id_length+2, 4, ENC_BIG_ENDIAN);
176 proto_tree_add_item(subtree, hf_isis_csnp_lsp_remain_life, tvb, offset, 2, ENC_BIG_ENDIAN);
177 proto_tree_add_item(subtree, hf_isis_csnp_lsp_checksum, tvb, offset+2+id_length+2+4, 2, ENC_BIG_ENDIAN);
179 length -= 2+id_length+2+4+2;
180 offset += 2+id_length+2+4+2;
185 static const isis_clv_handle_t clv_l1_csnp_opts[] = {
187 ISIS_CLV_LSP_ENTRIES,
189 &ett_isis_csnp_clv_lsp_entries,
190 dissect_snp_lsp_entries_clv
193 ISIS_CLV_AUTHENTICATION,
195 &ett_isis_csnp_clv_authentication,
196 dissect_snp_authentication_clv
199 ISIS_CLV_IP_AUTHENTICATION,
201 &ett_isis_csnp_clv_ip_authentication,
202 dissect_snp_ip_authentication_clv
207 &ett_isis_csnp_clv_checksum,
208 dissect_snp_checksum_clv
215 static const isis_clv_handle_t clv_l2_csnp_opts[] = {
217 ISIS_CLV_LSP_ENTRIES,
219 &ett_isis_csnp_clv_lsp_entries,
220 dissect_snp_lsp_entries_clv
223 ISIS_CLV_AUTHENTICATION,
225 &ett_isis_csnp_clv_authentication,
226 dissect_snp_authentication_clv
229 ISIS_CLV_IP_AUTHENTICATION,
231 &ett_isis_csnp_clv_ip_authentication,
232 dissect_snp_ip_authentication_clv
237 &ett_isis_csnp_clv_checksum,
238 dissect_snp_checksum_clv
245 static const isis_clv_handle_t clv_l1_psnp_opts[] = {
247 ISIS_CLV_LSP_ENTRIES,
249 &ett_isis_psnp_clv_lsp_entries,
250 dissect_snp_lsp_entries_clv
253 ISIS_CLV_AUTHENTICATION,
255 &ett_isis_psnp_clv_authentication,
256 dissect_snp_authentication_clv
259 ISIS_CLV_IP_AUTHENTICATION,
261 &ett_isis_psnp_clv_ip_authentication,
262 dissect_snp_ip_authentication_clv
267 &ett_isis_psnp_clv_checksum,
268 dissect_snp_checksum_clv
275 static const isis_clv_handle_t clv_l2_psnp_opts[] = {
277 ISIS_CLV_LSP_ENTRIES,
279 &ett_isis_psnp_clv_lsp_entries,
280 dissect_snp_lsp_entries_clv
283 ISIS_CLV_AUTHENTICATION,
285 &ett_isis_psnp_clv_authentication,
286 dissect_snp_authentication_clv
289 ISIS_CLV_IP_AUTHENTICATION,
291 &ett_isis_psnp_clv_ip_authentication,
292 dissect_snp_ip_authentication_clv
297 &ett_isis_psnp_clv_checksum,
298 dissect_snp_checksum_clv
306 dissect_isis_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
307 const isis_clv_handle_t *opts, int header_length, int id_length)
310 proto_tree *csnp_tree = NULL;
314 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISIS CSNP");
316 ti = proto_tree_add_item(tree, proto_isis_csnp, tvb, offset, -1, ENC_NA);
317 csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
319 pdu_length = tvb_get_ntohs(tvb, offset);
320 proto_tree_add_uint(csnp_tree, hf_isis_csnp_pdu_length, tvb,
321 offset, 2, pdu_length);
324 proto_tree_add_item(csnp_tree, hf_isis_csnp_source_id, tvb, offset, id_length, ENC_NA);
325 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s", tvb_print_system_id( tvb, offset, id_length ));
326 offset += id_length + 1;
328 proto_tree_add_item(csnp_tree, hf_isis_csnp_start_lsp_id, tvb, offset, id_length + 2, ENC_NA);
329 col_append_fstr(pinfo->cinfo, COL_INFO, ", Start LSP-ID: %s",
330 tvb_print_system_id( tvb, offset, id_length+2 ));
331 offset += id_length + 2;
333 proto_tree_add_item(csnp_tree, hf_isis_csnp_end_lsp_id, tvb, offset, id_length + 2, ENC_NA);
334 col_append_fstr(pinfo->cinfo, COL_INFO, ", End LSP-ID: %s",
335 tvb_print_system_id( tvb, offset, id_length+2 ));
336 offset += id_length + 2;
338 len = pdu_length - header_length;
340 proto_tree_add_expert_format(tree, pinfo, &ei_isis_csnp_short_packet, tvb, offset, -1,
341 "packet header length %d went beyond packet", header_length );
345 isis_dissect_clvs(tvb, pinfo, csnp_tree, offset,
346 opts, &ei_isis_csnp_short_packet, len, id_length, ett_isis_csnp_clv_unknown );
351 dissect_isis_l1_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
353 isis_data_t* isis = (isis_data_t*)data;
354 dissect_isis_csnp(tvb, pinfo, tree, 0,
355 clv_l1_csnp_opts, isis->header_length, isis->system_id_len);
356 return tvb_length(tvb);
360 dissect_isis_l2_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
362 isis_data_t* isis = (isis_data_t*)data;
363 dissect_isis_csnp(tvb, pinfo, tree, 0,
364 clv_l2_csnp_opts, isis->header_length, isis->system_id_len);
365 return tvb_length(tvb);
369 dissect_isis_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
370 const isis_clv_handle_t *opts, int header_length, int id_length)
373 proto_tree *psnp_tree;
377 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISIS PSNP");
379 ti = proto_tree_add_item(tree, proto_isis_psnp, tvb, offset, -1, ENC_NA);
380 psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
382 pdu_length = tvb_get_ntohs(tvb, offset);
383 proto_tree_add_uint(psnp_tree, hf_isis_psnp_pdu_length, tvb,
384 offset, 2, pdu_length);
387 proto_tree_add_item(psnp_tree, hf_isis_psnp_source_id, tvb, offset, id_length, ENC_NA);
388 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s", tvb_print_system_id( tvb, offset, id_length ));
390 offset += id_length + 1;
392 len = pdu_length - header_length;
394 proto_tree_add_expert_format(tree, pinfo, &ei_isis_psnp_long_packet, tvb, offset, -1,
395 "packet header length %d went beyond packet", header_length );
398 /* Call into payload dissector */
399 isis_dissect_clvs(tvb, pinfo, psnp_tree, offset,
400 opts, &ei_isis_psnp_short_packet, len, id_length, ett_isis_psnp_clv_unknown );
404 dissect_isis_l1_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
406 isis_data_t* isis = (isis_data_t*)data;
407 dissect_isis_psnp(tvb, pinfo, tree, 0,
408 clv_l1_psnp_opts, isis->header_length, isis->system_id_len);
409 return tvb_length(tvb);
413 dissect_isis_l2_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
415 isis_data_t* isis = (isis_data_t*)data;
416 dissect_isis_psnp(tvb, pinfo, tree, 0,
417 clv_l2_psnp_opts, isis->header_length, isis->system_id_len);
418 return tvb_length(tvb);
422 proto_register_isis_csnp(void)
424 static hf_register_info hf[] = {
425 { &hf_isis_csnp_pdu_length,
426 { "PDU length", "isis.csnp.pdu_length", FT_UINT16,
427 BASE_DEC, NULL, 0x0, NULL, HFILL }},
428 { &hf_isis_csnp_source_id,
429 { "Source-ID", "isis.csnp.source_id",
430 FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
431 { &hf_isis_csnp_start_lsp_id,
432 { "Start LSP-ID", "isis.csnp.start_lsp_id",
433 FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
434 { &hf_isis_csnp_end_lsp_id,
435 { "End LSP-ID", "isis.csnp.end_lsp_id",
436 FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
437 { &hf_isis_csnp_lsp_id,
438 { "LSP-ID", "isis.csnp.lsp_id",
439 FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
440 { &hf_isis_csnp_lsp_seq_num,
441 { "LSP Sequence Number", "isis.csnp.lsp_seq_num", FT_UINT32,
442 BASE_HEX, NULL, 0x0, NULL, HFILL }},
443 { &hf_isis_csnp_lsp_remain_life,
444 { "Remaining Lifetime", "isis.csnp.lsp_remain_life", FT_UINT16,
445 BASE_DEC, NULL, 0x0, NULL, HFILL }},
446 { &hf_isis_csnp_lsp_checksum,
447 { "LSP checksum", "isis.csnp.lsp_checksum", FT_UINT16,
448 BASE_HEX, NULL, 0x0, NULL, HFILL }},
449 { &hf_isis_csnp_checksum,
450 { "Checksum", "isis.csnp.checksum", FT_UINT16,
451 BASE_HEX, NULL, 0x0, NULL, HFILL }},
454 static gint *ett[] = {
456 &ett_isis_csnp_clv_lsp_entries,
457 &ett_isis_csnp_lsp_entry,
458 &ett_isis_csnp_clv_authentication,
459 &ett_isis_csnp_clv_ip_authentication,
460 &ett_isis_csnp_clv_checksum,
461 &ett_isis_csnp_clv_unknown,
464 static ei_register_info ei[] = {
465 { &ei_isis_csnp_short_packet, { "isis.csnp.short_packet", PI_MALFORMED, PI_ERROR, "Short packet", EXPFILL }},
466 { &ei_isis_csnp_long_packet, { "isis.csnp.long_packet", PI_MALFORMED, PI_ERROR, "Long packet", EXPFILL }},
467 { &ei_isis_csnp_authentication, { "isis.csnp.authentication.unknown", PI_PROTOCOL, PI_WARN, "Unknown authentication type", EXPFILL }},
469 expert_module_t* expert_isis_csnp;
471 /* Register the protocol name and description */
472 proto_isis_csnp = proto_register_protocol(PROTO_STRING_CSNP, "ISIS CSNP", "isis.csnp");
474 proto_register_field_array(proto_isis_csnp, hf, array_length(hf));
475 proto_register_subtree_array(ett, array_length(ett));
476 expert_isis_csnp = expert_register_protocol(proto_isis_csnp);
477 expert_register_field_array(expert_isis_csnp, ei, array_length(ei));
481 proto_reg_handoff_isis_csnp(void)
483 dissector_add_uint("isis.type", ISIS_TYPE_L1_CSNP, new_create_dissector_handle(dissect_isis_l1_csnp, proto_isis_csnp));
484 dissector_add_uint("isis.type", ISIS_TYPE_L2_CSNP, new_create_dissector_handle(dissect_isis_l2_csnp, proto_isis_csnp));
488 proto_register_isis_psnp(void)
490 static hf_register_info hf[] = {
491 { &hf_isis_psnp_pdu_length,
492 { "PDU length", "isis.psnp.pdu_length", FT_UINT16,
493 BASE_DEC, NULL, 0x0, NULL, HFILL }},
494 { &hf_isis_psnp_source_id,
495 { "Source-ID", "isis.psnp.source_id",
496 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
499 static gint *ett[] = {
501 &ett_isis_psnp_clv_lsp_entries,
502 &ett_isis_psnp_lsp_entry,
503 &ett_isis_psnp_clv_authentication,
504 &ett_isis_psnp_clv_ip_authentication,
505 &ett_isis_psnp_clv_checksum,
506 &ett_isis_psnp_clv_unknown,
508 static ei_register_info ei[] = {
509 { &ei_isis_psnp_long_packet, { "isis.psnp.long_packet", PI_MALFORMED, PI_ERROR, "Long packet", EXPFILL }},
510 { &ei_isis_psnp_short_packet, { "isis.psnp.short_packet", PI_MALFORMED, PI_ERROR, "Short packet", EXPFILL }},
512 expert_module_t* expert_isis_psnp;
514 /* Register the protocol name and description */
515 proto_isis_psnp = proto_register_protocol(PROTO_STRING_PSNP, "ISIS PSNP", "isis.psnp");
517 proto_register_field_array(proto_isis_psnp, hf, array_length(hf));
518 proto_register_subtree_array(ett, array_length(ett));
519 expert_isis_psnp = expert_register_protocol(proto_isis_psnp);
520 expert_register_field_array(expert_isis_psnp, ei, array_length(ei));
524 proto_reg_handoff_isis_psnp(void)
526 dissector_add_uint("isis.type", ISIS_TYPE_L1_PSNP, new_create_dissector_handle(dissect_isis_l1_psnp, proto_isis_psnp));
527 dissector_add_uint("isis.type", ISIS_TYPE_L2_PSNP, new_create_dissector_handle(dissect_isis_l2_psnp, proto_isis_psnp));