#include <sys/time.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    int			fd, sock;
    fd_set		set;
    struct timeval      wait;
    struct sockaddr_in  sin;
    struct sockaddr_in  sin2;

    signal(SIGPIPE, SIG_IGN);

    if (argc < 2 && argc > 3) {
	printf("usage: %s ipaddr [ipaddr]\n", argv[0]);
	exit(1);
    }

    fd = open("/dev/tap0", O_RDWR);
    if (fd < 0) {
	perror("open tap");
	exit(1);
    }

    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket");
	exit(1);
    }

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons((short)9998);
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
	perror("bind");
	exit(1);
    }

    sin.sin_addr.s_addr = inet_addr(argv[1]);
    if (argc == 3) {
	memset(&sin2, 0, sizeof(sin));
	sin2.sin_family = AF_INET;
	sin2.sin_port = htons((short)9998);
	sin2.sin_addr.s_addr = inet_addr(argv[2]);
    }

    chdir("/");
    if (fork() != 0)
	exit(0);
    setsid();
    if (fork() != 0)
	exit(0);

    while (1) {
	wait.tv_sec = 10;
	wait.tv_usec = 0;

	FD_ZERO(&set);
	FD_SET(fd, &set);
	FD_SET(sock, &set);

	if (select(FD_SETSIZE, &set, (fd_set *)0, (fd_set *)0, &wait) < 0) {
	    perror("select");
	    exit(1);
	}

	if (FD_ISSET(fd, &set)) {
	    char buf[10240];
	    int ret;

	    if ((ret=read(fd, buf, sizeof(buf))) < 0) {
		perror("read");
	    } else {
		int i;
		/* printf("%d bytes on tap0\n", ret); */
		i = sendto(sock, buf, ret, 0, (struct sockaddr*)&sin, sizeof(sin));
		if (i < 0) {
		    perror("sendto1");
		} else if (i != ret) {
		    printf("short sendto (%d/%d)\n", i, ret);
		}
		if (argc == 3) {
		    i = sendto(sock, buf, ret, 0, (struct sockaddr*)&sin2, sizeof(sin2));
		    if (i < 0) {
			perror("sendto2");
		    } else if (i != ret) {
			printf("short sendto (%d/%d)\n", i, ret);
		    }
		}
	    }
	}
	if (FD_ISSET(sock, &set)) {
	    char buf[10240];
	    int ret;

	    if ((ret=recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL)) < 0) {
		perror("recvfrom");
	    } else {
		int i;
		/* printf("%d bytes on socket\n", ret); */
		i = write(fd, buf, ret);
		if (i < 0) {
		    perror("write");
		} else if (i != ret) {
		    printf("short write (%d/%d)\n", i, ret);
		}
	    }
	}

    }
}
