Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-hdfs.c
1 /* packet-hdfs.c
2  * HDFS Protocol and dissectors
3  *
4  * Copyright (c) 2011 by Isilon Systems.
5  *
6  * Author: Allison Obourn <aobourn@isilon.com>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27
28 #include "config.h"
29
30 #include <glib.h>
31
32 #include <epan/packet.h>
33 #include <epan/dissectors/packet-tcp.h>
34 #include <epan/prefs.h>
35
36 void proto_register_hdfs(void);
37 void proto_reg_handoff_hdfs(void);
38
39 #if 0
40 #define NAMENODE_PORT 8020
41 #endif
42
43 #define REQUEST_STR "hrpc"
44
45 #define SEND_DEC 1936027236
46 #define SEND_OFFSET 13
47 #define HEAR_DEC 1214603634
48 #define HEAR_OFFSET 9
49 #define TBEA_DEC 1952605537
50 #define TBEA_OFFSET 5
51 #define T_DEC 116
52 #define T_OFFSET 1
53
54 #define FIRST_READ_FRAGMENT_LEN 15
55 #define SECOND_READ_FRAGMENT_LEN 29
56
57
58 #if 0
59 static const int START = 0;
60 static const int AUTHENTICATION = 1;
61 static const int DATA = 2;
62 #endif
63
64 static guint tcp_port = 0;
65
66 static int proto_hdfs = -1;
67 static int hf_hdfs_pdu_type = -1;
68 static int hf_hdfs_flags = -1;
69 static int hf_hdfs_sequenceno = -1;
70 static int hf_hdfs_packetno = -1;
71 static int hf_hdfs_authlen = -1;
72 static int hf_hdfs_success = -1;
73 static int hf_hdfs_auth = -1;
74 static int hf_hdfs_len = -1;
75 static int hf_hdfs_strcall = -1;
76 static int hf_hdfs_params = -1;
77 static int hf_hdfs_paramtype = -1;
78 static int hf_hdfs_paramval = -1;
79 static int hf_hdfs_paramvalnum = -1;
80 /* static int hf_hdfs_rest = -1; */
81 static int hf_hdfs_fileperm = -1;
82 static int hf_hdfs_blockloc = -1;
83 static int hf_hdfs_endblockloc = -1;
84 static int hf_hdfs_blockgen = -1;
85 static int hf_hdfs_prover = -1;
86 static int hf_hdfs_objname = -1;
87 static int hf_hdfs_filename = -1;
88 static int hf_hdfs_blockcount = -1;
89 static int hf_hdfs_ownername = -1;
90 static int hf_hdfs_groupname = -1;
91 static int hf_hdfs_namelenone = -1;
92 static int hf_hdfs_namelentwo = -1;
93 static int hf_hdfs_accesstime = -1;
94 static int hf_hdfs_modtime = -1;
95 static int hf_hdfs_blockrep = -1;
96 static int hf_hdfs_isdir = -1;
97 static int hf_hdfs_blocksize = -1;
98 static int hf_hdfs_filelen = -1;
99 static int hf_hdfs_construct = -1;
100 static int hf_hdfs_hostname = -1;
101 static int hf_hdfs_rackloc = -1;
102 static int hf_hdfs_adminstate = -1;
103 static int hf_hdfs_activecon = -1;
104 static int hf_hdfs_lastupdate = -1;
105 static int hf_hdfs_remaining = -1;
106 static int hf_hdfs_dfsused = -1;
107 static int hf_hdfs_capacity = -1;
108 static int hf_hdfs_ipcport = -1;
109 static int hf_hdfs_infoport = -1;
110 static int hf_hdfs_storageid = -1;
111 static int hf_hdfs_datanodeid = -1;
112 static int hf_hdfs_locations = -1;
113 static int hf_hdfs_offset = -1;
114 static int hf_hdfs_corrupt = -1;
115 static int hf_hdfs_identifier = -1;
116 static int hf_hdfs_password = -1;
117 static int hf_hdfs_kind = -1;
118 static int hf_hdfs_service = -1;
119
120 static gint ett_hdfs = -1;
121
122 static dissector_handle_t hdfs_handle;
123
124 /* Parses the parameters of a function.
125    Parses the type length which is always in 2 bytes.
126    Next the type which is the previously found length.
127    If this type is variable length it then reads the length of the data
128    from 2 bytes and then the data.
129    Otherwise reads just the data. */
130 static void
131 dissect_params (tvbuff_t *tvb, proto_tree *hdfs_tree, guint offset, int params) {
132
133     guint length;
134     int i =  0;
135     const guint8* type_name;
136     for (i = 0; i < params; i++) {
137
138         /* get length that we just dissected */
139         length = tvb_get_ntohs(tvb, offset);
140
141         /* 2 bytes = parameter type length */
142         proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
143         offset += 2;
144
145         /* length bytes = parameter type */
146         proto_tree_add_item(hdfs_tree, hf_hdfs_paramtype, tvb, offset, length, ENC_ASCII|ENC_NA);
147         offset += length;
148
149         if (offset >= length && (!tvb_memeql(tvb, offset - length, "long", length) || !tvb_memeql(tvb, offset - length, "int", length) ||
150                                  !tvb_memeql(tvb, offset - length, "short", length) || !tvb_memeql(tvb, offset - length, "char", length) ||
151                                  !tvb_memeql(tvb, offset - length, "byte", length) || !tvb_memeql(tvb, offset - length, "float", length)
152                                  || !tvb_memeql(tvb, offset - length, "double", length) || !tvb_memeql(tvb, offset - length, "boolean", length))) {
153
154             if (!tvb_memeql(tvb, offset - length, "boolean", length)) {
155                 length = 1;
156             } else if (!tvb_memeql(tvb, offset - length, "short", length)) {
157                 length = 2;
158             } else {
159                 length = sizeof(type_name);
160             }
161
162             proto_tree_add_item(hdfs_tree, hf_hdfs_paramvalnum, tvb, offset, length, ENC_BIG_ENDIAN);
163             offset += length;
164
165         } else {
166             /* get length */
167             length = tvb_get_ntohs(tvb, offset);
168
169             /* 2 bytes = parameter value length */
170             proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
171             offset += 2;
172
173             proto_tree_add_item(hdfs_tree, hf_hdfs_paramval, tvb, offset, length, ENC_ASCII|ENC_NA);
174             offset += length;
175
176             if (!tvb_memeql(tvb, offset - length, "org.apache.hadoop.fs.permission.FsPermission", length)) {
177                 proto_tree_add_item(hdfs_tree, hf_hdfs_fileperm, tvb, offset, 2, ENC_BIG_ENDIAN);
178                 offset += 2;
179             }
180         }
181     }
182 }
183
184
185 /* Dissects a data packet of the form:
186    method name length   : 2B
187    method name          : above value
188    number of parameters         : 4B
189     -- list of parameters the length of above --
190    parameter type length        : 2B
191    parameter type               : above value
192    -- if the type is variable size --
193    parameter value length       : 2B
194    parameter value              : above value
195    -- otherwise --
196    parameter value      : length of the type  */
197 static void
198 dissect_data (tvbuff_t *tvb, proto_tree *hdfs_tree, guint offset) {
199     int params = 0;
200     guint length = 0;
201
202     /* get length */
203     length = tvb_get_ntohs(tvb, offset);
204
205     /* method name length = 2 B */
206     proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
207     offset += 2;
208
209     /* length bytes = method name */
210     proto_tree_add_item(hdfs_tree, hf_hdfs_strcall, tvb, offset, length, ENC_ASCII|ENC_NA);
211     offset += length;
212
213     /* we only want to parse the packet if it is not a heartbeat (random looking numbers are the decimal
214        representation of sendHeartbeat */
215     if (!(tvb_get_ntohl(tvb, offset - SEND_OFFSET) == SEND_DEC && tvb_get_ntohl(tvb, offset - HEAR_OFFSET) == HEAR_DEC &&
216           tvb_get_ntohl(tvb, offset - TBEA_OFFSET) == TBEA_DEC && tvb_get_guint8(tvb, offset - T_OFFSET) == T_DEC)) {
217
218         /* get number of params */
219         params = tvb_get_ntohl(tvb, offset);
220
221         /* 4 bytes = # of parameters */
222         proto_tree_add_item(hdfs_tree, hf_hdfs_params, tvb, offset, 4, ENC_BIG_ENDIAN);
223         offset += 4;
224
225         /* go through all params and dissect their type length, type, value length and value */
226         dissect_params (tvb, hdfs_tree, offset, params);
227     }
228 }
229
230 /*
231 response to a get protocol version message
232 contains a type length, type name and the value
233 */
234 static int
235 dissect_resp_long (tvbuff_t *tvb, proto_tree *hdfs_tree, int offset) {
236     /* get length that we just dissected */
237     int length = tvb_get_ntohs(tvb, offset);
238
239     /* 2 bytes = parameter type length */
240     proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
241     offset += 2;
242
243     /* length bytes = parameter type */
244     proto_tree_add_item(hdfs_tree, hf_hdfs_paramtype, tvb, offset, length, ENC_ASCII|ENC_NA);
245     offset += length;
246
247     /* the value */
248     proto_tree_add_item(hdfs_tree, hf_hdfs_prover, tvb, offset, 8, ENC_BIG_ENDIAN);
249     offset += 8;
250
251     return offset;
252 }
253
254 /*
255 Response to a file status message
256 */
257 static int
258 dissect_resp_filestatus (tvbuff_t *tvb, proto_tree *hdfs_tree, int offset) {
259
260     int length;
261
262     /* file status */
263     proto_tree_add_item(hdfs_tree, hf_hdfs_fileperm, tvb, offset, 2, ENC_BIG_ENDIAN);
264     offset += 2;
265
266     /* get length */
267     length = tvb_get_ntohs(tvb, offset);
268
269     /* 2 bytes = file name length */
270     proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
271     offset += 2;
272
273     /* file name */
274     proto_tree_add_item(hdfs_tree, hf_hdfs_filename, tvb, offset, length, ENC_ASCII|ENC_NA);
275     offset += length;
276
277
278     /* 8 file size / end location  */
279     proto_tree_add_item(hdfs_tree, hf_hdfs_endblockloc, tvb, offset, 8, ENC_BIG_ENDIAN);
280     offset += 8;
281
282     /* is directory */
283     proto_tree_add_item(hdfs_tree, hf_hdfs_isdir, tvb, offset, 1, ENC_BIG_ENDIAN);
284     offset += 1;
285
286     /* block replication factor */
287     proto_tree_add_item(hdfs_tree, hf_hdfs_blockrep, tvb, offset, 2, ENC_BIG_ENDIAN);
288     offset += 2;
289
290     /* block size */
291     proto_tree_add_item(hdfs_tree, hf_hdfs_blocksize, tvb, offset, 8, ENC_BIG_ENDIAN);
292     offset += 8;
293
294     /* modified time */
295     proto_tree_add_item(hdfs_tree, hf_hdfs_modtime, tvb, offset, 8, ENC_BIG_ENDIAN);
296     offset += 8;
297
298     /* access time */
299     proto_tree_add_item(hdfs_tree, hf_hdfs_accesstime, tvb, offset, 8, ENC_BIG_ENDIAN);
300     offset += 8;
301
302     /* 2 of file permissions */
303     proto_tree_add_item(hdfs_tree, hf_hdfs_fileperm, tvb, offset, 2, ENC_BIG_ENDIAN);
304     offset += 2;
305
306
307     /* get length */
308     length = tvb_get_guint8 (tvb, offset);
309
310     /* owner name length */
311     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
312     offset += 1;
313
314     /* owner name */
315     proto_tree_add_item(hdfs_tree, hf_hdfs_ownername, tvb, offset, length, ENC_ASCII|ENC_NA);
316     offset += length;
317
318     /* get length */
319     length = tvb_get_guint8 (tvb, offset);
320
321     /* group name length */
322     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
323     offset += 1;
324
325     /* group name */
326     proto_tree_add_item(hdfs_tree, hf_hdfs_groupname, tvb, offset, length, ENC_ASCII|ENC_NA);
327     offset += length;
328
329     return offset;
330 }
331
332
333 /*
334 Response to the get block info message
335 parses the sent back information about each blcok
336 */
337 static int
338 dissect_block_info (tvbuff_t *tvb, proto_tree *hdfs_tree, int offset) {
339
340     int length;
341
342     length = tvb_get_guint8(tvb, offset);
343
344     /* identifier length */
345     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
346     offset += 1;
347
348     /* identifier */
349     proto_tree_add_item(hdfs_tree, hf_hdfs_identifier, tvb, offset, length, ENC_ASCII|ENC_NA);
350     offset += length;
351
352     length = tvb_get_guint8(tvb, offset);
353
354     /* password length */
355     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
356     offset += 1;
357
358     /* password */
359     proto_tree_add_item(hdfs_tree, hf_hdfs_password, tvb, offset, length, ENC_ASCII|ENC_NA);
360     offset += length;
361
362     length = tvb_get_guint8(tvb, offset);
363
364     /* kind length */
365     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
366     offset += 1;
367
368     /* kind */
369     proto_tree_add_item(hdfs_tree, hf_hdfs_kind, tvb, offset, length, ENC_ASCII|ENC_NA);
370     offset += length;
371
372     length = tvb_get_guint8(tvb, offset);
373
374     /* service length */
375     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
376     offset += 1;
377
378     /* service */
379     proto_tree_add_item(hdfs_tree, hf_hdfs_service, tvb, offset, length, ENC_ASCII|ENC_NA);
380     offset += length;
381
382     /* corrupt */
383     proto_tree_add_item(hdfs_tree, hf_hdfs_corrupt, tvb, offset, 1, ENC_BIG_ENDIAN);
384     offset += 1;
385
386     /* offset */
387     proto_tree_add_item(hdfs_tree, hf_hdfs_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
388     offset += 8;
389
390
391     /* block info section */
392
393     /* block location */
394     proto_tree_add_item(hdfs_tree, hf_hdfs_blockloc, tvb, offset, 8, ENC_BIG_ENDIAN);
395     offset += 8;
396
397     /* block size */
398     proto_tree_add_item(hdfs_tree, hf_hdfs_blocksize, tvb, offset, 8, ENC_BIG_ENDIAN);
399     offset += 8;
400
401     /* gen id 8 */
402     proto_tree_add_item(hdfs_tree, hf_hdfs_blockgen, tvb, offset, 8, ENC_BIG_ENDIAN);
403     offset += 8;
404
405     /* locations */
406     proto_tree_add_item(hdfs_tree, hf_hdfs_locations, tvb, offset, 4, ENC_BIG_ENDIAN);
407     offset += 4;
408
409
410     /* address section */
411
412     /* get length */
413     length = tvb_get_ntohs(tvb, offset);
414
415     /* length of addr */
416     proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
417     offset += 2;
418
419     /* datanode id */
420     proto_tree_add_item(hdfs_tree, hf_hdfs_datanodeid, tvb, offset, length, ENC_ASCII|ENC_NA);
421     offset += length;
422
423     length = tvb_get_ntohs(tvb, offset);
424
425     /* length of addr */
426     proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
427     offset += 2;
428
429     /* storageid */
430     proto_tree_add_item(hdfs_tree, hf_hdfs_storageid, tvb, offset, length, ENC_ASCII|ENC_NA);
431     offset += length;
432
433     /* info port */
434     proto_tree_add_item(hdfs_tree, hf_hdfs_infoport, tvb, offset, 2, ENC_BIG_ENDIAN);
435     offset += 2;
436
437
438     /* default name node port */
439     proto_tree_add_item(hdfs_tree, hf_hdfs_ipcport, tvb, offset, 2, ENC_BIG_ENDIAN);
440     offset += 2;
441
442     /* capacity */
443     proto_tree_add_item(hdfs_tree, hf_hdfs_capacity, tvb, offset, 8, ENC_BIG_ENDIAN);
444     offset += 8;
445
446     /* dfs used */
447     proto_tree_add_item(hdfs_tree, hf_hdfs_dfsused, tvb, offset, 8, ENC_BIG_ENDIAN);
448     offset += 8;
449
450     /* remaining */
451     proto_tree_add_item(hdfs_tree, hf_hdfs_remaining, tvb, offset, 8, ENC_BIG_ENDIAN);
452     offset += 8;
453
454     /* last update */
455     proto_tree_add_item(hdfs_tree, hf_hdfs_lastupdate, tvb, offset, 8, ENC_BIG_ENDIAN);
456     offset += 8;
457
458     /* num active connections */
459     proto_tree_add_item(hdfs_tree, hf_hdfs_activecon, tvb, offset, 4, ENC_BIG_ENDIAN);
460     offset += 4;
461
462
463     length = tvb_get_guint8(tvb, offset);
464
465     /* location rack length */
466     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
467     offset += 1;
468
469     /* location rack */
470     proto_tree_add_item(hdfs_tree, hf_hdfs_rackloc, tvb, offset, length, ENC_ASCII|ENC_NA);
471     offset += length;
472
473     length = tvb_get_guint8(tvb, offset);
474
475     /* hostname length */
476     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
477     offset += 1;
478
479     /* hostname */
480     proto_tree_add_item(hdfs_tree, hf_hdfs_hostname, tvb, offset, length, ENC_ASCII|ENC_NA);
481     offset += length;
482
483     length = tvb_get_guint8(tvb, offset);
484
485     /* admin state length */
486     proto_tree_add_item(hdfs_tree, hf_hdfs_namelenone, tvb, offset, 1, ENC_BIG_ENDIAN);
487     offset += 1;
488
489     /* admin state */
490     proto_tree_add_item(hdfs_tree, hf_hdfs_adminstate, tvb, offset, length, ENC_ASCII|ENC_NA);
491     offset += length;
492
493     return offset;
494
495 }
496
497
498
499 /*
500 dissects the response from get block info.
501 */
502 static void
503 dissect_resp_locatedblocks (tvbuff_t *tvb, proto_tree *hdfs_tree, int offset) {
504
505
506     /* file length = 8  */
507     proto_tree_add_item(hdfs_tree, hf_hdfs_filelen, tvb, offset, 8, ENC_BIG_ENDIAN);
508     offset += 8;
509
510     /* under construction = 1  */
511     proto_tree_add_item(hdfs_tree, hf_hdfs_construct, tvb, offset, 1, ENC_BIG_ENDIAN);
512     offset += 1;
513
514     /* number of blocks */
515     proto_tree_add_item(hdfs_tree, hf_hdfs_blockcount, tvb, offset, 4, ENC_BIG_ENDIAN);
516     offset += 4;
517
518     /* dissect info for each block */
519     while (tvb_reported_length(tvb) - offset > 0) {
520         offset = dissect_block_info (tvb, hdfs_tree, offset);
521     }
522
523 }
524
525
526 static int
527 dissect_hdfs_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
528 {
529     guint offset = 0;
530     int success = 0;
531     guint length = 0;
532
533
534     col_set_str(pinfo->cinfo, COL_PROTOCOL, "HDFS");
535     /* Clear out stuff in the info column */
536     col_clear(pinfo->cinfo,COL_INFO);
537
538     if (tree) {
539
540         proto_item *ti = NULL;
541         proto_tree *hdfs_tree = NULL;
542
543         ti = proto_tree_add_item(tree, proto_hdfs, tvb, 0, -1, ENC_NA);
544         hdfs_tree = proto_item_add_subtree(ti, ett_hdfs);
545
546         /* Response */
547         if (pinfo->srcport == tcp_port) {
548             /* 4 bytes = sequence number */
549             proto_tree_add_item(hdfs_tree, hf_hdfs_packetno, tvb, offset, 4, ENC_BIG_ENDIAN);
550             offset += 4;
551
552             /* 4 bytes = status -> 0000 = success, 0001 = error, ffff = fatal */
553             success = tvb_get_ntohl(tvb, offset);
554             proto_tree_add_item(hdfs_tree, hf_hdfs_success, tvb, offset, 4, ENC_BIG_ENDIAN);
555             offset += 4;
556
557             if (success != 0) {
558                 return offset;
559             }
560
561             if (!tvb_memeql(tvb, offset + 2, "long", 4)) {
562                 dissect_resp_long (tvb, hdfs_tree,  offset);
563
564             } else {
565
566                 /* name length = 2 B */
567                 length = tvb_get_ntohs(tvb, offset);
568                 proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
569                 offset += 2;
570
571                 /* length bytes = method name */
572                 proto_tree_add_item(hdfs_tree, hf_hdfs_objname, tvb, offset, length, ENC_ASCII|ENC_NA);
573                 offset += length;
574
575                 /* get length that we just dissected */
576                 length = tvb_get_ntohs(tvb, offset);
577
578                 /* 2 bytes = objects length */
579                 proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
580                 offset += 2;
581
582                 /* length bytes = object name */
583                 proto_tree_add_item(hdfs_tree, hf_hdfs_objname, tvb, offset, length, ENC_ASCII|ENC_NA);
584                 offset += length;
585
586                 /* responses about block location info */
587                 if (!tvb_memeql(tvb, offset - length, "org.apache.hadoop.hdfs.protocol.LocatedBlocks", length)) {
588                     dissect_resp_locatedblocks (tvb, hdfs_tree, offset);
589
590                     /* responses about file statuses */
591                 } else if (!tvb_memeql(tvb, offset - length, "org.apache.hadoop.hdfs.protocol.HdfsFileStatus", length)) {
592                     dissect_resp_filestatus (tvb, hdfs_tree, offset);
593
594                 } else {
595                     /* get length */
596                     length = tvb_get_ntohs(tvb, offset);
597
598                     /* 2 bytes = parameter value length */
599                     proto_tree_add_item(hdfs_tree, hf_hdfs_namelentwo, tvb, offset, 2, ENC_BIG_ENDIAN);
600                     offset += 2;
601
602                     /* the value of the parameter */
603                     proto_tree_add_item(hdfs_tree, hf_hdfs_paramval, tvb, offset, length, ENC_ASCII|ENC_NA);
604                     /*offset += length;*/
605                 }
606             }
607
608             /* Request to namenode */
609         } else {
610
611             /* check the packet length */
612             guint auth = tvb_get_ntohl(tvb, offset);
613
614             /* first setup packet starts with "hrpc" */
615             if (!tvb_memeql(tvb, offset, REQUEST_STR, sizeof(REQUEST_STR) - 1)) {
616
617                 proto_tree_add_item(hdfs_tree, hf_hdfs_sequenceno, tvb, offset, sizeof(REQUEST_STR) - 1, ENC_ASCII|ENC_NA);
618                 offset += (int)sizeof(REQUEST_STR) - 1;
619
620                 proto_tree_add_item(hdfs_tree, hf_hdfs_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
621                 offset += 1;
622
623                 proto_tree_add_item(hdfs_tree, hf_hdfs_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
624                 /*offset += 1;*/
625
626             } else {
627                 /* second authentication packet */
628                 if (auth + 4 != tvb_reported_length(tvb)) {
629
630                     /* authentication length (read out of first 4 bytes) */
631                     length = tvb_get_ntohl(tvb, offset);
632                     proto_tree_add_item(hdfs_tree, hf_hdfs_authlen, tvb, offset, 4, ENC_ASCII|ENC_NA);
633                     offset += 4;
634
635                     /* authentication (length the number we just got) */
636                     proto_tree_add_item(hdfs_tree, hf_hdfs_auth, tvb, offset, length, ENC_ASCII|ENC_NA);
637                     offset += length;
638                 }
639
640                 /* data packets */
641
642                 /* 4 bytes = length */
643                 proto_tree_add_item(hdfs_tree, hf_hdfs_len, tvb, offset, 4, ENC_BIG_ENDIAN);
644                 offset += 4;
645
646                 /* 4 bytes = sequence number */
647                 proto_tree_add_item(hdfs_tree, hf_hdfs_packetno, tvb, offset, 4, ENC_BIG_ENDIAN);
648                 offset += 4;
649
650                 /* dissect packet data */
651                 dissect_data (tvb, hdfs_tree, offset);
652             }
653         }
654     }
655     return tvb_length(tvb);
656 }
657
658 /* determine PDU length of protocol  */
659 static guint get_hdfs_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_)
660 {
661     int len = tvb_reported_length(tvb);
662
663     if (tvb_reported_length(tvb) == 1448 || tvb_reported_length(tvb) == 1321) {
664         len = 150 * tvb_get_ntohs(tvb, 113) + 115 ;
665     }
666
667     return len;
668
669 }
670
671 static int
672 dissect_hdfs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
673 {
674     int frame_header_len = 0;
675     gboolean need_reassemble = FALSE;
676
677     frame_header_len = tvb_reported_length(tvb);
678
679     if (frame_header_len == 1448 || frame_header_len ==  1321) {
680         need_reassemble = TRUE;
681     }
682
683     tcp_dissect_pdus(tvb, pinfo, tree, need_reassemble, frame_header_len, get_hdfs_message_len, dissect_hdfs_message, data);
684     return tvb_length(tvb);
685 }
686
687 /* registers the protcol with the given names */
688 void
689 proto_register_hdfs(void)
690 {
691
692     static hf_register_info hf[] = {
693
694         /* list of all options for dissecting the protocol */
695
696         /*************************************************
697         First packet
698         **************************************************/
699         { &hf_hdfs_sequenceno,
700           { "HDFS protocol type", "hdfs.type",
701             FT_STRING, BASE_NONE,
702             NULL, 0x0,
703             NULL, HFILL }
704         },
705         { &hf_hdfs_pdu_type,
706           { "HDFS protocol version", "hdfs.version",
707             FT_UINT8, BASE_DEC,
708             NULL, 0x0,
709             NULL, HFILL }
710         },
711         { &hf_hdfs_flags,
712           { "HDFS authentication type", "hdfs.auth_type",
713             FT_UINT8, BASE_DEC,
714             NULL, 0x0,
715             NULL, HFILL }
716         },
717         /***********************************************
718         Authentication packet
719         ***********************************************/
720         { &hf_hdfs_authlen,
721           { "HDFS authentication length", "hdfs.authlen",
722             FT_STRING, BASE_NONE,
723             NULL, 0x0,
724             NULL, HFILL }
725         },
726         { &hf_hdfs_auth,
727           { "HDFS authorization bits", "hdfs.auth",
728             FT_STRING, BASE_NONE,
729             NULL, 0x0,
730             NULL, HFILL }
731         },
732         /**********************************************
733         Response
734         **********************************************/
735         { &hf_hdfs_packetno,
736           { "HDFS packet number", "hdfs.seqno",
737             FT_UINT32, BASE_DEC,
738             NULL, 0x0,
739             NULL, HFILL }
740         },
741         { &hf_hdfs_success,
742           { "HDFS success", "hdfs.success",
743             FT_UINT32, BASE_DEC,
744             NULL, 0x0,
745             NULL, HFILL }
746         },
747         { &hf_hdfs_strcall,
748           { "HDFS method name", "hdfs.strcall",
749             FT_STRING, BASE_NONE,
750             NULL, 0x0,
751             NULL, HFILL }
752         },
753 #if 0
754         { &hf_hdfs_rest,
755           { "HDFS value", "hdfs.rest",
756             FT_STRING, BASE_NONE,
757             NULL, 0x0,
758             NULL, HFILL }
759         },
760 #endif
761         { &hf_hdfs_blockloc,
762           { "HDFS block location", "hdfs.blockloc",
763             FT_UINT64, BASE_DEC,
764             NULL, 0x0,
765             NULL, HFILL }
766         },
767         { &hf_hdfs_blocksize,
768           { "HDFS block size", "hdfs.blocksize",
769             FT_UINT64, BASE_DEC,
770             NULL, 0x0,
771             NULL, HFILL }
772         },
773         { &hf_hdfs_endblockloc,
774           { "HDFS file size", "hdfs.endblockloc",
775             FT_UINT64, BASE_DEC,
776             NULL, 0x0,
777             NULL, HFILL }
778         },
779         { &hf_hdfs_blockgen,
780           { "HDFS block gen", "hdfs.blockgen",
781             FT_UINT64, BASE_DEC,
782             NULL, 0x0,
783             NULL, HFILL }
784         },
785         { &hf_hdfs_prover,
786           { "HDFS protocol version", "hdfs.prover",
787             FT_UINT64, BASE_DEC,
788             NULL, 0x0,
789             NULL, HFILL }
790         },
791         { &hf_hdfs_objname,
792           { "HDFS object name", "hdfs.objname",
793             FT_STRING, BASE_NONE,
794             NULL, 0x0,
795             NULL, HFILL }
796         },
797         { &hf_hdfs_filename,
798           { "HDFS file name", "hdfs.filename",
799             FT_STRING, BASE_NONE,
800             NULL, 0x0,
801             NULL, HFILL }
802         },
803         { &hf_hdfs_blockcount,
804           { "HDFS block count", "hdfs.blockcount",
805             FT_UINT32, BASE_DEC,
806             NULL, 0x0,
807             NULL, HFILL }
808         },
809         { &hf_hdfs_ownername,
810           { "HDFS owner name", "hdfs.ownername",
811             FT_STRING, BASE_NONE,
812             NULL, 0x0,
813             NULL, HFILL }
814         },
815         { &hf_hdfs_groupname,
816           { "HDFS group name", "hdfs.groupname",
817             FT_STRING, BASE_NONE,
818             NULL, 0x0,
819             NULL, HFILL }
820         },
821         { &hf_hdfs_accesstime,
822           { "HDFS access time", "hdfs.accesstime",
823             FT_UINT64, BASE_DEC,
824             NULL, 0x0,
825             NULL, HFILL }
826         },
827         { &hf_hdfs_modtime,
828           { "HDFS modified time", "hdfs.modtime",
829             FT_UINT64, BASE_DEC,
830             NULL, 0x0,
831             NULL, HFILL }
832         },
833         { &hf_hdfs_blockrep,
834           { "HDFS block replication factor", "hdfs.blockrep",
835             FT_UINT16, BASE_DEC,
836             NULL, 0x0,
837             NULL, HFILL }
838         },
839         { &hf_hdfs_isdir,
840           { "HDFS is directory", "hdfs.isdir",
841             FT_UINT8, BASE_DEC,
842             NULL, 0x0,
843             NULL, HFILL }
844         },
845         { &hf_hdfs_filelen,
846           { "HDFS file length", "hdfs.filelen",
847             FT_UINT64, BASE_DEC,
848             NULL, 0x0,
849             NULL, HFILL }
850         },
851         { &hf_hdfs_construct,
852           { "HDFS under construction", "hdfs.construct",
853             FT_UINT8, BASE_DEC,
854             NULL, 0x0,
855             NULL, HFILL }
856         },
857         { &hf_hdfs_rackloc,
858           { "HDFS rack location", "hdfs.rackloc",
859             FT_STRING, BASE_NONE,
860             NULL, 0x0,
861             NULL, HFILL }
862         },
863         { &hf_hdfs_adminstate,
864           { "HDFS admin state", "hdfs.adminstate",
865             FT_STRING, BASE_NONE,
866             NULL, 0x0,
867             NULL, HFILL }
868         },
869         { &hf_hdfs_hostname,
870           { "HDFS hostname", "hdfs.hostname",
871             FT_STRING, BASE_NONE,
872             NULL, 0x0,
873             NULL, HFILL }
874         },
875
876
877         { &hf_hdfs_namelenone,
878           { "HDFS name length", "hdfs.namelenone",
879             FT_UINT8, BASE_DEC,
880             NULL, 0x0,
881             NULL, HFILL }
882         },
883         { &hf_hdfs_namelentwo,
884           { "HDFS name length", "hdfs.namelentwo",
885             FT_UINT16, BASE_DEC,
886             NULL, 0x0,
887             NULL, HFILL }
888         },
889
890
891         /***************************************
892         file info response
893         ***************************************/
894         { &hf_hdfs_activecon,
895           { "HDFS active connections", "hdfs.activecon",
896             FT_UINT32, BASE_DEC,
897             NULL, 0x0,
898             NULL, HFILL }
899         },
900         { &hf_hdfs_lastupdate,
901           { "HDFS lastupdate", "hdfs.lastupdate",
902             FT_UINT64, BASE_DEC,
903             NULL, 0x0,
904             NULL, HFILL }
905         },
906         { &hf_hdfs_remaining,
907           { "HDFS remaining", "hdfs.remaining",
908             FT_UINT64, BASE_DEC,
909             NULL, 0x0,
910             NULL, HFILL }
911         },
912         { &hf_hdfs_dfsused,
913           { "HDFS dfs used", "hdfs.dfsused",
914             FT_UINT64, BASE_DEC,
915             NULL, 0x0,
916             NULL, HFILL }
917         },
918         { &hf_hdfs_capacity,
919           { "HDFS capacity", "hdfs.capacity",
920             FT_UINT64, BASE_DEC,
921             NULL, 0x0,
922             NULL, HFILL }
923         },
924         { &hf_hdfs_ipcport,
925           { "HDFS ipcport", "hdfs.ipcport",
926             FT_UINT16, BASE_DEC,
927             NULL, 0x0,
928             NULL, HFILL }
929         },
930         { &hf_hdfs_infoport,
931           { "HDFS info port", "hdfs.infoport",
932             FT_UINT16, BASE_DEC,
933             NULL, 0x0,
934             NULL, HFILL }
935         },
936         { &hf_hdfs_storageid,
937           { "HDFS storage id", "hdfs.storageid",
938             FT_STRING, BASE_NONE,
939             NULL, 0x0,
940             NULL, HFILL }
941         },
942         { &hf_hdfs_datanodeid,
943           { "HDFS datanodeid", "hdfs.datanodeid",
944             FT_STRING, BASE_NONE,
945             NULL, 0x0,
946             NULL, HFILL }
947         },
948         { &hf_hdfs_locations,
949           { "HDFS locations", "hdfs.locations",
950             FT_UINT32, BASE_DEC,
951             NULL, 0x0,
952             NULL, HFILL }
953         },
954
955         { &hf_hdfs_identifier,
956           { "HDFS locations", "hdfs.identifier",
957             FT_STRING, BASE_NONE,
958             NULL, 0x0,
959             NULL, HFILL }
960         },
961         { &hf_hdfs_password,
962           { "HDFS password", "hdfs.password",
963             FT_STRING, BASE_NONE,
964             NULL, 0x0,
965             NULL, HFILL }
966         },
967         { &hf_hdfs_kind,
968           { "HDFS kind", "hdfs.kind",
969             FT_STRING, BASE_NONE,
970             NULL, 0x0,
971             NULL, HFILL }
972         },
973         { &hf_hdfs_service,
974           { "HDFS locations", "hdfs.service",
975             FT_STRING, BASE_NONE,
976             NULL, 0x0,
977             NULL, HFILL }
978         },
979         { &hf_hdfs_corrupt,
980           { "HDFS corrupt", "hdfs.corrupt",
981             FT_UINT8, BASE_DEC,
982             NULL, 0x0,
983             NULL, HFILL }
984         },
985         { &hf_hdfs_offset,
986           { "HDFS offset", "hdfs.offset",
987             FT_UINT64, BASE_DEC,
988             NULL, 0x0,
989             NULL, HFILL }
990         },
991
992
993         /***********************************************
994         Data request
995         ***********************************************/
996         { &hf_hdfs_len,
997           { "HDFS length", "hdfs.len",
998             FT_UINT32, BASE_DEC,
999             NULL, 0x0,
1000             NULL, HFILL }
1001         },
1002         /* packet number, same as in response
1003            method name length, same as in response
1004            string call, same as in response */
1005         { &hf_hdfs_params,
1006           { "HDFS number of parameters", "hdfs.params",
1007             FT_UINT32, BASE_DEC,
1008             NULL, 0x0,
1009             NULL, HFILL }
1010         },
1011         { &hf_hdfs_paramtype,
1012           { "HDFS parameter type", "hdfs.paramtype",
1013             FT_STRING, BASE_NONE,
1014             NULL, 0x0,
1015             NULL, HFILL }
1016         },
1017         { &hf_hdfs_paramval,
1018           { "HDFS parameter value", "hdfs.paramval",
1019             FT_STRING, BASE_NONE,
1020             NULL, 0x0,
1021             NULL, HFILL }
1022         },
1023         /* param value that is displayed as a number not a string */
1024         { &hf_hdfs_paramvalnum,
1025           { "HDFS parameter value", "hdfs.paramvalnum",
1026             FT_INT64, BASE_DEC,
1027             NULL, 0x0,
1028             NULL, HFILL }
1029         },
1030         { &hf_hdfs_fileperm,
1031           { "HDFS File permission", "hdfs.fileperm",
1032             FT_INT16, BASE_DEC,
1033             NULL, 0x0,
1034             NULL, HFILL }
1035         },
1036
1037     };
1038
1039     /* Setup protocol subtree array */
1040     static gint *ett[] = {
1041         &ett_hdfs
1042     };
1043
1044     module_t *hdfs_module;
1045
1046     proto_hdfs = proto_register_protocol (
1047         "HDFS Protocol", /* name       */
1048         "HDFS",      /* short name */
1049         "hdfs"       /* abbrev     */
1050         );
1051
1052     proto_register_field_array(proto_hdfs, hf, array_length(hf));
1053     proto_register_subtree_array(ett, array_length(ett));
1054
1055     hdfs_module = prefs_register_protocol(proto_hdfs, proto_reg_handoff_hdfs);
1056
1057     prefs_register_uint_preference(hdfs_module,
1058                                    "tcp.port",
1059                                    "TCP port for HDFS",
1060                                    "Set the TCP port for HDFS",
1061                                    10,
1062                                    &tcp_port);
1063
1064     hdfs_handle = new_register_dissector("hdfs", dissect_hdfs, proto_hdfs);
1065 }
1066
1067 /* registers handoff */
1068 void
1069 proto_reg_handoff_hdfs(void)
1070 {
1071     static gboolean initialized = FALSE;
1072     static guint saved_tcp_port;
1073
1074     if (!initialized) {
1075         dissector_add_handle("tcp.port", hdfs_handle);  /* for "decode as" */
1076         initialized = TRUE;
1077     } else if (saved_tcp_port != 0) {
1078         dissector_delete_uint("tcp.port", saved_tcp_port, hdfs_handle);
1079     }
1080
1081     if (tcp_port != 0) {
1082         dissector_add_uint("tcp.port", tcp_port, hdfs_handle);
1083     }
1084
1085     saved_tcp_port = tcp_port;
1086 }
1087 /*
1088  * Editor modelines
1089  *
1090  * Local Variables:
1091  * c-basic-offset: 4
1092  * tab-width: 8
1093  * indent-tabs-mode: nil
1094  * End:
1095  *
1096  * ex: set shiftwidth=4 tabstop=8 expandtab:
1097  * :indentSize=4:tabSize=8:noTabs=true:
1098  */