Why are there differences between ETH_P_IP and ETH_P_ALL when doing a read() - sockets

I have the following setup:
client(eth0) --- (eth2) linux bridge (eth1) --- (eth1) server
When I open a RAW socket on the linux bridge using
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
I have the socket bound to eth2. When the client sends a packet to the server, wireshark running on the bridge reports the packet with a source mac address of client(eth0) and a destination mac address of server(eth1).
When I do a read(), the first 6 bytes of the data read is the destination mac address, which is correctly read as server(eth1).
However when I change the statement to
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
When I do a read(), the first 6 bytes of the data read shows the destination mac address is linux bridge (eth2).
Why would this be? Is the kernel or ethernet card driver placing its own mac address in the buffer instead of reading off the wire with ETH_P_IP?

For the ETH_P_IP case, what you are describing sounds like a normal "routing" scenario.
(i.e. The routing mac is destination mac.)
It would make sense if your client and server are on different subnet/vlan, and a router in between.
However, the diagram is indicating a linux "bridge".
Does it do bridging only and no routing at all?
EDIT
ETH_P_IP only captures incoming IP packet according to this answer:
Packet Sniffing using Raw Sockets in Linux in C

Related

porting Socket programming from Ubuntu to Windows

I have the following connection in Ubuntu
Linux PC -> Switch (PoE) -> DUT
with the following ip configurations:
Ethernet adaptor Statically assigned
BASE IP (ipv4): 10.0.0.1
subnet : 255.255.255.0
gateway : 10.0.0.0
eth0 network address : 10.0.0.3
This setup enables me to send and receive UDP packets.Works perfectly fine in Ubuntu.
Now in Windows, I have made relevant changes to the python code of the codebase, but the code gets stuck waiting for UDP packets from the Hardware. I have statically assigned the same values as in Ubuntu. I am very new to networking..
(1) I have ensured Firewall is allowing UDP packets
(2) I have made the same IP address,subnet,gateway settings configurations.
Where am I going wrong?
It's impossible to say exactly what goes wrong based on this information.
I'd suggest trying Wireshark from https://www.wireshark.org/.
With that running on your windows PC, you can see if your packets are being sent out or not, and you can also see if the device responds or not. That way you can determine if the problem is in sending or receiving the packets.

Returned UDP packets lacking port and fail to arrive

Golang application with a client and server.
Server uses net.ListenUDP -- client also uses net.ListenUDP, connects to server and sends a packet with conn.WriteToUDP with the server address.
Server receives the packet with ReadFromUDP and grabs the return address. Using this return address, it then sends a large number of packets back to the client.
When running both client and server on local machine, this works perfectly. Using Wireshark I can inspect the UDP packets and see that they contain the source and destination ports - and in the application I can see that they arrive and my various checksum tests show the data is accurate.
I then moved the server off site to a remote machine. The application stops working. I can successfully send the first message from the client to server - this is received just fine. The server sends the response back 'toward' the client - but the client never receives them.
Using Wireshark, I can see that the packets do arrive back on the local machine with the correct IP address. It appears that my network router has performed NAT on the outgoing packets - and has correctly re-addressed response packets to the internal IP.. BUT there is no port.
So I have UDP packets arriving on the correct machine, but no port - so the client application does not receive them. Application times out on ReadFromUDP.
I don't know if it is relevant, but on local machine, Wireshark labels the packets as BT-uTP Utorrent packets. When they come in from remote server, this is what I see in Wireshark - note the lack of Port.
Any thoughts how I can solve this. I didn't think this was a UDP hole punching problem because although I am establishing a connection across a NAT it is with a server not a peer.
This packet is fragmented, You can see this under Internet Protocol Version 4 > Flags.
If you look at the frame as shown on the bottom of the picture you provided you should see the ports.
net.ListenUDP doesn't appear to support fragmentation at the socket level.
Do you have a PPPoe connection? You may need to reduce your packet size being sent by 8 bytes or change the MTU on the routers external interface of the remote side. You may also need to change the local routers MTU if it's on a PPPoe interface.

