hi all, i've a problem in converting struct into short
here's the code i'm using, but it's still error while i'm running it.

typedef struct ip_header;

unsigned short *temp;
memcpy(temp, &ip_header, sizeof(ip_header));

any help will be greatly appreciated.
thx.

How is your struct further subdivided:

For example:

struct
   {
       char cname[8];
       char sname[16];   
       char exam[16];
       char grade;
   } record;

How does your struct look.

typedef struct ip_header{
	unsigned char  headlen:4;	// header len
	unsigned char  ver:4;		// version
	unsigned char  tos;		// type of service
	unsigned short length;	// pack3t length
	unsigned short id;		// ident
	unsigned short offset;		// frag offset
	unsigned char  ttl;		// time to live
	unsigned char  proto;		// protocol
	unsigned short sum;		// checksum
	unsigned long  source;	// source addr
	unsigned long  dest;		// dest addr
}IP_HEADER; /* 20 bytes */

i'm trying to convert it to short so that i can do the checksum.

how in the world did you think you can stuff that structure into a short int ? I'd like to wear a size 32 pants too but my fat butt won't fit into it.

Perform the checksum calculation on the individual members of the structure.

Comments
lol
haha, nice explanation

TRIAD,

your question should be "how do i calculate a checksum" .... NOT "how do i convert a struct to a short".

the quick answer, is that you take your entire header and divide it into 2-byte "words", along their natural 16-bit boundaries, and perform a 1's complement addition on each word for a total checksum that is itself a 2-byte "word"

but before you do that, you've got a few potential problems, in that your header values do not align on the 16-bit boundaries.

your first two CHARs should not be individual 8-bit values, but should be concatenated into one total 8-bit value where VERSION is the 4 MSB's and HEADER LENGTH is the 4 LSB's. -- then that 8-bit value is itself concatenated with the TOS, where VERSION/HEADER are the 8 MSBs and the TOS is the 8 LSBs.

now you have your first "word"

LENGTH, ID, and OFFSET are your next three "words"... but it is important to note here that the first three (3) MSB's of the OFFSET are actually flag bits. (you may already know this and be handling it properly, but its not obvious from your structure.)

TTL and PROTOCOL are concatenated into the fifth "word", where TTL is the 8 MSB's and PROTOCOL is the 8 LSB's.

the HEADER CHECKSUM field will eventaully be the sixth "word" --- but for purposes of calculating this checksum in the first place, you ignore this field at this time (or pretend it is all zeros)

DESTINATION and SOURCE IP ADDRESSES are split into two words each for a total of four (4) words

now you have a total of nine (9) 16-bit words that you will add together, in "1's complement" fashion.

once you find the 1's complement sum of the 9 words, you put that 16-bit value in the checksum field.

and you're done.


a final way to check this, that you've done it correctly -- and this is what is checked at each internet "hop" -- is that the 10 words of the IP header (including the checksum), all add up to 0xFFFF when added together in 1's complement fashion.


.

I hate it when people use acronyms that I don't know the meaning of.

for real, man... me too!


by the way, have you met "TRIAD" ?

he's the original poster

:P

I hate it when people use acronyms that I don't know the meaning of.

what do you mean? sorry.. my english isn't good, because it isn't my mother language..
but i'm trying to understand it..

jephthah,
thx for the post.. i'll try it..
for i post it with the question "convert struct to short" because i have function that do the checksum but it need to be converted to short and i found that they just do this:

inet_cksum((u_short *)ip_hdr, IPHEADERLEN)

to call the function. so that i want to know if it can be done like that..
and the function is:

ushort
inet_cksum (ushort *addr, int len)
{
        register int sum;
        ushort answer;
        register ushort *w;
        register int nleft;
        sum = answer = 0;
        w = addr;
        nleft = len;
        while (nleft > 1)  {
           sum += *w++;
                nleft -= 2;
        }
        if (nleft == 1) {
           *(uchar *)(&answer) = *(uchar *)w ;
                sum += answer;
        }                                                                                            
        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;                          /* truncate to 16 bits */
        return answer;
}

then, i do googling and found that they do this:

struct cert c;
unsigned char buffer[sizeof c];
memcpy(buffer, &c, sizeof c);

to make it into char..

btw, thx for any of your reply... :)

for real, man... me too!


