/*
 *
 *     Module Name: root.c
 *	       Version: 1.00
 *   Original Date: 08/23/99	
 *	        Author: Charles Gordon
 *	      Language: Ansi C
 * Compile Options:
 * Compile defines:
 *	     Libraries:
 *    Link Options:
 *
 *    Entry Points: applicationStart(), applicationTcpDown()
 *
 *  Copyrighted (c) by NETsilicon, Inc.  All Rights Reserved.
 *
 * Description.
 * =======================================================================
 *  applicationStart() is the entry point for user applications.  This
 *  This function will be called after the kernel has started and the
 *  TCP/IP stack has loaded.  applicationTcpDown() is called periodically
 *  after the kernel has started while the system is waiting for the
 *  TCP/IP stack to start.  
 *
 *
 *
 *
 * Edit Date/Ver   Edit Description
 * ==============  =======================================================
 *
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <tx_api.h>
#include <sockapi.h>
#include <snmpapi.h>
#include <snmpv1v2capi.h>
#include <sysAccess.h>
#include "fservapi.h"
#include "http_awsapi.h"
#include "appconf.h"
#include <nastatus.h>


extern int ftp_server_app_init();

#define TRAP_PORT        162
#define TRAP_SINK_ADDR   0x0A342371     /* 10.52.35.113 */
#define TRAP_SOURCE_ADDR 0x0a342079     /* 10.52.32.121 */

/*
 *
 *  Function: void applicationTcpDown (void)
 *
 *  Description:
 *
 *      This routine will be called by the NET+OS root thread once every 
 *      clock tick while it is waiting for the TCP/IP stack to come up.  
 *      This function can increment a counter everytime it's called to 
 *      keep track of how long we've been waiting for the stack to start.
 *      If we've been waiting too long, then this function can do something
 *      to handle the error.  
 *
 *      This function will not be called once the stack has started.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

void applicationTcpDown (void)

{
    static int ticksPassed = 0;

    ticksPassed++;
/*
 * Code to handle error condition if the stack doesn't come up goes here.
 */
}



/*
 *
 *  Function: void applicationStart (void)
 *
 *  Description:
 *
 *      This routine is responsible for starting the user application.  It should 
 *      create any threads or other resources the application needs.
 *
 *      ThreadX, the NET+OS device drivers, and the TCP/IP stack will be running
 *      when this function is called.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

void applicationStart (void)

{
    int oid1value               = 0x1010;
    unsigned long oid1[]        = {1, 3, 6, 1, 4, 1, 6000, 1, 3, 1};
    char oid2value[]            = "Value of OID #2";
    unsigned long oid2[]        = {1, 3, 6, 1, 4, 1, 6000, 1, 3, 2, 1};
    unsigned long oid3value[]   = {1, 3, 6, 1, 4, 1, 6000, 1, 3, 3};
    unsigned long oid3[]        = {1, 3, 6, 1, 4, 1, 6000, 1, 3, 2, 2};
    struct sockaddr_storage sin;
    NaStatus ret;
    NaSnmpTrap_t trap;
    static char rcvData[1500];
    int szsin, result;
    struct variable_t variables[3];
    int fd;


    /* Starting with Net+OS7.0, more than one password(community string) is allowed
     * per user. */
    /*  Add Username private/private to the System Access Database   */
    NAsetSysAccess (NASYSACC_ADD, "private", "private", NASYSACC_LEVEL_SNMP_RW, NULL);

    /*  Add Username private/private to the System Access Database   */
    NAsetSysAccess (NASYSACC_ADD, "private", "private2", NASYSACC_LEVEL_SNMP_RW, NULL);

    /*  Add Username public/public to the System Access Database   */
    NAsetSysAccess (NASYSACC_ADD, "public", "public", NASYSACC_LEVEL_SNMP_R, NULL);

    /*  Add Username public/public to the System Access Database   */
    NAsetSysAccess (NASYSACC_ADD, "public", "public2", NASYSACC_LEVEL_SNMP_R, NULL);

    /*  Add Username netsilicon/sysadm to the System Access Database   */
    NAsetSysAccess (NASYSACC_ADD, "Netsilicon", "sysadm", NASYSACC_LEVEL_RW, NULL);

    /*  Add Username system/sysadm to the System Access Database   */
    NAsetSysAccess (NASYSACC_ADD, "system", "sysadm", NASYSACC_LEVEL_RW, NULL);

    /* At least one trap sink must be set before the agent is started. It will be used for 
       coldStart and authenticationFailure traps 
    */ 
    trap.destAddr.ss_port = ntohs(TRAP_PORT);
    trap.destAddr.ss_family = AF_INET;
    trap.destAddr.addr.ipv4.sin_addr.s_addr = ntohl(TRAP_SINK_ADDR);

    /* Set ss_family to 0 to use a default source address */
    trap.srcAddr.ss_family = AF_INET; 
    trap.srcAddr.addr.ipv4.sin_addr.s_addr = ntohl(TRAP_SOURCE_ADDR); 

    trap.enterpriseNum = 6000;
    trap.enterpriseLen = 8;

    strcpy((char *)trap.community, "public");
    trap.communityLen = strlen("public");

    /* Both v1 and v2c traps will be sent. 
       Use NA_SNMP_TRAP_NO_V1 to send only v2c traps to this destination address.
       Use NA_SNMP_TRAP_NO_V2c to send only v1 traps to this destination address.
    */
    trap.versionFilter = 0; 

    ret = naSnmpAddTrap (&trap);
    if (ret != NA_SUCCESS)
    {
        printf("naSnmpAddTrap failed [0x%X]\n", ret);
        return;
    }

