Приведение с необработанными пакетными данными и inet_ntoa () - PullRequest
3 голосов
/ 20 февраля 2012

Попытка написать обработчик для анализатора пакетов.У меня проблемы с кастингом и inet_ntoa().Код выглядит следующим образом:

uint32_t *iphdr_srcaddr = malloc(sizeof(uint32_t));
if (*packet_ethertype == ETHERTYPE_IP) { /* IPv4 */
    // copy packet data to vars
    memcpy(iphdr_srcaddr, packet+26, 4);

    // change to host-byte-order
    *iphdr_srcaddr = ntohl(*iphdr_srcaddr);

    struct in_addr *test;
    test = (struct in_addr*) iphdr_srcaddr;

    printf("uint32_t: %u\n", *iphdr_srcaddr); // Gives the correct long integer for the address
    printf("struct in_addr: %u\n", test->s_addr); // Gives the correct long integer through the cast

    char *test2;
    test2 = inet_ntoa(*test);
}

Теперь, если я попытаюсь printf("%s\n", test), я получу SEGV.Я уверен, что я путаю указатели, значения и выполняю какие-то глупые кастинги.Ошибка, полученная во время запуска ниже:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff787ec61 in __strlen_sse2 () from /lib/libc.so.6

Предупреждение компиляции также, я уверен, что это указывает мне в правильном направлении, но я не уверен, что это значит и как я могу это исправить:

mypcap.c: In function ‘handle_sniffed’:
mypcap.c:61:15: warning: assignment makes pointer from integer without a cast [enabled by default]

Это относится к строке test2 = inet_ntoa(*test);

1 Ответ

7 голосов
/ 20 февраля 2012

Предупреждение, вероятно, указывает на то, что у вас нет правильного прототипа в области действия inet_ntoa() (потому что вы не включили правильный заголовок). Это означает, что компилятор предполагает, что он имеет тип возврата int.

Вы также передаете test на printf(), когда вы должны проходить test2.

Дополнительно:

  • Нет необходимости использовать malloc() для выделения одного uint32_t;
  • Вам не нужно вызывать ntohl(), потому что inet_ntoa() ожидает его ввода в сетевом порядке байтов; и
  • inet_ntoa() устарел - в новом коде следует использовать inet_ntop().

Попробуйте:

#include <arpa/inet.h>

if (*packet_ethertype == ETHERTYPE_IP) { /* IPv4 */
    struct in_addr sin_addr;
    char straddr[INET_ADDRSTRLEN];

    memcpy(&sin_addr.s_addr, packet+26, 4);

    if (inet_ntop(AF_INET, &sin_addr, straddr, sizeof straddr))
        printf("%s\n", straddr);
    else
        perror("inet_ntop");
}
...