Don't include the header file to get the SNMP version unless we're
[obnox/wireshark/wip.git] / packet-isis-snp.c
1 /* packet-isis-snp.c
2  * Routines for decoding isis complete & partial SNP and their payload
3  *
4  * $Id: packet-isis-snp.c,v 1.20 2002/09/02 22:10:15 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 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "packet-osi.h"
35 #include "packet-isis.h"
36 #include "packet-isis-clv.h"
37 #include "packet-isis-lsp.h"
38 #include "packet-isis-snp.h"
39
40 /* csnp packets */
41 static int hf_isis_csnp_pdu_length = -1;
42 static gint ett_isis_csnp = -1;
43 static gint ett_isis_csnp_lsp_entries = -1;
44 static gint ett_isis_csnp_authentication = -1;
45 static gint ett_isis_csnp_clv_unknown = -1;
46
47 /* psnp packets */
48 static int hf_isis_psnp_pdu_length = -1;
49 static gint ett_isis_psnp = -1;
50 static gint ett_isis_psnp_lsp_entries = -1;
51 static gint ett_isis_psnp_authentication = -1;
52 static gint ett_isis_psnp_clv_unknown = -1;
53
54 static void dissect_l1_snp_authentication_clv(tvbuff_t *tvb,
55         proto_tree *tree, int offset, int id_length, int length);
56 static void dissect_l2_snp_authentication_clv(tvbuff_t *tvb,
57         proto_tree *tree, int offset, int id_length, int length);
58 static void dissect_csnp_lsp_entries(tvbuff_t *tvb,
59         proto_tree *tree, int offset, int id_length, int length);
60 static void dissect_psnp_lsp_entries(tvbuff_t *tvb,
61         proto_tree *tree, int offset, int id_length, int length);
62
63 static const isis_clv_handle_t clv_l1_csnp_opts[] = {
64         {
65                 ISIS_CLV_L1_CSNP_LSP_ENTRIES,
66                 "LSP entries",
67                 &ett_isis_csnp_lsp_entries,
68                 dissect_csnp_lsp_entries
69         },
70         {
71                 ISIS_CLV_L1_CSNP_AUTHENTICATION_NS,
72                 "Authentication(non spec)",
73                 &ett_isis_csnp_authentication,
74                 dissect_l1_snp_authentication_clv
75         },
76         {
77                 ISIS_CLV_L1_CSNP_AUTHENTICATION,
78                 "Authentication",
79                 &ett_isis_csnp_authentication,
80                 dissect_l1_snp_authentication_clv
81         },
82         {
83                 0, "", NULL, NULL
84         }
85 };
86
87 static const isis_clv_handle_t clv_l2_csnp_opts[] = {
88         {
89                 ISIS_CLV_L2_CSNP_LSP_ENTRIES,
90                 "LSP entries",
91                 &ett_isis_csnp_lsp_entries,
92                 dissect_csnp_lsp_entries
93         },
94         {
95                 ISIS_CLV_L2_CSNP_AUTHENTICATION_NS,
96                 "Authentication(non spec)",
97                 &ett_isis_csnp_authentication,
98                 dissect_l2_snp_authentication_clv
99         },
100         {
101                 ISIS_CLV_L2_CSNP_AUTHENTICATION,
102                 "Authentication",
103                 &ett_isis_csnp_authentication,
104                 dissect_l2_snp_authentication_clv
105         },
106         {
107                 0, "", NULL, NULL
108         }
109 };
110
111 static const isis_clv_handle_t clv_l1_psnp_opts[] = {
112         {
113                 ISIS_CLV_L1_PSNP_LSP_ENTRIES,
114                 "LSP entries",
115                 &ett_isis_psnp_lsp_entries,
116                 dissect_psnp_lsp_entries
117         },
118         {
119                 ISIS_CLV_L1_PSNP_AUTHENTICATION_NS,
120                 "Authentication(non spec)",
121                 &ett_isis_psnp_authentication,
122                 dissect_l1_snp_authentication_clv
123         },
124         {
125                 ISIS_CLV_L1_PSNP_AUTHENTICATION,
126                 "Authentication",
127                 &ett_isis_psnp_authentication,
128                 dissect_l1_snp_authentication_clv
129         },
130         {
131                 0, "", NULL, NULL
132         }
133 };
134
135 static const isis_clv_handle_t clv_l2_psnp_opts[] = {
136         {
137                 ISIS_CLV_L2_PSNP_LSP_ENTRIES,
138                 "LSP entries",
139                 &ett_isis_psnp_lsp_entries,
140                 dissect_psnp_lsp_entries
141         },
142         {
143                 ISIS_CLV_L2_PSNP_AUTHENTICATION,
144                 "Authentication",
145                 &ett_isis_psnp_authentication,
146                 dissect_l2_snp_authentication_clv
147         },
148         {
149                 ISIS_CLV_L2_PSNP_AUTHENTICATION_NS,
150                 "Authentication(non spec)",
151                 &ett_isis_psnp_authentication,
152                 dissect_l2_snp_authentication_clv
153         },
154         {
155                 0, "", NULL, NULL
156         }
157 };
158
159 /*
160  * Name: dissect_snp_lsp_entries()
161  *
162  * Description:
163  *      All the snp packets use a common payload format.  We have up
164  *      to n entries (based on length), which are made of:
165  *              2 : remaining life time
166  *              8 : lsp id
167  *              4 : sequence number
168  *              2 : checksum
169  *
170  * Input:
171  *      tvbuff_t * : tvbuffer for packet data
172  *      proto_tree * : protocol display tree to fill out.  May be NULL
173  *      int : offset into packet data where we are.
174  *      int : length of payload to decode.
175  *      int : length of IDs in packet.
176  *
177  * Output:
178  *      void, but we will add to proto tree if !NULL.
179  */
180 static void
181 dissect_csnp_lsp_entries(tvbuff_t *tvb, proto_tree *tree, int offset,
182         int id_length, int length)
183 {
184         proto_tree *subtree,*ti;
185
186         while ( length > 0 ) {
187                 if ( length < 2+id_length+2+4+2 ) {
188                         isis_dissect_unknown(tvb, tree, offset,
189                                 "Short SNP header entry (%d vs %d)", length,
190                                 2+id_length+2+4+2 );
191                         return;
192                 }
193
194                 ti = proto_tree_add_text(tree, tvb, offset, 16,
195                                     "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
196                                            print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ),
197                                            tvb_get_ntohl(tvb, offset+10),
198                                            tvb_get_ntohs(tvb, offset),
199                                            tvb_get_ntohs(tvb, offset+14));
200
201                 subtree = proto_item_add_subtree(ti,ett_isis_csnp_lsp_entries);
202
203                 proto_tree_add_text(subtree, tvb, offset+2, 8,
204                         "LSP-ID:             : %s",
205                         print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ));
206
207                 proto_tree_add_text(subtree, tvb, offset+10, 4,
208                         "LSP Sequence Number : 0x%08x",
209                         tvb_get_ntohl(tvb, offset+10));
210
211                 proto_tree_add_text(subtree, tvb, offset, 2,
212                         "Remaining Lifetime  : %us",
213                         tvb_get_ntohs(tvb, offset));
214
215                 proto_tree_add_text(subtree, tvb, offset+14, 2,
216                         "LSP checksum        : 0x%04x",
217                         tvb_get_ntohs(tvb, offset+14));
218
219                 length -= 16;
220                 offset += 16;
221         }
222
223 }
224 static void
225 dissect_psnp_lsp_entries(tvbuff_t *tvb, proto_tree *tree, int offset,
226         int id_length, int length)
227 {
228         proto_tree *subtree,*ti;
229
230         while ( length > 0 ) {
231                 if ( length < 2+id_length+2+4+2 ) {
232                         isis_dissect_unknown(tvb, tree, offset,
233                                 "Short SNP header entry (%d vs %d)", length,
234                                 2+id_length+2+4+2 );
235                         return;
236                 }
237
238                 ti = proto_tree_add_text(tree, tvb, offset, 16,
239                                     "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
240                                            print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ),
241                                            tvb_get_ntohl(tvb, offset+10),
242                                            tvb_get_ntohs(tvb, offset),
243                                            tvb_get_ntohs(tvb, offset+14));
244
245                 subtree = proto_item_add_subtree(ti,ett_isis_psnp_lsp_entries);
246
247                 proto_tree_add_text(subtree, tvb, offset+2, 8,
248                         "LSP-ID:             : %s",
249                         print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ));
250
251                 proto_tree_add_text(subtree, tvb, offset+10, 4,
252                         "LSP Sequence Number : 0x%08x",
253                         tvb_get_ntohl(tvb, offset+10));
254
255                 proto_tree_add_text(subtree, tvb, offset, 2,
256                         "Remaining Lifetime  : %us",
257                         tvb_get_ntohs(tvb, offset));
258
259                 proto_tree_add_text(subtree, tvb, offset+14, 2,
260                         "LSP checksum        : 0x%04x",
261                         tvb_get_ntohs(tvb, offset+14));
262
263                 length -= 16;
264                 offset += 16;
265         }
266
267 }
268
269 /*
270  * Name: isis_dissect_isis_csnp()
271  *
272  * Description:
273  *      Tear apart a L1 or L2 CSNP header and then call into payload dissect
274  *      to pull apart the lsp id payload.
275  *
276  * Input:
277  *      tvbuff_t * : tvbuffer for packet data
278  *      proto_tree * : protocol display tree to add to.  May be NULL.
279  *      int offset : our offset into packet data.
280  *      int : type (l1 csnp, l2 csnp)
281  *      int : header length of packet.
282  *      int : length of IDs in packet.
283  *
284  * Output:
285  *      void, but we will add to proto tree if !NULL.
286  */
287 void
288 isis_dissect_isis_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
289         int type, int header_length, int id_length)
290 {
291         proto_item      *ti;
292         proto_tree      *csnp_tree = NULL;
293         guint16         pdu_length;
294         int             len;
295
296         if (tree) {
297                 ti = proto_tree_add_text(tree, tvb, offset, -1,
298                     PROTO_STRING_CSNP);
299                 csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
300         }
301
302         pdu_length = tvb_get_ntohs(tvb, offset);
303         if (tree) {
304                 proto_tree_add_uint(csnp_tree, hf_isis_csnp_pdu_length, tvb,
305                         offset, 2, pdu_length);
306         }
307         offset += 2;
308
309         if (tree) {
310                 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 1,
311                         "Source-ID:    %s",
312                                 print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
313         }
314         if (check_col(pinfo->cinfo, COL_INFO)) {
315                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s",
316                         print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
317         }
318         offset += id_length + 1;
319
320         if (tree) {
321                 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 2,
322                         "Start LSP-ID: %s",
323                                     print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );                
324         }
325         if (check_col(pinfo->cinfo, COL_INFO)) {
326                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Start LSP-ID: %s",
327                         print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
328         }
329         offset += id_length + 2;
330
331         if (tree) {
332                 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 2,
333                         "End LSP-ID: %s",
334                                     print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );  
335         }
336         if (check_col(pinfo->cinfo, COL_INFO)) {
337                 col_append_fstr(pinfo->cinfo, COL_INFO, ", End LSP-ID: %s",
338                         print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
339         }
340         offset += id_length + 2;
341
342         len = pdu_length - header_length;
343         if (len < 0) {
344                 return;
345         }
346         /* Call into payload dissector */
347         if (type == ISIS_TYPE_L1_CSNP ) {
348                 isis_dissect_clvs(tvb, csnp_tree, offset,
349                         clv_l1_csnp_opts, len, id_length,
350                         ett_isis_csnp_clv_unknown );
351         } else {
352                 isis_dissect_clvs(tvb, csnp_tree, offset,
353                         clv_l2_csnp_opts, len, id_length,
354                         ett_isis_csnp_clv_unknown );
355         }
356 }
357
358 /*
359  * Name: isis_dissect_isis_psnp()
360  *
361  * Description:
362  *      Tear apart a L1 or L2 PSNP header and then call into payload dissect
363  *      to pull apart the lsp id payload.
364  *
365  * Input:
366  *      tvbuff_t * : tvbuffer for packet data
367  *      proto_tree * : protocol display tree to add to.  May be NULL.
368  *      int : our offset into packet data
369  *      int : type (l1 psnp, l2 psnp)
370  *      int : header length of packet.
371  *      int : length of IDs in packet.
372  *
373  * Output:
374  *      void, but we will add to proto tree if !NULL.
375  */
376 void
377 isis_dissect_isis_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
378         int type, int header_length, int id_length)
379 {
380         proto_item      *ti;
381         proto_tree      *psnp_tree = NULL;
382         guint16         pdu_length;
383         int             len;
384
385         if (tree) {
386                 ti = proto_tree_add_text(tree, tvb, offset, -1,
387                     PROTO_STRING_PSNP);
388                 psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
389         }
390
391         pdu_length = tvb_get_ntohs(tvb, offset);
392         if (tree) {
393                 proto_tree_add_uint(psnp_tree, hf_isis_psnp_pdu_length, tvb,
394                         offset, 2, pdu_length);
395         }
396         offset += 2;
397
398         if (tree) {
399                 proto_tree_add_text(psnp_tree, tvb, offset, id_length + 1,
400                         "Source-ID: %s",
401                         print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length + 1 ) );
402         }
403         if (check_col(pinfo->cinfo, COL_INFO)) {
404                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s",
405                         print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
406         }
407         offset += id_length + 1;
408
409         len = pdu_length - header_length;
410         if (len < 0) {
411                 isis_dissect_unknown(tvb, tree, offset,
412                         "packet header length %d went beyond packet",
413                         header_length );
414                 return;
415         }
416         /* Call into payload dissector */
417         if (type == ISIS_TYPE_L1_CSNP ) {
418                 isis_dissect_clvs(tvb, psnp_tree, offset,
419                         clv_l1_csnp_opts, len, id_length,
420                         ett_isis_psnp_clv_unknown );
421         } else {
422                 isis_dissect_clvs(tvb, psnp_tree, offset,
423                         clv_l2_csnp_opts, len, id_length,
424                         ett_isis_psnp_clv_unknown );
425         }
426 }
427
428 /*
429  * Name: dissect_L1_snp_authentication_clv()
430  *
431  * Description:
432  *      Decode for a lsp packets authenticaion clv.  Calls into the
433  *      clv common one.  An auth inside a L1 SNP is a per area password
434  *
435  * Input:
436  *      tvbuff_t * : tvbuffer for packet data
437  *      proto_tree * : proto tree to build on (may be null)
438  *      int : current offset into packet data
439  *      int : length of IDs in packet.
440  *      int : length of this clv
441  *
442  * Output:
443  *      void, will modify proto_tree if not null.
444  */
445 static void
446 dissect_l1_snp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
447         int id_length _U_, int length)
448 {
449         isis_dissect_authentication_clv(tvb, tree, offset, length,
450                 "Per area authentication" );
451 }
452
453 /*
454  * Name: dissect_l2_authentication_clv()
455  *
456  * Description:
457  *      Decode for a lsp packets authenticaion clv.  Calls into the
458  *      clv common one.  An auth inside a L2 LSP is a per domain password
459  *
460  * Input:
461  *      tvbuff_t * : tvbuffer for packet data
462  *      proto_tree * : proto tree to build on (may be null)
463  *      int : current offset into packet data
464  *      int : length of IDs in packet.
465  *      int : length of this clv
466  *
467  * Output:
468  *      void, will modify proto_tree if not null.
469  */
470 static void
471 dissect_l2_snp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
472         int id_length _U_, int length)
473 {
474         isis_dissect_authentication_clv(tvb, tree, offset, length,
475                 "Per domain authentication" );
476 }
477
478 /*
479  * Name: isis_register_csnp()
480  *
481  * Description:
482  *      Register our protocol sub-sets with protocol manager.
483  *
484  * Input:
485  *      int : protocol index for the ISIS protocol
486  *
487  * Output:
488  *      void
489  */
490 void
491 isis_register_csnp(int proto_isis) {
492         static hf_register_info hf[] = {
493                 { &hf_isis_csnp_pdu_length,
494                 { "PDU length",         "isis.csnp.pdu_length", FT_UINT16,
495                   BASE_DEC, NULL, 0x0, "", HFILL }},
496         };
497         static gint *ett[] = {
498                 &ett_isis_csnp,
499                 &ett_isis_csnp_lsp_entries,
500                 &ett_isis_csnp_authentication,
501                 &ett_isis_csnp_clv_unknown,
502         };
503
504         proto_register_field_array(proto_isis, hf, array_length(hf));
505         proto_register_subtree_array(ett, array_length(ett));
506 }
507
508
509 /*
510  * Name: isis_register_psnp()
511  *
512  * Description:
513  *      Register our protocol sub-sets with protocol manager.
514  *
515  * Input:
516  *      int : protocol index for the ISIS protocol
517  *
518  * Output:
519  *      void
520  */
521 void
522 isis_register_psnp(int proto_isis) {
523         static hf_register_info hf[] = {
524                 { &hf_isis_psnp_pdu_length,
525                 { "PDU length",         "isis.psnp.pdu_length", FT_UINT16,
526                   BASE_DEC, NULL, 0x0, "", HFILL }},
527         };
528         static gint *ett[] = {
529                 &ett_isis_psnp,
530                 &ett_isis_psnp_lsp_entries,
531                 &ett_isis_psnp_authentication,
532                 &ett_isis_psnp_clv_unknown,
533         };
534
535         proto_register_field_array(proto_isis, hf, array_length(hf));
536         proto_register_subtree_array(ett, array_length(ett));
537 }