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.
Related
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.
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.
I am developing an application that filters and mangles packets using netfilter queue's. It's rather complicated and needs to perform well so I would like to automate some rigorous testing. To do this I need to be to be able to route some TCP connections through my system, however, I don't want to have to rely on two other machines to act as client and server. I would prefer to run a local client that sends data and a local server that checks the mangled result.
The problem is that my application needs to intercept packets at the PREROUTING stage and so packets generated by the local client can't just be routed to the loopback interface.
So I need some way to inject packets before the prerouting stage and intercept them back after postrouting. If I could somehow use stream sockets to send and receive the data that would be great!
The most straightforward way I can think of doing this is to use a tun device. The tun device allows you to inject packets from userspace that appear to arrive through the tun interface. You could either write code to create and manipulate the tun interface yourself, or you can make use of an application like OpenVPN that already does this. With OpenVPN it would be easy: no special raw sockets or anything: you just send it IP packets encapsulated in UDP and it will make them arrive through a tun interface.
I've been thinking a bit about this and using the tun devices my client and server test applications should be able to use plain linux sockets. I will explain how this can work by describing the path of a packet sent by the test client.
Prerequisites:
a) Two tun devices each providing access to a distinct subnetwork
b) routing table was set up to route traffic to the correct tun device
1) the client sends a packet to an address in the tun1 subnetwork
2) the app attached to tun1 (tun1app) will translate the dst address of the packet to an address in tun2 subnetwork and the source address to an address in the tun1 subnetwork different from the address of the tun1 interface
3) tun1app will send the modified packet back out
4) after routing tun2app will receive the packet and translate the destination address to the tun2 interface and the source address to an address in the tun2 network different from the interface address
5) tun2app will send it back out and the server will receive the packet assuming the destination port is the one the server is listening on
Packets from the server will follow the inverse path.
This seems like the core idea of a very useful tool. Does anyone know of a tool that is able to do this?
All connections from-and-to localhost itself do go over PREROUTING and POSTROUTING. Whoever tells something else is mistaken. (You can verify that with ip6tables -t raw -I OUTPUT -j TRACE, and you will see that it passes through OUTPUT-POSTROUTING-PREROUTING-INPUT when, for example, you ping6 ::1 yourself.)
I have to write a Ethernet PHY loopback test in Linux. I've never done it before and had no clue where to start. After some researching, I came up with the plan for the test, and I wonder if anyone can help me to verify it and give me some pointers to my questions.
This is a external loopback setup. It connects the TX+/- to RX+/- pins for each internal PHY's on the Ethernet switch chip.
So the loopback high level packet path is as follow:
CPU->PHY0(chip)->Ethernet switch(chip)'s internal PHY->PHY0(chip)->CPU
For this test, I plan to
configure the internal PHYs on the Ethernet switch with specific MAC addresses,
pack the Ethernet test packet using CPU's MAC address as the source address and the
MAC address configured in step 1. as the destination address,
send and wait to receive the test packet,
compare sent and received data pattern.
Any suggestions? Also, I wonder if there are functions in Linux that I can use to generate the packets for step 2, and send the packets for step 3.
Thank you very much.
Most Phys can be switched to a test mode. We used the bootloader to write directly to the
Phy and switch to testing mode.
There is also an ioctl taken from documentation/networking/phy.txt
Ethtool convenience functions.
int phy_mii_ioctl(struct phy_device *phydev,
struct mii_ioctl_data *mii_data, int cmd);
The MII ioctl. Note that this function will completely screw up the state
machine if you write registers like BMCR, BMSR, ADVERTISE, etc. Best to
use this only to write registers which are not standard, and don't set off
a renegotiation.
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.