proto_tree_add_subtree[_format]
[metze/wireshark/wip.git] / epan / dissectors / packet-isis-lsp.c
1 /* packet-isis-lsp.c
2  * Routines for decoding isis lsp packets and their CLVs
3  *
4  * Stuart Stanley <stuarts@mxmail.net>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 /*
25  * Copyright 2011, Malgi Nikitha Vivekananda <malgi.nikitha@ipinfusion.com>
26  *                 Krishnamurthy Mayya <krishnamurthy.mayya@ipinfusion.com>
27  *                    - Decoding for Router Capability TLV and associated subTLVs as per RFC 6326
28  *                    - Decoding for Group Address TLV and associated subTLVs as per RFC 6326
29  */
30
31 #include "config.h"
32
33 #include <glib.h>
34
35 #include <epan/packet.h>
36 #include <epan/expert.h>
37 #include "packet-osi.h"
38 #include "packet-isis.h"
39 #include "packet-isis-clv.h"
40 #include <epan/addr_resolv.h>
41 #include <epan/addr_and_mask.h>
42
43 /*
44  * Declarations for L1/L2 LSP base header.
45  */
46
47 /* P | ATT | HIPPITY | DS FIELD description */
48 #define ISIS_LSP_PARTITION_MASK     0x80
49 #define ISIS_LSP_PARTITION_SHIFT    7
50 #define ISIS_LSP_PARTITION(info)    (((info) & ISIS_LSP_PARTITION_MASK) >> ISIS_LSP_PARTITION_SHIFT)
51
52 #define ISIS_LSP_ATT_MASK     0x78
53 #define ISIS_LSP_ATT_SHIFT    3
54 #define ISIS_LSP_ATT(info)    (((info) & ISIS_LSP_ATT_MASK) >> ISIS_LSP_ATT_SHIFT)
55
56 #define ISIS_LSP_ATT_ERROR(info)   ((info) >> 3)
57 #define ISIS_LSP_ATT_EXPENSE(info) (((info) >> 2) & 1)
58 #define ISIS_LSP_ATT_DELAY(info)   (((info) >> 1) & 1)
59 #define ISIS_LSP_ATT_DEFAULT(info) ((info) & 1)
60
61 #define ISIS_LSP_HIPPITY_MASK     0x04
62 #define ISIS_LSP_HIPPITY_SHIFT    2
63 #define ISIS_LSP_HIPPITY(info)    (((info) & ISIS_LSP_HIPPITY_MASK) >> ISIS_LSP_HIPPITY_SHIFT)
64
65 #define ISIS_LSP_IS_TYPE_MASK     0x03
66 #define ISIS_LSP_IS_TYPE(info)    ((info) & ISIS_LSP_IS_TYPE_MASK)
67
68 #define ISIS_LSP_MT_MSHIP_RES_MASK   0xF000
69 #define ISIS_LSP_MT_MSHIP_ID_MASK   0x0FFF
70
71
72 #define ISIS_LSP_TYPE_UNUSED0           0
73 #define ISIS_LSP_TYPE_LEVEL_1           1
74 #define ISIS_LSP_TYPE_UNUSED2           2
75 #define ISIS_LSP_TYPE_LEVEL_2           3
76
77 #define ISIS_LSP_ATTACHED_NONE    0
78 #define ISIS_LSP_ATTACHED_DEFAULT 1
79 #define ISIS_LSP_ATTACHED_DELAY   2
80 #define ISIS_LSP_ATTACHED_EXPENSE 4
81 #define ISIS_LSP_ATTACHED_ERROR   8
82
83
84 #define ISIS_LSP_CLV_METRIC_SUPPORTED(x)        ((x)&0x80)
85 #define ISIS_LSP_CLV_METRIC_IE(x)               ((x)&0x40)
86 #define ISIS_LSP_CLV_METRIC_RESERVED(x)         ((x)&0x40)
87 #define ISIS_LSP_CLV_METRIC_UPDOWN(x)           ((x)&0x80)
88 #define ISIS_LSP_CLV_METRIC_VALUE(x)            ((x)&0x3f)
89
90 /* Sub-TLVs under Router Capability TLV
91    As per RFC 6326 section 2.3 */
92 #define TRILL_VERSION            12
93 #define NICKNAME                  6
94 #define TREES                     7
95 #define TREE_IDENTIFIER           8
96 #define TREES_USED_IDENTIFIER     9
97 #define INTERESTED_VLANS         10
98 #define VLAN_GROUP               13
99
100
101 /*Sub-TLVs under Group Address TLV*/
102 #define GRP_MAC_ADDRESS 1
103 #define FP_HMAC_SWID_MASK  G_GINT64_CONSTANT(0xFFFF00000000)
104 #define FP_HMAC_SSWID_MASK G_GINT64_CONSTANT(0x0000FFFF0000)
105 #define FP_HMAC_LID_MASK   G_GINT64_CONSTANT(0x00000000FFFF)
106
107 void proto_register_isis_lsp(void);
108 void proto_reg_handoff_isis_lsp(void);
109
110 static int proto_isis_lsp = -1;
111
112 /* lsp packets */
113 static int hf_isis_lsp_pdu_length = -1;
114 static int hf_isis_lsp_remaining_life = -1;
115 static int hf_isis_lsp_sequence_number = -1;
116 static int hf_isis_lsp_lsp_id = -1;
117 static int hf_isis_lsp_hostname = -1;
118 static int hf_isis_lsp_checksum = -1;
119 static int hf_isis_lsp_checksum_bad = -1;
120 static int hf_isis_lsp_checksum_good = -1;
121 static int hf_isis_lsp_clv_ipv4_int_addr = -1;
122 static int hf_isis_lsp_clv_ipv6_int_addr = -1;
123 static int hf_isis_lsp_clv_te_router_id = -1;
124 static int hf_isis_lsp_clv_mt = -1;
125 static int hf_isis_lsp_p = -1;
126 static int hf_isis_lsp_att = -1;
127 static int hf_isis_lsp_hippity = -1;
128 static int hf_isis_lsp_is_type = -1;
129 static int hf_isis_lsp_root_id = -1;
130 static int hf_isis_lsp_spb_link_metric = -1;
131 static int hf_isis_lsp_spb_port_count = -1;
132 static int hf_isis_lsp_spb_port_id = -1;
133 static int hf_isis_lsp_spb_sr_bit = -1;
134 static int hf_isis_lsp_spb_spvid = -1;
135 /* Generated from convert_proto_tree_add_text.pl */
136 static int hf_isis_lsp_grp_address_length = -1;
137 static int hf_isis_lsp_mt_cap_spb_instance_v = -1;
138 static int hf_isis_lsp_mt_cap_spb_instance_cist_external_root_path_cost = -1;
139 static int hf_isis_lsp_rt_capable_tree_used_id_starting_tree_no = -1;
140 static int hf_isis_lsp_mt_cap_spb_instance_bridge_priority = -1;
141 static int hf_isis_lsp_rt_capable_trees_length = -1;
142 static int hf_isis_lsp_mt_cap_spbm_service_identifier_base_vid = -1;
143 static int hf_isis_lsp_64_bit_administrative_tag = -1;
144 static int hf_isis_lsp_grp_address_number_of_sources = -1;
145 static int hf_isis_lsp_ext_is_reachability_traffic_engineering_default_metric = -1;
146 static int hf_isis_lsp_grp_address_group_address = -1;
147 static int hf_isis_lsp_rt_capable_tree_root_id_nickname = -1;
148 static int hf_isis_lsp_ext_is_reachability_ipv4_interface_address = -1;
149 static int hf_isis_lsp_ext_ip_reachability_metric = -1;
150 static int hf_isis_lsp_ext_ip_reachability_ipv4_prefix = -1;
151 static int hf_isis_lsp_eis_neighbors_es_neighbor_id = -1;
152 static int hf_isis_lsp_rt_capable_interested_vlans_length = -1;
153 static int hf_isis_lsp_expense_metric = -1;
154 static int hf_isis_lsp_ext_is_reachability_link_remote_identifier = -1;
155 static int hf_isis_lsp_rt_capable_vlan_group_secondary_vlan_id = -1;
156 static int hf_isis_lsp_grp_address_vlan_id = -1;
157 static int hf_isis_lsp_rt_capable_trill_length = -1;
158 static int hf_isis_lsp_rt_capable_tree_root_id_starting_tree_no = -1;
159 static int hf_isis_lsp_rt_capable_interested_vlans_nickname = -1;
160 static int hf_isis_lsp_rt_capable_nickname_length = -1;
161 static int hf_isis_lsp_ip_reachability_ipv4_prefix = -1;
162 static int hf_isis_lsp_grp_address_topology_id = -1;
163 static int hf_isis_lsp_ext_is_reachability_ipv4_neighbor_address = -1;
164 static int hf_isis_lsp_rt_capable_vlan_group_nth_secondary_vlan_id = -1;
165 static int hf_isis_lsp_ipv6_reachability_reserved_bits = -1;
166 static int hf_isis_lsp_eis_neighbors_default_metric = -1;
167 static int hf_isis_lsp_mt_cap_spb_instance_cist_root_identifier = -1;
168 static int hf_isis_lsp_rt_capable_tree_used_id_nickname = -1;
169 static int hf_isis_lsp_grp_address_source_address = -1;
170 static int hf_isis_lsp_delay_metric = -1;
171 static int hf_isis_lsp_ext_is_reachability_link_local_identifier = -1;
172 static int hf_isis_lsp_mt_cap_mtid = -1;
173 static int hf_isis_lsp_32_bit_administrative_tag = -1;
174 static int hf_isis_lsp_ext_is_reachability_is_neighbor_id = -1;
175 static int hf_isis_lsp_reservable_link_bandwidth = -1;
176 static int hf_isis_lsp_rt_capable_vlan_group_primary_vlan_id = -1;
177 static int hf_isis_lsp_rt_capable_interested_vlans_multicast_ipv4 = -1;
178 static int hf_isis_lsp_rt_capable_interested_vlans_multicast_ipv6 = -1;
179 static int hf_isis_lsp_mt_cap_spb_instance_number_of_trees = -1;
180 static int hf_isis_lsp_mt_cap_spbm_service_identifier_b_mac = -1;
181 static int hf_isis_lsp_ipv6_reachability_distribution = -1;
182 static int hf_isis_lsp_ipv6_reachability_distribution_internal = -1;
183 static int hf_isis_lsp_ipv6_reachability_metric = -1;
184 static int hf_isis_lsp_rt_capable_trees_maximum_nof_trees_to_compute = -1;
185 static int hf_isis_lsp_rt_capable_interested_vlans_vlan_start_id = -1;
186 static int hf_isis_lsp_rt_capable_nickname_nickname_priority = -1;
187 static int hf_isis_lsp_ext_is_reachability_metric = -1;
188 static int hf_isis_lsp_default_metric = -1;
189 static int hf_isis_lsp_ext_ip_reachability_distribution = -1;
190 static int hf_isis_lsp_maximum_link_bandwidth = -1;
191 static int hf_isis_lsp_rt_capable_tree_root_id_length = -1;
192 static int hf_isis_lsp_rt_capable_nickname_tree_root_priority = -1;
193 static int hf_isis_lsp_eis_neighbors_delay_metric = -1;
194 static int hf_isis_lsp_rt_capable_trill_maximum_version = -1;
195 static int hf_isis_lsp_rt_capable_interested_vlans_afs_lost_counter = -1;
196 static int hf_isis_lsp_ipv6_reachability_ipv6_prefix = -1;
197 static int hf_isis_lsp_eis_neighbors_error_metric = -1;
198 static int hf_isis_lsp_rt_capable_interested_vlans_vlan_end_id = -1;
199 static int hf_isis_lsp_error_metric = -1;
200 static int hf_isis_lsp_grp_address_number_of_records = -1;
201 static int hf_isis_lsp_rt_capable_tree_used_id_length = -1;
202 static int hf_isis_lsp_rt_capable_nickname_nickname = -1;
203 static int hf_isis_lsp_mt_id_reserved = -1;
204 static int hf_isis_lsp_eis_neighbors_is_neighbor_id = -1;
205 static int hf_isis_lsp_mt_id = -1;
206 static int hf_isis_lsp_eis_neighbors_reserved = -1;
207 static int hf_isis_lsp_ip_reachability_error_metric = -1;
208 static int hf_isis_lsp_ip_reachability_delay_metric = -1;
209 static int hf_isis_lsp_ip_reachability_expense_metric = -1;
210 static int hf_isis_lsp_rt_capable_trees_nof_trees_to_use = -1;
211 static int hf_isis_lsp_ip_reachability_default_metric = -1;
212 static int hf_isis_lsp_rt_capable_trees_nof_trees_to_compute = -1;
213 static int hf_isis_lsp_eis_neighbors_expense_metric = -1;
214 static int hf_isis_lsp_rt_capable_vlan_group_length = -1;
215 static int hf_isis_lsp_partition_designated_l2_is = -1;
216 static int hf_isis_lsp_ip_reachability_default_metric_ie = -1;
217 static int hf_isis_lsp_eis_neighbors_default_metric_ie = -1;
218 static int hf_isis_lsp_eis_neighbors_error_metric_supported = -1;
219 static int hf_isis_lsp_unrsv_bw_priority_level = -1;
220 static int hf_isis_lsp_ip_reachability_expense_metric_support = -1;
221 static int hf_isis_lsp_mt_cap_overload = -1;
222 static int hf_isis_lsp_eis_neighbors_expense_metric_supported = -1;
223 static int hf_isis_lsp_ip_reachability_delay_metric_support = -1;
224 static int hf_isis_lsp_ip_reachability_error_metric_support = -1;
225 static int hf_isis_lsp_mt_cap_spsourceid = -1;
226 static int hf_isis_lsp_eis_neighbors_delay_metric_supported = -1;
227 static int hf_isis_lsp_eis_neighbors_error_metric_ie = -1;
228 static int hf_isis_lsp_eis_neighbors_expense_metric_ie = -1;
229 static int hf_isis_lsp_eis_neighbors_delay_metric_ie = -1;
230 static int hf_isis_lsp_ip_reachability_delay_metric_ie = -1;
231 static int hf_isis_lsp_ip_reachability_distribution = -1;
232 static int hf_isis_lsp_ip_reachability_error_metric_ie = -1;
233 static int hf_isis_lsp_ip_reachability_expense_metric_ie = -1;
234
235 static gint ett_isis_lsp = -1;
236 static gint ett_isis_lsp_info = -1;
237 static gint ett_isis_lsp_att = -1;
238 static gint ett_isis_lsp_cksum = -1;
239 static gint ett_isis_lsp_clv_area_addr = -1;
240 static gint ett_isis_lsp_clv_is_neighbors = -1;
241 static gint ett_isis_lsp_clv_ext_is_reachability = -1; /* CLV 22 */
242 static gint ett_isis_lsp_part_of_clv_ext_is_reachability = -1;
243 static gint ett_isis_lsp_subclv_admin_group = -1;
244 static gint ett_isis_lsp_subclv_unrsv_bw = -1;
245 static gint ett_isis_lsp_subclv_spb_link_metric = -1;
246 static gint ett_isis_lsp_clv_unknown = -1;
247 static gint ett_isis_lsp_clv_partition_dis = -1;
248 static gint ett_isis_lsp_clv_prefix_neighbors = -1;
249 static gint ett_isis_lsp_clv_nlpid = -1;
250 static gint ett_isis_lsp_clv_hostname = -1;
251 static gint ett_isis_lsp_clv_te_router_id = -1;
252 static gint ett_isis_lsp_clv_authentication = -1;
253 static gint ett_isis_lsp_clv_ip_authentication = -1;
254 static gint ett_isis_lsp_clv_ipv4_int_addr = -1;
255 static gint ett_isis_lsp_clv_ipv6_int_addr = -1; /* CLV 232 */
256 static gint ett_isis_lsp_clv_mt_cap = -1;
257 static gint ett_isis_lsp_clv_mt_cap_spb_instance = -1;
258 static gint ett_isis_lsp_clv_mt_cap_spbm_service_identifier = -1;
259 static gint ett_isis_lsp_clv_ip_reachability = -1;
260 static gint ett_isis_lsp_clv_ip_reach_subclv = -1;
261 static gint ett_isis_lsp_clv_ext_ip_reachability = -1; /* CLV 135 */
262 static gint ett_isis_lsp_part_of_clv_ext_ip_reachability = -1;
263 static gint ett_isis_lsp_clv_ipv6_reachability = -1; /* CLV 236 */
264 static gint ett_isis_lsp_part_of_clv_ipv6_reachability = -1;
265 static gint ett_isis_lsp_clv_mt = -1;
266 static gint ett_isis_lsp_clv_mt_is = -1;
267 static gint ett_isis_lsp_part_of_clv_mt_is = -1;
268 static gint ett_isis_lsp_clv_mt_reachable_IPv4_prefx = -1;  /* CLV 235 */
269 static gint ett_isis_lsp_clv_mt_reachable_IPv6_prefx = -1;  /* CLV 237 */
270 static gint ett_isis_lsp_clv_rt_capable_IPv4_prefx = -1;   /* CLV 242 */
271 static gint ett_isis_lsp_clv_grp_address_IPv4_prefx = -1;  /* CLV 142 */
272 static gint ett_isis_lsp_clv_mt_cap_spbv_mac_address = -1;
273
274 static expert_field ie_isis_lsp_checksum_bad = EI_INIT;
275 static expert_field ei_isis_lsp_short_packet = EI_INIT;
276 static expert_field ei_isis_lsp_long_packet = EI_INIT;
277 static expert_field ei_isis_lsp_subtlv = EI_INIT;
278 static expert_field ei_isis_lsp_authentication = EI_INIT;
279
280 static const value_string isis_lsp_istype_vals[] = {
281         { ISIS_LSP_TYPE_UNUSED0,        "Unused 0x0 (invalid)"},
282         { ISIS_LSP_TYPE_LEVEL_1,        "Level 1"},
283         { ISIS_LSP_TYPE_UNUSED2,        "Unused 0x2 (invalid)"},
284         { ISIS_LSP_TYPE_LEVEL_2,        "Level 2"},
285         { 0, NULL } };
286
287 static const true_false_string tfs_up_down = { "Up", "Down" };
288 static const true_false_string tfs_notsupported_supported = { "Not Supported", "Supported" };
289 static const true_false_string tfs_internal_external = { "Internal", "External" };
290 static const true_false_string tfs_external_internal = { "External", "Internal" };
291
292 static void
293 fp_get_hmac_addr (guint64 hmac, guint16 *swid, guint16 *sswid, guint16 *lid) {
294
295         if (!swid || !sswid || !lid) {
296                 return;
297         }
298
299         *swid  = (guint16) ((hmac & FP_HMAC_SWID_MASK) >> 32);
300         *sswid = (guint16) ((hmac & FP_HMAC_SSWID_MASK) >> 16);
301         *lid   = (guint16)  (hmac & FP_HMAC_LID_MASK);
302 }
303 /*
304  * Name: dissect_lsp_mt_id()
305  *
306  * Description:
307  *      dissect and display the multi-topology ID value
308  *
309  * Input:
310  *      tvbuff_t * : tvbuffer for packet data
311  *      proto_tree * : protocol display tree to fill out.  CAN'T BE NULL
312  *      int : offset into packet data where we are.
313  *
314  * Output:
315  *      void, but we will add to proto tree.
316  */
317 static void
318 dissect_lsp_mt_id(tvbuff_t *tvb, proto_tree *tree, int offset)
319 {
320         int  mt_block, mt_id;
321         const char *mt_desc="";
322
323         /* fetch two bytes */
324         mt_block = tvb_get_ntohs(tvb, offset);
325
326         proto_tree_add_item(tree, hf_isis_lsp_mt_id_reserved, tvb, offset, 2, ENC_NA);
327
328         mt_id = mt_block & ISIS_LSP_MT_MSHIP_ID_MASK;
329         /*mask out the lower 12 bits */
330         switch(mt_id) {
331         case 0:
332                 mt_desc="'standard' topology";
333                 break;
334         case 1:
335                 mt_desc="IPv4 In-Band Management purposes";
336                 break;
337         case 2:
338                 mt_desc="IPv6 routing topology";
339                 break;
340         case 3:
341                 mt_desc="IPv4 multicast routing topology";
342                 break;
343         case 4:
344                 mt_desc="IPv6 multicast routing topology";
345                 break;
346         default:
347                 mt_desc=((mt_block & 0x0fff) < 3996) ? "Reserved for IETF Consensus" : "Development, Experimental and Proprietary features";
348         }
349
350         proto_tree_add_uint_format( tree, hf_isis_lsp_mt_id, tvb, offset, 2,
351                              mt_id, "%s (%d)", mt_desc, mt_id);
352
353 }
354
355 /*
356  * Name: dissect_metric()
357  *
358  * Description:
359  *      Display a metric prefix portion.  ISIS has the concept of multple
360  *      metric per prefix (default, delay, expense, and error).  This
361  *      routine assists other dissectors by adding a single one of
362  *      these to the display tree..
363  *
364  *      The 8th(msbit) bit in the metric octet is the "supported" bit.  The
365  *              "default" support is required, so we support a "force_supported"
366  *              flag that tells us that it MUST be zero (zero==supported,
367  *              so it really should be a "not supported" in the boolean sense)
368  *              and to display a protocol failure accordingly.  Notably,
369  *              Cisco IOS 12(6) blows this!
370  *      The 7th bit must be zero (reserved).
371  *
372  * Input:
373  *      tvbuff_t * : tvbuffer for packet data
374  *      proto_tree * : protocol display tree to fill out.  May be NULL
375  *      int : offset into packet data where we are.
376  *      guint8 : value of the metric.
377  *      char * : string giving type of the metric.
378  *      int : force supported.  True is the supported bit MUST be zero.
379  *
380  * Output:
381  *      void, but we will add to proto tree if !NULL.
382  */
383 static void
384 dissect_metric(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 value,
385         const char *pstr, int force_supported )
386 {
387         int s;
388
389         if ( !tree ) return;
390
391         s = ISIS_LSP_CLV_METRIC_SUPPORTED(value);
392         proto_tree_add_text(tree, tvb, offset, 1,
393                 "%s Metric: %s%s %s%d:%d", pstr,
394                 s ? "Not supported" : "Supported",
395                 (s && force_supported) ? "(but is required to be)":"",
396                 ISIS_LSP_CLV_METRIC_RESERVED(value) ? "(reserved bit != 0)":"",
397                 ISIS_LSP_CLV_METRIC_VALUE(value), value );
398 }
399
400 /*
401  * Name: dissect_lsp_ip_reachability_clv()
402  *
403  * Description:
404  *      Decode an IP reachability CLV.  This can be either internal or
405  *      external (the clv format does not change and which type we are
406  *      displaying is put there by the dispatcher).  All of these
407  *      are a metric block followed by an IP addr and mask.
408  *
409  * Input:
410  *      tvbuff_t * : tvbuffer for packet data
411  *      proto_tree * : proto tree to build on (may be null)
412  *      int : current offset into packet data
413  *      int : length of IDs in packet.
414  *      int : length of this clv
415  *
416  * Output:
417  *      void, will modify proto_tree if not null.
418  */
419 static void
420 dissect_lsp_ip_reachability_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
421         int id_length _U_, int length)
422 {
423         proto_item      *ti;
424         proto_tree      *ntree = NULL;
425         guint32         src, mask, bitmask;
426         int             prefix_len;
427         gboolean        found_mask = FALSE;
428
429         while ( length > 0 ) {
430                 if (length<12) {
431                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
432                                 "short IP reachability (%d vs 12)", length );
433                         return;
434                 }
435                 /*
436                  * Gotta build a sub-tree for all our pieces
437                  */
438                 if ( tree ) {
439                         src = tvb_get_ipv4(tvb, offset+4);
440                         mask = tvb_get_ntohl(tvb, offset+8);
441
442                         /* find out if the mask matches one of 33 possible prefix lengths */
443                         bitmask = 0xffffffff;
444                         for(prefix_len = 32; prefix_len >= 0; prefix_len--) {
445                                 if (bitmask==mask) {
446                                         found_mask = TRUE;
447                                         break;
448                                 }
449                                 bitmask = bitmask << 1;
450                         }
451
452                         /* If we have a discontiguous netmask, dump the mask, otherwise print the prefix_len */
453                         /* XXX - We should probably have some sort of netmask_to_str() routine in to_str.c that does this. */
454
455                         if(found_mask) {
456                           ti = proto_tree_add_ipv4_format_value( tree, hf_isis_lsp_ip_reachability_ipv4_prefix, tvb, offset, 12,
457                                 src, "%s/%d", ip_to_str((guint8*)&src), prefix_len );
458                         } else {
459                           ti = proto_tree_add_ipv4_format_value( tree, hf_isis_lsp_ip_reachability_ipv4_prefix, tvb, offset, 12,
460                                 src, "%s mask %s", ip_to_str((guint8*)&src), tvb_ip_to_str(tvb, offset+8));
461                         };
462
463                         ntree = proto_item_add_subtree(ti, ett_isis_lsp_clv_ip_reachability);
464
465                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_default_metric, tvb, offset, 1, ENC_NA);
466                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_default_metric_ie, tvb, offset, 1, ENC_NA);
467                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_distribution, tvb, offset, 1, ENC_NA);
468
469                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_delay_metric, tvb, offset+1, 1, ENC_NA);
470                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_delay_metric_support, tvb, offset+1, 1, ENC_NA);
471                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_delay_metric_ie, tvb, offset+1, 1, ENC_NA);
472
473                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_expense_metric, tvb, offset+2, 1, ENC_NA);
474                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_expense_metric_support, tvb, offset+2, 1, ENC_NA);
475                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_expense_metric_ie, tvb, offset+2, 1, ENC_NA);
476
477                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_error_metric, tvb, offset+3, 1, ENC_NA);
478                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_error_metric_support, tvb, offset+3, 1, ENC_NA);
479                         proto_tree_add_item(ntree, hf_isis_lsp_ip_reachability_error_metric_ie, tvb, offset+3, 1, ENC_NA);
480                 }
481                 offset += 12;
482                 length -= 12;
483         }
484 }
485
486 /*
487  * Name: dissect_ipreach_subclv ()
488  *
489  * Description: parses IP reach subTLVs
490  *              Called by various IP Reachability dissectors.
491  *
492  * Input:
493  *   tvbuff_t * : tvbuffer for packet data
494  *   proto_tree * : protocol display tree to fill out.
495  *   int : offset into packet data where we are (beginning of the sub_clv value).
496  *
497  * Output:
498  *   void
499  */
500 static void
501 dissect_ipreach_subclv(tvbuff_t *tvb, proto_tree *tree, int offset, int clv_code, int clv_len)
502 {
503
504         switch (clv_code) {
505         case 1:
506                 while (clv_len >= 4) {
507                         proto_tree_add_item(tree, hf_isis_lsp_32_bit_administrative_tag, tvb, offset, 4, ENC_BIG_ENDIAN);
508                         offset+=4;
509                         clv_len-=4;
510                 }
511                 break;
512         case 2:
513                 while (clv_len >= 8) {
514                         proto_tree_add_item(tree, hf_isis_lsp_64_bit_administrative_tag, tvb, offset, 8, ENC_BIG_ENDIAN);
515                         offset+=8;
516                         clv_len-=8;
517                 }
518                 break;
519
520                 default :
521                         proto_tree_add_text (tree, tvb, offset, clv_len+2,
522                                              "Unknown sub-TLV: code %u, length %u",
523                                              clv_code, clv_len );
524                         break;
525         }
526 }
527
528
529 /*
530  * Name: dissect_lsp_ext_ip_reachability_clv()
531  *
532  * Description: Decode an Extended IP Reachability CLV - code 135.
533  *
534  *   The extended IP reachability TLV is an extended version
535  *   of the IP reachability TLVs (codes 128 and 130). It encodes
536  *   the metric as a 32-bit unsigned interger and allows to add
537  *   sub-CLV(s).
538  *
539  *   CALLED BY TLV 235 DISSECTOR
540  *
541  *
542  * Input:
543  *   tvbuff_t * : tvbuffer for packet data
544  *   proto_tree * : proto tree to build on (may be null)
545  *   int : current offset into packet data
546  *   int : length of IDs in packet.
547  *   int : length of this clv
548  *
549  * Output:
550  *   void, will modify proto_tree if not null.
551  */
552 static void
553 dissect_lsp_ext_ip_reachability_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree,
554         int offset, int id_length _U_, int length)
555 {
556         proto_tree *subtree = NULL;
557         proto_tree *subtree2 = NULL;
558         guint8     ctrl_info;
559         guint      bit_length;
560         int        byte_length;
561         guint8     prefix [4];
562         guint      len,i;
563         guint      subclvs_len;
564         guint      clv_code, clv_len;
565
566         if (!tree) return;
567
568         while (length > 0) {
569                 ctrl_info = tvb_get_guint8(tvb, offset+4);
570                 bit_length = ctrl_info & 0x3f;
571                 byte_length = ipv4_addr_and_mask(tvb, offset+5, prefix, bit_length);
572                 if (byte_length == -1) {
573                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
574                                 "IPv4 prefix has an invalid length: %d bits", bit_length );
575                                 return;
576                         }
577                 subclvs_len = 0;
578                 if ((ctrl_info & 0x40) != 0)
579                         subclvs_len = 1+tvb_get_guint8(tvb, offset+5+byte_length);
580
581                 /* open up a new tree per prefix */
582                 subtree = proto_tree_add_subtree(tree, tvb, offset, 5+byte_length+subclvs_len,
583                             ett_isis_lsp_part_of_clv_ext_ip_reachability, NULL, "Ext. IP Reachability");
584
585                 proto_tree_add_ipv4_format_value(subtree, hf_isis_lsp_ext_ip_reachability_ipv4_prefix, tvb, offset+5, byte_length,
586                              tvb_get_ntohl(tvb, offset+5), "%s/%u", ip_to_str (prefix), bit_length);
587                 proto_tree_add_item(subtree, hf_isis_lsp_ext_ip_reachability_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
588                 proto_tree_add_item(subtree, hf_isis_lsp_ext_ip_reachability_distribution, tvb, offset+4, 1, ENC_NA);
589
590                 len = 5 + byte_length;
591                 if ((ctrl_info & 0x40) != 0) {
592                         subclvs_len = tvb_get_guint8(tvb, offset+len);
593                         subtree2 = proto_tree_add_subtree_format(subtree, tvb, offset+len, subclvs_len+1,
594                                       ett_isis_lsp_clv_ip_reach_subclv, NULL,
595                                       "sub-TLVs present, total length: %u bytes", subclvs_len);
596                         i =0;
597                         while (i < subclvs_len) {
598                                 clv_code = tvb_get_guint8(tvb, offset+len+1); /* skip the total subtlv len indicator */
599                                 clv_len  = tvb_get_guint8(tvb, offset+len+2);
600
601                                 /*
602                                  * we pass on now the raw data to the ipreach_subtlv dissector
603                                  * therefore we need to skip 3 bytes
604                                  * (total subtlv len, subtlv type, subtlv len)
605                                  */
606                                 dissect_ipreach_subclv(tvb, subtree2, offset+len+3, clv_code, clv_len);
607                                 i += clv_len + 2;
608                         }
609                         len += 1 + subclvs_len;
610                 } else {
611                         proto_tree_add_text (subtree, tvb, offset+4, len, "no sub-TLVs present");
612                 }
613
614                 offset += len;
615                 length -= len;
616         }
617 }
618
619 /*
620  * Name: dissect_isis_grp_address_clv()
621  *
622  * Description: Decode GROUP ADDRESS subTLVs
623  *              The  Group Address  TLV is composed of 1 octet for the type,
624  *              1 octet that specifies the number of bytes in the value field, and a
625  *              Variable length value field that can have any or all of the subTLVs that are listed in the
626  *              - below section
627  *
628  *Input:
629  *   tvbuff_t * : tvbuffer for packet data
630  *   proto_tree * : proto tree to build on (may be null)
631  *   int : current offset into packet data
632  *   int : length of IDs in packet.
633  *   int : length of this clv
634  *
635  * Output:
636  *   void, will modify proto_tree if not null.
637  */
638
639 static void
640 dissect_isis_grp_address_clv(tvbuff_t *tvb, packet_info* pinfo _U_, proto_tree *tree, int offset,
641         int tree_id,int length)
642 {
643         gint len;
644         gint source_num;
645         gint k=1;
646         guint16 mt_block;
647         guint64 hmac_src;
648         guint16 swid = 0;
649         guint16 sswid = 0;
650         guint16 lid = 0;
651
652         proto_tree *rt_tree=NULL;
653
654         while (length>0) {
655                 /* fetch two bytes */
656                 mt_block=tvb_get_ntohs(tvb, offset);
657                 /* Mask out the lower 8 bits */
658                 switch((mt_block&0xff00)>>8) {
659
660
661                         case GRP_MAC_ADDRESS:
662                                 rt_tree = proto_tree_add_subtree(tree, tvb, offset, (mt_block&0x00ff)+2,
663                     ett_isis_lsp_clv_grp_address_IPv4_prefx, NULL, "GROUP MAC ADDRESS SUB TLV");
664
665                                 length--;
666                                 offset++;
667
668                                 len=tvb_get_guint8(tvb, offset);/* 1 byte fetched displays the length*/
669                                 proto_tree_add_item(rt_tree, hf_isis_lsp_grp_address_length, tvb, offset, 1, ENC_NA);
670
671                                 if(len < 5) {
672                                         length -= len;
673                                         offset += len;
674                                         break;
675                                 }
676
677                                 length--;
678                                 offset++;
679
680                                 proto_tree_add_item(rt_tree, hf_isis_lsp_grp_address_topology_id, tvb, offset, 2, ENC_BIG_ENDIAN);
681
682                                 length -= 2;
683                                 offset += 2;
684                                 len -= 2;
685
686                                 proto_tree_add_item(rt_tree, hf_isis_lsp_grp_address_vlan_id, tvb, offset, 2, ENC_BIG_ENDIAN);
687
688                                 length -= 2;
689                                 offset += 2;
690                                 len -= 2;
691
692                                 proto_tree_add_item(rt_tree, hf_isis_lsp_grp_address_number_of_records, tvb, offset, 1, ENC_NA);
693
694                                 length--;
695                                 offset++;
696                                 len--;
697
698                                 while(len > 0) {
699
700                                         source_num=tvb_get_guint8(tvb, offset);
701                                         proto_tree_add_item(rt_tree, hf_isis_lsp_grp_address_number_of_sources, tvb, offset, 1, ENC_NA);
702
703                                         length--;
704                                         offset++;
705                                         len--;
706
707                                         hmac_src=tvb_get_ntoh48(tvb, offset);/* Fetch the data in the next two bytes for display*/
708
709                                         fp_get_hmac_addr (hmac_src, &swid, &sswid, &lid);
710                                         proto_tree_add_bytes_format_value(rt_tree, hf_isis_lsp_grp_address_group_address, tvb, offset, 6,
711                                                 tvb_get_ptr(tvb, offset, 6), "%04x.%04x.%04x", swid, sswid, lid );
712
713                                         length -= 6;
714                                         offset += 6;
715                                         len -= 6;
716
717                                         while((len > 0) && (source_num > 0)) {
718                                                 hmac_src = tvb_get_ntoh48 (tvb, offset);
719                                                 fp_get_hmac_addr (hmac_src, &swid, &sswid, &lid);
720                                                 proto_tree_add_bytes_format(rt_tree, hf_isis_lsp_grp_address_source_address, tvb, offset, 6,
721                                                 tvb_get_ptr(tvb, offset, 6), "Source Address (%d):%04x.%04x.%04x",
722                                                 k, swid, sswid, lid);
723
724                                                 k++;
725                                                 length -= 6;
726                                                 offset += 6;
727                                                 len -= 6;
728                                                 source_num--;
729                                         }
730                                 }
731
732                                 break;
733
734
735                         default:
736                                 proto_tree_add_uint_format ( tree, tree_id, tvb, offset,(mt_block&0x00ff)+2,
737                                                 mt_block, "INVALID SUB TLV");
738                                 offset++;
739                                 length -= (2+tvb_get_guint8(tvb, offset));
740                                 offset += (1+tvb_get_guint8(tvb, offset));
741                                 break;
742                 }
743         }
744 }
745
746 /*
747  * Name: dissect_isis_rt_capable_clv()
748  *
749  * Description: Decode RouterCapability subTLVs
750  *
751  *   The Router Capability TLV is composed of 1 octet for the type,
752  *   1 octet that specifies the number of bytes in the value field, and a
753  *   variable length value field that can have any or all of the subTLVs
754  *   that are listed in the below section
755  *
756  * Input:
757  *   tvbuff_t * : tvbuffer for packet data
758  *   proto_tree * : proto tree to build on (may be null)
759  *   int : current offset into packet data
760  *   int : length of IDs in packet.
761  *   int : length of this clv
762  *   len : local variable described to handle the length of the subTLV
763  *
764  * Output:
765  *   void, will modify proto_tree if not null.
766  */
767
768 /* As per RFC 6326 section 2.3 */
769 static void
770 dissect_isis_rt_capable_clv(tvbuff_t *tvb, packet_info* pinfo _U_,
771         proto_tree *tree, int offset, int id_length _U_, int length)
772 {
773         gint len;
774         guint16 rt_block;
775         proto_tree *rt_tree;
776
777         gint root_id = 1;       /* To display the root id */
778         gint sec_vlan_id = 1;   /* To display the seconadary VLAN id */
779         length = length - 5;    /* Ignoring the 5 reserved bytes */
780         offset = offset + 5;
781
782         while (length>1) {
783                 /* fetch two bytes */
784                 rt_block = tvb_get_ntohs(tvb, offset);
785
786                 /* Mask out the lower 8 bits */
787                 switch ((rt_block&0xff00)>>8) {
788
789                 case TRILL_VERSION:
790                         rt_tree = proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
791                         ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "TRILL version sub tlv");
792
793                         length--;
794                         offset++;
795
796                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_trill_length, tvb, offset, 1, ENC_NA);
797                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_trill_maximum_version, tvb, offset+1, 1, ENC_NA);
798
799                         length -= 2;
800                         offset += 2;
801
802                         break;
803
804                 case TREES:
805                         rt_tree = proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
806                                 ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "Trees sub tlv");
807
808                         length--;
809                         offset++;
810
811                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_trees_length, tvb, offset, 1, ENC_NA);
812
813                         length--;
814                         offset++;
815
816                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_trees_nof_trees_to_compute, tvb, offset, 2, ENC_BIG_ENDIAN);
817
818                         length -= 2;
819                         offset += 2;
820
821                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_trees_maximum_nof_trees_to_compute, tvb, offset, 2, ENC_BIG_ENDIAN);
822
823                         length -= 2;
824                         offset += 2;
825
826                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_trees_nof_trees_to_use, tvb, offset, 2, ENC_BIG_ENDIAN);
827
828                         length -= 2;
829                         offset += 2;
830                         break;
831
832                 case TREE_IDENTIFIER:
833                         rt_tree=proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
834                                 ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "Tree root identifier sub tlv");
835
836                         length--;
837                         offset++;
838
839                         len = tvb_get_guint8(tvb, offset);
840                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_tree_root_id_length, tvb, offset, 1, ENC_NA);
841
842                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_tree_root_id_starting_tree_no, tvb, offset+1, 2, ENC_BIG_ENDIAN);
843
844                         len -= 2;
845                         length -= 2;
846                         offset += 2;
847
848                         while (len>1) {
849                                 rt_block = tvb_get_ntohs(tvb, offset);
850                                 proto_tree_add_uint_format(rt_tree, hf_isis_lsp_rt_capable_tree_root_id_nickname, tvb, offset, 2,
851                                            rt_block, "Nickname(%dth root): %d", root_id, rt_block);
852                                 root_id++;
853                                 len -= 2;
854                                 length -= 2;
855                                 offset += 2;
856                         }
857                         break;
858
859                 case NICKNAME:
860                         rt_tree = proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
861                                 ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "The nickname sub tlv");
862
863                         length--;
864                         offset++;
865                         len = tvb_get_guint8(tvb, offset);
866
867                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_nickname_length, tvb, offset, 1, ENC_NA);
868                         length--;
869                         offset++;
870
871                         while (len>0) {
872                                 proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_nickname_nickname_priority, tvb, offset, 1, ENC_NA);
873                                 length--;
874                                 offset++;
875                                 len--;
876
877                                 proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_nickname_tree_root_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
878                                 len -= 2;
879                                 length -= 2;
880                                 offset += 2;
881
882                                 proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_nickname_nickname, tvb, offset, 2, ENC_BIG_ENDIAN);
883                                 length = length-2;
884                                 offset = offset+2;
885                                 len = len-2;
886                         }
887                         break;
888
889                 case INTERESTED_VLANS:
890                         rt_tree = proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
891                             ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "Interested VLAN and spanning tree root sub tlv");
892
893                         length--;
894                         offset++;
895
896                         len = tvb_get_guint8(tvb, offset);
897                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_length, tvb, offset, 1, ENC_NA);
898                         length--;
899                         offset++;
900                         len--;
901
902                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_nickname, tvb, offset, 2, ENC_BIG_ENDIAN);
903                         len -= 2;
904                         length -= 2;
905                         offset += 2;
906
907                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_multicast_ipv4, tvb, offset, 2, ENC_BIG_ENDIAN);
908                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_multicast_ipv6, tvb, offset, 2, ENC_BIG_ENDIAN);
909                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_vlan_start_id, tvb, offset, 2, ENC_BIG_ENDIAN);
910                         len -= 2;
911                         length -= 2;
912                         offset += 2;
913
914                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_vlan_end_id, tvb, offset, 2, ENC_BIG_ENDIAN);
915                         len -= 2;
916                         length -= 2;
917                         offset += 2;
918
919                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_interested_vlans_afs_lost_counter, tvb, offset, 4, ENC_BIG_ENDIAN);
920                         length -= 4;
921                         offset += 4;
922                         len -= 4;
923
924                         while (len>0) {
925                                 proto_tree_add_item(rt_tree, hf_isis_lsp_root_id, tvb, offset, 6, ENC_BIG_ENDIAN);
926
927                                 length -= 6;
928                                 offset += 6;
929                                 len -= 6;
930                         }
931                         break;
932
933                 case TREES_USED_IDENTIFIER:
934                         rt_tree = proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
935                         ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "Trees used identifier sub tlv");
936
937                         length--;
938                         offset++;
939
940                         len = tvb_get_guint8(tvb, offset);
941                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_tree_used_id_length, tvb, offset, 1, ENC_NA);
942
943                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_tree_used_id_starting_tree_no, tvb, offset+1, 2, ENC_BIG_ENDIAN);
944                         len -= 2;
945                         length += 2;
946                         offset += 3;
947                         root_id = 1;
948
949                         while (len>0) {
950                                 rt_block = tvb_get_ntohs(tvb, offset);
951                                 proto_tree_add_uint_format(rt_tree, hf_isis_lsp_rt_capable_tree_used_id_nickname, tvb, offset,2,
952                                 rt_block, "Nickname(%dth root): %d", root_id, rt_block);
953                                 root_id++;
954
955                                 len -= 2;
956                                 offset += 2;
957                                 length -= 2;
958                         }
959                         break;
960
961                 case VLAN_GROUP:
962                         rt_tree = proto_tree_add_subtree(tree, tvb, offset, (rt_block&0x00ff)+2,
963                             ett_isis_lsp_clv_rt_capable_IPv4_prefx, NULL, "The VLAN group sub tlv");
964
965                         length--;
966                         offset++;
967
968                         len = tvb_get_guint8(tvb, offset);
969                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_vlan_group_length, tvb, offset, 1, ENC_NA);
970
971                         len--;
972                         length--;
973                         offset++;
974
975                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_vlan_group_primary_vlan_id, tvb, offset, 2, ENC_BIG_ENDIAN);
976
977                         len -= 2;
978                         offset += 2;
979                         length -= 2;
980
981                         proto_tree_add_item(rt_tree, hf_isis_lsp_rt_capable_vlan_group_secondary_vlan_id, tvb, offset, 2, ENC_BIG_ENDIAN);
982
983                         len -= 2;
984                         offset += 2;
985                         length -= 2;
986                         sec_vlan_id = 1;
987
988                         while (len>0) {
989                                 rt_block = tvb_get_ntohs(tvb, offset);
990
991                                 proto_tree_add_uint_format(rt_tree, hf_isis_lsp_rt_capable_vlan_group_nth_secondary_vlan_id, tvb, offset, 2,
992                                            rt_block, "%dth secondary vlan id: %x", sec_vlan_id, rt_block);
993
994                                 length -= 2;
995                                 offset += 2;
996                                 sec_vlan_id++;
997                                 len -= 2;
998                         }
999                         break;
1000
1001                 default:
1002                         proto_tree_add_text(tree, tvb, offset, (rt_block&0x00ff)+2, "INVALID sub tlv");
1003
1004                         offset++;
1005                         length -= (2+tvb_get_guint8(tvb, offset));
1006                         offset += (1+tvb_get_guint8(tvb, offset));
1007                         break;
1008                 }
1009         }
1010 }
1011
1012
1013
1014
1015 /*
1016  * Name: dissect_lsp_ipv6_reachability_clv()
1017  *
1018  * Description: Decode an IPv6 reachability CLV - code 236.
1019  *
1020  *   CALLED BY TLV 237 DISSECTOR
1021  *
1022  * Input:
1023  *   tvbuff_t * : tvbuffer for packet data
1024  *   proto_tree * : proto tree to build on (may be null)
1025  *   int : current offset into packet data
1026  *   int : length of IDs in packet.
1027  *   int : length of this clv
1028  *
1029  * Output:
1030  *   void, will modify proto_tree if not null.
1031  */
1032 static void
1033 dissect_lsp_ipv6_reachability_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1034         int id_length _U_, int length)
1035 {
1036         proto_tree        *subtree = NULL;
1037         proto_tree        *subtree2 = NULL;
1038         guint8            ctrl_info;
1039         guint             bit_length;
1040         int               byte_length;
1041         struct e_in6_addr prefix;
1042         guint             len,i;
1043         guint             subclvs_len;
1044         guint             clv_code, clv_len;
1045
1046         if (!tree) return;
1047
1048         while (length > 0) {
1049                 ctrl_info = tvb_get_guint8(tvb, offset+4);
1050                 bit_length = tvb_get_guint8(tvb, offset+5);
1051                 byte_length = ipv6_addr_and_mask(tvb, offset+6, &prefix, bit_length);
1052                 if (byte_length == -1) {
1053                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1054                                 "IPv6 prefix has an invalid length: %d bits", bit_length );
1055                                 return;
1056                         }
1057                 subclvs_len = 0;
1058                 if ((ctrl_info & 0x20) != 0)
1059                         subclvs_len = 1+tvb_get_guint8(tvb, offset+6+byte_length);
1060
1061                 subtree = proto_tree_add_subtree(tree, tvb, offset, 6+byte_length+subclvs_len,
1062             ett_isis_lsp_part_of_clv_ipv6_reachability, NULL, "IPv6 Reachability");
1063
1064                 proto_tree_add_ipv6_format_value(subtree, hf_isis_lsp_ipv6_reachability_ipv6_prefix, tvb, offset+6, byte_length,
1065                              (guint8*)&prefix, "IPv6 prefix: %s/%u", ip6_to_str (&prefix), bit_length);
1066
1067                 proto_tree_add_item(subtree, hf_isis_lsp_ipv6_reachability_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
1068                 proto_tree_add_item(subtree, hf_isis_lsp_ipv6_reachability_distribution, tvb, offset+4, 1, ENC_NA);
1069                 proto_tree_add_item(subtree, hf_isis_lsp_ipv6_reachability_distribution_internal, tvb, offset+4, 1, ENC_NA);
1070
1071                 if ((ctrl_info & 0x1f) != 0) {
1072                         proto_tree_add_item(subtree, hf_isis_lsp_ipv6_reachability_reserved_bits, tvb, offset+4, 1, ENC_NA);
1073                 }
1074
1075                 len = 6 + byte_length;
1076                 if ((ctrl_info & 0x20) != 0) {
1077                         subclvs_len = tvb_get_guint8(tvb, offset+len);
1078                         subtree2 = proto_tree_add_subtree_format(subtree, tvb, offset+len, subclvs_len+1,
1079                                       ett_isis_lsp_clv_ip_reach_subclv, NULL, "sub-TLVs present, total length: %u bytes",
1080                                                   subclvs_len);
1081
1082                         i =0;
1083                         while (i < subclvs_len) {
1084                                 clv_code = tvb_get_guint8(tvb, offset+len+1); /* skip the total subtlv len indicator */
1085                                 clv_len  = tvb_get_guint8(tvb, offset+len+2);
1086                                 dissect_ipreach_subclv(tvb, subtree2, offset+len+3, clv_code, clv_len);
1087                                 i += clv_len + 2;
1088                         }
1089                         len += 1 + subclvs_len;
1090                 } else {
1091                         proto_tree_add_text (subtree, tvb, offset+4, len, "no sub-TLVs present");
1092                 }
1093                 offset += len;
1094                 length -= len;
1095         }
1096 }
1097
1098 /*
1099  * Name: dissect_lsp_nlpid_clv()
1100  *
1101  * Description:
1102  *      Decode for a lsp packets NLPID clv.  Calls into the
1103  *      clv common one.
1104  *
1105  * Input:
1106  *      tvbuff_t * : tvbuffer for packet data
1107  *      proto_tree * : proto tree to build on (may be null)
1108  *      int : current offset into packet data
1109  *      int : length of IDs in packet.
1110  *      int : length of this clv
1111  *
1112  * Output:
1113  *      void, will modify proto_tree if not null.
1114  */
1115 static void
1116 dissect_lsp_nlpid_clv(tvbuff_t *tvb, packet_info* pinfo _U_, proto_tree *tree, int offset,
1117         int id_length _U_, int length)
1118 {
1119         isis_dissect_nlpid_clv(tvb, tree, offset, length);
1120 }
1121
1122 /*
1123  * Name: dissect_lsp_mt_clv()
1124  *
1125  * Description: - code 229
1126  *      Decode for a lsp packets Multi Topology clv.  Calls into the
1127  *      clv common one.
1128  *
1129  * Input:
1130  *      tvbuff_t * : tvbuffer for packet data
1131  *      proto_tree * : proto tree to build on (may be null)
1132  *      int : current offset into packet data
1133  *      guint : length of this clv
1134  *      int : length of IDs in packet.
1135  *
1136  * Output:
1137  *      void, will modify proto_tree if not null.
1138  */
1139 static void
1140 dissect_lsp_mt_clv(tvbuff_t *tvb, packet_info* pinfo _U_, proto_tree *tree, int offset,
1141         int id_length _U_, int length)
1142 {
1143         isis_dissect_mt_clv(tvb, tree, offset, length, hf_isis_lsp_clv_mt );
1144 }
1145
1146 /*
1147  * Name: dissect_lsp_hostname_clv()
1148  *
1149  * Description:
1150  *      Decode for a lsp packets hostname clv.  Calls into the
1151  *      clv common one.
1152  *
1153  * Input:
1154  *      tvbuff_t * : tvbuffer for packet data
1155  *      proto_tree * : proto tree to build on (may be null)
1156  *      int : current offset into packet data
1157  *      int : length of IDs in packet.
1158  *      int : length of this clv
1159  *
1160  * Output:
1161  *      void, will modify proto_tree if not null.
1162  */
1163 static void
1164 dissect_lsp_hostname_clv(tvbuff_t *tvb, packet_info* pinfo _U_, proto_tree *tree, int offset,
1165         int id_length _U_, int length)
1166 {
1167         isis_dissect_hostname_clv(tvb, tree, offset, length,
1168                 hf_isis_lsp_hostname);
1169 }
1170
1171
1172 /*
1173  * Name: dissect_lsp_te_router_id_clv()
1174  *
1175  * Description:
1176  *      Decode for a lsp packets Traffic Engineering ID clv.  Calls into the
1177  *      clv common one.
1178  *
1179  * Input:
1180  *      tvbuff_t * : tvbuffer for packet data
1181  *      proto_tree * : proto tree to build on (may be null)
1182  *      int : current offset into packet data
1183  *      int : length of IDs in packet.
1184  *      int : length of this clv
1185  *
1186  * Output:
1187  *      void, will modify proto_tree if not null.
1188  */
1189 static void
1190 dissect_lsp_te_router_id_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1191         int id_length _U_, int length)
1192 {
1193         isis_dissect_te_router_id_clv(tree, pinfo, tvb, &ei_isis_lsp_short_packet, offset, length,
1194                 hf_isis_lsp_clv_te_router_id );
1195 }
1196
1197
1198 /*
1199  * Name: dissect_lsp_ip_int_addr_clv()
1200  *
1201  * Description:
1202  *      Decode for a lsp packets ip interface addr clv.  Calls into the
1203  *      clv common one.
1204  *
1205  * Input:
1206  *      tvbuff_t * : tvbuffer for packet data
1207  *      proto_tree * : proto tree to build on (may be null)
1208  *      int : current offset into packet data
1209  *      int : length of IDs in packet.
1210  *      int : length of this clv
1211  *
1212  * Output:
1213  *      void, will modify proto_tree if not null.
1214  */
1215 static void
1216 dissect_lsp_ip_int_addr_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1217         int id_length _U_, int length)
1218 {
1219         isis_dissect_ip_int_clv(tree, pinfo, tvb, &ei_isis_lsp_short_packet, offset, length,
1220                 hf_isis_lsp_clv_ipv4_int_addr );
1221 }
1222
1223 /*
1224  * Name: dissect_lsp_ipv6_int_addr_clv()
1225  *
1226  * Description: Decode an IPv6 interface addr CLV - code 232.
1227  *
1228  *   Calls into the clv common one.
1229  *
1230  * Input:
1231  *   tvbuff_t * : tvbuffer for packet data
1232  *   proto_tree * : proto tree to build on (may be null)
1233  *   int : current offset into packet data
1234  *   int : length of IDs in packet.
1235  *   int : length of this clv
1236  *
1237  * Output:
1238  *   void, will modify proto_tree if not null.
1239  */
1240 static void
1241 dissect_lsp_ipv6_int_addr_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1242         int id_length _U_, int length)
1243 {
1244         isis_dissect_ipv6_int_clv(tree, pinfo, tvb, &ei_isis_lsp_short_packet, offset, length,
1245                 hf_isis_lsp_clv_ipv6_int_addr );
1246 }
1247
1248 static void
1249 dissect_isis_lsp_clv_mt_cap_spb_instance(tvbuff_t *tvb, packet_info *pinfo,
1250         proto_tree *tree, int offset, int subtype, int sublen)
1251 {
1252         const int CIST_ROOT_ID_LEN            = 8; /* CIST Root Identifier */
1253         const int CIST_EXT_ROOT_PATH_COST_LEN = 4; /* CIST External Root Path Cost */
1254         const int BRIDGE_PRI_LEN              = 2; /* Bridge Priority */
1255         const int V_SPSOURCEID_LEN            = 4; /* v | SPSourceID */
1256         const int NUM_TREES_LEN               = 1; /* num of trees */
1257
1258         const int CIST_ROOT_ID_OFFSET = 0;
1259         const int CIST_EXT_ROOT_PATH_COST_OFFSET = CIST_ROOT_ID_OFFSET            + CIST_ROOT_ID_LEN;
1260         const int BRIDGE_PRI_OFFSET              = CIST_EXT_ROOT_PATH_COST_OFFSET + CIST_EXT_ROOT_PATH_COST_LEN;
1261         const int V_SPSOURCEID_OFFSET            = BRIDGE_PRI_OFFSET              + BRIDGE_PRI_LEN;
1262         const int NUM_TREES_OFFSET               = V_SPSOURCEID_OFFSET            + V_SPSOURCEID_LEN;
1263         const int FIXED_LEN                      = NUM_TREES_OFFSET               + NUM_TREES_LEN;
1264         const int VLAN_ID_TUPLE_LEN = 8;
1265
1266         if (sublen < FIXED_LEN) {
1267                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1268                                       "Short SPB Digest subTLV (%d vs %d)", sublen, FIXED_LEN);
1269                 return;
1270         }
1271         else {
1272                 proto_tree *subtree, *ti;
1273                 int subofs = offset;
1274                 const guint8 *cist_root_identifier = tvb_get_ptr   (tvb, subofs + CIST_ROOT_ID_OFFSET, CIST_ROOT_ID_LEN);
1275                 guint8        num_trees            = tvb_get_guint8(tvb, subofs + NUM_TREES_OFFSET);
1276
1277                 /*************************/
1278                 subtree = proto_tree_add_subtree_format( tree, tvb, offset-2, sublen+2, ett_isis_lsp_clv_mt_cap_spb_instance, NULL,
1279                                           "SPB Instance: Type: 0x%02x, Length: %d", subtype, sublen);
1280
1281                 /*************************/
1282                 proto_tree_add_bytes_format_value( subtree, hf_isis_lsp_mt_cap_spb_instance_cist_root_identifier, tvb, subofs + CIST_ROOT_ID_OFFSET, CIST_ROOT_ID_LEN,
1283                                      cist_root_identifier, "%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x",
1284                                      cist_root_identifier[0], cist_root_identifier[1], cist_root_identifier[2],
1285                                      cist_root_identifier[3], cist_root_identifier[4], cist_root_identifier[5],
1286                                      cist_root_identifier[6], cist_root_identifier[7]);
1287                 proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spb_instance_cist_external_root_path_cost, tvb, subofs + CIST_EXT_ROOT_PATH_COST_OFFSET, CIST_EXT_ROOT_PATH_COST_LEN, ENC_BIG_ENDIAN);
1288                 proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spb_instance_bridge_priority, tvb, subofs + BRIDGE_PRI_OFFSET, BRIDGE_PRI_LEN, ENC_BIG_ENDIAN);
1289
1290                 proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spb_instance_v, tvb, subofs + V_SPSOURCEID_OFFSET, V_SPSOURCEID_LEN, ENC_BIG_ENDIAN);
1291
1292                 proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spsourceid, tvb, subofs + V_SPSOURCEID_OFFSET, V_SPSOURCEID_LEN, ENC_BIG_ENDIAN);
1293                 ti = proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spb_instance_number_of_trees, tvb, subofs + NUM_TREES_OFFSET, NUM_TREES_LEN, ENC_BIG_ENDIAN);
1294                 if (num_trees == 0)
1295                         proto_item_append_text(ti, " Invalid subTLV: zero trees");
1296
1297                 subofs += FIXED_LEN;
1298                 sublen -= FIXED_LEN;
1299
1300                 /*************************/
1301                 if (sublen != (num_trees * VLAN_ID_TUPLE_LEN)) {
1302                         proto_tree_add_text( subtree, tvb, subofs, 0,
1303                                              "SubTLV length doesn't match number of trees");
1304                         return;
1305                 }
1306                 while (sublen > 0 && num_trees > 0) {
1307                         if (sublen < VLAN_ID_TUPLE_LEN) {
1308                                 proto_tree_add_expert_format(subtree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1309                                                       "Short VLAN_ID entry (%d vs %d)", sublen, VLAN_ID_TUPLE_LEN);
1310                                 return;
1311                         }
1312                         else {
1313                                 const guint8 flags       = tvb_get_guint8(tvb, subofs);
1314                                 const guint8 *ect_id     = tvb_get_ptr(tvb, subofs + 1, 4);
1315                                 const guint8 *bvid_spvid = tvb_get_ptr(tvb, subofs + 1 + 4, 3);
1316                                 const guint16 bvid       = (0xff0 & (((guint16)bvid_spvid[0]) << 4)) | (0x0f & (bvid_spvid[1] >> 4));
1317                                 const guint16 spvid      = (0xf00 & (((guint16)bvid_spvid[1]) << 8)) | (0xff & (bvid_spvid[2]));
1318                                 proto_tree_add_text( subtree, tvb, subofs, VLAN_ID_TUPLE_LEN,
1319                                                      "  U: %u, M: %u, A: %u, ECT: %02x-%02x-%02x-%02x, BVID: 0x%03x (%d),%s SPVID: 0x%03x (%d)",
1320                                                      (flags >> 7) & 1,
1321                                                      (flags >> 6) & 1,
1322                                                      (flags >> 5) & 1,
1323                                                      ect_id[0], ect_id[1], ect_id[2], ect_id[3],
1324                                                      bvid, bvid,
1325                                                      (  bvid < 10   ? "   "
1326                                                       : bvid < 100  ? "  "
1327                                                       : bvid < 1000 ? " "
1328                                                       : ""),
1329                                                      spvid, spvid);
1330                                 subofs += VLAN_ID_TUPLE_LEN;
1331                                 sublen -= VLAN_ID_TUPLE_LEN;
1332                                 --num_trees;
1333                         }
1334                 }
1335                 if (num_trees) {
1336                         proto_tree_add_expert_format(subtree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1337                                               "Short subTLV (%d vs %d)", sublen, num_trees * VLAN_ID_TUPLE_LEN);
1338                         return;
1339                 }
1340         }
1341 }
1342 static void
1343 dissect_isis_lsp_clv_mt_cap_spb_oalg(tvbuff_t   *tvb,
1344         proto_tree *tree, int offset, int subtype, int sublen)
1345 {
1346         proto_tree_add_text( tree, tvb, offset, -1,
1347                               "MT-Cap SPB Opaque Algorithm: Type: 0x%02x, Length: %d", subtype, sublen);
1348 }
1349 static void
1350 dissect_isis_lsp_clv_mt_cap_spbm_service_identifier(tvbuff_t *tvb, packet_info *pinfo,
1351         proto_tree *tree, int offset, int subtype, int sublen)
1352 {
1353         const int BMAC_LEN = 6; /* B-MAC Address */
1354         const int BVID_LEN = 2; /* Base-VID */
1355
1356         const int BMAC_OFFSET = 0;
1357         const int BVID_OFFSET = BMAC_OFFSET + BMAC_LEN;
1358         const int FIXED_LEN   = BVID_OFFSET + BVID_LEN;
1359
1360         const int ISID_LEN = 4;
1361
1362         if (sublen < FIXED_LEN) {
1363                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1364                                       "Short SPBM Service Identifier and Unicast Address subTLV (%d vs %d)", sublen, FIXED_LEN);
1365                 return;
1366         }
1367         else {
1368                 proto_tree *subtree;
1369                 int subofs = offset;
1370
1371                 /*************************/
1372                 subtree = proto_tree_add_subtree_format( tree, tvb, offset-2, sublen+2, ett_isis_lsp_clv_mt_cap_spbm_service_identifier, NULL,
1373                                           "SPB Service ID and Unicast Address: Type: 0x%02x, Length: %d", subtype, sublen);
1374
1375                 /*************************/
1376                 proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spbm_service_identifier_b_mac, tvb, subofs + BMAC_OFFSET, BMAC_LEN, ENC_NA);
1377                 proto_tree_add_item(subtree, hf_isis_lsp_mt_cap_spbm_service_identifier_base_vid, tvb, subofs + BVID_OFFSET, BVID_LEN, ENC_BIG_ENDIAN);
1378
1379                 subofs += FIXED_LEN;
1380                 sublen -= FIXED_LEN;
1381
1382                 /*************************/
1383                 while (sublen > 0) {
1384                         if (sublen < ISID_LEN) {
1385                                 proto_tree_add_expert_format(subtree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1386                                                       "Short ISID entry (%d vs %d)", sublen, ISID_LEN);
1387                                 return;
1388                         }
1389                         else {
1390                                 const guint32 isid = tvb_get_ntohl(tvb, subofs);
1391                                 proto_tree_add_text( subtree, tvb, subofs, ISID_LEN,
1392                                                      "  T: %u, R: %u, ISID: 0x%06x (%d)",
1393                                                      (isid >> 31) & 1,
1394                                                      (isid >> 30) & 1,
1395                                                      isid & 0x00ffffff,
1396                                                      isid & 0x00ffffff);
1397                                 subofs += ISID_LEN;
1398                                 sublen -= ISID_LEN;
1399                         }
1400                 }
1401         }
1402 }
1403 static void
1404 dissect_isis_lsp_clv_mt_cap_spbv_mac_address(tvbuff_t *tvb, packet_info *pinfo,
1405         proto_tree *tree, int offset, int subtype, int sublen)
1406 {
1407         guint16 fixed_data;
1408         guint16 spvid;
1409         guint8 sr_bit;
1410         const int GMAC_LEN = 6; /* GMAC Address */
1411         const int SPVID_LEN = 2; /* SPVID */
1412         const int MAC_TUPLE_LEN = 7;
1413
1414         const int SPVID_OFFSET = 0;
1415         const int FIXED_LEN    = SPVID_OFFSET + SPVID_LEN;
1416
1417         if (sublen < FIXED_LEN) {
1418                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1419                                       "Short SPBV Mac Address subTLV (%d vs %d)", sublen, FIXED_LEN);
1420                 return;
1421         }
1422         else {
1423                 proto_tree *subtree;
1424                 int subofs = offset;
1425                 fixed_data = tvb_get_ntohs(tvb, subofs);
1426                 spvid = (fixed_data & 0x0FFF);
1427                 sr_bit = (fixed_data & 0x3000) >> 12;
1428
1429                 /*************************/
1430                 subtree = proto_tree_add_subtree_format( tree, tvb, offset-2, sublen+2, ett_isis_lsp_clv_mt_cap_spbv_mac_address, NULL,
1431                                           "SPBV Mac Address: Type: 0x%02x, Length: %d", subtype, sublen);
1432
1433                 /*************************/
1434                 proto_tree_add_uint(subtree, hf_isis_lsp_spb_sr_bit,
1435                                             tvb, subofs, 1, sr_bit);
1436                 proto_tree_add_uint(subtree, hf_isis_lsp_spb_spvid,
1437                                                             tvb, subofs, 2, spvid);
1438
1439                 subofs += FIXED_LEN;
1440                 sublen -= FIXED_LEN;
1441
1442                 /*************************/
1443                 while (sublen > 0) {
1444                         if (sublen < MAC_TUPLE_LEN) {
1445                                 proto_tree_add_expert_format(subtree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1446                                                       "Short MAC Address entry (%d vs %d)", sublen, MAC_TUPLE_LEN);
1447                                 return;
1448                         }
1449                         else {
1450                                 const guint32 tr_bit = tvb_get_guint8(tvb, subofs);
1451                                 const guint8 *gmac   = tvb_get_ptr(tvb, subofs + 1, GMAC_LEN);
1452                                 proto_tree_add_text( subtree, tvb, subofs, MAC_TUPLE_LEN,
1453                                                      "  T: %u, R: %u, MAC: %02x-%02x-%02x-%02x-%02x-%02x",
1454                                                      (tr_bit >> 7) & 1,
1455                                                      (tr_bit >> 6) & 1,
1456                                                                          gmac[0],
1457                                                                          gmac[1],
1458                                                                          gmac[2],
1459                                                                          gmac[3],
1460                                                                          gmac[4],
1461                                                                          gmac[5]);
1462                                 subofs += MAC_TUPLE_LEN;
1463                                 sublen -= MAC_TUPLE_LEN;
1464                         }
1465                 }
1466         }
1467 }
1468 /*
1469  * Name: dissect_lsp_clv_mt_cap()
1470  *
1471  * Description: Decode an ISIS MT-CAP CLV - code 144.
1472  *
1473  * Input:
1474  *   tvbuff_t * : tvbuffer for packet data
1475  *   proto_tree * : proto tree to build on (may be null)
1476  *   int : current offset into packet data
1477  *   int : length of IDs in packet.
1478  *   int : length of this clv
1479  *
1480  * Output:
1481  *   void, will modify proto_tree if not null.
1482  */
1483 static void
1484 dissect_isis_lsp_clv_mt_cap(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1485                             int id_length _U_, int length)
1486 {
1487         if (length >= 2) {
1488                 /* mtid */
1489                 proto_tree_add_item( tree, hf_isis_lsp_mt_cap_mtid, tvb, offset, 2, ENC_BIG_ENDIAN);
1490                 proto_tree_add_item(tree, hf_isis_lsp_mt_cap_overload, tvb, offset, 2, ENC_BIG_ENDIAN);
1491                 length -= 2;
1492                 offset += 2;
1493                 while (length >= 2) {
1494                         guint8 subtype   = tvb_get_guint8(tvb, offset);
1495                         guint8 subtlvlen = tvb_get_guint8(tvb, offset+1);
1496                         length -= 2;
1497                         offset += 2;
1498                         if (subtlvlen > length) {
1499                                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1500                                                       "Short type 0x%02x TLV (%d vs %d)", subtype, subtlvlen, length);
1501                                 return;
1502                         }
1503                         if (subtype == 0x01) { /* SPB Instance */
1504                                 dissect_isis_lsp_clv_mt_cap_spb_instance(tvb, pinfo, tree, offset, subtype, subtlvlen);
1505                         }
1506                         else if (subtype == 0x02) { /* OALG */
1507                                 dissect_isis_lsp_clv_mt_cap_spb_oalg(tvb, tree, offset, subtype, subtlvlen);
1508                         }
1509                         else if (subtype == 0x03) { /* SPBM Service Identifier */
1510                                 dissect_isis_lsp_clv_mt_cap_spbm_service_identifier(tvb, pinfo, tree, offset, subtype, subtlvlen);
1511                         }
1512                         else if (subtype == 0x04) { /* SPBV Mac Address */
1513                                 dissect_isis_lsp_clv_mt_cap_spbv_mac_address(tvb, pinfo, tree, offset, subtype, subtlvlen);
1514                         }
1515                         else {
1516                                 proto_tree_add_expert_format( tree, pinfo, &ei_isis_lsp_subtlv, tvb, offset, -1,
1517                                                       "Unknown SubTlv: Type: 0x%02x, Length: %d", subtype, subtlvlen);
1518                         }
1519                         length -= subtlvlen;
1520                         offset += subtlvlen;
1521                 }
1522
1523         }
1524 }
1525
1526 /*
1527  * Name: dissect_lsp_authentication_clv()
1528  *
1529  * Description:
1530  *      Decode for a lsp packets authenticaion clv.  Calls into the
1531  *      clv common one.
1532  *
1533  * Input:
1534  *      tvbuff_t * : tvbuffer for packet data
1535  *      proto_tree * : proto tree to build on (may be null)
1536  *      int : current offset into packet data
1537  *      int : length of IDs in packet.
1538  *      int : length of this clv
1539  *
1540  * Output:
1541  *      void, will modify proto_tree if not null.
1542  */
1543 static void
1544 dissect_lsp_authentication_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1545         int id_length _U_, int length)
1546 {
1547         isis_dissect_authentication_clv(tree, pinfo, tvb, &ei_isis_lsp_authentication, offset, length);
1548 }
1549
1550 /*
1551  * Name: dissect_lsp_ip_authentication_clv()
1552  *
1553  * Description:
1554  *      Decode for a lsp packets authenticaion clv.  Calls into the
1555  *      clv common one.
1556  *
1557  * Input:
1558  *      tvbuff_t * : tvbuffer for packet data
1559  *      proto_tree * : proto tree to build on (may be null)
1560  *      int : current offset into packet data
1561  *      int : length of IDs in packet.
1562  *      int : length of this clv
1563  *
1564  * Output:
1565  *      void, will modify proto_tree if not null.
1566  */
1567 static void
1568 dissect_lsp_ip_authentication_clv(tvbuff_t *tvb, packet_info* pinfo _U_, proto_tree *tree, int offset,
1569         int id_length _U_, int length)
1570 {
1571         isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
1572 }
1573
1574 /*
1575  * Name: dissect_lsp_area_address_clv()
1576  *
1577  * Description:
1578  *      Decode for a lsp packet's area address clv.  Call into clv common
1579  *      one.
1580  *
1581  * Input:
1582  *      tvbuff_t * : tvbuffer for packet data
1583  *      proto_tree * : protocol display tree to fill out.  May be NULL
1584  *      int : offset into packet data where we are.
1585  *      int : length of IDs in packet.
1586  *      int : length of clv we are decoding
1587  *
1588  * Output:
1589  *      void, but we will add to proto tree if !NULL.
1590  */
1591 static void
1592 dissect_lsp_area_address_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1593         int id_length _U_, int length)
1594 {
1595         isis_dissect_area_address_clv(tree, pinfo, tvb, &ei_isis_lsp_short_packet, offset, length);
1596 }
1597
1598 /*
1599  * Name: dissect_lsp_eis_neighbors_clv_inner()
1600  *
1601  * Description:
1602  *      Real work horse for showing neighbors.  This means we decode the
1603  *      first octet as either virtual/!virtual (if show_virtual param is
1604  *      set), or as a must == 0 reserved value.
1605  *
1606  *      Once past that, we decode n neighbor elements.  Each neighbor
1607  *      is comprised of a metric block (is dissect_metric) and the
1608  *      addresses.
1609  *
1610  * Input:
1611  *      tvbuff_t * : tvbuffer for packet data
1612  *      proto_tree * : protocol display tree to fill out.  May be NULL
1613  *      int : offset into packet data where we are.
1614  *      int : length of IDs in packet.
1615  *      int : length of clv we are decoding
1616  *      int : set to decode first octet as virtual vs reserved == 0
1617  *      int : set to indicate EIS instead of IS (6 octet per addr instead of 7)
1618  *
1619  * Output:
1620  *      void, but we will add to proto tree if !NULL.
1621  */
1622 static void
1623 dissect_lsp_eis_neighbors_clv_inner(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1624         int offset, int length, int id_length, int show_virtual, int is_eis)
1625 {
1626         proto_item      *ti;
1627         proto_tree      *ntree = NULL;
1628         int             tlen;
1629
1630         if (!is_eis) {
1631                 id_length++;    /* IDs are one octet longer in IS neighbours */
1632                 if ( tree ) {
1633                         if ( show_virtual ) {
1634                                 /* virtual path flag */
1635                                 proto_tree_add_text ( tree, tvb, offset, 1,
1636                                    tvb_get_guint8(tvb, offset) ? "IsVirtual" : "IsNotVirtual" );
1637                         } else {
1638                                 proto_tree_add_item(tree, hf_isis_lsp_eis_neighbors_reserved, tvb, offset, 1, ENC_NA);
1639                         }
1640                 }
1641                 offset++;
1642                 length--;
1643         }
1644         tlen = 4 + id_length;
1645
1646         while ( length > 0 ) {
1647                 if (length<tlen) {
1648                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1649                                 "short E/IS reachability (%d vs %d)", length, tlen );
1650                         return;
1651                 }
1652                 /*
1653                  * Gotta build a sub-tree for all our pieces
1654                  */
1655                 if ( tree ) {
1656                         if ( is_eis ) {
1657                                 ntree = proto_tree_add_subtree(tree, tvb, offset, tlen, ett_isis_lsp_clv_is_neighbors, &ti, "ES Neighbor");
1658                         } else {
1659                                 ntree = proto_tree_add_subtree(tree, tvb, offset, tlen, ett_isis_lsp_clv_is_neighbors, &ti, "IS Neighbor");
1660                         }
1661
1662                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_default_metric, tvb, offset, 1, ENC_NA);
1663                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_default_metric_ie, tvb, offset, 1, ENC_NA);
1664
1665                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_delay_metric, tvb, offset, 1, ENC_NA);
1666                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_delay_metric_supported, tvb, offset, 1, ENC_NA);
1667
1668                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_delay_metric_ie, tvb, offset+1, 1, ENC_NA);
1669
1670                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_expense_metric, tvb, offset, 1, ENC_NA);
1671                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_expense_metric_supported, tvb, offset, 1, ENC_NA);
1672                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_expense_metric_ie, tvb, offset+2, 1, ENC_NA);
1673
1674                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_error_metric, tvb, offset, 1, ENC_NA);
1675                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_error_metric_supported, tvb, offset, 1, ENC_NA);
1676                         proto_tree_add_item(ntree, hf_isis_lsp_eis_neighbors_error_metric_ie, tvb, offset+3, 1, ENC_NA);
1677                         proto_tree_add_item(ntree, is_eis ? hf_isis_lsp_eis_neighbors_es_neighbor_id : hf_isis_lsp_eis_neighbors_is_neighbor_id,
1678                                                                         tvb, offset+4, id_length, ENC_NA);
1679                         proto_item_append_text(ti, ": %s", tvb_print_system_id(tvb, offset+4, id_length));
1680                 }
1681                 offset += tlen;
1682                 length -= tlen;
1683         }
1684 }
1685
1686 /*
1687  * Name: dissect_lsp_l1_is_neighbors_clv()
1688  *
1689  * Description:
1690  *      Dispatch a l1 intermediate system neighbor by calling
1691  *      the inner function with show virtual set to TRUE and is es set to FALSE.
1692  *
1693  * Input:
1694  *      tvbuff_t * : tvbuffer for packet data
1695  *      proto_tree * : protocol display tree to fill out.  May be NULL
1696  *      int : offset into packet data where we are.
1697  *      int : length of IDs in packet.
1698  *      int : length of clv we are decoding
1699  *
1700  * Output:
1701  *      void, but we will add to proto tree if !NULL.
1702  */
1703 static void
1704 dissect_lsp_l1_is_neighbors_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1705         int id_length, int length)
1706 {
1707         dissect_lsp_eis_neighbors_clv_inner(tvb, pinfo, tree, offset,
1708                 length, id_length, TRUE, FALSE);
1709 }
1710
1711 /*
1712  * Name: dissect_lsp_l1_es_neighbors_clv()
1713  *
1714  * Description:
1715  *      Dispatch a l1 end or intermediate system neighbor by calling
1716  *      the inner function with show virtual set to TRUE and es set to TRUE.
1717  *
1718  * Input:
1719  *      tvbuff_t * : tvbuffer for packet data
1720  *      proto_tree * : protocol display tree to fill out.  May be NULL
1721  *      int : offset into packet data where we are.
1722  *      int : length of IDs in packet.
1723  *      int : length of clv we are decoding
1724  *
1725  * Output:
1726  *      void, but we will add to proto tree if !NULL.
1727  */
1728 static void
1729 dissect_lsp_l1_es_neighbors_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1730         int id_length, int length)
1731 {
1732         dissect_lsp_eis_neighbors_clv_inner(tvb, pinfo, tree, offset,
1733                 length, id_length, TRUE, TRUE);
1734 }
1735
1736 /*
1737  * Name: dissect_lsp_l2_is_neighbors_clv()
1738  *
1739  * Description:
1740  *      Dispatch a l2 intermediate system neighbor by calling
1741  *      the inner function with show virtual set to FALSE, and is es set
1742  *      to FALSE
1743  *
1744  * Input:
1745  *      tvbuff_t * : tvbuffer for packet data
1746  *      proto_tree * : protocol display tree to fill out.  May be NULL
1747  *      int : offset into packet data where we are.
1748  *      int : length of IDs in packet.
1749  *      int : length of clv we are decoding
1750  *
1751  * Output:
1752  *      void, but we will add to proto tree if !NULL.
1753  */
1754 static void
1755 dissect_lsp_l2_is_neighbors_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
1756         int id_length, int length)
1757 {
1758         dissect_lsp_eis_neighbors_clv_inner(tvb, pinfo, tree, offset,
1759                 length, id_length, FALSE, FALSE);
1760 }
1761
1762
1763 /*
1764  * Name: dissect_subclv_admin_group ()
1765  *
1766  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1767  *
1768  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1769  *   for dissect the administrive group sub-CLV (code 3).
1770  *
1771  * Input:
1772  *   tvbuff_t * : tvbuffer for packet data
1773  *   proto_tree * : protocol display tree to fill out.
1774  *   int : offset into packet data where we are (beginning of the sub_clv value).
1775  *
1776  * Output:
1777  *   void
1778  */
1779 static void
1780 dissect_subclv_admin_group (tvbuff_t *tvb, proto_tree *tree, int offset) {
1781         proto_tree *ntree;
1782         guint32    clv_value;
1783         guint32    mask;
1784         int        i;
1785
1786         ntree = proto_tree_add_subtree(tree, tvb, offset-2, 6,
1787                 ett_isis_lsp_subclv_admin_group, NULL, "Administrative group(s):");
1788
1789         clv_value = tvb_get_ntohl(tvb, offset);
1790         mask = 1;
1791         for (i = 0 ; i < 32 ; i++) {
1792                 if ( (clv_value & mask) != 0 ) {
1793                         proto_tree_add_text (ntree, tvb, offset, 4, "group %d", i);
1794                 }
1795                 mask <<= 1;
1796         }
1797 }
1798
1799 /*
1800  * Name: dissect_subclv_max_bw ()
1801  *
1802  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1803  *
1804  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1805  *   for dissect the maximum link bandwidth sub-CLV (code 9).
1806  *
1807  * Input:
1808  *   tvbuff_t * : tvbuffer for packet data
1809  *   proto_tree * : protocol display tree to fill out.
1810  *   int : offset into packet data where we are (beginning of the sub_clv value).
1811  *
1812  * Output:
1813  *   void
1814  */
1815 static void
1816 dissect_subclv_max_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
1817 {
1818         gfloat  bw;
1819
1820         bw = tvb_get_ntohieee_float(tvb, offset)*8/1000000;
1821         proto_tree_add_float_format_value(tree, hf_isis_lsp_maximum_link_bandwidth, tvb, offset-2, 6,
1822                 bw, "%.2f Mbps", bw);
1823 }
1824
1825 /*
1826  * Name: dissect_subclv_rsv_bw ()
1827  *
1828  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1829  *
1830  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1831  *   for dissect the reservable link bandwidth sub-CLV (code 10).
1832  *
1833  * Input:
1834  *   tvbuff_t * : tvbuffer for packet data
1835  *   proto_tree * : protocol display tree to fill out.
1836  *   int : offset into packet data where we are (beginning of the sub_clv value).
1837  *
1838  * Output:
1839  *   void
1840  */
1841 static void
1842 dissect_subclv_rsv_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
1843 {
1844         gfloat  bw;
1845
1846         bw = tvb_get_ntohieee_float(tvb, offset)*8/1000000;
1847         proto_tree_add_float_format_value (tree, hf_isis_lsp_reservable_link_bandwidth, tvb, offset-2, 6,
1848                 bw, "%.2f Mbps", bw );
1849 }
1850
1851 /*
1852  * Name: dissect_subclv_unrsv_bw ()
1853  *
1854  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1855  *
1856  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1857  *   for dissect the unreserved bandwidth sub-CLV (code 11).
1858  *
1859  * Input:
1860  *   tvbuff_t * : tvbuffer for packet data
1861  *   proto_tree * : protocol display tree to fill out.
1862  *   int : offset into packet data where we are (beginning of the sub_clv value).
1863  *
1864  * Output:
1865  *   void
1866  */
1867 static void
1868 dissect_subclv_unrsv_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
1869 {
1870         proto_tree *ntree;
1871         gfloat     bw;
1872         int        i;
1873
1874         ntree = proto_tree_add_subtree(tree, tvb, offset-2, 34,
1875                     ett_isis_lsp_subclv_unrsv_bw, NULL, "Unreserved bandwidth:");
1876
1877         for (i = 0 ; i < 8 ; i++) {
1878                 bw = tvb_get_ntohieee_float(tvb, offset+4*i)*8/1000000;
1879                 proto_tree_add_float_format(ntree, hf_isis_lsp_unrsv_bw_priority_level, tvb, offset+4*i, 4,
1880                         bw, "priority level %d: %.2f Mbps", i, bw );
1881         }
1882 }
1883
1884 /*
1885  * Name: dissect_subclv_spb_link_metric ()
1886  *
1887  * Description: Called by function dissect_lsp_ext_is_reachability_clv().
1888  *
1889  *   This function is called by dissect_lsp_ext_is_reachability_clv()
1890  *   for dissect the SPB link metric sub-CLV (code 29).
1891  *
1892  * Input:
1893  *   tvbuff_t * : tvbuffer for packet data
1894  *   proto_tree * : protocol display tree to fill out.
1895  *   int : offset into packet data where we are (beginning of the sub_clv value).
1896  *   int : subtlv type
1897  *   int : subtlv length
1898  *
1899  * Output:
1900  *   void
1901  */
1902
1903 static void
1904 dissect_subclv_spb_link_metric(tvbuff_t *tvb, packet_info *pinfo,
1905         proto_tree *tree, int offset, int subtype, int sublen)
1906 {
1907         const int SUBLEN     = 6;
1908
1909         if (sublen != SUBLEN) {
1910                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
1911                                       "Short SPB Link Metric sub-TLV (%d vs %d)", sublen, SUBLEN);
1912                 return;
1913         }
1914         else {
1915                 proto_tree *subtree;
1916                 subtree = proto_tree_add_subtree_format( tree, tvb, offset-2, sublen+2, ett_isis_lsp_subclv_spb_link_metric, NULL,
1917                                           "SPB Link Metric: Type: 0x%02x (%d), Length: %d", subtype, subtype, sublen);
1918
1919                 proto_tree_add_item(subtree, hf_isis_lsp_spb_link_metric,
1920                                     tvb, offset, 3, ENC_BIG_ENDIAN);
1921
1922                 proto_tree_add_item(subtree, hf_isis_lsp_spb_port_count,
1923                                     tvb, offset+3, 1, ENC_BIG_ENDIAN);
1924
1925                 proto_tree_add_item(subtree, hf_isis_lsp_spb_port_id,
1926                                     tvb, offset+4, 2, ENC_BIG_ENDIAN);
1927     }
1928 }
1929
1930 /*
1931  * Name: dissect_lsp_ext_is_reachability_clv()
1932  *
1933  * Description: Decode a Extended IS Reachability CLV - code 22
1934  * RFC 3784
1935  *
1936  *   The extended IS reachability TLV is an extended version
1937  *   of the IS reachability TLV (code 2). It encodes the metric
1938  *   as a 24-bit unsigned integer and allows to add sub-CLV(s).
1939  *
1940  *   CALLED BY TLV 222 DISSECTOR
1941  *
1942  * Input:
1943  *   tvbuff_t * : tvbuffer for packet data
1944  *   proto_tree * : protocol display tree to fill out.  May be NULL
1945  *   int : offset into packet data where we are.
1946  *   int : length of IDs in packet.
1947  *   int : length of clv we are decoding
1948  *
1949  * Output:
1950  *   void, but we will add to proto tree if !NULL.
1951  */
1952 static void
1953 dissect_lsp_ext_is_reachability_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree,
1954         int offset, int id_length _U_, int length)
1955 {
1956         proto_item *ti;
1957         proto_tree *ntree = NULL;
1958         guint      subclvs_len;
1959         guint      len, i;
1960         guint      clv_code, clv_len;
1961
1962         while (length > 0) {
1963                 ntree = proto_tree_add_subtree(tree, tvb, offset, -1,
1964                 ett_isis_lsp_part_of_clv_ext_is_reachability, &ti, "IS Neighbor");
1965
1966                 proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_is_neighbor_id, tvb, offset, 7, ENC_NA);
1967                 proto_item_append_text(ti, ": %s", tvb_print_system_id(tvb, offset, 7));
1968
1969                 proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_metric, tvb, offset+7, 3, ENC_BIG_ENDIAN);
1970
1971                 subclvs_len = tvb_get_guint8(tvb, offset+10);
1972                 if (subclvs_len == 0) {
1973                         proto_tree_add_text (ntree, tvb, offset+10, 1, "no sub-TLVs present");
1974                 }
1975                 else {
1976                         i = 0;
1977                         while (i < subclvs_len) {
1978                                 clv_code = tvb_get_guint8(tvb, offset+11+i);
1979                                 clv_len  = tvb_get_guint8(tvb, offset+12+i);
1980                                 switch (clv_code) {
1981                                 case 3 :
1982                                         dissect_subclv_admin_group(tvb, ntree, offset+13+i);
1983                                         break;
1984                                 case 4 :
1985                                         proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_link_local_identifier, tvb, offset+13+i, 4, ENC_BIG_ENDIAN);
1986                                         proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_link_remote_identifier, tvb, offset+17+i, 4, ENC_BIG_ENDIAN);
1987                                         break;
1988                                 case 6 :
1989                                         proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_ipv4_interface_address, tvb, offset+11+i, 6, ENC_BIG_ENDIAN);
1990                                         break;
1991                                 case 8 :
1992                                         proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_ipv4_neighbor_address, tvb, offset+11+i, 6, ENC_BIG_ENDIAN);
1993                                         break;
1994                                 case 9 :
1995                                         dissect_subclv_max_bw (tvb, ntree, offset+13+i);
1996                                         break;
1997                                 case 10:
1998                                         dissect_subclv_rsv_bw (tvb, ntree, offset+13+i);
1999                                         break;
2000                                 case 11:
2001                                         dissect_subclv_unrsv_bw (tvb, ntree, offset+13+i);
2002                                         break;
2003                                 case 18:
2004                                         proto_tree_add_item(ntree, hf_isis_lsp_ext_is_reachability_traffic_engineering_default_metric, tvb, offset+11+i, 5, ENC_BIG_ENDIAN);
2005                                         break;
2006                                 case 29:
2007                                         dissect_subclv_spb_link_metric(tvb, pinfo, ntree,
2008                                                 offset+13+i, clv_code, clv_len);
2009                                         break;
2010                                 case 250:
2011                                 case 251:
2012                                 case 252:
2013                                 case 253:
2014                                 case 254:
2015                                         proto_tree_add_text (ntree, tvb, offset+11+i, clv_len+2,
2016                                                 "Unknown Cisco specific extensions: code %d, length %d",
2017                                                 clv_code, clv_len );
2018                                         break;
2019                                 default :
2020                                         proto_tree_add_text (ntree, tvb, offset+11+i, clv_len+2,
2021                                                 "Unknown sub-CLV: code %d, length %d", clv_code, clv_len );
2022                                         break;
2023                                 }
2024                                 i += clv_len + 2;
2025                         }
2026                 }
2027
2028                 len = 11 + subclvs_len;
2029                 proto_item_set_len (ti, len);
2030                 offset += len;
2031                 length -= len;
2032         }
2033 }
2034
2035 /*
2036  * Name: dissect_lsp_mt_reachable_IPv4_prefx_clv()
2037  *
2038  * Description: Decode Multi-Topology IPv4 Prefixes - code 235
2039  *
2040  *
2041  * Input:
2042  *   tvbuff_t * : tvbuffer for packet data
2043  *   proto_tree * : protocol display tree to fill out.  May be NULL
2044  *   int : offset into packet data where we are.
2045  *   int : length of IDs in packet.
2046  *   int : length of clv we are decoding
2047  *
2048  * Output:
2049  *   void, but we will add to proto tree if !NULL.
2050  */
2051 static void
2052 dissect_lsp_mt_reachable_IPv4_prefx_clv(tvbuff_t *tvb, packet_info* pinfo,
2053         proto_tree *tree, int offset, int id_length _U_, int length)
2054 {
2055         if (length < 2) {
2056                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
2057                                 "short lsp multi-topology reachable IPv4 prefixes(%d vs %d)", length, 2 );
2058                 return;
2059         }
2060         dissect_lsp_mt_id(tvb, tree, offset);
2061         dissect_lsp_ext_ip_reachability_clv(tvb, pinfo, tree, offset+2, 0, length-2);
2062 }
2063
2064 /*
2065  * Name: dissect_lsp_mt_reachable_IPv6_prefx_clv()
2066  *
2067  * Description: Decode Multi-Topology IPv6 Prefixes - code 237
2068  *
2069  *
2070  * Input:
2071  *   tvbuff_t * : tvbuffer for packet data
2072  *   proto_tree * : protocol display tree to fill out.  May be NULL
2073  *   int : offset into packet data where we are.
2074  *   int : length of IDs in packet.
2075  *   int : length of clv we are decoding
2076  *
2077  * Output:
2078  *   void, but we will add to proto tree if !NULL.
2079  */
2080 static void
2081 dissect_lsp_mt_reachable_IPv6_prefx_clv(tvbuff_t *tvb, packet_info* pinfo,
2082         proto_tree *tree, int offset, int id_length _U_, int length)
2083 {
2084         if (length < 2) {
2085                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
2086                                 "short lsp multi-topology reachable IPv6 prefixes(%d vs %d)", length, 2 );
2087                 return;
2088         }
2089         dissect_lsp_mt_id(tvb, tree, offset);
2090         dissect_lsp_ipv6_reachability_clv(tvb, pinfo, tree, offset+2, 0, length-2);
2091 }
2092
2093
2094 /*
2095  * Name: dissect_lsp_mt_is_reachability_clv()
2096  *
2097  * Description: Decode Multi-Topology Intermediate Systems - code 222
2098  *
2099  *
2100  * Input:
2101  *   tvbuff_t * : tvbuffer for packet data
2102  *   proto_tree * : protocol display tree to fill out.  May be NULL
2103  *   int : offset into packet data where we are.
2104  *   int : unused
2105  *   int : length of clv we are decoding
2106  *
2107  * Output:
2108  *   void, but we will add to proto tree if !NULL.
2109  */
2110
2111 static void
2112 dissect_lsp_mt_is_reachability_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
2113         int id_length _U_, int length)
2114 {
2115         if (length < 2) {
2116                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
2117                                 "short lsp reachability(%d vs %d)", length, 2 );
2118                 return;
2119         }
2120
2121         /*
2122          * the MT ID value dissection is used in other LSPs so we push it
2123          * in a function
2124          */
2125         dissect_lsp_mt_id(tvb, tree, offset);
2126         /*
2127          * fix here. No need to parse TLV 22 (with bugs) while it is
2128          * already done correctly!!
2129          */
2130         dissect_lsp_ext_is_reachability_clv(tvb, pinfo, tree, offset+2, 0, length-2);
2131 }
2132
2133 /*
2134  * Name: dissect_lsp_partition_dis_clv()
2135  *
2136  * Description:
2137  *      This CLV is used to indicate which system is the designated
2138  *      IS for partition repair.  This means just putting out the
2139  *      "id_length"-octet IS.
2140  *
2141  * Input:
2142  *      tvbuff_t * : tvbuffer for packet data
2143  *      proto_tree * : protocol display tree to fill out.  May be NULL
2144  *      int : offset into packet data where we are.
2145  *      int : length of IDs in packet.
2146  *      int : length of clv we are decoding
2147  *
2148  * Output:
2149  *      void, but we will add to proto tree if !NULL.
2150  */
2151 static void
2152 dissect_lsp_partition_dis_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
2153         int id_length, int length)
2154 {
2155         if ( length < id_length ) {
2156                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
2157                                 "short lsp partition DIS(%d vs %d)", length, id_length );
2158                 return;
2159         }
2160         /*
2161          * Gotta build a sub-tree for all our pieces
2162          */
2163         proto_tree_add_item( tree, hf_isis_lsp_partition_designated_l2_is, tvb, offset, id_length, ENC_NA);
2164
2165         length -= id_length;
2166         offset += id_length;
2167         if ( length > 0 ) {
2168                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_long_packet, tvb, offset, -1,
2169                                 "Long lsp partition DIS, %d left over", length );
2170                 return;
2171         }
2172 }
2173
2174 /*
2175  * Name: dissect_lsp_prefix_neighbors_clv()
2176  *
2177  * Description:
2178  *      The prefix CLV describes what other (OSI) networks we can reach
2179  *      and what their cost is.  It is built from a metric block
2180  *      (see dissect_metric) followed by n addresses.
2181  *
2182  * Input:
2183  *      tvbuff_t * : tvbuffer for packet data
2184  *      proto_tree * : protocol display tree to fill out.  May be NULL
2185  *      int : offset into packet data where we are.
2186  *      int : length of IDs in packet.
2187  *      int : length of clv we are decoding
2188  *
2189  * Output:
2190  *      void, but we will add to proto tree if !NULL.
2191  */
2192 static void
2193 dissect_lsp_prefix_neighbors_clv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset,
2194         int id_length _U_, int length)
2195 {
2196         char *sbuf;
2197         int mylen;
2198
2199         if ( length < 4 ) {
2200                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
2201                         "Short lsp prefix neighbors (%d vs 4)", length );
2202                 return;
2203         }
2204         if ( tree ) {
2205                 dissect_metric (tvb, tree, offset,
2206                         tvb_get_guint8(tvb, offset), "Default", TRUE );
2207                 dissect_metric (tvb, tree, offset+1,
2208                         tvb_get_guint8(tvb, offset+1), "Delay", FALSE );
2209                 dissect_metric (tvb, tree, offset+2,
2210                         tvb_get_guint8(tvb, offset+2), "Expense", FALSE );
2211                 dissect_metric (tvb, tree, offset+3,
2212                         tvb_get_guint8(tvb, offset+3), "Error", FALSE );
2213         }
2214         offset += 4;
2215         length -= 4;
2216         while ( length > 0 ) {
2217                 mylen = tvb_get_guint8(tvb, offset);
2218                 length--;
2219                 if (length<=0) {
2220                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_short_packet, tvb, offset, -1,
2221                                 "Zero payload space after length in prefix neighbor" );
2222                         return;
2223                 }
2224                 if ( mylen > length) {
2225                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_long_packet, tvb, offset, -1,
2226                                 "Integral length of prefix neighbor too long (%d vs %d)", mylen, length );
2227                         return;
2228                 }
2229
2230                 /*
2231                  * Lets turn the area address into "standard" 0000.0000.etc
2232                  * format string.
2233                  */
2234                 sbuf =  print_area( tvb_get_ptr(tvb, offset+1, mylen), mylen );
2235                 /* and spit it out */
2236                 if ( tree ) {
2237                         proto_tree_add_text ( tree, tvb, offset, mylen + 1,
2238                                 "Area address (%d): %s", mylen, sbuf );
2239                 }
2240                 offset += mylen + 1;
2241                 length -= mylen;        /* length already adjusted for len fld*/
2242         }
2243 }
2244
2245 static void isis_lsp_checkum_additional_info(tvbuff_t * tvb, packet_info * pinfo,
2246     proto_item * it_cksum, int offset, gboolean is_cksum_correct)
2247 {
2248         proto_tree * checksum_tree;
2249         proto_item * item;
2250
2251         checksum_tree = proto_item_add_subtree(it_cksum, ett_isis_lsp_cksum);
2252         item = proto_tree_add_boolean(checksum_tree, hf_isis_lsp_checksum_good, tvb,
2253                                       offset, 2, is_cksum_correct);
2254         PROTO_ITEM_SET_GENERATED(item);
2255         item = proto_tree_add_boolean(checksum_tree, hf_isis_lsp_checksum_bad, tvb,
2256                                       offset, 2, !is_cksum_correct);
2257         PROTO_ITEM_SET_GENERATED(item);
2258         if (!is_cksum_correct) {
2259                 expert_add_info(pinfo, item, &ie_isis_lsp_checksum_bad);
2260                 col_append_str(pinfo->cinfo, COL_INFO, " [ISIS CHECKSUM INCORRECT]");
2261         }
2262 }
2263
2264 static const isis_clv_handle_t clv_l1_lsp_opts[] = {
2265         {
2266                 ISIS_CLV_AREA_ADDRESS,
2267                 "Area address(es)",
2268                 &ett_isis_lsp_clv_area_addr,
2269                 dissect_lsp_area_address_clv
2270         },
2271         {
2272                 ISIS_CLV_IS_REACH,
2273                 "IS Reachability",
2274                 &ett_isis_lsp_clv_is_neighbors,
2275                 dissect_lsp_l1_is_neighbors_clv
2276         },
2277         {
2278                 ISIS_CLV_ES_NEIGHBORS,
2279                 "ES Neighbor(s)",
2280                 &ett_isis_lsp_clv_is_neighbors,
2281                 dissect_lsp_l1_es_neighbors_clv
2282         },
2283         {
2284                 ISIS_CLV_EXTD_IS_REACH,
2285                 "Extended IS reachability",
2286                 &ett_isis_lsp_clv_ext_is_reachability,
2287                 dissect_lsp_ext_is_reachability_clv
2288         },
2289         {
2290                 ISIS_CLV_INT_IP_REACH,
2291                 "IP Internal reachability",
2292                 &ett_isis_lsp_clv_ip_reachability,
2293                 dissect_lsp_ip_reachability_clv
2294         },
2295         {
2296                 ISIS_CLV_EXT_IP_REACH,
2297                 "IP External reachability",
2298                 &ett_isis_lsp_clv_ip_reachability,
2299                 dissect_lsp_ip_reachability_clv
2300         },
2301         {
2302                 ISIS_CLV_EXTD_IP_REACH,
2303                 "Extended IP Reachability",
2304                 &ett_isis_lsp_clv_ext_ip_reachability,
2305                 dissect_lsp_ext_ip_reachability_clv
2306         },
2307         {
2308                 ISIS_CLV_IP6_REACH,
2309                 "IPv6 reachability",
2310                 &ett_isis_lsp_clv_ipv6_reachability,
2311                 dissect_lsp_ipv6_reachability_clv
2312         },
2313         {
2314                 ISIS_CLV_PROTOCOLS_SUPPORTED,
2315                 "Protocols supported",
2316                 &ett_isis_lsp_clv_nlpid,
2317                 dissect_lsp_nlpid_clv
2318         },
2319         {
2320                 ISIS_CLV_HOSTNAME,
2321                 "Hostname",
2322                 &ett_isis_lsp_clv_hostname,
2323                 dissect_lsp_hostname_clv
2324         },
2325         {
2326                 ISIS_CLV_TE_ROUTER_ID,
2327                 "Traffic Engineering Router ID",
2328                 &ett_isis_lsp_clv_te_router_id,
2329                 dissect_lsp_te_router_id_clv
2330         },
2331         {
2332                 ISIS_CLV_IP_ADDR,
2333                 "IP Interface address(es)",
2334                 &ett_isis_lsp_clv_ipv4_int_addr,
2335                 dissect_lsp_ip_int_addr_clv
2336         },
2337         {
2338                 ISIS_CLV_IP6_ADDR,
2339                 "IPv6 Interface address(es)",
2340                 &ett_isis_lsp_clv_ipv6_int_addr,
2341                 dissect_lsp_ipv6_int_addr_clv
2342         },
2343         {
2344                 ISIS_CLV_MT_CAP,
2345                 "MT-Capability",
2346                 &ett_isis_lsp_clv_mt_cap,
2347                 dissect_isis_lsp_clv_mt_cap
2348         },
2349         {
2350                 ISIS_CLV_AUTHENTICATION,
2351                 "Authentication",
2352                 &ett_isis_lsp_clv_authentication,
2353                 dissect_lsp_authentication_clv
2354         },
2355         {
2356                 ISIS_CLV_IP_AUTHENTICATION,
2357                 "IP Authentication",
2358                 &ett_isis_lsp_clv_ip_authentication,
2359                 dissect_lsp_ip_authentication_clv
2360         },
2361         {
2362                 ISIS_CLV_MT_SUPPORTED,
2363                 "Multi Topology supported",
2364                 &ett_isis_lsp_clv_mt,
2365                 dissect_lsp_mt_clv
2366         },
2367         {
2368                 ISIS_CLV_MT_IS_REACH,
2369                 "Multi Topology IS Reachability",
2370                 &ett_isis_lsp_clv_mt_is,
2371                 dissect_lsp_mt_is_reachability_clv
2372         },
2373         {
2374                 ISIS_CLV_MT_IP_REACH,
2375                 "Multi Topology Reachable IPv4 Prefixes",
2376                 &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
2377                 dissect_lsp_mt_reachable_IPv4_prefx_clv
2378         },
2379         {
2380                 ISIS_CLV_MT_IP6_REACH,
2381                 "Multi Topology Reachable IPv6 Prefixes",
2382                 &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
2383                 dissect_lsp_mt_reachable_IPv6_prefx_clv
2384         },
2385         {
2386                 ISIS_CLV_RT_CAPABLE,
2387                 "Router Capability",
2388                 &ett_isis_lsp_clv_rt_capable_IPv4_prefx,
2389                 dissect_isis_rt_capable_clv
2390         },
2391         {
2392                 ISIS_GRP_ADDR,
2393                 "GROUP ADDRESS TLV",
2394                 &ett_isis_lsp_clv_grp_address_IPv4_prefx,
2395                 dissect_isis_grp_address_clv
2396         },
2397         {
2398                 0,
2399                 "",
2400                 NULL,
2401                 NULL
2402         }
2403 };
2404
2405 static const isis_clv_handle_t clv_l2_lsp_opts[] = {
2406         {
2407                 ISIS_CLV_AREA_ADDRESS,
2408                 "Area address(es)",
2409                 &ett_isis_lsp_clv_area_addr,
2410                 dissect_lsp_area_address_clv
2411         },
2412         {
2413                 ISIS_CLV_IS_REACH,
2414                 "IS Reachability",
2415                 &ett_isis_lsp_clv_is_neighbors,
2416                 dissect_lsp_l2_is_neighbors_clv
2417         },
2418         {
2419                 ISIS_CLV_EXTD_IS_REACH,
2420                 "Extended IS reachability",
2421                 &ett_isis_lsp_clv_ext_is_reachability,
2422                 dissect_lsp_ext_is_reachability_clv
2423         },
2424         {
2425                 ISIS_CLV_PARTITION_DIS,
2426                 "Partition Designated Level 2 IS",
2427                 &ett_isis_lsp_clv_partition_dis,
2428                 dissect_lsp_partition_dis_clv
2429         },
2430         {
2431                 ISIS_CLV_PREFIX_NEIGHBORS,
2432                 "Prefix neighbors",
2433                 &ett_isis_lsp_clv_prefix_neighbors,
2434                 dissect_lsp_prefix_neighbors_clv
2435         },
2436         {
2437                 ISIS_CLV_INT_IP_REACH,
2438                 "IP Internal reachability",
2439                 &ett_isis_lsp_clv_ip_reachability,
2440                 dissect_lsp_ip_reachability_clv
2441         },
2442         {
2443                 ISIS_CLV_EXT_IP_REACH,
2444                 "IP External reachability",
2445                 &ett_isis_lsp_clv_ip_reachability,
2446                 dissect_lsp_ip_reachability_clv
2447         },
2448         {
2449                 ISIS_CLV_PROTOCOLS_SUPPORTED,
2450                 "Protocols supported",
2451                 &ett_isis_lsp_clv_nlpid,
2452                 dissect_lsp_nlpid_clv
2453         },
2454         {
2455                 ISIS_CLV_HOSTNAME,
2456                 "Hostname",
2457                 &ett_isis_lsp_clv_hostname,
2458                 dissect_lsp_hostname_clv
2459         },
2460         {
2461                 ISIS_CLV_TE_ROUTER_ID,
2462                 "Traffic Engineering Router ID",
2463                 &ett_isis_lsp_clv_te_router_id,
2464                 dissect_lsp_te_router_id_clv
2465         },
2466         {
2467                 ISIS_CLV_EXTD_IP_REACH,
2468                 "Extended IP Reachability",
2469                 &ett_isis_lsp_clv_ext_ip_reachability,
2470                 dissect_lsp_ext_ip_reachability_clv
2471         },
2472         {
2473                 ISIS_CLV_IP6_REACH,
2474                 "IPv6 reachability",
2475                 &ett_isis_lsp_clv_ipv6_reachability,
2476                 dissect_lsp_ipv6_reachability_clv
2477         },
2478         {
2479                 ISIS_CLV_IP_ADDR,
2480                 "IP Interface address(es)",
2481                 &ett_isis_lsp_clv_ipv4_int_addr,
2482                 dissect_lsp_ip_int_addr_clv
2483         },
2484         {
2485                 ISIS_CLV_IP6_ADDR,
2486                 "IPv6 Interface address(es)",
2487                 &ett_isis_lsp_clv_ipv6_int_addr,
2488                 dissect_lsp_ipv6_int_addr_clv
2489         },
2490         {
2491                 ISIS_CLV_MT_CAP,
2492                 "MT-Capability",
2493                 &ett_isis_lsp_clv_mt_cap,
2494                 dissect_isis_lsp_clv_mt_cap
2495         },
2496         {
2497                 ISIS_CLV_AUTHENTICATION,
2498                 "Authentication",
2499                 &ett_isis_lsp_clv_authentication,
2500                 dissect_lsp_authentication_clv
2501         },
2502         {
2503                 ISIS_CLV_IP_AUTHENTICATION,
2504                 "IP Authentication",
2505                 &ett_isis_lsp_clv_ip_authentication,
2506                 dissect_lsp_ip_authentication_clv
2507         },
2508         {
2509                 ISIS_CLV_MT_SUPPORTED,
2510                 "Multi Topology",
2511                 &ett_isis_lsp_clv_mt,
2512                 dissect_lsp_mt_clv
2513         },
2514         {
2515                 ISIS_CLV_MT_IS_REACH,
2516                 "Multi Topology IS Reachability",
2517                 &ett_isis_lsp_clv_mt_is,
2518                 dissect_lsp_mt_is_reachability_clv
2519         },
2520         {
2521                 ISIS_CLV_MT_IP_REACH,
2522                 "Multi Topology Reachable IPv4 Prefixes",
2523                 &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
2524                 dissect_lsp_mt_reachable_IPv4_prefx_clv
2525         },
2526         {
2527                 ISIS_CLV_MT_IP6_REACH,
2528                 "Multi Topology Reachable IPv6 Prefixes",
2529                 &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
2530                 dissect_lsp_mt_reachable_IPv6_prefx_clv
2531         },
2532         {
2533                 0,
2534                 "",
2535                 NULL,
2536                 NULL
2537         }
2538 };
2539
2540 /*
2541  * Name: isis_dissect_isis_lsp()
2542  *
2543  * Description:
2544  *      Print out the LSP part of the main header and then call the CLV
2545  *      de-mangler with the right list of valid CLVs.
2546  *
2547  * Input:
2548  *      tvbuff_t * : tvbuffer for packet data
2549  *      proto_tree * : protocol display tree to add to.  May be NULL.
2550  *      int offset : our offset into packet data.
2551  *      int : LSP type, a la packet-isis.h ISIS_TYPE_* values
2552  *      int : header length of packet.
2553  *      int : length of IDs in packet.
2554  *
2555  * Output:
2556  *      void, but we will add to proto tree if !NULL.
2557  */
2558 static void
2559 dissect_isis_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2560         const isis_clv_handle_t *opts, int header_length, int id_length)
2561 {
2562         proto_item      *ti, *ta;
2563         proto_tree      *lsp_tree, *info_tree, *att_tree;
2564         guint16         pdu_length, lifetime, checksum, cacl_checksum=0;
2565         guint8          lsp_info;
2566         int             len, offset_checksum;
2567         proto_item      *it_cksum;
2568         char* system_id;
2569
2570         col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISIS LSP");
2571
2572         ti = proto_tree_add_item(tree, proto_isis_lsp, tvb, offset, -1, ENC_NA);
2573         lsp_tree = proto_item_add_subtree(ti, ett_isis_lsp);
2574
2575         pdu_length = tvb_get_ntohs(tvb, offset);
2576         proto_tree_add_uint(lsp_tree, hf_isis_lsp_pdu_length, tvb,
2577                         offset, 2, pdu_length);
2578         offset += 2;
2579
2580         proto_tree_add_item(lsp_tree, hf_isis_lsp_remaining_life,
2581                         tvb, offset, 2, ENC_BIG_ENDIAN);
2582
2583         lifetime = tvb_get_ntohs(tvb, offset);
2584         offset += 2;
2585         offset_checksum = offset;
2586
2587         proto_tree_add_item(lsp_tree, hf_isis_lsp_lsp_id, tvb, offset, id_length + 2, ENC_NA);
2588         system_id = tvb_print_system_id( tvb, offset, id_length+2 );
2589         col_append_fstr(pinfo->cinfo, COL_INFO, ", LSP-ID: %s", system_id);
2590
2591         offset += (id_length + 2);
2592
2593         proto_tree_add_item(lsp_tree, hf_isis_lsp_sequence_number,
2594                         tvb, offset, 4, ENC_BIG_ENDIAN);
2595
2596         col_append_fstr(pinfo->cinfo, COL_INFO, ", Sequence: 0x%08x, Lifetime: %5us",
2597                         tvb_get_ntohl(tvb, offset),
2598                         tvb_get_ntohs(tvb, offset - (id_length+2+2)));
2599
2600         offset += 4;
2601
2602         checksum = lifetime ? tvb_get_ntohs(tvb, offset) : 0;
2603         switch (check_and_get_checksum(tvb, offset_checksum, pdu_length-12, checksum, offset, &cacl_checksum)) {
2604                 case NO_CKSUM :
2605                         checksum = tvb_get_ntohs(tvb, offset);
2606                         proto_tree_add_uint_format_value(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
2607                                         "0x%04x [unused]", checksum);
2608                 break;
2609                 case DATA_MISSING :
2610                         proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_long_packet, tvb, offset, -1,
2611                                         "Packet length %d went beyond packet",
2612                                         tvb_length_remaining(tvb, offset_checksum));
2613                 break;
2614                 case CKSUM_NOT_OK :
2615                         it_cksum = proto_tree_add_uint_format_value(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
2616                                         "0x%04x [incorrect, should be 0x%04x]",
2617                                         checksum, cacl_checksum);
2618                         isis_lsp_checkum_additional_info(tvb, pinfo, it_cksum, offset, FALSE);
2619                 break;
2620                 case CKSUM_OK :
2621                         it_cksum = proto_tree_add_uint_format_value(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
2622                                         "0x%04x [correct]", checksum);
2623                                 isis_lsp_checkum_additional_info(tvb, pinfo, it_cksum, offset, TRUE);
2624                 break;
2625         }
2626         offset += 2;
2627
2628         if (tree) {
2629                 /*
2630                  * P | ATT | HIPPITY | IS TYPE description.
2631                  */
2632                 lsp_info = tvb_get_guint8(tvb, offset);
2633                 info_tree = proto_tree_add_subtree_format(lsp_tree, tvb, offset, 1, ett_isis_lsp_info, NULL,
2634                         "Type block(0x%02x): Partition Repair:%d, Attached bits:%d, Overload bit:%d, IS type:%d",
2635                         lsp_info,
2636                         ISIS_LSP_PARTITION(lsp_info),
2637                         ISIS_LSP_ATT(lsp_info),
2638                         ISIS_LSP_HIPPITY(lsp_info),
2639                         ISIS_LSP_IS_TYPE(lsp_info)
2640                         );
2641
2642                 proto_tree_add_boolean(info_tree, hf_isis_lsp_p, tvb, offset, 1, lsp_info);
2643                 ta = proto_tree_add_uint(info_tree, hf_isis_lsp_att, tvb, offset, 1, lsp_info);
2644                 att_tree = proto_item_add_subtree(ta, ett_isis_lsp_att);
2645                 proto_tree_add_item(att_tree, hf_isis_lsp_error_metric, tvb, offset, 1, ENC_NA);
2646                 proto_tree_add_item(att_tree, hf_isis_lsp_expense_metric, tvb, offset, 1, ENC_NA);
2647                 proto_tree_add_item(att_tree, hf_isis_lsp_delay_metric, tvb, offset, 1, ENC_NA);
2648                 proto_tree_add_item(att_tree, hf_isis_lsp_default_metric, tvb, offset, 1, ENC_NA);
2649                 proto_tree_add_boolean(info_tree, hf_isis_lsp_hippity, tvb, offset, 1, lsp_info);
2650                 proto_tree_add_uint(info_tree, hf_isis_lsp_is_type, tvb, offset, 1, lsp_info);
2651         }
2652         offset += 1;
2653
2654         len = pdu_length - header_length;
2655         if (len < 0) {
2656                 proto_tree_add_expert_format(tree, pinfo, &ei_isis_lsp_long_packet, tvb, offset, -1,
2657                         "packet header length %d went beyond packet",
2658                          header_length );
2659                 return;
2660         }
2661         /*
2662          * Now, we need to decode our CLVs.  We need to pass in
2663          * our list of valid ones!
2664          */
2665         isis_dissect_clvs(tvb, pinfo, lsp_tree, offset,
2666                         opts, &ei_isis_lsp_short_packet, len, id_length, ett_isis_lsp_clv_unknown );
2667 }
2668
2669 static int
2670 dissect_isis_l1_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2671 {
2672         isis_data_t* isis = (isis_data_t*)data;
2673         dissect_isis_lsp(tvb, pinfo, tree, 0,
2674                 clv_l1_lsp_opts, isis->header_length, isis->system_id_len);
2675         return tvb_length(tvb);
2676 }
2677
2678 static int
2679 dissect_isis_l2_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2680 {
2681         isis_data_t* isis = (isis_data_t*)data;
2682         dissect_isis_lsp(tvb, pinfo, tree, 0,
2683                 clv_l2_lsp_opts, isis->header_length, isis->system_id_len);
2684         return tvb_length(tvb);
2685 }
2686
2687 void
2688 proto_register_isis_lsp(void)
2689 {
2690         static hf_register_info hf[] = {
2691                 { &hf_isis_lsp_pdu_length,
2692                 { "PDU length",         "isis.lsp.pdu_length", FT_UINT16,
2693                   BASE_DEC, NULL, 0x0, NULL, HFILL }},
2694
2695                 { &hf_isis_lsp_remaining_life,
2696                 { "Remaining lifetime", "isis.lsp.remaining_life", FT_UINT16,
2697                   BASE_DEC, NULL, 0x0, NULL, HFILL }},
2698
2699                 { &hf_isis_lsp_lsp_id,
2700                 { "LSP-ID", "isis.lsp.lsp_id", FT_SYSTEM_ID,
2701                   BASE_NONE, NULL, 0x0, NULL, HFILL }},
2702
2703                 { &hf_isis_lsp_hostname,
2704                 { "Hostname", "isis.lsp.hostname", FT_STRING,
2705                   BASE_NONE, NULL, 0x0, NULL, HFILL }},
2706
2707                 { &hf_isis_lsp_sequence_number,
2708                 { "Sequence number",           "isis.lsp.sequence_number",
2709                   FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2710
2711                 { &hf_isis_lsp_checksum,
2712                 { "Checksum",           "isis.lsp.checksum",FT_UINT16,
2713                   BASE_HEX, NULL, 0x0, NULL, HFILL }},
2714
2715                 { &hf_isis_lsp_checksum_good,
2716                 { "Good Checksum", "isis.lsp.checksum_good", FT_BOOLEAN, BASE_NONE,
2717                         NULL, 0x0, "Good IS-IS LSP Checksum", HFILL }},
2718
2719                 { &hf_isis_lsp_checksum_bad,
2720                 { "Bad Checksum", "isis.lsp.checksum_bad", FT_BOOLEAN, BASE_NONE,
2721                         NULL, 0x0, "Bad IS-IS LSP Checksum", HFILL }},
2722
2723                 { &hf_isis_lsp_clv_ipv4_int_addr,
2724                 { "IPv4 interface address", "isis.lsp.clv_ipv4_int_addr", FT_IPv4,
2725                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
2726
2727                 { &hf_isis_lsp_clv_ipv6_int_addr,
2728                 { "IPv6 interface address", "isis.lsp.clv_ipv6_int_addr", FT_IPv6,
2729                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
2730
2731                 { &hf_isis_lsp_clv_te_router_id,
2732                 { "Traffic Engineering Router ID", "isis.lsp.clv_te_router_id", FT_IPv4,
2733                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
2734
2735                 { &hf_isis_lsp_clv_mt,
2736                 { "MT-ID", "isis.lsp.clv_mt",
2737                         FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2738
2739                 { &hf_isis_lsp_p,
2740                 { "Partition Repair",   "isis.lsp.partition_repair", FT_BOOLEAN, 8,
2741                         TFS(&tfs_supported_not_supported), ISIS_LSP_PARTITION_MASK,
2742                         "If set, this router supports the optional Partition Repair function", HFILL }},
2743
2744                 { &hf_isis_lsp_att,
2745                 { "Attachment", "isis.lsp.att", FT_UINT8, BASE_DEC,
2746                         NULL, ISIS_LSP_ATT_MASK,
2747                         NULL, HFILL }},
2748
2749                 { &hf_isis_lsp_hippity,
2750                 { "Overload bit",       "isis.lsp.overload", FT_BOOLEAN, 8,
2751                         TFS(&tfs_set_notset), ISIS_LSP_HIPPITY_MASK,
2752                         "If set, this router will not be used by any decision process to calculate routes", HFILL }},
2753
2754                 { &hf_isis_lsp_root_id,
2755                 { "Root Bridge ID",     "isis.lsp.root.id", FT_UINT64, BASE_HEX,
2756                         NULL, 0x0, NULL, HFILL }},
2757
2758                 { &hf_isis_lsp_is_type,
2759                 { "Type of Intermediate System",        "isis.lsp.is_type", FT_UINT8, BASE_DEC,
2760                         VALS(isis_lsp_istype_vals), ISIS_LSP_IS_TYPE_MASK,
2761                         NULL, HFILL }},
2762
2763                 { &hf_isis_lsp_spb_link_metric,
2764                 { "SPB Link Metric", "isis.lsp.spb.link_metric",
2765                         FT_UINT24, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
2766
2767                 { &hf_isis_lsp_spb_port_count,
2768                 { "Number of Ports", "isis.lsp.spb.port_count",
2769                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2770
2771                 { &hf_isis_lsp_spb_port_id,
2772                 { "Port Id", "isis.lsp.spb.port_id",
2773                         FT_UINT16, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
2774
2775                 { &hf_isis_lsp_spb_sr_bit,
2776                 { "SR Bit", "isis.lsp.spb.sr_bit",
2777                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2778
2779                 { &hf_isis_lsp_spb_spvid,
2780                 { "SPVID", "isis.lsp.spb.spvid",
2781                         FT_UINT16, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
2782
2783       /* Generated from convert_proto_tree_add_text.pl */
2784       { &hf_isis_lsp_mt_id_reserved, { "Reserved", "isis.lsp.reserved", FT_UINT16, BASE_HEX, NULL, ISIS_LSP_MT_MSHIP_RES_MASK, NULL, HFILL }},
2785       { &hf_isis_lsp_mt_id, { "MT ID", "isis.lsp.mt_id", FT_UINT16, BASE_DEC, NULL, ISIS_LSP_MT_MSHIP_ID_MASK, NULL, HFILL }},
2786       { &hf_isis_lsp_ip_reachability_ipv4_prefix, { "IPv4 prefix", "isis.lsp.ip_reachability.ipv4_prefix", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2787       { &hf_isis_lsp_ip_reachability_default_metric, { "Default Metric", "isis.lsp.ip_reachability.default_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2788       { &hf_isis_lsp_ip_reachability_delay_metric, { "Delay Metric", "isis.lsp.ip_reachability.delay_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2789       { &hf_isis_lsp_ip_reachability_expense_metric, { "Expense Metric", "isis.lsp.ip_reachability.expense_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2790       { &hf_isis_lsp_ip_reachability_error_metric, { "Error Metric", "isis.lsp.ip_reachability.error_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2791       { &hf_isis_lsp_32_bit_administrative_tag, { "32-Bit Administrative tag", "isis.lsp.32_bit_administrative_tag", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2792       { &hf_isis_lsp_64_bit_administrative_tag, { "64-Bit Administrative tag", "isis.lsp.64_bit_administrative_tag", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2793       { &hf_isis_lsp_ext_ip_reachability_ipv4_prefix, { "IPv4 prefix", "isis.lsp.ext_ip_reachability.ipv4_prefix", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2794       { &hf_isis_lsp_ext_ip_reachability_metric, { "Metric", "isis.lsp.ext_ip_reachability.metric", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2795       { &hf_isis_lsp_ext_ip_reachability_distribution, { "Distribution", "isis.lsp.ext_ip_reachability.distribution", FT_BOOLEAN, 8, TFS(&tfs_up_down), 0x80, NULL, HFILL }},
2796       { &hf_isis_lsp_grp_address_length, { "Length", "isis.lsp.grp_address.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2797       { &hf_isis_lsp_grp_address_topology_id, { "Topology ID", "isis.lsp.grp_address.topology_id", FT_UINT16, BASE_DEC, NULL, 0x0fff, NULL, HFILL }},
2798       { &hf_isis_lsp_grp_address_vlan_id, { "VLAN ID", "isis.lsp.grp_address.vlan_id", FT_UINT16, BASE_DEC, NULL, 0x0fff, NULL, HFILL }},
2799       { &hf_isis_lsp_grp_address_number_of_records, { "Number of records", "isis.lsp.grp_address.number_of_records", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2800       { &hf_isis_lsp_grp_address_number_of_sources, { "Number of sources", "isis.lsp.grp_address.number_of_sources", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2801       { &hf_isis_lsp_grp_address_group_address, { "Group Address", "isis.lsp.grp_address.group_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2802       { &hf_isis_lsp_grp_address_source_address, { "Source Address", "isis.lsp.grp_address.source_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2803       { &hf_isis_lsp_rt_capable_trill_length, { "Length", "isis.lsp.rt_capable.trill.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2804       { &hf_isis_lsp_rt_capable_trill_maximum_version, { "Maximum version", "isis.lsp.rt_capable.trill.maximum_version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2805       { &hf_isis_lsp_rt_capable_trees_length, { "Length", "isis.lsp.rt_capable.trees.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2806       { &hf_isis_lsp_rt_capable_trees_nof_trees_to_compute, { "Nof. trees to compute", "isis.lsp.rt_capable.trees.nof_trees_to_compute", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2807       { &hf_isis_lsp_rt_capable_trees_maximum_nof_trees_to_compute, { "Maximum nof. trees to compute", "isis.lsp.rt_capable.trees.maximum_nof_trees_to_compute", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2808       { &hf_isis_lsp_rt_capable_trees_nof_trees_to_use, { "Nof. trees to use", "isis.lsp.rt_capable.trees.nof_trees_to_use", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2809       { &hf_isis_lsp_rt_capable_tree_root_id_length, { "Length", "isis.lsp.rt_capable.tree_root_id.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2810       { &hf_isis_lsp_rt_capable_tree_root_id_starting_tree_no, { "Starting tree no", "isis.lsp.rt_capable.tree_root_id.starting_tree_no", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2811       { &hf_isis_lsp_rt_capable_tree_root_id_nickname, { "Nickname", "isis.lsp.rt_capable.tree_root_id.nickname", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2812       { &hf_isis_lsp_rt_capable_nickname_length, { "Length", "isis.lsp.rt_capable.nickname.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2813       { &hf_isis_lsp_rt_capable_nickname_nickname_priority, { "Nickname priority", "isis.lsp.rt_capable.nickname.nickname_priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2814       { &hf_isis_lsp_rt_capable_nickname_tree_root_priority, { "Tree root priority", "isis.lsp.rt_capable.nickname.tree_root_priority", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2815       { &hf_isis_lsp_rt_capable_nickname_nickname, { "Nickname", "isis.lsp.rt_capable.nickname.nickname", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2816       { &hf_isis_lsp_rt_capable_interested_vlans_length, { "Length", "isis.lsp.rt_capable.interested_vlans.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2817       { &hf_isis_lsp_rt_capable_interested_vlans_nickname, { "Nickname", "isis.lsp.rt_capable.interested_vlans.nickname", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2818       { &hf_isis_lsp_rt_capable_interested_vlans_multicast_ipv4, { "IPv4 multicast router", "isis.lsp.rt_capable.interested_vlans.multicast_ipv4", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x8000, NULL, HFILL }},
2819       { &hf_isis_lsp_rt_capable_interested_vlans_multicast_ipv6, { "IPv6 multicast router", "isis.lsp.rt_capable.interested_vlans.multicast_ipv6", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x4000, NULL, HFILL }},
2820       { &hf_isis_lsp_rt_capable_interested_vlans_vlan_start_id, { "Vlan start id", "isis.lsp.rt_capable.interested_vlans.vlan_start_id", FT_UINT16, BASE_HEX, NULL, 0x0fff, NULL, HFILL }},
2821       { &hf_isis_lsp_rt_capable_interested_vlans_vlan_end_id, { "Vlan end id", "isis.lsp.rt_capable.interested_vlans.vlan_end_id", FT_UINT16, BASE_HEX, NULL, 0x0fff, NULL, HFILL }},
2822       { &hf_isis_lsp_rt_capable_interested_vlans_afs_lost_counter, { "Appointed forward state lost counter", "isis.lsp.rt_capable.interested_vlans.afs_lost_counter", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2823       { &hf_isis_lsp_rt_capable_tree_used_id_length, { "Length", "isis.lsp.rt_capable.tree_used_id.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2824       { &hf_isis_lsp_rt_capable_tree_used_id_starting_tree_no, { "Starting tree no", "isis.lsp.rt_capable.tree_used_id.starting_tree_no", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2825       { &hf_isis_lsp_rt_capable_tree_used_id_nickname, { "Nickname", "isis.lsp.rt_capable.tree_used_id.nickname", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2826       { &hf_isis_lsp_rt_capable_vlan_group_length, { "Length", "isis.lsp.rt_capable.vlan_group.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2827       { &hf_isis_lsp_rt_capable_vlan_group_primary_vlan_id, { "Primary vlan id", "isis.lsp.rt_capable.vlan_group.primary_vlan_id", FT_UINT16, BASE_DEC, NULL, 0x0fff, NULL, HFILL }},
2828       { &hf_isis_lsp_rt_capable_vlan_group_secondary_vlan_id, { "Secondary vlan id", "isis.lsp.rt_capable.vlan_group.secondary_vlan_id", FT_UINT16, BASE_DEC, NULL, 0x0fff, NULL, HFILL }},
2829       { &hf_isis_lsp_rt_capable_vlan_group_nth_secondary_vlan_id, { "%dth secondary vlan id", "isis.lsp.rt_capable.vlan_group.nth_secondary_vlan_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2830       { &hf_isis_lsp_ipv6_reachability_ipv6_prefix, { "IPv6 prefix", "isis.lsp.ipv6_reachability.ipv6_prefix", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2831       { &hf_isis_lsp_ipv6_reachability_metric, { "Metric", "isis.lsp.ipv6_reachability.metric", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2832       { &hf_isis_lsp_ipv6_reachability_distribution, { "Distribution", "isis.lsp.ipv6_reachability.distribution", FT_BOOLEAN, 8, TFS(&tfs_up_down), 0x80, NULL, HFILL }},
2833       { &hf_isis_lsp_ipv6_reachability_distribution_internal, { "Distribution", "isis.lsp.ipv6_reachability.distribution_internal", FT_BOOLEAN, 8, TFS(&tfs_internal_external), 0x40, NULL, HFILL }},
2834       { &hf_isis_lsp_ipv6_reachability_reserved_bits, { "Reserved bits", "isis.lsp.ipv6_reachability.reserved_bits", FT_UINT8, BASE_HEX, NULL, 0x1F, NULL, HFILL }},
2835       { &hf_isis_lsp_mt_cap_spb_instance_cist_root_identifier, { "CIST Root Identifier", "isis.lsp.mt_cap_spb_instance.cist_root_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2836       { &hf_isis_lsp_mt_cap_spb_instance_cist_external_root_path_cost, { "CIST External Root Path Cost", "isis.lsp.mt_cap_spb_instance.cist_external_root_path_cost", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2837       { &hf_isis_lsp_mt_cap_spb_instance_bridge_priority, { "Bridge Priority", "isis.lsp.mt_cap_spb_instance.bridge_priority", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2838       { &hf_isis_lsp_mt_cap_spb_instance_v, { "V", "isis.lsp.mt_cap_spb_instance.v", FT_BOOLEAN, 32, NULL, 0x00100000, NULL, HFILL }},
2839       { &hf_isis_lsp_mt_cap_spb_instance_number_of_trees, { "Number of Trees", "isis.lsp.mt_cap_spb_instance.number_of_trees", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2840       { &hf_isis_lsp_mt_cap_spbm_service_identifier_b_mac, { "B-MAC", "isis.lsp.mt_cap_spbm_service_identifier.b_mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2841       { &hf_isis_lsp_mt_cap_spbm_service_identifier_base_vid, { "Base-VID", "isis.lsp.mt_cap_spbm_service_identifier.base_vid", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2842       { &hf_isis_lsp_mt_cap_mtid, { "MTID", "isis.lsp.mt_cap.mtid", FT_UINT16, BASE_HEX, NULL, 0xfff, NULL, HFILL }},
2843       { &hf_isis_lsp_eis_neighbors_reserved, { "Reserved", "isis.lsp.eis_neighbors_clv_inner.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2844       { &hf_isis_lsp_eis_neighbors_es_neighbor_id, { "ES Neighbor ID", "isis.lsp.eis_neighbors.es_neighbor_id", FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2845       { &hf_isis_lsp_eis_neighbors_is_neighbor_id, { "IS Neighbor", "isis.lsp.eis_neighbors.is_neighbor", FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2846       { &hf_isis_lsp_eis_neighbors_default_metric, { "Default Metric", "isis.lsp.eis_neighbors.default_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2847       { &hf_isis_lsp_eis_neighbors_delay_metric, { "Delay Metric", "isis.lsp.eis_neighbors.delay_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2848       { &hf_isis_lsp_eis_neighbors_expense_metric, { "Expense Metric", "isis.lsp.eis_neighbors.expense_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2849       { &hf_isis_lsp_eis_neighbors_error_metric, { "Error Metric", "isis.lsp.eis_neighbors.error_metric", FT_UINT8, BASE_DEC, NULL, 0x3F, NULL, HFILL }},
2850       { &hf_isis_lsp_maximum_link_bandwidth, { "Maximum link bandwidth", "isis.lsp.maximum_link_bandwidth", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2851       { &hf_isis_lsp_reservable_link_bandwidth, { "Reservable link bandwidth", "isis.lsp.reservable_link_bandwidth", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2852       { &hf_isis_lsp_ext_is_reachability_is_neighbor_id, { "IS neighbor ID", "isis.lsp.ext_is_reachability.is_neighbor_id", FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2853       { &hf_isis_lsp_ext_is_reachability_metric, { "Metric", "isis.lsp.ext_is_reachability.metric", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2854       { &hf_isis_lsp_ext_is_reachability_link_local_identifier, { "Link Local Identifier", "isis.lsp.ext_is_reachability.link_local_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2855       { &hf_isis_lsp_ext_is_reachability_link_remote_identifier, { "Link Remote Identifier", "isis.lsp.ext_is_reachability.link_remote_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2856       { &hf_isis_lsp_ext_is_reachability_ipv4_interface_address, { "IPv4 interface address", "isis.lsp.ext_is_reachability.ipv4_interface_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2857       { &hf_isis_lsp_ext_is_reachability_ipv4_neighbor_address, { "IPv4 neighbor address", "isis.lsp.ext_is_reachability.ipv4_neighbor_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2858       { &hf_isis_lsp_ext_is_reachability_traffic_engineering_default_metric, { "Traffic engineering default metric", "isis.lsp.ext_is_reachability.traffic_engineering_default_metric", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2859       { &hf_isis_lsp_partition_designated_l2_is, { "Partition designated L2 IS", "isis.lsp.partition_designated_l2_is", FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2860       { &hf_isis_lsp_error_metric, { "Error metric", "isis.lsp.error_metric", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x08, NULL, HFILL }},
2861       { &hf_isis_lsp_expense_metric, { "Expense metric", "isis.lsp.expense_metric", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x04, NULL, HFILL }},
2862       { &hf_isis_lsp_delay_metric, { "Delay metric", "isis.lsp.delay_metric", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x02, NULL, HFILL }},
2863       { &hf_isis_lsp_default_metric, { "Default metric", "isis.lsp.default_metric", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x01, NULL, HFILL }},
2864       { &hf_isis_lsp_ip_reachability_default_metric_ie, { "Default Metric IE", "isis.lsp.ip_reachability.default_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2865       { &hf_isis_lsp_ip_reachability_delay_metric_support, { "Delay Metric", "isis.lsp.ip_reachability.delay_metric_support", FT_BOOLEAN, 8, TFS(&tfs_notsupported_supported), 0x80, NULL, HFILL }},
2866       { &hf_isis_lsp_ip_reachability_expense_metric_support, { "Expense Metric", "isis.lsp.ip_reachability.expense_metric_support", FT_BOOLEAN, 8, TFS(&tfs_notsupported_supported), 0x80, NULL, HFILL }},
2867       { &hf_isis_lsp_ip_reachability_error_metric_support, { "Error Metric", "isis.lsp.ip_reachability.error_metric_support", FT_BOOLEAN, 8, TFS(&tfs_notsupported_supported), 0x80, NULL, HFILL }},
2868       { &hf_isis_lsp_mt_cap_spsourceid, { "SPSourceId", "isis.lsp.mt_cap.spsourceid", FT_UINT32, BASE_HEX_DEC, NULL, 0xfffff, NULL, HFILL }},
2869       { &hf_isis_lsp_mt_cap_overload, { "Overload", "isis.lsp.overload", FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL }},
2870       { &hf_isis_lsp_eis_neighbors_default_metric_ie, { "Default Metric", "isis.lsp.eis_neighbors.default_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2871       { &hf_isis_lsp_eis_neighbors_delay_metric_supported, { "Delay Metric", "isis.lsp.eis_neighbors_delay_metric.supported", FT_BOOLEAN, 8, TFS(&tfs_notsupported_supported), 0x80, NULL, HFILL }},
2872       { &hf_isis_lsp_eis_neighbors_expense_metric_supported, { "Expense Metric", "isis.lsp.eis_neighbors.expense_metric_supported", FT_BOOLEAN, 8, TFS(&tfs_notsupported_supported), 0x80, NULL, HFILL }},
2873       { &hf_isis_lsp_eis_neighbors_error_metric_supported, { "Error Metric", "isis.lsp.eis_neighbors.error_metric_supported", FT_BOOLEAN, 8, TFS(&tfs_notsupported_supported), 0x80, NULL, HFILL }},
2874       { &hf_isis_lsp_unrsv_bw_priority_level, { "priority level", "isis.lsp.unrsv_bw.priority_level", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2875       { &hf_isis_lsp_ip_reachability_distribution, { "Distribution", "isis.lsp.ip_reachability.distribution", FT_BOOLEAN, 8, TFS(&tfs_up_down), 0x80, NULL, HFILL }},
2876       { &hf_isis_lsp_ip_reachability_delay_metric_ie, { "Delay Metric", "isis.lsp.ip_reachability.delay_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2877       { &hf_isis_lsp_ip_reachability_expense_metric_ie, { "Expense Metric", "isis.lsp.ip_reachability.expense_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2878       { &hf_isis_lsp_ip_reachability_error_metric_ie, { "Error Metric", "isis.lsp.ip_reachability.error_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2879       { &hf_isis_lsp_eis_neighbors_delay_metric_ie, { "Delay Metric", "isis.lsp.eis_neighbors.delay_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2880       { &hf_isis_lsp_eis_neighbors_expense_metric_ie, { "Expense Metric", "isis.lsp.eis_neighbors.expense_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2881       { &hf_isis_lsp_eis_neighbors_error_metric_ie, { "Error Metric", "isis.lsp.eis_neighbors.error_metric_ie", FT_BOOLEAN, 8, TFS(&tfs_external_internal), 0x40, NULL, HFILL }},
2882         };
2883         static gint *ett[] = {
2884                 &ett_isis_lsp,
2885                 &ett_isis_lsp_info,
2886                 &ett_isis_lsp_att,
2887                 &ett_isis_lsp_cksum,
2888                 &ett_isis_lsp_clv_area_addr,
2889                 &ett_isis_lsp_clv_is_neighbors,
2890                 &ett_isis_lsp_clv_ext_is_reachability, /* CLV 22 */
2891                 &ett_isis_lsp_part_of_clv_ext_is_reachability,
2892                 &ett_isis_lsp_subclv_admin_group,
2893                 &ett_isis_lsp_subclv_unrsv_bw,
2894                 &ett_isis_lsp_subclv_spb_link_metric,
2895                 &ett_isis_lsp_clv_unknown,
2896                 &ett_isis_lsp_clv_partition_dis,
2897                 &ett_isis_lsp_clv_prefix_neighbors,
2898                 &ett_isis_lsp_clv_authentication,
2899                 &ett_isis_lsp_clv_ip_authentication,
2900                 &ett_isis_lsp_clv_nlpid,
2901                 &ett_isis_lsp_clv_hostname,
2902                 &ett_isis_lsp_clv_ipv4_int_addr,
2903                 &ett_isis_lsp_clv_ipv6_int_addr, /* CLV 232 */
2904                 &ett_isis_lsp_clv_mt_cap,
2905                 &ett_isis_lsp_clv_mt_cap_spb_instance,
2906                 &ett_isis_lsp_clv_mt_cap_spbm_service_identifier,
2907                 &ett_isis_lsp_clv_te_router_id,
2908                 &ett_isis_lsp_clv_ip_reachability,
2909                 &ett_isis_lsp_clv_ip_reach_subclv,
2910                 &ett_isis_lsp_clv_ext_ip_reachability, /* CLV 135 */
2911                 &ett_isis_lsp_part_of_clv_ext_ip_reachability,
2912                 &ett_isis_lsp_clv_ipv6_reachability, /* CLV 236 */
2913                 &ett_isis_lsp_part_of_clv_ipv6_reachability,
2914                 &ett_isis_lsp_clv_mt,
2915                 &ett_isis_lsp_clv_mt_is,
2916                 &ett_isis_lsp_part_of_clv_mt_is,
2917                 &ett_isis_lsp_clv_rt_capable_IPv4_prefx,
2918                 &ett_isis_lsp_clv_grp_address_IPv4_prefx,    /*CLV 142*/
2919                 &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
2920                 &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
2921                 &ett_isis_lsp_clv_mt_cap_spbv_mac_address
2922         };
2923
2924         static ei_register_info ei[] = {
2925                 { &ie_isis_lsp_checksum_bad, { "isis.lsp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2926                 { &ei_isis_lsp_short_packet, { "isis.lsp.short_packet", PI_MALFORMED, PI_ERROR, "Short packet", EXPFILL }},
2927                 { &ei_isis_lsp_long_packet, { "isis.lsp.long_packet", PI_MALFORMED, PI_ERROR, "Long packet", EXPFILL }},
2928                 { &ei_isis_lsp_subtlv, { "isis.lsp.subtlv.unknown", PI_PROTOCOL, PI_WARN, "Unknown SubTLV", EXPFILL }},
2929                 { &ei_isis_lsp_authentication, { "isis.lsp.authentication.unknown", PI_PROTOCOL, PI_WARN, "Unknown authentication type", EXPFILL }},
2930         };
2931
2932         expert_module_t* expert_isis_lsp;
2933
2934         /* Register the protocol name and description */
2935         proto_isis_lsp = proto_register_protocol(PROTO_STRING_LSP, "ISIS LSP", "isis.lsp");
2936
2937         proto_register_field_array(proto_isis_lsp, hf, array_length(hf));
2938         proto_register_subtree_array(ett, array_length(ett));
2939         expert_isis_lsp = expert_register_protocol(proto_isis_lsp);
2940         expert_register_field_array(expert_isis_lsp, ei, array_length(ei));
2941 }
2942
2943 void
2944 proto_reg_handoff_isis_lsp(void)
2945 {
2946         dissector_add_uint("isis.type", ISIS_TYPE_L1_LSP, new_create_dissector_handle(dissect_isis_l1_lsp, proto_isis_lsp));
2947         dissector_add_uint("isis.type", ISIS_TYPE_L2_LSP, new_create_dissector_handle(dissect_isis_l2_lsp, proto_isis_lsp));
2948 }