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!

arp req [42] [1544][256] [][]
arp reply [wlan0] [00:be:ee:ca:fe:ff][] <-> []
arp req [42] [1544][256] [][]
arp reply [br-wan] [00:be:ee:ca:fe:00][] <-> []

... snippet ...

void send_arp(struct intf relay, char *who_adr, uchar *dst_mac, char *dst_adr) {
	printf("arp reply [%s] [%s][%s] <-> [%s]\n", relay.ifn, relay.smac, who_adr, dst_adr);

	int sock = relay.sock;
	unsigned char *src_mac = relay.mac;
	struct sockaddr ssa = relay.ssa;

	struct in_addr src_adr;
	struct arp_packet pkt;

	pkt.frame_type = htons(FRAME_HW_TYPE);
	pkt.hw_type    = htons(ETHER_HW_TYPE);
	pkt.proto_type = htons(IP_PROTO_TYPE);
	pkt.hw_size    = HW_ADDR_LEN;
	pkt.proto_size = IP_ADDR_LEN;
	pkt.op         = htons(OP_ARP_REPLY);

	bcopy(src_mac, pkt.sorc_hw_addr, HW_ADDR_LEN);
	bcopy(dst_mac, pkt.targ_hw_addr, HW_ADDR_LEN);

	bcopy(src_mac, pkt.sndr_hw_addr, HW_ADDR_LEN); /* target mac */
	src_adr.s_addr = inet_addr(who_adr);
	bcopy(&src_adr, pkt.sndr_ip_addr, IP_ADDR_LEN); /* target ip */

	bcopy(dst_mac, pkt.rcpt_hw_addr, HW_ADDR_LEN); /* requester mac */
	src_adr.s_addr = inet_addr(dst_adr);
	bcopy(&src_adr, pkt.rcpt_ip_addr, IP_ADDR_LEN); /* requester ip */

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

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: Logo

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

Google photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s