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