Give the code that computes protocol statistics a progress dialog box,
[obnox/wireshark/wip.git] / packet-vines.c
1 /* packet-vines.c
2  * Routines for Banyan VINES protocol packet disassembly
3  *
4  * $Id: packet-vines.c,v 1.25 2001/03/13 21:34:24 gram Exp $
5  *
6  * Don Lafontaine <lafont02@cn.ca>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  * Joerg Mayer <jmayer@telemation.de>
12  *
13  * 
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40
41 #include <string.h>
42 #include <glib.h>
43 #include "etypes.h"
44 #include "ppptypes.h"
45 #include "packet.h"
46 #include "packet-vines.h"
47 #include "packet-ip.h"
48
49 #define UDP_PORT_VINES  573
50
51 static int proto_vines = -1;
52 static int hf_vines_protocol = -1;
53
54 static gint ett_vines = -1;
55
56 static int proto_vines_frp = -1;
57
58 static gint ett_vines_frp = -1;
59
60 static int proto_vines_spp = -1;
61
62 static gint ett_vines_spp = -1;
63
64 static void dissect_vines_frp(tvbuff_t *, packet_info *, proto_tree *);
65 #if 0
66 static void dissect_vines_arp(tvbuff_t *, packet_info *, proto_tree *);
67 static void dissect_vines_icp(tvbuff_t *, packet_info *, proto_tree *);
68 static void dissect_vines_ipc(tvbuff_t *, packet_info *, proto_tree *);
69 static void dissect_vines_rtp(tvbuff_t *, packet_info *, proto_tree *);
70 #endif
71 static void dissect_vines_spp(tvbuff_t *, packet_info *, proto_tree *);
72 static void dissect_vines(tvbuff_t *, packet_info *, proto_tree *);
73
74 void
75 capture_vines(const u_char *pd, int offset, packet_counts *ld)
76 {
77         ld->vines++;
78 }
79
80 /* AFAIK Vines FRP (Fragmentation Protocol) is used on all media except
81  * Ethernet and TR (and probably FDDI) - Fragmentation on these media types
82  * is not possible
83  * FIXME: Do we need to use this header with PPP too?
84  */
85 static void
86 dissect_vines_frp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
87 {
88         guint8   vines_frp_ctrl;
89         proto_tree *vines_frp_tree;
90         proto_item *ti;
91         gchar   frp_flags_str[32];
92         tvbuff_t *next_tvb;
93
94         CHECK_DISPLAY_AS_DATA(proto_vines_frp, tvb, pinfo, tree);
95
96         pinfo->current_proto = "Vines FRP";
97
98         if (check_col(pinfo->fd, COL_PROTOCOL))
99                 col_set_str(pinfo->fd, COL_PROTOCOL, "Vines FRP");
100         if (check_col(pinfo->fd, COL_INFO))
101                 col_clear(pinfo->fd, COL_INFO);
102
103         if (tree) {
104                 ti = proto_tree_add_item(tree, proto_vines_frp, tvb, 0, 2,
105                     FALSE);
106                 vines_frp_tree = proto_item_add_subtree(ti, ett_vines_frp);
107
108                 vines_frp_ctrl = tvb_get_guint8(tvb, 0);
109   
110                 /*
111                  * 1: first fragment of vines packet
112                  * 2: last fragment of vines packet
113                  * 4 ... 80: unused
114                  */
115                 switch (vines_frp_ctrl) {
116
117                 case 0:
118                         strcpy(frp_flags_str, "middle");
119                         break;
120
121                 case 1:
122                         strcpy(frp_flags_str, "first");
123                         break;
124
125                 case 2:
126                         strcpy(frp_flags_str, "last");
127                         break;
128
129                 case 3:
130                         strcpy(frp_flags_str, "only");
131                         break;
132
133                 default:
134                         strcpy(frp_flags_str, "please report: unknown");
135                         break;
136                 }
137   
138                 proto_tree_add_text(vines_frp_tree, tvb, 0, 1, 
139                                     "Control Flags: 0x%02x = %s fragment", 
140                                     vines_frp_ctrl, frp_flags_str);
141
142                 proto_tree_add_text(vines_frp_tree, tvb, 1, 1, 
143                                     "Sequence Number: 0x%02x",
144                                     tvb_get_guint8(tvb, 1));
145         }
146
147         /* Decode the "real" Vines now */
148         next_tvb = tvb_new_subset(tvb, 2, -1, -1);
149         dissect_vines(next_tvb, pinfo, tree);
150 }
151
152 void
153 proto_register_vines_frp(void)
154 {
155         static gint *ett[] = {
156                 &ett_vines_frp,
157         };
158
159         proto_vines_frp = proto_register_protocol(
160             "Banyan Vines Fragmentation Protocol", "Vines FRP", "vines_frp");
161         proto_register_subtree_array(ett, array_length(ett));
162 }
163
164 void
165 proto_reg_handoff_vines_frp(void)
166 {
167         dissector_add("ip.proto", IP_PROTO_VINES, dissect_vines_frp,
168             proto_vines_frp);
169
170         /* XXX: AFAIK, src and dst port must be the same; should
171            the dissector check for that? */
172         dissector_add("udp.port", UDP_PORT_VINES, dissect_vines_frp,
173             proto_vines_frp);
174 }
175
176 gchar *
177 vines_addr_to_str(const guint8 *addrp)
178 {
179   static gchar  str[3][214];
180   static gchar  *cur;
181
182   if (cur == &str[0][0]) {
183     cur = &str[1][0];
184   } else if (cur == &str[1][0]) {
185     cur = &str[2][0];
186   } else {
187     cur = &str[0][0];
188   }
189
190   sprintf(cur, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
191   return cur;
192 }
193
194 static void
195 dissect_vines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
196 {
197         int         offset = 0;
198         e_vip       viph;
199         proto_tree *vip_tree;
200         proto_item *ti;
201 /*      gchar      tos_str[32]; */
202         const guint8     *dst_addr, *src_addr;
203         int  is_broadcast = 0;
204         int  hops = 0;
205         tvbuff_t *next_tvb;
206
207         CHECK_DISPLAY_AS_DATA(proto_vines, tvb, pinfo, tree);
208
209         pinfo->current_proto = "Vines";
210
211         if (check_col(pinfo->fd, COL_PROTOCOL))
212                 col_set_str(pinfo->fd, COL_PROTOCOL, "Vines");
213         if (check_col(pinfo->fd, COL_INFO))
214                 col_clear(pinfo->fd, COL_INFO);
215
216         /* To do: check for runts, errs, etc. */
217
218         /* Avoids alignment problems on many architectures. */
219         tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vip));
220
221         viph.vip_chksum = ntohs(viph.vip_chksum);
222         viph.vip_pktlen = ntohs(viph.vip_pktlen);
223         viph.vip_dnet = ntohl(viph.vip_dnet);
224         viph.vip_dsub = ntohs(viph.vip_dsub);
225         viph.vip_snet = ntohl(viph.vip_snet);
226         viph.vip_ssub = ntohs(viph.vip_ssub);
227
228         switch (viph.vip_proto) {
229         case VIP_PROTO_IPC:
230                 if (check_col(pinfo->fd, COL_PROTOCOL))
231                         col_set_str(pinfo->fd, COL_PROTOCOL, "Vines IPC");
232                 if (check_col(pinfo->fd, COL_INFO))
233                         col_add_fstr(pinfo->fd, COL_INFO, "IPC (%02x)", viph.vip_proto);
234                 break;
235         case VIP_PROTO_SPP:      
236                 if (check_col(pinfo->fd, COL_PROTOCOL))
237                         col_set_str(pinfo->fd, COL_PROTOCOL, "Vines SPP");
238                 if (check_col(pinfo->fd, COL_INFO))
239                         col_add_fstr(pinfo->fd, COL_INFO, "SPP (%02x)", viph.vip_proto);
240                 break;
241         case VIP_PROTO_ARP:
242                 if (check_col(pinfo->fd, COL_PROTOCOL))
243                         col_set_str(pinfo->fd, COL_PROTOCOL, "Vines ARP");
244                 if (check_col(pinfo->fd, COL_INFO))
245                         col_add_fstr(pinfo->fd, COL_INFO, "ARP (%02x)", viph.vip_proto);
246                 break;
247         case VIP_PROTO_RTP:
248                 if (check_col(pinfo->fd, COL_PROTOCOL))
249                         col_set_str(pinfo->fd, COL_PROTOCOL, "Vines RTP");
250                 if (check_col(pinfo->fd, COL_INFO))
251                         col_add_fstr(pinfo->fd, COL_INFO, "RTP (%02x)", viph.vip_proto);
252                 break;
253         case VIP_PROTO_ICP:
254                 if (check_col(pinfo->fd, COL_PROTOCOL))
255                         col_set_str(pinfo->fd, COL_PROTOCOL, "Vines ICP");
256                 if (check_col(pinfo->fd, COL_INFO))
257                         col_add_fstr(pinfo->fd, COL_INFO, "ICP (%02x)", viph.vip_proto);
258                 break;
259         default:
260                 if (check_col(pinfo->fd, COL_PROTOCOL))
261                         col_set_str(pinfo->fd, COL_PROTOCOL, "Vines IP");
262                 if (check_col(pinfo->fd, COL_INFO))
263                         col_add_fstr(pinfo->fd, COL_INFO, "Unknown VIP protocol (%02x)", 
264                                      viph.vip_proto);
265         }
266
267         src_addr = tvb_get_ptr(tvb, offset+12, VINES_ADDR_LEN);
268         SET_ADDRESS(&pinfo->net_src, AT_VINES, VINES_ADDR_LEN, src_addr);
269         SET_ADDRESS(&pinfo->src, AT_VINES, VINES_ADDR_LEN, src_addr);
270         dst_addr = tvb_get_ptr(tvb, offset+6, VINES_ADDR_LEN);
271         SET_ADDRESS(&pinfo->net_dst, AT_VINES, VINES_ADDR_LEN,dst_addr);
272         SET_ADDRESS(&pinfo->dst, AT_VINES, VINES_ADDR_LEN, dst_addr);
273
274         /* helpers to decode flags */
275         /* FIXME: Not used yet */
276         if ((viph.vip_dnet == 0xffffffff) && (viph.vip_dsub == 0xffff)) {
277                 is_broadcast = 1;
278         }
279         hops = viph.vip_tctl & 0xf; 
280  
281         /*
282         viph.ip_tos = IPTOS_TOS(viph.ip_tos);
283         switch (viph.ip_tos) {
284         case IPTOS_NONE:
285                 strcpy(tos_str, "None");
286                 break;
287         case IPTOS_LOWDELAY:
288                 strcpy(tos_str, "Minimize delay");
289                 break;
290         case IPTOS_THROUGHPUT:
291                 strcpy(tos_str, "Maximize throughput");
292                 break;
293         case IPTOS_RELIABILITY:
294                 strcpy(tos_str, "Maximize reliability");
295                 break;
296         case IPTOS_LOWCOST:
297                 strcpy(tos_str, "Minimize cost");
298                 break;
299         default:
300                 strcpy(tos_str, "Unknon.  Malformed?");
301                 break;
302         }
303         */
304
305         if (tree) {
306                 ti = proto_tree_add_protocol_format(tree, proto_vines, tvb, 
307                                                     offset, (viph.vip_pktlen),
308                                                     "Vines IP");
309                 vip_tree = proto_item_add_subtree(ti, ett_vines);
310                 proto_tree_add_text(vip_tree, tvb, offset,      2, 
311                                     "Packet checksum: 0x%04x", 
312                                     viph.vip_chksum);
313                 proto_tree_add_text(vip_tree, tvb, offset +  2, 2, 
314                                     "Packet length: 0x%04x (%d)", 
315                                     viph.vip_pktlen, viph.vip_pktlen); 
316                 proto_tree_add_text(vip_tree, tvb, offset +  4, 1, 
317                                     "Transport control: 0x%02x",
318                                     viph.vip_tctl);
319                 proto_tree_add_uint(vip_tree, hf_vines_protocol, tvb, 
320                                     offset +  5, 1, 
321                                     viph.vip_proto);
322                 proto_tree_add_text(vip_tree, tvb, offset +  6, 
323                                     VINES_ADDR_LEN, 
324                                     "Destination: %s",
325                                     vines_addr_to_str(dst_addr));
326                 proto_tree_add_text(vip_tree, tvb, offset +  12, 
327                                     VINES_ADDR_LEN, 
328                                     "Source: %s",
329                                     vines_addr_to_str(src_addr));
330
331         }
332
333         offset += 18;
334         switch (viph.vip_proto) {
335         case VIP_PROTO_SPP:
336                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
337                 dissect_vines_spp(next_tvb, pinfo, tree);
338                 break;
339         default:
340                 dissect_data(tvb, offset, pinfo, tree);
341                 break;
342         }
343 }
344
345 void
346 proto_register_vines(void)
347 {
348         static gint *ett[] = {
349                 &ett_vines,
350         };
351
352         static hf_register_info hf[] = {
353           { &hf_vines_protocol,
354             { "Protocol",                       "vines.protocol",
355               FT_UINT8,         BASE_HEX,       NULL,   0x0,
356               "Vines protocol" }}
357         };
358
359         proto_vines = proto_register_protocol("Banyan Vines", "Vines", "vines");
360         proto_register_field_array(proto_vines, hf, array_length(hf));
361         proto_register_subtree_array(ett, array_length(ett));
362 }
363
364 void
365 proto_reg_handoff_vines(void)
366 {
367         dissector_add("ethertype", ETHERTYPE_VINES, dissect_vines, proto_vines);
368         dissector_add("ppp.protocol", PPP_VINES, dissect_vines, proto_vines);
369 }
370
371 static void
372 dissect_vines_spp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
373 {
374         int          offset = 0;
375         e_vspp       viph;
376         proto_tree *vspp_tree;
377         proto_item *ti;
378
379         CHECK_DISPLAY_AS_DATA(proto_vines_spp, tvb, pinfo, tree);
380
381         pinfo->current_proto = "Vines SPP";
382
383         if (check_col(pinfo->fd, COL_PROTOCOL))
384                 col_set_str(pinfo->fd, COL_PROTOCOL, "VSPP");
385         if (check_col(pinfo->fd, COL_INFO))
386                 col_clear(pinfo->fd, COL_INFO);
387
388         /* To do: check for runts, errs, etc. */
389
390         /* Avoids alignment problems on many architectures. */
391         tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vspp));
392
393         viph.vspp_sport = ntohs(viph.vspp_sport);
394         viph.vspp_dport = ntohs(viph.vspp_dport);
395         viph.vspp_lclid = ntohs(viph.vspp_lclid);
396         viph.vspp_rmtid = ntohs(viph.vspp_rmtid);
397
398         switch (viph.vspp_pkttype) {
399         case VSPP_PKTTYPE_DATA:      
400                 if (check_col(pinfo->fd, COL_PROTOCOL))
401                         col_set_str(pinfo->fd, COL_PROTOCOL, "VSPP Data");
402                 break;
403         case VSPP_PKTTYPE_DISC:      
404                 if (check_col(pinfo->fd, COL_PROTOCOL))
405                         col_set_str(pinfo->fd, COL_PROTOCOL, "VSPP Disconnect");
406                 break;
407         case VSPP_PKTTYPE_PROBE:      
408                 if (check_col(pinfo->fd, COL_PROTOCOL))
409                         col_set_str(pinfo->fd, COL_PROTOCOL, "VSPP Probe");
410                 break;
411         case VSPP_PKTTYPE_ACK:
412                 if (check_col(pinfo->fd, COL_PROTOCOL))
413                         col_set_str(pinfo->fd, COL_PROTOCOL, "VSPP Ack");
414                 break;
415         default:
416                 if (check_col(pinfo->fd, COL_PROTOCOL))
417                         col_set_str(pinfo->fd, COL_PROTOCOL, "VSPP Unknown");
418         }
419
420         if (check_col(pinfo->fd, COL_INFO))
421                 col_add_fstr(pinfo->fd, COL_INFO, 
422                              "NS=%04x NR=%04x Window=%04x RID=%04x LID=%04x D=%04x S=%04x", 
423                              viph.vspp_seqno, viph.vspp_ack, viph.vspp_win, 
424                              viph.vspp_rmtid, viph.vspp_lclid, viph.vspp_dport,
425                              viph.vspp_sport);
426
427         /*
428         iph.ip_tos = IPTOS_TOS(iph.ip_tos);
429         switch (iph.ip_tos) {
430         case IPTOS_NONE:
431                 strcpy(tos_str, "None");
432                 break;
433         case IPTOS_LOWDELAY:
434                 strcpy(tos_str, "Minimize delay");
435                 break;
436         case IPTOS_THROUGHPUT:
437                 strcpy(tos_str, "Maximize throughput");
438                 break;
439         case IPTOS_RELIABILITY:
440                 strcpy(tos_str, "Maximize reliability");
441                 break;
442         case IPTOS_LOWCOST:
443                 strcpy(tos_str, "Minimize cost");
444                 break;
445         default:
446                 strcpy(tos_str, "Unknon.  Malformed?");
447                 break;
448         }
449         */ 
450
451         if (tree) {
452                 ti = proto_tree_add_item(tree, proto_vines_spp, tvb, offset,
453                     sizeof(viph), FALSE);
454                 vspp_tree = proto_item_add_subtree(ti, ett_vines_spp);
455                 proto_tree_add_text(vspp_tree, tvb, offset,      2, 
456                                     "Source port: 0x%04x", viph.vspp_sport);
457                 proto_tree_add_text(vspp_tree, tvb, offset + 2,  2, 
458                                     "Destination port: 0x%04x",
459                                     viph.vspp_dport); 
460                 proto_tree_add_text(vspp_tree, tvb, offset + 4,  1, 
461                                     "Packet type: 0x%02x", viph.vspp_pkttype);
462                 proto_tree_add_text(vspp_tree, tvb, offset + 5,  1, 
463                                     "Control: 0x%02x", viph.vspp_control);
464                 proto_tree_add_text(vspp_tree, tvb, offset + 6,  2, 
465                                     "Local Connection ID: 0x%04x",
466                                     viph.vspp_lclid);
467                 proto_tree_add_text(vspp_tree, tvb, offset + 8,  2,
468                                     "Remote Connection ID: 0x%04x", 
469                                     viph.vspp_rmtid);
470                 proto_tree_add_text(vspp_tree, tvb, offset + 10, 2,
471                                     "Sequence number: 0x%04x", 
472                                     viph.vspp_seqno);
473                 proto_tree_add_text(vspp_tree, tvb, offset + 12, 2,
474                                     "Ack number: 0x%04x", viph.vspp_ack);
475                 proto_tree_add_text(vspp_tree, tvb, offset + 14, 2,
476                                     "Window: 0x%04x", viph.vspp_win);
477         }
478         offset += 16; /* sizeof SPP */
479         dissect_data(tvb, offset, pinfo, tree);
480 }
481
482 void
483 proto_register_vines_spp(void)
484 {
485         static gint *ett[] = {
486                 &ett_vines_spp,
487         };
488
489         proto_vines_spp = proto_register_protocol("Banyan Vines SPP",
490             "Vines SPP", "vines_spp");
491         proto_register_subtree_array(ett, array_length(ett));
492 }