Linux bridge of my own making: arp request never succeeds - linux

I wrote a bridge (layer 2 switch) using my Boost.Asio extension. We can easily make additional sockets, endpoints and protocols which meet their type requirements. And my extension uses linux packet socket with AF_PACKET, SOCK_RAW and htons(ETH_P_ALL) (See man 7 packet for more information about packet socket).
Here's an example for explaining how my bridge works:
[PC1] <----> IF1[PC2]IF2 <----> [PC3]
Bridge connects the network interfaces(e.g. eth0) IF1 and IF2 so PC1 can communicate with PC3 via bridge running on PC2. The way to connect interfaces is sending packets received from IF1 to IF2 (and vice versa)
My bridge works under the wired connections as expected, but it doesn't work under the wireless connections. So I tried to find what causes this problem and I found that ARP request never succeeded.
The actual environment which causes this problem is:
[PC1] <--wired--> eth0[PC2]wlan0 <--wireless(802.11g)--> [router1]
Under the environment above, for example, now PC1 tries to send ping(ICMP) packet to router1. To send it to PC3, PC1 has to know the MAC address of router1 so PC1 sends ARP request to FF:FF:FF:FF:FF:FF And my bridge running on PC2 receives it from eth0 and send it to wlan0, but router1 never sends arp reply to PC1.
note: SOCK_RAW packets are passed to and from the device driver without any changes in the packet data. (quoted from man page of packet)
What should I do to allow PC1 to communicate with router1?
Thank you.
Edit:
Here is my Boost.Asio extension.
github: pfpacket/libarex
And this is my bridge using above.
libarex/example/layer2_switch/interface_bridge.cpp

