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