pointer arithmetic and packet capture

  • Thread starter Pieter Claassen
  • Start date
P

Pieter Claassen

Ok, I have something that works, but I don't understand why.

I use libpcap to get data of the wire and then initially I casted the
packet to ethernet, then marched along the memory in chunks of bytes for
the length of the ethernet header until I reached the IP header and so
forth...

So, I changed my code and now process the ethernet header after which I
pass the size of the the ethernet header to be deducted and a pointer to
the the location in the memory where the ethernet header starts like

handle_ip(ether_header_size,(void*)eptr);

The function that hanldes the ip has the following prototype:

void handle_ip(u_int32_t ether_hdr_size, void* eptr){

and I use the following function to crawl along the memory (in what I
assume to be byte sized chunks) to the IP header:

ip = (struct ip*)(eptr + ether_hdr_size);

My question is why does this work if I pass a void* in to the functions,
but not if I pass a pointer to a ether struct? I get garbage when I don't
do the void* cast.

Thanks for the help in advance.
Pieter
 
E

Eric Sosman

Pieter said:
Ok, I have something that works, but I don't understand why.

I use libpcap to get data of the wire and then initially I casted the
packet to ethernet, then marched along the memory in chunks of bytes for
the length of the ethernet header until I reached the IP header and so
forth...

So, I changed my code and now process the ethernet header after which I
pass the size of the the ethernet header to be deducted and a pointer to
the the location in the memory where the ethernet header starts like

handle_ip(ether_header_size,(void*)eptr);

The function that hanldes the ip has the following prototype:

void handle_ip(u_int32_t ether_hdr_size, void* eptr){

Minor point: It's far more natural to measure the size
of something with the Standard type `size_t' than with a
made-up type like `u_int32_t_gizmo'.
and I use the following function to crawl along the memory (in what I
assume to be byte sized chunks) to the IP header:

ip = (struct ip*)(eptr + ether_hdr_size);

This is illegal, and the compiler should complain. Since
it didn't I suspect (1) that you may be using gcc, which allows
arithmetic on `void*' pointers as a non-conforming language
extension, and (2) that if so, you're invoking the compiler in
a non-conforming mode. Use the "-ansi -pedantic" switches if
the code's clean enough to withstand them.
My question is why does this work if I pass a void* in to the functions,
but not if I pass a pointer to a ether struct? I get garbage when I don't
do the void* cast.

You need to review pointer arithmetic in your favorite
C textbook. If `p' is a pointer to a Thing object, then
`p+1' is a pointer to the next complete Thing that follows
the first. The "step size" already takes sizeof(Thing) into
account -- more accurately, it takes sizeof(*p) into account,
because it's the type of the pointer that determines the
size of the step. If `p' has the type `Thing*', `p+1' advances
by sizeof(Thing) bytes. If `q' has the type `char*' and
happens to point to the same location `p' does, `q+1' will
advance by just one byte, which will (in general) not be the
same location as `p+1'.

And if `r' is a `void*', `r+1' is an error because
sizeof(*r) is sizeof(void), which is undefined.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top