Home > Archive > Unix Programming > October 2007 > Why put the structures in a structure when assembling a TCP/IP Packet?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Why put the structures in a structure when assembling a TCP/IP Packet?
|
|
|
|
| Barry Margolin 2007-10-08, 10:10 pm |
| In article <1191893579.696576.127790@k79g2000hse.googlegroups.com>,
grocery_stocker <cdalten@gmail.com> wrote:
> Is there anykind of significance to putting a structure inside another
> stucture when assembling a TCP/IP packet by hand? In the following
> code snippet, struct iphdr and struct tcphdr are inside another
> stucture. The only thing I can think of is that it's to ensure some
> kind of memory alignmen
>
> struct tpack{
> struct iphdr ip;
> struct tcphdr tcp;
> }tpack; /*Why put the structures inside another structure?*/
Because that's how the packet is actually laid out. It also allows
applications that want to do stuff with the whole header to use a single
variable rather than two.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| Skybuck Flying 2007-10-08, 10:10 pm |
| The outer structure functions as a container of a truck.
Everything needs to be inside the container, and the container gets shipped
across the net ;)
Bye,
Skybuck.
| |
| K-mart Cashier 2007-10-09, 4:23 am |
| On Oct 8, 7:04 pm, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article <1191893579.696576.127...@k79g2000hse.googlegroups.com>,
>
> grocery_stocker <cdal...@gmail.com> wrote:
>
>
> Because that's how the packet is actually laid out. It also allows
> applications that want to do stuff with the whole header to use a single
> variable rather than two.
>
> --
I would like to take the time to point out that "googling" for
examples of building TCP/IP packets isn't always a good thing. Half
the sites I found had something like
struct tpack{
struct iphdr ip;
struct tcphdr tcp;
}tpack;
And the other half had something like
struct iphdr ip;
struct tcphdr tcp;
I figured the former, Ie
struct tpack{
struct iphdr ip;
struct tcphdr tcp;
}tpack;
was a little bit more politically correct since it was taken from the
Phrack, while the latter was take someone's personal blog.
| |
| Giorgos Keramidas 2007-10-10, 7:10 pm |
| On Mon, 08 Oct 2007 18:32:59 -0700, grocery_stocker <cdalten@gmail.com> wrote:
> Is there anykind of significance to putting a structure inside another
> stucture when assembling a TCP/IP packet by hand? In the following
> code snippet, struct iphdr and struct tcphdr are inside another
> stucture. The only thing I can think of is that it's to ensure some
> kind of memory alignmen
>
> struct tpack {
> struct iphdr ip;
> struct tcphdr tcp;
> } tpack; /* Why put the structures inside another structure?*/
Mostly because it helps when you want to 'reuse' common parts, like the
definition of struct iphdr.
It appears to be a trick to help with memory alignment, but if you read
the C standard carefully, alignment is not guaranteed.
For more details, see for example the following snippets of the
standard:
% ISO/IEC 9899:1999 (E) -- The C Programming Language
%
% » 6.5.3.4 The sizeof operator
%
% 3 When applied to an operand that has type char, unsigned char,
% or signed char, (or a qualified version thereof) the result is
% 1. When applied to an operand that has array type, the result
% is the total number of bytes in the array.84) When applied to
% an operand that has structure or union type, the result is the
% total number of bytes in such an object, including internal and
% trailing padding.
%
% » 6.7.2.1 Structure and union specifiers
%
% 13 Within a structure object, the non-bit-field members and the
% units in which bit-fields reside have addresses that increase
% in the order in which they are declared. A pointer to a
% structure object, suitably converted, points to its initial
% member (or if that member is a bit-field, then to the unit in
% which it resides), and vice versa. There may be unnamed
% padding within a structure object, but not at its beginning.
%
% 15 There may be unnamed padding at the end of a structure or union.
Paragraph 6.7.2.1(13) and 6.7.2.1(15) explicitly allow padding after
struct object parts, so there is no guarantee that in a struct
definition like the following the two sub-structures occupy adjacent
areas in the memory assigned to an object of the super-structure type:
struct tpack {
struct iphdr ip;
struct tcphdr tcp;
} tpack;
Having said that, there are usually compiler-specific extensions to
"pack" structure memmbers, so that no padding bits are used, but then
you may run into another sort of interesting problem: Unaligned memory
accesses cause traps on some platforms (most notably on SPARC).
This means that if you are using a platform where:
sizeof(int) == 4
sizeof(long) == 8
and unaligned memory accesses cause a hardware trap (that is, to read a
'long' value, the address you are accessing must be a multiple of 8
bytes), and you happen to be unlucky enough to use a "packed" structure
like the "struct pack" defined below:
struct foo {
int f_int;
};
struct bar {
long b_long;
};
struct pack {
struct foo;
struct bar;
} __attribute(__packed); /* compiler extension */
Then simply _reading_ from the pack.bar.b_long value of a structure may
cause a hardware trap (which is allowed even to terminate the program
with some sort of platform-specific error) :-(
| |
| Rainer Weikusat 2007-10-10, 7:10 pm |
| Giorgos Keramidas <keramida@ceid.upatras.gr> writes:
> On Mon, 08 Oct 2007 18:32:59 -0700, grocery_stocker <cdalten@gmail.com> wrote:
>
> Mostly because it helps when you want to 'reuse' common parts, like the
> definition of struct iphdr.
>
> It appears to be a trick to help with memory alignment,
The 'trick to help with alignment' would usually be a union, not a
struct. The declaration above just declares a composite type whose
members are composite types themselves.
> but if you read the C standard carefully, alignment is not
> guaranteed.
The usual meaning of 'alignment' would be that the struct members can
be accessed without causing processor exceptions because they have
been aligned correctly (ie word-sized objects on word-boundaries),
padding the structs themselves as necessary.
[...]
> % » 6.7.2.1 Structure and union specifiers
> %
> % 13 Within a structure object, the non-bit-field members and the
> % units in which bit-fields reside have addresses that increase
> % in the order in which they are declared. A pointer to a
> % structure object, suitably converted, points to its initial
> % member (or if that member is a bit-field, then to the unit in
> % which it resides), and vice versa. There may be unnamed
> % padding within a structure object, but not at its beginning.
> %
> % 15 There may be unnamed padding at the end of a structure or union.
[...]
> Having said that, there are usually compiler-specific extensions to
> "pack" structure memmbers, so that no padding bits are used, but then
> you may run into another sort of interesting problem: Unaligned memory
> accesses cause traps on some platforms (most notably on SPARC).
At least gcc takes care of accessing potentially misaligned structure
members such that those accesses don't trap (at the expense of
performance). And it would greatly surprise me of 'other compilers'
providing similar facilities would not do likewise -- after all,
packing structs would be completely useless if it would result in
unusable data.
| |
| Jorgen Grahn 2007-10-18, 8:08 am |
| ["Followup-To:" header set]
On Mon, 08 Oct 2007 18:32:59 -0700, grocery_stocker <cdalten@gmail.com> wrote:
> Is there anykind of significance to putting a structure inside another
> stucture when assembling a TCP/IP packet by hand? In the following
> code snippet, struct iphdr and struct tcphdr are inside another
> stucture. The only thing I can think of is that it's to ensure some
> kind of memory alignmen
Also ask yourself if there is a reason to use structs *at all*, and
take the portability and performance hit from having to tell your
compiler to disable its normal struct layout. And hoping your CPU
tolerates reading words from odd addresses.
Writing or reading an IP header octet-by-octet isn't exactly hard. I
recently had to debug and fix a bunch of code like this -- it broke in
interesting ways on 64-bit architectures.
/Jorgen
--
// Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
\X/ snipabacken.dyndns.org> R'lyeh wgah'nagl fhtagn!
|
|
|
|
|