Change from Ed Meaney - write capture files in binary, rather than ASCII
[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.12 2000/01/23 08:55:37 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 #include "config.h"
30
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
33 #endif
34
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
37 #endif
38
39 #include <glib.h>
40 #include "packet.h"
41 #include "packet-vines.h"
42
43 static gint ett_vines = -1;
44 static gint ett_vines_frp = -1;
45 static gint ett_vines_spp = -1;
46
47 void
48 capture_vines(const u_char *pd, int offset, packet_counts *ld)
49 {
50   ld->vines++;
51 }
52
53
54
55 /* AFAIK Vines FRP (Fragmentation Protocol) is used on all media except Ethernet
56  * and TR (and probably FDDI) - Fragmentation on these media types is not possible
57  * FIXME: Do we need to use this header with PPP too?
58  */
59 void
60 dissect_vines_frp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
61   guint8   vines_frp_ctrl, vines_frp_seqno; 
62   proto_tree *vines_frp_tree;
63   proto_item *ti;
64   gchar frp_flags_str[32];
65
66   /* To do: Check for {cap len,pkt len} < struct len */
67   /* Avoids alignment problems on many architectures. */
68   vines_frp_ctrl = pd[offset];
69   vines_frp_seqno = pd[offset+1];
70   
71   if (check_col(fd, COL_PROTOCOL))
72     col_add_str(fd, COL_PROTOCOL, "Vines FRP");
73   /*
74    * 1: first fragment of vines packet
75    * 2: last fragment of vines packet
76    * 4 ... 80: unused
77    */
78   switch (vines_frp_ctrl) {
79   case 0:
80     strcpy(frp_flags_str, "middle");
81     break;
82   case 1:
83     strcpy(frp_flags_str, "first");
84     break;
85   case 2:
86     strcpy(frp_flags_str, "last");
87     break;
88   case 3:
89     strcpy(frp_flags_str, "only");
90     break;
91   default:
92     strcpy(frp_flags_str, "please report: unknown");
93     break;
94   }
95   
96   if (tree) {
97     ti = proto_tree_add_text(tree, offset, 2, "Vines Fragmentation Protocol");
98     vines_frp_tree = proto_item_add_subtree(ti, ett_vines_frp);
99     proto_tree_add_text(vines_frp_tree, offset,     1, "Control Flags: 0x%02x = %s fragment", vines_frp_ctrl, frp_flags_str);
100     proto_tree_add_text(vines_frp_tree, offset + 1, 1, "Sequence Number: 0x%02x", vines_frp_seqno);
101   }
102
103   /* Skip over header */
104   offset += 2;
105
106   /* Decode the "real" Vines now */
107   dissect_vines(pd, offset, fd, tree);
108 }
109
110 gchar *
111 vines_addr_to_str(const guint8 *addrp)
112 {
113   static gchar  str[3][214];
114   static gchar  *cur;
115
116   if (cur == &str[0][0]) {
117     cur = &str[1][0];
118   } else if (cur == &str[1][0]) {
119     cur = &str[2][0];
120   } else {
121     cur = &str[0][0];
122   }
123
124   sprintf(cur, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
125   return cur;
126 }
127
128 void
129 dissect_vines(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
130         {
131         e_vip       viph;
132         proto_tree *vip_tree;
133         proto_item *ti;
134 /*      gchar      tos_str[32]; */
135         int  is_broadcast = 0;
136         int  hops = 0;
137
138   /* To do: check for runts, errs, etc. */
139   /* Avoids alignment problems on many architectures. */
140         memcpy(&viph, &pd[offset], sizeof(e_vip));
141
142         viph.vip_chksum = pntohs(&pd[offset]);
143         viph.vip_pktlen = pntohs(&pd[offset+2]);
144         viph.vip_dnet = pntohl(&pd[offset+6]);
145         viph.vip_dsub = pntohs(&pd[offset+10]);
146         viph.vip_snet = pntohl(&pd[offset+12]);
147         viph.vip_ssub = pntohs(&pd[offset+16]);
148
149         switch (viph.vip_proto) {
150         case VIP_PROTO_IPC:
151                 if (check_col(fd, COL_PROTOCOL))
152                         col_add_str(fd, COL_PROTOCOL, "Vines IPC");
153                 if (check_col(fd, COL_INFO))
154                         col_add_fstr(fd, COL_INFO, "IPC (%02x)", viph.vip_proto);
155                 break;
156         case VIP_PROTO_SPP:      
157                 if (check_col(fd, COL_PROTOCOL))
158                         col_add_str(fd, COL_PROTOCOL, "Vines SPP");
159                 if (check_col(fd, COL_INFO))
160                         col_add_fstr(fd, COL_INFO, "SPP (%02x)", viph.vip_proto);
161                 break;
162         case VIP_PROTO_ARP:
163                 if (check_col(fd, COL_PROTOCOL))
164                         col_add_str(fd, COL_PROTOCOL, "Vines ARP");
165                 if (check_col(fd, COL_INFO))
166                         col_add_fstr(fd, COL_INFO, "ARP (%02x)", viph.vip_proto);
167                 break;
168         case VIP_PROTO_RTP:
169                 if (check_col(fd, COL_PROTOCOL))
170                         col_add_str(fd, COL_PROTOCOL, "Vines RTP");
171                 if (check_col(fd, COL_INFO))
172                         col_add_fstr(fd, COL_INFO, "RTP (%02x)", viph.vip_proto);
173                 break;
174         case VIP_PROTO_ICP:
175                 if (check_col(fd, COL_PROTOCOL))
176                         col_add_str(fd, COL_PROTOCOL, "Vines ICP");
177                 if (check_col(fd, COL_INFO))
178                         col_add_fstr(fd, COL_INFO, "ICP (%02x)", viph.vip_proto);
179                 break;
180         default:
181                 if (check_col(fd, COL_PROTOCOL))
182                         col_add_str(fd, COL_PROTOCOL, "Vines IP");
183                 if (check_col(fd, COL_INFO))
184                         col_add_fstr(fd, COL_INFO, "Unknown VIP protocol (%02x)", viph.vip_proto);
185         }
186
187         SET_ADDRESS(&pi.net_src, AT_VINES, 6, &pd[offset+12]);
188         SET_ADDRESS(&pi.src, AT_VINES, 6, &pd[offset+12]);
189         SET_ADDRESS(&pi.net_dst, AT_VINES, 6, &pd[offset+6]);
190         SET_ADDRESS(&pi.dst, AT_VINES, 6, &pd[offset+6]);
191
192         /* helpers to decode flags */
193         /* FIXME: Not used yet */
194         if ((viph.vip_dnet == 0xffffffff) && (viph.vip_dsub == 0xffff)) {
195                 is_broadcast = 1;
196         }
197         hops = viph.vip_tctl & 0xf; 
198  
199   /*
200         viph.ip_tos = IPTOS_TOS(viph.ip_tos);
201         switch (viph.ip_tos) 
202                 {
203         case IPTOS_NONE:
204                 strcpy(tos_str, "None");
205                 break;
206         case IPTOS_LOWDELAY:
207                 strcpy(tos_str, "Minimize delay");
208                 break;
209         case IPTOS_THROUGHPUT:
210                 strcpy(tos_str, "Maximize throughput");
211                 break;
212         case IPTOS_RELIABILITY:
213                 strcpy(tos_str, "Maximize reliability");
214                 break;
215         case IPTOS_LOWCOST:
216                 strcpy(tos_str, "Minimize cost");
217                 break;
218         default:
219                 strcpy(tos_str, "Unknon.  Malformed?");
220                 break;
221                 }
222   */
223         if (tree) 
224                 {
225         ti = proto_tree_add_text(tree, offset, (viph.vip_pktlen), "Vines IP");
226         vip_tree = proto_item_add_subtree(ti, ett_vines);
227         proto_tree_add_text(vip_tree, offset,      2, "Packet checksum: 0x%04x", viph.vip_chksum);
228         proto_tree_add_text(vip_tree, offset +  2, 2, "Packet length: 0x%04x (%d)", viph.vip_pktlen, viph.vip_pktlen); 
229         proto_tree_add_text(vip_tree, offset +  4, 1, "Transport control: 0x%02x",
230                 viph.vip_tctl);
231         proto_tree_add_text(vip_tree, offset +  5, 1, "Protocol: 0x%02x", viph.vip_proto);
232                 }
233
234
235         offset += 18;
236         switch (viph.vip_proto) 
237                 {
238         case VIP_PROTO_SPP:
239                 dissect_vines_spp(pd, offset, fd, tree);
240                 break;
241         default:
242                 dissect_data(pd, offset, fd, tree);
243                 break;
244                 }
245         }
246 #define VINES_VSPP_DATA 1
247 #define VINES_VSPP_ACK 5
248 void dissect_vines_spp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
249         {
250         e_vspp       viph;
251         proto_tree *vspp_tree;
252         proto_item *ti;
253
254   /* To do: check for runts, errs, etc. */
255   /* Avoids alignment problems on many architectures. */
256         memcpy(&viph, &pd[offset], sizeof(e_vspp));
257
258         viph.vspp_sport = ntohs(viph.vspp_sport);
259         viph.vspp_dport = ntohs(viph.vspp_dport);
260         viph.vspp_lclid = ntohs(viph.vspp_lclid);
261         viph.vspp_rmtid = ntohs(viph.vspp_rmtid);
262
263     switch (viph.vspp_pkttype) 
264         {
265         case VSPP_PKTTYPE_DATA:      
266                                         if (check_col(fd, COL_PROTOCOL))
267                         col_add_str(fd, COL_PROTOCOL, "VSPP Data");
268                 break;
269         case VSPP_PKTTYPE_DISC:      
270                                         if (check_col(fd, COL_PROTOCOL))
271                         col_add_str(fd, COL_PROTOCOL, "VSPP Disconnect");
272                 break;
273         case VSPP_PKTTYPE_PROBE:      
274                                         if (check_col(fd, COL_PROTOCOL))
275                         col_add_str(fd, COL_PROTOCOL, "VSPP Probe");
276                 break;
277         case VSPP_PKTTYPE_ACK:
278                                         if (check_col(fd, COL_PROTOCOL))
279                         col_add_str(fd, COL_PROTOCOL, "VSPP Ack");
280                 break;
281         default:
282                                         if (check_col(fd, COL_PROTOCOL))
283                         col_add_str(fd, COL_PROTOCOL, "VSPP Unknown");
284         }
285         if (check_col(fd, COL_INFO))
286                 col_add_fstr(fd, COL_INFO, "NS=%04x NR=%04x Window=%04x RID=%04x LID=%04x D=%04x S=%04x", 
287                         viph.vspp_seqno, viph.vspp_ack, viph.vspp_win, viph.vspp_rmtid,
288                         viph.vspp_lclid, viph.vspp_dport, viph.vspp_sport);
289   /*
290         iph.ip_tos = IPTOS_TOS(iph.ip_tos);
291         switch (iph.ip_tos)
292                 {
293         case IPTOS_NONE:
294                 strcpy(tos_str, "None");
295                 break;
296         case IPTOS_LOWDELAY:
297                 strcpy(tos_str, "Minimize delay");
298                 break;
299         case IPTOS_THROUGHPUT:
300                 strcpy(tos_str, "Maximize throughput");
301                 break;
302         case IPTOS_RELIABILITY:
303                 strcpy(tos_str, "Maximize reliability");
304                 break;
305         case IPTOS_LOWCOST:
306                 strcpy(tos_str, "Minimize cost");
307                 break;
308         default:
309                 strcpy(tos_str, "Unknon.  Malformed?");
310                 break;
311                 }
312 */ 
313         if (tree) 
314                 {
315         ti = proto_tree_add_text(tree, offset, sizeof(viph), "Vines SPP");
316         vspp_tree = proto_item_add_subtree(ti, ett_vines_spp);
317         proto_tree_add_text(vspp_tree, offset,      2, "Source port: 0x%04x", viph.vspp_sport);
318         proto_tree_add_text(vspp_tree, offset+2,    2, "Destination port: 0x%04x", viph.vspp_dport); 
319         proto_tree_add_text(vspp_tree, offset+4,    1, "Packet type: 0x%02x", viph.vspp_pkttype);
320         proto_tree_add_text(vspp_tree, offset+5,    1, "Control: 0x%02x", viph.vspp_control);
321         proto_tree_add_text(vspp_tree, offset+6,    2, "Local Connection ID: 0x%04x", viph.vspp_lclid);
322         proto_tree_add_text(vspp_tree, offset+8,    2, "Remote Connection ID: 0x%04x", viph.vspp_rmtid);
323         proto_tree_add_text(vspp_tree, offset+10,   2, "Sequence number: 0x%04x", viph.vspp_seqno);
324         proto_tree_add_text(vspp_tree, offset+12,   2, "Ack number: 0x%04x", viph.vspp_ack);
325         proto_tree_add_text(vspp_tree, offset+14,   2, "Window: 0x%04x", viph.vspp_win);
326                 }
327         offset += 16; /* sizeof SPP */
328         dissect_data(pd, offset, fd, tree);
329         }
330
331 void
332 proto_register_vines(void)
333 {
334         static gint *ett[] = {
335                 &ett_vines,
336                 &ett_vines_frp,
337                 &ett_vines_spp,
338         };
339
340         proto_register_subtree_array(ett, array_length(ett));
341 }