Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Mail Systems
Eclipse Documentation

How To Guides
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Problem Solutions
Privacy Policy




9.3. How to handle transformed data

Some protocols do clever things with data. They might possibly encrypt the data, or compress data, or part of it. If you know how these steps are taken it is possible to reverse them within the dissector.

As encryption can be tricky, let's consider the case of compression. These techniques can also work for other transformations of data, where some step is required before the data can be examined.

What basically needs to happen here, is to identify the data that needs conversion, take that data and transform it into a new stream, and then call a dissector on it. Often this needs to be done "on-the-fly" based on clues in the packet. Sometimes this needs to be used in conjunction with other techniques, such as packet reassembly. The following shows a technique to achieve this effect.

Example 9.13. Decompressing data packets for dissection.

	guint8 flags = tvb_get_guint8(tvb, offset);
	offset ++;
	if (flags & FLAG_COMPRESSED) { /* the remainder of the packet is compressed */
		guint16 orig_size = tvb_get_ntohs(tvb, offset);
		guchar *decompressed_buffer = (guchar*)g_malloc(orig_size);
		offset += 2;
		decompress_packet(tvb_get_ptr(tvb, offset, -1),
				tvb_length_remaining(tvb, offset),
				decompressed_buffer, orig_size);
		/* Now re-setup the tvb buffer to have the new data */
		next_tvb = tvb_new_real_data(decompressed_buffer, orig_size, orig_size);
		tvb_set_child_real_data_tvbuff(tvb, next_tvb);
		add_new_data_source(pinfo, next_tvb, "Decompressed Data");
	} else {
		next_tvb = tvb_new_subset(tvb, offset, -1, -1);
	offset = 0;
	/* process next_tvb from here on */


The first steps here are to recognise the compression. In this case a flag byte alerts us to the fact the remainder of the packet is compressed. Next we retrieve the original size of the packet, which in this case is conveniently within the protocol. If it's not, it may be part of the compression routine to work it out for you, in which case the logic would be different.

So armed with the size, a buffer is allocated to receive the uncompressed data using g_malloc, and the packet is decompressed into it. The tvb_get_ptr function is useful to get a pointer to the raw data of the packet from the offset onwards. In this case the decompression routine also needs to know the length, which is given by the tvb_length_remaining function.

Next we build a new tvb buffer from this data, using the tvb_new_real_data call. This data is a child of our original data, so we acknowledge that in the next call to tvb_set_child_real_data_tvbuff. Finally we add this data as a new data source, so that the detailed display can show the decompressed bytes as well as the original. One procedural step is to add a handler to free the data when it's no longer needed. In this case as g_malloc was used to allocate the memory, g_free is the appropriate function.

After this has been set up the remainder of the dissector can dissect the buffer next_tvb, as it's a new buffer the offset needs to be 0 as we start again from the beginning of this buffer. To make the rest of the dissector work regardless of whether compression was involved or not, in the case that compression was not signaled, we use the tvb_new_subset to deliver us a new buffer based on the old one but starting at the current offset, and extending to the end. This makes dissecting the packet from this point on exactly the same regardless of compression.

  Published under the terms fo the GNU General Public License Design by Interspire