comargo
@comargo
Программист самоучка

Как получить UDP broadcast пакет из «чужой» подсети?

Есть GigE Vision камера подключенная прямым кабелем к компьютеру.
IP камеры: 10.0.0.234/24
IP компьютера: 192.168.42.1/24
Стандартный код передачи broadcast пакета (полный код пока писать не буду, только ключевые моменты псевдокодом:
int s = socket(AF_INET, SOCK_DGRAM, 0);
bind(s, {adapter->IP});
setsockopt(s, SOL_SOCKET, SO_BROADCAST, true);
setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, {1sec});
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, {1sec});
sendto(s, GVCPCmdDeviceDiscovery, {INADDR_BROADCAST});
sleep();
recvfrom(s);


В WireShark я вижу что команда уходит и ответ возвращается:
15	59.752591431	192.168.42.1	255.255.255.255	GVCP	50	> DISCOVERY_CMD 
16	59.752820098	10.0.0.234	255.255.255.255	GVCP	298	< DISCOVERY_ACK


Программа ответа не видит.
Если перевести компьютер в одну подсеть с камерой то все, конечно, работает. Но это не всегда возможно (особенно с точки зрения потребителя).

Под Windows (говорят... не проверил пока еще) все работает (сейчас займусь проверкой, добавлю информацию).

На тот же компьютер было установлено ПО от компании Pleora.
При установки Pleora был сказана интересная фраза про net.ipv4.conf.all.rp_filter. Были опробованы все три значения (0, 1, 2). В режимах 0 и 2 Pleora камеру видит, в режиме 1 - не видит. (как и сказано в коментарии к установке).
При этом указанный выше код не работает совсем. Разницы в пакетах по wireshark не увидел.

Собственно вопрос: Что из опций упущено в тестовом коде? Как получить Broadcast пакет из чужой подсети?
  • Вопрос задан
  • 1449 просмотров
Решения вопроса 1
comargo
@comargo Автор вопроса
Программист самоучка
В общем в итоге я натравил на Pleora strace.
Ответ интересный (для меня):
Создается два сокета (с флагом REUSEADDR):
  1. с привязкой к IP адресу
  2. Без привязки к IP адресу, но с привязкой к порту полученному из первого сокета

Пакеты уходят через первый сокет, а читаются через второй.
<код из strace>
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.42.1")}, 16) = 0
setsockopt(3, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(43861), sin_addr=inet_addr("192.168.42.1")}, [16]) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(43861), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(3, "B\21\0\2\0\0P\1", 8, 0, {sa_family=AF_INET, sin_port=htons(3956), sin_addr=inet_addr("255.255.255.255")}, 16) = 8
nanosleep({0, 200000000}, NULL)         = 0
recvfrom(4, "\0\0\0\3\0\370P\1\0\1\0\2\200\0\0\1\0\0\0\21\34\0\352C\0\0\0\7\0\0\0\7"..., 256, 0, {sa_family=AF_INET, sin_port=htons(3956), sin_addr=inet_addr("10.0.0.234")}, [16]) = 256
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
gbg
@gbg Куратор тега Linux
Любые ответы на любые вопросы
Чтобы получать бродкаст из чужой подсети, это должен быть мультикаст и роутер должен быть настроен на его пропуск.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы