因此,在从parseEther方法调用parseIP函数时发生分段错误
我真的不知道为什么我会遇到分段错误,我只是拿着我的数据包指针并添加以太网头的长度(14)。
打印地址的输出给出了十六进制的十六进制地址,所以我知道指针指向内存中的正确位置。尽管如此,我在传递它时仍然会出现分段错误?
我错过了一些令人眼花缭乱的事情吗?
示例输出:
https://s1.postimg.org/96owsptn8v/seg_fault.png
修改
我只是从parseIP中取出代码并将其放在调用它的if语句中,它的工作原理非常好。真奇怪。有人有任何想法吗?
void parseIP(const unsigned char *packet)
{
printf("before we cast ip header");
struct ip *ip_header = (struct ip*) *packet;
printf("Before we initialise length");
short length = ip_header -> ip_len;
printf("Before we initialise headerlength");
int headerlength = ntohs(ip_header-> ip_hl); //iphdr points to header of network packet
printf("No segmentation fault here! \n");
printf("\n Source Ip address \n");
printf("%s", inet_ntoa(ip_header -> ip_src));
printf("\n Destination Ip address \n");
printf("%s", inet_ntoa(ip_header -> ip_dst));
int data_bytes = length - headerlength;
const unsigned char *payload = packet + headerlength;
}
void parseEther(const unsigned char *packet, int length)
{
int i;
int pcount = 0;
struct ether_header *eth_header = (struct ether_header *) packet;
printf("\n\n === PACKET %ld HEADER ===", pcount);
printf("\nSource MAC: ");
for (i = 0; i < 6; ++i)
{
printf("%02x", eth_header->ether_shost[i]);
if (i < 5)
{
printf(":");
}
}
printf("\nDestination MAC: ");
for (i = 0; i < 6; ++i)
{
printf("%02x", eth_header->ether_dhost[i]);
if (i < 5)
{
printf(":");
}
}
int data_bytes = length - ETH_HLEN;
printf(" \n total length - %d -- length of header - %d -- remaining length - %d \n", length, ETH_HLEN, data_bytes);
printf("Packet address - %p\n", packet);
const unsigned char *payload = packet + ETH_HLEN;
printf("Payload address - %p\n", payload);
//payload pointer now points to start of the network header
printf("\nType: %d\n", ntohs(eth_header->ether_type));
if(ntohs(eth_header->ether_type) == 0x0806)
{
printf("ARP detected \n");
// parseARP(payload);
}
else if(ntohs(eth_header->ether_type) == 0x0800)
{
printf("\nIP detected\n");
parseIP(payload);
}
}
答案 0 :(得分:2)
我错过了一些令人眼花缭乱的事情吗?
我想这取决于你的显而易见的标准,但肯定是错的:
struct ip *ip_header = (struct ip*) *packet;
函数参数packet
是const unsigned char *
,因此该语句将其指向的单个unsigned char
的值转换为指针,然后将其用作指向a的指针struct ip
。这几乎肯定会产生未定义的行为,因为它违反了严格的别名规则,并且它产生你真正想要的行为的机会基本上是零。这样做:
struct ip *ip_header = (struct ip*) packet;
但是,请注意,将结构类型映射到原始字节数组是一件棘手的事情。获取正确的成员顺序和数据类型通常不是那么难,但C允许结构布局在结构成员之间(和之后)包含任意填充。特别是,尽管大多数C实现提供了避免这种情况的机制,但它没有标准的机制。
在这种情况下,你有这个问题。您的struct ip
和struct ether_header
不仅受其约束,系统的struct in_addr
也是如此。虽然您可以控制自己的结构的声明,但假设您可以将struct in_addr
映射到原始数据包数据上是危险的,因为您正在为inet_ntoa
生成参数。