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] Reassembling: pinfo and 2 functions

From: Graham Bloice <graham.bloice@xxxxxxxxxxxxx>
Date: Wed, 29 Apr 2009 08:14:54 +0100
gogrady@xxxxxxxxx wrote:
Hello all, 
 
You are probably all sick of me. Which is understandable, i ask an obnoxious 
amount of questions. However, i'm very close to being done and if you can help 
me the sooner you get rid of me. 
 
 
Right now i have a switch case for telling which bnp type i have. if 3 i have: 
save_fragmented = pinfo->fragmented; 
pinfo->fragmented = TRUE; 
frag_msg = fragment_add_seq_next(tvb, 3, pinfo, 
			 multiMessageID,			/* ID for fragments belonging together */ 
			 icom_fragment_table,	/* list of message fragments */ 
			 icom_reassembled_table,	/* list of reassembled messages */ 
			 bnpLength,/* fragment length - to the end */ 
			 TRUE);				/* More fragments? */ 
 
next_tvb = process_reassembled_data(tvb, 3, pinfo, 
				   "Reassembled ICom Message", frag_msg, 
				   &icom_fragment_items, NULL, 
				   bnp_tree); 
pinfo->fragmented = save_fragmented; 
 
4: 
save_fragmented = pinfo->fragmented; 
pinfo->fragmented = TRUE; 
frag_msg = fragment_add_seq_next(tvb, 3, pinfo, 
		 multiMessageID,			/* ID for fragments belonging together */ 
		 icom_fragment_table,	/* list of message fragments */ 
		 icom_reassembled_table,	/* list of reassembled messages */ 
		 bnpLength,/* fragment length - to the end */ 
		 TRUE);				/* More fragments? */ 
 
next_tvb = process_reassembled_data(tvb, 3, pinfo, 
			   "Reassembled ICom Message", frag_msg, 
			   &icom_fragment_items, NULL, 
			   bnp_tree); 
pinfo->fragmented = save_fragmented; 
 
5: 
save_fragmented = pinfo->fragmented; 
pinfo->fragmented = TRUE; 
frag_msg = fragment_add_seq_next(tvb, 3, pinfo, 
			 multiMessageID,			/* ID for fragments belonging together */ 
			 icom_fragment_table,	/* list of message fragments */ 
			 icom_reassembled_table,	/* list of reassembled messages */ 
			 bnpLength,/* fragment length - to the end */ 
			 FALSE);				/* More fragments? */ 
 
next_tvb = process_reassembled_data(tvb, 3, pinfo, 
				   "Reassembled ICom Message", frag_msg, 
				   &icom_fragment_items, NULL, 
				   bnp_tree); 
pinfo->fragmented = save_fragmented; 
multiMessageID++; 
if(next_tvb) 
	dissectPacket( next_tvb, bnp_tree, pinfo ); 
 
Now i'm having trouble with what to make the "ID for fragments" sections as 
having an incremented variable i now realize was stupid. 
Also, on the initial dissecting, next_tvb for case 5 appears to have a value, 
however, when i click on it after, it is NULL. 
 
Any ideas for why it is NULL / a way to ID? 
 

  
Greg,

I've watched this conversation from the sidelines for a while because the only example I know about is the one I did for the DNP 3.0 protocol (packet-dnp.c) which is complicated enough without having to go through re-assembly, but I think the bit you need might be clear enough to understand.  I'm not certain that I've done everything correctly but it seems to work for me.  DNP3.0 sends message data (application layer or AL) in a transport layer message (TL) wrapped in a data link layer (DL) frame that has heavy CRC checking.  The transport layer has a header with flags indicating the first and last messages in a fragmented sequence.

All line numbers I'm quoting refer to the current trunk version of packet-dnp (r).
  The fragments have no common "ID" in the protocol so I needed to invent one as the re-assembly stuff needs one.  To do this I create a conversation and store a sequence number in the conversation.

Around about line 2512 enough fiddling has been done to extract the payload from the encapsulating headers.  The two header flags tr_fir (first message in a fragmented sequence), and tr_fin (last message in a fragmented sequence) have been set from the header.  A non-fragmented message has them both set, so that is the else branch at line 2577.

Around line 2517 If it is a fragmented packet, then pinfo->fragmented is set to true and a check is made for a conversation.  If no conversation is found a new one is created.

Around line 2529 a pointer to the data structure (dnp3_conv_t) is retrieved from the conversation.  If this is null (i.e. no existing data structure) a new structure is allocated, a sequence number is stored in the structure (incrementing a static sequence counter for the next conversation) and the structure added to the conversation data.  Now there is a data structure the sequence number is extracted from it.

Around line 2548 the message fragment (just the payload remember) is added using fragment_add_seq_next() noting that tr_fin is passed in to indicate if this is the last fragment.

Around line 2554 process_reassembled_data() is called to see if reassembly is complete, a tvb* will be returned if this is the case.  This is checked around line 2558 and an appropriate update done to the info column.

Finally at the bottom of the loop, line 2594, if the reassembly produced a tvb or it was a complete message, that is handed off to the application layer dissector.

I hope this helps.

-- 
Regards,

Graham Bloice