2 * Routines for decoding isis complete & partial SNP and their payload
5 * Stuart Stanley <stuarts@mxmail.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <epan/packet.h>
30 #include "packet-osi.h"
31 #include "packet-isis.h"
32 #include "packet-isis-clv.h"
33 #include "packet-isis-lsp.h"
34 #include "packet-isis-snp.h"
37 static int hf_isis_csnp_pdu_length
= -1;
38 static gint ett_isis_csnp
= -1;
39 static gint ett_isis_csnp_clv_lsp_entries
= -1;
40 static gint ett_isis_csnp_lsp_entry
= -1;
41 static gint ett_isis_csnp_clv_authentication
= -1;
42 static gint ett_isis_csnp_clv_ip_authentication
= -1;
43 static gint ett_isis_csnp_clv_checksum
= -1;
44 static gint ett_isis_csnp_clv_unknown
= -1;
47 static int hf_isis_psnp_pdu_length
= -1;
48 static gint ett_isis_psnp
= -1;
49 static gint ett_isis_psnp_clv_lsp_entries
= -1;
50 static gint ett_isis_psnp_lsp_entry
= -1;
51 static gint ett_isis_psnp_clv_authentication
= -1;
52 static gint ett_isis_psnp_clv_ip_authentication
= -1;
53 static gint ett_isis_psnp_clv_checksum
= -1;
54 static gint ett_isis_psnp_clv_unknown
= -1;
56 static void dissect_snp_authentication_clv(tvbuff_t
*tvb
,
57 proto_tree
*tree
, int offset
, int id_length
, int length
);
58 static void dissect_snp_ip_authentication_clv(tvbuff_t
*tvb
,
59 proto_tree
*tree
, int offset
, int id_length
, int length
);
60 static void dissect_snp_checksum_clv(tvbuff_t
*tvb
,
61 proto_tree
*tree
, int offset
, int id_length
, int length
);
62 static void dissect_snp_lsp_entries_clv(tvbuff_t
*tvb
,
63 proto_tree
*tree
, int offset
, int id_length
, int length
);
65 static const isis_clv_handle_t clv_l1_csnp_opts
[] = {
69 &ett_isis_csnp_clv_lsp_entries
,
70 dissect_snp_lsp_entries_clv
73 ISIS_CLV_AUTHENTICATION
,
75 &ett_isis_csnp_clv_authentication
,
76 dissect_snp_authentication_clv
79 ISIS_CLV_IP_AUTHENTICATION
,
81 &ett_isis_csnp_clv_ip_authentication
,
82 dissect_snp_ip_authentication_clv
87 &ett_isis_csnp_clv_checksum
,
88 dissect_snp_checksum_clv
95 static const isis_clv_handle_t clv_l2_csnp_opts
[] = {
99 &ett_isis_csnp_clv_lsp_entries
,
100 dissect_snp_lsp_entries_clv
103 ISIS_CLV_AUTHENTICATION
,
105 &ett_isis_csnp_clv_authentication
,
106 dissect_snp_authentication_clv
109 ISIS_CLV_IP_AUTHENTICATION
,
111 &ett_isis_csnp_clv_ip_authentication
,
112 dissect_snp_ip_authentication_clv
117 &ett_isis_csnp_clv_checksum
,
118 dissect_snp_checksum_clv
125 static const isis_clv_handle_t clv_l1_psnp_opts
[] = {
127 ISIS_CLV_LSP_ENTRIES
,
129 &ett_isis_psnp_clv_lsp_entries
,
130 dissect_snp_lsp_entries_clv
133 ISIS_CLV_AUTHENTICATION
,
135 &ett_isis_psnp_clv_authentication
,
136 dissect_snp_authentication_clv
139 ISIS_CLV_IP_AUTHENTICATION
,
141 &ett_isis_psnp_clv_ip_authentication
,
142 dissect_snp_ip_authentication_clv
147 &ett_isis_psnp_clv_checksum
,
148 dissect_snp_checksum_clv
155 static const isis_clv_handle_t clv_l2_psnp_opts
[] = {
157 ISIS_CLV_LSP_ENTRIES
,
159 &ett_isis_psnp_clv_lsp_entries
,
160 dissect_snp_lsp_entries_clv
163 ISIS_CLV_AUTHENTICATION
,
165 &ett_isis_psnp_clv_authentication
,
166 dissect_snp_authentication_clv
169 ISIS_CLV_IP_AUTHENTICATION
,
171 &ett_isis_psnp_clv_ip_authentication
,
172 dissect_snp_ip_authentication_clv
177 &ett_isis_psnp_clv_checksum
,
178 dissect_snp_checksum_clv
186 * Name: dissect_snp_lsp_entries_clv()
189 * All the snp packets use a common payload format. We have up
190 * to n entries (based on length), which are made of:
191 * 2 : remaining life time
193 * 4 : sequence number
197 * tvbuff_t * : tvbuffer for packet data
198 * proto_tree * : protocol display tree to fill out. May be NULL
199 * int : offset into packet data where we are.
200 * int : length of IDs in packet.
201 * int : length of payload to decode.
204 * void, but we will add to proto tree if !NULL.
207 dissect_snp_lsp_entries_clv(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
,
208 int id_length
, int length
)
210 proto_tree
*subtree
,*ti
;
212 while ( length
> 0 ) {
213 if ( length
< 2+id_length
+2+4+2 ) {
214 isis_dissect_unknown(tvb
, tree
, offset
,
215 "Short SNP header entry (%d vs %d)", length
,
220 ti
= proto_tree_add_text(tree
, tvb
, offset
, 2+id_length
+2+4+2,
221 "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
222 print_system_id( tvb_get_ptr(tvb
, offset
+2, id_length
+2), id_length
+2 ),
223 tvb_get_ntohl(tvb
, offset
+2+id_length
+2),
224 tvb_get_ntohs(tvb
, offset
),
225 tvb_get_ntohs(tvb
, offset
+2+id_length
+2+4));
227 subtree
= proto_item_add_subtree(ti
,ett_isis_csnp_lsp_entry
);
229 proto_tree_add_text(subtree
, tvb
, offset
+2, 8,
231 print_system_id( tvb_get_ptr(tvb
, offset
+2, id_length
+2), id_length
+2 ));
233 proto_tree_add_text(subtree
, tvb
, offset
+2+id_length
+2, 4,
234 "LSP Sequence Number : 0x%08x",
235 tvb_get_ntohl(tvb
, offset
+2+id_length
+2));
237 proto_tree_add_text(subtree
, tvb
, offset
, 2,
238 "Remaining Lifetime : %us",
239 tvb_get_ntohs(tvb
, offset
));
241 proto_tree_add_text(subtree
, tvb
, offset
+2+id_length
+2+4, 2,
242 "LSP checksum : 0x%04x",
243 tvb_get_ntohs(tvb
, offset
+2+id_length
+2+4));
245 length
-= 2+id_length
+2+4+2;
246 offset
+= 2+id_length
+2+4+2;
253 * Name: isis_dissect_isis_csnp()
256 * Tear apart a L1 or L2 CSNP header and then call into payload dissect
257 * to pull apart the lsp id payload.
260 * tvbuff_t * : tvbuffer for packet data
261 * proto_tree * : protocol display tree to add to. May be NULL.
262 * int offset : our offset into packet data.
263 * int : type (l1 csnp, l2 csnp)
264 * int : header length of packet.
265 * int : length of IDs in packet.
268 * void, but we will add to proto tree if !NULL.
271 isis_dissect_isis_csnp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
,
272 int type
, int header_length
, int id_length
)
275 proto_tree
*csnp_tree
= NULL
;
280 ti
= proto_tree_add_text(tree
, tvb
, offset
, -1,
282 csnp_tree
= proto_item_add_subtree(ti
, ett_isis_csnp
);
285 pdu_length
= tvb_get_ntohs(tvb
, offset
);
287 proto_tree_add_uint(csnp_tree
, hf_isis_csnp_pdu_length
, tvb
,
288 offset
, 2, pdu_length
);
293 proto_tree_add_text(csnp_tree
, tvb
, offset
, id_length
+ 1,
295 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+1), id_length
+1 ) );
297 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Source-ID: %s",
298 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+1), id_length
+1 ) );
300 offset
+= id_length
+ 1;
302 proto_tree_add_text(csnp_tree
, tvb
, offset
, id_length
+ 2, "Start LSP-ID: %s",
303 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+2), id_length
+2 ) );
305 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Start LSP-ID: %s",
306 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+2), id_length
+2 ) );
308 offset
+= id_length
+ 2;
310 proto_tree_add_text(csnp_tree
, tvb
, offset
, id_length
+ 2, "End LSP-ID: %s",
311 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+2), id_length
+2 ) );
313 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", End LSP-ID: %s",
314 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+2), id_length
+2 ) );
316 offset
+= id_length
+ 2;
318 len
= pdu_length
- header_length
;
322 /* Call into payload dissector */
323 if (type
== ISIS_TYPE_L1_CSNP
) {
324 isis_dissect_clvs(tvb
, csnp_tree
, offset
,
325 clv_l1_csnp_opts
, len
, id_length
,
326 ett_isis_csnp_clv_unknown
);
328 isis_dissect_clvs(tvb
, csnp_tree
, offset
,
329 clv_l2_csnp_opts
, len
, id_length
,
330 ett_isis_csnp_clv_unknown
);
335 * Name: isis_dissect_isis_psnp()
338 * Tear apart a L1 or L2 PSNP header and then call into payload dissect
339 * to pull apart the lsp id payload.
342 * tvbuff_t * : tvbuffer for packet data
343 * proto_tree * : protocol display tree to add to. May be NULL.
344 * int : our offset into packet data
345 * int : type (l1 psnp, l2 psnp)
346 * int : header length of packet.
347 * int : length of IDs in packet.
350 * void, but we will add to proto tree if !NULL.
353 isis_dissect_isis_psnp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
,
354 int type
, int header_length
, int id_length
)
357 proto_tree
*psnp_tree
= NULL
;
362 ti
= proto_tree_add_text(tree
, tvb
, offset
, -1,
364 psnp_tree
= proto_item_add_subtree(ti
, ett_isis_psnp
);
367 pdu_length
= tvb_get_ntohs(tvb
, offset
);
369 proto_tree_add_uint(psnp_tree
, hf_isis_psnp_pdu_length
, tvb
,
370 offset
, 2, pdu_length
);
374 proto_tree_add_text(psnp_tree
, tvb
, offset
, id_length
+ 1, "Source-ID: %s",
375 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+1), id_length
+ 1 ) );
377 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Source-ID: %s",
378 print_system_id( tvb_get_ptr(tvb
, offset
, id_length
+1), id_length
+1 ) );
380 offset
+= id_length
+ 1;
382 len
= pdu_length
- header_length
;
384 isis_dissect_unknown(tvb
, tree
, offset
,
385 "packet header length %d went beyond packet",
389 /* Call into payload dissector */
390 if (type
== ISIS_TYPE_L1_PSNP
) {
391 isis_dissect_clvs(tvb
, psnp_tree
, offset
,
392 clv_l1_psnp_opts
, len
, id_length
,
393 ett_isis_psnp_clv_unknown
);
395 isis_dissect_clvs(tvb
, psnp_tree
, offset
,
396 clv_l2_psnp_opts
, len
, id_length
,
397 ett_isis_psnp_clv_unknown
);
402 * Name: dissect_snp_authentication_clv()
405 * Decode for a snp packets authenticaion clv.
406 * Calls into the CLV common one.
409 * tvbuff_t * : tvbuffer for packet data
410 * proto_tree * : proto tree to build on (may be null)
411 * int : current offset into packet data
412 * int : length of IDs in packet.
413 * int : length of this clv
416 * void, will modify proto_tree if not null.
419 dissect_snp_authentication_clv(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
,
420 int id_length _U_
, int length
)
422 isis_dissect_authentication_clv(tvb
, tree
, offset
, length
);
426 * Name: dissect_snp_ip_authentication_clv()
429 * Decode for a snp packets authenticaion clv.
430 * Calls into the CLV common one.
433 * tvbuff_t * : tvbuffer for packet data
434 * proto_tree * : proto tree to build on (may be null)
435 * int : current offset into packet data
436 * int : length of IDs in packet.
437 * int : length of this clv
440 * void, will modify proto_tree if not null.
443 dissect_snp_ip_authentication_clv(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
,
444 int id_length _U_
, int length
)
446 isis_dissect_ip_authentication_clv(tvb
, tree
, offset
, length
);
450 * Name: dissect_snp_checksum_clv()
453 * dump and verify the optional checksum in TLV 12
456 * tvbuff_t * : tvbuffer for packet data
457 * proto_tree * : protocol display tree to fill out. May be NULL
458 * int : offset into packet data where we are.
459 * int : length of clv we are decoding
462 * void, but we will add to proto tree if !NULL.
466 dissect_snp_checksum_clv(tvbuff_t
*tvb
,
467 proto_tree
*tree
, int offset
, int id_length _U_
, int length
) {
469 guint16 pdu_length
,checksum
, cacl_checksum
=0;
473 proto_tree_add_text ( tree
, tvb
, offset
, length
,
474 "incorrect checksum length (%u), should be (2)", length
);
478 checksum
= tvb_get_ntohs(tvb
, offset
);
480 /* the check_and_get_checksum() function needs to know how big
481 * the packet is. we can either pass through the pdu-len through several layers
482 * of dissectors and wrappers or extract the PDU length field from the PDU specific header
483 * which is offseted 8 bytes (relative to the beginning of the IS-IS packet) in SNPs */
485 pdu_length
= tvb_get_ntohs(tvb
, 8);
487 /* unlike the LSP checksum verification which starts at an offset of 12 we start at offset 0*/
488 switch (check_and_get_checksum(tvb
, 0, pdu_length
, checksum
, offset
, &cacl_checksum
))
492 proto_tree_add_text ( tree
, tvb
, offset
, length
,
493 "Checksum: 0x%04x [unused]", checksum
);
496 isis_dissect_unknown(tvb
, tree
, offset
,
497 "[packet length %d went beyond packet]",
501 proto_tree_add_text ( tree
, tvb
, offset
, length
,
502 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
507 proto_tree_add_text ( tree
, tvb
, offset
, length
,
508 "Checksum: 0x%04x [correct]", checksum
);
511 g_message("'check_and_get_checksum' returned an invalid value");
517 * Name: isis_register_csnp()
520 * Register our protocol sub-sets with protocol manager.
523 * int : protocol index for the ISIS protocol
529 isis_register_csnp(int proto_isis
) {
530 static hf_register_info hf
[] = {
531 { &hf_isis_csnp_pdu_length
,
532 { "PDU length", "isis.csnp.pdu_length", FT_UINT16
,
533 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
535 static gint
*ett
[] = {
537 &ett_isis_csnp_clv_lsp_entries
,
538 &ett_isis_csnp_lsp_entry
,
539 &ett_isis_csnp_clv_authentication
,
540 &ett_isis_csnp_clv_ip_authentication
,
541 &ett_isis_csnp_clv_checksum
,
542 &ett_isis_csnp_clv_unknown
,
545 proto_register_field_array(proto_isis
, hf
, array_length(hf
));
546 proto_register_subtree_array(ett
, array_length(ett
));
551 * Name: isis_register_psnp()
554 * Register our protocol sub-sets with protocol manager.
557 * int : protocol index for the ISIS protocol
563 isis_register_psnp(int proto_isis
) {
564 static hf_register_info hf
[] = {
565 { &hf_isis_psnp_pdu_length
,
566 { "PDU length", "isis.psnp.pdu_length", FT_UINT16
,
567 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
569 static gint
*ett
[] = {
571 &ett_isis_psnp_clv_lsp_entries
,
572 &ett_isis_psnp_lsp_entry
,
573 &ett_isis_psnp_clv_authentication
,
574 &ett_isis_psnp_clv_ip_authentication
,
575 &ett_isis_psnp_clv_checksum
,
576 &ett_isis_psnp_clv_unknown
,
579 proto_register_field_array(proto_isis
, hf
, array_length(hf
));
580 proto_register_subtree_array(ett
, array_length(ett
));