by the way, have you met "TRIAD" ?

he's the original poster

:P

what do you mean? sorry.. my english isn't good, because it isn't my mother language..
but i'm trying to understand it..

Well Duuh! I didn't realize that was triadR, since it was in all caps I assumed it was an abbreviation that jephthah made up :)

TRIAD

the code you show is how they perform 1's complement addition to calculate checksums.

its more complicated implementation of the basic process that I outlined to you above.

...

the last bit of code is a conversion of data from a structure into a string of unsigned chars.

so, yes, you could do something like that to convert your structure into a string of shorts.

be forewarned, though, your problems still exist with your arrangement of header elements, particularly VERSION and HEADER LENGTH should be concatenated into one 8 bit char, not strung across two.

seriously, i reccomend that you try to implement the basic IP header checksum process i described rather than blindly trying to apply some code from the internets that you don't understand.

your first two CHARs should not be individual 8-bit values, but should be concatenated into one total 8-bit value where VERSION is the 4 MSB's and HEADER LENGTH is the 4 LSB's. -- then that 8-bit value is itself concatenated with the TOS, where VERSION/HEADER are the 8 MSBs and the TOS is the 8 LSBs.

actually how can i do this? an example will be perfect..

so, yes, you could do something like that to convert your structure into a string of shorts.

but, can we do that like this?

(u_short *)ip_hdr

i think it convert all the struct content into a single short.

thx. :)

damn. i typed out a huge reply, and just lost it. sorry, but i just can't retype all of that... :(


(1) you need to use shift operators and bitwise-ANDS

(2) no, you cant do that. you need to do something similar to the code you posted that uses "memcopy"

damn. i typed out a huge reply, and just lost it. sorry, but i just can't retype all of that... :(

sadly...

do you mean that even if the result is more than 4 bit, we should just take the 4 MSB's of "VERSION"?

TRIAD,

your question should be "how do i calculate a checksum" .... NOT "how do i convert a struct to a short".

the quick answer, is that you take your entire header and divide it into 2-byte "words", along their natural 16-bit boundaries, and perform a 1's complement addition on each word for a total checksum that is itself a 2-byte "word"

but before you do that, you've got a few potential problems, in that your header values do not align on the 16-bit boundaries.

your first two CHARs should not be individual 8-bit values, but should be concatenated into one total 8-bit value where VERSION is the 4 MSB's and HEADER LENGTH is the 4 LSB's. -- then that 8-bit value is itself concatenated with the TOS, where VERSION/HEADER are the 8 MSBs and the TOS is the 8 LSBs.

now you have your first "word"

LENGTH, ID, and OFFSET are your next three "words"... but it is important to note here that the first three (3) MSB's of the OFFSET are actually flag bits. (you may already know this and be handling it properly, but its not obvious from your structure.)

TTL and PROTOCOL are concatenated into the fifth "word", where TTL is the 8 MSB's and PROTOCOL is the 8 LSB's.

the HEADER CHECKSUM field will eventaully be the sixth "word" --- but for purposes of calculating this checksum in the first place, you ignore this field at this time (or pretend it is all zeros)

DESTINATION and SOURCE IP ADDRESSES are split into two words each for a total of four (4) words

now you have a total of nine (9) 16-bit words that you will add together, in "1's complement" fashion.

once you find the 1's complement sum of the 9 words, you put that 16-bit value in the checksum field.

and you're done.


a final way to check this, that you've done it correctly -- and this is what is checked at each internet "hop" -- is that the 10 words of the IP header (including the checksum), all add up to 0xFFFF when added together in 1's complement fashion.

jephthah,

i know i should not asking for this.. but can you show me the code or a specific reference to do this? i'm really running out of time.. and i dont want to get stuck with this thing.. sorry for disturbing you..

