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