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