c - Struct copied into byte array .. wrong alignement? -
i'm trying send manually crafted arp packets on network,more arp request mac address of host. can't final packet right, on wireshark stills shows inconsistency. let me walk through : here struct & typedef use on program , i've defined
- a ip struct ( => in_addr )
- a mac struct ( => ether_addr )
- a host struct composed of mac & ip
- custom struct represent ethernet frame & arp frame.
the code:
#define eth_addr_size 6 #define ip_addr_size 4 typedef u_char packet; typedef struct in_addr ip; typedef struct ether_addr mac; struct host { ip ip; mac mac; }; typedef struct pkt_eth { mac dest; mac src; u_short type; } pkt_eth; typedef struct pkt_arp { u_short htype;/* hardware type => ethernet , etc */ u_short ptype; /*protocol type => ipv4 or ipv6 */ u_char hard_addr_len; /* 6 bytes ethernet */ u_char proto_addr_len; /*usually 8 bytes ipv4 */ u_short opcode; /* type of arp */ mac hard_addr_send; ip proto_addr_send; mac hard_addr_dest; ip proto_addr_dest; } pkt_arp; /* designate our own mac / ip addresses of interface */ extern mac mac; extern ip ip; extern char * interface; /* vars used compare struct use */ const mac broadcast_mac = { 0xff,0xff,0xff,0xff,0xff,0xff }; const mac null_mac = { 0x00,0x00,0x00,0x00,0x00,0x00 }; const ip broadcast_ip = { 0xffffffff }; const ip null_ip = { 0x00000000 }; const struct host null_host = {{ 0x00000000 }, { 0x00,0x00,0x00,0x00,0x00,0x00 }}; /* empty mac address can used temp variable */ mac tmp_mac = { 0x00,0x00,0x00,0x00,0x00,0x00 }; ip tmp_ip = { 0x00000000 };
here relevant function :
int arp_resolve_mac ( struct host * host ) { struct pkt_arp * arp; struct pkt_eth * eth; /*create request packet */ packet * request = arp_packet(request); eth = (struct pkt_eth *) (request); arp = (struct pkt_arp *) (request + eth_size); /* ethernet frame */ copy_mac(ð->dest,&broadcast_mac); copy_mac(ð->src,&mac); /* arp request => mac dest address set null */ copy_mac(&arp->hard_addr_send,&mac); copy_mac(&arp->hard_addr_dest,&null_mac); /* arp request => target ip ! */ copy_ip(&arp->proto_addr_send,&ip); copy_ip(&arp->proto_addr_dest,&host->ip); /* set sniffing. better before less * prepare time , if error occurs, no need send * packet. less intrusive */ pcap_init(interface,"arp"); pcap_set_arp_analyzer(arp_analyzer_resolv); /* sets tmp ip variable know if right * response or response coming source */ tmp_ip = host->ip; /* sends packet */ if(pcap_send_packet(request,arp_packet_size) == -1) { fprintf(stderr,"error while sending arp request packet.\n"); return -1; } .... } packet * arp_packet ( int opcode ) { struct pkt_arp * arp; struct pkt_eth * eth; packet * bytes = (packet *) malloc(arp_packet_size); if(bytes == null) { fprintf(stderr,"could not alloc arp packet.\n"); return null; } eth = (struct pkt_eth *) (bytes); eth->type = htons(ethertype_arp); /* length hard / proto ... */ arp = (struct pkt_arp *) (bytes + eth_size); arp->htype = htons(1); arp->ptype = htons(0x0800); arp->hard_addr_len = eth_addr_size; arp->proto_addr_len = ip_addr_size; /* reply or request */ arp->opcode = opcode == request ? htons(arpop_request) : htons(arpop_reply); return bytes; } /* ----- end of function arp_empty ----- */ void copy_mac(mac * m1,const mac * m2) { memcpy(m1,m2,eth_addr_size); } void copy_ip(ip * i1,const ip * i2) { memcpy(i1,i2,ip_addr_size); } void copy_host(struct host * h1,const struct host * h2) { copy_mac(&h1->mac,&h2->mac); copy_ip(&h1->ip,&h2->ip); }
problem: created packet not quite right. fine hard_addr_send. after field, there 2 bytes 0x00,0x00, (seen in gdb) , ip address. due offset, it's impossible correctly parse packet. example,in wireshark, instead of getting "10.0.0.1", i've got "0.0.10.0" ip. here transcript of gdb :
/** 14 pass ethernet frame & 4 + 2 + 2 go addresses section*/ (gdb) x/6xb request+14+4+2+2 /** mac address , field hard_addr_send. it's good. */ 0x606b16: 0x34 0x67 0x20 0x01 0x9a 0x67 (gdb) x/6xb request+14+4+2+2+6 /** 6bytes later, supposedly ip address. * should 10.0.0.7 can see 0x0a shifted 2 bytes */ 0x606b1c: 0x00 0x00 0x0a 0x00 0x00 0x07
in method "arp_resolv_mac", info right, i.e. struct host contains information etc; i've checked everything. don't offset 2 bytes ... in older versions, not using theses new structs (only char *), i've succeed @ creating right arp packet, i'm kind of wondering if not due struct, knowledge of c not extend memory alignement subject ...!
thank you.
the problem structs not packed. 1 solution use packed structs, i.e.
typedef struct __attribute__ ((__packed__)) pkt_arp { u_short htype;/* hardware type => ethernet , etc */ u_short ptype; /*protocol type => ipv4 or ipv6 */ u_char hard_addr_len; /* 6 bytes ethernet */ u_char proto_addr_len; /*usually 8 bytes ipv4 */ u_short opcode; /* type of arp */ mac hard_addr_send; ip proto_addr_send; mac hard_addr_dest; ip proto_addr_dest; } pkt_arp;
however, gcc-specific extension other compilers may not support.
in opinion, best solution accessing elements of byte array directly instead of using structs. yes, adds few lines of code, it's guaranteed work compilers don't implement packed structs too.
Comments
Post a Comment