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