/*
 * Copyright 2001-2003, Broadcom Corporation
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
 * the contents of this file may not be disclosed to third parties, copied or
 * duplicated in any form, in whole or in part, without the prior written
 * permission of Broadcom Corporation.
 *
 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE.  BROADCOM
 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
 *
 */

/*
 * et driver ioctl swiss army knife command.
 * $Id: et.c,v 1.1 2003/10/31 10:10:28 honor Exp $
 */

#include <stdio.h>

#ifndef linux
#include <pcap.h>
#endif
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <typedefs.h>
#include <etsockio.h>
#include <proto/ethernet.h>

static void usage(char *av0);
static void syserr(char *s);


#ifdef linux
char *interface = "eth0";
#else
char *interface = "et0";
#endif
char buf[16 * 1024];

#define VECLEN		2

int optind;

main(int ac, char *av[])
{
	struct ifreq ifr;
	char *endptr;
	int arg;
	int vecarg[VECLEN], i;
	int c;
	int s;

	if (ac < 2)
		usage(av[0]);

	optind = 1;

	if (av[1][0] == '-') {
		if ((av[1][1] != 'a') && (av[1][1] != 'i'))
			usage(av[0]);
		if (ac < 4)
			usage(av[0]);
		interface = av[2];
		optind += 2;
	}

	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
		syserr("socket");

	strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name));

	if (strcmp(av[optind], "up") == 0) {
		if (ioctl(s, SIOCSETCUP, (caddr_t)&ifr) < 0)
			syserr("etcup");
	}
	else if (strcmp(av[optind], "down") == 0) {
		if (ioctl(s, SIOCSETCDOWN, (caddr_t)&ifr) < 0)
			syserr("etcdown");
	}
	else if (strcmp(av[optind], "loop") == 0) {
		if (optind >= (ac -1))
			usage(av[0]);
		arg = atoi(av[optind + 1]);
		ifr.ifr_data = (caddr_t) &arg;
		if (ioctl(s, SIOCSETCLOOP, (caddr_t)&ifr) < 0)
			syserr("etcloop");
	}
	else if (strcmp(av[optind], "dump") == 0) {
		ifr.ifr_data = buf;
		if (ioctl(s, SIOCGETCDUMP, (caddr_t)&ifr) < 0)
			syserr("etcdump");
		printf("%s\n", buf);
	}
	else if (strcmp(av[optind], "msglevel") == 0) {
		if (optind >= (ac -1))
			usage(av[0]);
		arg = atoi(av[optind + 1]);
		arg = strtol(av[optind+1], &endptr, 0);
		ifr.ifr_data = (caddr_t) &arg;
		if (ioctl(s, SIOCSETCSETMSGLEVEL, (caddr_t)&ifr) < 0)
			syserr("etcsetmsglevel");
	}
	else if (strcmp(av[optind], "promisc") == 0) {
		if (optind >= (ac -1))
			usage(av[0]);
		arg = atoi(av[optind + 1]);
		ifr.ifr_data = (caddr_t) &arg;
		if (ioctl(s, SIOCSETCPROMISC, (caddr_t)&ifr) < 0)
			syserr("etcpromisc");
	}
	else if (strcmp(av[optind], "txdown") == 0) {
		if (ioctl(s, SIOCSETCTXDOWN, (caddr_t)&ifr) < 0)
			syserr("etctxdown");
	}
	else if (strcmp(av[optind], "speed") == 0) {
		if (optind >= (ac -1))
			usage(av[0]);
		if (strcmp(av[optind+1], "auto") == 0)
			arg = -1;
		else if (strcmp(av[optind+1], "10half") == 0)
			arg = 0;
		else if (strcmp(av[optind+1], "10full") == 0)
			arg = 1;
		else if (strcmp(av[optind+1], "100half") == 0)
			arg = 2;
		else if (strcmp(av[optind+1], "100full") == 0)
			arg = 3;
		else
			usage(av[0]);

		ifr.ifr_data = (caddr_t) &arg;
		if (ioctl(s, SIOCSETCSPEED, (caddr_t)&ifr) < 0)
			syserr("etcspeed");
	}
	else if (strcmp(av[optind], "phyrd") == 0) {
		if (optind >= (ac -1))
			usage(av[0]);
		vecarg[0] = strtoul(av[optind + 1], NULL, 0);
		ifr.ifr_data = (caddr_t) vecarg;
		if (ioctl(s, SIOCGETCPHYRD, (caddr_t)&ifr) < 0)
			syserr("etcphyrd");
		printf("0x%04x\n", vecarg[1]);
	}
	else if (strcmp(av[optind], "phywr") == 0) {
		if (optind >= (ac -2))
			usage(av[0]);
		vecarg[0] = strtoul(av[optind + 1], NULL, 0);
		vecarg[1] = strtoul(av[optind + 2], NULL, 0);
		ifr.ifr_data = (caddr_t) vecarg;
		if (ioctl(s, SIOCSETCPHYWR, (caddr_t)&ifr) < 0)
			syserr("etcphywr");
	}
	else
		usage(av[0]);
}

static void
usage(char *av0)
{
	fprintf(stderr, "usage: %s [ [ -a | -i ] interface ] and one of:\n"
		"\tup\n"
		"\tdown\n"
		"\tloop <0 or 1>\n"
		"\tdump\n"
		"\tmsglevel <num>\n"
		"\tpromisc <0 or 1>\n"
		"\ttxdown\n"
		"\tspeed <auto, 10half, 10full, 100half, 100full>\n"
		"\tphyrd <reg>\n"
		"\tphywr <reg> <val>\n"
		,
		av0);
	exit(1);
}

static void
syserr(char *s)
{
	perror(s);
	exit(1);
}

