Maybe the problem is that the compilers used on AIX weren't defining
[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.22 2003/07/09 04:25:16 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 #include <stdio.h>
31 #include <string.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "packet-osi.h"
35 #include "packet-isis.h"
36 #include "packet-isis-clv.h"
37 #include "packet-isis-lsp.h"
38 #include "packet-isis-snp.h"
39
40 /* csnp packets */
41 static int hf_isis_csnp_pdu_length = -1;
42 static gint ett_isis_csnp = -1;
43 static gint ett_isis_csnp_lsp_entries = -1;
44 static gint ett_isis_csnp_lsp_entry = -1;
45 static gint ett_isis_csnp_authentication = -1;
46 static gint ett_isis_csnp_clv_unknown = -1;
47
48 /* psnp packets */
49 static int hf_isis_psnp_pdu_length = -1;
50 static gint ett_isis_psnp = -1;
51 static gint ett_isis_psnp_lsp_entries = -1;
52 static gint ett_isis_psnp_lsp_entry = -1;
53 static gint ett_isis_psnp_authentication = -1;
54 static gint ett_isis_psnp_clv_unknown = -1;
55
56 static void dissect_l1_snp_authentication_clv(tvbuff_t *tvb,
57         proto_tree *tree, int offset, int id_length, int length);
58 static void dissect_l2_snp_authentication_clv(tvbuff_t *tvb,
59         proto_tree *tree, int offset, int id_length, int length);
60 static void dissect_csnp_lsp_entries(tvbuff_t *tvb,
61         proto_tree *tree, int offset, int id_length, int length);
62 static void dissect_psnp_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_csnp_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_csnp_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_psnp_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_psnp_lsp_entries
143         },
144         {
145                 ISIS_CLV_L2_PSNP_AUTHENTICATION_NS,
146                 "Authentication(non spec)",
147                 &ett_isis_psnp_authentication,
148                 dissect_l2_snp_authentication_clv
149         },
150         {
151                 ISIS_CLV_L2_PSNP_AUTHENTICATION,
152                 "Authentication",
153                 &ett_isis_psnp_authentication,
154                 dissect_l2_snp_authentication_clv
155         },
156         {
157                 0, "", NULL, NULL
158         }
159 };
160
161 /*
162  * Name: dissect_snp_lsp_entries()
163  *
164  * Description:
165  *      All the snp packets use a common payload format.  We have up
166  *      to n entries (based on length), which are made of:
167  *              2         : remaining life time
168  *              id_length : lsp id
169  *              4         : sequence number
170  *              2         : checksum
171  *
172  * Input:
173  *      tvbuff_t * : tvbuffer for packet data
174  *      proto_tree * : protocol display tree to fill out.  May be NULL
175  *      int : offset into packet data where we are.
176  *      int : length of IDs in packet.
177  *      int : length of payload to decode.
178  *
179  * Output:
180  *      void, but we will add to proto tree if !NULL.
181  */
182 static void
183 dissect_csnp_lsp_entries(tvbuff_t *tvb, proto_tree *tree, int offset,
184         int id_length, int length)
185 {
186         proto_tree *subtree,*ti;
187
188         while ( length > 0 ) {
189                 if ( length < 2+id_length+2+4+2 ) {
190                         isis_dissect_unknown(tvb, tree, offset,
191                                 "Short CSNP header entry (%d vs %d)", length,
192                                 2+id_length+2+4+2 );
193                         return;
194                 }
195
196                 ti = proto_tree_add_text(tree, tvb, offset, 2+id_length+2+4+2,
197                                     "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
198                                            print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ),
199                                            tvb_get_ntohl(tvb, offset+2+id_length+2),
200                                            tvb_get_ntohs(tvb, offset),
201                                            tvb_get_ntohs(tvb, offset+2+id_length+2+4));
202
203                 subtree = proto_item_add_subtree(ti,ett_isis_csnp_lsp_entry);
204
205                 proto_tree_add_text(subtree, tvb, offset+2, 8,
206                         "LSP-ID:             : %s",
207                         print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ));
208
209                 proto_tree_add_text(subtree, tvb, offset+2+id_length+2, 4,
210                         "LSP Sequence Number : 0x%08x",
211                         tvb_get_ntohl(tvb, offset+2+id_length+2));
212
213                 proto_tree_add_text(subtree, tvb, offset, 2,
214                         "Remaining Lifetime  : %us",
215                         tvb_get_ntohs(tvb, offset));
216
217                 proto_tree_add_text(subtree, tvb, offset+2+id_length+2+4, 2,
218                         "LSP checksum        : 0x%04x",
219                         tvb_get_ntohs(tvb, offset+2+id_length+2+4));
220
221                 length -= 2+id_length+2+4+2;
222                 offset += 2+id_length+2+4+2;
223         }
224
225 }
226
227 static void
228 dissect_psnp_lsp_entries(tvbuff_t *tvb, proto_tree *tree, int offset,
229         int id_length, int length)
230 {
231         proto_tree *subtree,*ti;
232
233         while ( length > 0 ) {
234                 if ( length < 2+id_length+2+4+2 ) {
235                         isis_dissect_unknown(tvb, tree, offset,
236                                 "Short PSNP header entry (%d vs %d)", length,
237                                 2+id_length+2+4+2 );
238                         return;
239                 }
240
241                 ti = proto_tree_add_text(tree, tvb, offset, 2+id_length+2+4+2,
242                                     "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
243                                            print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ),
244                                            tvb_get_ntohl(tvb, offset+2+id_length+2),
245                                            tvb_get_ntohs(tvb, offset),
246                                            tvb_get_ntohs(tvb, offset+2+id_length+2+4));
247
248                 subtree = proto_item_add_subtree(ti,ett_isis_psnp_lsp_entry);
249
250                 proto_tree_add_text(subtree, tvb, offset+2, 8,
251                         "LSP-ID:             : %s",
252                         print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ));
253
254                 proto_tree_add_text(subtree, tvb, offset+2+id_length+2, 4,
255                         "LSP Sequence Number : 0x%08x",
256                         tvb_get_ntohl(tvb, offset+2+id_length+2));
257
258                 proto_tree_add_text(subtree, tvb, offset, 2,
259                         "Remaining Lifetime  : %us",
260                         tvb_get_ntohs(tvb, offset));
261
262                 proto_tree_add_text(subtree, tvb, offset+2+id_length+2+4, 2,
263                         "LSP checksum        : 0x%04x",
264                         tvb_get_ntohs(tvb, offset+2+id_length+2+4));
265
266                 length -= 2+id_length+2+4+2;
267                 offset += 2+id_length+2+4+2;
268         }
269
270 }
271
272 /*
273  * Name: isis_dissect_isis_csnp()
274  *
275  * Description:
276  *      Tear apart a L1 or L2 CSNP header and then call into payload dissect
277  *      to pull apart the lsp id payload.
278  *
279  * Input:
280  *      tvbuff_t * : tvbuffer for packet data
281  *      proto_tree * : protocol display tree to add to.  May be NULL.
282  *      int offset : our offset into packet data.
283  *      int : type (l1 csnp, l2 csnp)
284  *      int : header length of packet.
285  *      int : length of IDs in packet.
286  *
287  * Output:
288  *      void, but we will add to proto tree if !NULL.
289  */
290 void
291 isis_dissect_isis_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
292         int type, int header_length, int id_length)
293 {
294         proto_item      *ti;
295         proto_tree      *csnp_tree = NULL;
296         guint16         pdu_length;
297         int             len;
298
299         if (tree) {
300                 ti = proto_tree_add_text(tree, tvb, offset, -1,
301                     PROTO_STRING_CSNP);
302                 csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
303         }
304
305         pdu_length = tvb_get_ntohs(tvb, offset);
306         if (tree) {
307                 proto_tree_add_uint(csnp_tree, hf_isis_csnp_pdu_length, tvb,
308                         offset, 2, pdu_length);
309         }
310         offset += 2;
311
312         if (tree) {
313                 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 1,
314                         "Source-ID:    %s",
315                                 print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
316         }
317         if (check_col(pinfo->cinfo, COL_INFO)) {
318                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s",
319                         print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
320         }
321         offset += id_length + 1;
322
323         if (tree) {
324                 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 2,
325                         "Start LSP-ID: %s",
326                                     print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );                
327         }
328         if (check_col(pinfo->cinfo, COL_INFO)) {
329                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Start LSP-ID: %s",
330                         print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
331         }
332         offset += id_length + 2;
333
334         if (tree) {
335                 proto_tree_add_text(csnp_tree, tvb, offset, id_length + 2,
336                         "End LSP-ID: %s",
337                                     print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );  
338         }
339         if (check_col(pinfo->cinfo, COL_INFO)) {
340                 col_append_fstr(pinfo->cinfo, COL_INFO, ", End LSP-ID: %s",
341                         print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
342         }
343         offset += id_length + 2;
344
345         len = pdu_length - header_length;
346         if (len < 0) {
347                 return;
348         }
349         /* Call into payload dissector */
350         if (type == ISIS_TYPE_L1_CSNP ) {
351                 isis_dissect_clvs(tvb, csnp_tree, offset,
352                         clv_l1_csnp_opts, len, id_length,
353                         ett_isis_csnp_clv_unknown );
354         } else {
355                 isis_dissect_clvs(tvb, csnp_tree, offset,
356                         clv_l2_csnp_opts, len, id_length,
357                         ett_isis_csnp_clv_unknown );
358         }
359 }
360
361 /*
362  * Name: isis_dissect_isis_psnp()
363  *
364  * Description:
365  *      Tear apart a L1 or L2 PSNP header and then call into payload dissect
366  *      to pull apart the lsp id payload.
367  *
368  * Input:
369  *      tvbuff_t * : tvbuffer for packet data
370  *      proto_tree * : protocol display tree to add to.  May be NULL.
371  *      int : our offset into packet data
372  *      int : type (l1 psnp, l2 psnp)
373  *      int : header length of packet.
374  *      int : length of IDs in packet.
375  *
376  * Output:
377  *      void, but we will add to proto tree if !NULL.
378  */
379 void
380 isis_dissect_isis_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
381         int type, int header_length, int id_length)
382 {
383         proto_item      *ti;
384         proto_tree      *psnp_tree = NULL;
385         guint16         pdu_length;
386         int             len;
387
388         if (tree) {
389                 ti = proto_tree_add_text(tree, tvb, offset, -1,
390                     PROTO_STRING_PSNP);
391                 psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
392         }
393
394         pdu_length = tvb_get_ntohs(tvb, offset);
395         if (tree) {
396                 proto_tree_add_uint(psnp_tree, hf_isis_psnp_pdu_length, tvb,
397                         offset, 2, pdu_length);
398         }
399         offset += 2;
400
401         if (tree) {
402                 proto_tree_add_text(psnp_tree, tvb, offset, id_length + 1,
403                         "Source-ID: %s",
404                         print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length + 1 ) );
405         }
406         if (check_col(pinfo->cinfo, COL_INFO)) {
407                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s",
408                         print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
409         }
410         offset += id_length + 1;
411
412         len = pdu_length - header_length;
413         if (len < 0) {
414                 isis_dissect_unknown(tvb, tree, offset,
415                         "packet header length %d went beyond packet",
416                         header_length );
417                 return;
418         }
419         /* Call into payload dissector */
420         if (type == ISIS_TYPE_L1_PSNP ) {
421                 isis_dissect_clvs(tvb, psnp_tree, offset,
422                         clv_l1_psnp_opts, len, id_length,
423                         ett_isis_psnp_clv_unknown );
424         } else {
425                 isis_dissect_clvs(tvb, psnp_tree, offset,
426                         clv_l2_psnp_opts, len, id_length,
427                         ett_isis_psnp_clv_unknown );
428         }
429 }
430
431 /*
432  * Name: dissect_L1_snp_authentication_clv()
433  *
434  * Description:
435  *      Decode for a lsp packets authenticaion clv.  Calls into the
436  *      clv common one.  An auth inside a L1 SNP is a per area password
437  *
438  * Input:
439  *      tvbuff_t * : tvbuffer for packet data
440  *      proto_tree * : proto tree to build on (may be null)
441  *      int : current offset into packet data
442  *      int : length of IDs in packet.
443  *      int : length of this clv
444  *
445  * Output:
446  *      void, will modify proto_tree if not null.
447  */
448 static void
449 dissect_l1_snp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
450         int id_length _U_, int length)
451 {
452         isis_dissect_authentication_clv(tvb, tree, offset, length,
453                 "Per area authentication" );
454 }
455
456 /*
457  * Name: dissect_l2_authentication_clv()
458  *
459  * Description:
460  *      Decode for a lsp packets authenticaion clv.  Calls into the
461  *      clv common one.  An auth inside a L2 LSP is a per domain password
462  *
463  * Input:
464  *      tvbuff_t * : tvbuffer for packet data
465  *      proto_tree * : proto tree to build on (may be null)
466  *      int : current offset into packet data
467  *      int : length of IDs in packet.
468  *      int : length of this clv
469  *
470  * Output:
471  *      void, will modify proto_tree if not null.
472  */
473 static void
474 dissect_l2_snp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
475         int id_length _U_, int length)
476 {
477         isis_dissect_authentication_clv(tvb, tree, offset, length,
478                 "Per domain authentication" );
479 }
480
481 /*
482  * Name: isis_register_csnp()
483  *
484  * Description:
485  *      Register our protocol sub-sets with protocol manager.
486  *
487  * Input:
488  *      int : protocol index for the ISIS protocol
489  *
490  * Output:
491  *      void
492  */
493 void
494 isis_register_csnp(int proto_isis) {
495         static hf_register_info hf[] = {
496                 { &hf_isis_csnp_pdu_length,
497                 { "PDU length",         "isis.csnp.pdu_length", FT_UINT16,
498                   BASE_DEC, NULL, 0x0, "", HFILL }},
499         };
500         static gint *ett[] = {
501                 &ett_isis_csnp,
502                 &ett_isis_csnp_lsp_entries,
503                 &ett_isis_csnp_lsp_entry,
504                 &ett_isis_csnp_authentication,
505                 &ett_isis_csnp_clv_unknown,
506         };
507
508         proto_register_field_array(proto_isis, hf, array_length(hf));
509         proto_register_subtree_array(ett, array_length(ett));
510 }
511
512
513 /*
514  * Name: isis_register_psnp()
515  *
516  * Description:
517  *      Register our protocol sub-sets with protocol manager.
518  *
519  * Input:
520  *      int : protocol index for the ISIS protocol
521  *
522  * Output:
523  *      void
524  */
525 void
526 isis_register_psnp(int proto_isis) {
527         static hf_register_info hf[] = {
528                 { &hf_isis_psnp_pdu_length,
529                 { "PDU length",         "isis.psnp.pdu_length", FT_UINT16,
530                   BASE_DEC, NULL, 0x0, "", HFILL }},
531         };
532         static gint *ett[] = {
533                 &ett_isis_psnp,
534                 &ett_isis_psnp_lsp_entries,
535                 &ett_isis_psnp_lsp_entry,
536                 &ett_isis_psnp_authentication,
537                 &ett_isis_psnp_clv_unknown,
538         };
539
540         proto_register_field_array(proto_isis, hf, array_length(hf));
541         proto_register_subtree_array(ett, array_length(ett));
542 }