Fetch values only once from the tvbuff, and save them in a variable,
[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.20 2001/07/02 01:41:25 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  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <glib.h>
39 #include "packet.h"
40 #include "packet-osi.h"
41 #include "packet-isis.h"
42 #include "packet-isis-clv.h"
43 #include "packet-isis-hello.h"
44
45 /* hello packets */
46 static int proto_isis_hello                  = -1;
47 static int hf_isis_hello_circuit_reserved    = -1;
48 static int hf_isis_hello_source_id           = -1;
49 static int hf_isis_hello_holding_timer       = -1;
50 static int hf_isis_hello_pdu_length          = -1;
51 static int hf_isis_hello_priority_reserved   = -1;
52 static int hf_isis_hello_lan_id              = -1;
53 static int hf_isis_hello_local_circuit_id    = -1;
54 static int hf_isis_hello_clv_ipv4_int_addr   = -1;
55 static int hf_isis_hello_clv_ipv6_int_addr   = -1;
56 static int hf_isis_hello_clv_ptp_adj         = -1;
57 static int hf_isis_hello_clv_mt              = -1;
58
59 static gint ett_isis_hello                   = -1;
60 static gint ett_isis_hello_clv_area_addr     = -1;
61 static gint ett_isis_hello_clv_is_neighbors  = -1;
62 static gint ett_isis_hello_clv_padding       = -1;
63 static gint ett_isis_hello_clv_unknown       = -1;
64 static gint ett_isis_hello_clv_nlpid         = -1;
65 static gint ett_isis_hello_clv_auth          = -1;
66 static gint ett_isis_hello_clv_ipv4_int_addr = -1;
67 static gint ett_isis_hello_clv_ipv6_int_addr = -1;
68 static gint ett_isis_hello_clv_ptp_adj       = -1;
69 static gint ett_isis_hello_clv_mt            = -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
109
110 static const isis_clv_handle_t clv_l1_hello_opts[] = {
111         {
112                 ISIS_CLV_L1H_AREA_ADDRESS,
113                 "Area address(es)",
114                 &ett_isis_hello_clv_area_addr,
115                 dissect_hello_area_address_clv
116         },
117         {
118                 ISIS_CLV_L1H_IS_NEIGHBORS,
119                 "IS Neighbor(s)",
120                 &ett_isis_hello_clv_is_neighbors,
121                 dissect_hello_is_neighbors_clv
122         },
123         {
124                 ISIS_CLV_L1H_PADDING,
125                 "Padding",
126                 &ett_isis_hello_clv_padding,
127                 dissect_hello_padding_clv
128         },
129         {
130                 ISIS_CLV_L1H_NLPID,
131                 "Protocols Supported",
132                 &ett_isis_hello_clv_nlpid,
133                 dissect_hello_nlpid_clv
134         },
135         {
136                 ISIS_CLV_L1H_IP_INTERFACE_ADDR,
137                 "IP Interface address(es)",
138                 &ett_isis_hello_clv_ipv4_int_addr,
139                 dissect_hello_ip_int_addr_clv
140         },
141         {
142                 ISIS_CLV_L1H_IPv6_INTERFACE_ADDR,
143                 "IPv6 Interface address(es)",
144                 &ett_isis_hello_clv_ipv6_int_addr,
145                 dissect_hello_ipv6_int_addr_clv
146         },
147         {
148                 ISIS_CLV_L1H_AUTHENTICATION_NS,
149                 "Authentication(non spec)",
150                 &ett_isis_hello_clv_auth,
151                 dissect_hello_auth_clv
152         },
153         {
154                 ISIS_CLV_L1H_AUTHENTICATION,
155                 "Authentication",
156                 &ett_isis_hello_clv_auth,
157                 dissect_hello_auth_clv
158         },
159         {
160                 ISIS_CLV_L1H_MT,
161                 "Multi Topology",
162                 &ett_isis_hello_clv_mt,
163                 dissect_hello_mt_clv
164         },
165         {
166                 0,
167                 "",
168                 NULL,
169                 NULL
170         }
171 };
172
173 static const isis_clv_handle_t clv_l2_hello_opts[] = {
174         {
175                 ISIS_CLV_L2H_AREA_ADDRESS,
176                 "Area address(es)",
177                 &ett_isis_hello_clv_area_addr,
178                 dissect_hello_area_address_clv
179         },
180         {
181                 ISIS_CLV_L2H_IS_NEIGHBORS,
182                 "IS Neighbor(s)",
183                 &ett_isis_hello_clv_is_neighbors,
184                 dissect_hello_is_neighbors_clv
185         },
186         {
187                 ISIS_CLV_L2H_PADDING,
188                 "Padding",
189                 &ett_isis_hello_clv_padding,
190                 dissect_hello_padding_clv
191         },
192         {
193                 ISIS_CLV_L2H_NLPID,
194                 "Protocols Supported",
195                 &ett_isis_hello_clv_nlpid,
196                 dissect_hello_nlpid_clv
197         },
198         {
199                 ISIS_CLV_L2H_IP_INTERFACE_ADDR,
200                 "IP Interface address(es)",
201                 &ett_isis_hello_clv_ipv4_int_addr,
202                 dissect_hello_ip_int_addr_clv
203         },
204         {
205                 ISIS_CLV_L2H_IPv6_INTERFACE_ADDR,
206                 "IPv6 Interface address(es)",
207                 &ett_isis_hello_clv_ipv6_int_addr,
208                 dissect_hello_ipv6_int_addr_clv
209         },
210         {
211                 ISIS_CLV_L2H_AUTHENTICATION_NS,
212                 "Authentication(non spec)",
213                 &ett_isis_hello_clv_auth,
214                 dissect_hello_auth_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_ADJ,
281                 "point-to-point Adjacency State",
282                 &ett_isis_hello_clv_ptp_adj,
283                 dissect_hello_ptp_adj_clv
284         },
285         {
286                 ISIS_CLV_PTP_MT,
287                 "Multi Topology",
288                 &ett_isis_hello_clv_mt,
289                 dissect_hello_mt_clv
290         },
291         {
292                 0,
293                 "",
294                 NULL,
295                 NULL
296         }
297 };
298
299 /*
300  * Name: dissect_hello_nlpid_clv()
301  *
302  * Description:
303  *      Decode for a hello packets NLPID clv.  Calls into the
304  *      clv common one.
305  *
306  * Input:
307  *      tvbuff_t * : tvbuffer for packet data
308  *      packet_info * : info for current packet
309  *      proto_tree * : proto tree to build on (may be null)
310  *      int : current offset into packet data
311  *      int : length of IDs in packet.
312  *      int : length of this clv
313  *
314  * Output:
315  *      void, will modify proto_tree if not null.
316  */
317 static void 
318 dissect_hello_nlpid_clv(tvbuff_t *tvb, 
319         packet_info *pinfo, proto_tree *tree, int offset, 
320         int id_length, int length)
321 {
322         isis_dissect_nlpid_clv(tvb, pinfo, tree, offset, length);
323 }
324
325 /*
326  * Name: dissect_hello_mt_clv()
327  *
328  * Description:
329  *      Decode for a hello packets Multi Topology clv.  Calls into the
330  *      clv common one.
331  *
332  * Input:
333  *      tvbuff_t * : tvbuffer for packet data
334  *      packet_info * : info for current packet
335  *      proto_tree * : proto tree to build on (may be null)
336  *      int : current offset into packet data
337  *      int : length of IDs in packet.
338  *      int : length of this clv
339  *
340  * Output:
341  *      void, will modify proto_tree if not null.
342  */
343
344 static void 
345 dissect_hello_mt_clv(tvbuff_t *tvb, 
346         packet_info *pinfo, proto_tree *tree, int offset, 
347         int id_length, int length)
348 {
349         isis_dissect_mt_clv(tvb, pinfo, tree, offset, length,
350                 hf_isis_hello_clv_mt );
351 }
352
353 /*
354  * Name: dissect_hello_ip_int_addr_clv()
355  *
356  * Description:
357  *      Decode for a hello packets ip interface addr clv.  Calls into the
358  *      clv common one.
359  *
360  * Input:
361  *      tvbuff_t * : tvbuffer for packet data
362  *      packet_info * : info for current packet
363  *      proto_tree * : proto tree to build on (may be null)
364  *      int : current offset into packet data
365  *      int : length of IDs in packet.
366  *      int : length of this clv
367  *
368  * Output:
369  *      void, will modify proto_tree if not null.
370  */
371 static void 
372 dissect_hello_ip_int_addr_clv(tvbuff_t *tvb, 
373         packet_info *pinfo, proto_tree *tree, int offset, 
374         int id_length, int length)
375 {
376         isis_dissect_ip_int_clv(tvb, pinfo, tree, offset, length,
377                 hf_isis_hello_clv_ipv4_int_addr );
378 }
379
380 /*
381  * Name: dissect_hello_ipv6_int_addr_clv()
382  *
383  * Description:
384  *      Decode for a hello packets ipv6 interface addr clv.  Calls into the
385  *      clv common one.
386  *
387  * Input:
388  *      tvbuff_t * : tvbuffer for packet data
389  *      packet_info * : info for current packet
390  *      proto_tree * : proto tree to build on (may be null)
391  *      int : current offset into packet data
392  *      int : length of IDs in packet.
393  *      int : length of this clv
394  *
395  * Output:
396  *      void, will modify proto_tree if not null.
397  */
398 static void 
399 dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb, 
400         packet_info *pinfo, proto_tree *tree, int offset, 
401         int id_length, int length)
402 {
403         isis_dissect_ipv6_int_clv(tvb, pinfo, tree, offset, length,
404                 hf_isis_hello_clv_ipv6_int_addr );
405 }
406
407 /*
408  * Name: dissect_hello_auth_clv()
409  *
410  * Description:
411  *      Decode for a hello packets authenticaion clv.  Calls into the
412  *      clv common one.  An auth inside a hello packet is a perlink
413  *      password.
414  *
415  * Input:
416  *      tvbuff_t * : tvbuffer for packet data
417  *      packet_info * : info for current packet
418  *      proto_tree * : proto tree to build on (may be null)
419  *      int : current offset into packet data
420  *      int : length of IDs in packet.
421  *      int : length of this clv
422  *
423  * Output:
424  *      void, will modify proto_tree if not null.
425  */
426 static void 
427 dissect_hello_auth_clv(tvbuff_t *tvb, 
428         packet_info *pinfo, proto_tree *tree, int offset, 
429         int id_length, int length)
430 {
431         isis_dissect_authentication_clv(tvb, pinfo, tree, offset,
432                 length, "authentication" );
433 }
434
435 /*
436  * Name: dissect_hello_area_address_clv()
437  *
438  * Description:
439  *      Decode for a hello packets area address clv.  Calls into the
440  *      clv common one.
441  *
442  * Input:
443  *      tvbuff_t * : tvbuffer for packet data
444  *      packet_info * : info for current packet
445  *      proto_tree * : proto tree to build on (may be null)
446  *      int : current offset into packet data
447  *      int : length of IDs in packet.
448  *      int : length of this clv
449  *
450  * Output:
451  *      void, will modify proto_tree if not null.
452  */
453 static void 
454 dissect_hello_area_address_clv(tvbuff_t *tvb, 
455         packet_info *pinfo, proto_tree *tree, int offset, 
456         int id_length, int length)
457 {
458         isis_dissect_area_address_clv(tvb, pinfo, tree, offset, length);
459 }
460
461
462
463 static void 
464 dissect_hello_ptp_adj_clv(tvbuff_t *tvb, 
465                 packet_info *pinfo, proto_tree *tree, int offset, 
466                 int id_length, int length)
467 {
468         char adj_state[20];
469
470         switch(tvb_get_guint8(tvb, offset)) {
471           case 0:
472             strcpy(adj_state,"Up");
473             break;
474           case 1:
475             strcpy(adj_state,"Initializing");
476             break;
477           case 2:
478             strcpy(adj_state,"Down");
479             break;
480           default:
481             strcpy(adj_state,"<illegal value !!!>");
482             }
483
484         switch(length) {
485           case 1:
486             proto_tree_add_text ( tree, tvb, offset, 1,
487                                   "Adjacency State: %s", adj_state );
488             break;
489           case 5:
490             proto_tree_add_text ( tree, tvb, offset, 1,        
491                                   "Adjacency State: %s", adj_state ); 
492             proto_tree_add_text ( tree, tvb, offset+1, 4,        
493                                   "Extended Local Circuit ID: %u", tvb_get_ntohl(tvb, offset+1) ); 
494             break;
495           case 11:
496             proto_tree_add_text ( tree, tvb, offset, 1,
497                                   "Adjacency State: %s", adj_state );
498             proto_tree_add_text ( tree, tvb, offset+1, 4,
499                                   "Extended Local Circuit ID: %u", tvb_get_ntohl(tvb, offset+1) );
500             proto_tree_add_text ( tree, tvb, offset+5, 6,
501                                   "Neighbor System ID: %s", print_system_id( tvb_get_ptr(tvb, offset+5, 6), 6 ) );
502             break;
503           case 15:
504             proto_tree_add_text ( tree, tvb, offset, 1,
505                                   "Adjacency State: %s", adj_state );
506             proto_tree_add_text ( tree, tvb, offset+1, 4,
507                                   "Extended Local Circuit ID: %u", tvb_get_ntohl(tvb, offset+1) );
508             proto_tree_add_text ( tree, tvb, offset+5, 6,
509                                   "Neighbor System ID: %s", print_system_id( tvb_get_ptr(tvb, offset+5, 6), 6 ) );  
510             proto_tree_add_text ( tree, tvb, offset+11, 4,
511                                   "Neighbor Extended Local Circuit ID: %u", tvb_get_ntohl(tvb, offset+11) );
512             break;
513           default:
514             isis_dissect_unknown(tvb, pinfo, tree, offset,
515                                  "malformed TLV (%d vs 1,5,11,15)", length );
516             return;
517         }
518 }
519
520 /*
521  * Name: isis_dissect_is_neighbors_clv()
522  * 
523  * Description:
524  *      Take apart a IS neighbor packet.  A neighbor is n 6 byte packets.
525  *      (they tend to be an 802.3 MAC address, but its not required).
526  *
527  * Input:
528  *      tvbuff_t * : tvbuffer for packet data
529  *      packet_info * : info for current packet
530  *      proto_tree * : protocol display tree to fill out.  May be NULL
531  *      int : offset into packet data where we are.
532  *      int : length of IDs in packet.
533  *      int : length of clv we are decoding
534  * 
535  * Output:
536  *      void, but we will add to proto tree if !NULL.
537  */
538 static void 
539 dissect_hello_is_neighbors_clv(tvbuff_t *tvb, packet_info *pinfo,
540                 proto_tree *tree, int offset, int id_length, int length)
541 {
542         while ( length > 0 ) {
543                 if (length<6) {
544                         isis_dissect_unknown(tvb, pinfo, tree, offset,
545                                 "short is neighbor (%d vs 6)", length );
546                         return;
547                 }
548                 /* 
549                  * Lets turn the area address into "standard" 0000.0000.etc
550                  * format string.  
551                  */
552                 if ( tree ) {
553                         proto_tree_add_text ( tree, tvb, offset, 6, 
554                                 "IS Neighbor: %s", print_system_id( tvb_get_ptr(tvb, offset, 6), 6 ) ); 
555                 }
556                 offset += 6;
557                 length -= 6;
558         }
559 }
560
561 /*
562  * Name: dissect_hello_padding_clv()
563  *
564  * Description:
565  *      Decode for a hello packet's padding clv.  Padding does nothing,
566  *      so we just return.
567  *
568  * Input:
569  *      tvbuff_t * : tvbuffer for packet data
570  *      packet_info * : info for current packet
571  *      proto_tree * : proto tree to build on (may be null)
572  *      int : current offset into packet data
573  *      int : length of IDs in packet.
574  *      int : length of this clv
575  *
576  * Output:
577  *      void
578  */
579 static void 
580 dissect_hello_padding_clv(tvbuff_t *tvb, packet_info *pinfo,
581         proto_tree *tree, int offset, int id_length, int length)
582 {
583         /* nothing to do here! */
584 }
585
586
587 /*
588  * Name: isis_dissect_isis_hello()
589  * 
590  * Description:
591  *      This procedure rips apart the various types of ISIS hellos.  L1H and
592  *      L2H's are identical for the most part, while the PTP hello has
593  *      a shorter header.
594  *
595  * Input:
596  *      tvbuff_t * : tvbuffer for packet data
597  *      packet_info * : info for current packet
598  *      proto_tree * : protocol display tree to add to.  May be NULL.
599  *      int offset : our offset into packet data.
600  *      int : hello type, a la packet-isis.h ISIS_TYPE_* values
601  *      int : header length of packet.
602  *      int : length of IDs in packet.
603  *
604  * Output:
605  *      void, will modify proto_tree if not NULL.
606  */     
607 void 
608 isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
609         int offset, int hello_type, int header_length, int id_length)
610 {
611         proto_item      *ti;
612         proto_tree      *hello_tree = NULL;
613         int             len;
614         guint8          octet;
615         const guint8    *source_id;
616         guint16         pdu_length;
617         const guint8    *lan_id;
618
619         if (!proto_is_protocol_enabled(proto_isis_hello)) {
620                 dissect_data(tvb, offset, pinfo, tree);
621                 return;
622         }
623
624         if (tree) {
625                 ti = proto_tree_add_item(tree, proto_isis_hello, tvb,
626                         offset, tvb_length_remaining(tvb, offset), FALSE);
627                 hello_tree = proto_item_add_subtree(ti, ett_isis_hello);
628                 octet = tvb_get_guint8(tvb, offset);
629                 proto_tree_add_uint_format(hello_tree,
630                         hf_isis_hello_circuit_reserved,
631                         tvb, offset, 1, octet,
632                         "Circuit type              : %s, reserved(0x%02x == 0)",
633                                 val_to_str(octet&ISIS_HELLO_CTYPE_MASK,
634                                         isis_hello_circuit_type_vals,
635                                         "Unknown (0x%x)"),
636                                 octet&ISIS_HELLO_CT_RESERVED_MASK
637                         );
638         }
639         offset += 1;
640
641         if (tree) {
642                 source_id = tvb_get_ptr(tvb, offset, id_length);
643                 proto_tree_add_bytes_format(hello_tree, hf_isis_hello_source_id, tvb,
644                                     offset, id_length, source_id,
645                                     "SystemID{ Sender of PDU } : %s", 
646                                     print_system_id( source_id, id_length ) );
647         }
648         offset += id_length;
649
650         if (tree) {
651                 proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, tvb,
652                                     offset, 2, FALSE);
653         }
654         offset += 2;
655
656         pdu_length = tvb_get_ntohs(tvb, offset);
657         if (tree) {
658                 proto_tree_add_uint(hello_tree, hf_isis_hello_pdu_length, tvb,
659                                     offset, 2, pdu_length);
660         }
661         offset += 2;
662
663         if (hello_type == ISIS_TYPE_PTP_HELLO) {
664                 if (tree) {
665                         proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, tvb,
666                                          offset, 1, FALSE );
667                 }
668                 offset += 1;
669         } else { 
670
671                 if (tree) {
672                         octet = tvb_get_guint8(tvb, offset);
673                         proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, tvb,
674                                     offset, 1, octet,
675                                     "Priority                  : %d, reserved(0x%02x == 0)",
676                                         octet&ISIS_HELLO_PRIORITY_MASK,
677                                         octet&ISIS_HELLO_P_RESERVED_MASK );
678                 }
679                 offset += 1;
680
681                 if (tree) {
682                         lan_id = tvb_get_ptr(tvb, offset, id_length+1);
683                         proto_tree_add_bytes_format(hello_tree, hf_isis_hello_lan_id, tvb, 
684                                      offset, id_length + 1, lan_id,
685                                          "SystemID{ Designated IS } : %s",
686                                               print_system_id( lan_id, id_length + 1 ) );
687                 }
688                 offset += id_length + 1;
689         }
690
691         len = pdu_length;
692         len -= header_length;
693         if (len < 0) {
694                 isis_dissect_unknown(tvb, pinfo, tree, offset,
695                         "Packet header length %d went beyond packet", 
696                         header_length );
697                 return;
698         }
699         /*
700          * Now, we need to decode our CLVs.  We need to pass in
701          * our list of valid ones!
702          */
703         if (hello_type == ISIS_TYPE_L1_HELLO){
704                 isis_dissect_clvs(tvb, pinfo, hello_tree, offset,
705                         clv_l1_hello_opts, len, id_length,
706                         ett_isis_hello_clv_unknown);
707         } else if (hello_type == ISIS_TYPE_L2_HELLO) {
708                 isis_dissect_clvs(tvb, pinfo, hello_tree, offset,
709                         clv_l2_hello_opts, len, id_length,
710                         ett_isis_hello_clv_unknown);
711         } else {
712                 isis_dissect_clvs(tvb, pinfo, hello_tree, offset,
713                         clv_ptp_hello_opts, len, id_length,
714                         ett_isis_hello_clv_unknown);
715         }
716 }
717
718 /*
719  * Name: proto_register_isis_hello()
720  *
721  * Description:
722  *      Register our protocol sub-sets with protocol manager.
723  *      NOTE: this procedure is autolinked by the makefile process that
724  *              builds register.c
725  *
726  * Input: 
727  *      void
728  *
729  * Output:
730  *      void
731  */
732 void
733 proto_register_isis_hello(void) {
734         static hf_register_info hf[] = {
735                 { &hf_isis_hello_circuit_reserved,
736                 { "Circuit type              ", "isis_hello.circuite_type",
737                         FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
738
739                 { &hf_isis_hello_source_id,
740                 { "SystemID{ Sender of PDU } ", "isis_hello.source_id",
741                         FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
742
743                 { &hf_isis_hello_holding_timer,
744                 { "Holding timer             ", "isis_hello.holding_timer", 
745                         FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
746
747                 { &hf_isis_hello_pdu_length,
748                 { "PDU length                ", "isis_hello.pdu_length",
749                         FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
750
751                 { &hf_isis_hello_priority_reserved,
752                  { "Priority                 ", "isis_hello.priority",
753                         FT_UINT8, BASE_DEC, NULL, ISIS_HELLO_P_RESERVED_MASK, "", HFILL }},
754
755                 { &hf_isis_hello_lan_id,
756                 { "SystemID{ Designated IS } ", "isis_hello.lan_id",
757                         FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL }},
758
759                 { &hf_isis_hello_local_circuit_id,
760                 { "Local circuit ID          ", "isis_hello.local_circuit_id",
761                         FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
762
763                 { &hf_isis_hello_clv_ipv4_int_addr,
764                 { "IPv4 interface address    ", "isis_hello.clv_ipv4_int_addr",
765                         FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL }},
766
767                 { &hf_isis_hello_clv_ipv6_int_addr,
768                 { "IPv6 interface address    ", "isis_hello.clv_ipv6_int_addr",
769                         FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL }},
770
771                 { &hf_isis_hello_clv_ptp_adj,
772                 { "point-to-point Adjacency  ", "isis_hello.clv_ptp_adj",
773                         FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
774
775         };
776         static gint *ett[] = {
777                 &ett_isis_hello,
778                 &ett_isis_hello_clv_area_addr,
779                 &ett_isis_hello_clv_is_neighbors,
780                 &ett_isis_hello_clv_padding,
781                 &ett_isis_hello_clv_unknown,
782                 &ett_isis_hello_clv_nlpid,
783                 &ett_isis_hello_clv_auth,
784                 &ett_isis_hello_clv_ipv4_int_addr,
785                 &ett_isis_hello_clv_ipv6_int_addr,
786                 &ett_isis_hello_clv_ptp_adj,
787                 &ett_isis_hello_clv_mt
788         };
789
790         proto_isis_hello = proto_register_protocol("ISIS HELLO",
791             "ISIS HELLO", "isis_hello");
792         proto_register_field_array(proto_isis_hello, hf, array_length(hf));
793         proto_register_subtree_array(ett, array_length(ett));
794 }