Ошибка привязки сокета, когда для адаптера 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
:
Был запрошен несуществующий интерфейс или запрошенный адрес не был локальным.
Очевидная причина
При загрузке устройства мы можем настроить нашу сеть одним из двух способов:
Сетевой IP-адрес и SUBNET автоматически конфигурируются на основе того, что находится в загрузчике по умолчанию (UBOOT), и настраиваются через ОС RTEMS.
Функция 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);
Это также сделает ваш код более переносимым, если это НЕ ваша проблема (т.е. вы работаете на хосте с прямым порядком байтов) и вы однажды попытаетесь скомпилировать в другой системе с прямым порядком байтов.