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