FIXUP: WIP: verification_trailer
[wireshark-wip.git] / epan / dissectors / packet-isis-snp.c
bloba5e073b08b7bfc463d8ce1ce0764230e47378e2d
1 /* packet-isis-snp.c
2 * Routines for decoding isis complete & partial SNP and their payload
4 * $Id$
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.
26 #include "config.h"
28 #include <glib.h>
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"
36 /* csnp packets */
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;
46 /* psnp packets */
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[] = {
67 ISIS_CLV_LSP_ENTRIES,
68 "LSP entries",
69 &ett_isis_csnp_clv_lsp_entries,
70 dissect_snp_lsp_entries_clv
73 ISIS_CLV_AUTHENTICATION,
74 "Authentication",
75 &ett_isis_csnp_clv_authentication,
76 dissect_snp_authentication_clv
79 ISIS_CLV_IP_AUTHENTICATION,
80 "IP Authentication",
81 &ett_isis_csnp_clv_ip_authentication,
82 dissect_snp_ip_authentication_clv
85 ISIS_CLV_CHECKSUM,
86 "Checksum",
87 &ett_isis_csnp_clv_checksum,
88 dissect_snp_checksum_clv
91 0, "", NULL, NULL
95 static const isis_clv_handle_t clv_l2_csnp_opts[] = {
97 ISIS_CLV_LSP_ENTRIES,
98 "LSP entries",
99 &ett_isis_csnp_clv_lsp_entries,
100 dissect_snp_lsp_entries_clv
103 ISIS_CLV_AUTHENTICATION,
104 "Authentication",
105 &ett_isis_csnp_clv_authentication,
106 dissect_snp_authentication_clv
109 ISIS_CLV_IP_AUTHENTICATION,
110 "IP Authentication",
111 &ett_isis_csnp_clv_ip_authentication,
112 dissect_snp_ip_authentication_clv
115 ISIS_CLV_CHECKSUM,
116 "Checksum",
117 &ett_isis_csnp_clv_checksum,
118 dissect_snp_checksum_clv
121 0, "", NULL, NULL
125 static const isis_clv_handle_t clv_l1_psnp_opts[] = {
127 ISIS_CLV_LSP_ENTRIES,
128 "LSP entries",
129 &ett_isis_psnp_clv_lsp_entries,
130 dissect_snp_lsp_entries_clv
133 ISIS_CLV_AUTHENTICATION,
134 "Authentication",
135 &ett_isis_psnp_clv_authentication,
136 dissect_snp_authentication_clv
139 ISIS_CLV_IP_AUTHENTICATION,
140 "IP Authentication",
141 &ett_isis_psnp_clv_ip_authentication,
142 dissect_snp_ip_authentication_clv
145 ISIS_CLV_CHECKSUM,
146 "Checksum",
147 &ett_isis_psnp_clv_checksum,
148 dissect_snp_checksum_clv
151 0, "", NULL, NULL
155 static const isis_clv_handle_t clv_l2_psnp_opts[] = {
157 ISIS_CLV_LSP_ENTRIES,
158 "LSP entries",
159 &ett_isis_psnp_clv_lsp_entries,
160 dissect_snp_lsp_entries_clv
163 ISIS_CLV_AUTHENTICATION,
164 "Authentication",
165 &ett_isis_psnp_clv_authentication,
166 dissect_snp_authentication_clv
169 ISIS_CLV_IP_AUTHENTICATION,
170 "IP Authentication",
171 &ett_isis_psnp_clv_ip_authentication,
172 dissect_snp_ip_authentication_clv
175 ISIS_CLV_CHECKSUM,
176 "Checksum",
177 &ett_isis_psnp_clv_checksum,
178 dissect_snp_checksum_clv
181 0, "", NULL, NULL
186 * Name: dissect_snp_lsp_entries_clv()
188 * Description:
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
192 * id_length : lsp id
193 * 4 : sequence number
194 * 2 : checksum
196 * Input:
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.
203 * Output:
204 * void, but we will add to proto tree if !NULL.
206 static void
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,
216 2+id_length+2+4+2 );
217 return;
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,
230 "LSP-ID: : %s",
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()
255 * Description:
256 * Tear apart a L1 or L2 CSNP header and then call into payload dissect
257 * to pull apart the lsp id payload.
259 * Input:
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.
267 * Output:
268 * void, but we will add to proto tree if !NULL.
270 void
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)
274 proto_item *ti;
275 proto_tree *csnp_tree = NULL;
276 guint16 pdu_length;
277 int len;
279 if (tree) {
280 ti = proto_tree_add_text(tree, tvb, offset, -1,
281 PROTO_STRING_CSNP);
282 csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
285 pdu_length = tvb_get_ntohs(tvb, offset);
286 if (tree) {
287 proto_tree_add_uint(csnp_tree, hf_isis_csnp_pdu_length, tvb,
288 offset, 2, pdu_length);
290 offset += 2;
292 if (tree) {
293 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 1,
294 "Source-ID: %s",
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;
319 if (len < 0) {
320 return;
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 );
327 } else {
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()
337 * Description:
338 * Tear apart a L1 or L2 PSNP header and then call into payload dissect
339 * to pull apart the lsp id payload.
341 * Input:
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.
349 * Output:
350 * void, but we will add to proto tree if !NULL.
352 void
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)
356 proto_item *ti;
357 proto_tree *psnp_tree = NULL;
358 guint16 pdu_length;
359 int len;
361 if (tree) {
362 ti = proto_tree_add_text(tree, tvb, offset, -1,
363 PROTO_STRING_PSNP);
364 psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
367 pdu_length = tvb_get_ntohs(tvb, offset);
368 if (tree) {
369 proto_tree_add_uint(psnp_tree, hf_isis_psnp_pdu_length, tvb,
370 offset, 2, pdu_length);
372 offset += 2;
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;
383 if (len < 0) {
384 isis_dissect_unknown(tvb, tree, offset,
385 "packet header length %d went beyond packet",
386 header_length );
387 return;
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 );
394 } else {
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()
404 * Description:
405 * Decode for a snp packets authenticaion clv.
406 * Calls into the CLV common one.
408 * Input:
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
415 * Output:
416 * void, will modify proto_tree if not null.
418 static void
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()
428 * Description:
429 * Decode for a snp packets authenticaion clv.
430 * Calls into the CLV common one.
432 * Input:
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
439 * Output:
440 * void, will modify proto_tree if not null.
442 static void
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()
452 * Description:
453 * dump and verify the optional checksum in TLV 12
455 * Input:
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
461 * Output:
462 * void, but we will add to proto tree if !NULL.
465 static void
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;
471 if (tree) {
472 if ( length != 2 ) {
473 proto_tree_add_text ( tree, tvb, offset, length,
474 "incorrect checksum length (%u), should be (2)", length );
475 return;
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))
491 case NO_CKSUM :
492 proto_tree_add_text ( tree, tvb, offset, length,
493 "Checksum: 0x%04x [unused]", checksum);
494 break;
495 case DATA_MISSING :
496 isis_dissect_unknown(tvb, tree, offset,
497 "[packet length %d went beyond packet]",
498 tvb_length(tvb));
499 break;
500 case CKSUM_NOT_OK :
501 proto_tree_add_text ( tree, tvb, offset, length,
502 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
503 checksum,
504 cacl_checksum);
505 break;
506 case CKSUM_OK :
507 proto_tree_add_text ( tree, tvb, offset, length,
508 "Checksum: 0x%04x [correct]", checksum);
509 break;
510 default :
511 g_message("'check_and_get_checksum' returned an invalid value");
517 * Name: isis_register_csnp()
519 * Description:
520 * Register our protocol sub-sets with protocol manager.
522 * Input:
523 * int : protocol index for the ISIS protocol
525 * Output:
526 * void
528 void
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[] = {
536 &ett_isis_csnp,
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()
553 * Description:
554 * Register our protocol sub-sets with protocol manager.
556 * Input:
557 * int : protocol index for the ISIS protocol
559 * Output:
560 * void
562 void
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[] = {
570 &ett_isis_psnp,
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));