/*
 * ifpromisc.c
 *
 * Set/remove the PROMISC flag on a given network interface.
 * Mostly useful under OpenBSD since other unices are able to do
 * this through ifconfig(8).
 *
 *
 * Joel Knight
 * <enabled@myrealbox.com>
 * [2006.07.04]
 */


#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/route.h>
#include <net/if.h>


void usage(void)
{
	fprintf(stderr, "usage: ifpromisc [-d] <ifname>\n\n"
			"-d disables promiscuous\n");
	exit(0);
}

int main(int argc, char *argv[])
{
	struct ifreq ifr;
	int s, dflag = 0;

	argc--, argv++;
	if (argc == 0) 
		usage();

	if (argc == 2) {
		if (!strcmp(*argv, "-d"))
			dflag = 1;
		else
			errx(1, "invalid argument (%s)", *argv);
		argv++;
	}

	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
		err(1, "socket()");

	bzero(&ifr, sizeof(struct ifreq));
	(void) strlcpy(ifr.ifr_name, *argv, sizeof(ifr.ifr_name));

	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
		err(1, "SIOCGIFFLAGS");
	
	if (dflag)
		ifr.ifr_flags &= ~IFF_PROMISC;
	else
		ifr.ifr_flags |= IFF_PROMISC;

	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
		err(1, "SIOCSIFFLAGS");

	printf("%s promiscuous mode on %s.\n", dflag ? "Disabled" : "Enabled",
			ifr.ifr_name);

	return (0);
}
