Patches to prevent problems under Windows when time formats are negative.
[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.8 2000/08/11 13:35:17 deniel 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  * Name: isis_dissect_ip_int_clv()
177  * 
178  * Description:
179  *      Take apart the CLV that lists all the IP interfaces.  The
180  *      meaning of which is slightly different for the different base packet
181  *      types, but the display is not different.  What we have is n ip
182  *      addresses, plain and simple.
183  *
184  * Input:
185  *      u_char * : packet data
186  *      int : offset into packet data where we are.
187  *      guint : length of clv we are decoding
188  *      frame_data * : frame data (complete frame)
189  *      proto_tree * : protocol display tree to fill out.  May be NULL
190  *      gint : tree id to use for proto tree.
191  * 
192  * Output:
193  *      void, but we will add to proto tree if !NULL.
194  */
195 void 
196 isis_dissect_ip_int_clv(const u_char *pd, int offset, 
197                 guint length, frame_data *fd, proto_tree *tree, gint tree_id ) {
198         guint32 addr;
199         if ( length <= 0 ) {
200                 return;
201         }
202
203         while ( length > 0 ) {
204                 if ( length < 4 ) {
205                         isis_dissect_unknown(offset, length, tree, fd,
206                                 "Short ip interface address (%d vs 4)",length );
207                         return;
208                 }
209                 memcpy(&addr, &pd[offset], sizeof(addr));
210                 if ( tree ) {
211                         proto_tree_add_ipv4(tree, tree_id, NullTVB, offset, 4, addr);
212                 }
213                 offset += 4;
214                 length -= 4;
215         }
216 }
217
218 /*
219  * Name: isis_dissect_nlpid_clv()
220  * 
221  * Description:
222  *      Take apart a NLPID packet and display it.  The NLPID (for intergrated
223  *      ISIS, contains n network layer protocol IDs that the box supports.
224  *      Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
225  *      plus 1 for zero termination.  We just just 256*6 for simplicity.
226  *
227  * Input:
228  *      u_char * : packet data
229  *      int : offset into packet data where we are.
230  *      guint : length of clv we are decoding
231  *      frame_data * : frame data (complete frame)
232  *      proto_tree * : protocol display tree to fill out.  May be NULL
233  * 
234  * Output:
235  *      void, but we will add to proto tree if !NULL.
236  */
237 void 
238 isis_dissect_nlpid_clv(const u_char *pd, int offset, 
239                 guint length, frame_data *fd, proto_tree *tree ) {
240         char sbuf[256*6];
241         char *s = sbuf;
242         int hlen = length;
243         int old_offset = offset;
244
245         if ( !tree ) return;            /* nothing to do! */
246
247         while ( length-- > 0 ) {
248                 if (s != sbuf ) {
249                         s += sprintf ( s, ", " );
250                 } 
251                 s += sprintf ( s, "0x%02x", pd[offset++] );
252         }
253         if ( hlen == 0 ) {
254                 sprintf ( sbuf, "--none--" );
255         }
256
257         proto_tree_add_text ( tree, NullTVB, old_offset, hlen,
258                         "NLPID: %s", sbuf );
259 }
260
261 /*
262  * Name: isis_dissect_clvs()
263  * 
264  * Description:
265  *      Dispatch routine to shred all the CLVs in a packet.  We just
266  *      walk through the clv entries in the packet.  For each one, we
267  *      search the passed in valid clv's for this protocol (opts) for
268  *      a matching code.  If found, we add to the display tree and
269  *      then call the dissector.  If it is not, we just post an
270  *      "unknown" clv entrie using the passed in unknown clv tree id.
271  *
272  * Input:
273  *      isis_clv_handle_t * : NULL dissector terminated array of codes
274  *              and handlers (along with tree text and tree id's).
275  *      int : length of CLV area.
276  *      u_char * : packet data
277  *      int : offset into packet data where we are.
278  *      guint : length of clv we are decoding
279  *      frame_data * : frame data (complete frame)
280  *      proto_tree * : protocol display tree to fill out.  May be NULL
281  *      gint : unknown clv tree id
282  * 
283  * Output:
284  *      void, but we will add to proto tree if !NULL.
285  */
286 void 
287 isis_dissect_clvs(const isis_clv_handle_t *opts, int len, int id_length,
288                 const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
289                 gint unknown_tree_id ) { 
290         guint8 code;
291         guint8 length;
292         int q;
293         proto_item      *ti;
294         proto_tree      *clv_tree;
295         char            sbuf[255];
296         int             adj;
297
298         while ( len > 0 ) {
299                 code = pd[offset++];
300                 length = pd[offset++];
301                 adj = (sizeof(code) + sizeof(length) + length);
302                 len -= adj;
303                 if ( len < 0 || !BYTES_ARE_IN_FRAME(offset, length) ) {
304                         isis_dissect_unknown(offset, adj, tree, fd,
305                                 "Short CLV header (%d vs %d)",
306                                 adj, len + adj );
307                         return;
308                 }
309                 q = 0;
310                 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
311                         q++;
312                 }
313                 if ( opts[q].dissect ) {
314                         if (tree) {
315                                 /* adjust by 2 for code/len octets */
316                                 snprintf ( sbuf, sizeof(sbuf), "%s (%d)", 
317                                         opts[q].tree_text, length ); 
318                                 ti = proto_tree_add_text(tree, NullTVB, offset - 2, 
319                                         length + 2, sbuf);
320                                 clv_tree = proto_item_add_subtree(ti, 
321                                         *opts[q].tree_id );
322                         } else {
323                                 clv_tree = NULL;
324                         }
325                         opts[q].dissect(pd, offset, length, id_length, fd,
326                                 clv_tree );
327                 } else {
328                         if (tree) { 
329                                 snprintf ( sbuf, sizeof(sbuf), 
330                                         "Unknown code (%d:%d)", code, length ); 
331                                 ti = proto_tree_add_text(tree, NullTVB, offset - 2, 
332                                         length + 2, sbuf);
333                                 clv_tree = proto_item_add_subtree(ti, 
334                                         unknown_tree_id );
335                         } else { 
336                                 clv_tree = NULL;
337                         }
338                 }
339                 offset += length;
340         }
341 }