I am opening a TAP device using
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);
The problem I am facing is when an application (say mozilla) wants to send out a packet via the tap device, it needs to get the dst mac address. So the kernel sends out an ARP request. The application I am writing forwards the arp request (via a raw socket on a physical eth device) and gets an arp reply. This arp reply is forwarded back to the tap device, but the kernel refuses to accept this. If I add an arp entry manually, no arp request is generated and there is two way ip packet exchange (mozilla is happy).
Wireshark is able to receive the packet and finds no errors. Same is the case with ICMPv6 packets (neighbor solicitation & advertisement). Any application listening on the device gets the packet intact. But the kernel does not process it for ARP/ICMP.
My question is, why doesn't the kernel accept the arp reply/ICMPv6 msgs? Is there some ioctl call that we need to call?
Edit:
Here is the details of packet captured (tshark output) at the tap device "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
This is the ifconfig output for "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)
As can be seen, the kernel is refusing the accept the ICMPv6 packets as received. But the tx packets are incremented.
The tap device "ethgress" is configured with IPv6 address fc00:1::2 and it an application wants to communicate to fc00:1::1. fc00:1::1 is at the same interface as fc00:1:100 which is responding with the neighbor advertisement (the target ip is fc00:1::1 in that packet) with proper mac address. Tcpdump is able to capture it and wireshark/tshark is able to decode it without and says its a properly formed packet. But Rx counters are not incremented by the kernel, nor does it update its arp cache. Same is the case with ARP packets.
Edit 2:
The network looks like this. There are two external boxes which are configured to be redundant. Only one of them will be active. They are connected to a pc via a physical NIC each. The application I am writing runs on this pc and opens a raw socket on each of the NICs. It also opens a TAP device. The NICs are not configured with an IP address. The TAP device is configured with both IPv4 and IPv6 address. A standard application, say mozilla, opens a socket via the tap device and wants to connect to the active box. For that the kernel generates an ARP request/Neighbor solicitation message on the tap device. The application reads this message and forwards it to both the NICs. The active box responds to the ARP request with an ARP reply which the application reads and writes it to the TAP device. This arp reply packet is captured by tcpdump, but the kernel doesn't update its arp cache. The mac address of both NICs and the TAP device are the same.
Other parameters asked for.
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