waste a couple of bytes per tcp conversation and make the tree for acked_packets...
[obnox/wireshark/wip.git] / epan / dissectors / packet-netsync.c
1 /* packet-netsync.c
2  * Routines for Monotone Netsync packet disassembly
3  *
4  * $Id$
5  *
6  * Copyright (c) 2005 by Erwin Rol <erwin@erwinrol.com>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1999 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 /* Include files */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <time.h>
37 #include <string.h>
38 #include <epan/packet.h>
39 #include <epan/addr_resolv.h>
40 #include <epan/prefs.h>
41 #include <epan/strutil.h>
42 #include <epan/emem.h>
43 #include "packet-tcp.h"
44
45 /*
46  * See
47  *
48  *      http://www.venge.net/monotone/
49  */
50
51 /* Define TCP ports for Monotone netsync */
52
53 #define TCP_PORT_NETSYNC 5253
54
55 #define NETSYNC_ROLE_SOURCE     1
56 #define NETSYNC_ROLE_SINK       2
57 #define NETSYNC_ROLE_BOTH       3
58
59 static const value_string netsync_role_vals[] = {
60         { NETSYNC_ROLE_SOURCE,  "Source" },
61         { NETSYNC_ROLE_SINK,    "Sink" },
62         { NETSYNC_ROLE_BOTH,    "Both" },
63         { 0,                    NULL }
64 };
65
66
67 #define NETSYNC_CMD_ERROR       0
68 #define NETSYNC_CMD_BYE         1
69 #define NETSYNC_CMD_HELLO       2
70 #define NETSYNC_CMD_ANONYMOUS   3
71 #define NETSYNC_CMD_AUTH        4
72 #define NETSYNC_CMD_CONFIRM     5
73 #define NETSYNC_CMD_REFINE      6
74 #define NETSYNC_CMD_DONE        7
75 #define NETSYNC_CMD_SEND_DATA   8
76 #define NETSYNC_CMD_SEND_DELTA  9
77 #define NETSYNC_CMD_DATA        10
78 #define NETSYNC_CMD_DELTA       11
79 #define NETSYNC_CMD_NONEXISTANT 12
80
81 static const value_string netsync_cmd_vals[] = {
82         { NETSYNC_CMD_ERROR,            "Error" },
83         { NETSYNC_CMD_BYE,              "Bye" },
84         { NETSYNC_CMD_HELLO,            "Hello" },
85         { NETSYNC_CMD_ANONYMOUS,        "Anonymous" },
86         { NETSYNC_CMD_AUTH,             "Auth" },
87         { NETSYNC_CMD_CONFIRM,          "Confirm" },
88         { NETSYNC_CMD_REFINE,           "Refine" },
89         { NETSYNC_CMD_DONE,             "Done" },
90         { NETSYNC_CMD_SEND_DATA,        "Send Data" },
91         { NETSYNC_CMD_SEND_DELTA,       "Send Delta" },
92         { NETSYNC_CMD_DATA,             "Data" },
93         { NETSYNC_CMD_DELTA,            "Delta" },
94         { NETSYNC_CMD_NONEXISTANT,      "Nonexistant" },
95         { 0,                            NULL }
96 };
97
98 #define NETSNYC_MERKLE_HASH_LENGTH 20
99
100 void proto_reg_handoff_netsync(void);
101
102 /* Define the monotone netsync proto */
103 static int proto_netsync = -1;
104
105 static int hf_netsync_version = -1;
106 static int hf_netsync_command = -1;
107 static int hf_netsync_size = -1;
108 static int hf_netsync_data = -1;
109 static int hf_netsync_checksum = -1;
110
111 static int hf_netsync_cmd_done_level = -1;
112 static int hf_netsync_cmd_done_type = -1;
113
114 static int hf_netsync_cmd_hello_keyname = -1;
115 static int hf_netsync_cmd_hello_key = -1;
116 static int hf_netsync_cmd_nonce = -1;
117
118 static int hf_netsync_cmd_anonymous_role = -1;
119 static int hf_netsync_cmd_anonymous_collection = -1;
120
121 static int hf_netsync_cmd_send_data_type = -1;
122 static int hf_netsync_cmd_send_data_id = -1;
123
124 static int hf_netsync_cmd_error_msg = -1;
125
126
127 static int hf_netsync_cmd_confirm_sig = -1;
128
129 static int hf_netsync_cmd_auth_role = -1;
130 static int hf_netsync_cmd_auth_collection = -1;
131 static int hf_netsync_cmd_auth_id = -1;
132 static int hf_netsync_cmd_auth_nonce1 = -1;
133 static int hf_netsync_cmd_auth_nonce2 = -1;
134 static int hf_netsync_cmd_auth_sig = -1;
135
136 static int hf_netsync_cmd_data_type = -1;
137 static int hf_netsync_cmd_data_id = -1;
138 static int hf_netsync_cmd_data_compressed = -1;
139 static int hf_netsync_cmd_data_payload = -1;
140
141 static int hf_netsync_cmd_delta_type = -1;
142 static int hf_netsync_cmd_delta_base_id = -1;
143 static int hf_netsync_cmd_delta_ident_id = -1;
144 static int hf_netsync_cmd_delta_compressed = -1;
145 static int hf_netsync_cmd_delta_payload = -1;
146
147 static int hf_netsync_cmd_refine_tree_node = -1;
148
149 static int hf_netsync_cmd_send_delta_type = -1;
150 static int hf_netsync_cmd_send_delta_base_id = -1;
151 static int hf_netsync_cmd_send_delta_ident_id = -1;
152
153 static int hf_netsync_cmd_nonexistant_type = -1;
154 static int hf_netsync_cmd_nonexistant_id = -1;
155
156 /* Define the tree for netsync */
157 static int ett_netsync = -1;
158
159
160 /*
161  * Here are the global variables associated with the preferences
162  * for monotone netsync
163  */
164
165 static dissector_handle_t netsync_handle;
166
167 static guint global_tcp_port_netsync = TCP_PORT_NETSYNC;
168 static guint tcp_port_netsync = TCP_PORT_NETSYNC;
169 static gboolean netsync_desegment = TRUE;
170
171 static gint dissect_uleb128( tvbuff_t *tvb, gint offset, guint* size)
172 {
173         guint shift = 0;
174         guint8 tmp;
175         guint start_offset = offset;
176
177         *size = 0;
178
179         /* get size */
180         do {
181                 tmp = tvb_get_guint8(tvb, offset);
182                 offset += 1;
183                         
184                 *size |= (tmp & 0x7F) << shift;
185                 shift += 7;     
186         } while (tmp & 0x80);
187
188
189         return offset - start_offset;
190 }
191
192 static gint dissect_netsync_cmd_error( tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_) 
193 {
194         guint len = 0;
195
196         offset += dissect_uleb128( tvb, offset, &len );
197
198         proto_tree_add_item(tree, hf_netsync_cmd_error_msg, tvb,
199                                 offset, len, FALSE );
200         offset += len;
201
202         return offset;
203 }
204
205 static gint dissect_netsync_cmd_bye(tvbuff_t *tvb _U_,  gint offset, proto_tree *tree _U_, guint size _U_)
206 {
207         return offset;
208 }
209
210
211 static gint dissect_netsync_cmd_hello(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
212 {
213         guint len = 0;
214
215         offset += dissect_uleb128( tvb, offset, &len );
216
217         proto_tree_add_item(tree, hf_netsync_cmd_hello_keyname, tvb,
218                                 offset, len, FALSE );
219         offset += len;
220
221
222         offset += dissect_uleb128( tvb, offset, &len );
223
224         proto_tree_add_item(tree, hf_netsync_cmd_hello_key, tvb,
225                                 offset, len, FALSE );
226         offset += len;
227
228         proto_tree_add_item(tree, hf_netsync_cmd_nonce, tvb,
229                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
230         offset += NETSNYC_MERKLE_HASH_LENGTH;
231
232         return offset;
233 }
234
235
236 static gint dissect_netsync_cmd_anonymous(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
237 {
238         guint len = 0;
239
240         proto_tree_add_item(tree, hf_netsync_cmd_anonymous_role, tvb,
241                                 offset, 1, FALSE );
242         offset += 1;
243
244         offset += dissect_uleb128( tvb, offset, &len );
245
246         proto_tree_add_item(tree, hf_netsync_cmd_anonymous_collection, tvb,
247                                 offset, len, FALSE );
248         offset += len;
249
250         proto_tree_add_item(tree, hf_netsync_cmd_nonce, tvb,
251                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
252         offset += NETSNYC_MERKLE_HASH_LENGTH;
253
254         return offset;
255 }
256
257
258 static gint dissect_netsync_cmd_auth(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
259 {
260         guint len = 0;
261
262         proto_tree_add_item(tree, hf_netsync_cmd_auth_role, tvb,
263                                 offset, 1, FALSE );
264         offset += 1;
265
266
267         offset += dissect_uleb128( tvb, offset, &len );
268
269         proto_tree_add_item(tree, hf_netsync_cmd_auth_collection, tvb,
270                                 offset, len, FALSE );
271         offset += len;
272
273         proto_tree_add_item(tree, hf_netsync_cmd_auth_id, tvb,
274                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
275         offset += NETSNYC_MERKLE_HASH_LENGTH;
276
277         offset += len;
278
279         proto_tree_add_item(tree, hf_netsync_cmd_auth_nonce1, tvb,
280                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
281         offset += NETSNYC_MERKLE_HASH_LENGTH;
282
283         offset += len;
284
285         proto_tree_add_item(tree, hf_netsync_cmd_auth_nonce2, tvb,
286                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
287         offset += NETSNYC_MERKLE_HASH_LENGTH;
288
289         offset += dissect_uleb128( tvb, offset, &len );
290
291         proto_tree_add_item(tree, hf_netsync_cmd_auth_sig, tvb,
292                                 offset, len, FALSE );
293         offset += len;
294
295         return offset;
296 }
297
298
299 static gint dissect_netsync_cmd_confirm(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
300 {
301         guint len = 0;
302
303         offset += dissect_uleb128( tvb, offset, &len );
304
305         proto_tree_add_item(tree, hf_netsync_cmd_confirm_sig, tvb,
306                                 offset, len, FALSE );
307         offset += len;
308
309
310         return offset;
311 }
312
313
314 static gint dissect_netsync_cmd_refine(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size)
315 {
316         proto_tree_add_item(tree, hf_netsync_cmd_refine_tree_node, tvb,
317                                 offset, size, FALSE );
318         offset += size;
319
320         return offset;
321 }
322
323
324 static gint dissect_netsync_cmd_done(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
325 {
326         guint len = 0;
327         guint bytes = 0;
328
329         bytes = dissect_uleb128( tvb, offset, &len );
330
331         proto_tree_add_uint(tree, hf_netsync_cmd_done_level, tvb,
332                                         offset, bytes, len );
333         offset += bytes;
334
335         proto_tree_add_item(tree, hf_netsync_cmd_done_type, tvb,
336                                 offset, 1, FALSE );
337         offset += 1;
338
339         return offset;
340 }
341
342
343 static gint dissect_netsync_cmd_send_data(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
344 {
345         proto_tree_add_item(tree, hf_netsync_cmd_send_data_type, tvb,
346                                         offset, 1, FALSE );
347         offset += 1;
348
349         proto_tree_add_item(tree, hf_netsync_cmd_send_data_id, tvb,
350                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
351         offset += NETSNYC_MERKLE_HASH_LENGTH;
352
353         return offset;
354 }
355
356
357 static gint dissect_netsync_cmd_send_delta(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
358 {
359         proto_tree_add_item(tree, hf_netsync_cmd_send_delta_type, tvb,
360                                         offset, 1, FALSE );
361         offset += 1;
362
363         proto_tree_add_item(tree, hf_netsync_cmd_send_delta_base_id, tvb,
364                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
365         offset += NETSNYC_MERKLE_HASH_LENGTH;
366
367
368         proto_tree_add_item(tree, hf_netsync_cmd_send_delta_ident_id, tvb,
369                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
370         offset += NETSNYC_MERKLE_HASH_LENGTH;
371
372         return offset;
373 }
374
375
376 static gint dissect_netsync_cmd_data(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
377 {
378         guint len = -1;
379         
380         proto_tree_add_item(tree, hf_netsync_cmd_data_type, tvb,
381                                 offset, 1, FALSE );
382         offset += 1;
383
384         proto_tree_add_item(tree, hf_netsync_cmd_data_id, tvb,
385                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
386         offset += NETSNYC_MERKLE_HASH_LENGTH;
387
388         proto_tree_add_item(tree, hf_netsync_cmd_data_compressed, tvb,
389                                 offset, 1, FALSE );
390         offset += 1;
391
392         offset += dissect_uleb128( tvb, offset, &len );
393
394         proto_tree_add_item(tree, hf_netsync_cmd_data_payload, tvb,
395                                 offset, len, FALSE );
396         offset += len;
397
398         return offset;
399 }
400
401
402 static gint dissect_netsync_cmd_delta(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
403 {
404         guint len = 0;
405
406         proto_tree_add_item(tree, hf_netsync_cmd_delta_type, tvb,
407                                 offset, 1, FALSE );
408         offset += 1;
409
410         proto_tree_add_item(tree, hf_netsync_cmd_delta_base_id, tvb,
411                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
412         offset += NETSNYC_MERKLE_HASH_LENGTH;
413
414         proto_tree_add_item(tree, hf_netsync_cmd_delta_ident_id, tvb,
415                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
416         offset += NETSNYC_MERKLE_HASH_LENGTH;
417
418         proto_tree_add_item(tree, hf_netsync_cmd_delta_compressed, tvb,
419                                 offset, 1, FALSE );
420         offset += 1;
421
422         offset += dissect_uleb128( tvb, offset, &len );
423
424         proto_tree_add_item(tree, hf_netsync_cmd_delta_payload, tvb,
425                                 offset, len, FALSE );
426         offset += len;
427
428         return offset;
429 }
430
431
432 static gint dissect_netsync_cmd_nonexistant(tvbuff_t *tvb,  gint offset, proto_tree *tree, guint size _U_)
433 {
434         proto_tree_add_item(tree, hf_netsync_cmd_nonexistant_type, tvb,
435                                 offset, 1, FALSE );
436         offset += 1;
437
438         proto_tree_add_item(tree, hf_netsync_cmd_nonexistant_id, tvb,
439                                 offset, NETSNYC_MERKLE_HASH_LENGTH, FALSE );
440         offset += NETSNYC_MERKLE_HASH_LENGTH;
441
442         return offset;
443 }
444
445 static guint
446 get_netsync_pdu_len(tvbuff_t *tvb, int offset)
447 {
448         guint size = 0, size_bytes;
449
450         /* skip version and command */
451         offset += 2;
452         
453         size_bytes = dissect_uleb128( tvb, offset, &size );
454                 
455         /* the calculated size if for the data only, this doesn't
456          * include the version (1 byte), command (1 byte), 
457          * lenght (size_bytes bytes) and checksum (4 bytes)
458          */
459
460         return 1 + 1 + size_bytes + size + 4;
461 }
462
463 static void
464 dissect_netsync_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
465 {
466         gint offset = 0;
467         guint8 tmp;
468         guint8 cmd, version;
469         guint32 size, size_bytes, shift;
470         proto_tree *ti,*netsync_tree=NULL;
471
472         /* Set the protocol column */
473         if (check_col(pinfo->cinfo,COL_PROTOCOL)) {
474                 col_set_str(pinfo->cinfo,COL_PROTOCOL,"Netsync");
475         }
476
477
478         if (tree == NULL)
479                 return;
480         
481         while (tvb_reported_length_remaining(tvb, offset)  > 0) {
482                 ti = proto_tree_add_item(tree, proto_netsync, tvb, offset, -1, FALSE);
483                 netsync_tree = proto_item_add_subtree(ti, ett_netsync);
484
485                 version = tvb_get_guint8(tvb, offset);
486                 proto_tree_add_item(netsync_tree, hf_netsync_version, tvb,
487                                         offset, 1, FALSE );
488                 offset += 1;
489
490                 cmd = tvb_get_guint8(tvb, offset);
491                 proto_tree_add_item(netsync_tree, hf_netsync_command, tvb,
492                                         offset, 1, FALSE );
493                 offset += 1;
494
495
496                 /* get size */
497                 size = 0;
498                 size_bytes = 0;
499                 shift = 0;
500                 do {
501                         tmp = tvb_get_guint8(tvb, offset + size_bytes);
502                         size_bytes += 1;
503                         
504                         size |= (tmp & 0x7F) << shift;
505                         shift += 7;     
506                 } while (tmp & 0x80);
507                 
508                 
509                 proto_tree_add_uint(netsync_tree, hf_netsync_size, tvb,
510                                         offset, size_bytes, size );
511                 offset += size_bytes;
512
513                 switch (cmd) {
514                         case NETSYNC_CMD_DONE:
515                                 dissect_netsync_cmd_done( tvb, offset, netsync_tree, size );
516                                 break;
517
518                         case NETSYNC_CMD_ERROR:
519                                 dissect_netsync_cmd_error( tvb, offset, netsync_tree, size );
520                                 break;
521
522                         case NETSYNC_CMD_BYE:
523                                 dissect_netsync_cmd_bye( tvb, offset, netsync_tree, size );
524                                 break;
525
526                         case NETSYNC_CMD_HELLO:
527                                 dissect_netsync_cmd_hello( tvb, offset, netsync_tree, size );
528                                 break;
529
530                         case NETSYNC_CMD_ANONYMOUS:
531                                 dissect_netsync_cmd_anonymous( tvb, offset, netsync_tree, size );
532                                 break;
533
534                         case NETSYNC_CMD_AUTH:
535                                 dissect_netsync_cmd_auth( tvb, offset, netsync_tree, size );
536                                 break;
537
538                         case NETSYNC_CMD_CONFIRM:
539                                 dissect_netsync_cmd_confirm( tvb, offset, netsync_tree, size );
540                                 break;
541
542                         case NETSYNC_CMD_REFINE:
543                                 dissect_netsync_cmd_refine( tvb, offset, netsync_tree, size );
544                                 break;
545
546                         case NETSYNC_CMD_SEND_DATA:
547                                 dissect_netsync_cmd_send_data( tvb, offset, netsync_tree, size );
548                                 break;
549
550                         case NETSYNC_CMD_SEND_DELTA:
551                                 dissect_netsync_cmd_send_delta( tvb, offset, netsync_tree, size );
552                                 break;
553
554                         case NETSYNC_CMD_DATA:
555                                 dissect_netsync_cmd_data( tvb, offset, netsync_tree, size );
556                                 break;
557
558                         case NETSYNC_CMD_DELTA:
559                                 dissect_netsync_cmd_delta( tvb, offset, netsync_tree, size );
560                                 break;
561
562                         case NETSYNC_CMD_NONEXISTANT:
563                                 dissect_netsync_cmd_nonexistant( tvb, offset, netsync_tree, size );
564                                 break;
565
566                         default:
567                                 proto_tree_add_item(netsync_tree, hf_netsync_data, tvb,
568                                         offset, size, FALSE );
569                                 break;
570                 }
571
572                 offset += size;
573
574                 proto_tree_add_item(netsync_tree, hf_netsync_checksum, tvb,
575                                         offset, 4, FALSE );
576                 offset += 4;
577
578
579                 proto_item_append_text(netsync_tree, " V%d, Cmd: %s (%d), Size: %d", 
580                                         version, val_to_str(cmd, netsync_cmd_vals, "(0x%x)"), cmd, size );              
581
582                 proto_item_set_len(netsync_tree, 1+1+size_bytes+size+4);
583         }
584 }
585
586 static void
587 dissect_netsync(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
588 {
589         tcp_dissect_pdus(tvb, pinfo, tree, netsync_desegment, 7, get_netsync_pdu_len,
590                                         dissect_netsync_pdu);
591 }
592
593 void
594 proto_register_netsync(void) 
595 {
596         static hf_register_info hf[] = {
597                 /* General */
598                 { &hf_netsync_version,
599                         { "Version", "netsync.version",
600                           FT_UINT8, BASE_DEC, NULL, 0x0,
601                           "Version", HFILL } },
602                 { &hf_netsync_command,
603                         { "Command", "netsync.command",
604                           FT_UINT8, BASE_HEX, VALS(netsync_cmd_vals), 0x0,
605                           "Command", HFILL } },
606                 { &hf_netsync_size,
607                         { "Size", "netsync.size",
608                           FT_UINT32, BASE_DEC, NULL, 0x0,
609                           "Size", HFILL } },
610                 { &hf_netsync_data,
611                         { "Data", "netsync.data",
612                           FT_BYTES, BASE_HEX, NULL, 0x0,
613                           "Data", HFILL } },
614                 { &hf_netsync_checksum,
615                         { "Checksum", "netsync.checksum",
616                           FT_UINT32, BASE_HEX, NULL, 0x0,
617                           "Checksum", HFILL } },
618                 { &hf_netsync_cmd_hello_keyname,
619                         { "Key Name", "netsync.cmd.hello.keyname",
620                           FT_STRING, BASE_HEX, NULL, 0x0,
621                           "Key Name", HFILL } },
622                 { &hf_netsync_cmd_hello_key,
623                         { "Key", "netsync.cmd.hello.key",
624                           FT_BYTES, BASE_HEX, NULL, 0x0,
625                           "Key", HFILL } },
626                 { &hf_netsync_cmd_nonce,
627                         { "Nonce", "netsync.cmd.nonce",
628                           FT_BYTES, BASE_HEX, NULL, 0x0,
629                           "Nonce", HFILL } },
630                 { &hf_netsync_cmd_anonymous_role,
631                         { "Role", "netsync.cmd.anonymous.role",
632                           FT_UINT8, BASE_DEC, VALS(netsync_role_vals), 0x0,
633                           "Role", HFILL } },
634                 { &hf_netsync_cmd_anonymous_collection,
635                         { "Collection", "netsync.cmd.anonymous.collection",
636                           FT_STRING, BASE_DEC, NULL, 0x0,
637                           "Collection", HFILL } },
638                 { &hf_netsync_cmd_confirm_sig,
639                         { "Signature", "netsync.cmd.confirm.signature",
640                           FT_BYTES, BASE_HEX, NULL, 0x0,
641                           "Signature", HFILL } },
642                 { &hf_netsync_cmd_send_data_type,
643                         { "Type", "netsync.cmd.send_data.type",
644                           FT_UINT8, BASE_DEC, NULL, 0x0,
645                           "Type", HFILL } },
646                 { &hf_netsync_cmd_send_data_id,
647                         { "ID", "netsync.cmd.send_data.id",
648                           FT_BYTES, BASE_HEX, NULL, 0x0,
649                           "ID", HFILL } },
650                 { &hf_netsync_cmd_error_msg,
651                         { "Message", "netsync.cmd.error.msg",
652                           FT_STRING, BASE_DEC, NULL, 0x0,
653                           "Message", HFILL } },
654
655                 { &hf_netsync_cmd_done_level,
656                         { "Level", "netsync.cmd.done.level",
657                           FT_UINT32, BASE_DEC, NULL, 0x0,
658                           "Level", HFILL } },
659                 { &hf_netsync_cmd_auth_role,
660                         { "Role", "netsync.cmd.auth.role",
661                           FT_UINT8, BASE_DEC, VALS(netsync_role_vals), 0x0,
662                           "Role", HFILL } },
663                 { &hf_netsync_cmd_auth_collection,
664                         { "Collection", "netsync.cmd.auth.collection",
665                           FT_STRING, BASE_DEC, NULL, 0x0,
666                           "Collection", HFILL } },
667                 { &hf_netsync_cmd_auth_id,
668                         { "ID", "netsync.cmd.auth.id",
669                           FT_BYTES, BASE_DEC, NULL, 0x0,
670                           "ID", HFILL } },
671                 { &hf_netsync_cmd_auth_nonce1,
672                         { "Nonce 1", "netsync.cmd.auth.nonce1",
673                           FT_BYTES, BASE_DEC, NULL, 0x0,
674                           "Nonce 1", HFILL } },
675                 { &hf_netsync_cmd_auth_nonce2,
676                         { "Nonce 2", "netsync.cmd.auth.nonce2",
677                           FT_BYTES, BASE_DEC, NULL, 0x0,
678                           "Nonce 2", HFILL } },
679                 { &hf_netsync_cmd_auth_sig,
680                         { "Signature", "netsync.cmd.auth.sig",
681                           FT_BYTES, BASE_DEC, NULL, 0x0,
682                           "Signature", HFILL } },
683                 { &hf_netsync_cmd_data_type,
684                         { "Type", "netsync.cmd.data.type",
685                           FT_UINT8, BASE_DEC, NULL, 0x0,
686                           "Type", HFILL } },
687                 { &hf_netsync_cmd_data_id,
688                         { "ID", "netsync.cmd.data.id",
689                           FT_BYTES, BASE_DEC, NULL, 0x0,
690                           "ID", HFILL } },
691                 { &hf_netsync_cmd_data_compressed,
692                         { "Compressed", "netsync.cmd.data.compressed",
693                           FT_UINT8, BASE_DEC, NULL, 0x0,
694                           "Compressed", HFILL } },
695                 { &hf_netsync_cmd_data_payload,
696                         { "Payload", "netsync.cmd.data.payload",
697                           FT_BYTES, BASE_DEC, NULL, 0x0,
698                           "Payload", HFILL } },
699                 { &hf_netsync_cmd_delta_type,
700                         { "Type", "netsync.cmd.delta.type",
701                           FT_UINT8, BASE_DEC, NULL, 0x0,
702                           "Type", HFILL } },
703                 { &hf_netsync_cmd_delta_base_id,
704                         { "Base ID", "netsync.cmd.delta.base_id",
705                           FT_BYTES, BASE_DEC, NULL, 0x0,
706                           "Base ID", HFILL } },
707                 { &hf_netsync_cmd_delta_ident_id,
708                         { "Ident ID", "netsync.cmd.delta.ident_id",
709                           FT_BYTES, BASE_DEC, NULL, 0x0,
710                           "Ident ID", HFILL } },
711                 { &hf_netsync_cmd_delta_compressed,
712                         { "Compressed", "netsync.cmd.delta.compressed",
713                           FT_UINT8, BASE_DEC, NULL, 0x0,
714                           "Compressed", HFILL } },
715                 { &hf_netsync_cmd_delta_payload,
716                         { "Payload", "netsync.cmd.delta.payload",
717                           FT_BYTES, BASE_DEC, NULL, 0x0,
718                           "Payload", HFILL } },
719                 { &hf_netsync_cmd_refine_tree_node,
720                         { "Tree Node", "netsync.cmd.refine.tree_node",
721                           FT_BYTES, BASE_DEC, NULL, 0x0,
722                           "Tree Node", HFILL } },
723                 { &hf_netsync_cmd_send_delta_type,
724                         { "Type", "netsync.cmd.send_delta.type",
725                           FT_UINT8, BASE_DEC, NULL, 0x0,
726                           "Type", HFILL } },
727                 { &hf_netsync_cmd_send_delta_base_id,
728                         { "Base ID", "netsync.cmd.send_delta.base_id",
729                           FT_BYTES, BASE_DEC, NULL, 0x0,
730                           "Base ID", HFILL } },
731                 { &hf_netsync_cmd_send_delta_ident_id,
732                         { "Ident ID", "netsync.cmd.send_delta.ident_id",
733                           FT_BYTES, BASE_DEC, NULL, 0x0,
734                           "Ident ID", HFILL } },
735                 { &hf_netsync_cmd_nonexistant_id,
736                         { "ID", "netsync.cmd.nonexistant.id",
737                           FT_BYTES, BASE_DEC, NULL, 0x0,
738                           "ID", HFILL } },
739                 { &hf_netsync_cmd_nonexistant_type,
740                         { "Type", "netsync.cmd.nonexistant.type",
741                           FT_UINT8, BASE_DEC, NULL, 0x0,
742                           "Type", HFILL } },
743                 { &hf_netsync_cmd_done_type,
744                         { "Type", "netsync.cmd.done.type",
745                           FT_UINT8, BASE_DEC, NULL, 0x0,
746                           "Type", HFILL } }
747
748
749         };
750
751         static gint *ett[] = {
752                 &ett_netsync,
753         };
754
755         module_t *netsync_module;
756
757         proto_netsync = proto_register_protocol("Monotone Netsync", "Netsync", "netsync");
758         proto_register_field_array(proto_netsync, hf, array_length(hf));
759         proto_register_subtree_array(ett, array_length(ett));
760
761         netsync_handle = create_dissector_handle(dissect_netsync, proto_netsync);
762
763         netsync_module = prefs_register_protocol(proto_netsync,
764                                                 proto_reg_handoff_netsync);
765
766         prefs_register_uint_preference(netsync_module, "tcp_port",
767                                         "Monotone Netsync TCP Port",
768                                         "The TCP port on which Monotone Netsync packets will be sent",
769                                         10, &global_tcp_port_netsync);
770
771
772         prefs_register_bool_preference(netsync_module, "desegment_netsync_messages",
773                 "Reassemble Netsync messages spanning multiple TCP segments",
774                 "Whether the Netsync dissector should reassemble messages spanning multiple TCP segments."
775                 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
776                 &netsync_desegment);
777
778 }
779
780 void
781 proto_reg_handoff_netsync(void) 
782 {
783         static gint initialized = 0;
784
785         if (initialized) {
786                 dissector_delete("tcp.port", tcp_port_netsync, netsync_handle);
787         } else {
788                 initialized = 1;
789         }
790
791         tcp_port_netsync = global_tcp_port_netsync;  
792         dissector_add("tcp.port", global_tcp_port_netsync, netsync_handle);
793 }
794