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