Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-isis.c
1 /* packet-isis.c
2  * Routines for ISO/OSI network and transport protocol packet disassembly, core
3  * bits.
4  *
5  * $Id: packet-isis.c,v 1.32 2002/08/02 23:35:52 jmayer Exp $
6  * Stuart Stanley <stuarts@mxmail.net>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include "nlpid.h"
36 #include "packet-osi.h"
37 #include "packet-isis.h"
38 #include "packet-isis-lsp.h"
39 #include "packet-isis-hello.h"
40 #include "packet-isis-snp.h"
41
42
43 /* isis base header */
44 static int proto_isis               = -1;
45
46 static int hf_isis_irpd             = -1;
47 static int hf_isis_header_length    = -1;
48 static int hf_isis_version          = -1;
49 static int hf_isis_system_id_length = -1;
50 static int hf_isis_type             = -1;
51 static int hf_isis_version2         = -1;
52 static int hf_isis_reserved         = -1;
53 static int hf_isis_max_area_adr     = -1;
54
55 static gint ett_isis                = -1;
56
57 static const value_string isis_vals[] = {
58   { ISIS_TYPE_L1_HELLO,  "L1 HELLO"},
59   { ISIS_TYPE_L2_HELLO,  "L2 HELLO"},
60   { ISIS_TYPE_PTP_HELLO, "P2P HELLO"},
61   { ISIS_TYPE_L1_LSP,    "L1 LSP"},
62   { ISIS_TYPE_L2_LSP,    "L2 LSP"},
63   { ISIS_TYPE_L1_CSNP,   "L1 CSNP"},
64   { ISIS_TYPE_L2_CSNP,   "L2 CSNP"},
65   { ISIS_TYPE_L1_PSNP,   "L1 PSNP"},
66   { ISIS_TYPE_L2_PSNP,   "L2 PSNP"},
67   { 0,                   NULL}      };
68
69 /*
70  * Name: dissect_isis_unknown()
71  *
72  * Description:
73  *      There was some error in the protocol and we are in unknown space
74  *      here.  Add a tree item to cover the error and go on.  Note
75  *      that we make sure we don't go off the end of the bleedin packet here!
76  *
77  * Input
78  *      tvbuff_t * : tvbuffer for packet data
79  *      proto_tree * : tree of display data.  May be NULL.
80  *      int : current offset into packet data
81  *      char * : format text
82  *      subsequent args : arguments to format
83  *
84  * Output:
85  *      void (may modify proto tree)
86  */
87 void
88 isis_dissect_unknown(tvbuff_t *tvb, proto_tree *tree, int offset,
89         char *fmat, ...)
90 {
91         va_list ap;
92
93         va_start(ap, fmat);
94         proto_tree_add_text_valist(tree, tvb, offset, -1, fmat, ap);
95         va_end(ap);
96 }
97
98 /*
99  * Name: dissect_isis()
100  * 
101  * Description:
102  *      Main entry area for isis de-mangling.  This will build the
103  *      main isis tree data and call the sub-protocols as needed.
104  *
105  * Input:
106  *      tvbuff_t * : tvbuffer for packet data
107  *      packet_info * : info for current packet
108  *      proto_tree * : tree of display data.  May be NULL.
109  *
110  * Output:
111  *      void, but we will add to the proto_tree if it is not NULL.
112  */
113 static void
114 dissect_isis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
115 {
116         proto_item *ti;
117         proto_tree *isis_tree = NULL;
118         int offset = 0;
119         guint8 isis_version;
120         guint8 isis_header_length;
121         guint8 isis_type_reserved;
122         guint8 isis_type;
123         guint8 isis_system_id_len;
124
125         if (check_col(pinfo->cinfo, COL_PROTOCOL))
126                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISIS");
127         if (check_col(pinfo->cinfo, COL_INFO))
128                 col_clear(pinfo->cinfo, COL_INFO);
129
130         isis_version = tvb_get_guint8(tvb, 2);
131         if (isis_version != ISIS_REQUIRED_VERSION){
132                 if (check_col(pinfo->cinfo, COL_INFO)) {
133                         col_add_fstr(pinfo->cinfo, COL_INFO,
134                                 "Unknown ISIS version (%u vs %u)",
135                                 isis_version, ISIS_REQUIRED_VERSION );
136                 }
137                 isis_dissect_unknown(tvb, tree, 0,
138                         "Unknown ISIS version (%d vs %d)",
139                         isis_version, ISIS_REQUIRED_VERSION);
140                 return;
141         }
142         
143         isis_header_length = tvb_get_guint8(tvb, 1);
144         if (tree) {
145                 ti = proto_tree_add_item(tree, proto_isis, tvb, 0, -1, FALSE);
146                 isis_tree = proto_item_add_subtree(ti, ett_isis);
147         }
148
149         if (tree) {
150                 proto_tree_add_item(isis_tree, hf_isis_irpd, tvb, offset, 1,
151                         FALSE );
152         }
153         offset += 1;
154
155         if (tree) {
156                 proto_tree_add_uint(isis_tree, hf_isis_header_length, tvb,
157                         offset, 1, isis_header_length );
158         }
159         offset += 1;
160
161         if (tree) {
162                 proto_tree_add_uint(isis_tree, hf_isis_version, tvb,
163                         offset, 1, isis_version );
164         }
165         offset += 1;
166
167         isis_system_id_len = tvb_get_guint8(tvb, 3);
168         if (tree) {
169                 proto_tree_add_uint(isis_tree, hf_isis_system_id_length, tvb,
170                         offset, 1, isis_system_id_len );
171         }
172         offset += 1;
173
174         isis_type_reserved = tvb_get_guint8(tvb, 4);
175         isis_type = isis_type_reserved & ISIS_TYPE_MASK;
176         if (check_col(pinfo->cinfo, COL_INFO)) {
177                 col_add_str(pinfo->cinfo, COL_INFO,
178                         val_to_str ( isis_type, isis_vals, "Unknown (0x%x)" ) );
179         }
180         if (tree) {
181                 proto_tree_add_uint_format(isis_tree, hf_isis_type, tvb,
182                         offset, 1, isis_type,
183                         "PDU Type           : %s (R:%s%s%s)",
184                         val_to_str(isis_type, isis_vals, "Unknown (0x%x)"),
185                         (isis_type_reserved & ISIS_R8_MASK) ? "1" : "0",
186                         (isis_type_reserved & ISIS_R7_MASK) ? "1" : "0",
187                         (isis_type_reserved & ISIS_R6_MASK) ? "1" : "0");
188         }
189         offset += 1;
190
191         if (tree) {
192                 proto_tree_add_item(isis_tree, hf_isis_version2, tvb, 5, 1,
193                         FALSE );
194         }
195         offset += 1;
196
197         if (tree) {
198                 proto_tree_add_item(isis_tree, hf_isis_reserved, tvb, 6, 1,
199                         FALSE );
200         }
201         offset += 1;
202
203         if (tree) {
204                 proto_tree_add_item(isis_tree, hf_isis_max_area_adr, tvb, 7, 1,
205                         FALSE );
206         }
207         offset += 1;
208
209         /*
210          * Interpret the system ID length.
211          */
212         if (isis_system_id_len == 0)
213                 isis_system_id_len = 6; /* zero means 6-octet ID field length */
214         else if (isis_system_id_len == 255) {
215                 isis_system_id_len = 0; /* 255 means null ID field */
216                 /* XXX - what about the LAN ID? */
217         }
218         /* XXX - otherwise, must be in the range 1 through 8 */
219
220         switch (isis_type) {
221         case ISIS_TYPE_L1_HELLO:
222         case ISIS_TYPE_L2_HELLO:
223         case ISIS_TYPE_PTP_HELLO:
224                 isis_dissect_isis_hello(tvb, isis_tree, offset,
225                         isis_type, isis_header_length, isis_system_id_len);
226                 break;
227         case ISIS_TYPE_L1_LSP:
228         case ISIS_TYPE_L2_LSP:
229                 isis_dissect_isis_lsp(tvb, isis_tree, offset,
230                         isis_type, isis_header_length, isis_system_id_len);
231                 break;
232         case ISIS_TYPE_L1_CSNP:
233         case ISIS_TYPE_L2_CSNP:
234                 isis_dissect_isis_csnp(tvb, isis_tree, offset,
235                         isis_type, isis_header_length, isis_system_id_len);
236                 break;
237         case ISIS_TYPE_L1_PSNP:
238         case ISIS_TYPE_L2_PSNP:
239                 isis_dissect_isis_psnp(tvb, isis_tree, offset,
240                         isis_type, isis_header_length, isis_system_id_len);
241                 break;
242         default:
243                 isis_dissect_unknown(tvb, tree, offset,
244                         "Unknown ISIS packet type");
245         }
246 } /* dissect_isis */
247
248
249 /*
250  * Name: proto_register_isis()
251  *
252  * Description:
253  *      main register for isis protocol set.  We register some display
254  *      formats and the protocol module variables.
255  *
256  *      NOTE: this procedure to autolinked by the makefile process that
257  *      builds register.c
258  *
259  * Input: 
260  *      void
261  *
262  * Output:
263  *      void
264  */
265 void 
266 proto_register_isis(void) {
267   static hf_register_info hf[] = {
268     { &hf_isis_irpd,
269       { "Intra Domain Routing Protocol Discriminator",  "isis.irpd",    
270         FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "", HFILL }},
271
272     { &hf_isis_header_length,
273       { "PDU Header Length  ", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
274
275     { &hf_isis_version,
276       { "Version (==1)      ", "isis.version", FT_UINT8, 
277          BASE_DEC, NULL, 0x0, "", HFILL }},
278
279     { &hf_isis_system_id_length,
280       { "System ID Length   ", "isis.sysid_len",        
281         FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
282
283     { &hf_isis_type, 
284       { "PDU Type           ", "isis.type", FT_UINT8, BASE_DEC, 
285         VALS(isis_vals), 0xff, "", HFILL }},
286
287     { &hf_isis_version2, 
288       { "Version2 (==1)     ", "isis.version2", FT_UINT8, BASE_DEC, NULL, 
289         0x0, "", HFILL }},
290
291     { &hf_isis_reserved,
292       { "Reserved (==0)     ", "isis.reserved", FT_UINT8, BASE_DEC, NULL, 
293         0x0, "", HFILL }},
294
295     { &hf_isis_max_area_adr,
296       { "Max.AREAs: (0==3)  ", "isis.max_area_adr", FT_UINT8, BASE_DEC, NULL, 
297       0x0, "", HFILL }},
298
299     };
300     /*
301      * Note, we pull in the unknown CLV handler here, since it
302      * is used by all ISIS packet types.
303      */
304     static gint *ett[] = {
305       &ett_isis,
306     };
307
308     proto_isis = proto_register_protocol(PROTO_STRING_ISIS, "ISIS", "isis");
309     proto_register_field_array(proto_isis, hf, array_length(hf));
310     proto_register_subtree_array(ett, array_length(ett));
311
312     /*
313      * Call registration routines for other source files in the ISIS
314      * dissector.
315      */
316     isis_register_hello(proto_isis);
317     isis_register_lsp(proto_isis);
318     isis_register_csnp(proto_isis);
319     isis_register_psnp(proto_isis);
320 }
321
322 void
323 proto_reg_handoff_isis(void)
324 {
325     dissector_handle_t isis_handle;
326
327     isis_handle = create_dissector_handle(dissect_isis, proto_isis);
328     dissector_add("osinl", NLPID_ISO10589_ISIS, isis_handle);
329 }