Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

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.