#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
/* #include <sys/time.h> */
#include <vxWorks.h>
#include "VXtime.h"
#include "VXparam.h"
#include <bootLib.h>
#include <intLib.h>
#include <iv.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in_pcb.h>
#include "VXif_ether.h"
#include <netinet/in_systm.h>
#ifndef sunV3
#include <netinet/in_var.h>
#endif
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_fsm.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp_var.h>
#include "VXnlist.h"

#define      PR_SLOWHZ       2               /* 2 slow timeouts per second */
#define sleep(a)	taskDelay(a*sysClkRateGet())

#ifndef NULL
#define NULL 0
#endif
#ifndef  MIN
#define  MIN(a,b)                     (((a) < (b)) ? (a) : (b)) 
#endif

#include "asn1.h"
#include "snmp.h"
#include "snmp_impl.h"
#include "mib.h"

#include "snmp_vars.h"

#include "m2m.h"
#include "snmp_vars_m2m.h"
#include "alarm.h"
#include "event.h"

#define PROCESSSLOTINDEX  0
#define PROCESSID         4
#define PROCESSCOMMAND    8
 
#include "party.h"
#include "context.h"
#include "acl.h"
#include "view.h"

#include "custom_snmp_vars.h"

#include "taskArchLib.h"
#include "errnoLib.h"
#include "taskLib.h"
#include "private/taskLibP.h"

/*
 * CUSTOMIZE
 *
 * Here is where local modifications can be added 
 */

/*
 *  XXXXX
 *  These objects are part of the pseudo enterprise specific MIB
 *  starting OID .1.3.6.1.4.1.9999.  (9999 is not registered -- it is for
 *  example ONLY!)  
 *
 * PLEASE DO NOT USE THIS IN PRODUCTION SYSTEM.
 */

/* Vxworks task list .1.3.6.1.4.1.9999.1.1.1.  */

u_char *
var_vxworks_task(vp, name, length, exact, var_len, write_method)
    register struct variable *vp;	/* IN - pointer to variable entry that points here */
    register oid	    *name;	/* IN/OUT - input name requested, output name found */
    register int	    *length;	/* IN/OUT - length of input and output oid's */
    int			    exact;	/* IN - TRUE if an exact match was requested. */
    int			    *var_len;	/* OUT - length of variable or 0 if function returned. */
    int			    (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
{
    oid newname[MAX_NAME_LEN];
    int result;
    int count;
#define XXX_MAX_TASKS 128
    int task_id_list[XXX_MAX_TASKS];
    int tid;
    static TASK_DESC tdesc;	/* non reentrant XXX bad example */
    u_char *cp;
    int ret;

    count = taskIdListGet(task_id_list, XXX_MAX_TASKS);
    bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    for (tid = 1; tid <= count; tid++) {
    	newname[12] = (oid)tid;
	result = compare(name, *length, newname, (int)vp->namelen + 1);
	if ((exact && (result == 0)) || (!exact && (result < 0)))
		break;
    }
    if (tid > count)
    	return NULL;

    bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
    *length = vp->namelen + 1;
    *write_method = 0;
    *var_len = sizeof(long);	/* default length */

    ret = taskInfoGet(task_id_list[tid-1], &tdesc);
    if (ret != OK)
    	return NULL;

    switch (vp->magic){
	case TASK_INDEX:
	long_return = tid;
	return (u_char *)&long_return;
	break;

	case TASK_ID:
	long_return = tdesc.td_id;
	return (u_char *)&long_return;
	break;

	case TASK_NAME:
	cp = tdesc.td_name;
	*var_len = strlen(cp);
	return (u_char*)cp;
	break;

	case TASK_PRIORITY:
	long_return = tdesc.td_priority;
	return (u_char *)&long_return;
	break;

	case TASK_STATUS:
	long_return = tdesc.td_status;
	return (u_char *)&long_return;
	break;

	case TASK_OPTIONS:
	long_return = tdesc.td_options;
	return (u_char *)&long_return;
	break;

	default:
	    ERRORMSG("var_vxworks_task");
    }
    return NULL;
}

u_char *
var_vxworks_snmpd(vp, name, length, exact, var_len, write_method)
    register struct variable *vp;   /* IN - pointer to variable entry that points here */
    register oid	*name;	    /* IN/OUT - input name requested, output name found */
    register int	*length;    /* IN/OUT - length of input and output oid's */
    int			exact;	    /* IN - TRUE if an exact match was requested. */
    int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
{
    extern int write_vxworks_snmpd ();
    oid newname[MAX_NAME_LEN];
    int result;

    bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    newname[10] = 0;
    result = compare(name, *length, newname, (int)vp->namelen + 1);
    if ((exact && (result != 0)) || (!exact && (result >= 0)))
	return NULL;
    bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
    *length = vp->namelen + 1;
    *write_method = 0;
    *var_len = sizeof(long);	/* default length */
    switch (vp->magic){
	case SNMPD_AGNT_VER:
	*var_len = strlen(vxworks_agent_version);
	return (u_char *)vxworks_agent_version;
	break;

	case SNMPD_PORT_VER:
	*var_len = strlen(vxworks_port_version);
	return (u_char *)vxworks_port_version;
	break;

	case SNMPD_PRIORITY:
	taskPriorityGet (taskIdSelf (), &long_return);
	*write_method = write_vxworks_snmpd;
	return (u_char *)&long_return;
	break;

	default:
	    ERRORMSG("var_vxworks_snmpd");
    }
    return NULL;
}


#define SNMPD_PARAM_INDEX 9
int
write_vxworks_snmpd(action, var_val, var_val_type, var_val_len, statP, name, name_len)
     int      action;
     u_char   *var_val;
     u_char   var_val_type;
     int      var_val_len;
     u_char   *statP;
     oid      *name;
     int      name_len;
{
    int bigsize = 1000;
    int count, size;
    long set_val;

    if (var_val_type != INTEGER) {
	ERRORMSG("integer");
	return SNMP_ERR_WRONGTYPE;
    }
    
    size = sizeof (set_val);
    asn_parse_int(var_val, &bigsize, &var_val_type, &set_val, size);

    if (action == COMMIT) {
	/*
	 *  modify requested value
	 */
	switch((char)name[SNMPD_PARAM_INDEX])
	    {
	    case 3:
	    taskPrioritySet (taskIdSelf (), set_val);
	    break;
	    
	    default:
	    ERRORMSG("");
	    break;
	    }
    }

    return SNMP_ERR_NOERROR;
}

