簡體   English   中英

分段故障傳遞函數指針

[英]segmentation fault passing pointer to function

因此,從parseEther方法調用parseIP函數時會發生分段錯誤。
我真的不知道為什么會出現分段錯誤,我只是獲取數據包指針並添加了以太網報頭的長度(14)。
打印地址的輸出為我提供了十六進制的地址,它們相距14,因此我知道指針指向內存中的正確位置。 盡管如此,通過時我仍然遇到分段錯誤?
我錯過了令人眼花obvious亂的明顯東西嗎?
輸出示例: 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);
    }
}

我錯過了令人眼花obvious亂的明顯東西嗎?

我想這取決於您的明顯性標准,但是肯定這是錯誤的:

 struct ip *ip_header = (struct ip*) *packet; 

函數參數packet是一個const unsigned char * ,因此該語句將其指向的單個unsigned char的值轉換為指針,然后將其用作指向struct ipstruct ip 這幾乎可以肯定會產生未定義的行為,這違反了嚴格的別名規則,並且基本上沒有機會產生您實際想要的行為。 改為這樣做:

struct ip *ip_header = (struct ip*) packet;

但是也要注意,將結構類型映射到原始字節數組是一件棘手的事情。 獲取正確的成員順序和數據類型通常並不難,但是C允許結構布局在結構成員之間(和之后)包含任意填充。 特別是,盡管大多數C實現都提供了避免這種情況的機制,但沒有標准的機制。

在這種情況下,您會雙重遇到該問題。 您的struct ipstruct ether_header不僅要服從它,系統的struct in_addr struct ether_header服從它。 盡管您可以控制自己的結構的聲明,但是假設您可以像為inet_ntoa生成參數那樣將struct in_addr映射到原始數據包數據上,這實在是一件很危險的inet_ntoa

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM