Well, what UniPCemu's server builds currently do is just inspect the destination IP address, then:
- If it's on the same subnet as the client, send it to the client receiver.
- Otherwise, send it to the default gateway configured.
Then, when receiving packets:
- Anything received from the host network for the client's IP address is received. All other traffic is ignored (for IPv4 packets. IPX packets are always received at this stage).
- Anything received from other clients (above subnet sending) or the specific IP address from the host network (the client's IP address) is matched against itself(receiving it for the client's own IP address) and the client's own subnet-mask based broadcast address (received only if originating from the client network's send function). The IPv4 broadcast address (255.255.255.255) also is received on all clients that are connected, but ignoring the IPv4 address and subnet mask of the client completely (always received).
Note that the host's subnet-based broadcast IP as well as the host's 255.255.255.255 received packets (from the host network) are filtered at the receiver for the host network itself. Thus all those 255.255.255.255 and *.255 packets(from the example, using a /24 subnet mask) are guaranteed to be from the client network. Each client, when trying to receive the packet (this happens in parallel on all the clients at the same time), checks the IP address against the three possibilities to determine if it's to receive it:
1. If it's for it's own IP address, receive it.
2. If it's for it's own subnet's broadcast address (for example, configured for it's /24 mask and matching it's broadcast address with the host bits all set), receive it.
3. If it's for 255.255.255.255, check if the source IP of the packet is on the same subnet. If it matches the subnet, receive it.
If 1, 2 and 3 aren't matched, the packet is discarded in the main loop parsing the packet. This point is where all the receivers for the connected clients on the server handle their sending and receiving of packets (the receiving part in this case). This happens for all connected clients in parallel (so if any clients is to receive the packet, all other clients must finish sending their packets to their clients first before this can start at all. Then all clients get the packet buffered in their own IPv4 buffer and a new packet can arrive (with this step only being retriggered once all clients have nothing to parse anymore). Finally, each client will then check their own buffers for available IPv4 packets and if invalid (according to the above rules) throws it away for a new packet to be able to arrive in parallel with all other clients.
If it's valid for a client on the other hand, it will start sending the packet to the client and remove it's buffered packet once it's completely sent to the client (allowing for all clients to receive a new packet once all other clients have cleared their buffers this or the above mentioned way as well).
So basically, it's receiving it like this:
1. sendpkt -> (host network (ARP-based or default gateway) or loopback buffer (for non-routable packets), depending on the general ARP result(loopback is used for any broadcast from the client as well as the subnet of the destination matching the subnet of the client)).
2. (host network or loopback buffer(priority)) to global receive buffer for IPv4 or IPX.
3. (IPv4 or IPX) global receive buffer to all clients's local buffer in parallel (to provide for broadcasting and the like).
4. Each client then checks it's own buffer for the packet type (round robin-style for priority resolving), discards it if filtering (not own IP, global broadcast(255.255.255.255) or it's own subnet source with subnet broadcast destination), otherwise starts sending it to the client, after which it will discard the packet in it's own packet buffer.
The .0 address isn't being used in any of those checks. So basically, to a client, only it's own IP, destination on it's own subnet and broadcast on it's own subnet are received back on it's interface, with other clients with their subnets receiving if subnet broadcast matches rule 4 with source address in it's own subnet or during a global broadcast(255.255.255.255)).
Also, sending (step 1) to it's own subnet won't perform an actual ARP. Instead, it'll just send the packet to the loopback buffer with the destination MAC address either broadcast (for an subnet broadcast (for example *.255)) or the first MAC address, which is reserved for the loopback to receive it's looped back packets on).
This first MAC address is protected against being the same as the host MAC, and will increase by 1 if it matches it. This MAC address is discarding the packet if received on the host's network, but accepted when on the loopback buffer (it's reserved for the loopback case to be properly detected, which acts like a normal ff:ff:ff:ff:ff:ff broadcast MAC just for the loopback).