How to reserve tcp source port on linux?

I'm working on simple traffic tunneling solution (Linux).
Client side creates tun interface, routes all traffic on it, packages all arrived packets and sends to the server side via udp or tcp connection.
Server side expected to work like NAT. Change source ip address, source port (for tcp/udp) put packet on external network interface via sock_raw, listen for response via sock_raw, keep map of original-source-port <-> replaced-source-port and send responses back to the client.
The question is: how should I choose replaced-source-port ? OS chooses them from ephemeral ports. I can't choose it by myself, it would cause conflicts. OS kernel chooses port after I send packet via sock_raw and I have no chance to build original-source-port <-> replaced-source-port map. Even if I choose port by myself – OS kernel will reply with tcp rst to all incoming tcp packets with dst port not associated with particular app.
P.S. I'm not sure on the overall solution for tunneling too. Your suggestions would be highly appreciated.

How to write user-mode NAT without any binding port?

I would like to make my own user-mode NAT application.
I have the folowing scheme:
VM2[192.168.8.2] ------ [192.168.8.1]Win2003[192.168.9.1] ------ [192.168.9.2]VM1
VM3[192.168.8.3] _/
VM4[192.168.8.4] _/
I'm capturing RAW IP packets on 8.1 and 9.1 interfaces.
Some packets from 8.1 are transfered to 9.1 interface this way: 8.2->9.2 replaced by 9.1->9.2
Some packets from 9.1 are transfered to 8.1 interface this way: 9.2->9.1 replaced by 9.2->8.2
My application does not bind any ports at all - it is only capturing from interfaces.
I saw this scenario:
8.2->9.2 translated to 9.1->9.2 contains SYN flag
9.2->9.1 translated to 9.2->8.2 containt SYN+ACK flags
And step 2 contains 9.1->9.2 with RST flag...
Windows Server 2003 resets my NATed connection. I don't want to bind any ports at all.
How can I handle this?
UPDATE:
user1202136, how is it possible to:
Use Windows Firewall to block RST packets from the ports your
user-space NAT uses.
without writing own NDIS driver?
According to the TCP specification, a RST is always sent when an ACK (or SYN+ACK) is received on a port which is not bound to any process. This is done to ensure that node crashes can be reliably detected.
In your case, it is the TCP/IP implementation in Windows Server 2003 that generates the RST packet. You should either prevent the ACK from reaching the TCP layer or block the RST from reaching the wire. You could try doing this in several ways:
Disable TCP (but not IP) on your interfaces.
Use Windows Firewall to block RST packets from the ports your user-space NAT uses.
(Not sure this is working) Use Windows Firewall to block all TCP packets to the ports your user-space NAT uses. I am afraid this would also block packets from reaching your RAW socket.

General sockets UDP programming question

I have an FPGA device with which my code needs to talk. The protocol is as follows:
I send a single non-zero byte (UDP) to turn on a feature. The FPGA board then begins spewing data on the port from which I sent.
Do you see my dilemma? I know which port I sent the message to, but I do not know from which port I sent (is this port not typically chosen automatically by the OS?).
My best guess for what I'm supposed to do is create a socket with the destination IP and port number and then reuse the socket for receiving. If I do so, will it already be set up to listen on the port from which I sent the original message?
Also, for your information, variations of this code will be written in Python and C#. I can look up specific API's as both follow the BSD socket model.
This is exactly what connect(2) and getsockname(2) are for. As a bonus for connecting the UDP socket you will not have to specify the destination address/port on each send, you will be able to discover unavailable destination port (the ICMP reply from the target will manifest as error on the next send instead of being dropped), and your OS will not have to implicitly connect and disconnect the UDP socket on each send saving some cycles.
You can bind a socket to a specific port, check man bind
you can bind the socket to get the desired port.
The only problem with doing that is that you won't be able to run more then one instance of your program at a time on a computer.
You're using UDP to send/receive data. Simply create a new UDP socket and bind to your desired interface / port. Then instruct your FPGA program to send UDP packets back to the port you bound to. UDP does not require you to listen/set up connections. (only required with TCP)