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