Added mockups for LSA_SECRET and LSA_SECURITY_DESCRIPTOR inside
[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.16 2002/01/21 07:36:36 guy Exp $
5  * Stuart Stanley <stuarts@mxmail.net>
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  *
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <glib.h>
39
40 #ifdef NEED_SNPRINTF_H
41 # include "snprintf.h"
42 #endif
43
44 #include <epan/packet.h>
45 #include "packet-osi.h"
46 #include "packet-isis.h"
47 #include "packet-isis-clv.h"
48 #include "nlpid.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  *      tvbuff_t * : tvbuffer for packet data
60  *      packet_info * : info for current packet
61  *      proto_tree * : protocol display tree to fill out.  May be NULL
62  *      int : offset into packet data where we are.
63  *      int : length of clv we are decoding
64  * 
65  * Output:
66  *      void, but we will add to proto tree if !NULL.
67  */
68 void 
69 isis_dissect_area_address_clv(tvbuff_t *tvb, packet_info *pinfo, 
70         proto_tree *tree, int offset, int length)
71 {       
72         char            *sbuf;
73         int             mylen;
74
75         while ( length > 0 ) {
76                 mylen = tvb_get_guint8(tvb, offset);
77                 length--;
78                 if (length<=0) {
79                         isis_dissect_unknown(tvb, pinfo, tree, offset,
80                                 "short address (no length for payload)");
81                         return;
82                 }
83                 if ( mylen > length) {
84                         isis_dissect_unknown(tvb, pinfo, tree, offset,
85                                 "short address, packet say %d, we have %d left",
86                                 mylen, length );
87                         return;
88                 }
89
90                 /* 
91                  * Lets turn the area address into "standard" 0000.0000.etc
92                  * format string.  
93                  */
94 /*              sbuf = isis_address_to_string ( tvb, offset + 1, mylen );*/
95       sbuf = print_nsap_net( tvb_get_ptr(tvb, offset + 1, mylen), mylen );
96                 /* and spit it out */
97                 if ( tree ) {
98                         proto_tree_add_text ( tree, tvb, offset, mylen + 1,  
99                                 "Area address (%d): %s", mylen, sbuf );
100                 }
101                 offset += mylen + 1;
102                 length -= mylen;        /* length already adjusted for len fld*/
103         }
104 }
105
106
107 /*
108  * Name: isis_dissect_authentication_clv()
109  * 
110  * Description:
111  *      Take apart the CLV that hold authentication information.  This
112  *      is currently 1 octet auth type (which must be 1) and then
113  *      the clear text password.
114  *      
115  *      An ISIS password has different meaning depending where it
116  *      is found.  Thus we support a passed in prefix string to 
117  *      use to name this.
118  *
119  * Input:
120  *      tvbuff_t * : tvbuffer for packet data
121  *      packet_info * : info for current packet
122  *      proto_tree * : protocol display tree to fill out.  May be NULL
123  *      int : offset into packet data where we are.
124  *      int : length of clv we are decoding
125  *      char * : Password meaning
126  * 
127  * Output:
128  *      void, but we will add to proto tree if !NULL.
129  */
130 void 
131 isis_dissect_authentication_clv(tvbuff_t *tvb, packet_info *pinfo, 
132         proto_tree *tree, int offset, int length, char *meaning)
133 {       
134         u_char pw_type;
135         char sbuf[300];         /* 255 + header info area */
136         char *s = sbuf;
137         int auth_unsupported;
138
139         if ( length <= 0 ) {
140                 return;
141         }
142
143         pw_type = tvb_get_guint8(tvb, offset);
144         offset += 1;
145         length--;
146         auth_unsupported = FALSE;
147
148         switch (pw_type) {
149         case 1:
150                 s += sprintf ( s, "clear text (1), password (length %d) = ", length );
151
152                 if ( length > 0 ) {
153                   strncpy(s, tvb_get_ptr(tvb, offset, length), length);
154                   s[length] = 0;
155                 } else {
156                   strcat(s, "no clear-text password found!!!" );
157                 }
158                 break;
159         case 54:
160                 s += sprintf ( s, "hmac-md5 (54), password (length %d) = ", length );
161
162                 if ( length == 16 ) {
163                   s += sprintf ( s, "0x%02x", tvb_get_guint8(tvb, offset) );
164                   offset += 1;
165                   length--;
166                   while (length > 0) {
167                     s += sprintf ( s, "%02x", tvb_get_guint8(tvb, offset) );
168                     offset += 1;
169                     length--;
170                     }
171                     s = 0;
172                 } else {
173                   strcat(s, "illegal hmac-md5 digest format (must be 16 bytes)" );
174                 }
175                 break;
176         default:
177                 s += sprintf ( s, "type 0x%02x (0x%02x): ", pw_type, length );
178                 auth_unsupported=TRUE;
179                 break;
180         }
181
182         proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
183                         "%s %s", meaning, sbuf );
184
185         if ( auth_unsupported ) {
186                 isis_dissect_unknown(tvb, pinfo, tree, offset,
187                         "Unknown authentication type" );
188         }       
189 }           
190
191 /*
192  * Name: isis_dissect_hostname_clv()
193  *
194  * Description:
195  *      dump the hostname information found in TLV 137
196  *      pls note that the hostname is not null terminated
197  *
198  * Input:
199  *      tvbuff_t * : tvbuffer for packet data
200  *      packet_info * : info for current packet
201  *      proto_tree * : protocol display tree to fill out.  May be NULL
202  *      int : offset into packet data where we are.
203  *      int : length of clv we are decoding
204  *
205  * Output:
206  *      void, but we will add to proto tree if !NULL.
207  */
208
209
210 void
211 isis_dissect_hostname_clv(tvbuff_t *tvb, packet_info *pinfo, 
212         proto_tree *tree, int offset, int length)
213 {       
214         if ( !tree ) return;            /* nothing to do! */
215
216         if ( length == 0 ) {
217                 proto_tree_add_text ( tree, tvb, offset, length,
218                         "Hostname: --none--" );
219         } else {
220                 proto_tree_add_text ( tree, tvb, offset, length,
221                         "Hostname: %.*s", length,
222                         tvb_get_ptr(tvb, offset, length) );
223         }
224 }
225
226
227
228
229 void 
230 isis_dissect_mt_clv(tvbuff_t *tvb, packet_info *pinfo, 
231         proto_tree *tree, int offset, int length, int tree_id)
232 {       
233   guint16 mt_block;
234   char mt_desc[60];
235
236         while (length>1) {
237           /* length can only be a multiple of 2, otherwise there is 
238              something broken -> so decode down until length is 1 */
239           if (length!=1)
240             {
241               /* fetch two bytes */
242               mt_block=tvb_get_ntohs(tvb, offset);
243
244               /* mask out the lower 12 bits */
245               switch(mt_block&0x0fff) {
246                 case 0:
247                   strcpy(mt_desc,"IPv4 unicast");
248                   break;
249                 case 1:
250                   strcpy(mt_desc,"In-Band Management");
251                   break;
252                 case 2:
253                   strcpy(mt_desc,"IPv6 unicast");
254                   break;
255                 case 3:
256                   strcpy(mt_desc,"Multicast");
257                   break;
258                 case 4095:
259                   strcpy(mt_desc,"Development, Experimental or Proprietary");
260                   break;
261                 default:
262                   strcpy(mt_desc,"Reserved for IETF Consensus");
263               }
264                 proto_tree_add_text ( tree, tvb, offset, 2 ,
265                         "%s Topology (0x%03x)%s%s",
266                                       mt_desc,
267                                       mt_block&0xfff,
268                                       (mt_block&0x8000) ? "" : ", no sub-TLVs present",
269                                       (mt_block&0x4000) ? ", ATT bit set" : "" );
270             }
271           else {
272             proto_tree_add_text ( tree, tvb, offset, 2 ,
273                         "malformed MT-ID");
274             break;
275           }
276           length=length-2;
277           offset=offset+2;
278         }
279 }
280
281
282 /*
283  * Name: isis_dissect_ip_int_clv()
284  * 
285  * Description:
286  *      Take apart the CLV that lists all the IP interfaces.  The
287  *      meaning of which is slightly different for the different base packet
288  *      types, but the display is not different.  What we have is n ip
289  *      addresses, plain and simple.
290  *
291  * Input:
292  *      tvbuff_t * : tvbuffer for packet data
293  *      packet_info * : info for current packet
294  *      proto_tree * : protocol display tree to fill out.  May be NULL
295  *      int : offset into packet data where we are.
296  *      int : length of clv we are decoding
297  *      int : tree id to use for proto tree.
298  * 
299  * Output:
300  *      void, but we will add to proto tree if !NULL.
301  */
302 void 
303 isis_dissect_ip_int_clv(tvbuff_t *tvb, packet_info *pinfo, 
304         proto_tree *tree, int offset, int length, int tree_id)
305 {
306         guint32 addr;
307
308         if ( length <= 0 ) {
309                 return;
310         }
311
312         while ( length > 0 ) {
313                 if ( length < 4 ) {
314                         isis_dissect_unknown(tvb, pinfo, tree, offset,
315                                 "Short ip interface address (%d vs 4)",length );
316                         return;
317                 }
318
319                 tvb_memcpy(tvb, (guint8 *)&addr, offset, sizeof(addr));
320                 if ( tree ) {
321                         proto_tree_add_ipv4(tree, tree_id, tvb, offset, 4, addr);
322                 }
323                 offset += 4;
324                 length -= 4;
325         }
326 }
327
328 /*
329  * Name: isis_dissect_ipv6_int_clv()
330  * 
331  * Description:
332  *      Take apart the CLV that lists all the IPv6 interfaces.  The
333  *      meaning of which is slightly different for the different base packet
334  *      types, but the display is not different.  What we have is n ip
335  *      addresses, plain and simple.
336  *
337  * Input:
338  *      tvbuff_t * : tvbuffer for packet data
339  *      packet_info * : info for current packet
340  *      proto_tree * : protocol display tree to fill out.  May be NULL
341  *      int : offset into packet data where we are.
342  *      int : length of clv we are decoding
343  *      int : tree id to use for proto tree.
344  * 
345  * Output:
346  *      void, but we will add to proto tree if !NULL.
347  */
348 void 
349 isis_dissect_ipv6_int_clv(tvbuff_t *tvb, packet_info *pinfo, 
350         proto_tree *tree, int offset, int length, int tree_id)
351 {
352         guint8 addr [16];
353
354         if ( length <= 0 ) {
355                 return;
356         }
357
358         while ( length > 0 ) {
359                 if ( length < 16 ) {
360                         isis_dissect_unknown(tvb, pinfo, tree, offset,
361                                 "Short IPv6 interface address (%d vs 16)",length );
362                         return;
363                 }
364                 tvb_memcpy(tvb, addr, offset, sizeof(addr));
365                 if ( tree ) {
366                         proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr);
367                 }
368                 offset += 16;
369                 length -= 16;
370         }
371 }
372
373
374 /*
375  * Name: isis_dissect_te_router_id_clv()
376  *
377  * Description:
378  *      Display the Traffic Engineering Router ID TLV #134.
379  *      This TLV is like the IP Interface TLV, except that
380  *      only _one_ IP address is present
381  *
382  * Input:
383  *      tvbuff_t * : tvbuffer for packet data
384  *      packet_info * : info for current packet
385  *      proto_tree * : protocol display tree to fill out.  May be NULL
386  *      int : offset into packet data where we are.
387  *      int : length of clv we are decoding
388  *      int : tree id to use for proto tree.
389  *
390  * Output:
391  *      void, but we will add to proto tree if !NULL.
392  */
393 void
394 isis_dissect_te_router_id_clv(tvbuff_t *tvb, packet_info *pinfo, 
395         proto_tree *tree, int offset, int length, int tree_id)
396 {
397         guint32 addr;
398
399         if ( length <= 0 ) {
400                 return;
401         }
402
403         if ( length != 4 ) {
404                 isis_dissect_unknown(tvb, pinfo, tree, offset,
405                         "malformed Traffic Engineering Router ID (%d vs 4)",length );
406                 return;
407         }
408         tvb_memcpy(tvb, (guint8 *)&addr, offset, sizeof(addr));
409         if ( tree ) {
410                 proto_tree_add_ipv4(tree, tree_id, tvb, offset, 4, addr);
411         }
412 }
413
414 /*
415  * Name: isis_dissect_nlpid_clv()
416  * 
417  * Description:
418  *      Take apart a NLPID packet and display it.  The NLPID (for intergrated
419  *      ISIS, contains n network layer protocol IDs that the box supports.
420  *      Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
421  *      plus 1 for zero termination.  We just just 256*6 for simplicity.
422  *
423  * Input:
424  *      tvbuff_t * : tvbuffer for packet data
425  *      packet_info * : info for current packet
426  *      proto_tree * : protocol display tree to fill out.  May be NULL
427  *      int : offset into packet data where we are.
428  *      int : length of clv we are decoding
429  * 
430  * Output:
431  *      void, but we will add to proto tree if !NULL.
432  */
433 void 
434 isis_dissect_nlpid_clv(tvbuff_t *tvb, packet_info *pinfo, 
435         proto_tree *tree, int offset, int length)
436 {
437         char sbuf[256*6];
438         char *s = sbuf;
439         int hlen = length;
440         int old_offset = offset;
441
442         if ( !tree ) return;            /* nothing to do! */
443
444         while ( length-- > 0 ) {
445                 if (s != sbuf ) {
446                         s += sprintf ( s, ", " ); 
447                 }
448                 s += sprintf ( s, "%s (0x%02x)",
449                     val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals, 
450                         "Unknown"), tvb_get_guint8(tvb, offset));
451                 offset++;       
452         }
453
454         if ( hlen == 0 ) {
455                 sprintf ( sbuf, "--none--" );
456         }
457
458         proto_tree_add_text ( tree, tvb, old_offset, hlen,
459                         "NLPID(s): %s", sbuf );
460 }
461
462 /*
463  * Name: isis_dissect_clvs()
464  * 
465  * Description:
466  *      Dispatch routine to shred all the CLVs in a packet.  We just
467  *      walk through the clv entries in the packet.  For each one, we
468  *      search the passed in valid clv's for this protocol (opts) for
469  *      a matching code.  If found, we add to the display tree and
470  *      then call the dissector.  If it is not, we just post an
471  *      "unknown" clv entrie using the passed in unknown clv tree id.
472  *
473  * Input:
474  *      tvbuff_t * : tvbuffer for packet data
475  *      packet_info * : info for current packet
476  *      proto_tree * : protocol display tree to fill out.  May be NULL
477  *      int : offset into packet data where we are.
478  *      isis_clv_handle_t * : NULL dissector terminated array of codes
479  *              and handlers (along with tree text and tree id's).
480  *      int : length of CLV area.
481  *      int : length of IDs in packet.
482  *      int : unknown clv tree id
483  * 
484  * Output:
485  *      void, but we will add to proto tree if !NULL.
486  */
487 void 
488 isis_dissect_clvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
489         int offset, const isis_clv_handle_t *opts, int len, int id_length,
490         int unknown_tree_id)
491 {
492         guint8 code;
493         guint8 length;
494         int q;
495         proto_item      *ti;
496         proto_tree      *clv_tree;
497         char            sbuf[255];
498         int             adj;
499
500         while ( len > 0 ) {
501                 code = tvb_get_guint8(tvb, offset);
502                 offset += 1;
503
504                 length = tvb_get_guint8(tvb, offset);
505                 offset += 1;
506
507                 adj = (sizeof(code) + sizeof(length) + length);
508                 len -= adj;
509                 if ( len < 0 ) {
510                         isis_dissect_unknown(tvb, pinfo, tree, offset,
511                                 "Short CLV header (%d vs %d)",
512                                 adj, len + adj );
513                         return;
514                 }
515                 q = 0;
516                 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
517                         q++;
518                 }
519                 if ( opts[q].dissect ) {
520                         if (tree) {
521                                 /* adjust by 2 for code/len octets */
522                                 snprintf ( sbuf, sizeof(sbuf), "%s (%d)", 
523                                         opts[q].tree_text, length ); 
524                                 ti = proto_tree_add_text(tree, tvb, offset - 2, 
525                                         length + 2, sbuf);
526                                 clv_tree = proto_item_add_subtree(ti, 
527                                         *opts[q].tree_id );
528                         } else {
529                                 clv_tree = NULL;
530                         }
531                         opts[q].dissect(tvb, pinfo, clv_tree, offset,
532                                 id_length, length);
533                 } else {
534                         if (tree) { 
535                                 snprintf ( sbuf, sizeof(sbuf), 
536                                         "Unknown code (%d:%d)", code, length ); 
537                                 ti = proto_tree_add_text(tree, tvb, offset - 2, 
538                                         length + 2, sbuf);
539                                 clv_tree = proto_item_add_subtree(ti, 
540                                         unknown_tree_id );
541                         } else { 
542                                 clv_tree = NULL;
543                         }
544                 }
545                 offset += length;
546         }
547 }
548