i even do this fool thing but it still not working..:) (it's exactly what you said but i dont understand what do you mean by split the "DESTINATION and SOURCE IP ADDRESSES")

typedef unsigned short u16;
typedef unsigned long u32;

u16 ip_sum_calc(IP_HEADER ip_header)
{
	u16 word16;
	u32 sum=0;
	u16 i;
    
	sum += (u32) (((u_short)ip_header.headlen<<12)&0xF000) + (((u_short)ip_header.ver<<8)&0xFF00) + ((u_short)ip_header.tos&0x00FF);
		
	sum += (u32) ((u_short)ip_header.length&0xFFFF);
	sum += (u32) ((u_short)ip_header.id&0xFFFF);
	sum += (u32) ((u_short)ip_header.offset&0xFFFF);

	sum += (u32) (((u_short)ip_header.ttl<<8)&0xFF00) + ((u_short)ip_header.proto&0x00FF);

	sum += (u32) ((u_short)ip_header.source&0xFFFF);

	sum += (u32) ((u_short)ip_header.source&0xFFFF);
		
	sum += (u32) ((u_short)ip_header.dest&0xFFFF);
		
	sum += (u32) ((u_short)ip_header.dest&0xFFFF);

	sum = ~sum;
		
	return ((u16) sum);
}

Haha.. i've give up on this...
And for the reference.. thanks.. i've forgot bout that..

Sorry to go behind jephthah's back here, but if this is your original structure

typedef struct ip_header{
	unsigned char  headlen:4;	// header len
	unsigned char  ver:4;		// version
	unsigned char  tos;		// type of service
	unsigned short length;	// pack3t length
	unsigned short id;		// ident
	unsigned short offset;		// frag offset
	unsigned char  ttl;		// time to live
	unsigned char  proto;		// protocol
	unsigned short sum;		// checksum
	unsigned long  source;	// source addr
	unsigned long  dest;		// dest addr
}IP_HEADER; /* 20 bytes */

and it's 20 bytes, then you don't have any structure alignment issues. (Or did you add it up and assume it was 20 bytes?)

If that's the case, then I guess you could treat the ip_header structure as 10 consecutive shorts.

size_t x;
IP_HEADER data;
for(x = 0; x < sizeof(IP_HEADER) / sizeof(short); x ++) {
    calculate_checksum_for_short((short *)data + x);
}

Of course, if there's structure alignment happening, this could run into issues as it checksums uninitialized structure padding data. (You could set the whole structure to zeros with memset() to fix this, I suppose.) And I have no idea if it's what you're looking for, because I don't understand what you want. It's just a way to get a checksum of an entire structure by breaking it up into shorts . . . .

TRIAD, sorry for the delay... for some reason, i dont get email notification of responses to threads lately, there's been a lag somewhere.

DWKS, there are no "backs" to go behind, mate. that's why we keep this all in the open. everyone is welcome to contribute. :)

Still, the first problem is his structure is NOT 20 bytes. it's 21. (regardless of what the comment says it is :P ) ...

That's why I'm saying he has alignment issues. "Version" and "HeaderLength" are only 4 bits each, and they need to be concatenated together into one 8-bit char.

if he gets the entire header correctly aligned into a string of 20 bytes, then a method like the one you described will work, and is what i've been trying to tell him do do all along :D

but i dont understand what do you mean by split the "DESTINATION and SOURCE IP ADDRESSES

the IP addresses are 4 bytes each.

in order to caluclate an IP checksum, you need to calculate all values by "performing 1's complement addition on the header broken into ten (10) 2-byte words"

so you split each of the addresses in an "upper half" and a "lower half", each sized 2-bytes.

you can do it like the way DWKS showed you. another way that might be easier to understand is convert the code you posted earlier, to convert your struct into an array of unsigned shorts, like so:

IP_HEADER myHeader;

unsigned short buffer[sizeof(myHeader)/2];
memcpy(buffer, &myHeader, sizeof(myHeader)/2);

in either case, you now have the task of performing the 1's complement addition on each of the unsigned shorts to find the checksum.

but you still need to fix your alignment issues. and make sure you treat the "header checksum" field as being all zeros when performing the checksum.


.

TRIAD, sorry for the delay... for some reason, i dont get email notification of responses to threads lately, there's been a lag somewhere.

That's ok jephthah.. besides, I have to say thank you very much for spending your time replying me..

DWKS, there are no "backs" to go behind, mate. that's why we keep this all in the open. everyone is welcome to contribute. :)

I do agree with that..

it's 20 bytes, then you don't have any structure alignment issues. (Or did you add it up and assume it was 20 bytes?)

Still, the first problem is his structure is NOT 20 bytes. it's 21. (regardless of what the comment says it is :P ) ...

I try to print out the size of ip_header and it's just 20 bytes..
i'm not sure bout this, but i guess the code "headlen:4" and "ver:4" has made the headlen and ver into 4 bits..
When i continue doing my work(without concern to the checksum), i coincidentally found the code and it works perfectly do the ip checksum:

u_short csum (u_short *buf, int nwords) {
	u_long sum=0;

    for( sum=0; nwords > 0; nwords-- )
		sum += *buf++;
		sum = (sum >> 16) + (sum & 0xffff);
		sum += (sum >> 16);
    return (u_short)~sum;
}
//do this to convert header length to unsigned short then calculate the checksum
//u_short = unsigned short
u_short ipbuf[IPHEADERLEN];
memset(ipbuf, 0, IPHEADERLEN);
memcpy(ipbuf, &ip_header, IPHEADERLEN);
ip_header_cksum = csum(ipbuf, IPHEADERLEN);

Finally, i think i've to "marked this thread as solved" for we've known the answer for my question "convert struct to short" is by converting it into string of shorts (the code is shown above). Sorry for discussing other things than the question itself, but i still hope it can be useful for anyone wants to know.
Last, i've to thank jephthah, dwks, Ancient Dragon, and iamthwee for all your reply.. it means a lot to me..

thanks for the replies.

one word of caution. just because it calculates a checksum, doesnt mean the checksum is correct. you still have 21 bytes. the fact that you think you're only using 4 bits for HEADLEN and VERSION, doesnt change teh fact that they are each chars and occupying 8 bits of memory space

thanks for the replies.

one word of caution. just because it calculates a checksum, doesnt mean the checksum is correct. you still have 21 bytes. the fact that you think you're only using 4 bits for HEADLEN and VERSION, doesnt change teh fact that they are each chars and occupying 8 bits of memory space

thx, i'll remember that, but efficiency is not a "word" for me now.. :)

thx, i'll remember that, but efficiency is not a "word" for me now.. :)

we seem to be having a major disconnect here, with comprehension or something.

i'm not talking about "efficiency". I'm taking about your code being "just plain wrong"

because that is what your checksum will be. wrong.

now if you don't care, then i don't care.

but the fact remains, you can't spread a 20 byte IP header across 21 physical bytes and expect the gotdam checksum calculation to work.

i havent even BEGUN to address "efficiency" .

get it?

we seem to be having a major disconnect here, with comprehension or something.

Haha.. i think so.. i think you're talking bout wasting memory space before..

i'm not talking about "efficiency". I'm taking about your code being "just plain wrong"
because that is what your checksum will be. wrong.

Um... well about the wrong checksum, i've tried to catch my packet with wireshark and it's just show me that the checksum is right..

now if you don't care, then i don't care.

all i don't care is wasting the memory space.. :)

but the fact remains, you can't spread a 20 byte IP header across 21 physical bytes and expect the gotdam checksum calculation to work.
i havent even BEGUN to address "efficiency" .

but i used to print out the size of header, and it show me just 20 bytes. how bout this?

get it?

Now, do i get the meaning right? :) Wat a waste for me, learning english for quite a long time but still not good at it.. :)
But i've to proud a little bout myself.. (just a little :( ) hehe.. when i'm saying "efficiency is not a word for me" you still know that i'm talking bout dont care for efficiency.. :)

last time Im going to post here:

it's IMPOSSIBLE for you to get the correct checksum if youve got the IP header spread over 21 bytes, like you do. it CANT be 20 bytes, if you've got the 4-bit "version" and the 4-bit "header length" spread across two chars.

i dont care if english is your second language... you can still COUNT, can't you??

so whatever your problem is, i don't know, but I'm done wasting time on this thread.

.

jephthah, one question for you. HAVE YOU TRIED IT?

i've tried it, and it's just RIGHT.
i'm not here to debate, but i've to say what RIGHT is RIGHT!
i dont know which side do you see and insist on saying its 21 bytes and keep saying the checksum will be wrong.. once again i've to say i've tried it, and it's just right..

maybe you should see
http://www.enderunix.org/docs/en/rawipspoof/ =>Thanks Murat Balaban, i've to use it as a proof..
he has similar ip header as i do.

Comments
whatever. but good for you for not backing down.

okay fine.

i've obviously missed something then, that you're doing somewhere, that gets rid of the extra byte.

good for you, im glad you got it working.

This question has already been answered. Start a new discussion instead.