Ethereal-dev: [Ethereal-dev] packet-iscsi.c improvements

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Mark Burton <markb@xxxxxxxxxx>
Date: Thu, 31 May 2001 12:18:45 +0100
Hi,

Here's another patch to the current CVS version of packet-iscsi.c that
adds a sub-tree for the flags byte and provides a bit more information
in the Info field.

Cheers,

Mark

Index: packet-iscsi.c
===================================================================
RCS file: /cvsroot/ethereal/packet-iscsi.c,v
retrieving revision 1.2
diff -u -3 -p -c -r1.2 packet-iscsi.c
*** packet-iscsi.c	2001/05/31 08:54:17	1.2
--- packet-iscsi.c	2001/05/31 11:17:50
*************** static int proto_iscsi = -1;
*** 61,66 ****
--- 61,67 ----
  static int hf_iscsi_Payload = -1;
  static int hf_iscsi_Opcode = -1;
  static int hf_iscsi_Opcode_03 = -1;
+ static int hf_iscsi_Flags = -1;
  #if 0
  static int hf_iscsi_X = -1;
  static int hf_iscsi_I = -1;
*************** static int hf_iscsi_AdditionalRuns = -1;
*** 152,157 ****
--- 153,159 ----
  /* Initialize the subtree pointers */
  static gint ett_iscsi_KeyValues = -1;
  static gint ett_iscsi_CDB = -1;
+ static gint ett_iscsi_Flags = -1;
  
  static const value_string iscsi_opcodes[] = {
    {0x00, "NOP Out"},
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 520,536 ****
      guint32 data_segment_len;
      guint8 opcode;
      const char *opcode_str;
!     guint32 pdu_len;
  
!     /* Make sure we have enough of the packet to check whether it's
!        iSCSI */
!     if (tvb_length_remaining(tvb, offset) < 8) {
! 	/* We don't */
  	return FALSE;
      }
  
      opcode = tvb_get_guint8(tvb, offset + 0);
!     pdu_len = tvb_length_remaining(tvb, 0);
      if(enable_03_mode) {
  	opcode_str = match_strval(opcode, iscsi_opcodes_03);
  	data_segment_len = tvb_get_ntohl(tvb, offset + 4);
--- 522,538 ----
      guint32 data_segment_len;
      guint8 opcode;
      const char *opcode_str;
!     guint32 packet_len = tvb_length_remaining(tvb, offset);
  
!     /* quick check to see if the packet is long enough to contain a
!      * whole iSCSI header segment */
!     if (packet_len < 48) {
! 	/* no, so give up */
  	return FALSE;
      }
  
      opcode = tvb_get_guint8(tvb, offset + 0);
! 
      if(enable_03_mode) {
  	opcode_str = match_strval(opcode, iscsi_opcodes_03);
  	data_segment_len = tvb_get_ntohl(tvb, offset + 4);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 544,551 ****
      if(opcode_str == NULL ||
         (enable_bogosity_filter &&
  	(data_segment_len > bogus_pdu_data_length_threshold ||
! 	 pdu_len < 48  ||
! 	 pdu_len > (data_segment_len + 48 + bogus_pdu_max_digest_padding)))) {
  	return FALSE;
      }
  
--- 546,552 ----
      if(opcode_str == NULL ||
         (enable_bogosity_filter &&
  	(data_segment_len > bogus_pdu_data_length_threshold ||
! 	 packet_len > (data_segment_len + 48 + bogus_pdu_max_digest_padding)))) {
  	return FALSE;
      }
  
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 555,569 ****
  
  
      if (check_col(pinfo->fd, COL_INFO)) {
- 	const char *scsiCommandName = 0;
  
  	col_add_str(pinfo->fd, COL_INFO, (char *)opcode_str);
  
! 	if((opcode & 0xbf) == 0x01 && pdu_len > 32)
! 	    scsiCommandName = match_strval(tvb_get_guint8(tvb, offset + 32),
! 					   iscsi_scsi_cdb0);
! 	if(scsiCommandName != NULL)
! 	    col_append_fstr(pinfo->fd, COL_INFO, " (%s)", scsiCommandName);
      }
  
      /* In the interest of speed, if "tree" is NULL, don't do any
--- 556,584 ----
  
  
      if (check_col(pinfo->fd, COL_INFO)) {
  
  	col_add_str(pinfo->fd, COL_INFO, (char *)opcode_str);
  
! 	if((opcode & 0xbf) == 0x01) {
! 	    const char *scsiCommandName = match_strval(tvb_get_guint8(tvb, offset + 32),
! 						       iscsi_scsi_cdb0);
! 	    if(scsiCommandName != NULL)
! 		col_append_fstr(pinfo->fd, COL_INFO, " (%s)", scsiCommandName);
! 	}
! 	else if(enable_03_mode && opcode == 0x81) {
! 	    const char *blurb = match_strval(tvb_get_guint8(tvb, offset + 36), iscsi_scsi_statuses);
! 	    if(blurb != NULL)
! 		col_append_fstr(pinfo->fd, COL_INFO, " (%s)", blurb);
! 	}
! 	else if(!enable_03_mode && opcode == 0xc1) {
! 	    const char *blurb = NULL;
! 	    if(tvb_get_guint8(tvb, offset + 1) & 0x01)
! 		blurb = match_strval(tvb_get_guint8(tvb, offset + 3), iscsi_scsi_statuses);
! 	    else
! 		blurb = match_strval(tvb_get_guint8(tvb, offset + 3), iscsi_scsi_responses);
! 	    if(blurb != NULL)
! 		col_append_fstr(pinfo->fd, COL_INFO, " (%s)", blurb);
! 	}
      }
  
      /* In the interest of speed, if "tree" is NULL, don't do any
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 571,585 ****
      if (tree) {
  
  	/* create display subtree for the protocol */
! 	ti = proto_tree_add_item(tree, proto_iscsi, tvb, offset,
! 				 pdu_len, FALSE);
  
  	if((enable_03_mode && opcode == 0x00) ||
  	   (!enable_03_mode && (opcode == 0x00 ||
  				opcode == 0x40 ||
  				opcode == 0x80))) {
  	    /* NOP Out */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
--- 586,599 ----
      if (tree) {
  
  	/* create display subtree for the protocol */
! 	ti = proto_tree_add_protocol_format(tree, proto_iscsi, tvb, offset,
! 				 packet_len, "iSCSI (%s)", (char *)opcode_str);
  
  	if((enable_03_mode && opcode == 0x00) ||
  	   (!enable_03_mode && (opcode == 0x00 ||
  				opcode == 0x40 ||
  				opcode == 0x80))) {
  	    /* NOP Out */
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 587,594 ****
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
- 	    proto_tree_add_boolean(ti, hf_iscsi_NOP_P, tvb, offset + 1, 1, b);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
--- 601,613 ----
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
+ 	    }
+ 	    {
+ 		gint b = tvb_get_guint8(tvb, offset + 1);
+ 		proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ 		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+ 		proto_tree_add_boolean(tt, hf_iscsi_NOP_P, tvb, offset + 1, 1, b);
  	    }
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 609,615 ****
  	else if((enable_03_mode && opcode == 0x80) ||
  		(!enable_03_mode && opcode == 0xc0)) {
  	    /* NOP In */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
--- 628,633 ----
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 617,624 ****
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
- 	    proto_tree_add_boolean(ti, hf_iscsi_NOP_P, tvb, offset + 1, 1, b);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
--- 635,647 ----
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
+ 	    }
+ 	    {
+ 		gint b = tvb_get_guint8(tvb, offset + 1);
+ 		proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ 		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+ 		proto_tree_add_boolean(tt, hf_iscsi_NOP_P, tvb, offset + 1, 1, b);
  	    }
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 637,660 ****
  				     opcode == 0x41 ||
  				     opcode == 0x81))) {
  	    /* SCSI Command */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSICommand_X03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
! 		proto_tree_add_uint(ti, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
  		proto_tree_add_uint(ti, hf_iscsi_SCSICommand_AddCDB, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
! 		proto_tree_add_uint(ti, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
  		proto_tree_add_uint(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, tvb_get_guint8(tvb, offset + 4));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
--- 660,694 ----
  				     opcode == 0x41 ||
  				     opcode == 0x81))) {
  	    /* SCSI Command */
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_X03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
! 		    proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_SCSICommand_AddCDB, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
! 		    proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, tvb_get_guint8(tvb, offset + 4));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 675,702 ****
  	else if((enable_03_mode && opcode == 0x81) ||
  		(!enable_03_mode && opcode == 0xc1)) {
  	    /* SCSI Response */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_o03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_u03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_O03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_U03, tvb, offset + 1, 1, b);
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIResponse_S, tvb, offset + 1, 1, b);
! 		if(b & 0x01)
! 		    proto_tree_add_uint(ti, hf_iscsi_StatusResponse_is_status, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
! 		else
! 		    proto_tree_add_uint(ti, hf_iscsi_StatusResponse_is_response, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
--- 709,747 ----
  	else if((enable_03_mode && opcode == 0x81) ||
  		(!enable_03_mode && opcode == 0xc1)) {
  	    /* SCSI Response */
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U03, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_S, tvb, offset + 1, 1, b);
! 		    if(b & 0x01)
! 			proto_tree_add_uint(ti, hf_iscsi_StatusResponse_is_status, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
! 		    else
! 			proto_tree_add_uint(ti, hf_iscsi_StatusResponse_is_response, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 720,726 ****
  				     opcode == 0x42 ||
  				     opcode == 0x82))) {
  	    /* SCSI Task Command */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
--- 765,770 ----
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 729,735 ****
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
! 	    proto_tree_add_uint(ti, hf_iscsi_SCSITask_Function, tvb, offset + 1, 1, b);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
--- 773,779 ----
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
! 	    proto_tree_add_uint(ti, hf_iscsi_SCSITask_Function, tvb, offset + 1, 1, tvb_get_guint8(tvb, offset + 1));
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 772,778 ****
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_Login_F, tvb, offset + 1, 1, tvb_get_guint8(tvb, offset + 1));
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
--- 816,828 ----
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_Login_F, tvb, offset + 1, 1, b);
! 		}
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 794,801 ****
  		proto_tree_add_uint(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    }
  	    offset += 48;
! 	    if(pdu_len > 48) {
! 		int text_len = min(data_segment_len, pdu_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
--- 844,851 ----
  		proto_tree_add_uint(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    }
  	    offset += 48;
! 	    if(packet_len > 48) {
! 		int text_len = min(data_segment_len, packet_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 804,810 ****
  	else if((enable_03_mode && opcode == 0x83) ||
  		(!enable_03_mode && opcode == 0xc3)) {
  	    /* Login Response */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
--- 854,859 ----
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 813,819 ****
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
! 	    proto_tree_add_boolean(ti, hf_iscsi_Login_F, tvb, offset + 1, 1, b);
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  	    if(enable_03_mode) {
--- 862,874 ----
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
! 	    {
! 		gint b = tvb_get_guint8(tvb, offset + 1);
! 		proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		proto_tree_add_boolean(tt, hf_iscsi_Login_F, tvb, offset + 1, 1, b);
! 	    }
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
  	    proto_tree_add_uint(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  	    if(enable_03_mode) {
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 835,842 ****
  		proto_tree_add_uint(ti, hf_iscsi_Login_Status, tvb, offset + 36, 1, tvb_get_ntohs(tvb, offset + 36));
  	    }
  	    offset += 48;
! 	    if(pdu_len > 48) {
! 		int text_len = min(data_segment_len, pdu_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
--- 890,897 ----
  		proto_tree_add_uint(ti, hf_iscsi_Login_Status, tvb, offset + 36, 1, tvb_get_ntohs(tvb, offset + 36));
  	    }
  	    offset += 48;
! 	    if(packet_len > 48) {
! 		int text_len = min(data_segment_len, packet_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 855,869 ****
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_Text_F, tvb, offset + 1, 1, tvb_get_guint8(tvb, offset + 1));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
  	    proto_tree_add_uint(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, tvb_get_ntohl(tvb, offset + 24));
  	    proto_tree_add_uint(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    offset += 48;
! 	    if(pdu_len > 48) {
! 		int text_len = min(data_segment_len, pdu_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
--- 910,930 ----
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
  	    proto_tree_add_uint(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, tvb_get_ntohl(tvb, offset + 24));
  	    proto_tree_add_uint(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    offset += 48;
! 	    if(packet_len > 48) {
! 		int text_len = min(data_segment_len, packet_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 880,886 ****
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_Text_F, tvb, offset + 1, 1, tvb_get_guint8(tvb, offset + 1));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
--- 941,953 ----
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 888,895 ****
  	    proto_tree_add_uint(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    proto_tree_add_uint(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, tvb_get_ntohl(tvb, offset + 32));
  	    offset += 48;
! 	    if(pdu_len > 48) {
! 		int text_len = min(data_segment_len, pdu_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
--- 955,962 ----
  	    proto_tree_add_uint(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    proto_tree_add_uint(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, tvb_get_ntohl(tvb, offset + 32));
  	    offset += 48;
! 	    if(packet_len > 48) {
! 		int text_len = min(data_segment_len, packet_len - 48);
  		proto_item *tf = proto_tree_add_text(ti, tvb, 48, text_len, "Key/Value Pairs");
  		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
  		offset = addTextKeys(tt, tvb, 48, text_len);
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 897,903 ****
  	}
  	else if(opcode == 0x05) {
  	    /* SCSI Data (write) */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
--- 964,969 ----
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 905,912 ****
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
  	    }
- 	    proto_tree_add_boolean(ti, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
--- 971,984 ----
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
+ 	    }
+ 	    {
+ 		gint b = tvb_get_guint8(tvb, offset + 1);
+ 		proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ 		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+ 
+ 		proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
  	    }
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 925,947 ****
  	else if((enable_03_mode && opcode == 0x85) ||
  		(!enable_03_mode && opcode == 0xc5)) {
  	    /* SCSI Data (read) */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_P03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_S03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_O03, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_U03, tvb, offset + 1, 1, b);
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
! 		proto_tree_add_boolean(ti, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
  		proto_tree_add_uint(ti, hf_iscsi_StatusResponse_is_status, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
--- 997,1030 ----
  	else if((enable_03_mode && opcode == 0x85) ||
  		(!enable_03_mode && opcode == 0xc5)) {
  	    /* SCSI Data (read) */
  	    if(enable_03_mode) {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb, 
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_P03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O03, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U03, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
  	    }
  	    else {
  		proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				    offset + 0, 1, opcode);
! 		{
! 		    gint b = tvb_get_guint8(tvb, offset + 1);
! 		    proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		    proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
! 		    proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
! 		}
  		proto_tree_add_uint(ti, hf_iscsi_StatusResponse_is_status, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  		proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
  	    }
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 1005,1020 ****
  	    offset += 48;
  	}
  	else if((!enable_03_mode && (opcode == 0x10 || opcode == 0x50))) {
  	    /* SNACK Request */
- 	    gint b = tvb_get_guint8(tvb, offset + 1);
  	    proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				offset + 0, 1, opcode);
! 	    proto_tree_add_boolean(ti, hf_iscsi_SNACK_S, tvb, offset + 1, 1, b);
  	    proto_tree_add_boolean(ti, hf_iscsi_AddRuns, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
  	    proto_tree_add_uint(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, tvb_get_ntohl(tvb, offset + 20));
  	    proto_tree_add_uint(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, tvb_get_ntohl(tvb, offset + 24));
! 	    if(b & 0x01) {
  		proto_tree_add_uint(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    }
  	    else {
--- 1088,1110 ----
  	    offset += 48;
  	}
  	else if((!enable_03_mode && (opcode == 0x10 || opcode == 0x50))) {
+ 	    int S = 0;
  	    /* SNACK Request */
  	    proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
  				offset + 0, 1, opcode);
! 	    {
! 		gint b = tvb_get_guint8(tvb, offset + 1);
! 		proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
! 		proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
! 
! 		proto_tree_add_boolean(tt, hf_iscsi_SNACK_S, tvb, offset + 1, 1, b);
! 		S = b & 0x01;
! 	    }
  	    proto_tree_add_boolean(ti, hf_iscsi_AddRuns, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
  	    proto_tree_add_uint(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, tvb_get_ntohl(tvb, offset + 16));
  	    proto_tree_add_uint(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, tvb_get_ntohl(tvb, offset + 20));
  	    proto_tree_add_uint(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, tvb_get_ntohl(tvb, offset + 24));
! 	    if(S) {
  		proto_tree_add_uint(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, tvb_get_ntohl(tvb, offset + 28));
  	    }
  	    else {
*************** dissect_iscsi(tvbuff_t *tvb, packet_info
*** 1094,1101 ****
  	    offset += 48;
  	}
  
! 	if(pdu_len > offset)
! 	    proto_tree_add_bytes(ti, hf_iscsi_Payload, tvb, offset, pdu_len - offset, tvb_get_ptr(tvb, offset, pdu_len - offset));
      }
  
      return TRUE;
--- 1184,1191 ----
  	    offset += 48;
  	}
  
! 	if(packet_len > offset)
! 	    proto_tree_add_bytes(ti, hf_iscsi_Payload, tvb, offset, packet_len - offset, tvb_get_ptr(tvb, offset, packet_len - offset));
      }
  
      return TRUE;
*************** proto_register_iscsi(void)
*** 1116,1122 ****
  	{ &hf_iscsi_Payload,
  	  { "Payload", "iscsi.payload",
  	    FT_BYTES, BASE_HEX, NULL, 0,
! 	    "Payload" }
  	},
  	{ &hf_iscsi_Opcode,
  	  { "Opcode", "iscsi.opcode",
--- 1206,1212 ----
  	{ &hf_iscsi_Payload,
  	  { "Payload", "iscsi.payload",
  	    FT_BYTES, BASE_HEX, NULL, 0,
! 	    "Payload (includes any header digest)" }
  	},
  	{ &hf_iscsi_Opcode,
  	  { "Opcode", "iscsi.opcode",
*************** proto_register_iscsi(void)
*** 1140,1145 ****
--- 1230,1240 ----
  	    "Immediate delivery" }
  	},
  #endif
+ 	{ &hf_iscsi_Flags,
+ 	  { "Flags", "iscsi.flags",
+ 	    FT_UINT8, BASE_HEX, NULL, 0,          
+ 	    "Opcode specific flags" }
+ 	},
  	{ &hf_iscsi_SCSICommand_X03,
  	  { "X", "iscsi.scsicommand.x",
  	    FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,          
*************** proto_register_iscsi(void)
*** 1551,1556 ****
--- 1646,1652 ----
      static gint *ett[] = {
  	&ett_iscsi_KeyValues,
  	&ett_iscsi_CDB,
+ 	&ett_iscsi_Flags,
      };
  
      /* Register the protocol name and description */