I'm writing a TCP/IP stack for embedded systems, but I wanted to test it on my host system.
Originally I tried with tap0 + a bridge. But I quickly realized it would make the most sense to bind to the ethernet device.
// devname is "eth0"
fd = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) ); // or AF_PACKET/IPPROTO_RAW / PF_PACKET/htons(ETH_P_ALL)
struct ifreq if_idx;
memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, devname, IFNAMSIZ-1);
if (ioctl(fd, SIOCGIFINDEX, &if_idx) < 0)
Error
struct sockaddr_ll socket_address = {
.sll_ifindex = if_idx.ifr_ifindex,
.sll_halen = 0,
.sll_family = AF_PACKET,
.sll_protocol = htons(ETH_P_ALL),
.sll_hatype = 0,
.sll_pkttype = PACKET_BROADCAST,
};
if ( bind( fd, (const struct sockaddr*)&socket_address, sizeof( socket_address ) ) < 0 )
Error
Then I also tried with this (These do not seem required, except to get the network card into promiscuous mode)
// https://stackoverflow.com/questions/10070008/reading-from-pf-packet-sock-raw-with-read-misses-packets MAYBE?
struct packet_mreq mr = {
.mr_ifindex = socket_address.sll_ifindex,
.mr_type = PACKET_MR_PROMISC,
};
if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0) {
FAIL( "Error setting packet membership\n" );
}
struct ifreq ifr = { 0 };
strncpy(ifr.ifr_name, devname, IFNAMSIZ-1);
if( ioctl( fd, SIOCGIFHWADDR, &ifr ) < 0 )
Error
memcpy( mymac, (char*)ifr.ifr_hwaddr.sa_data, 6 );
int rv = setsockopt( fd, SOL_SOCKET, SO_BINDTODEVICE, devname, strlen(devname) );
I can easily receive packets, with read() and I can reply with write() or send() and everything works perfectly with other computers on the network. But when my local machine sends my IP stack packets, the stack receives the messages and tries sending back. I can see those replies in Wireshark as well when monitoring the device... but the system (userspace/kernel space) does not see the packets.
I tried specifically using sendto() with various sockaddr_ll addresses, and I can't seem to get it to fail, but still, my local system does not receive any of the packets locally.
What am I missing? How do I send packets from a C program to a local network interface and have my local system see them?
Right now, I can't even get my local system to see the arp replies.
EDIT: To clarify, my goal is to make it so my IP stack can reply to other computers on the same network or to the PC the app is running on, as though it were on a LAN.
EDIT: My issue with bridging was that I still gave my ethernet device an address, I should have only given my bridge device an address. With a bridge and code that connects to tap0, I could access the code from both sides and everything worked!