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