Update Free Software Foundation address.
[metze/wireshark/wip.git] / epan / dissectors / packet-hdfsdata.c
1 /* packet-hdfsdata.c
2  * HDFS data Protocol and dissectors
3  *
4  * Copyright (c) 2011 by Isilon Systems.
5  *
6  * Author: Allison Obourn <aobourn@isilon.com>
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1999 Gerald Combs
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  */
28
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include "epan/dissectors/packet-tcp.h"
37
38
39 #if 0
40 #define NAMENODE_PORT 8020
41 #define DATANODE_PORT 8021
42 #endif
43
44 #define FIRST_READ_FRAGMENT_LEN 15
45 #define SECOND_READ_FRAGMENT_LEN 29
46 #define LAST_READ_FRAGMENT_LEN 4
47 #define WRITE_OP 80
48 #define READ_OP 81
49 #define MIN_WRITE_REQ 35
50 #define MIN_READ_REQ 36
51
52 #define STATUS_SUCCESS 6
53 #define PIPELINE_LEN 1
54 #define STATUS_LEN 2
55 #define FINISH_REQ_LEN 4
56 #define END_PACKET_LEN 8
57 #define READ_RESP_HEAD_LEN 19
58 #define WRITE_RESP_HEAD_LEN 21
59 #define WRITE_REQ_HEAD_LEN 7
60
61 #define CRC 1
62 #define CRC_SIZE 8.0
63 #define CHUNKSIZE_START 3
64
65
66 static const int RESPONSE_HEADER = 1;
67 static const int RESPONSE_METADATA = 2;
68 static const int RESPONSE_DATA = 3;
69
70 static guint tcp_port = 0;
71
72 static int proto_hdfsdata = -1;
73 static int hf_hdfsdata_version = -1;
74 static int hf_hdfsdata_cmd = -1;
75 static int hf_hdfsdata_blockid = -1;
76 static int hf_hdfsdata_timestamp = -1;
77 static int hf_hdfsdata_startoffset = -1;
78 static int hf_hdfsdata_blocklen = -1;
79 static int hf_hdfsdata_clientlen = -1;
80 static int hf_hdfsdata_clientid = -1;
81 static int hf_hdfsdata_tokenlen = -1;
82 static int hf_hdfsdata_tokenid = -1;
83 static int hf_hdfsdata_tokenpassword = -1;
84 static int hf_hdfsdata_tokentype = -1;
85 static int hf_hdfsdata_tokenservice = -1;
86 static int hf_hdfsdata_status = -1;
87 static int hf_hdfsdata_checksumtype = -1;
88 static int hf_hdfsdata_chunksize = -1;
89 static int hf_hdfsdata_chunkoffset = -1;
90 static int hf_hdfsdata_datalength = -1;
91 static int hf_hdfsdata_inblockoffset = -1;
92 static int hf_hdfsdata_seqnum = -1;
93 static int hf_hdfsdata_last = -1;
94 static int hf_hdfsdata_crc32 = -1;
95 static int hf_hdfsdata_datalen = -1;
96 static int hf_hdfsdata_rest = -1;
97 static int hf_hdfsdata_end = -1;
98 static int hf_hdfsdata_packetsize = -1;
99 static int hf_hdfsdata_chunklength = -1;
100 static int hf_hdfsdata_crc64 = -1;
101 static int hf_hdfsdata_pipelinestatus = -1;
102
103 static int hf_hdfsdata_pipelinenum = -1;
104 static int hf_hdfsdata_recovery = -1;
105 static int hf_hdfsdata_sourcenode = -1;
106 static int hf_hdfsdata_currentpipeline = -1;
107 static int hf_hdfsdata_node = -1;
108
109 static gint ett_hdfsdata = -1;
110
111 void proto_reg_handoff_hdfsdata(void);
112
113 /* Taken from HDFS
114    Parse the first byte of a vint/vlong to determine the number of bytes
115    value is the first byte of the vint/vlong
116    returns the total number of bytes (1 to 9) */
117 static int
118 decode_vint_size (char value) {
119   if (value >= -112) {
120     return 1;
121   } else if (value < -120) {
122     return -119 - value;
123   }
124   return -111 - value;
125 }
126
127 /* Taken from HDFS
128    converts a variable length number into a long and discovers how many bytes it is
129    returns the decoded number */
130 static guint
131 dissect_variable_length_long (tvbuff_t *tvb, proto_tree *hdfsdata_tree, int* offset)
132 {
133   int byte_count = 1;
134   int idx = 0;
135   long i = 0;
136   char first_byte = tvb_get_guint8(tvb, *offset);
137   long size = 0;
138
139   int len = decode_vint_size(first_byte);
140   if (len == 1) {
141     proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_clientlen, tvb, *offset, byte_count, ENC_BIG_ENDIAN);
142     *offset = (*offset) + byte_count;
143     return first_byte;
144   }
145
146   for  (idx = 0; idx < len-1; idx++) {
147     char b = tvb_get_guint8(tvb, *offset + byte_count);
148     byte_count++;
149     i = i << 8;
150     i = i | (b & 0xFF);
151   }
152   size = ((first_byte < -120 || (first_byte >= -112 && first_byte < 0)) ? (i ^ -1L) : i);
153   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_clientlen, tvb, *offset, byte_count, ENC_BIG_ENDIAN);
154   *offset = (*offset) + byte_count;
155
156   return size;
157 }
158
159 /* dissects a variable length int and then using its value dissects the following string */
160 static void
161 dissect_variable_int_string(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset)
162 {
163   /* Get the variable length int that represents the length of the next feild */
164   int len = dissect_variable_length_long (tvb, hdfsdata_tree, offset);
165
166   /* client id = amount of bytes in previous */
167   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_clientid, tvb, *offset, len, ENC_ASCII|ENC_NA);
168   *offset += len;
169 }
170
171 /* dissects the access tokens that appear at the end of requests.
172  tokens: id, password, kind, service */
173 static void
174 dissect_access_tokens(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset)
175 {
176   int len = 0;
177
178   len = tvb_get_guint8(tvb, *offset);
179   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN);
180   *offset += 1;
181
182   /* token id = amount of bytes in previous */
183   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenid, tvb, *offset, len, ENC_ASCII|ENC_NA);
184   *offset += len;
185
186   len = tvb_get_guint8(tvb, *offset);
187   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN);
188   *offset += 1;
189
190   /* token password = amount of bytes in previous */
191   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenpassword, tvb, *offset, len, ENC_ASCII|ENC_NA);
192   *offset += len;
193
194   len = tvb_get_guint8(tvb, *offset);
195   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN);
196   *offset += 1;
197
198   /* token type = amount of bytes in previous */
199   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokentype, tvb, *offset, len, ENC_ASCII|ENC_NA);
200   *offset += len;
201
202   len = tvb_get_guint8(tvb, *offset);
203   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN);
204   *offset += 1;
205
206   /* token service = amount of bytes in previous; */
207   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenservice, tvb, *offset, len, ENC_ASCII|ENC_NA);
208   *offset += len;
209 }
210
211 /* handles parsing read response packets */
212 static void
213 dissect_read_response(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int offset)
214 {
215   int len = 0;
216
217   /* 4 bytes = data length */
218   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_datalength, tvb, offset, 4, ENC_BIG_ENDIAN);
219   offset += 4;
220
221   /* 8 bytes = in block offset */
222   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_inblockoffset, tvb, offset, 8, ENC_BIG_ENDIAN);
223   offset += 8;
224
225   /* 8 bytes = sequence number */
226   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_seqnum, tvb, offset, 8, ENC_BIG_ENDIAN);
227   offset += 8;
228
229   /* 1 byte = last packet in block */
230   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_last, tvb, offset, 1, ENC_BIG_ENDIAN);
231   offset += 1;
232
233   /* 4 byte = length of data */
234   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_datalen, tvb, offset, 4, ENC_BIG_ENDIAN);
235   offset += 4;
236
237   /* if there is a crc checksum it is 8* the length of the data * checksum size / chunksize */
238   if (tvb_get_guint8(tvb, 2) == CRC) {
239     len = (int)(CRC_SIZE * tvb_get_ntohl(tvb, offset - 4) *
240       tvb_get_ntohl(tvb, offset - 8) / tvb_get_ntohl(tvb, CHUNKSIZE_START));
241   }
242
243   /* the rest of bytes (usually 4) = crc32 code */
244   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_crc32, tvb, offset, len, ENC_BIG_ENDIAN);
245   /* offset += len; */
246 }
247
248 /* dissects the first packet of the read response */
249 static void
250 dissect_read_response_start(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int offset) {
251   /* 2 bytes = status code */
252   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_status, tvb, offset, 2, ENC_BIG_ENDIAN);
253   offset += 2;
254
255   /* checksum type = 1 byte. 1 = crc32, 0 = null */
256   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_checksumtype, tvb, offset, 1, ENC_BIG_ENDIAN);
257   offset += 1;
258
259   /* 4 bytes = chunksize */
260   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunksize, tvb, offset, 4, ENC_BIG_ENDIAN);
261   offset += 4;
262
263   /* 8 bytes = chunk offset */
264   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunkoffset, tvb, offset, 8, ENC_BIG_ENDIAN);
265   /* offset += 8; */
266 }
267
268 /* dissects the fields specific to a read request */
269 static void
270 dissect_read_request(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset)
271 {
272
273   /* 8 bytes = start offset */
274   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_startoffset, tvb, *offset, 8, ENC_BIG_ENDIAN);
275   *offset += 8;
276
277   /* 8 bytes = block length */
278   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_blocklen, tvb, *offset, 8, ENC_BIG_ENDIAN);
279   *offset += 8;
280
281 }
282
283 /* dissects the fields specific to a write request */
284 static void
285 dissect_write_request(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset)
286 {
287   /* 4 bytes = number of nodes in pipeline */
288   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_pipelinenum, tvb, *offset, 4, ENC_BIG_ENDIAN);
289   *offset += 4;
290
291   /* 1 bytes = recovery boolean */
292   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_recovery, tvb, *offset, 1, ENC_BIG_ENDIAN);
293   *offset += 1;
294 }
295
296 /* dissects the fields specific to a write request */
297 static void
298 dissect_write_request_end(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset)
299 {
300   int i = 0;
301   int len = 0;
302
303   /* 1 bytes = source node */
304   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_sourcenode, tvb, *offset, 1, ENC_BIG_ENDIAN);
305   *offset += 1;
306
307   /* 4 bytes = number of nodes currently in the pipeline (usually just -1 of before) */
308   len = tvb_get_ntohl(tvb, *offset);
309   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_currentpipeline, tvb, *offset, 4, ENC_BIG_ENDIAN);
310   *offset += 4;
311
312   /* varible length sequence of node objects */
313   for (i = 0; i < len; i++) {
314     proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_node, tvb, *offset, 4, ENC_BIG_ENDIAN);
315     *offset += 4;
316   }
317 }
318
319 /* dissects the beginning of the read and write request messages */
320 static int
321 dissect_header(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int* offset){
322
323   int command = 0;
324
325   /* 2 bytes = protocol version */
326   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_version, tvb, *offset, 2, ENC_BIG_ENDIAN);
327   *offset += 2;
328
329   /* 1 byte = command */
330   command = tvb_get_guint8(tvb, *offset);
331   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_cmd, tvb, *offset, 1, ENC_BIG_ENDIAN);
332   *offset += 1;
333
334   /* 8 bytes = block id */
335   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_blockid, tvb, *offset, 8, ENC_BIG_ENDIAN);
336   *offset += 8;
337
338   /* 8 bytes = timestamp */
339   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_timestamp, tvb, *offset, 8, ENC_BIG_ENDIAN);
340   *offset += 8;
341
342   return command;
343 }
344
345 /* decodes the write response messages */
346 static void
347 dissect_write_response(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int offset)
348 {
349   /* 4 bytes = packetsize */
350   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_packetsize, tvb, offset, 4, ENC_BIG_ENDIAN);
351   offset += 4;
352
353   /* 8 bytes = offset in block */
354   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_startoffset, tvb, offset, 8, ENC_BIG_ENDIAN);
355   offset += 8;
356
357   /* 8 bytes = sequence number */
358   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_seqnum, tvb, offset, 8, ENC_BIG_ENDIAN);
359   offset += 8;
360
361   /* 1 bytes = last packet */
362   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_last, tvb, offset, 1, ENC_BIG_ENDIAN);
363   offset += 1;
364
365   /* 4 bytes = chunk length */
366   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunklength, tvb, offset, 4, ENC_BIG_ENDIAN);
367   offset += 4;
368
369   /* 8 bytes = crc code */
370   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_crc64, tvb, offset, 8, ENC_BIG_ENDIAN);
371   offset += 8;
372
373   /* add the rest -> RESPONSE_DATA */
374   proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_rest, tvb, offset, (tvb_reported_length(tvb)) - offset, ENC_ASCII|ENC_NA);
375    /* offset += (tvb_reported_length(tvb)); */
376 }
377
378 /* determine PDU length of protocol  */
379 static guint
380 get_hdfsdata_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
381 {
382   /* get data packet len, add FIRST_READ_FRAGMENT_LEN for first fragment (before len),
383      SECOND_READ_FRAGMENT_LEN for second fragment (incl len), subtract 4 for length itself. */
384
385   if (tvb_reported_length(tvb) <= 4 || tvb_reported_length(tvb) == END_PACKET_LEN
386     || tvb_get_ntohl(tvb, 0) == tvb_reported_length(tvb) - WRITE_RESP_HEAD_LEN
387     || (tvb_reported_length(tvb) >= MIN_READ_REQ && tvb_get_guint8(tvb, 2) == READ_OP)
388     || (tvb_reported_length(tvb) >= MIN_WRITE_REQ && tvb_get_guint8(tvb, 2) == WRITE_OP)) {
389
390     return tvb_reported_length(tvb);
391   }
392   return tvb_get_ntohl(tvb, offset + FIRST_READ_FRAGMENT_LEN) +
393     FIRST_READ_FRAGMENT_LEN + SECOND_READ_FRAGMENT_LEN - LAST_READ_FRAGMENT_LEN;
394 }
395
396 /* This method dissects fully reassembled messages */
397 static void
398 dissect_hdfsdata_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
399 {
400   int offset = 0;
401
402   col_set_str(pinfo->cinfo, COL_PROTOCOL, "HDFSDATA");
403   /* Clear out stuff in the info column */
404   col_set_str(pinfo->cinfo, COL_INFO, "HDFS Data");
405
406
407   if (tree) {
408     proto_item *ti = NULL;
409     proto_tree *hdfsdata_tree = NULL;
410
411     ti = proto_tree_add_item(tree, proto_hdfsdata, tvb, offset, -1, ENC_NA);
412     hdfsdata_tree = proto_item_add_subtree(ti, ett_hdfsdata);
413
414     /* if only 1 bytes packet must just contain just the pipeline status */
415     if ((tvb_reported_length(tvb)) == PIPELINE_LEN) {
416
417       /* 1 bytes = pipeline status */
418       proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_pipelinestatus, tvb, offset, PIPELINE_LEN, ENC_BIG_ENDIAN);
419
420     /* if only 2 bytes packet must just contain just a status code */
421     } else if ((tvb_reported_length(tvb)) == STATUS_LEN) {
422       /* 2 bytes = status code */
423       proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_status, tvb, offset, STATUS_LEN, ENC_BIG_ENDIAN);
424
425     /* if it is 4 bytes long it must be a finish request packet */
426     } else if ((tvb_reported_length(tvb)) == FINISH_REQ_LEN) {
427       proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_end, tvb, offset, 4, ENC_BIG_ENDIAN);
428
429     /* read response packet */
430     } else if (tvb_reported_length(tvb) >= READ_RESP_HEAD_LEN && tvb_reported_length(tvb) ==
431       tvb_get_ntohl(tvb, FIRST_READ_FRAGMENT_LEN) +
432       FIRST_READ_FRAGMENT_LEN + SECOND_READ_FRAGMENT_LEN - LAST_READ_FRAGMENT_LEN){
433
434       dissect_read_response_start(tvb, hdfsdata_tree, offset);
435       offset += FIRST_READ_FRAGMENT_LEN;
436
437       dissect_read_response(tvb, hdfsdata_tree, offset);
438       offset+= SECOND_READ_FRAGMENT_LEN;
439
440       /* This message just contains data so we can display it all as one block */
441
442       proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_rest, tvb, offset, (tvb_reported_length(tvb)) - offset, ENC_ASCII|ENC_NA);
443
444     } else {
445
446       guint8 op = tvb_get_guint8(tvb, 2);
447
448       /* READ  request */
449       if ((tvb_reported_length(tvb)) >= MIN_READ_REQ && op == READ_OP) {
450         dissect_header(tvb, hdfsdata_tree, &offset);
451         dissect_read_request(tvb, hdfsdata_tree, &offset);
452         dissect_variable_int_string(tvb, hdfsdata_tree, &offset);
453         dissect_access_tokens(tvb, hdfsdata_tree, &offset);
454
455       /* WRITE request */
456       } else if ((tvb_reported_length(tvb)) >= MIN_WRITE_REQ && op == WRITE_OP) {
457         dissect_header(tvb, hdfsdata_tree, &offset);
458         dissect_write_request(tvb, hdfsdata_tree, &offset);
459         dissect_variable_int_string(tvb, hdfsdata_tree, &offset);
460         dissect_write_request_end(tvb, hdfsdata_tree, &offset);
461         dissect_access_tokens(tvb, hdfsdata_tree, &offset);
462
463         /* checksum type = 1 byte. 1 = crc32, 0 = null */
464         proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_checksumtype, tvb, offset, 1, ENC_BIG_ENDIAN);
465         offset += 1;
466
467         /* 4 bytes = chunksize */
468         proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunksize, tvb, offset, 4, ENC_BIG_ENDIAN);
469
470       /* write responses store the data length in the first 4 bytes. This length does not
471          include 21 bits of header */
472       } else if (tvb_reported_length(tvb) >= 4 && tvb_get_ntohl(tvb, 0) ==
473         tvb_reported_length(tvb) - WRITE_RESP_HEAD_LEN) {
474
475         dissect_write_response(tvb, hdfsdata_tree, offset);
476
477       } else {
478         /* This message contains some form of data that we have not successfully been able to
479            pattern match and catagorize. Display all of it as data. */
480         proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_rest, tvb, offset, (tvb_reported_length(tvb)), ENC_ASCII|ENC_NA);
481       }
482     }
483   }
484 }
485
486 static void
487 dissect_hdfsdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
488 {
489   int frame_header_len = 0;
490
491   gboolean need_reassemble = FALSE;
492   guint8 op = 0;
493   gboolean only_packet = tvb_reported_length(tvb) == 1 || (tvb_reported_length(tvb) == 2 &&
494     tvb_get_ntohs(tvb, 0) == STATUS_SUCCESS);
495
496   if (tvb_reported_length(tvb) >= 3)
497     op = tvb_get_guint8(tvb, 2);
498
499   if (!only_packet && tvb_reported_length(tvb) != 4 && !(tvb_reported_length(tvb) >= MIN_READ_REQ && op == READ_OP) &&
500     !(tvb_reported_length(tvb) >= MIN_WRITE_REQ && op == WRITE_OP) && !(tvb_reported_length(tvb) == END_PACKET_LEN &&
501     !tvb_get_ntohl(tvb, 0) && !tvb_get_ntohl(tvb, 4))) {
502
503     need_reassemble = TRUE;
504   }
505
506   /* setting the header size for the different types of packets */
507   if (only_packet || tvb_reported_length(tvb) == END_PACKET_LEN) {
508     frame_header_len = tvb_reported_length(tvb);
509
510   } else if (tvb_reported_length(tvb) == FIRST_READ_FRAGMENT_LEN ||(tvb_reported_length(tvb) >= MIN_READ_REQ &&
511     op == READ_OP && !((tvb_reported_length(tvb)) == 2 && !tvb_get_ntohs(tvb, 0)))) {
512
513     frame_header_len = READ_RESP_HEAD_LEN;
514
515   } else if (tvb_reported_length(tvb) >= MIN_WRITE_REQ && op == WRITE_OP) {
516     frame_header_len = WRITE_REQ_HEAD_LEN;
517   }
518
519   tcp_dissect_pdus(tvb, pinfo, tree, need_reassemble, frame_header_len, get_hdfsdata_message_len, dissect_hdfsdata_message);
520 }
521
522 /* registers the protcol with the given names */
523 void
524 proto_register_hdfsdata(void)
525 {
526     static hf_register_info hf[] = {
527
528   /* list of all options for dissecting the protocol */
529
530   /*************************************************
531   Read request
532   **************************************************/
533   { &hf_hdfsdata_version,
534     { "HDFSDATA protocol version", "hdfsdata.version",
535       FT_UINT16, BASE_DEC,
536       NULL, 0x0,
537       NULL, HFILL }
538   },
539   { &hf_hdfsdata_cmd,
540     { "HDFSDATA command", "hdfsdata.cmd",
541       FT_UINT8, BASE_DEC,
542       NULL, 0x0,
543       NULL, HFILL }
544   },
545   { &hf_hdfsdata_blockid,
546     { "HDFSDATA block id", "hdfsdata.blockid",
547       FT_UINT64, BASE_DEC,
548       NULL, 0x0,
549       NULL, HFILL }
550   },
551   { &hf_hdfsdata_timestamp,
552     { "HDFSDATA timestamp", "hdfsdata.timestamp",
553       FT_UINT64, BASE_DEC,
554       NULL, 0x0,
555       NULL, HFILL }
556   },
557   /***
558   Read specific
559   ***/
560   { &hf_hdfsdata_startoffset,
561     { "HDFSDATA start offset" , "hdfsdata.startoffset",
562       FT_UINT64, BASE_DEC,
563       NULL, 0x0,
564       NULL, HFILL }
565   },
566   { &hf_hdfsdata_blocklen,
567     { "HDFSDATA block length", "hdfsdata.blocklen",
568       FT_UINT64, BASE_DEC,
569       NULL, 0x0,
570       NULL, HFILL }
571   },
572   /***
573   Write specific
574   ***/
575   { &hf_hdfsdata_pipelinenum,
576     { "HDFSDATA number in pipeline", "hdfsdata.pipelinenum",
577       FT_UINT32, BASE_DEC,
578       NULL, 0x0,
579       NULL, HFILL }
580   },
581   { &hf_hdfsdata_recovery,
582     { "HDFSDATA recovery boolean", "hdfsdata.recovery",
583       FT_UINT8, BASE_DEC,
584       NULL, 0x0,
585       NULL, HFILL }
586   },
587   { &hf_hdfsdata_sourcenode,
588     { "HDFSDATA source node", "hdfsdata.sourcenode",
589       FT_UINT8, BASE_DEC,
590       NULL, 0x0,
591       NULL, HFILL }
592   },
593   { &hf_hdfsdata_currentpipeline,
594     { "HDFSDATA current number of nodes in the pipeline", "hdfsdata.currentpipline",
595       FT_UINT32, BASE_DEC,
596       NULL, 0x0,
597       NULL, HFILL }
598   },
599   { &hf_hdfsdata_node,
600     { "HDFSDATA node object", "hdfsdata.node",
601       FT_UINT32, BASE_DEC,
602       NULL, 0x0,
603       NULL, HFILL }
604   },
605   /***
606   Var length
607   **/
608   { &hf_hdfsdata_clientlen,
609     { "HDFSDATA client id length", "hdfsdata.clientlen",
610       FT_UINT8, BASE_DEC,
611       NULL, 0x0,
612       NULL, HFILL }
613   },
614   { &hf_hdfsdata_clientid,
615     { "HDFSDATA client id", "hdfsdata.clientid",
616       FT_STRING, BASE_NONE,
617       NULL, 0x0,
618       NULL, HFILL }
619   },
620   { &hf_hdfsdata_end,
621     { "HDFSDATA end data request", "hdfsdata.end",
622       FT_UINT32, BASE_DEC,
623       NULL, 0x0,
624       NULL, HFILL }
625   },
626   /*************************************************
627   Access tokens
628   **************************************************/
629   { &hf_hdfsdata_tokenlen,
630     { "HDFSDATA access token length", "hdfsdata.tokenlen",
631       FT_UINT8, BASE_DEC,
632       NULL, 0x0,
633       NULL, HFILL }
634   },
635   { &hf_hdfsdata_tokenid,
636     { "HDFSDATA access token ID", "hdfsdata.tokenid",
637       FT_STRING, BASE_NONE,
638       NULL, 0x0,
639       NULL, HFILL }
640   },
641   { &hf_hdfsdata_tokenpassword,
642     { "HDFSDATA access token password", "hdfsdata.tokenpassword",
643       FT_STRING, BASE_NONE,
644       NULL, 0x0,
645       NULL, HFILL }
646   },
647   { &hf_hdfsdata_tokentype,
648     { "HDFSDATA access token type", "hdfsdata.tokentype",
649       FT_STRING, BASE_NONE,
650       NULL, 0x0,
651       NULL, HFILL }
652   },
653   { &hf_hdfsdata_tokenservice,
654     { "HDFSDATA access token service", "hdfsdata.tokenservice",
655       FT_STRING, BASE_NONE,
656       NULL, 0x0,
657       NULL, HFILL }
658   },
659   /***********************************************
660   Responses 1
661   ***********************************************/
662   { &hf_hdfsdata_status,
663     { "HDFSDATA status code", "hdfsdata.status",
664       FT_UINT16, BASE_DEC,
665       NULL, 0x0,
666       NULL, HFILL }
667   },
668   { &hf_hdfsdata_checksumtype,
669     { "HDFSDATA checksum type", "hdfsdata.checksumtype",
670       FT_UINT8, BASE_DEC,
671       NULL, 0x0,
672       NULL, HFILL }
673   },
674   { &hf_hdfsdata_chunksize,
675     { "HDFSDATA chunk size", "hdfsdata.chunksize",
676       FT_UINT16, BASE_DEC,
677       NULL, 0x0,
678       NULL, HFILL }
679   },
680   { &hf_hdfsdata_chunkoffset,
681     { "HDFSDATA chunk offset", "hdfsdata.chunkoffset",
682       FT_UINT64, BASE_DEC,
683       NULL, 0x0,
684       NULL, HFILL }
685   },
686   /***********************************************
687   Responses 2
688   ***********************************************/
689   { &hf_hdfsdata_datalength,
690     { "HDFSDATA length of data", "hdfsdata.datalength",
691       FT_UINT32, BASE_DEC,
692       NULL, 0x0,
693       NULL, HFILL }
694   },
695   { &hf_hdfsdata_inblockoffset,
696     { "HDFSDATA in block offset", "hdfsdata.inblockoffset",
697       FT_UINT64, BASE_DEC,
698       NULL, 0x0,
699       NULL, HFILL }
700   },
701   { &hf_hdfsdata_seqnum,
702     { "HDFSDATA sequence number", "hdfsdata.seqnum",
703       FT_UINT64, BASE_DEC,
704       NULL, 0x0,
705       NULL, HFILL }
706   },
707   { &hf_hdfsdata_last,
708     { "HDFSDATA last packet in block", "hdfsdata.last",
709       FT_INT8, BASE_DEC,
710       NULL, 0x0,
711       NULL, HFILL }
712   },
713   { &hf_hdfsdata_datalen,
714     { "HDFSDATA length of data", "hdfsdata.datalen",
715       FT_INT32, BASE_DEC,
716       NULL, 0x0,
717       NULL, HFILL }
718   },
719   { &hf_hdfsdata_crc32,
720     { "HDFSDATA crc32 checksum", "hdfsdata.crc32",
721       FT_INT32, BASE_DEC,
722       NULL, 0x0,
723       NULL, HFILL }
724   },
725   /***********************************************
726   Responses 3
727   ***********************************************/
728   { &hf_hdfsdata_rest,
729     { "HDFSDATA data", "hdfsdata.rest",
730       FT_STRING, BASE_NONE,
731       NULL, 0x0,
732       NULL, HFILL }
733   },
734   /***********************************************
735   Write Response 1
736   ***********************************************/
737   { &hf_hdfsdata_packetsize,
738     { "HDFSDATA packet size", "hdfsdata.packetsize",
739       FT_UINT32, BASE_DEC,
740       NULL, 0x0,
741       NULL, HFILL }
742   },
743   { &hf_hdfsdata_chunklength,
744     { "HDFSDATA chunk length", "hdfsdata.chunklength",
745       FT_UINT32, BASE_DEC,
746       NULL, 0x0,
747       NULL, HFILL }
748   },
749   { &hf_hdfsdata_crc64,
750     { "HDFSDATA crc64 checksum", "hdfsdata.crc64",
751       FT_INT64, BASE_DEC,
752       NULL, 0x0,
753       NULL, HFILL }
754   },
755   { &hf_hdfsdata_pipelinestatus,
756     { "HDFSDATA pipeline status", "hdfsdata.pipelinestatus",
757       FT_INT8, BASE_DEC,
758       NULL, 0x0,
759       NULL, HFILL }
760   },
761     };
762
763     /* Setup protocol subtree array */
764     static gint *ett[] = {
765         &ett_hdfsdata
766     };
767
768     module_t *hdfsdata_module;
769
770     proto_hdfsdata = proto_register_protocol (
771       "HDFSDATA Protocol", /* name       */
772       "HDFSDATA",      /* short name */
773       "hdfsdata"       /* abbrev     */
774       );
775
776     proto_register_field_array(proto_hdfsdata, hf, array_length(hf));
777     proto_register_subtree_array(ett, array_length(ett));
778
779     hdfsdata_module = prefs_register_protocol(proto_hdfsdata, proto_reg_handoff_hdfsdata);
780
781     prefs_register_uint_preference(hdfsdata_module,
782                                    "tcp.port",
783                                    "TCP port for HDFSDATA",
784                                    "Set the TCP port for HDFSDATA",
785                                    10,
786                                    &tcp_port);
787
788     register_dissector("hdfsdata", dissect_hdfsdata, proto_hdfsdata);
789 }
790
791 /* registers handoff */
792 void
793 proto_reg_handoff_hdfsdata(void)
794 {
795   static gboolean initialized = FALSE;
796     static dissector_handle_t hdfsdata_handle;
797     static guint saved_tcp_port;
798
799     if (!initialized) {
800         hdfsdata_handle = create_dissector_handle(dissect_hdfsdata, proto_hdfsdata);
801         dissector_add_handle("tcp.port", hdfsdata_handle);  /* for "decode as" */
802         initialized = TRUE;
803     } else if (saved_tcp_port != 0) {
804         dissector_delete_uint("tcp.port", saved_tcp_port, hdfsdata_handle);
805     }
806
807     if (tcp_port != 0) {
808         dissector_add_uint("tcp.port", tcp_port, hdfsdata_handle);
809     }
810
811     saved_tcp_port = tcp_port;
812 }
813 /*
814  * Editor modelines
815  *
816  * Local Variables:
817  * c-basic-offset: 2
818  * tab-width: 8
819  * indent-tabs-mode: nil
820  * End:
821  *
822  * ex: set shiftwidth=2 tabstop=8 expandtab:
823  * :indentSize=2:tabSize=8:noTabs=true:
824  */