add tethereal_static
[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.20 2000/11/19 08:54:10 guy 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 static int proto_vines = -1;
50 static int hf_vines_protocol = -1;
51
52 static gint ett_vines = -1;
53 static gint ett_vines_frp = -1;
54 static gint ett_vines_spp = -1;
55
56 #if 0
57 static void dissect_vines_arp(const u_char *, int, frame_data *, proto_tree *);
58 static void dissect_vines_icp(const u_char *, int, frame_data *, proto_tree *);
59 static void dissect_vines_ipc(const u_char *, int, frame_data *, proto_tree *);
60 static void dissect_vines_rtp(const u_char *, int, frame_data *, proto_tree *);
61 #endif
62 static void dissect_vines_spp(const u_char *, int, frame_data *, proto_tree *);
63 static void dissect_vines(const u_char *, int, frame_data *, proto_tree *);
64
65 void
66 capture_vines(const u_char *pd, int offset, packet_counts *ld)
67 {
68   ld->vines++;
69 }
70
71 /* AFAIK Vines FRP (Fragmentation Protocol) is used on all media except Ethernet
72  * and TR (and probably FDDI) - Fragmentation on these media types is not possible
73  * FIXME: Do we need to use this header with PPP too?
74  */
75 void
76 dissect_vines_frp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
77   guint8   vines_frp_ctrl, vines_frp_seqno; 
78   proto_tree *vines_frp_tree;
79   proto_item *ti;
80   gchar frp_flags_str[32];
81
82   /* To do: Check for {cap len,pkt len} < struct len */
83
84   vines_frp_ctrl = pd[offset];
85   vines_frp_seqno = pd[offset+1];
86   
87   if (check_col(fd, COL_PROTOCOL))
88     col_set_str(fd, COL_PROTOCOL, "Vines FRP");
89   /*
90    * 1: first fragment of vines packet
91    * 2: last fragment of vines packet
92    * 4 ... 80: unused
93    */
94   switch (vines_frp_ctrl) {
95   case 0:
96     strcpy(frp_flags_str, "middle");
97     break;
98   case 1:
99     strcpy(frp_flags_str, "first");
100     break;
101   case 2:
102     strcpy(frp_flags_str, "last");
103     break;
104   case 3:
105     strcpy(frp_flags_str, "only");
106     break;
107   default:
108     strcpy(frp_flags_str, "please report: unknown");
109     break;
110   }
111   
112   if (tree) {
113     ti = proto_tree_add_text(tree, NullTVB, offset, 2, 
114                              "Vines Fragmentation Protocol");
115     vines_frp_tree = proto_item_add_subtree(ti, ett_vines_frp);
116     proto_tree_add_text(vines_frp_tree, NullTVB, offset,     1, 
117                         "Control Flags: 0x%02x = %s fragment", 
118                         vines_frp_ctrl, frp_flags_str);
119     proto_tree_add_text(vines_frp_tree, NullTVB, offset + 1, 1, 
120                         "Sequence Number: 0x%02x", vines_frp_seqno);
121   }
122
123   /* Skip over header */
124   offset += 2;
125
126   /* Decode the "real" Vines now */
127   dissect_vines(pd, offset, fd, tree);
128 }
129
130 gchar *
131 vines_addr_to_str(const guint8 *addrp)
132 {
133   static gchar  str[3][214];
134   static gchar  *cur;
135
136   if (cur == &str[0][0]) {
137     cur = &str[1][0];
138   } else if (cur == &str[1][0]) {
139     cur = &str[2][0];
140   } else {
141     cur = &str[0][0];
142   }
143
144   sprintf(cur, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
145   return cur;
146 }
147
148 static void
149 dissect_vines(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
150         e_vip       viph;
151         proto_tree *vip_tree;
152         proto_item *ti;
153 /*      gchar      tos_str[32]; */
154         int  is_broadcast = 0;
155         int  hops = 0;
156
157         OLD_CHECK_DISPLAY_AS_DATA(proto_vines, pd, offset, fd, tree);
158
159         /* To do: check for runts, errs, etc. */
160
161         /* Avoids alignment problems on many architectures. */
162         memcpy(&viph, &pd[offset], sizeof(e_vip));
163
164         viph.vip_chksum = pntohs(&pd[offset]);
165         viph.vip_pktlen = pntohs(&pd[offset+2]);
166         viph.vip_dnet = pntohl(&pd[offset+6]);
167         viph.vip_dsub = pntohs(&pd[offset+10]);
168         viph.vip_snet = pntohl(&pd[offset+12]);
169         viph.vip_ssub = pntohs(&pd[offset+16]);
170
171         switch (viph.vip_proto) {
172         case VIP_PROTO_IPC:
173                 if (check_col(fd, COL_PROTOCOL))
174                         col_set_str(fd, COL_PROTOCOL, "Vines IPC");
175                 if (check_col(fd, COL_INFO))
176                         col_add_fstr(fd, COL_INFO, "IPC (%02x)", viph.vip_proto);
177                 break;
178         case VIP_PROTO_SPP:      
179                 if (check_col(fd, COL_PROTOCOL))
180                         col_set_str(fd, COL_PROTOCOL, "Vines SPP");
181                 if (check_col(fd, COL_INFO))
182                         col_add_fstr(fd, COL_INFO, "SPP (%02x)", viph.vip_proto);
183                 break;
184         case VIP_PROTO_ARP:
185                 if (check_col(fd, COL_PROTOCOL))
186                         col_set_str(fd, COL_PROTOCOL, "Vines ARP");
187                 if (check_col(fd, COL_INFO))
188                         col_add_fstr(fd, COL_INFO, "ARP (%02x)", viph.vip_proto);
189                 break;
190         case VIP_PROTO_RTP:
191                 if (check_col(fd, COL_PROTOCOL))
192                         col_set_str(fd, COL_PROTOCOL, "Vines RTP");
193                 if (check_col(fd, COL_INFO))
194                         col_add_fstr(fd, COL_INFO, "RTP (%02x)", viph.vip_proto);
195                 break;
196         case VIP_PROTO_ICP:
197                 if (check_col(fd, COL_PROTOCOL))
198                         col_set_str(fd, COL_PROTOCOL, "Vines ICP");
199                 if (check_col(fd, COL_INFO))
200                         col_add_fstr(fd, COL_INFO, "ICP (%02x)", viph.vip_proto);
201                 break;
202         default:
203                 if (check_col(fd, COL_PROTOCOL))
204                         col_set_str(fd, COL_PROTOCOL, "Vines IP");
205                 if (check_col(fd, COL_INFO))
206                         col_add_fstr(fd, COL_INFO, "Unknown VIP protocol (%02x)", 
207                                      viph.vip_proto);
208         }
209
210         SET_ADDRESS(&pi.net_src, AT_VINES, VINES_ADDR_LEN, &pd[offset+12]);
211         SET_ADDRESS(&pi.src, AT_VINES, VINES_ADDR_LEN, &pd[offset+12]);
212         SET_ADDRESS(&pi.net_dst, AT_VINES, VINES_ADDR_LEN, &pd[offset+6]);
213         SET_ADDRESS(&pi.dst, AT_VINES, VINES_ADDR_LEN, &pd[offset+6]);
214
215         /* helpers to decode flags */
216         /* FIXME: Not used yet */
217         if ((viph.vip_dnet == 0xffffffff) && (viph.vip_dsub == 0xffff)) {
218                 is_broadcast = 1;
219         }
220         hops = viph.vip_tctl & 0xf; 
221  
222         /*
223         viph.ip_tos = IPTOS_TOS(viph.ip_tos);
224         switch (viph.ip_tos) {
225         case IPTOS_NONE:
226                 strcpy(tos_str, "None");
227                 break;
228         case IPTOS_LOWDELAY:
229                 strcpy(tos_str, "Minimize delay");
230                 break;
231         case IPTOS_THROUGHPUT:
232                 strcpy(tos_str, "Maximize throughput");
233                 break;
234         case IPTOS_RELIABILITY:
235                 strcpy(tos_str, "Maximize reliability");
236                 break;
237         case IPTOS_LOWCOST:
238                 strcpy(tos_str, "Minimize cost");
239                 break;
240         default:
241                 strcpy(tos_str, "Unknon.  Malformed?");
242                 break;
243         }
244         */
245
246         if (tree) {
247                 ti = proto_tree_add_protocol_format(tree, proto_vines, NullTVB, 
248                                                     offset, (viph.vip_pktlen),
249                                                     "Vines IP");
250                 vip_tree = proto_item_add_subtree(ti, ett_vines);
251                 proto_tree_add_text(vip_tree, NullTVB, offset,      2, 
252                                     "Packet checksum: 0x%04x", 
253                                     viph.vip_chksum);
254                 proto_tree_add_text(vip_tree, NullTVB, offset +  2, 2, 
255                                     "Packet length: 0x%04x (%d)", 
256                                     viph.vip_pktlen, viph.vip_pktlen); 
257                 proto_tree_add_text(vip_tree, NullTVB, offset +  4, 1, 
258                                     "Transport control: 0x%02x",
259                                     viph.vip_tctl);
260                 proto_tree_add_uint(vip_tree, hf_vines_protocol, NullTVB, 
261                                     offset +  5, 1, 
262                                     viph.vip_proto);
263                 proto_tree_add_text(vip_tree, NullTVB, offset +  6, 
264                                     VINES_ADDR_LEN, 
265                                     "Destination: %s",
266                                     vines_addr_to_str(&pd[offset + 6]));
267                 proto_tree_add_text(vip_tree, NullTVB, offset +  12, 
268                                     VINES_ADDR_LEN, 
269                                     "Source: %s",
270                                     vines_addr_to_str(&pd[offset + 12]));
271
272         }
273
274         offset += 18;
275         switch (viph.vip_proto) {
276         case VIP_PROTO_SPP:
277                 dissect_vines_spp(pd, offset, fd, tree);
278                 break;
279         default:
280                 old_dissect_data(pd, offset, fd, tree);
281                 break;
282         }
283 }
284
285 void dissect_vines_spp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
286
287         e_vspp       viph;
288         proto_tree *vspp_tree;
289         proto_item *ti;
290
291         /* To do: check for runts, errs, etc. */
292
293         /* Avoids alignment problems on many architectures. */
294         memcpy(&viph, &pd[offset], sizeof(e_vspp));
295
296         viph.vspp_sport = ntohs(viph.vspp_sport);
297         viph.vspp_dport = ntohs(viph.vspp_dport);
298         viph.vspp_lclid = ntohs(viph.vspp_lclid);
299         viph.vspp_rmtid = ntohs(viph.vspp_rmtid);
300
301         switch (viph.vspp_pkttype) {
302         case VSPP_PKTTYPE_DATA:      
303                 if (check_col(fd, COL_PROTOCOL))
304                         col_set_str(fd, COL_PROTOCOL, "VSPP Data");
305                 break;
306         case VSPP_PKTTYPE_DISC:      
307                 if (check_col(fd, COL_PROTOCOL))
308                         col_set_str(fd, COL_PROTOCOL, "VSPP Disconnect");
309                 break;
310         case VSPP_PKTTYPE_PROBE:      
311                 if (check_col(fd, COL_PROTOCOL))
312                         col_set_str(fd, COL_PROTOCOL, "VSPP Probe");
313                 break;
314         case VSPP_PKTTYPE_ACK:
315                 if (check_col(fd, COL_PROTOCOL))
316                         col_set_str(fd, COL_PROTOCOL, "VSPP Ack");
317                 break;
318         default:
319                 if (check_col(fd, COL_PROTOCOL))
320                         col_set_str(fd, COL_PROTOCOL, "VSPP Unknown");
321         }
322
323         if (check_col(fd, COL_INFO))
324                 col_add_fstr(fd, COL_INFO, 
325                              "NS=%04x NR=%04x Window=%04x RID=%04x LID=%04x D=%04x S=%04x", 
326                              viph.vspp_seqno, viph.vspp_ack, viph.vspp_win, 
327                              viph.vspp_rmtid, viph.vspp_lclid, viph.vspp_dport,
328                              viph.vspp_sport);
329
330         /*
331         iph.ip_tos = IPTOS_TOS(iph.ip_tos);
332         switch (iph.ip_tos) {
333         case IPTOS_NONE:
334                 strcpy(tos_str, "None");
335                 break;
336         case IPTOS_LOWDELAY:
337                 strcpy(tos_str, "Minimize delay");
338                 break;
339         case IPTOS_THROUGHPUT:
340                 strcpy(tos_str, "Maximize throughput");
341                 break;
342         case IPTOS_RELIABILITY:
343                 strcpy(tos_str, "Maximize reliability");
344                 break;
345         case IPTOS_LOWCOST:
346                 strcpy(tos_str, "Minimize cost");
347                 break;
348         default:
349                 strcpy(tos_str, "Unknon.  Malformed?");
350                 break;
351         }
352         */ 
353
354         if (tree) {
355                 ti = proto_tree_add_text(tree, NullTVB, offset, sizeof(viph), "Vines SPP");
356                 vspp_tree = proto_item_add_subtree(ti, ett_vines_spp);
357                 proto_tree_add_text(vspp_tree, NullTVB, offset,      2, 
358                                     "Source port: 0x%04x", viph.vspp_sport);
359                 proto_tree_add_text(vspp_tree, NullTVB, offset+2,    2, 
360                                     "Destination port: 0x%04x",
361                                     viph.vspp_dport); 
362                 proto_tree_add_text(vspp_tree, NullTVB, offset+4,    1, 
363                                     "Packet type: 0x%02x", viph.vspp_pkttype);
364                 proto_tree_add_text(vspp_tree, NullTVB, offset+5,    1, 
365                                     "Control: 0x%02x", viph.vspp_control);
366                 proto_tree_add_text(vspp_tree, NullTVB, offset+6,    2, 
367                                     "Local Connection ID: 0x%04x",
368                                     viph.vspp_lclid);
369                 proto_tree_add_text(vspp_tree, NullTVB, offset+8,    2,
370                                     "Remote Connection ID: 0x%04x", 
371                                     viph.vspp_rmtid);
372                 proto_tree_add_text(vspp_tree, NullTVB, offset+10,   2,
373                                     "Sequence number: 0x%04x", 
374                                     viph.vspp_seqno);
375                 proto_tree_add_text(vspp_tree, NullTVB, offset+12,   2,
376                                     "Ack number: 0x%04x", viph.vspp_ack);
377                 proto_tree_add_text(vspp_tree, NullTVB, offset+14,   2,
378                                     "Window: 0x%04x", viph.vspp_win);
379         }
380         offset += 16; /* sizeof SPP */
381         old_dissect_data(pd, offset, fd, tree);
382 }
383
384 void
385 proto_register_vines(void)
386 {
387         static gint *ett[] = {
388                 &ett_vines,
389                 &ett_vines_frp,
390                 &ett_vines_spp,
391         };
392
393         static hf_register_info hf[] = {
394           { &hf_vines_protocol,
395             { "Protocol",                       "vines.protocol",
396               FT_UINT8,         BASE_HEX,       NULL,   0x0,
397               "Vines protocol" }}
398         };
399
400         proto_vines = proto_register_protocol("Banyan Vines", "vines");
401         proto_register_field_array(proto_vines, hf, array_length(hf));
402         proto_register_subtree_array(ett, array_length(ett));
403 }
404
405 void
406 proto_reg_handoff_vines(void)
407 {
408         old_dissector_add("ethertype", ETHERTYPE_VINES, dissect_vines);
409         old_dissector_add("ppp.protocol", PPP_VINES, dissect_vines);
410         old_dissector_add("ip.proto", IP_PROTO_VINES, dissect_vines_frp);
411 }