/*
 *  Copyright (c) 1996-2007 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "trdefs.h"
#include "trasn1.h"
#include "trsnmp.h"
#include "trimpl.h"
#include "trmib.h"
#include "trconsts.h"
#ifdef TM_SNMP_AGENT_V3
#include "trsnmpv3.h"
#include "trdeskey.h"
#endif /* TM_SNMP_AGENT_V3 */
#include "trregstr.h"
#include "example_local.h"
#include "example_var.h"

#include "snmpv3api.h"

static struct group example_group;
static int example_group_initialized = 0;

#define IF_INDEX 2

static struct exampletrapgreen  greenLedTrapEntry  = {1, 0, IF_INDEX};
static struct exampletrapyellow yellowLedTrapEntry = {2, 0, IF_INDEX};

static void example_group_init(void)
{
    memset(&example_group, 0x0, sizeof example_group);
    example_group.greenledon = 1; /* TRUE */
    example_group.yellowledon = 2; /* FALSE */
    strcpy((char *)example_group.bigboss, "Bruce");
    example_group.bigboss_len = strlen((char *)example_group.bigboss);

	example_group_initialized = 1;
}

static char *name[] =
{
    "Walpole",
    "Compton",
    "Pelham",
    "Pelham-Holles",
    "Cavendish",
    "William Pitt - the Elder",
    "Stuart",
    "Grenville",
};

static struct simpletable_entry example_table[MAX_EXAMPLE_ENTRIES];

static int example_table_initialized = 0;
static int example_table_entries = sizeof name / sizeof (char *);

static void example_table_init(void)
{
    int j;

    for (j = 0; j < example_table_entries; j++)
    {
        if (strlen(name[j]) < MAX_STRING_LEN)
		{
            strcpy((char *) example_table[j].name, name[j]);
			example_table[j].name_len = strlen(name[j]) + 1;
			example_table[j].rowstatus = NA_SNMP_ROW_STATUS_ACTIVE;
		}
    }

    for (j = example_table_entries; j < MAX_EXAMPLE_ENTRIES; j++)
    {
        example_table[j].name[0] = '\0';
		example_table[j].name_len = 1;
		example_table[j].rowstatus = NA_SNMP_ROW_STATUS_DESTROY;
    }
    example_table_initialized = 1;
}


long * app_group_get(u_char what, int *length)
{
    /* Insert your code here */
    static long * data_ptr = NULL;

    *length = 0;
    if (!example_group_initialized)
    {
        example_group_init();
    }

    switch(what)
    {
        case GREENLEDON:
            *length = sizeof(ttS32Bit);
            data_ptr = &example_group.greenledon;
            break;
        case YELLOWLEDON:
            *length = sizeof(ttS32Bit);
            data_ptr = &example_group.yellowledon;
            break;
        case BIGBOSS:
            *length = example_group.bigboss_len;
            data_ptr = (long *)example_group.bigboss;
        default:
            break;
    }
    return data_ptr;

}

int app_write_group(int what, u_char *buffer, int buffer_length)
{
    /* Insert your code here */
    int retValue = OK;

    if (buffer == NULL || buffer_length == 0)
    {
        retValue = FALSE;
        goto exit;
    }
    if (!example_group_initialized)
    {
        example_group_init();
    }

    switch(what)
    {
        case GREENLEDON:
            if (buffer_length != sizeof(ttS32Bit))
            {
                retValue = FALSE;
                goto exit;
            }
            memcpy(&example_group.greenledon, buffer, buffer_length);
            break;
        case YELLOWLEDON:
            if (buffer_length != sizeof(ttS32Bit))
            {
                retValue = FALSE;
                goto exit;
            }
            memcpy(&example_group.yellowledon, buffer, buffer_length);
            break;
        case BIGBOSS:
            if (buffer_length > MAX_STRING_LEN)
            {
                retValue = FALSE;
                goto exit;
            }
            memcpy(example_group.bigboss, buffer, buffer_length);
            example_group.bigboss_len = buffer_length;
            break;
        default:
            return FALSE;
    }

exit:
    return retValue;
}

int exampleEntryCreate(oid *index, int index_length, oid status)
{
	if ((example_table_entries >= MAX_EXAMPLE_ENTRIES) ||
		(index == NULL)	||
		(index_length != 1) ||
		((int)(*index) != (example_table_entries + 1 )) ||
		 (status != NA_SNMP_ROW_STATUS_CREATE_AND_GO && 
		  status != NA_SNMP_ROW_STATUS_CREATE_AND_WAIT)
	    )
	{
		return -1;
	}		
	example_table[*index - 1].name[0] = '\0';
	example_table[*index - 1].name_len = 1;
	example_table[*index - 1].rowstatus = (ttS32Bit) status;
	example_table_entries ++;
	return 1;
}

