Отправка/получение широковещательных пакетов (как отправить с 0.0.0.0?)

Модератор: Модераторы разделов

Аватара пользователя
Mifodix
Сообщения: 373
ОС: Fedora 17 x86_64

Отправка/получение широковещательных пакетов

Сообщение Mifodix »

Всем доброго времени!
Пишу DHCP-сервер на С++ и столкнулся с неожиданной проблемой: не могу отправить широковещательный пакет.
Есть сокет, висящий на адресе INADDR_ANY (т. е. 0.0.0.0) и 67 порту. У этого сокета включена опция для работы с широковещательными пакетами (через setsockopt()). Широковещательные сообщения он получает превосходно, но вот отправить что-либо широковещательно не может. Как быть? Приведу простой тестовый пример:

Код: Выделить всё

int main()
{
    int mySocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (mySocket < 0)
    {
        return -1;
    }

    int enableBroadcast = 1;
    if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, &enableBroadcast,
            sizeof(enableBroadcast)) < 0)
    {
        close(mySocket);
        return -1;
    }
    sockaddr_in myAddress;
    myAddress.sin_family = AF_INET;
    myAddress.sin_port = htons(67);//вешаем на порт
    myAddress.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(mySocket, (sockaddr*) &myAddress, sizeof(myAddress)) < 0)
    {
        close(mySocket);
        return -1;
    }
    sockaddr_in to;
    to.sin_family=AF_INET;
    to.sin_port=htons(68);
    to.sin_addr.s_addr=htonl(INADDR_BROADCAST);
    socklen_t toLen=sizeof(to);
    char *mess="trololo";
    int n=sendto(mySocket, mess, 7, 0, (sockaddr*) &to, toLen);
return 0;
}

С "настоящего" адреса 192.168.0.1 я могу отправить широковещательное сообщение без проблем, но не могу получать их. А связать сокеты одновременно и к 0.0.0.0:67, и к 192.168.0.1:67 невозможно:)

P.S. netstat показывает, что стандартный линуксовый dhcp-сервер висит на 0.0.0.0:67, но отправляет как-то с 192.168.0.1:67 (вижу через сниффер wireshark).
Спасибо сказали:
Аватара пользователя
Alxn1
Сообщения: 402
Статус: Красноглазик со стажем
ОС: Mavericks

Re: Отправка/получение широковещательных пакетов

Сообщение Alxn1 »

Может быть 2 сокета открыть?
Спасибо сказали:
Аватара пользователя
skeletor
Сообщения: 1224

Re: Отправка/получение широковещательных пакетов

Сообщение skeletor »

У меня вопрос: а зачем DHCP-серверу посылать broadcast?
Спасибо сказали:
Аватара пользователя
Mifodix
Сообщения: 373
ОС: Fedora 17 x86_64

Re: Отправка/получение широковещательных пакетов

Сообщение Mifodix »

Alxn1 писал(а):
02.06.2011 10:16
Может быть 2 сокета открыть?

пока что других вариантов я не вижу, но ведь стандартный сервер умудряется с 67 порта и слушать, и слать широковещательные сообщения.

У меня вопрос: а зачем DHCP-серверу посылать broadcast?


Например, если появился абсолютно новый клиент в сети: у него ещё нет никакого адреса, следовательно сервер должен слать ему broadcast-сообщение с параметрами . Есть, конечно, вариант слать напрямую на mac-адрес, но это как-то жёстко:)

Фактически вопрос сводится к следующей формулировке:
Как принимать и отправлять широковещательные пакеты с одного сокета?
Спасибо сказали:
Аватара пользователя
skeletor
Сообщения: 1224

Re: Отправка/получение широковещательных пакетов

Сообщение skeletor »

Mifodix писал(а):
02.06.2011 14:34
Например, если появился абсолютно новый клиент в сети: у него ещё нет никакого адреса, следовательно сервер должен слать ему broadcast-сообщение с параметрами . Есть, конечно, вариант слать напрямую на mac-адрес, но это как-то жёстко:)

Неправильно! Только клиент посылает broadcast, причём именно 255.255.255.255. А сервер уже отвечает конкретно этому клиенту. Об этом написано в RFC 2131. И ничего это не жёстко, именно так всё и работает. Если вам в упор хочется слать broadcast'ы - шлите. Это будет создавать лишний трафик в сети. Да и смысл его слать, если клиент не сможет его обработать или ответить?
Это я к тому, что вы создаёте проблему лишённую смысла и пытаетесь её решить. Если я неправ - укажите, где именно.
Спасибо сказали:
Аватара пользователя
Mifodix
Сообщения: 373
ОС: Fedora 17 x86_64

