* Prefer col_append_str instead of col_append_fstr for constant strings
[metze/wireshark/wip.git] / epan / dissectors / packet-isis-lsp.c
1 /* packet-isis-lsp.c
2  * Routines for decoding isis lsp packets and their CLVs
3  *
4  * $Id$
5  * Stuart Stanley <stuarts@mxmail.net>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <glib.h>
33
34 #include <epan/ipv4.h>
35 #include <epan/packet.h>
36 #include "packet-osi.h"
37 #include "packet-ipv6.h"
38 #include "packet-isis.h"
39 #include "packet-isis-clv.h"
40 #include "packet-isis-lsp.h"
41 #include <epan/addr_resolv.h>
42 #include <epan/addr_and_mask.h>
43 #include <epan/expert.h>
44
45 /* lsp packets */
46 static int hf_isis_lsp_pdu_length = -1;
47 static int hf_isis_lsp_remaining_life = -1;
48 static int hf_isis_lsp_sequence_number = -1;
49 static int hf_isis_lsp_lsp_id = -1;
50 static int hf_isis_lsp_hostname = -1;
51 static int hf_isis_lsp_checksum = -1;
52 static int hf_isis_lsp_checksum_bad = -1;
53 static int hf_isis_lsp_checksum_good = -1;
54 static int hf_isis_lsp_clv_ipv4_int_addr = -1;
55 static int hf_isis_lsp_clv_ipv6_int_addr = -1;
56 static int hf_isis_lsp_clv_te_router_id = -1;
57 static int hf_isis_lsp_clv_mt = -1;
58 static int hf_isis_lsp_p = -1;
59 static int hf_isis_lsp_att = -1;
60 static int hf_isis_lsp_hippity = -1;
61 static int hf_isis_lsp_is_type = -1;
62
63 static gint ett_isis_lsp = -1;
64 static gint ett_isis_lsp_info = -1;
65 static gint ett_isis_lsp_att = -1;
66 static gint ett_isis_lsp_cksum = -1;
67 static gint ett_isis_lsp_clv_area_addr = -1;
68 static gint ett_isis_lsp_clv_is_neighbors = -1;
69 static gint ett_isis_lsp_clv_ext_is_reachability = -1; /* CLV 22 */
70 static gint ett_isis_lsp_part_of_clv_ext_is_reachability = -1;
71 static gint ett_isis_lsp_subclv_admin_group = -1;
72 static gint ett_isis_lsp_subclv_unrsv_bw = -1;
73 static gint ett_isis_lsp_clv_unknown = -1;
74 static gint ett_isis_lsp_clv_partition_dis = -1;
75 static gint ett_isis_lsp_clv_prefix_neighbors = -1;
76 static gint ett_isis_lsp_clv_nlpid = -1;
77 static gint ett_isis_lsp_clv_hostname = -1;
78 static gint ett_isis_lsp_clv_te_router_id = -1;
79 static gint ett_isis_lsp_clv_authentication = -1;
80 static gint ett_isis_lsp_clv_ip_authentication = -1;
81 static gint ett_isis_lsp_clv_ipv4_int_addr = -1;
82 static gint ett_isis_lsp_clv_ipv6_int_addr = -1; /* CLV 232 */
83 static gint ett_isis_lsp_clv_ip_reachability = -1;
84 static gint ett_isis_lsp_clv_ip_reach_subclv = -1;
85 static gint ett_isis_lsp_clv_ext_ip_reachability = -1; /* CLV 135 */
86 static gint ett_isis_lsp_part_of_clv_ext_ip_reachability = -1;
87 static gint ett_isis_lsp_clv_ipv6_reachability = -1; /* CLV 236 */
88 static gint ett_isis_lsp_part_of_clv_ipv6_reachability = -1;
89 static gint ett_isis_lsp_clv_mt = -1;
90 static gint ett_isis_lsp_clv_mt_is = -1;
91 static gint ett_isis_lsp_part_of_clv_mt_is = -1;
92 static gint ett_isis_lsp_clv_mt_reachable_IPv4_prefx = -1;  /* CLV 235 */
93 static gint ett_isis_lsp_clv_mt_reachable_IPv6_prefx = -1;  /* CLV 237 */
94
95 static const value_string isis_lsp_istype_vals[] = {
96         { ISIS_LSP_TYPE_UNUSED0,        "Unused 0x0 (invalid)"},
97         { ISIS_LSP_TYPE_LEVEL_1,        "Level 1"},
98         { ISIS_LSP_TYPE_UNUSED2,        "Unused 0x2 (invalid)"},
99         { ISIS_LSP_TYPE_LEVEL_2,        "Level 2"},
100         { 0, NULL } };
101
102
103 /*
104  * Predclare dissectors for use in clv dissection.
105  */
106 static void dissect_lsp_prefix_neighbors_clv(tvbuff_t *tvb,
107         proto_tree *tree, int offset, int id_length, int length);
108 static void dissect_lsp_partition_dis_clv(tvbuff_t *tvb,
109         proto_tree *tree, int offset, int id_length, int length);
110 static void dissect_lsp_mt_is_reachability_clv(tvbuff_t *tvb,
111         proto_tree *tree, int offset, int id_length, int length);
112 static void dissect_lsp_ext_is_reachability_clv(tvbuff_t *tvb,
113         proto_tree *tree, int offset, int id_length, int length);
114 static void dissect_lsp_l2_is_neighbors_clv(tvbuff_t *tvb,
115         proto_tree *tree, int offset, int id_length, int length);
116 static void dissect_lsp_l1_es_neighbors_clv(tvbuff_t *tvb,
117         proto_tree *tree, int offset, int id_length, int length);
118 static void dissect_lsp_l1_is_neighbors_clv(tvbuff_t *tvb,
119         proto_tree *tree, int offset, int id_length, int length);
120 static void dissect_lsp_area_address_clv(tvbuff_t *tvb,
121         proto_tree *tree, int offset, int id_length, int length);
122 static void dissect_lsp_authentication_clv(tvbuff_t *tvb,
123         proto_tree *tree, int offset, int id_length, int length);
124 static void dissect_lsp_ip_authentication_clv(tvbuff_t *tvb,
125         proto_tree *tree, int offset, int id_length, int length);
126 static void dissect_lsp_ipv6_int_addr_clv(tvbuff_t *tvb,
127         proto_tree *tree, int offset, int id_length, int length);
128 static void dissect_lsp_ip_int_addr_clv(tvbuff_t *tvb,
129         proto_tree *tree, int offset, int id_length, int length);
130 static void dissect_lsp_te_router_id_clv(tvbuff_t *tvb,
131         proto_tree *tree, int offset, int id_length, int length);
132 static void dissect_lsp_hostname_clv(tvbuff_t *tvb,
133         proto_tree *tree, int offset, int id_length, int length);
134 static void dissect_lsp_mt_clv(tvbuff_t *tvb,
135         proto_tree *tree, int offset, int id_length, int length);
136 static void dissect_lsp_nlpid_clv(tvbuff_t *tvb,
137         proto_tree *tree, int offset, int id_length, int length);
138 static void dissect_lsp_ipv6_reachability_clv(tvbuff_t *tvb,
139         proto_tree *tree, int offset, int id_length, int length);
140 static void dissect_lsp_ext_ip_reachability_clv(tvbuff_t *tvb,
141         proto_tree *tree, int offset, int id_length, int length);
142 static void dissect_lsp_ip_reachability_clv(tvbuff_t *tvb,
143         proto_tree *tree, int offset, int id_length, int length);
144 static void dissect_ipreach_subclv(tvbuff_t *tvb,
145         proto_tree *tree, int offset, int clv_code, int clv_len);
146 static void dissect_lsp_mt_reachable_IPv4_prefx_clv(tvbuff_t *tvb,
147         proto_tree *tree, int offset, int id_length, int length);
148 static void dissect_lsp_mt_reachable_IPv6_prefx_clv(tvbuff_t *tvb,
149         proto_tree *tree, int offset, int id_length, int length);
150
151
152 static const isis_clv_handle_t clv_l1_lsp_opts[] = {
153         {
154                 ISIS_CLV_AREA_ADDRESS,
155                 "Area address(es)",
156                 &ett_isis_lsp_clv_area_addr,
157                 dissect_lsp_area_address_clv
158         },
159         {
160                 ISIS_CLV_IS_REACH,
161                 "IS Reachability",
162                 &ett_isis_lsp_clv_is_neighbors,
163                 dissect_lsp_l1_is_neighbors_clv
164         },
165         {
166                 ISIS_CLV_ES_NEIGHBORS,
167                 "ES Neighbor(s)",
168                 &ett_isis_lsp_clv_is_neighbors,
169                 dissect_lsp_l1_es_neighbors_clv
170         },
171         {
172                 ISIS_CLV_EXTD_IS_REACH,
173                 "Extended IS reachability",
174                 &ett_isis_lsp_clv_ext_is_reachability,
175                 dissect_lsp_ext_is_reachability_clv
176         },
177         {
178                 ISIS_CLV_INT_IP_REACH,
179                 "IP Internal reachability",
180                 &ett_isis_lsp_clv_ip_reachability,
181                 dissect_lsp_ip_reachability_clv
182         },
183         {
184                 ISIS_CLV_EXT_IP_REACH,
185                 "IP External reachability",
186                 &ett_isis_lsp_clv_ip_reachability,
187                 dissect_lsp_ip_reachability_clv
188         },
189         {
190                 ISIS_CLV_EXTD_IP_REACH,
191                 "Extended IP Reachability",
192                 &ett_isis_lsp_clv_ext_ip_reachability,
193                 dissect_lsp_ext_ip_reachability_clv
194         },
195         {
196                 ISIS_CLV_IP6_REACH,
197                 "IPv6 reachability",
198                 &ett_isis_lsp_clv_ipv6_reachability,
199                 dissect_lsp_ipv6_reachability_clv
200         },
201         {
202                 ISIS_CLV_PROTOCOLS_SUPPORTED,
203                 "Protocols supported",
204                 &ett_isis_lsp_clv_nlpid,
205                 dissect_lsp_nlpid_clv
206         },
207         {
208                 ISIS_CLV_HOSTNAME,
209                 "Hostname",
210                 &ett_isis_lsp_clv_hostname,
211                 dissect_lsp_hostname_clv
212         },
213         {
214                 ISIS_CLV_TE_ROUTER_ID,
215                 "Traffic Engineering Router ID",
216                 &ett_isis_lsp_clv_te_router_id,
217                 dissect_lsp_te_router_id_clv
218         },
219         {
220                 ISIS_CLV_IP_ADDR,
221                 "IP Interface address(es)",
222                 &ett_isis_lsp_clv_ipv4_int_addr,
223                 dissect_lsp_ip_int_addr_clv
224         },
225         {
226                 ISIS_CLV_IP6_ADDR,
227                 "IPv6 Interface address(es)",
228                 &ett_isis_lsp_clv_ipv6_int_addr,
229                 dissect_lsp_ipv6_int_addr_clv
230         },
231         {
232                 ISIS_CLV_AUTHENTICATION,
233                 "Authentication",
234                 &ett_isis_lsp_clv_authentication,
235                 dissect_lsp_authentication_clv
236         },
237         {
238                 ISIS_CLV_IP_AUTHENTICATION,
239                 "IP Authentication",
240                 &ett_isis_lsp_clv_ip_authentication,
241                 dissect_lsp_ip_authentication_clv
242         },
243         {
244                 ISIS_CLV_MT_SUPPORTED,
245                 "Multi Topology supported",
246                 &ett_isis_lsp_clv_mt,
247                 dissect_lsp_mt_clv
248         },
249         {
250                 ISIS_CLV_MT_IS_REACH,
251                 "Multi Topology IS Reachability",
252                 &ett_isis_lsp_clv_mt_is,
253                 dissect_lsp_mt_is_reachability_clv
254         },
255         {
256                 ISIS_CLV_MT_IP_REACH,
257                 "Multi Topology Reachable IPv4 Prefixes",
258                 &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
259                 dissect_lsp_mt_reachable_IPv4_prefx_clv
260         },
261         {
262                 ISIS_CLV_MT_IP6_REACH,
263                 "Multi Topology Reachable IPv6 Prefixes",
264                 &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
265                 dissect_lsp_mt_reachable_IPv6_prefx_clv
266         },
267         {
268                 0,
269                 "",
270                 NULL,
271                 NULL
272         }
273 };
274
275 static const isis_clv_handle_t clv_l2_lsp_opts[] = {
276         {
277                 ISIS_CLV_AREA_ADDRESS,
278                 "Area address(es)",
279                 &ett_isis_lsp_clv_area_addr,
280                 dissect_lsp_area_address_clv
281         },
282         {
283                 ISIS_CLV_IS_REACH,
284                 "IS Reachability",
285                 &ett_isis_lsp_clv_is_neighbors,
286                 dissect_lsp_l2_is_neighbors_clv
287         },
288         {
289                 ISIS_CLV_EXTD_IS_REACH,
290                 "Extended IS reachability",
291                 &ett_isis_lsp_clv_ext_is_reachability,
292                 dissect_lsp_ext_is_reachability_clv
293         },
294         {
295                 ISIS_CLV_PARTITION_DIS,
296                 "Partition Designated Level 2 IS",
297                 &ett_isis_lsp_clv_partition_dis,
298                 dissect_lsp_partition_dis_clv
299         },
300         {
301                 ISIS_CLV_PREFIX_NEIGHBORS,
302                 "Prefix neighbors",
303                 &ett_isis_lsp_clv_prefix_neighbors,
304                 dissect_lsp_prefix_neighbors_clv
305         },
306         {
307                 ISIS_CLV_INT_IP_REACH,
308                 "IP Internal reachability",
309                 &ett_isis_lsp_clv_ip_reachability,
310                 dissect_lsp_ip_reachability_clv
311         },
312         {
313                 ISIS_CLV_EXT_IP_REACH,
314                 "IP External reachability",
315                 &ett_isis_lsp_clv_ip_reachability,
316                 dissect_lsp_ip_reachability_clv
317         },
318         {
319                 ISIS_CLV_PROTOCOLS_SUPPORTED,
320                 "Protocols supported",
321                 &ett_isis_lsp_clv_nlpid,
322                 dissect_lsp_nlpid_clv
323         },
324         {
325                 ISIS_CLV_HOSTNAME,
326                 "Hostname",
327                 &ett_isis_lsp_clv_hostname,
328                 dissect_lsp_hostname_clv
329         },
330         {
331                 ISIS_CLV_TE_ROUTER_ID,
332                 "Traffic Engineering Router ID",
333                 &ett_isis_lsp_clv_te_router_id,
334                 dissect_lsp_te_router_id_clv
335         },
336         {
337                 ISIS_CLV_EXTD_IP_REACH,
338                 "Extended IP Reachability",
339                 &ett_isis_lsp_clv_ext_ip_reachability,
340                 dissect_lsp_ext_ip_reachability_clv
341         },
342         {
343                 ISIS_CLV_IP6_REACH,
344                 "IPv6 reachability",
345                 &ett_isis_lsp_clv_ipv6_reachability,
346                 dissect_lsp_ipv6_reachability_clv
347         },
348         {
349                 ISIS_CLV_IP_ADDR,
350                 "IP Interface address(es)",
351                 &ett_isis_lsp_clv_ipv4_int_addr,
352                 dissect_lsp_ip_int_addr_clv
353         },
354         {
355                 ISIS_CLV_IP6_ADDR,
356                 "IPv6 Interface address(es)",
357                 &ett_isis_lsp_clv_ipv6_int_addr,
358                 dissect_lsp_ipv6_int_addr_clv
359         },
360         {
361                 ISIS_CLV_AUTHENTICATION,
362                 "Authentication",
363                 &ett_isis_lsp_clv_authentication,
364                 dissect_lsp_authentication_clv
365         },
366         {
367                 ISIS_CLV_IP_AUTHENTICATION,
368                 "IP Authentication",
369                 &ett_isis_lsp_clv_ip_authentication,
370                 dissect_lsp_ip_authentication_clv
371         },
372         {
373                 ISIS_CLV_MT_SUPPORTED,
374                 "Multi Topology",
375                 &ett_isis_lsp_clv_mt,
376                 dissect_lsp_mt_clv
377         },
378         {
379                 ISIS_CLV_MT_IS_REACH,
380                 "Multi Topology IS Reachability",
381                 &ett_isis_lsp_clv_mt_is,
382                 dissect_lsp_mt_is_reachability_clv
383         },
384         {
385                 ISIS_CLV_MT_IP_REACH,
386                 "Multi Topology Reachable IPv4 Prefixes",
387                 &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
388                 dissect_lsp_mt_reachable_IPv4_prefx_clv
389         },
390         {
391                 ISIS_CLV_MT_IP6_REACH,
392                 "Multi Topology Reachable IPv6 Prefixes",
393                 &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
394                 dissect_lsp_mt_reachable_IPv6_prefx_clv
395         },
396         {
397                 0,
398                 "",
399                 NULL,
400                 NULL
401         }
402 };
403
404 /*
405  * Name: dissect_lsp_mt_id()
406  *
407  * Description:
408  *      dissect and display the multi-topology ID value
409  *
410  * Input:
411  *      tvbuff_t * : tvbuffer for packet data
412  *      proto_tree * : protocol display tree to fill out.  CAN'T BE NULL
413  *      int : offset into packet data where we are.
414  *
415  * Output:
416  *      void, but we will add to proto tree.
417  */
418 static void
419 dissect_lsp_mt_id(tvbuff_t *tvb, proto_tree *tree, int offset)
420 {
421         int  mt_block, mt_id;
422         const char *mt_desc="";
423
424         /* fetch two bytes */
425         mt_block = tvb_get_ntohs(tvb, offset);
426
427         proto_tree_add_text ( tree, tvb, offset, 1 ,
428                         "4 most significant bits reserved, should be set to 0 (%d)", ISIS_LSP_MT_MSHIP_RES(mt_block));
429
430         mt_id = ISIS_LSP_MT_MSHIP_ID(mt_block);
431         /*mask out the lower 12 bits */
432         switch(mt_id) {
433         case 0:
434                 mt_desc="'standard' topology";
435                 break;
436         case 1:
437                 mt_desc="IPv4 In-Band Management purposes";
438                 break;
439         case 2:
440                 mt_desc="IPv6 routing topology";
441                 break;
442         case 3:
443                 mt_desc="IPv4 multicast routing topology";
444                 break;
445         case 4:
446                 mt_desc="IPv6 multicast routing topology";
447                 break;
448         default:
449                 mt_desc=((mt_block & 0x0fff) < 3996) ? "Reserved for IETF Consensus" : "Development, Experimental and Proprietary features";
450         }
451
452         proto_tree_add_text ( tree, tvb, offset, 2 ,
453                         "%s (%d)", mt_desc, mt_id);
454
455 }
456
457 /*
458  * Name: dissect_metric()
459  *
460  * Description:
461  *      Display a metric prefix portion.  ISIS has the concept of multple
462  *      metric per prefix (default, delay, expense, and error).  This
463  *      routine assists other dissectors by adding a single one of
464  *      these to the display tree..
465  *
466  *      The 8th(msbit) bit in the metric octet is the "supported" bit.  The
467  *              "default" support is required, so we support a "force_supported"
468  *              flag that tells us that it MUST be zero (zero==supported,
469  *              so it really should be a "not supported" in the boolean sense)
470  *              and to display a protocol failure accordingly.  Notably,
471  *              Cisco IOS 12(6) blows this!
472  *      The 7th bit must be zero (reserved).
473  *
474  * Input:
475  *      tvbuff_t * : tvbuffer for packet data
476  *      proto_tree * : protocol display tree to fill out.  May be NULL
477  *      int : offset into packet data where we are.
478  *      guint8 : value of the metric.
479  *      char * : string giving type of the metric.
480  *      int : force supported.  True is the supported bit MUST be zero.
481  *
482  * Output:
483  *      void, but we will add to proto tree if !NULL.
484  */
485 static void
486 dissect_metric(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 value,
487         const char *pstr, int force_supported )
488 {
489         int s;
490
491         if ( !tree ) return;
492
493         s = ISIS_LSP_CLV_METRIC_SUPPORTED(value);
494         proto_tree_add_text(tree, tvb, offset, 1,
495                 "%s Metric: %s%s %s%d:%d", pstr,
496                 s ? "Not supported" : "Supported",
497                 (s && force_supported) ? "(but is required to be)":"",
498                 ISIS_LSP_CLV_METRIC_RESERVED(value) ? "(reserved bit != 0)":"",
499                 ISIS_LSP_CLV_METRIC_VALUE(value), value );
500 }
501
502 /*
503  * Name: dissect_lsp_ip_reachability_clv()
504  *
505  * Description:
506  *      Decode an IP reachability CLV.  This can be either internal or
507  *      external (the clv format does not change and which type we are
508  *      displaying is put there by the dispatcher).  All of these
509  *      are a metric block followed by an IP addr and mask.
510  *
511  * Input:
512  *      tvbuff_t * : tvbuffer for packet data
513  *      proto_tree * : proto tree to build on (may be null)
514  *      int : current offset into packet data
515  *      int : length of IDs in packet.
516  *      int : length of this clv
517  *
518  * Output:
519  *      void, will modify proto_tree if not null.
520  */
521 static void
522 dissect_lsp_ip_reachability_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
523         int id_length _U_, int length)
524 {
525         proto_item      *ti;
526         proto_tree      *ntree = NULL;
527         guint32         src, mask, bitmask;
528         int             prefix_len;
529         gboolean        found_mask = FALSE;
530
531         while ( length > 0 ) {
532                 if (length<12) {
533                         isis_dissect_unknown(tvb, tree, offset,
534                                 "short IP reachability (%d vs 12)", length );
535                         return;
536                 }
537                 /*
538                  * Gotta build a sub-tree for all our pieces
539                  */
540                 if ( tree ) {
541                         src = tvb_get_ipv4(tvb, offset+4);
542                         mask = tvb_get_ntohl(tvb, offset+8);
543
544                         /* find out if the mask matches one of 33 possible prefix lengths */
545                         bitmask = 0xffffffff;
546                         for(prefix_len = 32; prefix_len >= 0; prefix_len--) {
547                           if (bitmask==mask) {
548                             found_mask = TRUE;
549                             break;
550                           }
551                           bitmask = bitmask << 1;
552                         }
553
554                         /* If we have a discontiguous netmask, dump the mask, otherwise print the prefix_len */
555                         /* XXX - We should probably have some sort of netmask_to_str() routine in to_str.c that does this. */
556
557                         if(found_mask) {
558                           ti = proto_tree_add_text ( tree, tvb, offset, 12,
559                                 "IPv4 prefix: %s/%d",
560                                 ip_to_str((guint8*)&src),
561                                 prefix_len );
562                         } else {
563                           ti = proto_tree_add_text ( tree, tvb, offset, 12,
564                                 "IPv4 prefix: %s mask %s",
565                                 ip_to_str((guint8*)&src),
566                                 ip_to_str(tvb_get_ptr(tvb, offset+8, 4)));
567                         };
568
569                         ntree = proto_item_add_subtree(ti,
570                                 ett_isis_lsp_clv_ip_reachability);
571
572                         proto_tree_add_text (ntree, tvb, offset, 1,
573                                 "Default Metric: %d, %s, Distribution: %s",
574                                 ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset)),
575                                 ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset)) ? "External" : "Internal",
576                                 ISIS_LSP_CLV_METRIC_UPDOWN(tvb_get_guint8(tvb, offset)) ? "down" : "up");
577
578
579                         if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+1))) {
580                           proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric:   Not supported");
581                                                } else {
582                           proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric:   %d, %s",
583                                                ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+1)),
584                                                ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+1)) ? "External" : "Internal");
585                                                }
586
587                         if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+2))) {
588                           proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric: Not supported");
589                         } else {
590                           proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric:  %d, %s",
591                                                ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+2)),
592                                                ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+2)) ? "External" : "Internal");
593                         }
594
595                         if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+3))) {
596                           proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric:   Not supported");
597                         } else {
598                           proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric:   %d, %s",
599                                                ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+3)),
600                                                ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+3)) ? "External" : "Internal");
601                         }
602                 }
603                 offset += 12;
604                 length -= 12;
605         }
606 }
607
608 /*
609  * Name: dissect_ipreach_subclv ()
610  *
611  * Description: parses IP reach subTLVs
612  *              Called by various IP Reachability dissectors.
613  *
614  * Input:
615  *   tvbuff_t * : tvbuffer for packet data
616  *   proto_tree * : protocol display tree to fill out.
617  *   int : offset into packet data where we are (beginning of the sub_clv value).
618  *
619  * Output:
620  *   void
621  */
622 static void
623 dissect_ipreach_subclv(tvbuff_t *tvb, proto_tree *tree, int offset, int clv_code, int clv_len)
624 {
625
626         switch (clv_code) {
627         case 1:
628                 while (clv_len >= 4) {
629                         proto_tree_add_text(tree, tvb, offset, 4,
630                                     "32-Bit Administrative tag: 0x%08x (=%u)",
631                                     tvb_get_ntohl(tvb, offset),
632                                     tvb_get_ntohl(tvb, offset));                
633                         offset+=4;
634                         clv_len-=4;
635                 }
636                 break;
637         case 2:
638                 while (clv_len >= 8) {
639                         proto_tree_add_text(tree, tvb, offset, 8,
640                                     "64-Bit Administrative tag: 0x%08x%08x",
641                                     tvb_get_ntohl(tvb, offset),
642                                     tvb_get_ntohl(tvb, offset+4));
643                         offset+=8;
644                         clv_len-=8;
645                 }
646                 break;
647
648         default :
649                 proto_tree_add_text (tree, tvb, offset, clv_len+2,
650                                      "Unknown sub-TLV: code %u, length %u",
651                                      clv_code, clv_len );
652                 break;
653         }
654 }
655
656
657 /*
658  * Name: dissect_lsp_ext_ip_reachability_clv()
659  *
660  * Description: Decode an Extended IP Reachability CLV - code 135.
661  *
662  *   The extended IP reachability TLV is an extended version
663  *   of the IP reachability TLVs (codes 128 and 130). It encodes
664  *   the metric as a 32-bit unsigned interger and allows to add
665  *   sub-CLV(s).
666  *
667  *   CALLED BY TLV 235 DISSECTOR
668  *
669  *
670  * Input:
671  *   tvbuff_t * : tvbuffer for packet data
672  *   proto_tree * : proto tree to build on (may be null)
673  *   int : current offset into packet data
674  *   int : length of IDs in packet.
675  *   int : length of this clv
676  *
677  * Output:
678  *   void, will modify proto_tree if not null.
679  */
680 static void
681 dissect_lsp_ext_ip_reachability_clv(tvbuff_t *tvb, proto_tree *tree,
682         int offset, int id_length _U_, int length)
683 {
684         proto_item *pi = NULL;
685         proto_tree *subtree = NULL;
686         proto_tree *subtree2 = NULL;
687         guint8     ctrl_info;
688         guint      bit_length;
689         int        byte_length;
690         guint8     prefix [4];
691         guint32    metric;
692         guint      len,i;
693         guint      subclvs_len;
694         guint      clv_code, clv_len;
695
696         if (!tree) return;
697
698         while (length > 0) {
699                 ctrl_info = tvb_get_guint8(tvb, offset+4);
700                 bit_length = ctrl_info & 0x3f;
701                 byte_length = ipv4_addr_and_mask(tvb, offset+5, prefix, bit_length);
702                 if (byte_length == -1) {
703                          isis_dissect_unknown(tvb, tree, offset,
704                                 "IPv4 prefix has an invalid length: %d bits", bit_length );
705                         return;
706                 }
707                 metric = tvb_get_ntohl(tvb, offset);
708                 subclvs_len = 0;
709                 if ((ctrl_info & 0x40) != 0)
710                         subclvs_len = 1+tvb_get_guint8(tvb, offset+5+byte_length);
711
712                 pi = proto_tree_add_text (tree, tvb, offset, 5+byte_length+subclvs_len,
713                                           "IPv4 prefix: %s/%d, Metric: %u, Distribution: %s, %ssub-TLVs present",
714                                           ip_to_str (prefix),
715                                           bit_length,
716                                           metric,
717                                           ((ctrl_info & 0x80) == 0) ? "up" : "down",
718                                           ((ctrl_info & 0x40) == 0) ? "no " : "" );
719
720                 /* open up a new tree per prefix */
721                 subtree = proto_item_add_subtree (pi, ett_isis_lsp_part_of_clv_ext_ip_reachability);
722
723                 proto_tree_add_text (subtree, tvb, offset+5, byte_length, "IPv4 prefix: %s/%u",
724                                      ip_to_str (prefix),
725                                      bit_length);
726
727                 proto_tree_add_text (subtree, tvb, offset, 4, "Metric: %u", metric);
728
729                 proto_tree_add_text (subtree, tvb, offset+4, 1, "Distribution: %s",
730                                      ((ctrl_info & 0x80) == 0) ? "up" : "down");
731
732                 len = 5 + byte_length;
733                 if ((ctrl_info & 0x40) != 0) {
734                         subclvs_len = tvb_get_guint8(tvb, offset+len);
735                         pi = proto_tree_add_text (subtree, tvb, offset+len, 1, "sub-TLVs present, total length: %u bytes",
736                                              subclvs_len);
737                         proto_item_set_len (pi, subclvs_len+1);
738                         /* open up a new tree for the subTLVs */
739                         subtree2 = proto_item_add_subtree (pi, ett_isis_lsp_clv_ip_reach_subclv);
740
741                         i =0;
742                         while (i < subclvs_len) {
743                                 clv_code = tvb_get_guint8(tvb, offset+len+1); /* skip the total subtlv len indicator */
744                                 clv_len  = tvb_get_guint8(tvb, offset+len+2);
745                                 
746                                 /*
747                                  * we pass on now the raw data to the ipreach_subtlv dissector
748                                  * therefore we need to skip 3 bytes
749                                  * (total subtlv len, subtlv type, subtlv len)
750                                  */
751                                 dissect_ipreach_subclv(tvb, subtree2, offset+len+3, clv_code, clv_len);
752                                 i += clv_len + 2;
753                         }
754                         len += 1 + subclvs_len;
755                 } else {
756                         proto_tree_add_text (subtree, tvb, offset+4, 1, "no sub-TLVs present");
757                         proto_item_set_len (pi, len);
758                 }
759
760                 offset += len;
761                 length -= len;
762         }
763 }
764
765 /*
766  * Name: dissect_lsp_ipv6_reachability_clv()
767  *
768  * Description: Decode an IPv6 reachability CLV - code 236.
769  *
770  *   CALLED BY TLV 237 DISSECTOR
771  *
772  * Input:
773  *   tvbuff_t * : tvbuffer for packet data
774  *   proto_tree * : proto tree to build on (may be null)
775  *   int : current offset into packet data
776  *   int : length of IDs in packet.
777  *   int : length of this clv
778  *
779  * Output:
780  *   void, will modify proto_tree if not null.
781  */
782 static void
783 dissect_lsp_ipv6_reachability_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
784         int id_length _U_, int length)
785 {
786         proto_item        *pi;
787         proto_tree        *subtree = NULL;
788         proto_tree        *subtree2 = NULL;
789         guint8            ctrl_info;
790         guint             bit_length;
791         int               byte_length;
792         struct e_in6_addr prefix;
793         guint32           metric;
794         guint             len,i;
795         guint             subclvs_len;
796         guint             clv_code, clv_len;
797
798         if (!tree) return;
799
800         while (length > 0) {
801                 ctrl_info = tvb_get_guint8(tvb, offset+4);
802                 bit_length = tvb_get_guint8(tvb, offset+5);
803                 byte_length = ipv6_addr_and_mask(tvb, offset+6, &prefix, bit_length);
804                 if (byte_length == -1) {
805                         isis_dissect_unknown(tvb, tree, offset,
806                                 "IPv6 prefix has an invalid length: %d bits", bit_length );
807                         return;
808                 }
809                 metric = tvb_get_ntohl(tvb, offset);
810                 subclvs_len = 0;
811                 if ((ctrl_info & 0x20) != 0)
812                         subclvs_len = 1+tvb_get_guint8(tvb, offset+6+byte_length);
813
814                 pi = proto_tree_add_text (tree, tvb, offset, 6+byte_length+subclvs_len,
815                                           "IPv6 prefix: %s/%u, Metric: %u, Distribution: %s, %s, %ssub-TLVs present",
816                                           ip6_to_str (&prefix),
817                                           bit_length,
818                                           metric,
819                                           ((ctrl_info & 0x80) == 0) ? "up" : "down",
820                                           ((ctrl_info & 0x40) == 0) ? "internal" : "external",
821                                           ((ctrl_info & 0x20) == 0) ? "no " : "" );
822
823                 subtree = proto_item_add_subtree (pi, ett_isis_lsp_part_of_clv_ipv6_reachability);
824
825                 proto_tree_add_text (subtree, tvb, offset+6, byte_length, "IPv6 prefix: %s/%u",
826                                      ip6_to_str (&prefix),
827                                      bit_length);
828
829                 proto_tree_add_text (subtree, tvb, offset, 4,
830                         "Metric: %u", metric);
831
832                 proto_tree_add_text (subtree, tvb, offset+4, 1,
833                         "Distribution: %s, %s",
834                         ((ctrl_info & 0x80) == 0) ? "up" : "down",
835                         ((ctrl_info & 0x40) == 0) ? "internal" : "external" );
836
837                 if ((ctrl_info & 0x1f) != 0) {
838                         proto_tree_add_text (subtree, tvb, offset+4, 1,
839                                              "Reserved bits: 0x%x",
840                                              (ctrl_info & 0x1f) );
841                 }
842
843                 len = 6 + byte_length;
844                 if ((ctrl_info & 0x20) != 0) {
845                         subclvs_len = tvb_get_guint8(tvb, offset+len);
846                         pi = proto_tree_add_text (subtree, tvb, offset+len, 1, "sub-TLVs present, total length: %u bytes",
847                                              subclvs_len);
848                         proto_item_set_len (pi, subclvs_len+1);
849                         /* open up a new tree for the subTLVs */
850                         subtree2 = proto_item_add_subtree (pi, ett_isis_lsp_clv_ip_reach_subclv);
851
852                         i =0;
853                         while (i < subclvs_len) {
854                                 clv_code = tvb_get_guint8(tvb, offset+len+1); /* skip the total subtlv len indicator */
855                                 clv_len  = tvb_get_guint8(tvb, offset+len+2);
856                                 dissect_ipreach_subclv(tvb, subtree2, offset+len+3, clv_code, clv_len);
857                                 i += clv_len + 2;
858                         }
859                         len += 1 + subclvs_len;
860                 } else {
861                         proto_tree_add_text (subtree, tvb, offset+4, 1, "no sub-TLVs present");
862                         proto_item_set_len (pi, len);
863                 }
864                 offset += len;
865                 length -= len;
866         }
867 }
868
869 /*
870  * Name: dissect_lsp_nlpid_clv()
871  *
872  * Description:
873  *      Decode for a lsp packets NLPID clv.  Calls into the
874  *      clv common one.
875  *
876  * Input:
877  *      tvbuff_t * : tvbuffer for packet data
878  *      proto_tree * : proto tree to build on (may be null)
879  *      int : current offset into packet data
880  *      int : length of IDs in packet.
881  *      int : length of this clv
882  *
883  * Output:
884  *      void, will modify proto_tree if not null.
885  */
886 static void
887 dissect_lsp_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
888         int id_length _U_, int length)
889 {
890         isis_dissect_nlpid_clv(tvb, tree, offset, length);
891 }
892
893 /*
894  * Name: dissect_lsp_mt_clv()
895  *
896  * Description: - code 229
897  *      Decode for a lsp packets Multi Topology clv.  Calls into the
898  *      clv common one.
899  *
900  * Input:
901  *      tvbuff_t * : tvbuffer for packet data
902  *      proto_tree * : proto tree to build on (may be null)
903  *      int : current offset into packet data
904  *      guint : length of this clv
905  *      int : length of IDs in packet.
906  *
907  * Output:
908  *      void, will modify proto_tree if not null.
909  */
910 static void
911 dissect_lsp_mt_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
912         int id_length _U_, int length)
913 {
914         isis_dissect_mt_clv(tvb, tree, offset, length, hf_isis_lsp_clv_mt );
915 }
916
917 /*
918  * Name: dissect_lsp_hostname_clv()
919  *
920  * Description:
921  *      Decode for a lsp packets hostname clv.  Calls into the
922  *      clv common one.
923  *
924  * Input:
925  *      tvbuff_t * : tvbuffer for packet data
926  *      proto_tree * : proto tree to build on (may be null)
927  *      int : current offset into packet data
928  *      int : length of IDs in packet.
929  *      int : length of this clv
930  *
931  * Output:
932  *      void, will modify proto_tree if not null.
933  */
934 static void
935 dissect_lsp_hostname_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
936         int id_length _U_, int length)
937 {
938         isis_dissect_hostname_clv(tvb, tree, offset, length, 
939                 hf_isis_lsp_hostname);
940 }
941
942
943 /*
944  * Name: dissect_lsp_te_router_id_clv()
945  *
946  * Description:
947  *      Decode for a lsp packets Traffic Engineering ID clv.  Calls into the
948  *      clv common one.
949  *
950  * Input:
951  *      tvbuff_t * : tvbuffer for packet data
952  *      proto_tree * : proto tree to build on (may be null)
953  *      int : current offset into packet data
954  *      int : length of IDs in packet.
955  *      int : length of this clv
956  *
957  * Output:
958  *      void, will modify proto_tree if not null.
959  */
960 static void
961 dissect_lsp_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
962         int id_length _U_, int length)
963 {
964         isis_dissect_te_router_id_clv(tvb, tree, offset, length,
965                 hf_isis_lsp_clv_te_router_id );
966 }
967
968
969 /*
970  * Name: dissect_lsp_ip_int_addr_clv()
971  *
972  * Description:
973  *      Decode for a lsp packets ip interface addr clv.  Calls into the
974  *      clv common one.
975  *
976  * Input:
977  *      tvbuff_t * : tvbuffer for packet data
978  *      proto_tree * : proto tree to build on (may be null)
979  *      int : current offset into packet data
980  *      int : length of IDs in packet.
981  *      int : length of this clv
982  *
983  * Output:
984  *      void, will modify proto_tree if not null.
985  */
986 static void
987 dissect_lsp_ip_int_addr_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
988         int id_length _U_, int length)
989 {
990         isis_dissect_ip_int_clv(tvb, tree, offset, length,
991                 hf_isis_lsp_clv_ipv4_int_addr );
992 }
993
994 /*
995  * Name: dissect_lsp_ipv6_int_addr_clv()
996  *
997  * Description: Decode an IPv6 interface addr CLV - code 232.
998  *
999  *   Calls into the clv common one.
1000  *
1001  * Input:
1002  *   tvbuff_t * : tvbuffer for packet data
1003  *   proto_tree * : proto tree to build on (may be null)
1004  *   int : current offset into packet data
1005  *   int : length of IDs in packet.
1006  *   int : length of this clv
1007  *
1008  * Output:
1009  *   void, will modify proto_tree if not null.
1010  */
1011 static void
1012 dissect_lsp_ipv6_int_addr_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1013         int id_length _U_, int length)
1014 {
1015         isis_dissect_ipv6_int_clv(tvb, tree, offset, length,
1016                 hf_isis_lsp_clv_ipv6_int_addr );
1017 }
1018
1019 /*
1020  * Name: dissect_lsp_authentication_clv()
1021  *
1022  * Description:
1023  *      Decode for a lsp packets authenticaion clv.  Calls into the
1024  *      clv common one.
1025  *
1026  * Input:
1027  *      tvbuff_t * : tvbuffer for packet data
1028  *      proto_tree * : proto tree to build on (may be null)
1029  *      int : current offset into packet data
1030  *      int : length of IDs in packet.
1031  *      int : length of this clv
1032  *
1033  * Output:
1034  *      void, will modify proto_tree if not null.
1035  */
1036 static void
1037 dissect_lsp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1038         int id_length _U_, int length)
1039 {
1040         isis_dissect_authentication_clv(tvb, tree, offset, length);
1041 }
1042
1043 /*
1044  * Name: dissect_lsp_ip_authentication_clv()
1045  *
1046  * Description:
1047  *      Decode for a lsp packets authenticaion clv.  Calls into the
1048  *      clv common one.
1049  *
1050  * Input:
1051  *      tvbuff_t * : tvbuffer for packet data
1052  *      proto_tree * : proto tree to build on (may be null)
1053  *      int : current offset into packet data
1054  *      int : length of IDs in packet.
1055  *      int : length of this clv
1056  *
1057  * Output:
1058  *      void, will modify proto_tree if not null.
1059  */
1060 static void
1061 dissect_lsp_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1062         int id_length _U_, int length)
1063 {
1064         isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
1065 }
1066
1067 /*
1068  * Name: dissect_lsp_area_address_clv()
1069  *
1070  * Description:
1071  *      Decode for a lsp packet's area address clv.  Call into clv common
1072  *      one.
1073  *
1074  * Input:
1075  *      tvbuff_t * : tvbuffer for packet data
1076  *      proto_tree * : protocol display tree to fill out.  May be NULL
1077  *      int : offset into packet data where we are.
1078  *      int : length of IDs in packet.
1079  *      int : length of clv we are decoding
1080  *
1081  * Output:
1082  *      void, but we will add to proto tree if !NULL.
1083  */
1084 static void
1085 dissect_lsp_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1086         int id_length _U_, int length)
1087 {
1088         isis_dissect_area_address_clv(tvb, tree, offset, length);
1089 }
1090
1091 /*
1092  * Name: dissect_lsp_eis_neighbors_clv_inner()
1093  *
1094  * Description:
1095  *      Real work horse for showing neighbors.  This means we decode the
1096  *      first octet as either virtual/!virtual (if show_virtual param is
1097  *      set), or as a must == 0 reserved value.
1098  *
1099  *      Once past that, we decode n neighbor elements.  Each neighbor
1100  *      is comprised of a metric block (is dissect_metric) and the
1101  *      addresses.
1102  *
1103  * Input:
1104  *      tvbuff_t * : tvbuffer for packet data
1105  *      proto_tree * : protocol display tree to fill out.  May be NULL
1106  *      int : offset into packet data where we are.
1107  *      int : length of IDs in packet.
1108  *      int : length of clv we are decoding
1109  *      int : set to decode first octet as virtual vs reserved == 0
1110  *      int : set to indicate EIS instead of IS (6 octet per addr instead of 7)
1111  *
1112  * Output:
1113  *      void, but we will add to proto tree if !NULL.
1114  */
1115 static void
1116 dissect_lsp_eis_neighbors_clv_inner(tvbuff_t *tvb, proto_tree *tree,
1117         int offset, int length, int id_length, int show_virtual, int is_eis)
1118 {
1119         proto_item      *ti;
1120         proto_tree      *ntree = NULL;
1121         int             tlen;
1122
1123         if (!is_eis) {
1124                 id_length++;    /* IDs are one octet longer in IS neighbours */
1125                 if ( tree ) {
1126                         if ( show_virtual ) {
1127                                 /* virtual path flag */
1128                                 proto_tree_add_text ( tree, tvb, offset, 1,
1129                                    tvb_get_guint8(tvb, offset) ? "IsVirtual" : "IsNotVirtual" );
1130                         } else {
1131                                 proto_tree_add_text ( tree, tvb, offset, 1,
1132                                         "Reserved value 0x%02x, must == 0",
1133                                         tvb_get_guint8(tvb, offset)  );
1134                         }
1135                 }
1136                 offset++;
1137                 length--;
1138         }
1139         tlen = 4 + id_length;
1140
1141         while ( length > 0 ) {
1142                 if (length<tlen) {
1143                         isis_dissect_unknown(tvb, tree, offset,
1144                                 "short E/IS reachability (%d vs %d)", length,
1145                                 tlen );
1146                         return;
1147                 }
1148                 /*
1149                  * Gotta build a sub-tree for all our pieces
1150                  */
1151                 if ( tree ) {
1152                         if ( is_eis ) {
1153                                 ti = proto_tree_add_text(tree, tvb, offset, tlen,
1154                                         "ES Neighbor: %s",
1155                                 print_system_id( tvb_get_ptr(tvb, offset+4, id_length), id_length ) );
1156                         } else {
1157                                 ti = proto_tree_add_text(tree, tvb, offset, tlen,
1158                                         "IS Neighbor:  %s",
1159                                 print_system_id(tvb_get_ptr(tvb, offset+4, id_length), id_length ) );
1160                         }
1161                         ntree = proto_item_add_subtree(ti,
1162                                 ett_isis_lsp_clv_is_neighbors);
1163
1164
1165
1166                         proto_tree_add_text (ntree, tvb, offset, 1,
1167                                              "Default Metric: %d, %s",
1168                                              ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset)),
1169                                              ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset)) ? "External" : "Internal");
1170
1171                         if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+1))) {
1172                           proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric:   Not supported");
1173                         } else {
1174                           proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric:   %d, %s",
1175                                              ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+1)),
1176                                              ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+1)) ? "External" : "Internal");
1177                         }
1178
1179
1180                         if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+2))) {
1181                           proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric: Not supported");
1182                         } else {
1183                           proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric: %d, %s",
1184                                                ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+2)),
1185                                                ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+2)) ? "External" : "Internal");
1186                         }
1187
1188                         if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+3))) {
1189                           proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric:   Not supported");
1190                         } else {
1191                           proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric:   %d, %s",
1192                                                ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+3)),
1193                                                ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+3)) ? "External" : "Internal");
1194                         }
1195
1196                 }
1197                 offset += tlen;
1198                 length -= tlen;
1199         }
1200 }
1201
1202 /*
1203  * Name: dissect_lsp_l1_is_neighbors_clv()
1204  *
1205  * Description:
1206  *      Dispatch a l1 intermediate system neighbor by calling
1207  *      the inner function with show virtual set to TRUE and is es set to FALSE.
1208  *
1209  * Input:
1210  *      tvbuff_t * : tvbuffer for packet data
1211  *      proto_tree * : protocol display tree to fill out.  May be NULL
1212  *      int : offset into packet data where we are.
1213  *      int : length of IDs in packet.
1214  *      int : length of clv we are decoding
1215  *
1216  * Output:
1217  *      void, but we will add to proto tree if !NULL.
1218  */
1219 static void
1220 dissect_lsp_l1_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1221         int id_length, int length)
1222 {
1223         dissect_lsp_eis_neighbors_clv_inner(tvb, tree, offset,
1224                 length, id_length, TRUE, FALSE);
1225 }
1226
1227 /*
1228  * Name: dissect_lsp_l1_es_neighbors_clv()
1229  *
1230  * Description:
1231  *      Dispatch a l1 end or intermediate system neighbor by calling
1232  *      the inner function with show virtual set to TRUE and es set to TRUE.
1233  *
1234  * Input:
1235  *      tvbuff_t * : tvbuffer for packet data
1236  *      proto_tree * : protocol display tree to fill out.  May be NULL
1237  *      int : offset into packet data where we are.
1238  *      int : length of IDs in packet.
1239  *      int : length of clv we are decoding
1240  *
1241  * Output:
1242  *      void, but we will add to proto tree if !NULL.
1243  */
1244 static void
1245 dissect_lsp_l1_es_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1246         int id_length, int length)
1247 {
1248         dissect_lsp_eis_neighbors_clv_inner(tvb, tree, offset,
1249                 length, id_length, TRUE, TRUE);
1250 }
1251
1252 /*
1253  * Name: dissect_lsp_l2_is_neighbors_clv()
1254  *
1255  * Description:
1256  *      Dispatch a l2 intermediate system neighbor by calling
1257  *      the inner function with show virtual set to FALSE, and is es set
1258  *      to FALSE
1259  *
1260  * Input:
1261  *      tvbuff_t * : tvbuffer for packet data
1262  *      proto_tree * : protocol display tree to fill out.  May be NULL
1263  *      int : offset into packet data where we are.
1264  *      int : length of IDs in packet.
1265  *      int : length of clv we are decoding
1266  *
1267  * Output:
1268  *      void, but we will add to proto tree if !NULL.
1269  */
1270 static void
1271 dissect_lsp_l2_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1272         int id_length, int length)
1273 {
1274         dissect_lsp_eis_neighbors_clv_inner(tvb, tree, offset,
1275                 length, id_length, FALSE, FALSE);
1276 }
1277
1278
1279 /*
1280  * Name: dissect_subclv_admin_group ()
1281  *
1282  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1283  *
1284  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1285  *   for dissect the administrive group sub-CLV (code 3).
1286  *
1287  * Input:
1288  *   tvbuff_t * : tvbuffer for packet data
1289  *   proto_tree * : protocol display tree to fill out.
1290  *   int : offset into packet data where we are (beginning of the sub_clv value).
1291  *
1292  * Output:
1293  *   void
1294  */
1295 static void
1296 dissect_subclv_admin_group (tvbuff_t *tvb, proto_tree *tree, int offset) {
1297         proto_item *ti;
1298         proto_tree *ntree;
1299         guint32    clv_value;
1300         guint32    mask;
1301         int        i;
1302
1303         ti = proto_tree_add_text(tree, tvb, offset-2, 6, "Administrative group(s):");
1304         ntree = proto_item_add_subtree (ti, ett_isis_lsp_subclv_admin_group);
1305
1306         clv_value = tvb_get_ntohl(tvb, offset);
1307         mask = 1;
1308         for (i = 0 ; i < 32 ; i++) {
1309                 if ( (clv_value & mask) != 0 ) {
1310                         proto_tree_add_text (ntree, tvb, offset, 4, "group %d", i);
1311                 }
1312                 mask <<= 1;
1313         }
1314 }
1315
1316 /*
1317  * Name: dissect_subclv_max_bw ()
1318  *
1319  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1320  *
1321  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1322  *   for dissect the maximum link bandwidth sub-CLV (code 9).
1323  *
1324  * Input:
1325  *   tvbuff_t * : tvbuffer for packet data
1326  *   proto_tree * : protocol display tree to fill out.
1327  *   int : offset into packet data where we are (beginning of the sub_clv value).
1328  *
1329  * Output:
1330  *   void
1331  */
1332 static void
1333 dissect_subclv_max_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
1334 {
1335         gfloat  bw;
1336
1337         bw = tvb_get_ntohieee_float(tvb, offset);
1338         proto_tree_add_text (tree, tvb, offset-2, 6,
1339                 "Maximum link bandwidth : %.2f Mbps", bw*8/1000000 );
1340 }
1341
1342 /*
1343  * Name: dissect_subclv_rsv_bw ()
1344  *
1345  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1346  *
1347  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1348  *   for dissect the reservable link bandwidth sub-CLV (code 10).
1349  *
1350  * Input:
1351  *   tvbuff_t * : tvbuffer for packet data
1352  *   proto_tree * : protocol display tree to fill out.
1353  *   int : offset into packet data where we are (beginning of the sub_clv value).
1354  *
1355  * Output:
1356  *   void
1357  */
1358 static void
1359 dissect_subclv_rsv_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
1360 {
1361         gfloat  bw;
1362
1363         bw = tvb_get_ntohieee_float(tvb, offset);
1364         proto_tree_add_text (tree, tvb, offset-2, 6,
1365                 "Reservable link bandwidth: %.2f Mbps", bw*8/1000000 );
1366 }
1367
1368 /*
1369  * Name: dissect_subclv_unrsv_bw ()
1370  *
1371  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1372  *
1373  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1374  *   for dissect the unreserved bandwidth sub-CLV (code 11).
1375  *
1376  * Input:
1377  *   tvbuff_t * : tvbuffer for packet data
1378  *   proto_tree * : protocol display tree to fill out.
1379  *   int : offset into packet data where we are (beginning of the sub_clv value).
1380  *
1381  * Output:
1382  *   void
1383  */
1384 static void
1385 dissect_subclv_unrsv_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
1386 {
1387         proto_item *ti;
1388         proto_tree *ntree;
1389         gfloat     bw;
1390         int        i;
1391
1392         ti = proto_tree_add_text (tree, tvb, offset-2, 34, "Unreserved bandwidth:");
1393         ntree = proto_item_add_subtree (ti, ett_isis_lsp_subclv_unrsv_bw);
1394
1395         for (i = 0 ; i < 8 ; i++) {
1396                 bw = tvb_get_ntohieee_float(tvb, offset+4*i);
1397                 proto_tree_add_text (ntree, tvb, offset+4*i, 4,
1398                         "priority level %d: %.2f Mbps", i, bw*8/1000000 );
1399         }
1400 }
1401
1402 /*
1403  * Name: dissect_lsp_ext_is_reachability_clv()
1404  *
1405  * Description: Decode a Extended IS Reachability CLV - code 22
1406  *
1407  *   The extended IS reachability TLV is an extended version
1408  *   of the IS reachability TLV (code 2). It encodes the metric
1409  *   as a 24-bit unsigned interger and allows to add sub-CLV(s).
1410  *
1411  *   CALLED BY TLV 222 DISSECTOR
1412  *
1413  * Input:
1414  *   tvbuff_t * : tvbuffer for packet data
1415  *   proto_tree * : protocol display tree to fill out.  May be NULL
1416  *   int : offset into packet data where we are.
1417  *   int : length of IDs in packet.
1418  *   int : length of clv we are decoding
1419  *
1420  * Output:
1421  *   void, but we will add to proto tree if !NULL.
1422  */
1423 static void
1424 dissect_lsp_ext_is_reachability_clv(tvbuff_t *tvb, proto_tree *tree,
1425         int offset, int id_length _U_, int length)
1426 {
1427         proto_item *ti;
1428         proto_tree *ntree = NULL;
1429         guint      subclvs_len;
1430         guint      len, i;
1431         guint      clv_code, clv_len;
1432
1433         if (!tree) return;
1434
1435         while (length > 0) {
1436                 ti = proto_tree_add_text (tree, tvb, offset, -1,
1437                         "IS neighbor: %s",
1438                         print_system_id (tvb_get_ptr(tvb, offset, 7), 7) );
1439                 ntree = proto_item_add_subtree (ti,
1440                         ett_isis_lsp_part_of_clv_ext_is_reachability );
1441
1442                 proto_tree_add_text (ntree, tvb, offset+7, 3,
1443                         "Metric: %d", tvb_get_ntoh24(tvb, offset+7) );
1444
1445                 subclvs_len = tvb_get_guint8(tvb, offset+10);
1446                 if (subclvs_len == 0) {
1447                         proto_tree_add_text (ntree, tvb, offset+10, 1, "no sub-TLVs present");
1448                 }
1449                 else {
1450                         i = 0;
1451                         while (i < subclvs_len) {
1452                                 clv_code = tvb_get_guint8(tvb, offset+11+i);
1453                                 clv_len  = tvb_get_guint8(tvb, offset+12+i);
1454                                 switch (clv_code) {
1455                                 case 3 :
1456                                         dissect_subclv_admin_group(tvb, ntree, offset+13+i);
1457                                         break;
1458                                 case 6 :
1459                                         proto_tree_add_text (ntree, tvb, offset+11+i, 6,
1460                                                 "IPv4 interface address: %s", ip_to_str (tvb_get_ptr(tvb, offset+13+i, 4)) );
1461                                         break;
1462                                 case 8 :
1463                                         proto_tree_add_text (ntree, tvb, offset+11+i, 6,
1464                                                 "IPv4 neighbor address: %s", ip_to_str (tvb_get_ptr(tvb, offset+13+i, 4)) );
1465                                         break;
1466                                 case 9 :
1467                                         dissect_subclv_max_bw (tvb, ntree, offset+13+i);
1468                                         break;
1469                                 case 10:
1470                                         dissect_subclv_rsv_bw (tvb, ntree, offset+13+i);
1471                                         break;
1472                                 case 11:
1473                                         dissect_subclv_unrsv_bw (tvb, ntree, offset+13+i);
1474                                         break;
1475                                 case 18:
1476                                         proto_tree_add_text (ntree, tvb, offset+11+i, 5,
1477                                                 "Traffic engineering default metric: %d",
1478                                                 tvb_get_ntoh24(tvb, offset+13+i) );
1479                                         break;
1480                                 case 250:
1481                                 case 251:
1482                                 case 252:
1483                                 case 253:
1484                                 case 254:
1485                                         proto_tree_add_text (ntree, tvb, offset+11+i, clv_len+2,
1486                                                 "Unknown Cisco specific extensions: code %d, length %d",
1487                                                 clv_code, clv_len );
1488                                         break;
1489                                 default :
1490                                         proto_tree_add_text (ntree, tvb, offset+11+i, clv_len+2,
1491                                                 "Unknown sub-CLV: code %d, length %d", clv_code, clv_len );
1492                                         break;
1493                                 }
1494                                 i += clv_len + 2;
1495                         }
1496                 }
1497
1498                 len = 11 + subclvs_len;
1499                 proto_item_set_len (ti, len);
1500                 offset += len;
1501                 length -= len;
1502         }
1503 }
1504
1505 /*
1506  * Name: dissect_lsp_mt_reachable_IPv4_prefx_clv()
1507  *
1508  * Description: Decode Multi-Topology IPv4 Prefixes - code 235
1509  *
1510  *
1511  * Input:
1512  *   tvbuff_t * : tvbuffer for packet data
1513  *   proto_tree * : protocol display tree to fill out.  May be NULL
1514  *   int : offset into packet data where we are.
1515  *   int : length of IDs in packet.
1516  *   int : length of clv we are decoding
1517  *
1518  * Output:
1519  *   void, but we will add to proto tree if !NULL.
1520  */
1521 static void
1522 dissect_lsp_mt_reachable_IPv4_prefx_clv(tvbuff_t *tvb,
1523         proto_tree *tree, int offset, int id_length _U_, int length)
1524 {
1525         if (!tree) return;
1526         if (length < 2) {
1527                 isis_dissect_unknown(tvb, tree, offset,
1528                                 "short lsp multi-topology reachable IPv4 prefixes(%d vs %d)", length,
1529                                 2 );
1530                 return;
1531         }
1532         dissect_lsp_mt_id(tvb, tree, offset);
1533         dissect_lsp_ext_ip_reachability_clv(tvb, tree, offset+2, 0, length-2);
1534 }
1535
1536 /*
1537  * Name: dissect_lsp_mt_reachable_IPv6_prefx_clv()
1538  *
1539  * Description: Decode Multi-Topology IPv6 Prefixes - code 237
1540  *
1541  *
1542  * Input:
1543  *   tvbuff_t * : tvbuffer for packet data
1544  *   proto_tree * : protocol display tree to fill out.  May be NULL
1545  *   int : offset into packet data where we are.
1546  *   int : length of IDs in packet.
1547  *   int : length of clv we are decoding
1548  *
1549  * Output:
1550  *   void, but we will add to proto tree if !NULL.
1551  */
1552 static void
1553 dissect_lsp_mt_reachable_IPv6_prefx_clv(tvbuff_t *tvb,
1554         proto_tree *tree, int offset, int id_length _U_, int length)
1555 {
1556         if (!tree) return;
1557         if (length < 2) {
1558                 isis_dissect_unknown(tvb, tree, offset,
1559                                 "short lsp multi-topology reachable IPv6 prefixes(%d vs %d)", length,
1560                                 2 );
1561                 return;
1562         }
1563         dissect_lsp_mt_id(tvb, tree, offset);
1564         dissect_lsp_ipv6_reachability_clv(tvb, tree, offset+2, 0, length-2);
1565 }
1566
1567
1568 /*
1569  * Name: dissect_lsp_mt_is_reachability_clv()
1570  *
1571  * Description: Decode Multi-Topology Intermediate Systems - code 222
1572  *
1573  *
1574  * Input:
1575  *   tvbuff_t * : tvbuffer for packet data
1576  *   proto_tree * : protocol display tree to fill out.  May be NULL
1577  *   int : offset into packet data where we are.
1578  *   int : unused
1579  *   int : length of clv we are decoding
1580  *
1581  * Output:
1582  *   void, but we will add to proto tree if !NULL.
1583  */
1584
1585 static void
1586 dissect_lsp_mt_is_reachability_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1587         int id_length _U_, int length)
1588 {
1589         if (!tree) return;
1590         if (length < 2) {
1591                 isis_dissect_unknown(tvb, tree, offset,
1592                                 "short lsp reachability(%d vs %d)", length,
1593                                 2 );
1594                 return;
1595         }
1596
1597         /*
1598          * the MT ID value dissection is used in other LSPs so we push it
1599          * in a function
1600          */
1601         dissect_lsp_mt_id(tvb, tree, offset);
1602         /*
1603          * fix here. No need to parse TLV 22 (with bugs) while it is
1604          * already done correctly!!
1605          */
1606         dissect_lsp_ext_is_reachability_clv(tvb, tree, offset+2, 0, length-2);
1607 }
1608
1609 /*
1610  * Name: dissect_lsp_partition_dis_clv()
1611  *
1612  * Description:
1613  *      This CLV is used to indicate which system is the designated
1614  *      IS for partition repair.  This means just putting out the
1615  *      "id_length"-octet IS.
1616  *
1617  * Input:
1618  *      tvbuff_t * : tvbuffer for packet data
1619  *      proto_tree * : protocol display tree to fill out.  May be NULL
1620  *      int : offset into packet data where we are.
1621  *      int : length of IDs in packet.
1622  *      int : length of clv we are decoding
1623  *
1624  * Output:
1625  *      void, but we will add to proto tree if !NULL.
1626  */
1627 static void
1628 dissect_lsp_partition_dis_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1629         int id_length, int length)
1630 {
1631         if ( length < id_length ) {
1632                 isis_dissect_unknown(tvb, tree, offset,
1633                                 "short lsp partition DIS(%d vs %d)", length,
1634                                 id_length );
1635                 return;
1636         }
1637         /*
1638          * Gotta build a sub-tree for all our pieces
1639          */
1640         if ( tree ) {
1641                 proto_tree_add_text ( tree, tvb, offset, id_length,
1642                         "Partition designated L2 IS: %s",
1643                         print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
1644         }
1645         length -= id_length;
1646         offset += id_length;
1647         if ( length > 0 ){
1648                 isis_dissect_unknown(tvb, tree, offset,
1649                                 "Long lsp partition DIS, %d left over", length );
1650                 return;
1651         }
1652 }
1653
1654 /*
1655  * Name: dissect_lsp_prefix_neighbors_clv()
1656  *
1657  * Description:
1658  *      The prefix CLV describes what other (OSI) networks we can reach
1659  *      and what their cost is.  It is built from a metric block
1660  *      (see dissect_metric) followed by n addresses.
1661  *
1662  * Input:
1663  *      tvbuff_t * : tvbuffer for packet data
1664  *      proto_tree * : protocol display tree to fill out.  May be NULL
1665  *      int : offset into packet data where we are.
1666  *      int : length of IDs in packet.
1667  *      int : length of clv we are decoding
1668  *
1669  * Output:
1670  *      void, but we will add to proto tree if !NULL.
1671  */
1672 static void
1673 dissect_lsp_prefix_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
1674         int id_length _U_, int length)
1675 {
1676         char *sbuf;
1677         int mylen;
1678
1679         if ( length < 4 ) {
1680                 isis_dissect_unknown(tvb, tree, offset,
1681                         "Short lsp prefix neighbors (%d vs 4)", length );
1682                 return;
1683         }
1684         if ( tree ) {
1685                 dissect_metric (tvb, tree, offset,
1686                         tvb_get_guint8(tvb, offset), "Default", TRUE );
1687                 dissect_metric (tvb, tree, offset+1,
1688                         tvb_get_guint8(tvb, offset+1), "Delay", FALSE );
1689                 dissect_metric (tvb, tree, offset+2,
1690                         tvb_get_guint8(tvb, offset+2), "Expense", FALSE );
1691                 dissect_metric (tvb, tree, offset+3,
1692                         tvb_get_guint8(tvb, offset+3), "Error", FALSE );
1693         }
1694         offset += 4;
1695         length -= 4;
1696         while ( length > 0 ) {
1697                 mylen = tvb_get_guint8(tvb, offset);
1698                 length--;
1699                 if (length<=0) {
1700                         isis_dissect_unknown(tvb, tree, offset,
1701                                 "Zero payload space after length in prefix neighbor" );
1702                         return;
1703                 }
1704                 if ( mylen > length) {
1705                         isis_dissect_unknown(tvb, tree, offset,
1706                                 "Integral length of prefix neighbor too long (%d vs %d)",
1707                                 mylen, length );
1708                         return;
1709                 }
1710
1711                 /*
1712                  * Lets turn the area address into "standard" 0000.0000.etc
1713                  * format string.
1714                  */
1715                 sbuf =  print_area( tvb_get_ptr(tvb, offset+1, mylen), mylen );
1716                 /* and spit it out */
1717                 if ( tree ) {
1718                         proto_tree_add_text ( tree, tvb, offset, mylen + 1,
1719                                 "Area address (%d): %s", mylen, sbuf );
1720                 }
1721                 offset += mylen + 1;
1722                 length -= mylen;        /* length already adjusted for len fld*/
1723         }
1724 }
1725
1726 static void isis_lsp_checkum_additional_info(tvbuff_t * tvb, packet_info * pinfo, 
1727     proto_item * it_cksum, int offset, gboolean is_cksum_correct)
1728 {
1729         proto_tree * checksum_tree;
1730         proto_item * item;
1731
1732         checksum_tree = proto_item_add_subtree(it_cksum, ett_isis_lsp_cksum);
1733         item = proto_tree_add_boolean(checksum_tree, hf_isis_lsp_checksum_good, tvb,
1734            offset, 2, is_cksum_correct);
1735         PROTO_ITEM_SET_GENERATED(item);
1736         item = proto_tree_add_boolean(checksum_tree, hf_isis_lsp_checksum_bad, tvb,
1737            offset, 2, !is_cksum_correct);
1738         PROTO_ITEM_SET_GENERATED(item);
1739         if (!is_cksum_correct) {
1740           expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
1741           col_append_str(pinfo->cinfo, COL_INFO, " [ISIS CHECKSUM INCORRECT]");
1742         }
1743 }
1744
1745
1746 /*
1747  * Name: isis_dissect_isis_lsp()
1748  *
1749  * Description:
1750  *      Print out the LSP part of the main header and then call the CLV
1751  *      de-mangler with the right list of valid CLVs.
1752  *
1753  * Input:
1754  *      tvbuff_t * : tvbuffer for packet data
1755  *      proto_tree * : protocol display tree to add to.  May be NULL.
1756  *      int offset : our offset into packet data.
1757  *      int : LSP type, a la packet-isis.h ISIS_TYPE_* values
1758  *      int : header length of packet.
1759  *      int : length of IDs in packet.
1760  *
1761  * Output:
1762  *      void, but we will add to proto tree if !NULL.
1763  */
1764 void
1765 isis_dissect_isis_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
1766         int lsp_type, int header_length, int id_length)
1767 {
1768         proto_item      *ti, *to, *ta;
1769         proto_tree      *lsp_tree = NULL, *info_tree, *att_tree;
1770         guint16         pdu_length, lifetime, checksum, cacl_checksum=0;
1771         guint8          lsp_info, lsp_att;
1772         int             len, offset_checksum;
1773         proto_item      *it_cksum;
1774
1775         if (tree) {
1776                 ti = proto_tree_add_text(tree, tvb, offset, -1,
1777                     PROTO_STRING_LSP);
1778                 lsp_tree = proto_item_add_subtree(ti, ett_isis_lsp);
1779         }
1780
1781         pdu_length = tvb_get_ntohs(tvb, offset);
1782         if (tree) {
1783                 proto_tree_add_uint(lsp_tree, hf_isis_lsp_pdu_length, tvb,
1784                         offset, 2, pdu_length);
1785         }
1786         offset += 2;
1787
1788         if (tree) {
1789                 proto_tree_add_item(lsp_tree, hf_isis_lsp_remaining_life, 
1790                         tvb, offset, 2, FALSE);
1791         }
1792         lifetime = tvb_get_ntohs(tvb, offset);
1793         offset += 2;
1794         offset_checksum = offset;
1795
1796         if (tree) {
1797                 char* value = print_system_id( tvb_get_ptr(tvb, offset, id_length+2), 
1798                                     id_length+2);
1799                 proto_tree_add_string_format(lsp_tree, hf_isis_lsp_lsp_id, 
1800                         tvb, offset, id_length + 2,
1801                         value, "LSP-ID: %s", value);
1802         }
1803
1804         if (check_col(pinfo->cinfo, COL_INFO)) {
1805             col_append_fstr(pinfo->cinfo, COL_INFO, ", LSP-ID: %s",
1806                         print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
1807         }
1808         offset += id_length + 2;
1809
1810         if (tree) {
1811                 proto_tree_add_item(lsp_tree, hf_isis_lsp_sequence_number, 
1812                         tvb, offset, 4, FALSE);
1813         }
1814         if (check_col(pinfo->cinfo, COL_INFO)) {
1815                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Sequence: 0x%08x, Lifetime: %5us",
1816                         tvb_get_ntohl(tvb, offset),
1817                         tvb_get_ntohs(tvb, offset - (id_length+2+2)));
1818         }
1819         offset += 4;
1820
1821         if (tree) {
1822                 checksum = lifetime ? tvb_get_ntohs(tvb, offset) : 0;
1823                 switch (check_and_get_checksum(tvb, offset_checksum, pdu_length-12, checksum, offset, &cacl_checksum))
1824                 {
1825                         case NO_CKSUM :
1826                                 checksum = tvb_get_ntohs(tvb, offset);
1827                                 proto_tree_add_uint_format(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
1828                                         "Checksum: 0x%04x [unused]", checksum);
1829                         break;
1830                         case DATA_MISSING :
1831                                 isis_dissect_unknown(tvb, tree, offset,
1832                                         "[packet length %d went beyond packet]",
1833                                         tvb_length_remaining(tvb, offset_checksum));
1834                         break;
1835                         case CKSUM_NOT_OK :
1836                                 it_cksum = proto_tree_add_uint_format(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
1837                                         "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1838                                         checksum, cacl_checksum);
1839                                 isis_lsp_checkum_additional_info(tvb, pinfo, it_cksum, offset, FALSE);
1840                         break;
1841                         case CKSUM_OK :
1842                                 it_cksum = proto_tree_add_uint_format(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
1843                                         "Checksum: 0x%04x [correct]", checksum);
1844                                 isis_lsp_checkum_additional_info(tvb, pinfo, it_cksum, offset, TRUE);
1845                         break;
1846                         default :
1847                                 g_message("'check_and_get_checksum' returned an invalid value");
1848                 }
1849         }
1850         offset += 2;
1851
1852         if (tree) {
1853                 /*
1854                  * P | ATT | HIPPITY | IS TYPE description.
1855                  */
1856                 lsp_info = tvb_get_guint8(tvb, offset);
1857                 to = proto_tree_add_text(lsp_tree, tvb, offset, 1,
1858                         "Type block(0x%02x): Partition Repair:%d, Attached bits:%d, Overload bit:%d, IS type:%d",
1859                         lsp_info,
1860                         ISIS_LSP_PARTITION(lsp_info),
1861                         ISIS_LSP_ATT(lsp_info),
1862                         ISIS_LSP_HIPPITY(lsp_info),
1863                         ISIS_LSP_IS_TYPE(lsp_info)
1864                         );
1865
1866                 info_tree = proto_item_add_subtree(to, ett_isis_lsp_info);
1867                 proto_tree_add_boolean(info_tree, hf_isis_lsp_p, tvb, offset, 1, lsp_info);
1868                 ta = proto_tree_add_uint(info_tree, hf_isis_lsp_att, tvb, offset, 1, lsp_info);
1869                 att_tree = proto_item_add_subtree(ta, ett_isis_lsp_att);
1870                 lsp_att = ISIS_LSP_ATT(lsp_info);
1871                 proto_tree_add_text(att_tree, tvb, offset, 1,
1872                           "%d... = Error metric: %s", ISIS_LSP_ATT_ERROR(lsp_att), ISIS_LSP_ATT_ERROR(lsp_att) ? "Set" : "Unset");
1873                 proto_tree_add_text(att_tree, tvb, offset, 1,
1874                           ".%d.. = Expense metric: %s", ISIS_LSP_ATT_EXPENSE(lsp_att), ISIS_LSP_ATT_EXPENSE(lsp_att) ? "Set" : "Unset");
1875                 proto_tree_add_text(att_tree, tvb, offset, 1,
1876                           "..%d. = Delay metric: %s", ISIS_LSP_ATT_DELAY(lsp_att), ISIS_LSP_ATT_DELAY(lsp_att) ? "Set" : "Unset");
1877                 proto_tree_add_text(att_tree, tvb, offset, 1,
1878                           "...%d = Default metric: %s", ISIS_LSP_ATT_DEFAULT(lsp_att), ISIS_LSP_ATT_DEFAULT(lsp_att) ? "Set" : "Unset");
1879                 proto_tree_add_boolean(info_tree, hf_isis_lsp_hippity, tvb, offset, 1, lsp_info);
1880                 proto_tree_add_uint(info_tree, hf_isis_lsp_is_type, tvb, offset, 1, lsp_info);
1881         }
1882         offset += 1;
1883
1884         len = pdu_length - header_length;
1885         if (len < 0) {
1886                 isis_dissect_unknown(tvb, tree, offset,
1887                         "packet header length %d went beyond packet",
1888                          header_length );
1889                 return;
1890         }
1891         /*
1892          * Now, we need to decode our CLVs.  We need to pass in
1893          * our list of valid ones!
1894          */
1895         if (lsp_type == ISIS_TYPE_L1_LSP){
1896                 isis_dissect_clvs(tvb, lsp_tree, offset,
1897                         clv_l1_lsp_opts, len, id_length,
1898                         ett_isis_lsp_clv_unknown );
1899         } else {
1900                 isis_dissect_clvs(tvb, lsp_tree, offset,
1901                         clv_l2_lsp_opts, len, id_length,
1902                         ett_isis_lsp_clv_unknown );
1903         }
1904 }
1905 /*
1906  * Name: isis_register_lsp()
1907  *
1908  * Description:
1909  *      Register our protocol sub-sets with protocol manager.
1910  *
1911  * Input:
1912  *      int : protocol index for the ISIS protocol
1913  *
1914  * Output:
1915  *      void
1916  */
1917 void
1918 isis_register_lsp(int proto_isis) {
1919         static hf_register_info hf[] = {
1920                 { &hf_isis_lsp_pdu_length,
1921                 { "PDU length",         "isis.lsp.pdu_length", FT_UINT16,
1922                   BASE_DEC, NULL, 0x0, NULL, HFILL }},
1923
1924                 { &hf_isis_lsp_remaining_life,
1925                 { "Remaining lifetime", "isis.lsp.remaining_life", FT_UINT16,
1926                   BASE_DEC, NULL, 0x0, NULL, HFILL }},
1927
1928                 { &hf_isis_lsp_lsp_id,
1929                 { "LSP-ID", "isis.lsp.lsp_id", FT_STRING,
1930                   BASE_NONE, NULL, 0x0, NULL, HFILL }},
1931
1932                 { &hf_isis_lsp_hostname,
1933                 { "Hostname", "isis.lsp.hostname", FT_STRING,
1934                   BASE_NONE, NULL, 0x0, NULL, HFILL }},
1935
1936                 { &hf_isis_lsp_sequence_number,
1937                 { "Sequence number",           "isis.lsp.sequence_number",
1938                   FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1939
1940                 { &hf_isis_lsp_checksum,
1941                 { "Checksum",           "isis.lsp.checksum",FT_UINT16,
1942                   BASE_HEX, NULL, 0x0, NULL, HFILL }},
1943                   
1944                 { &hf_isis_lsp_checksum_good,
1945                 { "Good Checksum", "isis.lsp.checksum_good", FT_BOOLEAN, BASE_NONE,
1946                         NULL, 0x0, "Good IS-IS LSP Checksum", HFILL }},
1947
1948                 { &hf_isis_lsp_checksum_bad,
1949                 { "Bad Checksum", "isis.lsp.checksum_bad", FT_BOOLEAN, BASE_NONE,
1950                         NULL, 0x0, "Bad IS-IS LSP Checksum", HFILL }},
1951
1952                 { &hf_isis_lsp_clv_ipv4_int_addr,
1953                 { "IPv4 interface address", "isis.lsp.clv_ipv4_int_addr", FT_IPv4,
1954                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
1955
1956                 { &hf_isis_lsp_clv_ipv6_int_addr,
1957                 { "IPv6 interface address", "isis.lsp.clv_ipv6_int_addr", FT_IPv6,
1958                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
1959
1960                 { &hf_isis_lsp_clv_te_router_id,
1961                 { "Traffic Engineering Router ID", "isis.lsp.clv_te_router_id", FT_IPv4,
1962                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
1963
1964                 { &hf_isis_lsp_clv_mt,
1965                 { "MT-ID", "isis.lsp.clv_mt",
1966                         FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1967
1968                 { &hf_isis_lsp_p,
1969                 { "Partition Repair",   "isis.lsp.partition_repair", FT_BOOLEAN, 8,
1970                         TFS(&tfs_supported_not_supported), ISIS_LSP_PARTITION_MASK,
1971                         "If set, this router supports the optional Partition Repair function", HFILL }},
1972
1973                 { &hf_isis_lsp_att,
1974                 { "Attachment", "isis.lsp.att", FT_UINT8, BASE_DEC,
1975                         NULL, ISIS_LSP_ATT_MASK,
1976                         NULL, HFILL }},
1977
1978                 { &hf_isis_lsp_hippity,
1979                 { "Overload bit",       "isis.lsp.overload", FT_BOOLEAN, 8,
1980                         TFS(&tfs_set_notset), ISIS_LSP_HIPPITY_MASK,
1981                         "If set, this router will not be used by any decision process to calculate routes", HFILL }},
1982
1983                 { &hf_isis_lsp_is_type,
1984                 { "Type of Intermediate System",        "isis.lsp.is_type", FT_UINT8, BASE_DEC,
1985                         VALS(isis_lsp_istype_vals), ISIS_LSP_IS_TYPE_MASK,
1986                         NULL, HFILL }}
1987         };
1988         static gint *ett[] = {
1989                 &ett_isis_lsp,
1990                 &ett_isis_lsp_info,
1991                 &ett_isis_lsp_att,
1992                 &ett_isis_lsp_cksum,
1993                 &ett_isis_lsp_clv_area_addr,
1994                 &ett_isis_lsp_clv_is_neighbors,
1995                 &ett_isis_lsp_clv_ext_is_reachability, /* CLV 22 */
1996                 &ett_isis_lsp_part_of_clv_ext_is_reachability,
1997                 &ett_isis_lsp_subclv_admin_group,
1998                 &ett_isis_lsp_subclv_unrsv_bw,
1999                 &ett_isis_lsp_clv_unknown,
2000                 &ett_isis_lsp_clv_partition_dis,
2001                 &ett_isis_lsp_clv_prefix_neighbors,
2002                 &ett_isis_lsp_clv_authentication,
2003                 &ett_isis_lsp_clv_ip_authentication,
2004                 &ett_isis_lsp_clv_nlpid,
2005                 &ett_isis_lsp_clv_hostname,
2006                 &ett_isis_lsp_clv_ipv4_int_addr,
2007                 &ett_isis_lsp_clv_ipv6_int_addr, /* CLV 232 */
2008                 &ett_isis_lsp_clv_te_router_id,
2009                 &ett_isis_lsp_clv_ip_reachability,
2010                 &ett_isis_lsp_clv_ip_reach_subclv,
2011                 &ett_isis_lsp_clv_ext_ip_reachability, /* CLV 135 */
2012                 &ett_isis_lsp_part_of_clv_ext_ip_reachability,
2013                 &ett_isis_lsp_clv_ipv6_reachability, /* CLV 236 */
2014                 &ett_isis_lsp_part_of_clv_ipv6_reachability,
2015                 &ett_isis_lsp_clv_mt,
2016                 &ett_isis_lsp_clv_mt_is,
2017                 &ett_isis_lsp_part_of_clv_mt_is,
2018     &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
2019     &ett_isis_lsp_clv_mt_reachable_IPv6_prefx
2020         };
2021
2022         proto_register_field_array(proto_isis, hf, array_length(hf));
2023         proto_register_subtree_array(ett, array_length(ett));
2024 }