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