/*****************************************************************************
* Copyright (c) 2004, 2005 Digi International Inc., All Rights Reserved
*
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
*
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/

#include "bsp_cli.h"
#if BSP_CLI_INCLUDE_IN_BSP
#include <string.h>
// #include <naifconfig.h>
#include <boardParams.h>
#include "cliapi.h"
#include "cli_local.h"
#include "bsp_net.h"

/* 
#define TM_LL_PPPOE_DISC_COMPLETE   0x0001
#define TM_LL_OPEN_COMPLETE         0x0002
#define TM_LL_OPEN_FAILED           0x0004
#define TM_LL_CLOSE_STARTED         0x0008
#define TM_LL_CLOSE_COMPLETE        0x0010
#define TM_DEV_IP_USER_BOOT         0x0020
#define TM_DEV_IP_BOOTP             0x0040
#define TM_DEV_IP_DHCP              0x0080
#define TM_DEV_SCATTER_SEND_ENB     0x0100
#define TM_DEV_MCAST_ENB            0x0200
#define TM_DEV_IP_FORW_ENB          0x0400
#define TM_DEV_IP_FORW_DBROAD_ENB   0x0800
#define TM_DEV_IP_NO_CHECK          0x1000
#define TM_DEV_IP_FORW_MCAST_ENB    0x2000
#define TM_DEV_IP_MCAST_ROUTE       0x4000
#define TM_DEV_IP_ASYMMETRICAL      0x8000
*/

/* 0x10fd0 */
char *flgStr[] =
{
	/* link layer flags */
	"PPPOE_DISC_COMPLETE",
	"OPEN_COMPLETE",
	"OPEN_FAILED",
	"CLOSE_STARTED",
	"CLOSE_COMPLETE",
	/* device flags */
	"UBOOT",
	"BOOTP",
	"DHCP",
	"SSND",
	"MCAST",
	"IPFW",
	"FWBR",
	"NOCHK",
	"FWMC",
	"MCRTE",
	"ASYM"
};

/* external prototypes */
extern int tfInterfaceToName(ttDeviceEntryPtr devPtr, char TM_FAR *ifname);
extern int tfInterfaceToFlags(ttDeviceEntryPtr devPtr, int TM_FAR *flags);
extern int tfInterfaceToMtuSz(ttDeviceEntryPtr devPtr, int TM_FAR *ifMtuSz);
extern int tfInterfaceToPhy(ttDeviceEntryPtr devPtr, char TM_FAR *phy);

int cli_help_ifconfig(int fd, int n, char *args[])
{
	if (n > 0)
		cli_printf(fd, "%s\n\r", args[0]);
	cli_printf(fd, "ifconfig\n\r");
	return 0;
}

char *cli_phy_htoa(char *hexAddr, int len, char *phyString)
{
	char *pd = phyString;
	int ndx;

	for (ndx = 0; ndx < len - 1; ndx++)
	{
		pd += sprintf(pd, "%02x:", hexAddr[ndx]);
	}
	pd += sprintf(pd, "%02x", hexAddr[ndx]);
	return phyString;
}

char *cli_inet_ntoa(unsigned long x, char *netString)
{
	char *pd = netString;

	pd += sprintf(pd, "%ld", (x >> 24) & 0xff);
	pd += sprintf(pd, ".");
	pd += sprintf(pd, "%ld", (x >> 16) & 0xff);
	pd += sprintf(pd, ".");
	pd += sprintf(pd, "%ld", (x >> 8) & 0xff);
	pd += sprintf(pd, ".");
	pd += sprintf(pd, "%ld", (x) & 0xff);
	return netString;
}

/*
 * bash-2.03# /usr/sbin/ifconfig -a
 * lo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1
 * 		inet 127.0.0.1 netmask ff000000
 * eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
 * 		inet 10.64.18.3 netmask ffffff00 broadcast 10.64.18.255
 * lo0: flags=2000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6> mtu 8252 index 1
 * 		inet6 ::1/128
 * i0: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
 * 		inet6 fe80::203:baff:fe04:a4e8/10
 *
 * In the Treck tsDeviceEntry structure (ttDeviceEntryPtr) this info
 * is encoded in
 * devFlag, devMtu, dev6Flag,
 * dev6Mtu, devNameArray, devPhysAddrArr, ...
 * This structure is private (we see it as an opaque handle).
 */

char *devNames[] = {"eth0", "wln0", "LOOPBACK", NULL};