#ifdef DISABLE_COLD_START_TRAP 
    ret = naSnmpDisableColdStartTrap();
    if (ret != NA_SUCCESS)
    {
        printf("naSnmpDisableColdStartTrap failed [0x%X]\n", ret);
        return;
    }
#endif
   
    if ((ret = naSnmpStart()) != NA_SUCCESS)
    {
        printf("naSnmpStart failed [0x%X]\n", ret);
        return;
    }   

    /*  open some UDP Services  */
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) 
    {
        printf("Couldn't open UDP socket 10002\n" );
    }
    else
    {
    	memset(&sin, 0, sizeof(sin));
        sin.ss_family         = AF_INET;
        sin.addr.ipv4.sin_addr.s_addr  = 0;
        sin.ss_port          = htons(10002);
        bind(fd, (struct sockaddr *)&sin, sizeof(sin));
    }
    
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) 
    {
        printf("Couldn't open UDP socket 10000\n" );
    }
    else
    {
    	memset(&sin, 0, sizeof(sin));
        sin.ss_family       = AF_INET;
        sin.addr.ipv4.sin_addr.s_addr  = 0;
        sin.ss_port         = htons(10000);
        bind(fd, (struct sockaddr *)&sin, sizeof(sin));
    }

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) 
    {
        printf("Couldn't open UDP socket 10001\n" );
    }
    else
    {
    	memset(&sin, 0, sizeof(sin));
        sin.ss_family       = AF_INET;
        sin.addr.ipv4.sin_addr.s_addr  = 0;
        sin.ss_port         = htons(10001);
        bind(fd, (struct sockaddr *)&sin, sizeof(sin));
    }

    /*  variable 1 is integer 0x1010 at 1.3.6.1.4.1.6000.1.3.1 */
    memcpy (variables[0].value, &oid1value, sizeof (oid1value));
    memcpy (variables[0].oid_value, &oid1, sizeof (oid1));
    variables[0].oid_length     = sizeof (oid1) / sizeof (unsigned long);
    variables[0].value_type     = ASN_INTEGER;
    variables[0].value_length   = sizeof (oid1value) / sizeof (int);

    /*  variable 2 is string 'Value of OID #2' at 1.3.6.1.4.1.6000.1.3.2.1 */
    memcpy (variables[1].value, &oid2value, strlen (oid2value));
    memcpy (variables[1].oid_value, &oid2, sizeof (oid2));
    variables[1].oid_length     = sizeof (oid2) / sizeof (unsigned long);
    variables[1].value_type     = ASN_OCTET_STR;
    variables[1].value_length   = strlen (oid2value);

    /*  variable 3 is object 1.3.6.1.4.1.6000.1.3.3 at 1.3.6.1.4.1.6000.1.3.2.2 */
    memcpy (variables[2].value, &oid3value, sizeof (oid3value));
    memcpy (variables[2].oid_value, &oid3, sizeof (oid3));
    variables[2].oid_length     = sizeof (oid3)/sizeof (unsigned long);
    variables[2].value_type     = ASN_OBJECT_ID;
    variables[2].value_length   = sizeof (oid3value) / sizeof (unsigned long);

    printf ("SNMP Sample application ready.\n"); 

    do 
    {
        /*  Receive data from an IPv4 node.  */
        szsin = sizeof(sin);
        result = recvfrom(fd, rcvData, 1500, 0, (struct sockaddr *)&sin, &szsin);
        if (result < 0)
        {
            printf("recvfrom failure: [%d]\n", getErrno());
        }
        else
        {
            /* Reuse most of this structure. */
            trap.destAddr.ss_port = ntohs(TRAP_PORT);
            trap.destAddr.ss_family = AF_INET;
            trap.destAddr.addr.ipv4.sin_addr.s_addr = \
                              ntohl(sin.addr.ipv4.sin_addr.s_addr);
       
            ret = naSnmpSendTrap (SNMP_TRAP_ENTERPRISESPECIFIC,
                                  ESPECIFIC_NOT_DEFINED,
                                  2,            /* interface index */
                                  3, 
                                  variables,
                                  &trap);

            if (ret != NA_SUCCESS)
            {
                printf("naSnmpSendTrap failure: ret[0x%X]\n", ret);
            }
        }
    }
    while (1);
}


