#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>

#include <project2/include/kernel.h>
#include <project2/include/snmp.h>
#include <project2/include/ipc_names.h>
#include <project2/include/bpf.h>

static int sockfd = 0;
static char buf[64*1024];

void
usage(int argc, char **argv)
{
	fprintf(stderr, "usage: %s\n", argv[0]);
	fprintf(stderr,
		"\t -i <interface number>\n"
		"\t -n <node number>\n"
		"\t -p <packet drop rate>\n\n");
}

int
main(int argc, char **argv)
{
	struct snmp_request *sm = (struct snmp_request*) buf;
	int interface = 0, node = 0;
	char ch;

	if(argc != 7) {
		usage(argc, argv);
		exit(1);
	}

	bzero(buf, sizeof(buf));

	while((ch = getopt(argc, argv, "i:n:p:")) != EOF) {
		switch (ch) {
		case 'i':
			interface = atoi(optarg);
			break;
		case 'n':
			node = atoi(optarg);
			break;
		case 'p':
			sm->sm_droprate = atof(optarg);
			if(sm->sm_droprate < 0 || sm->sm_droprate > 1.0)
				fprintf(stderr,
					"invalid drop rate %f "
					"(0.0 <= rate <= 1.0)\n",
					sm->sm_droprate);
				      
			break;
		default:
			usage(argc, argv);
			exit(1);
		}
	}

	if(argc != optind) {
		usage(argc, argv);
		exit(1);
	}

	/*
	 * Socket setup
	 */
	{
		struct sockaddr_un srv;

		if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
			perror("socket");
			exit(1);
		}

		bzero(&srv, sizeof(struct sockaddr_un));
		srv.sun_family = AF_UNIX;
		sprintf(srv.sun_path, SOCKUN_SNMP_FMT,
			(long int) getuid(), node, interface);

		if(connect(sockfd, SA(&srv), sizeof(struct sockaddr_un)) < 0) {
			perror("connect");
			exit(1);
		}
#ifdef DEBUG
		fprintf(stderr, "connected to '%s'\n", srv.sun_path);
#endif
	}

	sm->sm_type = SNMP_REQ_PDROP;
	sm->sm_ifindex = interface;
	sm->sm_reserved = 0;

	if(write(sockfd, (caddr_t) sm, sizeof(struct snmp_request)) < 0) {
		perror("write");
		exit(1);
	}

	close(sockfd);

	return 0;
}
