Add routines for adding items to a protocol tree that take arguments of
[obnox/wireshark/wip.git] / packet-isis.c
1 /* packet-isis-core.c
2  * Routines for ISO/OSI network and transport protocol packet disassembly, core
3  * bits.
4  *
5  * $Id: packet-isis.c,v 1.10 2000/05/31 05:07:15 guy Exp $
6  * Stuart Stanley <stuarts@mxmail.net>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  *
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <glib.h>
41 #include "packet.h"
42 #include "nlpid.h"
43 #include "packet-osi.h"
44 #include "packet-isis.h"
45 #include "packet-isis-lsp.h"
46 #include "packet-isis-hello.h"
47 #include "packet-isis-snp.h"
48
49
50 /* isis base header */
51 static int proto_isis               = -1;
52
53 static int hf_isis_irpd             = -1;
54 static int hf_isis_header_length    = -1;
55 static int hf_isis_version          = -1;
56 static int hf_isis_system_id_length = -1;
57 static int hf_isis_type             = -1;
58 static int hf_isis_version2         = -1;
59 static int hf_isis_reserved         = -1;
60 static int hf_isis_max_area_adr     = -1;
61
62 static gint ett_isis                = -1;
63
64 static const value_string isis_vals[] = {
65   { ISIS_TYPE_L1_HELLO,  "L1 HELLO"},
66   { ISIS_TYPE_L2_HELLO,  "L2 HELLO"},
67   { ISIS_TYPE_PTP_HELLO, "P2P HELLO"},
68   { ISIS_TYPE_L1_LSP,    "L1 LSP"},
69   { ISIS_TYPE_L2_LSP,    "L2 LSP"},
70   { ISIS_TYPE_L1_CSNP,   "L1 CSNP"},
71   { ISIS_TYPE_L2_CSNP,   "L2 CSNP"},
72   { ISIS_TYPE_L1_PSNP,   "L1 PSNP"},
73   { ISIS_TYPE_L2_PSNP,   "L2 PSNP"},
74   { 0,                   NULL}      };
75
76 /*
77  * Name: dissect_isis_unknown()
78  *
79  * Description:
80  *      There was some error in the protocol and we are in unknown space
81  *      here.  Add a tree item to cover the error and go on.  Note
82  *      that we make sure we don't go off the end of the bleedin packet here!
83  *
84  * Input
85  *      unt offset : Current offset into packet data.
86  *      int len : length of to dump.
87  *      proto_tree * : tree of display data.  May be NULL.
88  *      frame_data * fd : frame data
89  *      char * : format text
90  *
91  * Output:
92  *      void (may modify proto tree)
93  */
94 void
95 isis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd,
96                 char *fmat, ...){
97         va_list ap;
98
99         if ( !IS_DATA_IN_FRAME(offset) ) {
100                 /* 
101                  * big oops   They were off the end of the packet already.
102                  * Just ignore this one.
103                  */
104                 return;
105         }
106         if ( !BYTES_ARE_IN_FRAME(offset, length) ) {
107                 /* 
108                  * length will take us past eop.  Truncate length.
109                  */
110                 length = END_OF_FRAME;
111         }
112
113         va_start(ap, fmat);
114         proto_tree_add_text(tree, NullTVB, offset, length, fmat, ap);
115         va_end(ap);
116 }
117 /*
118  * Name: dissect_isis()
119  * 
120  * Description:
121  *      Main entry area for isis de-mangling.  This will build the
122  *      main isis tree data and call the sub-protocols as needed.
123  *
124  * Input:
125  *      u_char * : packet data
126  *      int : offset into packet where we are (packet_data[offset]== start
127  *              of what we care about)
128  *      frame_data * : frame data (whole packet with extra info)
129  *      proto_tree * : tree of display data.  May be NULL.
130  *
131  * Output:
132  *      void, but we will add to the proto_tree if it is not NULL.
133  */
134 static void
135 dissect_isis(const u_char *pd, int offset, frame_data *fd, 
136                 proto_tree *tree) {
137         isis_hdr_t *ihdr;
138         proto_item *ti;
139         proto_tree *isis_tree = NULL;
140
141         if (check_col(fd, COL_PROTOCOL))
142                 col_add_str(fd, COL_PROTOCOL, "ISIS");
143
144         if (!BYTES_ARE_IN_FRAME(offset, sizeof(*ihdr))) {
145                 isis_dissect_unknown(offset, sizeof(*ihdr), tree, fd,
146                         "not enough capture data for header (%d vs %d)",
147                         sizeof(*ihdr), END_OF_FRAME);
148                 return;
149         }
150
151         ihdr = (isis_hdr_t *) &pd[offset];
152
153         if (ihdr->isis_version != ISIS_REQUIRED_VERSION){
154                 isis_dissect_unknown(offset, END_OF_FRAME, tree, fd,
155                         "Unknown ISIS version (%d vs %d)",
156                         ihdr->isis_version, ISIS_REQUIRED_VERSION );
157                 return;
158         }
159         
160         
161         if (tree) {
162                 ti = proto_tree_add_item(tree, proto_isis, NullTVB, offset, 
163                         END_OF_FRAME, FALSE );
164                 isis_tree = proto_item_add_subtree(ti, ett_isis);
165                 proto_tree_add_uint(isis_tree, hf_isis_irpd, NullTVB, offset, 1,
166                         ihdr->isis_irpd );
167                 proto_tree_add_uint(isis_tree, hf_isis_header_length, NullTVB,
168                         offset + 1, 1, ihdr->isis_header_length );
169                 proto_tree_add_uint(isis_tree, hf_isis_version, NullTVB,
170                         offset + 2, 1, ihdr->isis_version );
171                 proto_tree_add_uint(isis_tree, hf_isis_system_id_length, NullTVB,
172                         offset + 3, 1, ihdr->isis_system_id_len );
173                 proto_tree_add_uint_format(isis_tree, hf_isis_type, NullTVB,
174                         offset + 4, 1, ihdr->isis_type,
175                         "Type               : %s (R:%s%s%s)",
176                         val_to_str(ihdr->isis_type & ISIS_TYPE_MASK, isis_vals,
177                                    "Unknown (0x%x)"),
178                         (ihdr->isis_type & ISIS_R8_MASK) ? "1" : "0",
179                         (ihdr->isis_type & ISIS_R7_MASK) ? "1" : "0",
180                         (ihdr->isis_type & ISIS_R6_MASK) ? "1" : "0");
181                 proto_tree_add_uint(isis_tree, hf_isis_version2, NullTVB,
182                         offset + 5, 1, ihdr->isis_version2 );
183                 proto_tree_add_uint(isis_tree, hf_isis_reserved, NullTVB,
184                         offset + 6, 1, ihdr->isis_reserved );
185                 proto_tree_add_uint(isis_tree, hf_isis_max_area_adr, NullTVB,
186                         offset + 7, 1, ihdr->isis_max_area_adr );
187         }
188
189
190         /*
191          * Let us make sure we use the same names for all our decodes
192          * here.  First, dump the name into info column, and THEN
193          * dispatch the sub-type.
194          */
195         if (check_col(fd, COL_INFO)) {
196                 col_add_str(fd, COL_INFO, val_to_str ( 
197                         ihdr->isis_type&ISIS_TYPE_MASK, isis_vals,
198                         "Unknown (0x%x)" ) );
199         }
200
201         /*
202          * Advance offset (we are past the header).
203          */
204         offset += sizeof(*ihdr);
205         switch (ihdr->isis_type) {
206         case ISIS_TYPE_L1_HELLO:
207                 isis_dissect_isis_hello(ISIS_TYPE_L1_HELLO, 
208                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
209                 break;
210         case ISIS_TYPE_L2_HELLO:
211                 isis_dissect_isis_hello(ISIS_TYPE_L2_HELLO, 
212                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
213                 break;
214         case ISIS_TYPE_PTP_HELLO:
215                 isis_dissect_isis_hello(ISIS_TYPE_PTP_HELLO, 
216                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
217                 break;
218         case ISIS_TYPE_L1_LSP:
219                 isis_dissect_isis_lsp(ISIS_TYPE_L1_LSP, ihdr->isis_header_length,
220                         pd, offset, fd, isis_tree);
221                 break;
222         case ISIS_TYPE_L2_LSP:
223                 isis_dissect_isis_lsp(ISIS_TYPE_L2_LSP, ihdr->isis_header_length,
224                         pd, offset, fd, isis_tree);
225                 break;
226         case ISIS_TYPE_L1_CSNP:
227                 isis_dissect_isis_csnp(ISIS_TYPE_L1_CSNP, 
228                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
229                 break;
230         case ISIS_TYPE_L2_CSNP:
231                 isis_dissect_isis_csnp(ISIS_TYPE_L2_CSNP,
232                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
233                 break;
234         case ISIS_TYPE_L1_PSNP:
235                 isis_dissect_isis_psnp(ISIS_TYPE_L1_PSNP, 
236                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
237                 break;
238         case ISIS_TYPE_L2_PSNP:
239                 isis_dissect_isis_psnp(ISIS_TYPE_L2_PSNP,
240                         ihdr->isis_header_length, pd, offset, fd, isis_tree);
241                 break;
242         default:
243                 isis_dissect_unknown(offset, END_OF_FRAME, tree, fd,
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, "" }},
271
272     { &hf_isis_header_length,
273       { "PDU Header Length  ", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
274
275     { &hf_isis_version,
276       { "Version (==1)      ", "isis.version", FT_UINT8, 
277          BASE_DEC, NULL, 0x0, "" }},
278
279     { &hf_isis_system_id_length,
280       { "System ID Length   ", "isis.sysid_len",        
281         FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
282
283     { &hf_isis_type, 
284       { "PDU Type          :", "isis.type", FT_UINT8, BASE_DEC, 
285         VALS(isis_vals), 0xff, "" }},
286
287     { &hf_isis_version2, 
288       { "Version2 (==1)     ", "isis.version2", FT_UINT8, BASE_DEC, NULL, 
289         0x0, "" }},
290
291     { &hf_isis_reserved,
292       { "Reserved (==0)     ", "isis.reserved", FT_UINT8, BASE_DEC, NULL, 
293         0x0, "" }},
294
295     { &hf_isis_max_area_adr,
296       { "Max.AREAs: (0==3)  ", "isis.max_area_adr", FT_UINT8, BASE_DEC, NULL, 
297       0x0, "" }},
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");
309     proto_register_field_array(proto_isis, hf, array_length(hf));
310     proto_register_subtree_array(ett, array_length(ett));
311 }
312
313 void
314 proto_reg_handoff_isis(void)
315 {
316     dissector_add("osinl", NLPID_ISO10589_ISIS, dissect_isis);
317 }