Add the source files for the swift library.
[swifty.git] / src / libswift / doc / wireshark-dissector / packet-swift.c
1 /* packet-swift.c
2  * Routines for swift protocol packet disassembly
3  * By Andrew Keating <andrewzkeating@gmail.com>
4  * Copyright 2011 Andrew Keating
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <epan/packet.h>
32
33 static int proto_swift = -1;
34
35 /* Global fields */
36 static int hf_swift_receiving_channel = -1;
37 static int hf_swift_message_type = -1;
38
39 /* 00 Handshake fields */
40 static int hf_swift_handshake_channel = -1;
41
42 /* 01 Data fields */
43 static int hf_swift_data_bin_id = -1;
44 static int hf_swift_data_payload = -1;
45
46 /* 02 Ack fields */
47 static int hf_swift_ack_bin_id = -1;
48 static int hf_swift_ack_timestamp = -1;
49
50 /* 03 Have fields */
51 static int hf_swift_have_bin_id = -1;
52
53 /* 04 Hash fields */
54 static int hf_swift_hash_bin_id = -1;
55 static int hf_swift_hash_value = -1;
56
57 /* 05 PEX+ fields */
58 static int hf_swift_pexplus_ip = -1;
59 static int hf_swift_pexplus_port = -1;
60
61 /* 06 PEX- fields */
62 static int hf_swift_pexminus_ip = -1;
63 static int hf_swift_pexminus_port = -1;
64
65 /* 07 Signed hash fields */
66 static int hf_swift_signed_hash_bin_id = -1;
67 static int hf_swift_signed_hash_value = -1;
68 static int hf_swift_signed_hash_signature = -1;
69
70 /* 08 Hint fields */
71 static int hf_swift_hint_bin_id = -1;
72
73 static gint ett_swift = -1;
74
75 static void dissect_swift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
76 static gboolean dissect_swift_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
77
78 static const value_string message_type_names[] = {
79     { 0, "Handshake" },
80     { 1, "Data" },
81     { 2, "Ack" },
82     { 3, "Have" },
83     { 4, "Hash" },
84     { 5, "PEX+" },
85     { 6, "PEX-" },
86     { 7, "Signed Hash" },
87     { 8, "Hint" },
88     { 9, "SWIFT_MSGTYPE_RCVD" },
89     { 10, "SWIFT_MESSAGE_COUNT" },
90     { 0, NULL}
91 };
92
93
94 void
95 proto_register_swift(void)
96 {
97     static hf_register_info hf[] = {
98         /* Global */
99     { &hf_swift_receiving_channel,
100                 { "Receiving Channel", "swift.receiving.channel",
101                 FT_UINT32, BASE_HEX,
102                 NULL, 0x0,
103                 NULL, HFILL }
104      },
105         { &hf_swift_message_type,
106             { "Message Type", "swift.message.type",
107         FT_UINT8, BASE_DEC,
108         VALS(message_type_names), 0x0,
109         NULL, HFILL }
110         },
111
112         /* 00 Handshake */
113         { &hf_swift_handshake_channel,
114             { "Handshake Channel", "swift.handshake.channel",
115             FT_UINT32, BASE_HEX,
116         NULL, 0x0,
117         NULL, HFILL }
118         },
119
120         /* 01 Data */
121         { &hf_swift_data_bin_id,
122             { "Data Bin ID", "swift.data.bin_id",
123             FT_UINT32, BASE_HEX,
124             NULL, 0x0,
125             NULL, HFILL }
126         },
127         { &hf_swift_data_payload,
128             { "Data Payload", "swift.data.payload",
129             FT_BYTES, BASE_NONE,
130             NULL, 0x0,
131             NULL, HFILL }
132         },
133
134         /* 02 Ack */
135         { &hf_swift_ack_bin_id,
136             { "Ack Bin ID", "swift.ack.bin_id",
137             FT_UINT32, BASE_HEX,
138             NULL, 0x0,
139             NULL, HFILL }
140         },
141         { &hf_swift_ack_timestamp,
142             { "Timestamp", "swift.ack.timestamp",
143             FT_UINT64, BASE_HEX,
144             NULL, 0x0,
145             NULL, HFILL }
146         },
147
148         /* 03 Have */
149         { &hf_swift_have_bin_id,
150             { "Have Bin ID", "swift.have.bin_id",
151             FT_UINT32, BASE_HEX,
152             NULL, 0x0,
153             NULL, HFILL }
154         },
155
156         /* 04 Hash */ 
157         { &hf_swift_hash_bin_id,
158             { "Hash Bin ID", "swift.hash.bin_id",
159             FT_UINT32, BASE_HEX,
160             NULL, 0x0,
161             NULL, HFILL }
162         },
163         { &hf_swift_hash_value,
164             { "Hash Value", "swift.hash.value",
165             FT_BYTES, BASE_NONE,
166             NULL, 0x0,
167             NULL, HFILL }
168         },
169
170         /* 05 PEX+ */
171         { &hf_swift_pexplus_ip,
172             { "PEX+ IP Address", "swift.pex_plus.ip",
173             FT_IPv4, BASE_NONE,
174             NULL, 0x0,
175             NULL, HFILL }
176         },
177         { &hf_swift_pexplus_port,
178             { "PEX+ Port", "swift.pex_plus.port",
179             FT_UINT16, BASE_DEC,
180             NULL, 0x0,
181             NULL, HFILL }
182         },
183
184         /* 06 PEX- */
185         { &hf_swift_pexminus_ip,
186             { "PEX- IP Address", "swift.pex_minus.ip",
187             FT_IPv4, BASE_NONE,
188             NULL, 0x0,
189             NULL, HFILL }
190         },
191         { &hf_swift_pexminus_port,
192             { "PEX- Port", "swift.pex_minus.port",
193             FT_UINT16, BASE_DEC,
194             NULL, 0x0,
195             NULL, HFILL }
196         },
197
198         /* 07 Signed Hash */
199         { &hf_swift_signed_hash_bin_id,
200             { "Signed Hash Bin ID", "swift.signed_hash.bin_id",
201             FT_UINT32, BASE_HEX,
202             NULL, 0x0,
203             NULL, HFILL }
204         },
205         { &hf_swift_signed_hash_value,
206             { "Signed Hash Value", "swift.signed_hash.value",
207             FT_BYTES, BASE_NONE,
208             NULL, 0x0,
209             NULL, HFILL }
210         },
211         { &hf_swift_signed_hash_signature,
212             { "Signed Hash Signature", "swift.signed_hash.signature",
213             FT_BYTES, BASE_NONE,
214             NULL, 0x0,
215             NULL, HFILL }
216         },
217
218         /* 08 Hint */
219         { &hf_swift_hint_bin_id,
220             { "Hint Bin ID", "swift.hint.bin_id",
221             FT_UINT32, BASE_HEX,
222             NULL, 0x0,
223             NULL, HFILL }
224         },
225    };
226
227     /* Setup protocol subtree array */
228     static gint *ett[] = {
229         &ett_swift
230     };
231
232     proto_swift = proto_register_protocol (
233         "swift: the multiparty transport protocol", /* name       */
234         "swift",      /* short name */
235         "swift"       /* abbrev     */
236         );
237
238     proto_register_field_array(proto_swift, hf, array_length(hf));
239     proto_register_subtree_array(ett, array_length(ett));
240         register_dissector("swift", dissect_swift, proto_swift);
241 }
242
243 void
244 proto_reg_handoff_swift(void)
245 {
246         dissector_handle_t swift_handle;
247         swift_handle = find_dissector("swift");
248
249         /* Allow "Decode As" with any UDP packet. */
250         dissector_add_handle("udp.port", swift_handle);
251
252         /* Add our heuristic packet finder. */
253         heur_dissector_add("udp", dissect_swift_heur, proto_swift);
254 }
255
256 /* This heuristic is somewhat ambiguous, but for research purposes, it should be fine */
257 static gboolean
258 dissect_swift_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
259 {
260         guint message_length;
261         message_length = tvb_length(tvb);
262         /* If the fifth byte isn't one of the supported packet types, it's not swift (except keep-alives) */
263         if(message_length != 4) {       
264                 guint8 message_type;
265                 message_type = tvb_get_guint8(tvb, 4);
266                 if(message_type > 10) {
267                         return FALSE;
268                 }
269         }
270
271         dissect_swift(tvb, pinfo, tree);
272         return TRUE;
273 }
274
275 static void
276 dissect_swift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
277 {
278         gint offset = 0;
279     col_set_str(pinfo->cinfo, COL_PROTOCOL, "swift");
280     /* Clear out stuff in the info column */
281     col_clear(pinfo->cinfo,COL_INFO);
282
283     if (tree) { /* we are being asked for details */
284         proto_item *ti;
285                 ti = proto_tree_add_item(tree, proto_swift, tvb, 0, -1, FALSE);
286
287                 proto_tree *swift_tree;
288                 swift_tree = proto_item_add_subtree(ti, ett_swift);
289
290                 /* All messages start with the receiving channel, so we can pull it out here */
291                 proto_tree_add_item(swift_tree, hf_swift_receiving_channel, tvb, offset, 4, FALSE); offset += 4;
292
293                 /* Loop until there is nothing left to read in the packet */
294                 while(tvb_bytes_exist(tvb, offset, 1)) {
295                         guint8 message_type;
296                         guint dat_len;
297                     message_type = tvb_get_guint8(tvb, offset);
298                         proto_tree_add_item(swift_tree, hf_swift_message_type, tvb, offset, 1, FALSE); 
299                         offset += 1;
300
301                         /* Add message type to the info column */
302                         if(offset > 5) {
303                                 col_append_fstr(pinfo->cinfo, COL_INFO, ", ");
304                         }
305                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
306                                 val_to_str(message_type, message_type_names, "Unknown (0x%02x)"));
307
308                         /* Add it to the dissection window as well */
309                         proto_item_append_text(ti, ", %s",
310                                 val_to_str(message_type, message_type_names, "Unknown (0x%02x)"));
311
312                         switch(message_type) {
313                                 case 0: /* Handshake */
314                                         proto_tree_add_item(swift_tree, hf_swift_handshake_channel, tvb, offset, 4, FALSE); 
315                                         offset += 4;
316                                         break;
317                                 case 1: /* Data */
318                                         proto_tree_add_item(swift_tree, hf_swift_data_bin_id, tvb, offset, 4, FALSE); 
319                                         offset += 4;
320                                         /* We assume that the data field comprises the rest of this packet */
321                                         dat_len = tvb_length(tvb) - offset;
322                                         proto_tree_add_item(swift_tree, hf_swift_data_payload, tvb, offset, dat_len, FALSE); 
323                                         offset += dat_len;
324                                         break;
325                                 case 2: /* Ack */
326                                         proto_tree_add_item(swift_tree, hf_swift_ack_bin_id, tvb, offset, 4, FALSE); 
327                                         offset += 4;
328                                         proto_tree_add_item(swift_tree, hf_swift_ack_timestamp, tvb, offset, 8, FALSE); 
329                                         offset += 8;
330                                         break;
331                                 case 3: /* Have */
332                                         proto_tree_add_item(swift_tree, hf_swift_have_bin_id, tvb, offset, 4, FALSE); 
333                                         offset += 4;
334                                         break;
335                                 case 4: /* Hash */
336                                         proto_tree_add_item(swift_tree, hf_swift_hash_bin_id, tvb, offset, 4, FALSE); 
337                                         offset += 4;
338                                         proto_tree_add_item(swift_tree, hf_swift_hash_value, tvb, offset, 20, FALSE); 
339                                         offset += 20;
340                                         break;
341                                 case 5: /* PEX+ */
342                                         proto_tree_add_item(swift_tree, hf_swift_pexplus_ip, tvb, offset, 4, FALSE); 
343                                         offset += 4;
344                                         proto_tree_add_item(swift_tree, hf_swift_pexplus_port, tvb, offset, 2, FALSE); 
345                                         offset += 2;
346                                         break;
347                                 case 6: /* PEX- */
348                                         proto_tree_add_item(swift_tree, hf_swift_pexminus_ip, tvb, offset, 4, FALSE); 
349                                         offset += 4;
350                                         proto_tree_add_item(swift_tree, hf_swift_pexminus_port, tvb, offset, 2, FALSE); 
351                                         offset += 2;
352                                         break;
353                                 case 7: /* Signed Hash */
354                                         proto_tree_add_item(swift_tree, hf_swift_signed_hash_bin_id, tvb, offset, 4, FALSE); 
355                                         offset += 4;
356                                         proto_tree_add_item(swift_tree, hf_swift_signed_hash_value, tvb, offset, 20, FALSE); 
357                                         offset += 20;
358                                         /* It is not entirely clear what size the public key will be, so we allow any size
359                                            For this to work, we must assume there aren't any more messages in the packet */
360                                         dat_len = tvb_length(tvb) - offset;
361                                         proto_tree_add_item(swift_tree, hf_swift_signed_hash_signature, tvb, offset, dat_len, FALSE); 
362                                         offset += dat_len;
363                                         break;
364                                 case 8: /* Hint */
365                                         proto_tree_add_item(swift_tree, hf_swift_hint_bin_id, tvb, offset, 4, FALSE); 
366                                         offset += 4;
367                                         break;
368                                 case 9: /* SWIFT_MSGTYPE_RCVD */
369                                         break;
370                                 case 10: /* SWIFT_MESSAGE_COUNT */
371                                         break;
372                                 default:
373                                         break;
374                         }
375                 }
376                 /* If the offset is still 4 here, the message is a keep-alive */
377                 if(offset == 4) {
378                         col_append_fstr(pinfo->cinfo, COL_INFO, "Keep-Alive");
379                         proto_item_append_text(ti, ", Keep-Alive");
380                 }
381         }
382 }
383