strlen () отказывается читать строку из структуры hostent * - PullRequest
1 голос
/ 28 июля 2010

Я работал над небольшим учебным пособием по созданию базового анализатора пакетов для Linux.У меня все работает, и теперь я хочу добавить сопоставление IP-адреса с хостом.

Все работало до того, как я добавил эту функцию:

void IPtoHostname(char *ipaddress, char *hostname){
    struct hostent *host;
    in_addr_t ip = inet_addr(ipaddress);
    if (!hostname){
        puts("Can't allocate memory...");
        exit(-1);
    }
    host = gethostbyaddr((char *)&ip, 32, AF_INET);
    hostname = strdup(host->h_name);
}

Это в основном берет строковый IP-адрес ("192.168.28.18") ipaddress и заполняет эти IP-адресаимя хоста ("who.cares.com") в имя хоста .

Что происходит, когда strlen ОТКАЗЫВАЕТСЯ , чтобы дать мне что-нибудь (я знаюкак работает strdup , и я сам это проверял) и segfaults.Я использовал GDB, и строка оканчивается нулевым символом, и это не NULL.

Я также тестировал использование необработанного назначения строки со статической структурой:

void IPtoHostname(char *ipaddress, char *hostname){
    static struct hostent *host;
    in_addr_t ip = inet_addr(ipaddress);
    if (!hostname){
        puts("Can't allocate memory...");
        exit(-1);
    }
    host = gethostbyaddr((char *)&ip, 32, AF_INET);
    hostname = host->h_name;
}

И до сих пор нет игры в кости.

Итак, что случилось с strlen ?

Ответы [ 2 ]

4 голосов
/ 28 июля 2010

С strlen все в порядке.Вам нужно передать char ** имя хоста, а затем установить * hostname равным host-> h_name, предполагая, что вы выполняете свой strlen вне IPToHostName.Вы устанавливаете локальную копию вашего указателя имени хоста.

Итак, у вас есть что-то вроде этого:

char myip[]  = "123.45.67.89";
char *myhost = NULL;

IPToHostname(myip, myhost); /* this sets its own local copy of myhost, which is on the stack */

/* At this point, myhost is still null!! */

Если вы измените его так, как показано ниже, он, вероятно, сделает то, что нужноВы хотите.

void IPtoHostname(char *ipaddress, char **hostname)
{
    assert(hostname); /* you'll need to include assert.h for this - it'll abort your program in debug mode if hostname is null */

    struct hostent *host;
    in_addr_t ip = inet_addr(ipaddress);
    if (!hostname)
    {
        puts("Can't allocate memory...");
        exit(-1);
    }
    host = gethostbyaddr((char *)&ip, 32, AF_INET);
    *hostname = strdup(host->h_name);
}

char myip[]  = "123.45.67.89";
char *myhost = NULL;

IPtoHostname(myip, &myhost);
0 голосов
/ 28 июля 2010

Ух ты ... Никогда не борись с POSIX.В конце концов я написал свою функцию так:

#define MAXHOST 256

char *IPtoHostname(char *ipaddress){
    struct in_addr iaddr;
    inet_pton(AF_INET, ipaddress, &iaddr);
    struct sockaddr_in saddr;
    saddr.sin_family =  AF_INET;
    saddr.sin_addr = iaddr;

    char *hostname = (char *)malloc(sizeof(char) * MAXHOST);
    if (getnameinfo((struct sockaddr*)&saddr, 32, hostname, MAXHOST, NULL, 0, 0) == -1){
        puts("Cannot reverse engineer IP");
        return;
    }
    return hostname;
}

И это работает!

...