Wireshark-dev: Re: [Wireshark-dev] Rearranging packets
From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Fri, 4 Dec 2009 13:54:17 -0800
On Dec 3, 2009, at 11:54 PM, Rach, Darshan wrote:

Hi,

If data is split across packets, how to extract fields (from next packet) in continuation with the previous packet?
As your protocol runs over UDP, which makes no guarantees of packet  
delivery in order (in fact, it makes no guarantees of packet delivery  
at all!), you presumably have a field in the packet to specify the  
order of the UDP datagrams within a full packet.
That appears to be the "block number" field.  You also have a "message  
ID" field, which appears to identify the data packets.  I infer from  
the code that the block number is 0 for the first - or only - block  
within a data message.
What indicates whether a given block is followed by by another block  
within a message?  Is a block a fragment if either
	1) the "last packet" flag is *clear*

or

	2) the block number is non-zero

so that a block with a block number of 0 and the "last packet" flag set is *not* a fragment and does *not* need to be reassembled?
If so, then *most* of your code is correct.  However, what you need to  
do is:
			case OQTP_PACKET_OPCODE_DATA:

				/* Extract the data packet block number */
proto_tree_add_item(oqtp_tree, hf_oqtp_data_packet_block_number, tvb, packet_field_offset, 2, FALSE);
				block_number = tvb_get_ntohs(tvb, packet_field_offset);
				packet_field_offset += 2;

/*save the fragmented state of this packet, so we can restore it later.*/
				save_fragmented = pkt->fragmented;

/* Multiple packets in response - last_packet_flag field is the last packet flag */
				if(((block_number == 0) && (last_packet_flag == 0)) ||
				   (block_number > 0))
				{
					/*darshan*/
					pkt->fragmented = TRUE;

					frag_msg = fragment_add_seq_check(tvb, packet_field_offset, pkt,
													  msgid, /* ID for fragments belonging together */
													  msg_fragment_table, /* list of message fragments */
													  msg_reassembled_table, /* list of reassembled messages */
													  block_number, /* fragment sequence number */
tvb_length_remaining(tvb, packet_field_offset), /* fragment length - to the end */
													  !last_packet_flag); /* More fragments? */

					new_tvb = process_reassembled_data(tvb, packet_field_offset, pkt,
													   "Reassembled OQTP Message",
													   frag_msg,
													   &msg_frag_items,
													   NULL,
													   oqtp_tree);

					/* Reassembled */
					if (frag_msg)
					{
						col_append_str(pkt->cinfo, COL_INFO,
									   "(Reassembled OQTP Response)");
					}
					else
					{
						/* Not last packet of reassembled short message */
						col_append_fstr(pkt->cinfo, COL_INFO,
										"(OQTP fragment %u)", block_number);
					}

					if (new_tvb) /* take it all */
					{
						next_tvb = new_tvb;
					}
					else
					{
/* We cannot dissect anything yet, as we don't have a reassembled packet */
						next_tvb = NULL;
					}
				}
				else
				{
					next_tvb = tvb_new_subset(tvb, packet_field_offset, -1, -1);
				}

				/*restoring fragmented state*/
				pkt->fragmented = save_fragmented;

				if (next_tvb == NULL)
				{
/* Just a fragment - put an item into the protocol tree for the fragment data */ proto_tree_add_text(oqtp_tree, tvb, packet_field_offset, -1, "Fragment data");
				}
				else
				{
					/* Not a fragment, or fragments were reassembled */

					/*Request Satisfied*/
					request_satisfied = tvb_get_guint8(tvb, packet_field_offset);
proto_tree_add_uint(oqtp_tree, hf_request_satisfied, tvb, packet_field_offset, 1, ((request_satisfied & 0x80) >> 7));
					/*Reserved_for_future_use*/
reserved_for_future_use = ((tvb_get_guint8(tvb, packet_field_offset)& 0x7E) >> 1); proto_tree_add_uint(oqtp_tree, hf_reserved_for_future_use, tvb, packet_field_offset, 1, reserved_for_future_use );
					/*No Extended pd syntax*/
no_extended_pd_syntax = (tvb_get_guint8(tvb, packet_field_offset) & 0x1); proto_tree_add_uint(oqtp_tree, hf_no_extended_pd_syntax, tvb, packet_field_offset, 1, no_extended_pd_syntax );
					packet_field_offset += 1;

					/*Number of classifications*/
proto_tree_add_item(oqtp_tree, hf_num_classifications, tvb, packet_field_offset, 1, FALSE);
					num_classifications = tvb_get_guint8(tvb, packet_field_offset);
					packet_field_offset += 1;

for(loop_index = 0 ; loop_index < num_classifications ; + +loop_index)
					{
						...
					}

						...
				}

				break;

I.e., DO NOT attempt to dissect the contents of a fragment - defer dissection until all the fragments are reassembled.