изменение исходного IP-адреса по умолчанию для привязки сервера udp с INADDR_ANY - PullRequest
2 голосов
/ 02 апреля 2012

Мое приложение открыло сокет UDP, связанный с INADDR_ANY, для прослушивания пакетов на всех интерфейсах, которые есть на моем сервере.Я отправляю ответы через тот же сокет.

Однако при отправке ответа с сервера IP-уровень по умолчанию выбирается IP-уровнем linux в зависимости от того, какой интерфейс выбран для выхода пакета.IP-адрес, связанный с этим интерфейсом, может не быть адресом назначения, с которого этот UDP-сервер получил запрос от клиента.Таким образом, исходный IP-адрес ответа от сервера становится отличным от целевого IP-адреса, с которого поступил запрос.Клиенту может быть неудобно с таким ответом.

Следующая ссылка дает поведение INADDR_ANY с UDP: http://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html

Как я могу изменить это поведение по умолчанию и использовать конкретный IP-интерфейс интерфейса вадрес источника?Это больше контроля над кодом приложения, чтобы решить, какой будет исходный адрес.Также имеет смысл, чтобы адрес источника в ответе совпадал с адресом назначения, с которого поступил запрос.

1 Ответ

1 голос
/ 02 октября 2012

Если у вас есть несколько интерфейсов (один из которых имеет правильный ip), конечно, вы можете привязать интерфейс к исходящему ответу. Взгляните на параметр сокета SO_BINDTODEVICE.

int bind_sock2inf(int sock, char *interface_name)
{
    int status = -1;
    struct ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), interface_name);
    if ( (status = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
                (void *)&ifr, sizeof(ifr))) < 0) {
        log_debug(4, "Failed binding to interface named %s", inf_name);
    }
    else log_debug(3, "Binding to interface %s", inf_name);

    return status;
}

Теперь ваш исходящий запрос должен автоматически использовать IP-адрес, связанный с этим интерфейсом. Единственным недостатком является то, что вы перестаете получать сообщения на любом другом интерфейсе для этого сокета.

Возможные обходные пути:

  1. Используйте отдельный сокет для прослушивания, который не привязан к какому-либо интерфейсу, и другой для отправки и привязки к любому интерфейсу, который вам нужен перед отправкой.

  2. Привязать к интерфейсу перед отправкой сообщения и снова привязать к «», что сразу после отправки очищает предыдущее связывание. Однако вы можете потерять все пакеты, полученные в течение этого периода времени, к которому ваш сокет должен был подключиться, скажем, eth0, и пакеты пришли в eth1.

Также вы можете просто использовать bind () для привязки исходного IP-адреса для исходящего пакета.

...