In "dissect_eth()", update "pi.len" and "pi.captured_len" regardless of
[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.1 1999/12/15 04:34:19 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 #include "packet.h"
41 #include "packet-isis.h"
42 #include "packet-isis-clv.h"
43 #include "packet-isis-lsp.h"
44 #include "packet-isis-snp.h"
45
46 /* csnp packets */
47 static int proto_isis_csnp = -1;
48 static int hf_isis_csnp_pdu_length = -1;
49 static gint ett_isis_csnp = -1;
50 static gint ett_isis_csnp_lsp_entries = -1;
51 static gint ett_isis_csnp_authentication = -1;
52 static gint ett_isis_csnp_clv_unknown = -1;
53
54 /* psnp packets */
55 static int proto_isis_psnp = -1;
56 static int hf_isis_psnp_pdu_length = -1;
57 static gint ett_isis_psnp = -1;
58 static gint ett_isis_psnp_lsp_entries = -1;
59 static gint ett_isis_psnp_authentication = -1;
60 static gint ett_isis_psnp_clv_unknown = -1;
61
62 static void dissect_snp_lsp_entries(const u_char *pd, int offset,
63                 guint length, frame_data *fd, proto_tree *tree );
64 static void dissect_l1_snp_authentication_clv(const u_char *pd, int offset,
65                 guint length, frame_data *fd, proto_tree *tree );
66 static void dissect_l2_snp_authentication_clv(const u_char *pd, int offset,
67                 guint length, frame_data *fd, proto_tree *tree );
68
69 static const isis_clv_handle_t clv_l1_csnp_opts[] = {
70         {
71                 ISIS_CLV_L1_CSNP_LSP_ENTRIES,
72                 "LSP entries",
73                 &ett_isis_csnp_lsp_entries,
74                 dissect_snp_lsp_entries
75         },
76         {
77                 ISIS_CLV_L1_CSNP_AUTHENTICATION_NS,
78                 "Authentication(non spec)",
79                 &ett_isis_csnp_authentication,
80                 dissect_l1_snp_authentication_clv
81         },
82         {
83                 ISIS_CLV_L1_CSNP_AUTHENTICATION,
84                 "Authentication",
85                 &ett_isis_csnp_authentication,
86                 dissect_l1_snp_authentication_clv
87         },
88         {
89                 0, "", NULL, NULL 
90         }
91 };
92
93 static const isis_clv_handle_t clv_l2_csnp_opts[] = {
94         {
95                 ISIS_CLV_L2_CSNP_LSP_ENTRIES,
96                 "LSP entries",
97                 &ett_isis_csnp_lsp_entries,
98                 dissect_snp_lsp_entries
99         },
100         {
101                 ISIS_CLV_L2_CSNP_AUTHENTICATION_NS,
102                 "Authentication(non spec)",
103                 &ett_isis_csnp_authentication,
104                 dissect_l2_snp_authentication_clv
105         },
106         {
107                 ISIS_CLV_L2_CSNP_AUTHENTICATION,
108                 "Authentication",
109                 &ett_isis_csnp_authentication,
110                 dissect_l2_snp_authentication_clv
111         },
112         {
113                 0, "", NULL, NULL 
114         }
115 };
116
117 static const isis_clv_handle_t clv_l1_psnp_opts[] = {
118         {
119                 ISIS_CLV_L1_PSNP_LSP_ENTRIES,
120                 "LSP entries",
121                 &ett_isis_psnp_lsp_entries,
122                 dissect_snp_lsp_entries
123         },
124         {
125                 ISIS_CLV_L1_PSNP_AUTHENTICATION_NS,
126                 "Authentication(non spec)",
127                 &ett_isis_psnp_authentication,
128                 dissect_l1_snp_authentication_clv
129         },
130         {
131                 ISIS_CLV_L1_PSNP_AUTHENTICATION,
132                 "Authentication",
133                 &ett_isis_psnp_authentication,
134                 dissect_l1_snp_authentication_clv
135         },
136         {
137                 0, "", NULL, NULL 
138         }
139 };
140
141 static const isis_clv_handle_t clv_l2_psnp_opts[] = {
142         {
143                 ISIS_CLV_L2_PSNP_LSP_ENTRIES,
144                 "LSP entries",
145                 &ett_isis_psnp_lsp_entries,
146                 dissect_snp_lsp_entries
147         },
148         {
149                 ISIS_CLV_L2_PSNP_AUTHENTICATION,
150                 "Authentication",
151                 &ett_isis_psnp_authentication,
152                 dissect_l2_snp_authentication_clv
153         },
154         {
155                 ISIS_CLV_L2_PSNP_AUTHENTICATION_NS,
156                 "Authentication(non spec)",
157                 &ett_isis_psnp_authentication,
158                 dissect_l2_snp_authentication_clv
159         },
160         {
161                 0, "", NULL, NULL 
162         }
163 };
164 /*
165  * Name: dissect_snp_payload()
166  *
167  * Description:
168  *      All the snp packets use a common payload format.  We have up
169  *      to n entries (based on length), which are made of:
170  *              2 : remaining life time
171  *              8 : lsp id
172  *              4 : sequence number
173  *              2 : checksum
174  *
175  * Input:
176  *      u_char * : packet data
177  *      int : offset into packet data where we are.
178  *      int : length of payload to decode.
179  *      frame_data * : frame data (complete frame)
180  *      proto_tree * : protocol display tree to fill out.  May be NULL
181  *
182  * Output:
183  *      void, but we will add to proto tree if !NULL.
184  */
185 static void 
186 dissect_snp_lsp_entries(const u_char *pd, int offset, guint length, 
187                 frame_data *fd, proto_tree *tree ) {
188         isis_snp_t *ps;
189
190         ps = (isis_snp_t *) &pd[offset];
191         while ( length > 0 ) {
192                 if ( length < sizeof(isis_psnp_t) ) {
193                         isis_dissect_unknown(offset, length, tree, fd,
194                                 "Short SNP header entry (%d vs %d)", length,
195                                 sizeof(isis_psnp_t) );
196                         return;
197                 }
198                 
199                 proto_tree_add_text(tree, offset, 2, "Remaining life: %d",
200                         pntohs(&ps->isis_snp_remaining_lifetime));
201                 isis_lsp_decode_lsp_id( "LSP ID", tree, offset + 2,
202                         &ps->isis_snp_lsp_id );
203                 proto_tree_add_text(tree, offset+10, 4, 
204                         "LSP Sequence Number: 0x%04x",
205                         pntohl(&ps->isis_snp_sequence_number));
206                 proto_tree_add_text(tree, offset+14, 2, 
207                         "LSP checksum: 0x%02x",
208                         pntohl(&ps->isis_snp_checksum));
209                 length -= sizeof ( isis_snp_t );
210                 offset += sizeof ( isis_snp_t );
211                 ps++;
212         }
213
214 }
215
216 /*
217  * Name: isis_dissect_isis_csnp()
218  *
219  * Description:
220  *      Tear apart a L1 or L2 CSNP header and then call into payload dissect
221  *      to pull apart the lsp id payload.
222  *
223  * Input:
224  *      int : type (l1 csnp, l2 csnp)
225  *      u_char * : packet data
226  *      int : offset into packet data where we are.
227  *      guint : length of clv we are decoding
228  *      frame_data * : frame data (complete frame)
229  *      proto_tree * : protocol display tree to fill out.  May be NULL
230  *
231  * Output:
232  *      void, but we will add to proto tree if !NULL.
233  */
234 void 
235 isis_dissect_isis_csnp(int type, int header_length, const u_char *pd, 
236                 int offset, frame_data *fd, proto_tree *tree){
237         isis_csnp_t     *ilp;
238         proto_item      *ti;
239         proto_tree      *csnp_tree = NULL;
240         int             hlen;
241         int             len;
242
243         hlen = sizeof(*ilp);
244
245         if (fd->cap_len < (offset + hlen)) {
246                 isis_dissect_unknown(offset, hlen, tree, fd,
247                         "not enough capture data for header (%d vs %d)",
248                          hlen, offset - fd->cap_len);
249                 return;
250         }
251         
252         ilp = (isis_csnp_t *) &pd[offset];
253
254         if (tree) {
255                 ti = proto_tree_add_item(tree, proto_isis_csnp,
256                         offset, fd->cap_len - offset, NULL);
257                 csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
258                 proto_tree_add_item(csnp_tree, hf_isis_csnp_pdu_length,
259                         offset, 2, pntohs(&ilp->isis_csnp_pdu_length));
260                 proto_tree_add_text(csnp_tree, offset + 2, 7, 
261                         "Source id: %02x%02x.%02x%02x.%02x%02x.%02x",
262                                 ilp->isis_csnp_source_id[0],
263                                 ilp->isis_csnp_source_id[1],
264                                 ilp->isis_csnp_source_id[2],
265                                 ilp->isis_csnp_source_id[3],
266                                 ilp->isis_csnp_source_id[4],
267                                 ilp->isis_csnp_source_id[5],
268                                 ilp->isis_csnp_source_id[6] );
269                 isis_lsp_decode_lsp_id( "Start LSP id", csnp_tree, offset + 9,
270                         &ilp->isis_csnp_start_lsp_id );
271                 isis_lsp_decode_lsp_id( "End LSP id", csnp_tree, offset + 17,
272                         &ilp->isis_csnp_start_lsp_id );
273         }
274
275         offset += hlen;
276         len = pntohs(&ilp->isis_csnp_pdu_length);
277         len -= header_length;
278         if (len < 0) {
279                 return;
280         }
281         /* Call into payload dissector */
282         if (type == ISIS_TYPE_L1_CSNP ) {
283                 isis_dissect_clvs ( clv_l1_csnp_opts, len, pd, offset, fd,
284                         csnp_tree, ett_isis_csnp_clv_unknown );
285         } else {
286                 isis_dissect_clvs ( clv_l2_csnp_opts, len, pd, offset, fd,
287                         csnp_tree, ett_isis_csnp_clv_unknown );
288         }
289 }
290
291 /*
292  * Name: isis_dissect_isis_psnp()
293  *
294  * Description:
295  *      Tear apart a L1 or L2 PSNP header and then call into payload dissect
296  *      to pull apart the lsp id payload.
297  *
298  * Input:
299  *      u_char * : packet data
300  *      int : offset into packet data where we are.
301  *      guint : length of clv we are decoding
302  *      frame_data * : frame data (complete frame)
303  *      proto_tree * : protocol display tree to fill out.  May be NULL
304  *
305  * Output:
306  *      void, but we will add to proto tree if !NULL.
307  */
308 void 
309 isis_dissect_isis_psnp(int type, int header_length, const u_char *pd, 
310                 int offset, frame_data *fd, proto_tree *tree){
311         isis_psnp_t     *ilp;
312         proto_item      *ti;
313         proto_tree      *psnp_tree = NULL;
314         int             hlen;
315         int             len;
316
317         hlen = sizeof(*ilp);
318
319         if (fd->cap_len < (offset + hlen)) {
320                 isis_dissect_unknown(offset, hlen, tree, fd,
321                         "not enough capture data for header (%d vs %d)",
322                          hlen, offset - fd->cap_len);
323                 return;
324         }
325         
326         ilp = (isis_psnp_t *) &pd[offset];
327
328         if (tree) {
329                 ti = proto_tree_add_item(tree, proto_isis_psnp,
330                         offset, fd->cap_len - offset, NULL);
331                 psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
332                 proto_tree_add_item(psnp_tree, hf_isis_psnp_pdu_length,
333                         offset, 2, pntohs(&ilp->isis_psnp_pdu_length));
334                 proto_tree_add_text(psnp_tree, offset + 2, 7, 
335                         "Source id: %02x%02x.%02x%02x.%02x%02x.%02x",
336                                 ilp->isis_psnp_source_id[0],
337                                 ilp->isis_psnp_source_id[1],
338                                 ilp->isis_psnp_source_id[2],
339                                 ilp->isis_psnp_source_id[3],
340                                 ilp->isis_psnp_source_id[4],
341                                 ilp->isis_psnp_source_id[5],
342                                 ilp->isis_psnp_source_id[6] );
343         }
344
345         offset += hlen;
346         len = pntohs(&ilp->isis_psnp_pdu_length);
347         len -= header_length;
348         if (len < 0) {
349                 isis_dissect_unknown(offset, header_length, tree, fd,
350                         "packet header length %d went beyond packet",
351                         header_length );
352                 return;
353         }
354         /* Call into payload dissector */
355         if (type == ISIS_TYPE_L1_CSNP ) {
356                 isis_dissect_clvs ( clv_l1_csnp_opts, len, pd, offset, fd,
357                         psnp_tree, ett_isis_psnp_clv_unknown );
358         } else {
359                 isis_dissect_clvs ( clv_l2_csnp_opts, len, pd, offset, fd,
360                         psnp_tree, ett_isis_psnp_clv_unknown );
361         }
362 }
363
364 /*
365  * Name: dissect_L1_snp_authentication_clv()
366  *
367  * Description:
368  *      Decode for a lsp packets authenticaion clv.  Calls into the
369  *      clv common one.  An auth inside a L1 SNP is a per area password
370  *
371  * Input:
372  *      u_char * : packet data
373  *      int : current offset into packet data
374  *      guint : length of this clv
375  *      frame_data * : frame data
376  *      proto_tree * : proto tree to build on (may be null)
377  *
378  * Output:
379  *      void, will modify proto_tree if not null.
380  */
381 static void 
382 dissect_l1_snp_authentication_clv(const u_char *pd, int offset, 
383                 guint length, frame_data *fd, proto_tree *tree) {
384         isis_dissect_authentication_clv(pd, offset, length, fd, tree, 
385                 "Per area authentication" );
386 }
387
388 /*
389  * Name: dissect_l2_authentication_clv()
390  *
391  * Description:
392  *      Decode for a lsp packets authenticaion clv.  Calls into the
393  *      clv common one.  An auth inside a L2 LSP is a per domain password
394  *
395  * Input:
396  *      u_char * : packet data
397  *      int : current offset into packet data
398  *      guint : length of this clv
399  *      frame_data * : frame data
400  *      proto_tree * : proto tree to build on (may be null)
401  *
402  * Output:
403  *      void, will modify proto_tree if not null.
404  */
405 static void 
406 dissect_l2_snp_authentication_clv(const u_char *pd, int offset, 
407                 guint length, frame_data *fd, proto_tree *tree) {
408         isis_dissect_authentication_clv(pd, offset, length, fd, tree, 
409                 "Per domain authentication" );
410 }
411
412 /*
413  * Name: proto_register_isis_csnp()
414  *
415  * Description: 
416  *      Register our protocol sub-sets with protocol manager.
417  *      NOTE: this procedure is autolinked by the makefile process that
418  *              builds register.c
419  *
420  * Input:
421  *      u_char * : packet data
422  *      int : offset into packet data where we are.
423  *      guint : length of clv we are decoding
424  *      frame_data * : frame data (complete frame)
425  *      proto_tree * : protocol display tree to fill out.  May be NULL
426  *
427  * Output:
428  *      void, but we will add to proto tree if !NULL.
429  */
430 void 
431 proto_register_isis_csnp(void) {
432         static hf_register_info hf[] = {
433                 { &hf_isis_csnp_pdu_length,
434                 { "PDU length",         "isis_csnp.pdu_length", FT_UINT16, 
435                   BASE_DEC, NULL, 0x0, "" }},
436         };
437         static gint *ett[] = {
438                 &ett_isis_csnp,
439                 &ett_isis_csnp_lsp_entries,
440                 &ett_isis_csnp_authentication,
441                 &ett_isis_csnp_clv_unknown,
442         };
443
444         proto_isis_csnp = proto_register_protocol("ISIS csnp", "ISIS-csnp");
445         proto_register_field_array(proto_isis_csnp, hf, array_length(hf));
446         proto_register_subtree_array(ett, array_length(ett));
447 }
448
449
450 /*
451  * Name: proto_register_isis_psnp()
452  *
453  * Description: 
454  *      Register our protocol sub-sets with protocol manager.
455  *      NOTE: this procedure is autolinked by the makefile process that
456  *              builds register.c
457  *
458  * Input:
459  *      u_char * : packet data
460  *      int : offset into packet data where we are.
461  *      guint : length of clv we are decoding
462  *      frame_data * : frame data (complete frame)
463  *      proto_tree * : protocol display tree to fill out.  May be NULL
464  *
465  * Output:
466  *      void, but we will add to proto tree if !NULL.
467  */
468 void 
469 proto_register_isis_psnp(void) {
470         static hf_register_info hf[] = {
471                 { &hf_isis_psnp_pdu_length,
472                 { "PDU length",         "isis_psnp.pdu_length", FT_UINT16, 
473                   BASE_DEC, NULL, 0x0, "" }},
474         };
475         static gint *ett[] = {
476                 &ett_isis_psnp,
477                 &ett_isis_psnp_lsp_entries,
478                 &ett_isis_psnp_authentication,
479                 &ett_isis_psnp_clv_unknown,
480         };
481
482         proto_isis_psnp = proto_register_protocol("ISIS psnp", "ISIS-psnp");
483         proto_register_field_array(proto_isis_psnp, hf, array_length(hf));
484         proto_register_subtree_array(ett, array_length(ett));
485 }
486