Я открываю устройство TAP, используя
p->fd = open("/dev/net/tun", O_RDWR);
// skipping error handling code
ifr.ifr_flags = IFF_TAP | IFF_ONE_QUEUE | IFF_NO_PI;
strncpy(ifr.ifr_name, p->name, IFNAMSIZ-1);
result = ioctl(p->fd, TUNSETIFF, &ifr);
// skipping error handling and setting ipv4 address & netmask code
ifr.ifr_flags = (IFF_UP | IFF_RUNNING);
result = ioctl(dummySock, SIOCSIFFLAGS, &ifr);
Проблема, с которой я сталкиваюсь, заключается в том, что когда приложение (скажем, mozilla) хочет отправить пакет через устройство «tap», ему нужно получить MAC-адрес DST. Поэтому ядро отправляет запрос ARP. Приложение, которое я пишу, перенаправляет запрос arp (через необработанный сокет на физическом устройстве eth) и получает ответ arp. Этот ответ arp пересылается обратно на устройство крана, но ядро отказывается принять это. Если я добавляю запись arp вручную, запрос arp не генерируется, и существует двухсторонний обмен ip-пакетами (mozilla счастлив).
Wireshark может получить пакет и не находит ошибок. То же самое имеет место с пакетами ICMPv6 (запрос соседа и реклама). Любое приложение, прослушивающее устройство, получает пакет без изменений. Но ядро не обрабатывает его для ARP / ICMP.
У меня вопрос: почему ядро не принимает ответ arp / ICMPv6 msgs? Есть ли какой-нибудь вызов ioctl, который нам нужен?
Edit:
Вот подробности захвата пакета (вывод tshark) на отводном устройстве "ethgress"
9 16.548328 fc00:1::2 -> ff02::1:ff00:1 ICMPv6 86 Neighbor Solicitation
10 17.243247 fc00:1::100 -> fc00:1::2 ICMPv6 86 Neighbor Advertisement
11 17.548652 fc00:1::2 -> ff02::1:ff00:1 ICMPv6 86 Neighbor Solicitation
12 17.668736 fc00:1::100 -> fc00:1::2 ICMPv6 86 Neighbor Advertisement
Это вывод ifconfig для "ethgress"
ethgress Link encap:Ethernet HWaddr 00:01:02:03:04:05
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:83 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10000
RX bytes:0 (0.0 b) TX bytes:7062 (6.8 KiB)
Как видно, ядро отказывается принимать пакеты ICMPv6 как полученные. Но tx-пакеты увеличиваются.
Для устройства «ethgress» настроен IPv6-адрес fc00: 1 :: 2, и приложение хочет установить связь с fc00: 1 :: 1. fc00: 1 :: 1 находится на том же интерфейсе, что и fc00: 1: 100, который отвечает объявлением соседа (целевой ip - fc00: 1 :: 1 в этом пакете) с правильным mac-адресом. Tcpdump может захватить его, а wireshark / tshark может декодировать его без и говорит, что это правильно сформированный пакет. Но счетчики Rx не увеличиваются ядром и не обновляют свой кэш arp. То же самое и в случае пакетов ARP.
Редактировать 2:
Сеть выглядит следующим образом. Есть два внешних блока, которые настроены как избыточные. Только один из них будет активным. Они подключены к компьютеру через физическую сетевую карту каждый. Приложение, которое я пишу, работает на этом компьютере и открывает необработанный сокет на каждом из сетевых адаптеров. Это также открывает устройство TAP. Сетевые адаптеры не настроены с IP-адресом. Устройство TAP сконфигурировано с адресами IPv4 и IPv6. Стандартное приложение, скажем, mozilla, открывает сокет через устройство крана и хочет подключиться к активной коробке. Для этого ядро генерирует запрос запроса ARP / запроса соседей на устройстве крана. Приложение читает это сообщение и пересылает его на оба сетевых адаптера. Активное поле отвечает на запрос ARP ответом ARP, который приложение считывает и записывает на устройство TAP. Этот ответный пакет arp перехватывается tcpdump, но ядро не обновляет свой кэш arp. MAC-адрес обеих сетевых карт и устройства TAP одинаков.
Запрошены другие параметры.
cat /proc/sys/net/ipv4/conf/all/log_martians
0
cat /proc/sys/net/ipv4/conf/all/rp_filter
1
cat /proc/sys/net/ipv4/conf/all/arp_filter
0