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