Re: Отправка/получение широковещательных пакетов

Сообщение Mifodix »

skeletor писал(а):
02.06.2011 15:02
Mifodix писал(а):
02.06.2011 14:34
Например, если появился абсолютно новый клиент в сети: у него ещё нет никакого адреса, следовательно сервер должен слать ему broadcast-сообщение с параметрами . Есть, конечно, вариант слать напрямую на mac-адрес, но это как-то жёстко:)

Неправильно! Только клиент посылает broadcast, причём именно 255.255.255.255. А сервер уже отвечает конкретно этому клиенту. Об этом написано в RFC 2131. И ничего это не жёстко, именно так всё и работает. Если вам в упор хочется слать broadcast'ы - шлите. Это будет создавать лишний трафик в сети. Да и смысл его слать, если клиент не сможет его обработать или ответить?
Это я к тому, что вы создаёте проблему лишённую смысла и пытаетесь её решить. Если я неправ - укажите, где именно.


Возможно я действительно ошибаюсь. Давайте разбираться.
Предложение настроек (DHCPOFFER) может отсылаться как unicast, так и broadcast (правда в редком случае). Более того, другие виды сообщений сервера тоже могут быть широковещательными. Так что пример я действительно привёл плохой, не разобравшись толком, но проблема всё равно остаётся. В доказательство привожу текст из RFC 2131:
If the ’giaddr’ field in a DHCP message from a client is non-zero,
the server sends any return messages to the ’DHCP server’ port on the
BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
field is zero and the ’ciaddr’ field is nonzero, then the server
unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
set, then the server broadcasts DHCPOFFER and DHCPACK messages to
0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
messages to the client’s hardware address and ’yiaddr’ address. In
all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
messages to 0xffffffff.

Возникают дополнительные проблемы: как отправить unicast на mac-адрес и можно ли это сделать с сокета, привязанного к 0.0.0.0?
Спасибо сказали:
Аватара пользователя
skeletor
Сообщения: 1224

Re: Отправка/получение широковещательных пакетов

Сообщение skeletor »

Я бы порекомендовал взять исходиники того же isc-dhcp сервера и покопаться в них.
Спасибо сказали:
Аватара пользователя
Mifodix
Сообщения: 373
ОС: Fedora 17 x86_64

Re: Отправка/получение широковещательных пакетов

Сообщение Mifodix »

skeletor писал(а):
02.06.2011 17:50
Я бы порекомендовал взять исходиники того же isc-dhcp сервера и покопаться в них.

Открыл я их и...в общем долго придётся разбираться:)

Считерил я: повесил отправляющий сокет на адрес сервера и 68 порт, а все пакеты отсылаю широковещательно. Удивительно, но клиент прекрасно воспринимает широковещательные DHCPOFFER и DHCPACK:)

Но на будущее всё-таки надо выяснить решения следующих проблем:
1) Как отсылать ширкоовещательные пакеты с адреса 0.0.0.0 и вообще возможно ли это?
2) Если предыдущее невозможно, то как получать широковещательные пакеты, привязав сокет к локальному адресу аля 192.168.0.1?
3) Как отправить пакет напрямую на mac-адрес?

Гугл не помог, к сожалению.
Спасибо сказали:
Аватара пользователя
skeletor
Сообщения: 1224

Re: Отправка/получение широковещательных пакетов

Сообщение skeletor »

Спасибо сказали:
Аватара пользователя
Илуватар
Сообщения: 295
Статус: Antic1tizen 0ne
ОС: Debian Wheezy/Sid amd64

Re: Отправка/получение широковещательных пакетов

Сообщение Илуватар »

Присоединяюсь к вопросу. Как отправить unicast на MAC-адрес?

По вышеприведенной ссылке в основном Winsock.
† Obiit animus, natus est atomus †
Спасибо сказали:
Аватара пользователя
Gloomy
Сообщения: 340
Статус: сочувствующий

Re: Отправка/получение широковещательных пакетов

Сообщение Gloomy »

Mifodix писал(а):
02.06.2011 18:40
1) Как отсылать ширкоовещательные пакеты с адреса 0.0.0.0 и вообще возможно ли это?
2) Если предыдущее невозможно, то как получать широковещательные пакеты, привязав сокет к локальному адресу аля 192.168.0.1?
3) Как отправить пакет напрямую на mac-адрес?

Когда подобное потребовалось мне, не придумал ничего лучше, чем написать свой миниатюрный стек TCP/IP (реализованы ARP, ICMP, IP, UDP). Быть может, существуют и более лёгкие, прямые варианты, но я их не нашёл, хотя и проштудировал всего Р. Стивенса.
Спасибо сказали: