
#include <stdio.h>
#include <tx_api.h>
#include <hservapi.h>
#include <sysAccess.h>
#include <ace_params.h>
#include <boardParams.h>

#define MAX_IPADDRESS_LENGTH    15

int 	kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress);
void 	printIpAddress(char *buffer, unsigned long ip);
int  	checkIpAddress(char *buffer);
unsigned long kbGetHexValue(char * buffer);

//	Global variables for this module

	aceProtoStartInfo   	staticIPStartInfo = {ACE_PROT_STATIC, 0, 0, ACE_CONT_IF_GOT_ADDRESS};
	aceProtoStartInfo   	autoIPStartInfo = {ACE_PROT_AUTOIP, 0, 0, ACE_CONT_IF_GOT_ADDRESS};

	aceConfigInfo       	ACEFromNV;
	unsigned long			ipaddr, subnetMask, defGW;

	aceConfigInterfaceInfo	* ace_intfc;

	configAceStaticInfo 	* staticIPInfo;
	configAceAutoipInfo 	* autoIPInfo;
	configAceDhcpInfo   	* dhcpInfo;
	configAcePingArpInfo 	* pingArpInfo;
	configAceBootpInfo		* bootPInfo;
	configAceRarpInfo		* rarpInfo;
	devBoardParamsType  params;
 


void    readLine(char * buf);
void	getNVParams();

