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