Ethereal-dev: Re: [Ethereal-dev] Reassembly & tvb_find_guint8()
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Alex Kirk <alex@xxxxxxxxxxxx>
Date: Thu, 3 Feb 2005 15:41:19 -0500
Quoting Guy Harris <gharris@xxxxxxxxx>: > Alex Kirk wrote: > > > The situation is this: my PDU begins with a 4-byte field that gives me its > > length. Following the instructions in README.developer, I've been able to > get a > > tvb whose size, as shown by tvb_reported_length_remaining(), is correct. > During > > dissection, I have a function that searches for a record terminator with > > tvb_get_guint8() (since these long packets should only ever be a series of > > records with a specific terminator). Using either -1 or the remaining > length of > > the packet (given by, again, tvb_reported_length_remaining(tvb, > > current_offset)), however, tvb_get_guint8() always fails to find record > > terminators that are beyond the current packet's boundary in the tvb. For > > example, if the packet ends at 1440 bytes, but tvb has a reported length of > 2880 > > with a terminator at 1450, tvb_get_guint8() never finds that terminator. > > OK, so what's a "packet" and what's a "record" here? Is a PDU a > "packet" or a "record", or none of the above, e.g. with a "packet" and a > "record" being the same thing, with multiple "packets"/"records" in a PDU? > > It sounds from "since these long packets should only ever be a series of > records with a specific terminator" as if a PDU is a "packet", where the > packet boundaries are determined by the 4-byte length field, and the > "records" are delimited by terminator bytes. > > If so, then, if "the packet ends at 1440 bytes", but "tvb has a reported > length of 2880", does that mean that the 4-byte length field had a value > of 1440 or 2880? > > If it's 1440, then the PDU/packet is 1440 bytes long, so it shouldn't be > surprising that "tvb_get_guint8()" doesn't find a terminator at 1450. > It is, however, surprising that the tvb has a reported length of 2880, > as the tvbuff should have the PDU/packet length as the reported length. > > If it's 2880, then if "the packet ends at 1440 bytes", does that mean > that the "packet" is a record with a 2880-byte PDU, rather than being > the PDU? > > > Is this behavior to be expected? If so, then obviuosly my approach of > treating > > the PDU like one big packet and continuing to add branches to the > dissection > > tree irrespective of packet boundaries is incorrect, and I need some > guidance as > > to how to dissect data that comes in the 2nd -> Nth packets of a PDU > > OK, so *that* sounds as if a "packet" is a "record", rather than a PDU. > If you have a 2880-byte PDU with the first 1440 bytes being the first > packet, and a terminator at an offset of 1450, I presume the extra 10 > bytes are some sort of trailer not considered part of the packet. A "packet" is a straight TCP packet; a "record" is a chunk of data within that packet. Since I appear to have been confusing in my explanation, I'm attaching a sample PCAP: packet #5 is the start of the PDU, and packet #6 is a continuation (as well as the end of the PDU). The 4-byte length field, at the start of packet #5 in this case is 2420; as you'll be able to see, there are exactly that many bytes of data following in the PDU (i.e. in the remainder of packet #5's payload and in the payload of packet #6, just for clarity's sake). After some header data, the first "record" starts at offset 0x5A and goes through offset 0x89 (0xFFFFFFFF is the terminator; my search routine actually scans for 0xFF, and then checks the next three bytes one at a time to see if we've got the terminator). All of the remaining records are identical. > If there is a terminator byte with a particular value at an offset of > 1450 from the beginning of the tvbuff, then a call > > terminator_offset = tvb_find_guint8(tvb, 0, {value}); > > should find that terminator byte, as should any other call with the > offset argument being <= 1450. (Obviously, a call with an offset > 1450 > won't find it.) Is that not happening? Uh, for starters, tvb_find_guint8() takes 4 parameters: the tvb, the starting offset, how far into the tvb to search (with -1 meaning "search through the rest of the packet"), and the byte you're looking for (see comment starting at line 355 of epan/tvbuff.h). But assuming that's just a typo or a minor mental slip on your part, I'll answer the question. I'm calling: next_terminator = tvb_find_guint8(tvb, offset, -1, 255); I had inserted a bunch of fprintf() calls in my function, to watch where terminators were being found, the size of tvbuff, etc. The output should be pretty self-explanatory: ... In find_record_terminator, size of tvb: 2424, tvb remaining, 1056, offset: 1368 Next terminator: 1412 Success: record ends at 1416 In find_record_terminator, size of tvb: 2424, tvb remaining, 1008, offset: 1416 Next terminator: -1 Since I know that there's *at least* one more terminator byte in my tvbuff, that shouldn't be happening. I suspect that the problem is because there are no more terminators left in packet #5, which should end at offset 1448 of tvbuff. Just for reference, here's the code of my terminator-lookup function: /* Find the next record terminator */ int find_record_terminator(tvbuff_t *tvb, int offset, guint32 sizeof_tvb) { gint next_terminator; int c = 0; guint8 next_byte; FILE *fp; fp = fopen("/tmp/ethereal", "a+"); fprintf(fp, "In find_record_terminator, size of tvb: %d, tvb remaining, %d, offset: %d\n", tvb_reported_length_remaining(tvb, 0), tvb_reported_length_remaining(tvb, offset), offset); next_terminator = tvb_find_guint8(tvb, offset, -1, 255); fprintf(fp, "Next terminator: %d\n", next_terminator); if (next_terminator > 0) { /* We found an 0xFF, check the next 3 bytes */ offset = next_terminator; while ((c < 3) && ((next_byte = tvb_get_guint8(tvb, offset)) == 255)) { c++; offset++; } if (c == 3) { /* We've obviously seen all 4 0xFF's, return offset to end of record */ fprintf(fp, "Success: record ends at %d\n", (offset + 1)); fclose(fp); return (offset + 1); } else { /* * One of our bytes wasn't right; no field terminator found. * Call ourself again to see if we can find a terminator later on * in the packet; infinite loops are prevented because, if we * hit the end of the packet, our first if above will fail. */ fprintf(fp, "Calling ourself...\n"); fclose(fp); find_record_terminator(tvb, offset, sizeof_tvb); } } else { /* No 0xFF's before packet end, return -1 for failure */ fprintf(fp, "No more terminators, aww...\n"); fclose(fp); return -1; } /* We should never, ever get here; make compiler warning go away */ fprintf(fp, "Utter insanity!\n"); fclose(fp); return -1; } Hopefully this will clarify what I'm trying to do. Please let me know if there is still any confusion, and I'll be happy to elaborate. Oh, and once we get this settled, perhaps it'd be a good idea to discuss (on- or off-list) what the hell a PDU *actually* is, and how all of this is supposed to work, so I can write some better documentation. :-P Alex Kirk
Attachment:
wins-fake-long-rep-msg.pcap
Description: Binary data
- Follow-Ups:
- Re: [Ethereal-dev] Reassembly & tvb_find_guint8()
- From: Guy Harris
- Re: [Ethereal-dev] Reassembly & tvb_find_guint8()
- References:
- [Ethereal-dev] Reassembly & tvb_find_guint8()
- From: Alex Kirk
- Re: [Ethereal-dev] Reassembly & tvb_find_guint8()
- From: Guy Harris
- [Ethereal-dev] Reassembly & tvb_find_guint8()
- Prev by Date: Re: [Ethereal-dev] Hi I'm a newbie :)
- Next by Date: Re: [Ethereal-dev] [patch] minor bug fix for stun dissector error attribute
- Previous by thread: Re: [Ethereal-dev] Reassembly & tvb_find_guint8()
- Next by thread: Re: [Ethereal-dev] Reassembly & tvb_find_guint8()
- Index(es):