Don't include the header file to get the SNMP version unless we're
[obnox/wireshark/wip.git] / packet-isis-hello.c
1 /* packet-isis-hello.c
2  * Routines for decoding isis hello packets and their CLVs
3  *
4  * $Id: packet-isis-hello.c,v 1.33 2002/08/29 18:52:51 guy Exp $
5  * Stuart Stanley <stuarts@mxmail.net>
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "packet-osi.h"
35 #include "packet-isis.h"
36 #include "packet-isis-clv.h"
37 #include "packet-isis-hello.h"
38 #include "epan/resolv.h"
39
40 /* hello packets */
41 static int hf_isis_hello_circuit_reserved    = -1;
42 static int hf_isis_hello_source_id           = -1;
43 static int hf_isis_hello_holding_timer       = -1;
44 static int hf_isis_hello_pdu_length          = -1;
45 static int hf_isis_hello_priority_reserved   = -1;
46 static int hf_isis_hello_lan_id              = -1;
47 static int hf_isis_hello_local_circuit_id    = -1;
48 static int hf_isis_hello_clv_ipv4_int_addr   = -1;
49 static int hf_isis_hello_clv_ipv6_int_addr   = -1;
50 static int hf_isis_hello_clv_ptp_adj         = -1;
51 static int hf_isis_hello_clv_mt              = -1;
52
53 static gint ett_isis_hello                   = -1;
54 static gint ett_isis_hello_clv_area_addr     = -1;
55 static gint ett_isis_hello_clv_is_neighbors  = -1;
56 static gint ett_isis_hello_clv_padding       = -1;
57 static gint ett_isis_hello_clv_unknown       = -1;
58 static gint ett_isis_hello_clv_nlpid         = -1;
59 static gint ett_isis_hello_clv_auth          = -1;
60 static gint ett_isis_hello_clv_ipv4_int_addr = -1;
61 static gint ett_isis_hello_clv_ipv6_int_addr = -1;
62 static gint ett_isis_hello_clv_ptp_adj       = -1;
63 static gint ett_isis_hello_clv_mt            = -1;
64 static gint ett_isis_hello_clv_restart       = -1;
65
66 static const value_string isis_hello_circuit_type_vals[] = {
67         { ISIS_HELLO_TYPE_RESERVED,     "Reserved 0 (discard PDU)"},
68         { ISIS_HELLO_TYPE_LEVEL_1,      "Level 1 only"},
69         { ISIS_HELLO_TYPE_LEVEL_2,      "Level 2 only"},
70         { ISIS_HELLO_TYPE_LEVEL_12,     "Level 1 and 2"},
71         { 0,            NULL} };
72
73 /*
74  * Predclare dissectors for use in clv dissection.
75  */
76 static void dissect_hello_padding_clv(tvbuff_t *tvb,
77                 proto_tree *tree, int offset, int id_length, int length);
78 static void dissect_hello_is_neighbors_clv(tvbuff_t *tvb,
79                 proto_tree *tree, int offset, int id_length, int length);
80 static void dissect_hello_ptp_adj_clv(tvbuff_t *tvb,
81                 proto_tree *tree, int offset, int id_length, int length);
82 static void dissect_hello_area_address_clv(tvbuff_t *tvb,
83                 proto_tree *tree, int offset, int id_length, int length);
84 static void dissect_hello_auth_clv(tvbuff_t *tvb,
85                 proto_tree *tree, int offset, int id_length, int length);
86 static void dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb,
87                 proto_tree *tree, int offset, int id_length, int length);
88 static void dissect_hello_ip_int_addr_clv(tvbuff_t *tvb,
89                 proto_tree *tree, int offset, int id_length, int length);
90 static void dissect_hello_mt_clv(tvbuff_t *tvb,
91                 proto_tree *tree, int offset, int id_length, int length);
92 static void dissect_hello_nlpid_clv(tvbuff_t *tvb,
93                 proto_tree *tree, int offset, int id_length, int length);
94 static void dissect_hello_restart_clv(tvbuff_t *tvb,
95                 proto_tree *tree, int offset, int id_length, int length);
96
97
98 static const isis_clv_handle_t clv_l1_hello_opts[] = {
99         {
100                 ISIS_CLV_L1H_AREA_ADDRESS,
101                 "Area address(es)",
102                 &ett_isis_hello_clv_area_addr,
103                 dissect_hello_area_address_clv
104         },
105         {
106                 ISIS_CLV_L1H_IS_NEIGHBORS,
107                 "IS Neighbor(s)",
108                 &ett_isis_hello_clv_is_neighbors,
109                 dissect_hello_is_neighbors_clv
110         },
111         {
112                 ISIS_CLV_L1H_PADDING,
113                 "Padding",
114                 &ett_isis_hello_clv_padding,
115                 dissect_hello_padding_clv
116         },
117         {
118                 ISIS_CLV_L1H_NLPID,
119                 "Protocols Supported",
120                 &ett_isis_hello_clv_nlpid,
121                 dissect_hello_nlpid_clv
122         },
123         {
124                 ISIS_CLV_L1H_IP_INTERFACE_ADDR,
125                 "IP Interface address(es)",
126                 &ett_isis_hello_clv_ipv4_int_addr,
127                 dissect_hello_ip_int_addr_clv
128         },
129         {
130                 ISIS_CLV_L1H_IPv6_INTERFACE_ADDR,
131                 "IPv6 Interface address(es)",
132                 &ett_isis_hello_clv_ipv6_int_addr,
133                 dissect_hello_ipv6_int_addr_clv
134         },
135         {
136                 ISIS_CLV_L1H_RESTART,
137                 "Restart Signaling",
138                 &ett_isis_hello_clv_restart,
139                 dissect_hello_restart_clv
140         },
141         {
142                 ISIS_CLV_L1H_AUTHENTICATION_NS,
143                 "Authentication(non spec)",
144                 &ett_isis_hello_clv_auth,
145                 dissect_hello_auth_clv
146         },
147         {
148                 ISIS_CLV_L1H_AUTHENTICATION,
149                 "Authentication",
150                 &ett_isis_hello_clv_auth,
151                 dissect_hello_auth_clv
152         },
153         {
154                 ISIS_CLV_L1H_MT,
155                 "Multi Topology",
156                 &ett_isis_hello_clv_mt,
157                 dissect_hello_mt_clv
158         },
159         {
160                 0,
161                 "",
162                 NULL,
163                 NULL
164         }
165 };
166
167 static const isis_clv_handle_t clv_l2_hello_opts[] = {
168         {
169                 ISIS_CLV_L2H_AREA_ADDRESS,
170                 "Area address(es)",
171                 &ett_isis_hello_clv_area_addr,
172                 dissect_hello_area_address_clv
173         },
174         {
175                 ISIS_CLV_L2H_IS_NEIGHBORS,
176                 "IS Neighbor(s)",
177                 &ett_isis_hello_clv_is_neighbors,
178                 dissect_hello_is_neighbors_clv
179         },
180         {
181                 ISIS_CLV_L2H_PADDING,
182                 "Padding",
183                 &ett_isis_hello_clv_padding,
184                 dissect_hello_padding_clv
185         },
186         {
187                 ISIS_CLV_L2H_NLPID,
188                 "Protocols Supported",
189                 &ett_isis_hello_clv_nlpid,
190                 dissect_hello_nlpid_clv
191         },
192         {
193                 ISIS_CLV_L2H_IP_INTERFACE_ADDR,
194                 "IP Interface address(es)",
195                 &ett_isis_hello_clv_ipv4_int_addr,
196                 dissect_hello_ip_int_addr_clv
197         },
198         {
199                 ISIS_CLV_L2H_IPv6_INTERFACE_ADDR,
200                 "IPv6 Interface address(es)",
201                 &ett_isis_hello_clv_ipv6_int_addr,
202                 dissect_hello_ipv6_int_addr_clv
203         },
204         {
205                 ISIS_CLV_L2H_AUTHENTICATION_NS,
206                 "Authentication(non spec)",
207                 &ett_isis_hello_clv_auth,
208                 dissect_hello_auth_clv
209         },
210         {
211                 ISIS_CLV_L2H_RESTART,
212                 "Restart Signaling",
213                 &ett_isis_hello_clv_restart,
214                 dissect_hello_restart_clv
215         },
216         {
217                 ISIS_CLV_L2H_AUTHENTICATION,
218                 "Authentication",
219                 &ett_isis_hello_clv_auth,
220                 dissect_hello_auth_clv
221         },
222         {
223                 ISIS_CLV_L2H_MT,
224                 "Multi Topology",
225                 &ett_isis_hello_clv_mt,
226                 dissect_hello_mt_clv
227         },
228         {
229                 0,
230                 "",
231                 NULL,
232                 NULL
233         }
234 };
235
236 static const isis_clv_handle_t clv_ptp_hello_opts[] = {
237         {
238                 ISIS_CLV_PTP_AREA_ADDRESS,
239                 "Area address(es)",
240                 &ett_isis_hello_clv_area_addr,
241                 dissect_hello_area_address_clv
242         },
243         {
244                 ISIS_CLV_PTP_PADDING,
245                 "Padding",
246                 &ett_isis_hello_clv_padding,
247                 dissect_hello_padding_clv
248         },
249         {
250                 ISIS_CLV_PTP_NLPID,
251                 "Protocols Supported",
252                 &ett_isis_hello_clv_nlpid,
253                 dissect_hello_nlpid_clv
254         },
255         {
256                 ISIS_CLV_PTP_IP_INTERFACE_ADDR,
257                 "IP Interface address(es)",
258                 &ett_isis_hello_clv_ipv4_int_addr,
259                 dissect_hello_ip_int_addr_clv
260         },
261         {
262                 ISIS_CLV_PTP_IPv6_INTERFACE_ADDR,
263                 "IPv6 Interface address(es)",
264                 &ett_isis_hello_clv_ipv6_int_addr,
265                 dissect_hello_ipv6_int_addr_clv
266         },
267         {
268                 ISIS_CLV_PTP_AUTHENTICATION_NS,
269                 "Authentication(non spec)",
270                 &ett_isis_hello_clv_auth,
271                 dissect_hello_auth_clv
272         },
273         {
274                 ISIS_CLV_PTP_AUTHENTICATION,
275                 "Authentication",
276                 &ett_isis_hello_clv_auth,
277                 dissect_hello_auth_clv
278         },
279         {
280                 ISIS_CLV_PTP_RESTART,
281                 "Restart Option",
282                 &ett_isis_hello_clv_restart,
283                 dissect_hello_restart_clv
284         },
285         {
286                 ISIS_CLV_PTP_ADJ,
287                 "Point-to-point Adjacency State",
288                 &ett_isis_hello_clv_ptp_adj,
289                 dissect_hello_ptp_adj_clv
290         },
291         {
292                 ISIS_CLV_PTP_MT,
293                 "Multi Topology",
294                 &ett_isis_hello_clv_mt,
295                 dissect_hello_mt_clv
296         },
297         {
298                 0,
299                 "",
300                 NULL,
301                 NULL
302         }
303 };
304
305
306 /*
307  * Name: dissect_hello_restart_clv()
308  *
309  * Description:
310  *      Decode for a restart clv - only found in IIHs
311  *      hence no call in the common clv dissector
312  *
313  */
314
315 static void
316 dissect_hello_restart_clv(tvbuff_t *tvb,
317                 proto_tree *tree, int offset, int id_length _U_, int length)
318 {
319         int restart_options;
320
321         if (length != 3) {
322             isis_dissect_unknown(tvb, tree, offset,
323                                  "malformed TLV (%d vs 3)",
324                                  length, 3 );
325             return;
326         }
327
328         restart_options = tvb_get_guint8(tvb, offset);
329
330         proto_tree_add_text ( tree, tvb, offset, 1,
331                               "Restart Request bit %s, "
332                               "Restart Acknowledgement bit %s",
333                               ISIS_MASK_RESTART_RR(restart_options) ? "set" : "clear",
334                               ISIS_MASK_RESTART_RA(restart_options) ? "set" : "clear");
335         proto_tree_add_text ( tree, tvb, offset+1, 2,
336                               "Remaining holding time: %us",
337                               tvb_get_ntohs(tvb, offset+1) );
338 }
339
340 /*
341  * Name: dissect_hello_nlpid_clv()
342  *
343  * Description:
344  *      Decode for a hello packets NLPID clv.  Calls into the
345  *      clv common one.
346  *
347  * Input:
348  *      tvbuff_t * : tvbuffer for packet data
349  *      proto_tree * : proto tree to build on (may be null)
350  *      int : current offset into packet data
351  *      int : length of IDs in packet.
352  *      int : length of this clv
353  *
354  * Output:
355  *      void, will modify proto_tree if not null.
356  */
357 static void
358 dissect_hello_nlpid_clv(tvbuff_t *tvb,
359         proto_tree *tree, int offset, int id_length _U_, int length)
360 {
361         isis_dissect_nlpid_clv(tvb, tree, offset, length);
362 }
363
364 /*
365  * Name: dissect_hello_mt_clv()
366  *
367  * Description:
368  *      Decode for a hello packets Multi Topology clv.  Calls into the
369  *      clv common one.
370  *
371  * Input:
372  *      tvbuff_t * : tvbuffer for packet data
373  *      proto_tree * : proto tree to build on (may be null)
374  *      int : current offset into packet data
375  *      int : length of IDs in packet.
376  *      int : length of this clv
377  *
378  * Output:
379  *      void, will modify proto_tree if not null.
380  */
381
382 static void
383 dissect_hello_mt_clv(tvbuff_t *tvb,
384         proto_tree *tree, int offset, int id_length _U_, int length)
385 {
386         isis_dissect_mt_clv(tvb, tree, offset, length,
387                 hf_isis_hello_clv_mt );
388 }
389
390 /*
391  * Name: dissect_hello_ip_int_addr_clv()
392  *
393  * Description:
394  *      Decode for a hello packets ip interface addr clv.  Calls into the
395  *      clv common one.
396  *
397  * Input:
398  *      tvbuff_t * : tvbuffer for packet data
399  *      proto_tree * : proto tree to build on (may be null)
400  *      int : current offset into packet data
401  *      int : length of IDs in packet.
402  *      int : length of this clv
403  *
404  * Output:
405  *      void, will modify proto_tree if not null.
406  */
407 static void
408 dissect_hello_ip_int_addr_clv(tvbuff_t *tvb,
409         proto_tree *tree, int offset, int id_length _U_, int length)
410 {
411         isis_dissect_ip_int_clv(tvb, tree, offset, length,
412                 hf_isis_hello_clv_ipv4_int_addr );
413 }
414
415 /*
416  * Name: dissect_hello_ipv6_int_addr_clv()
417  *
418  * Description:
419  *      Decode for a hello packets ipv6 interface addr clv.  Calls into the
420  *      clv common one.
421  *
422  * Input:
423  *      tvbuff_t * : tvbuffer for packet data
424  *      proto_tree * : proto tree to build on (may be null)
425  *      int : current offset into packet data
426  *      int : length of IDs in packet.
427  *      int : length of this clv
428  *
429  * Output:
430  *      void, will modify proto_tree if not null.
431  */
432 static void
433 dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb,
434         proto_tree *tree, int offset, int id_length _U_, int length)
435 {
436         isis_dissect_ipv6_int_clv(tvb, tree, offset, length,
437                 hf_isis_hello_clv_ipv6_int_addr );
438 }
439
440 /*
441  * Name: dissect_hello_auth_clv()
442  *
443  * Description:
444  *      Decode for a hello packets authenticaion clv.  Calls into the
445  *      clv common one.  An auth inside a hello packet is a perlink
446  *      password.
447  *
448  * Input:
449  *      tvbuff_t * : tvbuffer for packet data
450  *      proto_tree * : proto tree to build on (may be null)
451  *      int : current offset into packet data
452  *      int : length of IDs in packet.
453  *      int : length of this clv
454  *
455  * Output:
456  *      void, will modify proto_tree if not null.
457  */
458 static void
459 dissect_hello_auth_clv(tvbuff_t *tvb,
460         proto_tree *tree, int offset, int id_length _U_, int length)
461 {
462         isis_dissect_authentication_clv(tvb, tree, offset,
463                 length, "authentication" );
464 }
465
466 /*
467  * Name: dissect_hello_area_address_clv()
468  *
469  * Description:
470  *      Decode for a hello packets area address clv.  Calls into the
471  *      clv common one.
472  *
473  * Input:
474  *      tvbuff_t * : tvbuffer for packet data
475  *      proto_tree * : proto tree to build on (may be null)
476  *      int : current offset into packet data
477  *      int : length of IDs in packet.
478  *      int : length of this clv
479  *
480  * Output:
481  *      void, will modify proto_tree if not null.
482  */
483 static void
484 dissect_hello_area_address_clv(tvbuff_t *tvb,
485         proto_tree *tree, int offset, int id_length _U_, int length)
486 {
487         isis_dissect_area_address_clv(tvb, tree, offset, length);
488 }
489
490
491
492 static void
493 dissect_hello_ptp_adj_clv(tvbuff_t *tvb,
494                 proto_tree *tree, int offset, int id_length _U_, int length)
495 {
496         static const value_string adj_state_vals[] = {
497             { 0, "Up" },
498             { 1, "Initializing" },
499             { 2, "Down" },
500             { 0, NULL }
501         };
502         guint8 adj_state;
503         char *adj_state_str;
504
505         adj_state = tvb_get_guint8(tvb, offset);
506         adj_state_str = val_to_str(adj_state, adj_state_vals, "Unknown (%u)");
507         switch(length) {
508           case 1:
509             proto_tree_add_text ( tree, tvb, offset, 1,
510                                   "Adjacency State: %s", adj_state_str );
511             break;
512           case 5:
513             proto_tree_add_text ( tree, tvb, offset, 1,
514                                   "Adjacency State: %s", adj_state_str );
515             proto_tree_add_text ( tree, tvb, offset+1, 4,
516                                   "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
517             break;
518           case 11:
519             proto_tree_add_text ( tree, tvb, offset, 1,
520                                   "Adjacency State: %s", adj_state_str );
521             proto_tree_add_text ( tree, tvb, offset+1, 4,
522                                   "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
523             proto_tree_add_text ( tree, tvb, offset+5, 6,
524                                   "Neighbor SystemID: %s", print_system_id( tvb_get_ptr(tvb, offset+5, 6), 6 ) );
525             break;
526           case 15:
527             proto_tree_add_text ( tree, tvb, offset, 1,
528                                   "Adjacency State: %s", adj_state_str );
529             proto_tree_add_text ( tree, tvb, offset+1, 4,
530                                   "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
531             proto_tree_add_text ( tree, tvb, offset+5, 6,
532                                   "Neighbor SystemID: %s", print_system_id( tvb_get_ptr(tvb, offset+5, 6), 6 ) );
533             proto_tree_add_text ( tree, tvb, offset+11, 4,
534                                   "Neighbor Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+11) );
535             break;
536           default:
537             isis_dissect_unknown(tvb, tree, offset,
538                                  "malformed TLV (%d vs 1,5,11,15)", length );
539             return;
540         }
541 }
542
543 /*
544  * Name: isis_dissect_is_neighbors_clv()
545  *
546  * Description:
547  *      Take apart a IS neighbor packet.  A neighbor is n 6 byte packets.
548  *      (they tend to be an 802.3 MAC address, but its not required).
549  *
550  * Input:
551  *      tvbuff_t * : tvbuffer for packet data
552  *      proto_tree * : protocol display tree to fill out.  May be NULL
553  *      int : offset into packet data where we are.
554  *      int : length of IDs in packet.
555  *      int : length of clv we are decoding
556  *
557  * Output:
558  *      void, but we will add to proto tree if !NULL.
559  */
560 static void
561 dissect_hello_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
562         int id_length _U_, int length)
563 {
564         while ( length > 0 ) {
565                 if (length<6) {
566                         isis_dissect_unknown(tvb, tree, offset,
567                                 "short is neighbor (%d vs 6)", length );
568                         return;
569                 }
570                 /*
571                  * Lets turn the area address into "standard" 0000.0000.etc
572                  * format string.
573                  */
574                 if ( tree ) {
575                         proto_tree_add_text ( tree, tvb, offset, 6,
576                                 "IS Neighbor: %s", get_ether_name( tvb_get_ptr(tvb, offset, 6)) );
577                 }
578                 offset += 6;
579                 length -= 6;
580         }
581 }
582
583 /*
584  * Name: dissect_hello_padding_clv()
585  *
586  * Description:
587  *      Decode for a hello packet's padding clv.  Padding does nothing,
588  *      so we just return.
589  *
590  * Input:
591  *      tvbuff_t * : tvbuffer for packet data
592  *      proto_tree * : proto tree to build on (may be null)
593  *      int : current offset into packet data
594  *      int : length of IDs in packet.
595  *      int : length of this clv
596  *
597  * Output:
598  *      void
599  */
600 static void
601 dissect_hello_padding_clv(tvbuff_t *tvb _U_, proto_tree *tree _U_, int offset _U_,
602         int id_length _U_, int length _U_)
603 {
604         /* nothing to do here! */
605 }
606
607
608 /*
609  * Name: isis_dissect_isis_hello()
610  *
611  * Description:
612  *      This procedure rips apart the various types of ISIS hellos.  L1H and
613  *      L2H's are identical for the most part, while the PTP hello has
614  *      a shorter header.
615  *
616  * Input:
617  *      tvbuff_t * : tvbuffer for packet data
618  *      proto_tree * : protocol display tree to add to.  May be NULL.
619  *      int offset : our offset into packet data.
620  *      int : hello type, a la packet-isis.h ISIS_TYPE_* values
621  *      int : header length of packet.
622  *      int : length of IDs in packet.
623  *
624  * Output:
625  *      void, will modify proto_tree if not NULL.
626  */
627 void
628 isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
629         int hello_type, int header_length, int id_length)
630 {
631         proto_item      *ti;
632         proto_tree      *hello_tree = NULL;
633         int             len;
634         guint8          octet;
635         const guint8    *source_id;
636         guint16         pdu_length;
637         const guint8    *lan_id;
638
639         if (tree) {
640                 ti = proto_tree_add_text(tree, tvb, offset, -1, "ISIS HELLO");
641                 hello_tree = proto_item_add_subtree(ti, ett_isis_hello);
642                 octet = tvb_get_guint8(tvb, offset);
643                 proto_tree_add_uint_format(hello_tree,
644                         hf_isis_hello_circuit_reserved,
645                         tvb, offset, 1, octet,
646                         "Circuit type              : %s, reserved(0x%02x == 0)",
647                                 val_to_str(octet&ISIS_HELLO_CTYPE_MASK,
648                                         isis_hello_circuit_type_vals,
649                                         "Unknown (0x%x)"),
650                                 octet&ISIS_HELLO_CT_RESERVED_MASK
651                         );
652         }
653         offset += 1;
654
655         if (tree) {
656                 source_id = tvb_get_ptr(tvb, offset, id_length);
657                 proto_tree_add_bytes_format(hello_tree, hf_isis_hello_source_id, tvb,
658                                     offset, id_length, source_id,
659                                     "System-ID {Sender of PDU} : %s", 
660                                     print_system_id( source_id, id_length ) );
661         }
662         if (check_col(pinfo->cinfo, COL_INFO)) {
663                 col_append_fstr(pinfo->cinfo, COL_INFO, ", System-ID: %s",
664                         print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
665         }
666         offset += id_length;
667
668         if (tree) {
669                 proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, tvb,
670                                     offset, 2, FALSE);
671         }
672         offset += 2;
673
674         pdu_length = tvb_get_ntohs(tvb, offset);
675         if (tree) {
676                 proto_tree_add_uint(hello_tree, hf_isis_hello_pdu_length, tvb,
677                                     offset, 2, pdu_length);
678         }
679         offset += 2;
680
681         if (hello_type == ISIS_TYPE_PTP_HELLO) {
682                 if (tree) {
683                         proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, tvb,
684                                          offset, 1, FALSE );
685                 }
686                 offset += 1;
687         } else {
688                 if (tree) {
689                         octet = tvb_get_guint8(tvb, offset);
690                         proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, tvb,
691                                     offset, 1, octet,
692                                     "Priority                  : %d, reserved(0x%02x == 0)",
693                                         octet&ISIS_HELLO_PRIORITY_MASK,
694                                         octet&ISIS_HELLO_P_RESERVED_MASK );
695                 }
696                 offset += 1;
697
698                 if (tree) {
699                         lan_id = tvb_get_ptr(tvb, offset, id_length+1);
700                         proto_tree_add_bytes_format(hello_tree, hf_isis_hello_lan_id, tvb,
701                                      offset, id_length + 1, lan_id,
702                                          "System-ID {Designated IS} : %s",
703                                               print_system_id( lan_id, id_length + 1 ) );
704                 }
705                 offset += id_length + 1;
706         }
707
708         len = pdu_length;
709         len -= header_length;
710         if (len < 0) {
711                 isis_dissect_unknown(tvb, tree, offset,
712                         "Packet header length %d went beyond packet",
713                         header_length );
714                 return;
715         }
716         /*
717          * Now, we need to decode our CLVs.  We need to pass in
718          * our list of valid ones!
719          */
720         if (hello_type == ISIS_TYPE_L1_HELLO){
721                 isis_dissect_clvs(tvb, hello_tree, offset,
722                         clv_l1_hello_opts, len, id_length,
723                         ett_isis_hello_clv_unknown);
724         } else if (hello_type == ISIS_TYPE_L2_HELLO) {
725                 isis_dissect_clvs(tvb, hello_tree, offset,
726                         clv_l2_hello_opts, len, id_length,
727                         ett_isis_hello_clv_unknown);
728         } else {
729                 isis_dissect_clvs(tvb, hello_tree, offset,
730                         clv_ptp_hello_opts, len, id_length,
731                         ett_isis_hello_clv_unknown);
732         }
733 }
734
735 /*
736  * Name: isis_register_hello()
737  *
738  * Description:
739  *      Register our protocol sub-sets with protocol manager.
740  *
741  * Input:
742  *      int : protocol index for the ISIS protocol
743  *
744  * Output:
745  *      void
746  */
747 void
748 isis_register_hello(int proto_isis) {
749         static hf_register_info hf[] = {
750                 { &hf_isis_hello_circuit_reserved,
751                 { "Circuit type              ", "isis.hello.circuit_type",
752                         FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
753
754                 { &hf_isis_hello_source_id,
755                 { "SystemID{ Sender of PDU } ", "isis.hello.source_id",
756                         FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
757
758                 { &hf_isis_hello_holding_timer,
759                 { "Holding timer             ", "isis.hello.holding_timer",
760                         FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
761
762                 { &hf_isis_hello_pdu_length,
763                 { "PDU length                ", "isis.hello.pdu_length",
764                         FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
765
766                 { &hf_isis_hello_priority_reserved,
767                  { "Priority                 ", "isis.hello.priority",
768                         FT_UINT8, BASE_DEC, NULL, ISIS_HELLO_P_RESERVED_MASK, "", HFILL }},
769
770                 { &hf_isis_hello_lan_id,
771                 { "SystemID{ Designated IS } ", "isis.hello.lan_id",
772                         FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL }},
773
774                 { &hf_isis_hello_local_circuit_id,
775                 { "Local circuit ID          ", "isis.hello.local_circuit_id",
776                         FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
777
778                 { &hf_isis_hello_clv_ipv4_int_addr,
779                 { "IPv4 interface address    ", "isis.hello.clv_ipv4_int_addr",
780                         FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL }},
781
782                 { &hf_isis_hello_clv_ipv6_int_addr,
783                 { "IPv6 interface address    ", "isis.hello.clv_ipv6_int_addr",
784                         FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL }},
785
786                 { &hf_isis_hello_clv_ptp_adj,
787                 { "Point-to-point Adjacency  ", "isis.hello.clv_ptp_adj",
788                         FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
789
790                 { &hf_isis_hello_clv_mt,
791                 { "MT-ID                     ", "isis.hello.clv_mt",
792                         FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
793         };
794         static gint *ett[] = {
795                 &ett_isis_hello,
796                 &ett_isis_hello_clv_area_addr,
797                 &ett_isis_hello_clv_is_neighbors,
798                 &ett_isis_hello_clv_padding,
799                 &ett_isis_hello_clv_unknown,
800                 &ett_isis_hello_clv_nlpid,
801                 &ett_isis_hello_clv_auth,
802                 &ett_isis_hello_clv_ipv4_int_addr,
803                 &ett_isis_hello_clv_ipv6_int_addr,
804                 &ett_isis_hello_clv_ptp_adj,
805                 &ett_isis_hello_clv_mt,
806                 &ett_isis_hello_clv_restart
807         };
808
809         proto_register_field_array(proto_isis, hf, array_length(hf));
810         proto_register_subtree_array(ett, array_length(ett));
811 }