Creating a simple relayd replacement in C (compiled for an ARMv7 WRT router)

I’ve been running into different issues with relayd that I tried to manually fix in the framework, for example: not locking host route entries onto a specific interface, better detection for when a host changes interfaces, better arp table & ip routing management, etc.. However, I’ve still been experiencing some flakiness in it’s operation so I made a simple alternative that I can run which duplicates its most essential features needed for layer 2 bridging:

  • Layer 2 server socket to listen for ARP request packets
  • Layer 2 client sockets to send ARP packets with the routers MAC address inserted into the ARP replies for each host and for each bridged interface
  • Layer 3 UDP socket-based pinging for unknown host detection & discovery (auto IP-to-MAC ARP table entry resolution for each bridged interface)
  • Layer 3 IP routing-table host-entry updates related to which bridged interface the client is currently on

The code is just under 300 lines but it seems to be working so far and will keep testing it out to see if it works better than what I was experiencing with relayd!

https://github.com/stoops/arprb/blob/master/arprb.c?ts=4

--
arp req [42] [1544][256] [192.168.17.175][192.168.16.1]
arp reply [wlan0] [00:be:ee:ca:fe:ff][192.168.17.175] <-> [192.168.16.1]
--
arp req [42] [1544][256] [192.168.16.1][192.168.17.175]
arp reply [br-wan] [00:be:ee:ca:fe:00][192.168.16.1] <-> [192.168.17.175]
--
void send_arps(struct intf *relay, char *who_adr, uchar *dst_mac, char *dst_adr) {
	int sock = relay->sock_arp;
	unsigned char *src_mac = relay->mac;
	struct sockaddr ssa = relay->ssa;

	unsigned int psiz = sizeof(struct arp_pkt);
	struct arp_pkt pkt;

	printf("arp reply !! [%s][%s] -> [%s][%s]\n", relay->smac, who_adr, relay->ifn, dst_adr);

	pkt.frame_type = htons(ETH_P_ARP);
	pkt.hw_type    = htons(ETH_HW_TYPE);
	pkt.proto_type = htons(ETH_P_IP);
	pkt.hw_size    = HW_ADDR_LEN;
	pkt.proto_size = IP_ADDR_LEN;
	pkt.op_code    = htons(ARP_OP_REPLY);

	bcopy(src_mac, pkt.sorc_hw, HW_ADDR_LEN); /* src mac */
	bcopy(dst_mac, pkt.dest_hw, HW_ADDR_LEN); /* dst mac */

	bcopy(src_mac, pkt.sndr_hw, HW_ADDR_LEN); /* who mac */
	ipstr(who_adr, pkt.sndr_ip);              /* who ip  */

	bcopy(dst_mac, pkt.rcpt_hw, HW_ADDR_LEN); /* dst mac */
	ipstr(dst_adr, pkt.rcpt_ip);              /* dst ip  */

	sendto(sock, &pkt, psiz, 0, &ssa, sizeof(ssa));
}

Creating a simple relayd replacement in C (compiled for an ARMv7 WRT router)

One thought on “Creating a simple relayd replacement in C (compiled for an ARMv7 WRT router)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s