I'm writing up what we discussed in the comments.
It is a common problem that wireless bridging is problematic (under linux at least, I don't know for others). Investigation has shown that most probably the wireless driver or chipset of the hardware used as bridge is incapable of doing bridging operations (brctl failing supports this assumption).
Other possible reasons, as explained in the link above, may be the AP dropping packets with unassociated MAC adresses or the likes.
Additionally, the code works fine for wired interfaces, so it is a hardware problem on some layer. Not much more to say about it.

Related

I am working with vlan, I have to write a server which used vlan interface to accept the packet?

Hints about working with VLAN? I have to write a client-server program, where the client will send a packet through eth0 and the server will receive the packet on VLAN, and to send it to a concerned VLAN client should parse on which command line VLAN will receive it?
Usually there is nothing to do in the application to work with a VLAN. The VLAN is realized using a virtual network interface with its own IP address. From the perspective of the application this is not different from a real network interface with own IP address. The OS will take care about routing and encapsulation of packets and there is nothing to do from the application itself.

Programatically inject packets to virtual interface

We are currently developing a prototype aiming to "bridge" a local virtual interface in Linux to an API sending/receiving Ethernet packets using proprietary hardware. The idea is in the end to use standard libraries and tools transparently with this proprietary hardware.
As a first step ensuring that what we want to do is indeed possible, we made a first version of the prototype bridging a virtual interface to an actual Ethernet interface using libpcap. Here is what we did :
create a local dummy interface on PC1 with a MAC/IP address (192.168.0.1)
configure PC2 with an IP on the same network (192.168.0.2)
link PC1 and PC2 using a non-configured interface on PC1
use a simple 'bridge' program on PC1, developed with libpcap that listens on one interface and inject packets on the second one (using pcap_sendpacket), and the other way around, to bridge dummy interface and actual Ethernet interface
launch ping from PC1 to PC2
When spying on the dummy interface on PC1, we observe ICMP requests and responses, so the bridge program works OK, but the ping tool does not get the ICMP responses at application level.
I'm guessing we inject packets too late in the kernel routing process...or something.
Do you know how to do this properly? Maybe use an alternate type of virtual interface? (bridge, tun/tap...) It cannot be a full system/command line solution since in the end we want to bridge packets to a proprietary API and not to an Ethernet interface, so we need programmatic access to the packets (hence libpcap).
Thanks in advance for your help.
This is not possible with dummy module interfaces in Linux. They can only transmit packets 'downwards', from the kernel to the network hardware device. And, as in the case of dummy interfaces there is no hardware device, packets are discarded when they reach the bottom of this path (dummy_xmit function). You can treat it as a one-way sink.
Here is the call graph:
[applications]
[tcp/ip stack]
|
|
v
pcap_sendpacket -> tpacket_snd -> dev_queue_xmit -> dev_hard_start_xmit -> xmit_one -> netdev_start_xmit -> ndo_start_xmit -> dummy_xmit -> dev_kfree_skb
|
|
pcap_next <- tpacket_rcv <- prot_hook.func <- deliver_skb <-dev_queue_xmit_nit <-----
So, in your case, ping requests from ping application go into the device transmission path. They are discarded at the end of this path, but before that, they are copied and these copies are being passed into the pcap bridge listening on the interface. Bridge application forwards them to the PC2. PC2 answers ping requests and send responses back to the bridge application. The bridge application injects these responses into the device transmission path, they go downwards it and are discarded. But before that, they are copied to all pcap listeners, including tcpdump you use to spy and observe traffic, but excluding your bridge application which injected them:
++ net/core/dev.c
## void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
...
/* Never send packets back to the socket
* they originated from - MvS (miquels#drinkel.ow.org)
*/
if (skb_loop_sk(ptype, skb))
continue;
This is why you see both requests and responses. But responses are not being passed up to the kernel TCP/IP stack and ping application, because this is not possible with dummy interface. They are transmitted downwards to dummy_xmit and discarded.
Therefore, in your case, you should use either TAP interface, or, if you want to still use pcap to exchange packets, veth virtual links.

Tun interface and IPv6

I'd like to ask you a question about tun interfaces, but without OpenVPN.
I have two applications that tunnel traffic:
"sgsn userspace app" reads IP packets from the tun interface "tun sgsn", sends them to "ggsn userspace app", this app writes them to "tun ggsn".
It works the other way too, so I can have a working ssh session, copy files, etc.
So, the packets go this way:
scp client --> sgsn tun interface ---> tunneling through my app -----> ggsn tun interface (dropped here) ----------> sshd
Now, I've tried it with IPv4 and it works, but when I switch to IPv6 the IP packet is written to "tun ggsn" and the IP stack discards it. I've seen it with dropwatch, which says the discard is in ip_rcv+c0.
The routes must be correct because otherwise the packet wouldn't have made it into tun_sgsn in the first place.
I've tried this in both CentOS 6.7 and 7.1 with same result. However, in the 7.1 I only have a single host, so I've done a few tricks with ip6tables to NAT addresses, so the traffic from each user space app (scp and sshd) goes through the tun interfaces. I'm saying this just so it's clear from the beginning, but with the 6.7 I have two machines and no NAT (I'm aware that NAT doesn't work in CentOS 6.7 for IPv6). I've used tcpdump in the tun ggsn interface and the IPv6 datagram seems all right.
Another hint: If I scp to the tun_ggsn interface directly, it works, but I don't think this discards anything with the tun driver, since being in the same machine that means the IP packets don't go down the TCP/IP stack to reach the tun driver (in fact, tcpdump does not capture the packet if I do this).
Any help would be appreciated, thank you very much in advance.

Cannot send or receive packets from my VirtualBox debian linux VM using UDP

For the sake of simplicity, I will refer you to http://en.wikipedia.org/wiki/Berkeley_sockets and the UDP server and client source code there.
I am trying to send a packet using UDP protocol to a linux VirtualMachine server program. Both my host and VM ping well; all packets sent are received in both directions. However my server program is either not receiving any packets, or it is simply not printing. Either way, it isn't printing the confirmation or contents of any packets I send to it from the host.
I do not have another PC handy, but both programs communicate well enough if I stage them on the same computer and Wireshark reports that the packets are being sent.
Mine is a three part question: first, how can I fix this. Second, why would the host and VM receive each others ping messages, but not pass these on to the open sockets of both ends of my UDP system? Finally, do you have any suggestions about the form or intent of this question?
EDIT: I've tried running my VM with the NAT and bridged adapter network setups. However, I can't conceptualize the relationship between those setups and my problems right now.
With NAT networking, the VM gets a private IP address (usually 192.168.x.y) and the host does NAT translation of outgoing packets, and translates reply packets back to the VM. In this mode, all communication must be initiated by the VM -- outside machines can only send packets to the VM in reply to packets the VM sent to them. On the network, the packets will look like they're coming from/going to the host on some unrelated port.
With bridged networking, the VM gets a device that connects directly to the host's network device. In this mode, the VM appears as a separate machine on the same network LAN as the host, with its own IP address. You need to allocate an IP address for it, the same as the host get allocated an IP address (usually via DHCP).
In either case, to debug what is going on, use tcpdump/wireshark on the host to monitor the host's network device. Send packets from the VM, and you should see them in the trace -- they'll appear to come from the host and a different port in the NAT case, and will appear to come from the VM's IP address (and unchanged ports) in the bridged case.
Once you see that, you should be able to send packets back to the VM, though in the NAT case, they must come FROM the address/port the original packet(s) were sent to.
There are known issues with VirtualBox bridged networking not working properly on wifi devices; in general you can only use bridged networking with wired networks.
Oracles VB manual page clear all the terminology used in settings.
I've had similar problem, where my VB program didn't receive any packets, which I solved by setting "Bridged Networking" and setting up proper source/destination IP address in my program by analyzing WLAN interface with wireshark and using ifconfig (or ipconfig) in terminal.

Selecting an Interface when Multicasting on Linux

I'm working with a cluster of about 40 nodes running Debian 4. Each node runs a daemon which sits and listens on a multicast IP.
I wrote some client software to send out a multicast over the LAN with a client computer on the same switch as the cluster, so that each node in the cluster would receive the packet and respond.
It works great, except when I run the client software on a computer that has both LAN and WAN interfaces. If there is a WAN interface, the multicast doesn't work. So obviously, I figure the multicast is incorrectly going over the WAN interface (eth0), rather than the LAN (eth1.) So, I use the SO_BINDTODEVICE socket option to force the multicast socket to use eth1, and all is well.
But I thought that the kernel's routing table should determine that the LAN (eth1) is obviously a lower cost destination for the multicast. Is there some reason I have to explicitly force the socket to use eth1? And, is there some way (perhaps an ioctl call) that I can have the application automatically determine if a particular interface is a LAN or WAN?
If you don't explicitly bind to an
interface, I believe Linux uses the
interface for the default unicast
route for multicast sending.
Linux needs a multicast route, if none exists you will get a EHOSTUNREACH or ENETUNREACH error. The LCM project documents this possible problem. The routing will be overridden if you use the socket option IP_MULTICAST_IF or IPV6_MULTICAST_IF. You are supposed be able to specify the interface via scope-id field in IPv6 addresses but not all platforms properly support it. As dameiss points out, Stevens' Unix Network Programming book covers these details, you can browse most of the chapter on multicast via Google Books for free.
If you don't explicitly bind to an interface, I believe Linux uses the interface for the default unicast route for multicast sending. So my guess is that your default route is via the WAN interface.
Richard Stevens' "Unix Network Programming, Vol. 1", chapter 17 (at least in the 3rd edition), has some good information and examples of how to enumerate the network interfaces.

Resources