void    aceTest()
{
	char            buffer[128];
	int             result = -1;
	typedef enum
	{
		DEFAULT_MODE,
		STATIC_MODE,
		AUTOIP_MODE,
		DHCP_MODE,
		RARP_MODE,
		PING_ARP_MODE,
	}IPADDR_MODE;

	IPADDR_MODE AddressMode = STATIC_MODE;

	unsigned long	gatewayIP = 0x0a34010f;			// 10.52.1.15
	unsigned long	localIP = 0x0a343117;			// 10.52.49.23
	unsigned long	subnetMask = 0xfffff800;		// 255.255.248.0
	unsigned long	autoip_start_addr = 0x0a343119;	// 10.52.49.25

	/////////////////////////////////////////////////////////
	// Some ACE variables and structures
	/////////////////////////////////////////////////////////

//	configAceAutoipInfo autoIPInfo;
//	configAceStaticInfo staticIPInfo;
	aceProtoStartInfo   staticIPStartInfo = {ACE_PROT_STATIC, 0, 0, ACE_CONT_IF_GOT_ADDRESS};
//	aceProtoStartInfo   autoIPStartInfo = {ACE_PROT_AUTOIP, 0, 0, ACE_ALWAYS_SHUTDOWN};
	aceProtoStartInfo   autoIPStartInfo = {ACE_PROT_AUTOIP, 0, 0, ACE_CONT_IF_GOT_ADDRESS};

	char ipAddrDesc[16];
	unsigned long ipAddress;


	// First get a copy of the ACE Configuration from NVRAM

	getNVParams();


	printf("\naceTest() - select ace mode by typing one of the following:\n");
	printf("autoip\nstatic\ndhcp\nnone\n");
	printf("What is your selection?");
	readLine(&buffer[0]);
	if(buffer[0] == "\0")
		printf("Empty line, default mode is static IP\n");
	else
	{
		if(strncmp(&buffer[0], "static", 4) == 0)
		{
			printf("Static ip mode selected, type in the IP address to use> ");
			NAWait(1000);
			AddressMode = STATIC_MODE;
			if(kbGetIpAddress (&ipAddrDesc, &ipAddress) == 1)
				localIP = ipAddress;
			else
			{
				printf("Bad IP address - I will not take it pffffffft!\n");
				return;
			}
		}
		else
		{
			if(strncmp(&buffer[0], "autoip", 4) == 0)
			{
				printf("AutoIP mode selected type in the IP address to use>");
				NAWait(1000);
				AddressMode = AUTOIP_MODE;
				if(kbGetIpAddress (&ipAddrDesc, &ipAddress) == 1)
					localIP = ipAddress;
				else
				{
					printf("Bad IP address - I will not take it pffffffft!\n");
					return;
				}
				printf("Specify autoIP start delay>");
				autoIPStartInfo.delay_before_start = kbGetHexValue(&buffer[0]);
			}
			else
			{
				if(strncmp(&buffer[0], "dhcp", 4) == 0)
				{
					printf("DHCP Mode selected\n");
					AddressMode = DHCP_MODE;
				}
				else
				{
					AddressMode = DEFAULT_MODE;
					printf("None selected, skipping Ace Setup\n");
				}
			}
		}
	}


	if(AddressMode == DEFAULT_MODE)
		return;


	/////////////////////////////////////////////////////
	// ACE reconfiguration sample
	/////////////////////////////////////////////////////


	if(AddressMode == AUTOIP_MODE || AddressMode == STATIC_MODE)
		aceStop("eth0");
	else
		printf("Unsupported mode selected - aborting.\n");

	/////////////////////////////////////////////////////////
	// Change the parameters (ACE parameters) in the NVRAM
	// using the aceParams API.
	/////////////////////////////////////////////////////////

#if 0
	// First, get the  dhcp info
	result = customizeAceGetDhcpConfig("eth0", &dhcpConfig);
	if(result != BP_SUCCESS)
	{
		printf("Failed to get dhcp config info - bye-bye\n");
		exit(-1);
	}

	// Now, reset the dhcp info to disable dhcp
	dhcpConfig.isEnabled = FALSE;
	result = customizeAceSetDhcpConfig("eth0", &dhcpConfig);
	if(result != BP_SUCCESS)
	{
		printf("Failed to set dhcp config info - bye-bye\n");
		exit(-2);
	}

#endif

	if(AddressMode == STATIC_MODE)
	{
		printf("aceTest() Static mode\n");

		// Now set the Static IP parameters the way we want them.
		// First a little initialization...

		staticIPInfo->auto_assign = TRUE;
		strcpy(staticIPInfo->domain_name,"");
		staticIPInfo->gateway = gatewayIP;
		staticIPInfo->ip_address = localIP;
		staticIPInfo->isConfigValid = TRUE;
		staticIPInfo->isEnabled = TRUE;
//		staticIPInfo->name_server_address[0] = 0;
		staticIPInfo->startInfo = staticIPStartInfo;
		staticIPInfo->subnet_mask = subnetMask;

		result = customizeAceSetStaticConfig("eth0", staticIPInfo);
		if(result != BP_SUCCESS)
		{
			printf("STATIC IP MODE: Failed to set static config info - bye-bye\n");
			exit(-6);
		}
		else
		{
			printf("STATIC IP MODE: IP = %x, GW = %x, Mask = %x\n", staticIPInfo->ip_address,
				   staticIPInfo->gateway, staticIPInfo->subnet_mask);
		}

		// falls through to ace start call at the bottom ...
	}

	///////////////////////////////////////////
	// For auto ip selection.

	if(AddressMode == AUTOIP_MODE)
	{
		printf("AutoIP mode - setting parameters.\n");

		// First get the static ip config
		// and disable it.

		autoIPInfo->isConfigValid = TRUE;
		autoIPInfo->isEnabled = TRUE;
		autoIPInfo->startInfo = autoIPStartInfo;
//		autoIPInfo->autoip_local_addr = BP_AUTOIP_START_WITH_RANDOM_IP_ADDRESS;
		autoIPInfo->autoip_local_addr = localIP;
//		autoIPInfo->autoip_local_addr = autoip_start_addr;


		result = customizeAceSetAutoipConfig("eth0", autoIPInfo);
		if(result != BP_SUCCESS)
		{
			printf("AUTO IP MODE: Failed to set auto ip config info - bye-bye\n");
			exit(-10);
		}
		else
		{
			printf("AUTO IP MODE: Starting with ");
			if(autoIPInfo->autoip_local_addr == BP_AUTOIP_START_WITH_RANDOM_IP_ADDRESS)
				printf("random ip address\n");
			else
				printf("%x\n", autoIPInfo->autoip_local_addr);
		}
	}


	/////////////////////////////////////////////////////////
	// Once the parameters are set up, start ACE.
	/////////////////////////////////////////////////////////

	printf("starting ACE\n");
	customizeStartAce();	// starts ACE with the parameters in the NVRAM.

	NAWait(10000);
	customizeGetIPParameters(&ipaddr, &subnetMask, &defGW);
	printf("Checked parameters after 10 second delay:\n");
	printf("IP Address = %x, Mask = %x, Gateway = %x\n", ipaddr, subnetMask, defGW);

}

