Я пытаюсь отправить некоторые ARP-пакеты вручную с помощью сети, более конкретно, ARP-запрос для получения MAC-адреса хоста. Я не могу получить окончательный пакет вправо, на проводах, он все еще показывает некоторую несогласованность. Позвольте мне вас через: Вот структура & ЬурейеЕ Я использую все по программе, я определилСтруктура, скопированная в массив байтов .. неправильное выравнивание?
- IP STRUCT (=> in_addr)
- УДС структура (=> ether_addr)
- хост структура состоит из MAC & IP
- пользовательских структур для представления Ethernet кадра & кадр ARP.
Код:
#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; /* usually 6 bytes for ethernet */
u_char proto_addr_len; /*usually 8 bytes for 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 the interface */
extern MAC mac;
extern IP ip;
extern char * interface;
/* Just some vars used to compare with the struct we 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 which can be used as a temp variable */
MAC tmp_mac = { 0x00,0x00,0x00,0x00,0x00,0x00 };
IP tmp_ip = { 0x00000000 };
Вот соответствующая функция:
int
arp_resolve_mac (struct Host * host)
{
struct pkt_arp * arp;
struct pkt_eth * eth;
/*Create the 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 to 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 up sniffing. Better to do it before so less
* prepare time and if any error occurs, no need to send
* the packet. less intrusive */
pcap_init(interface,"arp");
pcap_set_arp_analyzer(arp_analyzer_resolv);
/* Sets the tmp ip variable so we will know if it the right
* response we get or a response coming from another source */
tmp_ip = host->ip;
/* sends the 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 about 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);
}
Проблема: Созданный пакет не совсем верно. Все хорошо до hard_addr_send. После этого поля есть 2 байта 0x00,0x00, (см. В GDB), а затем IP-адрес. Но из-за этого смещения невозможно правильно разобрать этот пакет. Например, в wirehark вместо получения «10.0.0.1» у меня есть «0.0.10.0» для IP. Вот расшифровка БГДА:
/** 14 to pass ethernet frame & 4 + 2 + 2 to go to the addresses section*/
(gdb) x/6xb request+14+4+2+2
/** My 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 my IP address.
* It should be 10.0.0.7 but you can see the 0x0a shifted by 2 bytes */
0x606b1c: 0x00 0x00 0x0a 0x00 0x00 0x07
В методе «arp_resolv_mac», вся информация верна, то есть структура хост содержит полезную информацию и т.д.; Я проверил все. Я просто не получаю это смещение на 2 байта ... В старых версиях, не используя все тезисы new structs (только char *), мне уже удалось создать правильный пакет ARP, поэтому я отчасти интересно, не связано ли это с конструкцией, но мои знания о C не распространяются на объект привязки к памяти ...!
спасибо.
В C компилятор может собирать или размещать информацию в 'struct' по своему усмотрению. Поэтому, если вы хотите конвертировать назад и вперед между массивом байтов и 'struct', вам нужно будет копировать элементы по отдельности, чтобы гарантировать выравнивание. – lurker
Не является ли «нормальное выравнивание» (каждый член присоединен друг к другу в том же порядке, что и в определении) по умолчанию? – Nikkolasg
Они были бы в порядке, но, возможно, дополнены. На выравнивание влияет заполнение. – lurker