understand TCP MD5 signature. Greg Hankins <gregh@twoguys.org>
[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.7 2000/08/13 14:08:22 deniel 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, int id_length, frame_data *fd, proto_tree *tree );
65 static void dissect_l1_snp_authentication_clv(const u_char *pd, int offset,
66                 guint length, int id_length, frame_data *fd, proto_tree *tree );
67 static void dissect_l2_snp_authentication_clv(const u_char *pd, int offset,
68                 guint length, int id_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_lsp_entries()
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  *      guint : length of payload to decode.
180  *      int : length of IDs in packet.
181  *      frame_data * : frame data (complete frame)
182  *      proto_tree * : protocol display tree to fill out.  May be NULL
183  *
184  * Output:
185  *      void, but we will add to proto tree if !NULL.
186  */
187 static void 
188 dissect_snp_lsp_entries(const u_char *pd, int offset, guint length, 
189                 int id_length, frame_data *fd, proto_tree *tree ) {
190         while ( length > 0 ) {
191                 if ( length < 2+id_length+2+4+2 ) {
192                         isis_dissect_unknown(offset, length, tree, fd,
193                                 "Short SNP header entry (%d vs %d)", length,
194                                 2+id_length+2+4+2 );
195                         return;
196                 }
197                 
198                 proto_tree_add_text(tree, NullTVB, offset, 2, "Remaining life      : %d",
199                         pntohs(&pd[offset]));
200                 length -= 2;
201                 offset += 2;
202
203                 isis_lsp_decode_lsp_id( "LSP ID              ", tree, pd,
204                         offset, id_length);
205                 length -= id_length + 2;
206                 offset += id_length + 2;
207
208                 proto_tree_add_text(tree, NullTVB, offset, 4, 
209                         "LSP Sequence Number : 0x%04x",
210                         pntohl(&pd[offset]));
211                 length -= 4;
212                 offset += 4;
213
214                 proto_tree_add_text(tree, NullTVB, offset, 2, 
215                         "LSP checksum        : 0x%02x",
216                         pntohs(&pd[offset]));
217                 length -= 2;
218                 offset += 2;
219         }
220
221 }
222
223 /*
224  * Name: isis_dissect_isis_csnp()
225  *
226  * Description:
227  *      Tear apart a L1 or L2 CSNP header and then call into payload dissect
228  *      to pull apart the lsp id payload.
229  *
230  * Input:
231  *      int : type (l1 csnp, l2 csnp)
232  *      int : header length of packet.
233  *      int : length of IDs in packet.
234  *      u_char * : packet data
235  *      int offset : our offset into packet data.
236  *      frame_data * : frame data
237  *      proto_tree * : protocol display tree to add to.  May be NULL.
238  *
239  * Output:
240  *      void, but we will add to proto tree if !NULL.
241  */
242 void 
243 isis_dissect_isis_csnp(int type, int header_length, int id_length,
244                 const u_char *pd, int offset, frame_data *fd, proto_tree *tree){
245         proto_item      *ti;
246         proto_tree      *csnp_tree = NULL;
247         int             hlen;
248         guint16         pdu_length;
249         int             len;
250
251         OLD_CHECK_DISPLAY_AS_DATA(proto_isis_csnp, pd, offset, fd, tree);
252
253         hlen = 2+id_length+1+id_length+2+id_length+2;
254
255         if (!BYTES_ARE_IN_FRAME(offset, hlen)) {
256                 isis_dissect_unknown(offset, hlen, tree, fd,
257                         "not enough capture data for header (%d vs %d)",
258                          hlen, END_OF_FRAME);
259                 return;
260         }
261         
262         if (tree) {
263                 ti = proto_tree_add_item(tree, proto_isis_csnp, NullTVB,
264                         offset, END_OF_FRAME, FALSE);
265                 csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
266         }
267
268         pdu_length = pntohs(&pd[offset]);
269         if (tree) {
270                 proto_tree_add_uint(csnp_tree, hf_isis_csnp_pdu_length, NullTVB,
271                         offset, 2, pdu_length);
272         }
273         offset += 2;
274
275         if (tree) {
276                 proto_tree_add_text(csnp_tree, NullTVB, offset, id_length + 1, 
277                         "Source id    : %s",
278                                 print_system_id( pd + offset, id_length + 1 ) );
279         }
280         offset += id_length + 1;
281
282         if (tree) {
283                 isis_lsp_decode_lsp_id( "Start LSP id ", csnp_tree, pd, offset,
284                         id_length );
285         }
286         offset += id_length + 2;
287
288         if (tree) {
289                 isis_lsp_decode_lsp_id( "End   LSP id ", csnp_tree, pd, offset,
290                         id_length );
291         }
292         offset += id_length + 2;
293
294         len = pdu_length - header_length;
295         if (len < 0) {
296                 return;
297         }
298         /* Call into payload dissector */
299         if (type == ISIS_TYPE_L1_CSNP ) {
300                 isis_dissect_clvs ( clv_l1_csnp_opts, len, id_length, pd,
301                         offset, fd, csnp_tree, ett_isis_csnp_clv_unknown );
302         } else {
303                 isis_dissect_clvs ( clv_l2_csnp_opts, len, id_length, pd,
304                         offset, fd, csnp_tree, ett_isis_csnp_clv_unknown );
305         }
306 }
307
308 /*
309  * Name: isis_dissect_isis_psnp()
310  *
311  * Description:
312  *      Tear apart a L1 or L2 PSNP header and then call into payload dissect
313  *      to pull apart the lsp id payload.
314  *
315  * Input:
316  *      int : type (l1 psnp, l2 psnp)
317  *      int : header length of packet.
318  *      int : length of IDs in packet.
319  *      u_char * : packet data
320  *      int offset : our offset into packet data.
321  *      frame_data * : frame data
322  *      proto_tree * : protocol display tree to add to.  May be NULL.
323  *
324  * Output:
325  *      void, but we will add to proto tree if !NULL.
326  */
327 void 
328 isis_dissect_isis_psnp(int type, int header_length, int id_length,
329                 const u_char *pd, int offset, frame_data *fd, proto_tree *tree){
330         proto_item      *ti;
331         proto_tree      *psnp_tree = NULL;
332         int             hlen;
333         guint16         pdu_length;
334         int             len;
335
336         OLD_CHECK_DISPLAY_AS_DATA(proto_isis_psnp, pd, offset, fd, tree);
337     
338         hlen = 2+id_length+1;
339
340         if (!BYTES_ARE_IN_FRAME(offset, hlen)) {
341                 isis_dissect_unknown(offset, hlen, tree, fd,
342                         "not enough capture data for header (%d vs %d)",
343                          hlen, END_OF_FRAME);
344                 return;
345         }
346         
347         if (tree) {
348                 ti = proto_tree_add_item(tree, proto_isis_psnp, NullTVB,
349                         offset, END_OF_FRAME, FALSE);
350                 psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
351         }
352
353         pdu_length = pntohs(&pd[offset]);
354         if (tree) {
355                 proto_tree_add_uint(psnp_tree, hf_isis_psnp_pdu_length, NullTVB,
356                         offset, 2, pdu_length);
357         }
358         offset += 2;
359
360         if (tree) {
361                 proto_tree_add_text(psnp_tree, NullTVB, offset, id_length + 1,
362                         "Source id: %s",
363                         print_system_id( pd + offset, id_length + 1 ) );
364         }
365         offset += id_length + 1;
366
367         len = pdu_length - header_length;
368         if (len < 0) {
369                 isis_dissect_unknown(offset, header_length, tree, fd,
370                         "packet header length %d went beyond packet",
371                         header_length );
372                 return;
373         }
374         /* Call into payload dissector */
375         if (type == ISIS_TYPE_L1_CSNP ) {
376                 isis_dissect_clvs ( clv_l1_csnp_opts, len, id_length, pd,
377                         offset, fd, psnp_tree, ett_isis_psnp_clv_unknown );
378         } else {
379                 isis_dissect_clvs ( clv_l2_csnp_opts, len, id_length, pd,
380                         offset, fd, psnp_tree, ett_isis_psnp_clv_unknown );
381         }
382 }
383
384 /*
385  * Name: dissect_L1_snp_authentication_clv()
386  *
387  * Description:
388  *      Decode for a lsp packets authenticaion clv.  Calls into the
389  *      clv common one.  An auth inside a L1 SNP is a per area password
390  *
391  * Input:
392  *      u_char * : packet data
393  *      int : current offset into packet data
394  *      guint : length of this clv
395  *      int : length of IDs in packet.
396  *      frame_data * : frame data
397  *      proto_tree * : proto tree to build on (may be null)
398  *
399  * Output:
400  *      void, will modify proto_tree if not null.
401  */
402 static void 
403 dissect_l1_snp_authentication_clv(const u_char *pd, int offset, 
404                 guint length, int id_length, frame_data *fd, proto_tree *tree) {
405         isis_dissect_authentication_clv(pd, offset, length, fd, tree, 
406                 "Per area authentication" );
407 }
408
409 /*
410  * Name: dissect_l2_authentication_clv()
411  *
412  * Description:
413  *      Decode for a lsp packets authenticaion clv.  Calls into the
414  *      clv common one.  An auth inside a L2 LSP is a per domain password
415  *
416  * Input:
417  *      u_char * : packet data
418  *      int : current offset into packet data
419  *      guint : length of this clv
420  *      int : length of IDs in packet.
421  *      frame_data * : frame data
422  *      proto_tree * : proto tree to build on (may be null)
423  *
424  * Output:
425  *      void, will modify proto_tree if not null.
426  */
427 static void 
428 dissect_l2_snp_authentication_clv(const u_char *pd, int offset, 
429                 guint length, int id_length, frame_data *fd, proto_tree *tree) {
430         isis_dissect_authentication_clv(pd, offset, length, fd, tree, 
431                 "Per domain authentication" );
432 }
433
434 /*
435  * Name: proto_register_isis_csnp()
436  *
437  * Description: 
438  *      Register our protocol sub-sets with protocol manager.
439  *      NOTE: this procedure is autolinked by the makefile process that
440  *              builds register.c
441  *
442  * Input:
443  *      u_char * : packet data
444  *      int : offset into packet data where we are.
445  *      guint : length of clv we are decoding
446  *      frame_data * : frame data (complete frame)
447  *      proto_tree * : protocol display tree to fill out.  May be NULL
448  *
449  * Output:
450  *      void, but we will add to proto tree if !NULL.
451  */
452 void 
453 proto_register_isis_csnp(void) {
454         static hf_register_info hf[] = {
455                 { &hf_isis_csnp_pdu_length,
456                 { "PDU length",         "isis_csnp.pdu_length", FT_UINT16, 
457                   BASE_DEC, NULL, 0x0, "" }},
458         };
459         static gint *ett[] = {
460                 &ett_isis_csnp,
461                 &ett_isis_csnp_lsp_entries,
462                 &ett_isis_csnp_authentication,
463                 &ett_isis_csnp_clv_unknown,
464         };
465
466         proto_isis_csnp = proto_register_protocol(PROTO_STRING_CSNP, "isis_csnp");
467         proto_register_field_array(proto_isis_csnp, hf, array_length(hf));
468         proto_register_subtree_array(ett, array_length(ett));
469 }
470
471
472 /*
473  * Name: proto_register_isis_psnp()
474  *
475  * Description: 
476  *      Register our protocol sub-sets with protocol manager.
477  *      NOTE: this procedure is autolinked by the makefile process that
478  *              builds register.c
479  *
480  * Input:
481  *      u_char * : packet data
482  *      int : offset into packet data where we are.
483  *      guint : length of clv we are decoding
484  *      frame_data * : frame data (complete frame)
485  *      proto_tree * : protocol display tree to fill out.  May be NULL
486  *
487  * Output:
488  *      void, but we will add to proto tree if !NULL.
489  */
490 void 
491 proto_register_isis_psnp(void) {
492         static hf_register_info hf[] = {
493                 { &hf_isis_psnp_pdu_length,
494                 { "PDU length",         "isis_psnp.pdu_length", FT_UINT16, 
495                   BASE_DEC, NULL, 0x0, "" }},
496         };
497         static gint *ett[] = {
498                 &ett_isis_psnp,
499                 &ett_isis_psnp_lsp_entries,
500                 &ett_isis_psnp_authentication,
501                 &ett_isis_psnp_clv_unknown,
502         };
503
504         proto_isis_psnp = proto_register_protocol(PROTO_STRING_PSNP, "isis_psnp");
505         proto_register_field_array(proto_isis_psnp, hf, array_length(hf));
506         proto_register_subtree_array(ett, array_length(ett));
507 }