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