4

I am working on a PDP-10 emulator (see https://github.com/Rhialto/klh10 ). The operating system installed inside it may want to communicate with the outside world via IPv4 (which was just gaining use when those machines were popular). For this purpose, the emulator opens a packet filter (or alternatively, a tap device) on the host machine.

Suppose you're on a local network, 10.0.0.x. The emulated OS may use an IPv4 address of, say, 10.0.0.51.

In order for other hosts on the same network to be able to communicate with the virtual host, they send ARP requests for 10.0.0.51. I want the Unix kernel to answer these requests for me with a sensible ethernet address (which is called proxy-ARP).

To make the Unix do this, the emulator does (the equivalent of) "arp -s 10.0.0.51 01:23:45:56:78:9A pub", where the ethernet address of the host OS is used.

On other Unixen than Linux, this has the desired effect. If I attempt to telnet, or ping, to 10.0.0.51 I see the ARP requests go out for the emulated host, and replies come back:

23:13:42.391941 ARP, Request who-has 10.0.0.51 tell 10.0.0.16, length 46
23:13:42.391954 ARP, Reply 10.0.0.51 is-at f6:2b:a4:a0:76:b0 (oui Unknown), length 28

However, on Linux (I have Ubuntu 15.10), this does not work. The entry does show up in the ARP table with "arp -a", although in a weird way:

? (10.0.0.51) at <from_interface> PERM PUB on eth0

I have tried a few seemingly related sysctls to try to enable the proxy ARPing, such as

net.ipv4.conf.all.proxy_arp = 1
net.ipv4.conf.default.proxy_arp = 1
net.ipv4.conf.eth0.proxy_arp = 1

and even

net.ipv4.ip_forward = 1

but none of this helps. What am I missing?

I can test this just using the arp command on the Linux box, a tcpdump for observation, and another box to initiate ARP requests. When I get it to work, I can install any necessary extra setup steps into the emulator.

EDIT: here is a simple scenario to try, if you have 2 machines on the same network, one of which is Linux:

  1. On the Linux box, do sudo arp -s 10.0.0.51 01:23:45:56:78:9A pub. You may need to substitute a different IP address if you're using a different local network; the address should not exist but fit inside your network. 192.168.0.51 could be a possibility. Also, I noticed that Ubuntu refused to accept random ethernet addresses, so you may need to substitute an ethernet address of the eth0 interface.
  2. On the same or other box, sudo tcpdump -i eth0 arp. This will show all ARP requests and replies on the network.
  3. On some other box, which may be a different operating system altogether, do ping 10.0.0.51 (or the address you used, of course). Expected result: the running tcpdump command should show ARP Requests and ARP Replies. If it doesn't, I would like to know what setting is needed to make it happen. And if this is Ubuntu-specific perhaps. The ping will ultimately fail (no host by that IP address is available) but that is immaterial in this test. If it says ping: sendto: Host is down it means it knows there is no ARP Reply.
  • you are missing the ip route to the interface, I think – Rui F Ribeiro Dec 21 '15 at 23:25
  • Well, there isn't really a route to an interface, since there is no interface. The emulator listens to the world via a packet filter (I am using libpcap for the purpose). – Rhialto Dec 21 '15 at 23:28
  • ip route add 10.0.0.51 dev eth0 – Rui F Ribeiro Dec 21 '15 at 23:30
  • Interesting idea; I tried but but alas, it didn't seem to work. I now have TWO entries for this addres though: ? (10.0.0.51) at <incomplete> on eth0 and ? (10.0.0.51) at <from_interface> PERM PUB on eth0 – Rhialto Dec 21 '15 at 23:34
  • does rp_filter = 0 in sysctl helps? (cannot remember the full syntax) – Rui F Ribeiro Dec 21 '15 at 23:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.