gpt4 book ai didi

c - 结构复制到字节数组中..对齐错误?

转载 作者:行者123 更新时间:2023-11-30 15:22:37 25 4
gpt4 key购买 nike

我正在尝试通过网络发送一些手工制作的 ARP 数据包,更具体地说,是一个获取主机 MAC 地址的 ARP 请求。我无法获得正确的最终数据包,在wireshark上它仍然显示出一些不一致。让我带您了解一下:这是我在整个程序中使用的 struct 和 typedef,我已经定义了

  • IP 结构 ( => in_addr )
  • MAC 结构体 ( => ether_addr )
  • 由 MAC 和 IP 组成的 Host 结构
  • 表示以太网帧和 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(&eth->dest,&broadcast_mac);
copy_mac(&eth->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 地址。但由于这个偏移量,无法正确解析这个数据包。例如,在wireshark中,我得到的IP不是“10.0.0.1”,而是“0.0.10.0”。以下是 GDB 的文字记录:

/** 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”中,所有信息都是正确的,即struct Host包含好的信息等;我已经检查了一切。我只是没有得到 2 个字节的偏移量...在旧版本中,不使用所有这些新结构(仅 char *),我已经成功创建了正确的 ARP 数据包,所以我有点想知道如果这不是由于结构引起的,但我对 C 的了解并没有延伸到内存对齐主题......!

谢谢。

最佳答案

问题是你的结构没有打包。一种解决方案是使用打包结构,即

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; /* 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;

但是,这是其他编译器可能不支持的 gcc 特定扩展。

在我看来,最好的解决方案是直接访问字节数组的元素,而不是使用结构体。是的,它添加了几行代码,但它保证也适用于不实现打包结构的编译器。

关于c - 结构复制到字节数组中..对齐错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29175242/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com