/*
 *
 *  Function: static void readLine(char * buf)
 *
 *  Description:
 *
 *      This routine gets one line of the information input from keyboard.
 *      It prints out the information as well.
 *
 *  Parameters:
 *      buf     points to an array to hold the information
 *
 *  Return Values:
 *
 *      none
 *
 */ 
void readLine(char * buf)
{
	char character;
	int i = 0;
	do
	{
		character = getchar();
		if(character == '\b')
		{
			if(i > 0)
			{
				putchar(character);
				putchar(0x20);	 /*space*/
				putchar(character);
				--i;
			}
		}

		else if(character != '\n')
		{
			buf[i] = character;
			putchar(character);
			++i;
		}
	}
	while(character != '\r');
	putchar('\n');

	buf[i-1] = '\0';
}  


/*
 *
 *  Function: void getNVParams()
 *
 *  Description:
 *
 *      This function fetches the ACE configuration parameters from the NVRAM.
 *
 *  Parameters:
 *      
 *		none
 *
 *  Return Values:
 *
 *      none
 *
 */ 

void	getNVParams()
{

//	result = customizeAceGetStaticConfig("eth0", &staticIPInfo);

	customizeReadDevBoardParams(&params);
	customizeGetIPParameters(&ipaddr, &subnetMask, &defGW);

	ACEFromNV = params.aceConfig;
	ace_intfc = &(ACEFromNV.ace_interface_info[0]);
	
	staticIPInfo = &(ace_intfc->static_config);
	autoIPInfo = &(ace_intfc->autoip_config);
	dhcpInfo = &(ace_intfc->dhcp_config);
	pingArpInfo = &(ace_intfc->ping_arp_config);
	bootPInfo = &(ace_intfc->bootp_config);
	rarpInfo = &(ace_intfc->rarp_config);

	printf("getNVParams() - Configuration dump:\n");
	printf("static IP info: IP = %x gateway = %x mask = %x\n",staticIPInfo->ip_address,
		   staticIPInfo->gateway, staticIPInfo->subnet_mask);

	printf("auto IP info: IP = %x\n", autoIPInfo->autoip_local_addr);

	printf("dhcp info: IP suggested = %x lease time = %x server IP = %x\n", dhcpInfo->suggested_ip_address, dhcpInfo->suggested_lease_time,
		   dhcpInfo->server_ip_address);

	printf("pingArpInfo: start_info.delay = %x\n", pingArpInfo->startInfo.delay_before_start);
	printf("bootPInfo: file = %s   server IP = %x\n", bootPInfo->bootfile_name, bootPInfo->server_ip_address);
	printf("rarpInfo: rexint = %x\n", rarpInfo->rarp_rexint);
}

/*
 *		LIFTED FROM DIALOG.C
 *
 *  Function: static int kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress)
 *
 *  Description:
 *
 *      This routine print out what kind of IP address it needs and gets it from keyboard.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      ipAddrDesc    points to the string which contains some descriptions.
 *      ipAddres      points to an unsigned long which holds the old IP address.
 *                    upon return, will hold the new IP address if any.
 *
 *  Return Values:
 *
 *      0             no update, keep the old IP address
 *      1             got a new IP address     
 *
 */ 
