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