Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Принудительная отправка пакета


Автор: konshyn 13.2.2014, 11:47
Привет!
Есть несколько интерфейсов. Хотя лушче на пальцах объясню.
Есть 1 сетевая карта, ее имя eth0;
На этой сетевой карте 3 vlan'a - eth0.102, eth0.103, eth0.104. У них ip-адреса: 192.168.2.11, 192.168.3.11, 192.168.4.11 соответственно. Шлюз у каждого свой: 192.168.2.1, 192.168.3.1, 192.168.4.1 соответственно
На коммутаторе стоит транковый порт, который видит эти 3 vlan'a + еще один - интернетовский.
по любому из этих vlan'oв можно выйти во внешнюю сеть (интернет), т.е. неважно куда будет default'ный маршрут: на 192.168.2.1, 192.168.3.1 или 192.168.4.1. Отправляться пакеты будут с соответствующего интерфейса eth0.102, eth0.103, eth0.104 - смотря, какой шлюз прописан.

Теперь вопрос: я хочу программным путем выбирать, с какого интерфейса отправить (очень желательно через socket(PF_INET,  SOCK_DGRAM, 0)) пакет. Через интерфейс, который прописан в default'ном маршруте, отправляется без проблем, а через любой другой wireshark ловит arp-запросы, но ответы не приходят и просто не хочет отправлять эти пакеты.

Что я для этого делаю:
Код

char name[] = "eth0.103";
sd = socket(PF_INET, SOCK_DGRAM,  0);
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name);
// дальше заполняю структуру struct sockaddr_in и отправляю пакет
sendto(...)


Как можно заставить систему отправлять с определнного интерфеса пакеты, независимо от того, знает он адресата или нет? Желательно программно. Не прописывая явно шлюзы.

Автор: tzirechnoy 13.2.2014, 15:00
Цитата
Как можно заставить систему отправлять с определнного интерфеса пакеты, независимо от того, знает он адресата или нет?


А куда Вы собрались отправлять эти пакеты если адресат неизвестен?

Автор: konshyn 13.2.2014, 15:40
Цитата(tzirechnoy @  13.2.2014,  15:00 Найти цитируемый пост)
А куда Вы собрались отправлять эти пакеты если адресат неизвестен?

Адресат известен. Linux'у просто не известен шлюз (он есть, но не хочется, чтобы о нем знали). Хочется, чтобы пакет просто вылетел из сетевой карты.

Что получается. У меня есть пакет. Я в структуре задаю адрес получателя, семейство и порт. Отправляю. Ядру нужно добавить заголовки. IP/UDP легко добавить на основе той информации, что я предоставил. Чтобы коммутатор не отбросил этот пакет, нужно в eth-заголовке в поле dest-addr подставить mac коммутатора. Для этого ядро отправляет arp-запрос, мол кто знает такого-то с таким-то IP (который я указал для функции sendto). Все это работает до момента с arp-запросом. Запрос отправляется с этого интерфеса, а ответ не приходит. Вообще не приходит, ни на какой интерфейс. 
Пингануть адрес с этого интерфейса тоже не получается. 

И как бы должно работать, но не работает. А в какую сторону смотреть не знаю. То ли реализовать это нужно по-другому, то ли схема, которую описал в первом сообщении, не такая. То ли вообще нельзя такое сделать, покрайне мере с udp-сокетом.

Автор: feodorv 13.2.2014, 16:30
Цитата(konshyn @  13.2.2014,  12:47 Найти цитируемый пост)
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name);

Если я правильно понял проблему, нужен простой bind() на сокет с номером порта 0 и IP адресом желаемого интерфейса.

Автор: konshyn 13.2.2014, 18:13
Цитата(feodorv @  13.2.2014,  16:30 Найти цитируемый пост)
Если я правильно понял проблему, нужен простой bind() на сокет с номером порта 0 и IP адресом желаемого интерфейса. 

А в чем разница для linux'a в данном случае? Сегодня уже нет возможности проверить.

Автор: tzirechnoy 14.2.2014, 19:07
Цитата
На коммутаторе стоит транковый порт, который видит эти 3 vlan'a + еще один - интернетовский.


Вероятно, на L3 коммутаторе, который, по сути, ужэ работает роутером.

Цитата
Теперь вопрос: я хочу программным путем выбирать, с какого интерфейса отправить (очень желательно через socket(PF_INET,  SOCK_DGRAM, 0)) пакет. 


Вообще, это делается через bind() и задание адреса.
И source-based routing -- админом хоста.

Код
ip route add table 15000 default via 192.168.4.1
ip rule add from 192.168.4.11 lookup 15000



Цитата
Все это работает до момента с arp-запросом. Запрос отправляется с этого интерфеса, а ответ не приходит.


Если ответ не приходит от роутера -- то и смотреть надо конфиг роутера.

Ну, или забить на arp и воспользоваться статикой. Впрочем, это вряд ли поможэт, учитывая, что роутер не считает арп своим -- так что и src адрес вряд ли сочтёт. Хотя можэт и сочтёт, но мне в любом случае лень выпытывать из Вас, какие ещё  тривиальные ошыбки Вы допустили.

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

Автор: konshyn 18.2.2014, 16:11
Цитата(feodorv @  13.2.2014,  16:30 Найти цитируемый пост)
Если я правильно понял проблему, нужен простой bind() на сокет с номером порта 0 и IP адресом желаемого интерфейса. 


Цитата(tzirechnoy @  14.2.2014,  19:07 Найти цитируемый пост)

Вообще, это делается через bind() и задание адреса.
И source-based routing -- админом хоста.


Да, вы правы.


Цитата(tzirechnoy @  14.2.2014,  19:07 Найти цитируемый пост)
Если ответ не приходит от роутера -- то и смотреть надо конфиг роутера.

Ну, или забить на arp и воспользоваться статикой. Впрочем, это вряд ли поможэт, учитывая, что роутер не считает арп своим -- так что и src адрес вряд ли сочтёт. Хотя можэт и сочтёт, но мне в любом случае лень выпытывать из Вас, какие ещё  тривиальные ошыбки Вы допустили.

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

Проблема была именно в SO_BINDTODEVICE. Грубо говоря, приязывалось к физическому устройству, а на логические (ВЛАНы) не выдавала ошибку, но почему-то не отправлялось.
bind() выручил, и там неважно уже, пакетные сокеты, или обычные датаграммные.

но все намного проще делается через libpcap и libnet (особенно последние версии, там все есть, что нужно. для меня smile). не понимаю, чего так долго откладывал его изучение..

tzirechnoy, feodorv, Спасибо за объяснения

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)