Stuart Stanley's ISIS dissection support.
[obnox/wireshark/wip.git] / packet-isis-clv.c
1 /* packet-isis-clv.c
2  * Common CLV decode routines.
3  *
4  * $Id: packet-isis-clv.c,v 1.1 1999/12/15 04:34:17 guy Exp $
5  * Stuart Stanley <stuarts@mxmail.net>
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
9  * Copyright 1998 Gerald Combs
10  *
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  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <glib.h>
40 #include "packet.h"
41 #include "packet-isis.h"
42 #include "packet-isis-clv.h"
43
44
45 /*
46  * Name: isis_dissect_area_address_clv()
47  * 
48  * Description:
49  *      Take an area address CLV and display it pieces.  An area address
50  *      CLV is n, x byte hex strings.
51  *
52  * Input:
53  *      u_char * : packet data
54  *      int : offset into packet data where we are.
55  *      guint : length of clv we are decoding
56  *      frame_data * : frame data (complete frame)
57  *      proto_tree * : protocol display tree to fill out.  May be NULL
58  * 
59  * Output:
60  *      void, but we will add to proto tree if !NULL.
61  */
62 void 
63 isis_dissect_area_address_clv(const u_char *pd, int offset, 
64                 guint length, frame_data *fd, proto_tree *tree ) {
65         char            *sbuf;
66         int             mylen;
67
68         while ( length > 0 ) {
69                 mylen = pd[offset];
70                 length--;
71                 if (length<=0) {
72                         isis_dissect_unknown( offset, length, tree, fd,
73                                 "short address (no length for payload)");
74                         return;
75                 }
76                 if ( mylen > length) {
77                         isis_dissect_unknown(offset, length, tree, fd, 
78                                 "short address, packet say %d, we have %d left",
79                                 mylen, length );
80                         return;
81                 }
82
83                 /* 
84                  * Lets turn the area address into "standard" 0000.0000.etc
85                  * format string.  
86                  */
87                 sbuf = isis_address_to_string ( pd, offset + 1, mylen );
88                 /* and spit it out */
89                 if ( tree ) {
90                         proto_tree_add_text ( tree, offset, mylen + 1,  
91                                 "Area address (%d): %s", mylen, sbuf );
92                 }
93                 offset += mylen + 1;
94                 length -= mylen;        /* length already adjusted for len fld*/
95         }
96 }
97
98
99 /*
100  * Name: isis_dissect_authentication_clv()
101  * 
102  * Description:
103  *      Take apart the CLV that hold authentication information.  This
104  *      is currently 1 octet auth type (which must be 1) and then
105  *      the clear text password.
106  *      
107  *      An ISIS password has different meaning depending where it
108  *      is found.  Thus we support a passed in prefix string to 
109  *      use to name this.
110  *
111  * Input:
112  *      u_char * : packet data
113  *      int : offset into packet data where we are.
114  *      guint : length of clv we are decoding
115  *      frame_data * : frame data (complete frame)
116  *      proto_tree * : protocol display tree to fill out.  May be NULL
117  *      char * : Password meaning
118  * 
119  * Output:
120  *      void, but we will add to proto tree if !NULL.
121  */
122 void 
123 isis_dissect_authentication_clv(const u_char *pd, int offset, guint length, 
124                 frame_data *fd, proto_tree *tree, char *meaning) {
125         u_char pw_type;
126         char sbuf[300];         /* 255 + header info area */
127         char *s = sbuf;
128         int use_cleartext;
129
130         if ( length <= 0 ) {
131                 return;
132         }
133
134         pw_type = pd[offset++];
135         length--;
136         use_cleartext = FALSE;
137         switch (pw_type) {
138         case 1:
139                 s += sprintf ( s, "type 1, clear text"  );
140                 use_cleartext = TRUE;
141                 break;
142         default:
143                 s += sprintf ( s, "type 0x%02x, (must be 1)", pw_type );
144                 break;
145         }
146
147         s += sprintf ( s, " (0x%02x): ", length );
148
149         if ( use_cleartext ) {
150                 if ( length > 0 ) {
151                         strncpy(s, &pd[offset], length);
152                         /* null terminate */
153                         s[length] = 0;
154                 } else {
155                         strcat(s, "<<no password found!!!>>" );
156                 }
157         /* NOTE, s no longer valid */
158         }
159         proto_tree_add_text ( tree, offset - 1, length + 1,
160                         "%s %s", meaning, sbuf );
161         if ( !use_cleartext ) {
162                 if ( length ) {
163                         isis_dissect_unknown(offset, length, tree, fd,
164                                 "Unknown autheticion type" );
165                 }
166         }
167 }
168 /*
169  * Name: isis_dissect_ip_int_clv()
170  * 
171  * Description:
172  *      Take apart the CLV that lists all the IP interfaces.  The
173  *      meaning of which is slightly different for the different base packet
174  *      types, but the display is not different.  What we have is n ip
175  *      addresses, plain and simple.
176  *
177  * Input:
178  *      u_char * : packet data
179  *      int : offset into packet data where we are.
180  *      guint : length of clv we are decoding
181  *      frame_data * : frame data (complete frame)
182  *      proto_tree * : protocol display tree to fill out.  May be NULL
183  *      gint : tree id to use for proto tree.
184  * 
185  * Output:
186  *      void, but we will add to proto tree if !NULL.
187  */
188 void 
189 isis_dissect_ip_int_clv(const u_char *pd, int offset, 
190                 guint length, frame_data *fd, proto_tree *tree, gint tree_id ) {
191         guint32 addr;
192         if ( length <= 0 ) {
193                 return;
194         }
195
196         while ( length > 0 ) {
197                 if ( length < 4 ) {
198                         isis_dissect_unknown(offset, length, tree, fd,
199                                 "Short ip interface address (%d vs 4)",length );
200                         return;
201                 }
202                 memcpy(&addr, &pd[offset], sizeof(addr));
203                 if ( tree ) {
204                         proto_tree_add_item(tree, tree_id, offset, 4, addr);
205                 }
206                 offset += 4;
207                 length -= 4;
208         }
209 }
210
211 /*
212  * Name: isis_dissect_nlpid_clv()
213  * 
214  * Description:
215  *      Take apart a NLPID packet and display it.  The NLPID (for intergrated
216  *      ISIS, contains n network layer protocol IDs that the box supports.
217  *      Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
218  *      plus 1 for zero termination.  We just just 256*6 for simplicity.
219  *
220  * Input:
221  *      u_char * : packet data
222  *      int : offset into packet data where we are.
223  *      guint : length of clv we are decoding
224  *      frame_data * : frame data (complete frame)
225  *      proto_tree * : protocol display tree to fill out.  May be NULL
226  * 
227  * Output:
228  *      void, but we will add to proto tree if !NULL.
229  */
230 void 
231 isis_dissect_nlpid_clv(const u_char *pd, int offset, 
232                 guint length, frame_data *fd, proto_tree *tree ) {
233         char sbuf[256*6];
234         char *s = sbuf;
235         int hlen = length;
236         int old_offset = offset;
237
238         if ( !tree ) return;            /* nothing to do! */
239
240         while ( length-- > 0 ) {
241                 if (s != sbuf ) {
242                         s += sprintf ( s, ", " );
243                 } 
244                 s += sprintf ( s, "0x%02x", pd[offset++] );
245         }
246         if ( hlen == 0 ) {
247                 sprintf ( sbuf, "--none--" );
248         }
249
250         proto_tree_add_text ( tree, old_offset, hlen,
251                         "NLPID: %s", sbuf );
252 }
253
254 /*
255  * Name: isis_dissect_clvs()
256  * 
257  * Description:
258  *      Dispatch routine to shred all the CLVs in a packet.  We just
259  *      walk through the clv entries in the packet.  For each one, we
260  *      search the passed in valid clv's for this protocol (opts) for
261  *      a matching code.  If found, we add to the display tree and
262  *      then call the dissector.  If it is not, we just post an
263  *      "unknown" clv entrie using the passed in unknown clv tree id.
264  *
265  * Input:
266  *      isis_clv_handle_t * : NULL dissector terminated array of codes
267  *              and handlers (along with tree text and tree id's).
268  *      int : length of CLV area.
269  *      u_char * : packet data
270  *      int : offset into packet data where we are.
271  *      guint : length of clv we are decoding
272  *      frame_data * : frame data (complete frame)
273  *      proto_tree * : protocol display tree to fill out.  May be NULL
274  *      gint : unknown clv tree id
275  * 
276  * Output:
277  *      void, but we will add to proto tree if !NULL.
278  */
279 void 
280 isis_dissect_clvs(const isis_clv_handle_t *opts, int len, 
281                 const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
282                 gint unknown_tree_id ) { 
283         guint8 code;
284         guint8 length;
285         int q;
286         proto_item      *ti;
287         proto_tree      *clv_tree;
288         char            sbuf[255];
289         int             adj;
290
291         while ( len > 0 ) {
292                 code = pd[offset++];
293                 length = pd[offset++];
294                 adj = (sizeof(code) + sizeof(length) + length);
295                 len -= adj;
296                 if ( len < 0 ) {
297                         isis_dissect_unknown(offset, adj, tree, fd,
298                                 "Short CLV header (%d vs %d)",
299                                 adj, len + adj );
300                         return;
301                 }
302                 q = 0;
303                 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
304                         q++;
305                 }
306                 if ( opts[q].dissect ) {
307                         if (tree) {
308                                 /* adjust by 2 for code/len octets */
309                                 snprintf ( sbuf, sizeof(sbuf), "%s (%d)", 
310                                         opts[q].tree_text, length ); 
311                                 ti = proto_tree_add_text(tree, offset - 2, 
312                                         length + 2, sbuf);
313                                 clv_tree = proto_item_add_subtree(ti, 
314                                         *opts[q].tree_id );
315                         } else {
316                                 clv_tree = NULL;
317                         }
318                         opts[q].dissect(pd, offset, length, fd, clv_tree );
319                 } else {
320                         if (tree) { 
321                                 snprintf ( sbuf, sizeof(sbuf), 
322                                         "Unknown code (%d:%d)", code, length ); 
323                                 ti = proto_tree_add_text(tree, offset - 2, 
324                                         length + 2, sbuf);
325                                 clv_tree = proto_item_add_subtree(ti, 
326                                         unknown_tree_id );
327                         } else { 
328                                 clv_tree = NULL;
329                         }
330                 }
331                 offset += length;
332         }
333 }