static int kbGetIpAddress (char *ipAddrDesc, unsigned long *ipAddress)
{
	int	rc;

    char buffer[128];
	unsigned long	IPAddr;

	while (1)
    {
		printf ("%s ", ipAddrDesc);
//        printIpAddress("IP address [%d.%d.%d.%d]? ", *ipAddress);
        readLine (buffer);
        if (buffer[0] == '\0')
        {
			rc = 0;
			break;
		}

        if(checkIpAddress(buffer))
        {
          	*ipAddress = NAInet_addr(buffer);

			printf ("  %s ", ipAddrDesc);
//          	printIpAddress("IP address is %d.%d.%d.%d\r\n", *ipAddress);
			rc = 1;
			break;
        }

        printf("Invalid IP address\r\n");
    }

	return (rc);
}

/*
 *
 *  Function: static int  checkIpAddress(char *buffer)
 *
 *  Description:
 *
 *      This routine validates an IP address.
 *
 *  Parameters:
 *
 *      buffer    points to the string which contains an IP address in "a.b.c.d" format.
 *
 *  Return Values:
 *
 *      0         invalid
 *      1         valid
 *
 */ 
static int  checkIpAddress(char *buffer)
{
   unsigned int length,i;
   unsigned int j =0;
   unsigned int val;
      
   
   length = strlen(buffer);
   
   if ( (length > MAX_IPADDRESS_LENGTH))
      return 0;
   else
   {
     for (i=0; i<length; i++)
     {
       
       if (buffer[i] =='.')
           {
             j++;
             if (j > 3)   /* only three '.' allowed */
                return 0;
           }
       else if (!(isdigit(buffer[i]))) /* all input char must be numeric */
           return 0;
     } 
     
     for (i = 0; i < 4; i++)
      {
           if (*buffer != '\0') 
           {
               val = 0;
               while (*buffer != '\0' && *buffer != '.') 
               {  
                    val *= 10;
                    val += *buffer - '0';
                    buffer++;
               }
               if (val > 255)
                  return 0;       /* any field should be less than 256 */
                  
               if (*buffer != '\0') 
                   buffer++;
           } 
       }   
   }
   return 1; 
}  
/*
 *
 *  Function: static void printIpAddress(char *buffer, unsigned long ip)
 *
 *  Description:
 *
 *      This routine print out the board's IP address with descriptions.
 *
 *  Notes:
 *
 *      THIS CODE MUST BE CUSTOMIZED FOR YOUR BOARD SHOULD YOU USE DIFFERENT 
 *      DISPLAY FORMAT. The implementation below is for NET+OS development 
 *      boards only.
 *
 *  Parameters:
 *
 *      buffer    points to the string which contains some descriptions.
 *      ip        ip address
 *
 *  Return Values:
 *
 *      none
 *
 */ 
void printIpAddress(char *buffer, unsigned long ip)
{
#ifndef _LITTLE_ENDIAN
    printf(buffer, (ip >> 24) & 0xFF,
                   (ip >> 16) & 0xFF,
                   (ip >> 8)  & 0xFF,
                   (ip) & 0xFF);
#else
    printf(buffer, (ip) & 0xFF,
                   (ip >> 8)  & 0xFF,
                   (ip >> 16) & 0xFF,
                   (ip >> 24) & 0xFF);
#endif
} 

/*
 *	unsigned long kbGetHexValue(char * buffer)
 *					
 *	returns the hex value
 */

unsigned long kbGetHexValue(char * buffer)
{
	int				i = 0;
	unsigned long	val = 0xffffffff;

	printf("<hex> ");
	readLine(buffer);
	
	while (*buffer != '\0' && i < 9) 
	{  
		 val *= 0x10;
		 val += *buffer - '0';
		 buffer++;
		 i++;
	}
	return(val);
}




