Linux UDP сервер - IP-адрес получателя неправильный - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть встроенное устройство Linux, которое прослушивает UDP-пакеты. Устройство имеет два интерфейса Ethernet, поэтому пакеты могут быть получены на обоих интерфейсах. На определенных UDP-сообщениях / пакетах я должен сделать что-то определенное для интерфейса, на котором он был получен. Поэтому мне нужно определить, какой интерфейс получил пакет.

Я нашел сообщения и примеры в Stackoverflow, показывающие, как извлечь целевой IP из IP_PKTINFO. Это работает нормально, если я тестирую интерфейсы один за другим. При подключении обоих интерфейсов и получении IP-адреса назначения совпадает.

Я заметил, что ifindex не то же самое, но я не понимаю, почему ipi_spec_dst одинаково, когда я ясно получаю пакет на двух разных интерфейсах с двумя разными IP-адресами.

C / C ++ Код, отвечающий за извлечение IP-адреса назначения:

    ssize_t byteCount=recvmsg(f_socket, &message, 0);
    if (byteCount==-1) {
        printf("%s",strerror(errno));
    }

    for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&message); 
         cmsg != NULL; 
         cmsg = CMSG_NXTHDR(&message, cmsg)) 
    {
        if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO) continue;
        struct in_pktinfo *pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
        char* destAddr = (char*) calloc(4, sizeof(char));
        destAddr = inet_ntoa(pi->ipi_spec_dst);
        std::cout << destAddr << " " << std::to_string(pi->ipi_ifindex) << std::endl;
    }

Подключен выход eth0:

172.20.55.9 4
172.20.55.9 4
172.20.55.9 4
...

Выход eth0 подключен:

200.0.0.101 6
200.0.0.101 6
200.0.0.101 6
...

Выходные данные eth0 и eth1 подключены:

172.20.55.9 6
172.20.55.9 4
172.20.55.9 6
172.20.55.9 4
...

Ожидаемый результат:

200.0.0.101 6
172.20.55.9 4
200.0.0.101 6
172.20.55.9 4
...

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

Я могу предоставить больше кода при необходимости.

Код взят из:

  1. Получение адреса назначения пакета UDP
  2. Получить адрес назначения полученного пакета UDP


Любая помощь очень ценится. Спасибо.

-aln

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Я решил эту проблему с помощью ifindex, чтобы получить имя интерфейса, которое затем использовал для выполнения кода, специфичного для интерфейса.

0 голосов
/ 17 сентября 2018

Я думаю, что есть проблема в строках:

char* destAddr = (char*) calloc(4, sizeof(char));
destAddr = inet_ntoa(pi->ipi_spec_dst);
std::cout << destAddr << " " << std::to_string(pi->ipi_ifindex) << std::endl;

Две проблемы:

  • Вы должны использовать ipi_addr вместо ipi_spec_dst (см. man 7 ip )
  • Вам не нужны данные calloc (которые

    • недостаточно велики,
    • неправильно инициализированы,
    • не освобожден.)

Вы можете упростить его следующим образом:

printf("%s %d\n", inet_ntoa(pi->ipi_addr), pi->ipi_ifindex);

Таким образом, чтобы возобновить, ваш цикл может выглядеть следующим образом:

for (   struct cmsghdr *cmsg = CMSG_FIRSTHDR(&message); 
        cmsg != NULL; 
        cmsg = CMSG_NXTHDR(&message, cmsg)) 
{
    if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO) 
        continue;

    struct in_pktinfo *pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
    printf("%s %d\n", inet_ntoa(pi->ipi_addr), pi->ipi_ifindex);
}
...