int exampleEntryDelete(oid *index, int index_length)
{
	int idx, start, end;

	if ((index == NULL)	|| 	(index_length != 1))
	{
		return TM_SNMP_ERR_NOSUCHNAME;
	}

	if ((example_table_entries == 0) || 
		((int)(*index) < 1) || 
		((int)(*index) > example_table_entries) 
	   )
	{
		return TM_SNMP_ERR_NOSUCHNAME;
	}
	if (example_table_entries > 1)
	{
		start = (int)(*index) - 1;
		end   = example_table_entries -1;

		for (idx = start; idx <= end; idx++)
		{
			example_table[idx] = example_table[idx+1];
		}
	}
	example_table_entries--;
	return TM_SNMP_ERR_NOERROR;
}

int app_simpletable_entry_get(int exact, struct simpletable_entry *entry0)
{
    /* Insert your code here */
    int retValue = 1;

    if (entry0 == NULL)
    {
        retValue = 0;
        goto exit;
    }

    if (!example_table_initialized)
    {
        example_table_init();
        example_table_initialized = 1;
    }
	if (example_table_entries == 0)
	{
        retValue = 0;
        goto exit;
    }

    if (!exact)
    {
        if (entry0->index >= example_table_entries ||
            !entry0->index)
        {
            retValue = 0;
            goto exit;
        }

        if (entry0->index < 0)
            entry0->index = 1;
        else
            entry0->index++;
    }
    else
    {
        if (entry0->index > example_table_entries ||
            entry0->index < 1)
        {
            retValue = 0;
            goto exit;
        }
    }

    strcpy((char *)entry0->name, (char *)example_table[entry0->index - 1].name);
    entry0->name_len = example_table[entry0->index - 1].name_len;
	entry0->rowstatus = example_table[entry0->index - 1].rowstatus;

exit:
    return retValue;
}

int app_write_simpletable_entry(int index0, int what, u_char *value, int value_length)
{
    /* Insert your code here */
    int retValue = OK;

	if ((what == ROWSTATUS) && (value != NULL) && 
		(*((ttS32Bit *) value) == NA_SNMP_ROW_STATUS_DESTROY)
	   )
	{
		goto exit;
	}

    if (index0 > example_table_entries||
        index0 < 1 ||
        value == NULL)
        
    {
        /* check for valid function arguments */
        retValue = FAIL;
        goto exit;
    }
	switch(what)
	{
	case NAME:
		if (value_length < 0 || value_length > MAX_STRING_LEN)
		{
			/* check for valid function arguments */
			retValue = FAIL;
			goto exit;
		}
		strncpy((char *) &example_table[index0 - 1].name[0], (const char *)value, value_length);
		example_table[index0 - 1].name_len = value_length;
		break;

	case ROWSTATUS:
		{
		ttS32Bit new_status = *((ttS32Bit *) value);
		ttS32Bit old_status =  example_table[index0 - 1].rowstatus;

		if (old_status == NA_SNMP_ROW_STATUS_ACTIVE ||
			old_status == NA_SNMP_ROW_STATUS_NOT_IN_SERVICE ||
			old_status == NA_SNMP_ROW_STATUS_NOT_READY)
		{
			if (!(new_status == NA_SNMP_ROW_STATUS_ACTIVE ||
				  new_status == NA_SNMP_ROW_STATUS_NOT_IN_SERVICE ||
				  new_status == NA_SNMP_ROW_STATUS_NOT_READY))
			{	
				/* check for valid function arguments */
				retValue = FAIL;
				goto exit;
			}
			example_table[index0 - 1].rowstatus = new_status;
		}
		else
		if (new_status == NA_SNMP_ROW_STATUS_CREATE_AND_GO)
			example_table[index0 - 1].rowstatus = NA_SNMP_ROW_STATUS_ACTIVE;
		else
		if (new_status == NA_SNMP_ROW_STATUS_CREATE_AND_WAIT)
			example_table[index0 - 1].rowstatus = NA_SNMP_ROW_STATUS_NOT_READY;
		else
		{	
				/* check for valid function arguments */
				retValue = FAIL;
				goto exit;
		}
		}
		break;
	default:
		retValue = FAIL;
		goto exit;
	}
exit:
    return retValue;
}

/*
 * Call this function to send exampleTrapGreen trap. 
 * Don't call it from any of the access MIB functions,
 * envoked on remote access.
 */
int sendGreenLedTrap(void)
{
	if (example_group_initialized == 0)
		example_group_init();
	
	greenLedTrapEntry.greenledon = example_group.greenledon;
	return tfexampletrapgreen_trap(&greenLedTrapEntry);
}

/*
 * Call this function to send exampleTrapYellow trap. 
 * Don't call it from any of the access MIB functions,
 * envoked on remote access.
 */
int sendYellowLedTrap(void)
{
	if (example_group_initialized == 0)
		example_group_init();

	yellowLedTrapEntry.yellowledon = example_group.yellowledon;
	return tfexampletrapyellow_trap(&yellowLedTrapEntry);
}
