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