Ошибка привязки сокета, когда для адаптера Ethernet установлен пользовательский ip

Эта проблема

В нашей системе, работающей с RTEMS 4.9.2, у нас возникла очень странная проблема с коммуникацией через сокет. Мы настраиваем сокет и используем следующую команду для привязки:

// Bind the socket to set the local port
sockaddr_in localSocketAddress = {0};
localSocketAddress.sin_family = AF_INET;
localSocketAddress.sin_port = (u_short)localPort;
localSocketAddress.sin_addr.s_addr = localAddress;

if (bind( mSocket, (sockaddr *)&localSocketAddress, sizeof(sockaddr_in)) == SOCKET_ERROR)
{
    int errorOut = errno;
    ...

И это работает для UDP-коммуникаций, за исключением странного специфического сценария, который объясняется ниже. Проблема, с которой мы сталкиваемся - это провал bind Позвоните, даже если настройка правильная. Мы получаем ошибку 125 который для RTEMS является EADDRNOTAVAIL:

Был запрошен несуществующий интерфейс или запрошенный адрес не был локальным.

Очевидная причина

При загрузке устройства мы можем настроить нашу сеть одним из двух способов:

  1. Сетевой IP-адрес и SUBNET автоматически конфигурируются на основе того, что находится в загрузчике по умолчанию (UBOOT), и настраиваются через ОС RTEMS.

  2. Функция RTEMS rtems_bsdnet_ifconfig вызывается для изменения IP-адреса единственного интерфейса Ethernet после загрузки.

Для пояснения вариант 2 называется так:

rtems_bsdnet_ifconfig(eth_interface, SIOCSIFADDR, &ipaddr);

Если сеть настроена так, как указано в опции 1, все работает должным образом, но если используется опция 2 (даже в случае, если настройка соответствует параметрам сети, определенным в опции 1), то привязка сокетов завершается неудачно.

Есть ли известная причина или ошибка для RTEMS, которая указывает, что эта привязка потерпит неудачу, если вы перенастроите свой IP?

Дополнительная информация

  • Мы устанавливаем новый IP-адрес (вариант 2), используя метод, который по существу использует ioctl("eht1", SIOCSIFADDR, ...),

  • Если мы связываем наш сокет без указания локального АДРЕСА (т.е. используйте INADDR_ANY) тогда это работает в любом случае.

  • rtems_bsdnet_ifconfig это простой интерфейс для ioctl функция. Это из rtems_glue.c и имеет функцию подписи int rtems_bsdnet_ifconfig(const char *ifname, uint32_t cmd, void *param)

  • Кажется, что все нормальные сетевые функции работают, кроме этой привязки.

  • Посмотрев на это, я подумал, что, возможно, мне нужно сделать больше для сброса моего IP-адреса. Но это не работает, используя первый ответ или даже делать что-то с SIOCSIFFLAGS вызывает прекращение работы всей сети.

1 ответ

Вы не упомянули архитектуру, на которой работаете, но вы устанавливаете порт и адрес в локальном порядке байтов, который может не совпадать с порядком байтов в сети. Самое первое, что я бы попробовал, это:

localSocketAddress.sin_port = htons (localPort); localSocketAddress.sin_addr.s_addr = htonl (localAddress);

Это также сделает ваш код более переносимым, если это НЕ ваша проблема (т.е. вы работаете на хосте с прямым порядком байтов) и вы однажды попытаетесь скомпилировать в другой системе с прямым порядком байтов.

Другие вопросы по тегам