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