int cli_ifconfig(int fd, int n, char *args[])
{
	/* compare with ttDeviceEntry in treck/include/trtype.h  */
	/* following is typedef void TM_fAR * in treck/include/trsocket.h */
	int ifCount;
	ttUserInterface *pIfList;
	ttUserInterface interfaceHandle;	/* gets recast as above */
	unsigned long ipAddr;
	struct sockaddr_storage ipv6Addr;
	char ipAddrString[MAX_IP_ADDR_STR_LEN];
	unsigned long default_gateway;
	char gwAddrString[MAX_IP_ADDR_STR_LEN];
	int ndx = 0;
	char phyAddr[TM_NT_MAX_PHYS_ADDR];
	char phyAddrStr[18];
	char nameBuf[TM_MAX_DEVICE_NAME];
	int flags, mtuSz, home = 0;
	unsigned char prefixLen;

	/* for the compiler */
	if (n > 0)
		cli_printf(fd, "%s\n\r", args[0]);
	pIfList = tfGetInterfaceList(&ifCount);

	cli_printf(fd, "\r\nInterface list (%d):\r\n", ifCount);
	while (ifCount--)
	{
		interfaceHandle = pIfList[ndx++];
		/* init the name string */
		memset(nameBuf, ' ', TM_MAX_DEVICE_NAME);
#if	1
		tfGetIfName((ttUserInterface) interfaceHandle,
					  nameBuf, TM_MAX_DEVICE_NAME);
		tfGetIfPhysAddr((ttUserInterface) interfaceHandle,
					  phyAddr, TM_NT_MAX_PHYS_ADDR);
		tfGetIfFlags((ttUserInterface) interfaceHandle, &flags, 0);
		tfGetIfMtu((ttUserInterface) interfaceHandle, &mtuSz);
#else
		/* these interface functions are under an EXPORT_VARS flag in
		 * treck/source/ossuport/trifapi.c */
		tfInterfaceToName(interfaceHandle, nameBuf);	/* tfGetIfName */
		tfInterfaceToPhy(interfaceHandle, phyAddr);	/* tfGetIfPhysAddr */
		tfInterfaceToFlags(interfaceHandle, &flags);	/* tfGetIfFlags */
		tfInterfaceToMtuSz(interfaceHandle, &mtuSz);	/* tfGetIfMtu */
#endif
		mtuSz &= 0xffff;	/* it's a short */
		if (tfGetIpAddress(interfaceHandle, &ipAddr, 0) == 0)
		{
			if ((tfGetIfGateway(interfaceHandle,
										   	&default_gateway, 0)) != 0)
			{
				default_gateway = 0;
			}
		cli_printf(fd, "%d: %s:  flags=%x mtu %d Phy %s IpAddr:%s GW: %s\r\n",
				ndx, nameBuf, flags, mtuSz,
			   	cli_phy_htoa(phyAddr, TM_NT_MAX_PHYS_ADDR, phyAddrStr),
				cli_inet_ntoa(ipAddr, ipAddrString),
				cli_inet_ntoa(default_gateway, gwAddrString));
		}
		else
		{
#if BSP_ETH_WIFI_BRIDGE
			customizeGetMACAddress((BYTE *) phyAddr);
			if (strncmp(nameBuf, "eth", 3) == 0)
			cli_printf(fd, "%d: %s: Phy %s is bridged\r\n",
				ndx, nameBuf, 
				cli_phy_htoa(phyAddr, TM_NT_MAX_PHYS_ADDR, phyAddrStr));
			else
#endif
			cli_printf(fd, "%d: %s: flags=%x Phy %s is down\r\n",
				ndx, nameBuf, flags,
				cli_phy_htoa(phyAddr, TM_NT_MAX_PHYS_ADDR, phyAddrStr));
		}
		if (tfGetIpAddress(interfaceHandle, &ipAddr, 1) == 0 && ipAddr != 0)
		{
			cli_inet_ntoa(ipAddr, ipAddrString);
			cli_printf(fd, "   %s:0 %s\r\n", nameBuf, ipAddrString);
		}
		for (home = 1; home < 12; home++)
		{
			if (tfNgGetIpAddress(interfaceHandle, &ipv6Addr, AF_INET6, home) == TM_ENOERROR)
			{
				if (inet_ntop(AF_INET6, &ipv6Addr.addr.ipv6.sin6_addr, ipAddrString, MAX_IP_ADDR_STR_LEN))
				{
					tfNgGetPrefixLen(interfaceHandle, &prefixLen, AF_INET6, home);

                    cli_printf(fd, "   %s:%d %s, prefixlen: %d", nameBuf, home-1, 
									ipAddrString, prefixLen);

                    if (home == NA_IAM_STATICV6_INDEX)
                    {
                        struct sockaddr_storage ipv6Gateway;

                        if (tfNgGetIfGateway(interfaceHandle, &ipv6Gateway, AF_INET6, home) == TM_ENOERROR && 
                            inet_ntop(AF_INET6, &ipv6Gateway.addr.ipv6.sin6_addr, gwAddrString, MAX_IP_ADDR_STR_LEN))
                        {
                            cli_printf(fd, ", GW: %s", gwAddrString);
                        }
                    }
                    cli_printf(fd,"\r\n");
 				}
			}
		}

	}
	tfFreeInterfaceList(pIfList);
	return 0;
}

#endif /* BSP_CLI_INCLUDE_IN_BSP */

