/*
 * arp_inject.c -- DF-2253 end-to-end: inject an ARP frame with an unknown
 * hardware address format (ar_hrd = 0x1234) into the kernel receive path
 * via tap(4), exactly as a LAN peer could.  Stock kernel is expected to log
 *
 *     arp: unknown hardware address format (0x1)      <- buggy: 1 digit
 *
 * (full 2-byte hrd = 0x1234 should print 0x1234).  Root, guest-only rig.
 */
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int
main(void)
{
	unsigned char frame[14 + 28];	/* eth hdr + minimal arp */
	unsigned char *p;
	int fd;
	ssize_t n;

	memset(frame, 0, sizeof(frame));

	/* dst = broadcast */
	frame[0] = frame[1] = frame[2] = 0xff;
	frame[3] = frame[4] = frame[5] = 0xff;
	/* src = 02:03:04:05:06:07 */
	frame[6] = 0x02; frame[7] = 0x03; frame[8] = 0x04;
	frame[9] = 0x05; frame[10] = 0x06; frame[11] = 0x07;
	/* ethertype = ARP */
	frame[12] = 0x08; frame[13] = 0x06;

	p = frame + 14;
	p[0] = 0x12; p[1] = 0x34;	/* ar_hrd = 0x1234 (unknown format) */
	p[2] = 0x08; p[3] = 0x00;	/* ar_pro = ETHERTYPE_IP */
	p[4] = 6;    p[5] = 4;		/* ar_hln, ar_pln */
	p[6] = 0;    p[7] = 1;		/* ar_op = ARPOP_REQUEST */
	/* sha = 02:03:04:05:06:07 */
	p[8] = 0x02; p[9] = 0x03; p[10] = 0x04;
	p[11] = 0x05; p[12] = 0x06; p[13] = 0x07;
	/* spa = 10.66.66.66 */
	p[14] = 10; p[15] = 66; p[16] = 66; p[17] = 66;
	/* tha, tpa left zero */

	fd = open("/dev/tap0", O_RDWR);
	if (fd < 0) {
		perror("open /dev/tap0");
		return (1);
	}
	n = write(fd, frame, sizeof(frame));
	printf("arp_inject: wrote %zd bytes to /dev/tap0 (ar_hrd=0x1234)\n", n);
	close(fd);
	return (n == (ssize_t)sizeof(frame) ? 0 : 1);
}
