/* packet-hdfsdata.c * HDFS data Protocol and dissectors * * Copyright (c) 2011 by Isilon Systems. * * Author: Allison Obourn * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1999 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include "packet-tcp.h" void proto_register_hdfsdata(void); void proto_reg_handoff_hdfsdata(void); #if 0 #define NAMENODE_PORT 8020 #define DATANODE_PORT 8021 #endif #define FIRST_READ_FRAGMENT_LEN 15 #define SECOND_READ_FRAGMENT_LEN 29 #define LAST_READ_FRAGMENT_LEN 4 #define WRITE_OP 80 #define READ_OP 81 #define MIN_WRITE_REQ 35 #define MIN_READ_REQ 36 #define STATUS_SUCCESS 6 #define PIPELINE_LEN 1 #define STATUS_LEN 2 #define FINISH_REQ_LEN 4 #define END_PACKET_LEN 8 #define READ_RESP_HEAD_LEN 19 #define WRITE_RESP_HEAD_LEN 21 #define WRITE_REQ_HEAD_LEN 7 #define CRC 1 #define CRC_SIZE 8.0 #define CHUNKSIZE_START 3 #if 0 static const int RESPONSE_HEADER = 1; static const int RESPONSE_METADATA = 2; static const int RESPONSE_DATA = 3; #endif static guint tcp_port = 0; static int proto_hdfsdata = -1; static int hf_hdfsdata_version = -1; static int hf_hdfsdata_cmd = -1; static int hf_hdfsdata_blockid = -1; static int hf_hdfsdata_timestamp = -1; static int hf_hdfsdata_startoffset = -1; static int hf_hdfsdata_blocklen = -1; static int hf_hdfsdata_clientlen = -1; static int hf_hdfsdata_clientid = -1; static int hf_hdfsdata_tokenlen = -1; static int hf_hdfsdata_tokenid = -1; static int hf_hdfsdata_tokenpassword = -1; static int hf_hdfsdata_tokentype = -1; static int hf_hdfsdata_tokenservice = -1; static int hf_hdfsdata_status = -1; static int hf_hdfsdata_checksumtype = -1; static int hf_hdfsdata_chunksize = -1; static int hf_hdfsdata_chunkoffset = -1; static int hf_hdfsdata_datalength = -1; static int hf_hdfsdata_inblockoffset = -1; static int hf_hdfsdata_seqnum = -1; static int hf_hdfsdata_last = -1; static int hf_hdfsdata_crc32 = -1; static int hf_hdfsdata_datalen = -1; static int hf_hdfsdata_rest = -1; static int hf_hdfsdata_end = -1; static int hf_hdfsdata_packetsize = -1; static int hf_hdfsdata_chunklength = -1; static int hf_hdfsdata_crc64 = -1; static int hf_hdfsdata_pipelinestatus = -1; static int hf_hdfsdata_pipelinenum = -1; static int hf_hdfsdata_recovery = -1; static int hf_hdfsdata_sourcenode = -1; static int hf_hdfsdata_currentpipeline = -1; static int hf_hdfsdata_node = -1; static gint ett_hdfsdata = -1; static dissector_handle_t hdfsdata_handle; /* Taken from HDFS Parse the first byte of a vint/vlong to determine the number of bytes value is the first byte of the vint/vlong returns the total number of bytes (1 to 9) */ static int decode_vint_size (gint8 value) { if (value >= -112) { return 1; } else if (value < -120) { return -119 - value; } return -111 - value; } /* Taken from HDFS converts a variable length number into a long and discovers how many bytes it is returns the decoded number */ static guint dissect_variable_length_long (tvbuff_t *tvb, proto_tree *hdfsdata_tree, int* offset) { int byte_count = 1; int idx = 0; guint i = 0; gint8 first_byte = tvb_get_guint8(tvb, *offset); guint size = 0; int len = decode_vint_size(first_byte); if (len == 1) { proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_clientlen, tvb, *offset, byte_count, ENC_BIG_ENDIAN); *offset = (*offset) + byte_count; return first_byte; } for (idx = 0; idx < len-1; idx++) { char b = tvb_get_guint8(tvb, *offset + byte_count); byte_count++; i = i << 8; i = i | (b & 0xFF); } size = ((first_byte < -120 || (first_byte >= -112 && first_byte < 0)) ? (i ^ 0xFFFFFFFF) : i); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_clientlen, tvb, *offset, byte_count, ENC_BIG_ENDIAN); *offset = (*offset) + byte_count; return size; } /* dissects a variable length int and then using its value dissects the following string */ static void dissect_variable_int_string(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset) { /* Get the variable length int that represents the length of the next feild */ int len = dissect_variable_length_long (tvb, hdfsdata_tree, offset); /* client id = amount of bytes in previous */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_clientid, tvb, *offset, len, ENC_ASCII|ENC_NA); *offset += len; } /* dissects the access tokens that appear at the end of requests. tokens: id, password, kind, service */ static void dissect_access_tokens(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset) { int len = 0; len = tvb_get_guint8(tvb, *offset); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* token id = amount of bytes in previous */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenid, tvb, *offset, len, ENC_ASCII|ENC_NA); *offset += len; len = tvb_get_guint8(tvb, *offset); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* token password = amount of bytes in previous */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenpassword, tvb, *offset, len, ENC_ASCII|ENC_NA); *offset += len; len = tvb_get_guint8(tvb, *offset); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* token type = amount of bytes in previous */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokentype, tvb, *offset, len, ENC_ASCII|ENC_NA); *offset += len; len = tvb_get_guint8(tvb, *offset); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenlen, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* token service = amount of bytes in previous; */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_tokenservice, tvb, *offset, len, ENC_ASCII|ENC_NA); *offset += len; } /* handles parsing read response packets */ static void dissect_read_response(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int offset) { int len = 0; guint32 chunksize; /* 4 bytes = data length */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_datalength, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* 8 bytes = in block offset */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_inblockoffset, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* 8 bytes = sequence number */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_seqnum, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* 1 byte = last packet in block */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_last, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* 4 byte = length of data */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_datalen, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* if there is a crc checksum it is 8* the length of the data * checksum size / chunksize */ chunksize = tvb_get_ntohl(tvb, CHUNKSIZE_START); if (chunksize == 0) /* let's not divide by zero */ return; if (tvb_get_guint8(tvb, 2) == CRC) { len = (int)(CRC_SIZE * tvb_get_ntohl(tvb, offset - 4) * tvb_get_ntohl(tvb, offset - 8) / chunksize); } /* the rest of bytes (usually 4) = crc32 code */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_crc32, tvb, offset, len, ENC_BIG_ENDIAN); /* offset += len; */ } /* dissects the first packet of the read response */ static void dissect_read_response_start(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int offset) { /* 2 bytes = status code */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_status, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* checksum type = 1 byte. 1 = crc32, 0 = null */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_checksumtype, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* 4 bytes = chunksize */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunksize, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* 8 bytes = chunk offset */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunkoffset, tvb, offset, 8, ENC_BIG_ENDIAN); /* offset += 8; */ } /* dissects the fields specific to a read request */ static void dissect_read_request(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset) { /* 8 bytes = start offset */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_startoffset, tvb, *offset, 8, ENC_BIG_ENDIAN); *offset += 8; /* 8 bytes = block length */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_blocklen, tvb, *offset, 8, ENC_BIG_ENDIAN); *offset += 8; } /* dissects the fields specific to a write request */ static void dissect_write_request(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset) { /* 4 bytes = number of nodes in pipeline */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_pipelinenum, tvb, *offset, 4, ENC_BIG_ENDIAN); *offset += 4; /* 1 bytes = recovery boolean */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_recovery, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; } /* dissects the fields specific to a write request */ static void dissect_write_request_end(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int *offset) { int i = 0; int len = 0; /* 1 bytes = source node */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_sourcenode, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* 4 bytes = number of nodes currently in the pipeline (usually just -1 of before) */ len = tvb_get_ntohl(tvb, *offset); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_currentpipeline, tvb, *offset, 4, ENC_BIG_ENDIAN); *offset += 4; /* varible length sequence of node objects */ for (i = 0; i < len; i++) { proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_node, tvb, *offset, 4, ENC_BIG_ENDIAN); *offset += 4; } } /* dissects the beginning of the read and write request messages */ static int dissect_header(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int* offset){ int command = 0; /* 2 bytes = protocol version */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_version, tvb, *offset, 2, ENC_BIG_ENDIAN); *offset += 2; /* 1 byte = command */ command = tvb_get_guint8(tvb, *offset); proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_cmd, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* 8 bytes = block id */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_blockid, tvb, *offset, 8, ENC_BIG_ENDIAN); *offset += 8; /* 8 bytes = timestamp */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_timestamp, tvb, *offset, 8, ENC_BIG_ENDIAN); *offset += 8; return command; } /* decodes the write response messages */ static void dissect_write_response(tvbuff_t *tvb, proto_tree *hdfsdata_tree, int offset) { /* 4 bytes = packetsize */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_packetsize, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* 8 bytes = offset in block */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_startoffset, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* 8 bytes = sequence number */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_seqnum, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* 1 bytes = last packet */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_last, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* 4 bytes = chunk length */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunklength, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* 8 bytes = crc code */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_crc64, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* add the rest -> RESPONSE_DATA */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_rest, tvb, offset, (tvb_reported_length(tvb)) - offset, ENC_ASCII|ENC_NA); /* offset += (tvb_reported_length(tvb)); */ } /* determine PDU length of protocol */ static guint get_hdfsdata_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { /* get data packet len, add FIRST_READ_FRAGMENT_LEN for first fragment (before len), SECOND_READ_FRAGMENT_LEN for second fragment (incl len), subtract 4 for length itself. */ if (tvb_reported_length(tvb) <= 4 || tvb_reported_length(tvb) == END_PACKET_LEN || tvb_get_ntohl(tvb, 0) == tvb_reported_length(tvb) - WRITE_RESP_HEAD_LEN || (tvb_reported_length(tvb) >= MIN_READ_REQ && tvb_get_guint8(tvb, 2) == READ_OP) || (tvb_reported_length(tvb) >= MIN_WRITE_REQ && tvb_get_guint8(tvb, 2) == WRITE_OP)) { return tvb_reported_length(tvb); } return tvb_get_ntohl(tvb, offset + FIRST_READ_FRAGMENT_LEN) + FIRST_READ_FRAGMENT_LEN + SECOND_READ_FRAGMENT_LEN - LAST_READ_FRAGMENT_LEN; } /* This method dissects fully reassembled messages */ static int dissect_hdfsdata_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "HDFSDATA"); /* Clear out stuff in the info column */ col_set_str(pinfo->cinfo, COL_INFO, "HDFS Data"); if (tree) { proto_item *ti = NULL; proto_tree *hdfsdata_tree = NULL; ti = proto_tree_add_item(tree, proto_hdfsdata, tvb, offset, -1, ENC_NA); hdfsdata_tree = proto_item_add_subtree(ti, ett_hdfsdata); /* if only 1 bytes packet must just contain just the pipeline status */ if ((tvb_reported_length(tvb)) == PIPELINE_LEN) { /* 1 bytes = pipeline status */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_pipelinestatus, tvb, offset, PIPELINE_LEN, ENC_BIG_ENDIAN); /* if only 2 bytes packet must just contain just a status code */ } else if ((tvb_reported_length(tvb)) == STATUS_LEN) { /* 2 bytes = status code */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_status, tvb, offset, STATUS_LEN, ENC_BIG_ENDIAN); /* if it is 4 bytes long it must be a finish request packet */ } else if ((tvb_reported_length(tvb)) == FINISH_REQ_LEN) { proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_end, tvb, offset, 4, ENC_BIG_ENDIAN); /* read response packet */ } else if (tvb_reported_length(tvb) >= READ_RESP_HEAD_LEN && tvb_reported_length(tvb) == tvb_get_ntohl(tvb, FIRST_READ_FRAGMENT_LEN) + FIRST_READ_FRAGMENT_LEN + SECOND_READ_FRAGMENT_LEN - LAST_READ_FRAGMENT_LEN){ dissect_read_response_start(tvb, hdfsdata_tree, offset); offset += FIRST_READ_FRAGMENT_LEN; dissect_read_response(tvb, hdfsdata_tree, offset); offset+= SECOND_READ_FRAGMENT_LEN; /* This message just contains data so we can display it all as one block */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_rest, tvb, offset, (tvb_reported_length(tvb)) - offset, ENC_ASCII|ENC_NA); } else { guint8 op = tvb_get_guint8(tvb, 2); /* READ request */ if ((tvb_reported_length(tvb)) >= MIN_READ_REQ && op == READ_OP) { dissect_header(tvb, hdfsdata_tree, &offset); dissect_read_request(tvb, hdfsdata_tree, &offset); dissect_variable_int_string(tvb, hdfsdata_tree, &offset); dissect_access_tokens(tvb, hdfsdata_tree, &offset); /* WRITE request */ } else if ((tvb_reported_length(tvb)) >= MIN_WRITE_REQ && op == WRITE_OP) { dissect_header(tvb, hdfsdata_tree, &offset); dissect_write_request(tvb, hdfsdata_tree, &offset); dissect_variable_int_string(tvb, hdfsdata_tree, &offset); dissect_write_request_end(tvb, hdfsdata_tree, &offset); dissect_access_tokens(tvb, hdfsdata_tree, &offset); /* checksum type = 1 byte. 1 = crc32, 0 = null */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_checksumtype, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* 4 bytes = chunksize */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_chunksize, tvb, offset, 4, ENC_BIG_ENDIAN); /* write responses store the data length in the first 4 bytes. This length does not include 21 bits of header */ } else if (tvb_reported_length(tvb) >= 4 && tvb_get_ntohl(tvb, 0) == tvb_reported_length(tvb) - WRITE_RESP_HEAD_LEN) { dissect_write_response(tvb, hdfsdata_tree, offset); } else { /* This message contains some form of data that we have not successfully been able to pattern match and catagorize. Display all of it as data. */ proto_tree_add_item(hdfsdata_tree, hf_hdfsdata_rest, tvb, offset, (tvb_reported_length(tvb)), ENC_ASCII|ENC_NA); } } } return tvb_captured_length(tvb); } static int dissect_hdfsdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { int frame_header_len = 0; gboolean need_reassemble = FALSE; guint8 op = 0; gboolean only_packet = tvb_reported_length(tvb) == 1 || (tvb_reported_length(tvb) == 2 && tvb_get_ntohs(tvb, 0) == STATUS_SUCCESS); if (tvb_reported_length(tvb) >= 3) op = tvb_get_guint8(tvb, 2); if (!only_packet && tvb_reported_length(tvb) != 4 && !(tvb_reported_length(tvb) >= MIN_READ_REQ && op == READ_OP) && !(tvb_reported_length(tvb) >= MIN_WRITE_REQ && op == WRITE_OP) && !(tvb_reported_length(tvb) == END_PACKET_LEN && !tvb_get_ntohl(tvb, 0) && !tvb_get_ntohl(tvb, 4))) { need_reassemble = TRUE; } /* setting the header size for the different types of packets */ if (only_packet || tvb_reported_length(tvb) == END_PACKET_LEN) { frame_header_len = tvb_reported_length(tvb); } else if (tvb_reported_length(tvb) == FIRST_READ_FRAGMENT_LEN ||(tvb_reported_length(tvb) >= MIN_READ_REQ && op == READ_OP && !((tvb_reported_length(tvb)) == 2 && !tvb_get_ntohs(tvb, 0)))) { frame_header_len = READ_RESP_HEAD_LEN; } else if (tvb_reported_length(tvb) >= MIN_WRITE_REQ && op == WRITE_OP) { frame_header_len = WRITE_REQ_HEAD_LEN; } tcp_dissect_pdus(tvb, pinfo, tree, need_reassemble, frame_header_len, get_hdfsdata_message_len, dissect_hdfsdata_message, data); return tvb_captured_length(tvb); } /* registers the protcol with the given names */ void proto_register_hdfsdata(void) { static hf_register_info hf[] = { /* list of all options for dissecting the protocol */ /************************************************* Read request **************************************************/ { &hf_hdfsdata_version, { "HDFSDATA protocol version", "hdfsdata.version", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_cmd, { "HDFSDATA command", "hdfsdata.cmd", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_blockid, { "HDFSDATA block id", "hdfsdata.blockid", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_timestamp, { "HDFSDATA timestamp", "hdfsdata.timestamp", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /*** Read specific ***/ { &hf_hdfsdata_startoffset, { "HDFSDATA start offset" , "hdfsdata.startoffset", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_blocklen, { "HDFSDATA block length", "hdfsdata.blocklen", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /*** Write specific ***/ { &hf_hdfsdata_pipelinenum, { "HDFSDATA number in pipeline", "hdfsdata.pipelinenum", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_recovery, { "HDFSDATA recovery boolean", "hdfsdata.recovery", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_sourcenode, { "HDFSDATA source node", "hdfsdata.sourcenode", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_currentpipeline, { "HDFSDATA current number of nodes in the pipeline", "hdfsdata.currentpipline", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_node, { "HDFSDATA node object", "hdfsdata.node", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /*** Var length **/ { &hf_hdfsdata_clientlen, { "HDFSDATA client id length", "hdfsdata.clientlen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_clientid, { "HDFSDATA client id", "hdfsdata.clientid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_end, { "HDFSDATA end data request", "hdfsdata.end", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /************************************************* Access tokens **************************************************/ { &hf_hdfsdata_tokenlen, { "HDFSDATA access token length", "hdfsdata.tokenlen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_tokenid, { "HDFSDATA access token ID", "hdfsdata.tokenid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_tokenpassword, { "HDFSDATA access token password", "hdfsdata.tokenpassword", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_tokentype, { "HDFSDATA access token type", "hdfsdata.tokentype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_tokenservice, { "HDFSDATA access token service", "hdfsdata.tokenservice", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, /*********************************************** Responses 1 ***********************************************/ { &hf_hdfsdata_status, { "HDFSDATA status code", "hdfsdata.status", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_checksumtype, { "HDFSDATA checksum type", "hdfsdata.checksumtype", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_chunksize, { "HDFSDATA chunk size", "hdfsdata.chunksize", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_chunkoffset, { "HDFSDATA chunk offset", "hdfsdata.chunkoffset", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /*********************************************** Responses 2 ***********************************************/ { &hf_hdfsdata_datalength, { "HDFSDATA length of data", "hdfsdata.datalength", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_inblockoffset, { "HDFSDATA in block offset", "hdfsdata.inblockoffset", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_seqnum, { "HDFSDATA sequence number", "hdfsdata.seqnum", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_last, { "HDFSDATA last packet in block", "hdfsdata.last", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_datalen, { "HDFSDATA length of data", "hdfsdata.datalen", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_crc32, { "HDFSDATA crc32 checksum", "hdfsdata.crc32", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /*********************************************** Responses 3 ***********************************************/ { &hf_hdfsdata_rest, { "HDFSDATA data", "hdfsdata.rest", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, /*********************************************** Write Response 1 ***********************************************/ { &hf_hdfsdata_packetsize, { "HDFSDATA packet size", "hdfsdata.packetsize", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_chunklength, { "HDFSDATA chunk length", "hdfsdata.chunklength", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_crc64, { "HDFSDATA crc64 checksum", "hdfsdata.crc64", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_hdfsdata_pipelinestatus, { "HDFSDATA pipeline status", "hdfsdata.pipelinestatus", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_hdfsdata }; module_t *hdfsdata_module; proto_hdfsdata = proto_register_protocol ( "HDFSDATA Protocol", /* name */ "HDFSDATA", /* short name */ "hdfsdata" /* abbrev */ ); proto_register_field_array(proto_hdfsdata, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); hdfsdata_module = prefs_register_protocol(proto_hdfsdata, proto_reg_handoff_hdfsdata); prefs_register_uint_preference(hdfsdata_module, "tcp.port", "TCP port for HDFSDATA", "Set the TCP port for HDFSDATA", 10, &tcp_port); hdfsdata_handle = register_dissector("hdfsdata", dissect_hdfsdata, proto_hdfsdata); } /* registers handoff */ void proto_reg_handoff_hdfsdata(void) { static gboolean initialized = FALSE; static guint saved_tcp_port; if (!initialized) { dissector_add_for_decode_as("tcp.port", hdfsdata_handle); initialized = TRUE; } else if (saved_tcp_port != 0) { dissector_delete_uint("tcp.port", saved_tcp_port, hdfsdata_handle); } if (tcp_port != 0) { dissector_add_uint("tcp.port", tcp_port, hdfsdata_handle); } saved_tcp_port = tcp_port; } /* * Editor modelines * * Local Variables: * c-basic-offset: 2 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=2 tabstop=8 expandtab: * :indentSize=2:tabSize=8:noTabs=true: */