#c #network-programming #ip #ping #icmp
#c #сетевое программирование #ip #ping #icmp
Вопрос:
Я пытаюсь перекодировать команду ping на C в образовательных целях. Отправка ICMP кажется нормальной (я сравнил ее с оригинальным ping на wireshark), но при приеме IP-пакетов у меня возникает следующая проблема:
16 бит общей длины в заголовке IP отличаются от того, что я вижу на wireshark. Я использую функцию recvmsg() для получения данных в буфере, как показано ниже.
ОБНОВЛЕНИЕ: у меня есть такое поведение на macos, но не на виртуальной машине Linux
struct msghdr msg;
struct iovec iov[1];
char databuf[1000];
char datacontrol[1000];
bzero(amp;(msg), sizeof(msg));
bzero(amp;(iov), sizeof(iov));
bzero(amp;(databuf), sizeof(databuf));
bzero(amp;(datacontrol), sizeof(datacontrol));
msg.msg_name = env->addr->ai_addr;
msg.msg_namelen = env->addr->ai_addrlen;
iov[0].iov_base = amp;(databuf[0]);
iov[0].iov_len = sizeof(databuf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = amp;(datacontrol[0]);
msg.msg_controllen = sizeof(datacontrol);
msg.msg_flags = 0;
int retrecv = recvmsg(env.sockfd, amp;(msg), MSG_WAITALL);
Когда я отображаю данные, которые я получаю в databuf, как показано ниже:
for (int i = 0; i < 20; i )
{
for (int j = 7; j >= 0; j--)
printf("%d", ((databuf[i] >> j) amp; 1));
printf(" ");
if (i == 7 || i == 15)
printf("n");
}
У меня это как результат:
01000101 00000000 01000000 00000000 00000000 00000000 00000000 00000000
01110100 00000001 11010111 00110011 11011000 00111010 11010101 01001110
11000000 10101000 00000001 01000100
когда в настоящее время на wireshark у меня:
01000101 00000000 00000000 01010100 00000000 00000000 00000000 00000000
01110100 00000001 11010111 00110011 11011000 00111010 11010101 01001110
11000000 10101000 00000001 01000100
Все биты одинаковы, кроме 3-го и 4-го (общая длина IP-пакета). Я знаю о проблеме малого / большого конца, но я не понимаю, в чем разница.
Спасибо!
Комментарии:
1. Не имеет отношения к вашей проблеме, но семантически ваше использование оператора address-of
amp;
для массивов неверно. Вы должны передать указатель на первый элемент, а не указатель на массив. Например, plaindatabuf
сам по себе будет распадаться на указатель на его первый элемент,amp;databuf[0]
т. Е. Имеющий типchar *
. При использованииamp;databuf
вы получаете указатель на сам массив, который имеет типchar (*)[1000]
. Вам повезло, что оба указывают на одно и то же местоположение, но, как я уже сказал, они семантически отличаются из-за разницы в типе.2. Верно! Я не заметил, но я изменил его. Спасибо!