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