So I'm trying to unmarshall ethernet frames eth and ip headers. I have a program skeleton that reads input data from file and serves me a struct with the frame data.
I have googled and read other posts on the topic but i'm getting nowhere. For example: Data Alignment with network programming http://en.wikipedia.org/wiki/Data_structure_alignment
I not sure what the problem is. Obviously im new to C.
If I just try using memcpy and copy data into my structs of eth and ip headers most of the data comes out nice, but not the ip adresses in my ip struct. I also tried reading from the input struct in 1byte, 2byte and 4byte chunks but it doesn't give me correct data.
Here is an example of input data frame from the input file:
200 0000 0002 0200 0000 0012 0800 4500 0026 17d4 81e7 ff01 0000 0a02 0002 0c0c 0c0c 0000 e802 c04b 0004 3e89 3325 0006 ddef 0809
Here is the header structs im using
struct ethhdr{
char da[6];
char sa[6];
uint16_t pt;
};
typedef struct ethhdr ethhdr;
struct iphdr{
#ifdef WORDS_BIGENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#else
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
uint8_t ip_tos; /* type of service */
uint16_t ip_len; /* total length */
uint16_t ip_id; /* identification */
uint16_t ip_off; /* fragment offset field */
uint8_t ip_ttl; /* time to live */
uint8_t ip_p; /* protocol */
uint16_t ip_sum; /* checksum */
uint32_t ip_src, ip_dst; /* source and dest address */
};
typedef struct iphdr iphdr;
The input data struct that im being served.
struct fe_context{
char *pkt; /* Pointer to packet */
size_t len; /* Length of packet */
void *if_in; /* Incoming interface - handle */
};
typedef struct fe_context fe_context;
Sample code of how I've tied to read the data.
int fe_process(fe_context *c)
{
printf("\n\nPacket received!\n");
printf("memcpy to header structs:\n");
ethhdr * ethh = (ethhdr *) malloc(sizeof(ethhdr));
iphdr * iph = (iphdr *) malloc(sizeof(iphdr));
memcpy(ethh, c->pkt, sizeof(ethhdr));
memcpy(iph, c->pkt+sizeof(ethhdr), sizeof(ethhdr));
printf("MAC SA: %02x:%02x:%02x:%02x:%02x:%02x\n", ethh->sa[0], ethh->sa[1], ethh->sa[2],
ethh->sa[3], ethh->sa[4], ethh->sa[5]);
printf("MAC P: %04x\n", ntohs(ethh->pt));
printf("IP Ver: %x\n", ntohl(iph->ip_v));
printf("IP IHL: %x\n", ntohl(iph->ip_hl));
printf("IP TTL: %i\n", iph->ip_ttl);
printf("IP Checksum: %x\n", ntohl(iph->ip_sum));
printf("IP SRC: %08x\n", ntohl(iph->ip_src));
printf("IP DST: %08x\n", ntohl(iph->ip_dst));
char * cp = c->pkt;
printf("\nPacket read by char:\n");
char data;
int p;
for(p = 0; p < 52; p++) {
data = *cp;
cp++;
printf("%02x", data);
if(p%2==1) {
printf(" ");
}
}
printf("\n\n");
cp = c->pkt;
printf("Packet read by uint16_t:\n");
uint16_t data16;
for(p = 0; p < 52/2; p++) {
data16 = *cp;
cp+=2;
printf("%04x ", ntohs(data16));
}
printf("\n\n");
cp = c->pkt;
printf("Packet read by uint32_t:\n");
uint32_t data32;
for(p = 0; p < 52/4; p++) {
data32 = *cp;
cp+=4;
printf("%08x ", ntohl(data32));
}
printf("\n\n");
return 0;
}
And here is its output with the above test data input.
Packet received!
memcpy to header structs:
MAC SA: 02:00:00:00:00:12
MAC P: 0800
IP Ver: 4000000
IP IHL: 5000000
IP TTL: 255
IP Checksum: 0
IP SRC: 0a020000
IP DST: 00000000 // It looks good up until here. this should be 0c0c0c0c
Packet read by char:
0200 0000 0002 0200 0000 0012 0800 4500 0026 17ffffffd4 ffffff81ffffffe7 ffffffff01 0000 0a02 0002 0c0c 0c0c 0000 ffffffe802 ffffffc04b 0004 3effffff89 3325 0006 ffffffddffffffef 0809
Packet read by uint16_t:
0200 0000 0000 0200 0000 0000 0800 4500 0000 1700 81ff ffff 0000 0a00 0000 0c00 0c00 0000 e8ff c0ff 0000 3e00 3300 0000 ddff 0800
Packet read by uint32_t:
02000000 00000000 00000000 08000000 00000000 81ffffff 00000000 00000000 0c000000 e8ffffff 00000000 33000000 ddffffff
As you can see the data in the structs is fine all the way until the DST IP. Could this be because of padding/data alignment? It would appear, by looking at the char read, that the problem somehow happens in the ip header part of the data? When I read by char, where does these 'f's come from?
I tried checking the c->pkt pointer adress and its even. I'm not even sure if that matters though? Im thinking that it will always be since malloc got that for me. Whats the right way of reading this data for for parsing/unmarshalling? I am going to be doing alterations to this data so I would prefer to get the data into neat structs.
Do I have a simple error in my code or am I going about it the wrong way? Any help is much appreciated!