
/*
 * This file was generated by mib2c and is intended for use as a mib module
 * for the ucd-snmp snmpd agent.
 */

#include <config.h>

#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif

#include "mibincl.h"
#include "util_funcs.h"
#include "dlmod.h"
#include "dlmod_mib.h"

static oid      dlmod_name[16] = {1, 3, 6, 1, 4, 1, 2021, 14};
static int      dlmod_name_len = 8;

void
init_dlmod_mib (void) {
	register_mib("dlmod_mib", (struct variable *) dlmod_variables,
		     sizeof(*dlmod_variables),
		     sizeof(dlmod_variables) / sizeof(*dlmod_variables),
		     dlmod_name, dlmod_name_len);
#if 1
	fprintf(stderr, "register mib\n");
	fflush(stderr);
#endif
}

void
deinit_dlmod_mib (void) {
	unregister_mib(dlmod_name, dlmod_name_len);
}

int
dynamic_init_dlmod_mib (void) {
	init_dlmod_mib();
#if 1
	fprintf(stderr, "dynamic_init_dlmod_mib\n");
	fflush(stderr);
#endif
	return 0;
}

int
dynamic_deinit_dlmod_mib (void) {
	deinit_dlmod_mib();
	return 0;
}

/*
  header_dlmod(...
  Arguments:
  vp	  IN      - pointer to variable entry that points here
  name    IN/OUT  - IN/name requested, OUT/name found
  length  IN/OUT  - length of IN/OUT oid's 
  exact   IN      - TRUE if an exact match was requested
  var_len OUT     - length of variable or 0 if function returned
  write_method
  
*/

static int
header_dlmod(struct variable *vp,
	     oid *name,
	     int *length,
	     int exact,
	     int *var_len,
	     WriteMethod **write_method)
{
#define DLMOD_NAME_LENGTH	9	
	oid             newname[MAX_OID_LEN];
	int             result;
	char            buf[1024];

	memcpy((char *) newname, (char *) vp->name, (int) vp->namelen * sizeof(oid));
	newname[DLMOD_NAME_LENGTH] = 0;
#if 1

	fprintf(stderr, "dlmod exact: %d\n", exact);
	sprint_mib_oid(buf, name, *length);
	fprintf(stderr, "dlmod name: %s length %d\n", buf, *length);
	sprint_mib_oid(buf, newname, vp->namelen+1);
	fprintf(stderr, "dlmod newname: %s length %d\n", buf, vp->namelen+1);
#endif

	result = snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
	if ((exact && (result != 0)) || (!exact && (result >= 0)))  {
#if 1
		fprintf(stderr, "dlmod: FAILED\n");
#endif
		return MATCH_FAILED;
	}
	
	memcpy((char *) name, (char *) newname, ((int) vp->namelen + 1) * sizeof(oid));
	*length = vp->namelen + 1;

	*write_method = 0;
	*var_len = sizeof(long);/* default to 'long' results */
#if 1
	fprintf(stderr, "dlmod: SUCCEEDED\n");
#endif
	return MATCH_SUCCEEDED;
}


unsigned char  *
var_dlmod(struct variable *vp,
	  oid *name,
	  int *length,
	  int exact,
	  int *var_len,
	  WriteMethod **write_method)
{

	/* variables we may use later */

	*write_method = 0;	/* assume it isnt writable for the time being */
	*var_len = sizeof(int);	/* assume an integer and change later
					 * if not */

	if (header_dlmod(vp, name, length, exact, var_len, write_method) == 
		MATCH_FAILED)
		return 0;

	/* this is where we do the value assignments for the mib results. */
	switch (vp->magic) {

	case DLMODNEXTINDEX:
		return (unsigned char *)&dlmod_next_index;

	default:
		ERROR_MSG("");
	}
	return 0;
}


/*
  header_dlmodEntry(...
  Arguments:
  vp	  IN      - pointer to variable entry that points here
  name    IN/OUT  - IN/name requested, OUT/name found
  length  IN/OUT  - length of IN/OUT oid's 
  exact   IN      - TRUE if an exact match was requested
  var_len OUT     - length of variable or 0 if function returned
  write_method
  
*/


static struct dlmod *
header_dlmodEntry(struct variable *vp,
		  oid *name,
		  int *length,
		  int exact,
		  int *var_len,
		  WriteMethod **write_method)
{
#define DLMODENTRY_NAME_LENGTH	11
	oid	newname[MAX_OID_LEN];
	int	result;
	struct dlmod   *dlm = 0;
	int dlmod_index;
	char buf[1024];

	memcpy((char *) newname, (char *) vp->name, (int) vp->namelen * sizeof(oid));
	*write_method = 0;

	for (dlmod_index = 1; dlmod_index < dlmod_next_index; dlmod_index++)  {
		dlm = dlmod_get_by_index(dlmod_index);
#if 1
		fprintf(stderr, "dlmodEntry dlm: %x dlmod_index: %d\n",
                        (int) dlm, dlmod_index);
#endif
		if (dlm) {
			newname[11] = dlmod_index;
			result = snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
#if 1
			fprintf(stderr, "dlmodEntry exact: %d\n", exact);
			sprint_mib_oid(buf, name, *length);
			fprintf(stderr, "dlmodEntry name: %s length %d\n", buf, *length);
			sprint_mib_oid(buf, newname, vp->namelen+1);
			fprintf(stderr, "dlmodEntry newname: %s length %d\n", buf, vp->namelen+1);
			fprintf(stderr, "dlmodEntry result: %d\n", result);
#endif

			if ((exact && (result == 0)) || (!exact && (result < 0))) 
				break;
		}
	}
#if 1
	fprintf(stderr, "dlmod_index: %d dlmod_next_index %d\n",
		dlmod_index, dlmod_next_index);
#endif
	if (dlmod_index >= dlmod_next_index) {
#if 1
		fprintf(stderr, "vp->magic :%d\n", vp->magic);
#endif
		if (dlmod_index == dlmod_next_index && 
			exact && vp->magic == DLMODSTATUS)  

			*write_method = write_dlmodStatus;
		return NULL;
	}
	
	memcpy((char *) name, (char *) newname, ((int) vp->namelen + 1) * sizeof(oid));
	*length = vp->namelen + 1;

	*var_len = sizeof(long);/* default to 'long' results */
#if 1
    fprintf(stderr, "dlmodEntry return dlm: %x\n", (int) dlm);
#endif
	return dlm;
}

unsigned char  *
var_dlmodEntry(struct variable *vp,
	       oid *name,
	       int *length,
	       int exact,
	       int *var_len,
	       WriteMethod **write_method)
{

	/* variables we may use later */
	struct dlmod   *dlm;

	*var_len = sizeof(int);	/* assume an integer and change later
					 * if not */

	dlm =  header_dlmodEntry(vp, name, length, exact, var_len, write_method);
	if (dlm == MATCH_FAILED)
		return 0;

	/* this is where we do the value assignments for the mib results. */
	switch (vp->magic) {

	case DLMODINDEX:
		return (unsigned char *) &dlm->index;;

	case DLMODNAME:
		*write_method = write_dlmodName;
		*var_len = strlen(dlm->name);
		return dlm->name;

	case DLMODPATH:
		*write_method = write_dlmodPath;
		*var_len = strlen(dlm->path);
		return dlm->path;

	case DLMODERROR:
		*var_len = strlen(dlm->error);
		return dlm->error;

	case DLMODSTATUS:
		*write_method = write_dlmodStatus;
		return (unsigned char *) &dlm->status;

	default:
		ERROR_MSG("");
	}
	return 0;
}

static int
write_dlmodName(int action,
		u_char *var_val,
		u_char var_val_type,
		int var_val_len,
		u_char *statP,
		oid *name,
		int name_len)
{
	/* variables we may use later */
	unsigned char string[1500];
	int bigsize = 1000, size;
	struct dlmod *dlm;
	char buf[1024];

#if 1
	fprintf(stderr, "write_dlmodName type: %d action %d\n",
		var_val_type, action);
#endif

	if (var_val_type != ASN_OCTET_STR) {
		fprintf(stderr, "write to dlmodName not ASN_OCTET_STR\n");
		return SNMP_ERR_WRONGTYPE;
	}
	if (var_val_len > sizeof(string)) {
		fprintf(stderr, "write to dlmodName: bad length\n");
		return SNMP_ERR_WRONGLENGTH;
	}
	if (action == COMMIT) {
		size = sizeof(string);
		asn_parse_string(var_val, &bigsize, &var_val_type, string, &size);
		
#if 1
		sprint_mib_oid(buf, name, name_len);
		fprintf(stderr, "write_dlmodName strings: %s size: %d big_size: %d name: %s name_len %d\n",
			string, size, bigsize, buf, name_len);
#endif
		string[size] = '\0';
		/*
		 * Here, the variable has been stored in string for you to
		 * use, and you have just been asked to do something with
		 * it... Your code goes here.
		 */
		dlm = dlmod_get_by_index(name[11]);
		if (!dlm || dlm->status == DLMOD_LOADED) 
			return SNMP_ERR_RESOURCEUNAVAILABLE;
		strncpy(dlm->name, string, sizeof(dlm->name));
	}
	return SNMP_ERR_NOERROR;
}

static int
write_dlmodPath(int action,
		u_char *var_val,
		u_char var_val_type,
		int var_val_len,
		u_char *statP,
		oid *name,
		int name_len)
{
	/* variables we may use later */
	static unsigned char string[1500];
	int             size, bigsize = 1000;
	struct dlmod *dlm;

	if (var_val_type != ASN_OCTET_STR) {
		fprintf(stderr, "write to dlmodPath not ASN_OCTET_STR\n");
		return SNMP_ERR_WRONGTYPE;
	}
	if (var_val_len > sizeof(string)) {
		fprintf(stderr, "write to dlmodPath: bad length\n");
		return SNMP_ERR_WRONGLENGTH;
	}
	if (action == COMMIT) {
		size = sizeof(string);
		asn_parse_string(var_val, &bigsize, &var_val_type, string, &size);
		string[size] = '\0';
		/*
		 * Here, the variable has been stored in string for you to
		 * use, and you have just been asked to do something with
		 * it... Your code goes here.
		 */
		dlm = dlmod_get_by_index(name[11]);
		if (!dlm || dlm->status == DLMOD_LOADED) 
			return SNMP_ERR_RESOURCEUNAVAILABLE;
		strncpy(dlm->path, string, sizeof(dlm->path));
	}
	return SNMP_ERR_NOERROR;
}

static int
write_dlmodStatus(int action,
		  u_char *var_val,
		  u_char var_val_type,
		  int var_val_len,
		  u_char *statP,
		  oid *name,
		  int name_len)
{
	/* variables we may use later */
	long dlm_status;
	struct dlmod *dlm;
	int bigsize = 1000, size;

	if (var_val_type != ASN_INTEGER) {
		fprintf(stderr, "write to dlmodStatus not ASN_INTEGER\n");
		return SNMP_ERR_WRONGTYPE;
	}
	if (var_val_len > sizeof(dlm_status)) {
		fprintf(stderr, "write to dlmodStatus: bad length\n");
		return SNMP_ERR_WRONGLENGTH;
	}
	if (action == COMMIT) {
		size = sizeof(dlm_status);
		asn_parse_int(var_val, &bigsize, &var_val_type, 
			&dlm_status, sizeof(dlm_status));

		/* object identifier in form .1.3.6.1.4.1.2021.14.2.1.4.x 
		   where X is index with offset 11 */

		dlm = dlmod_get_by_index(name[11]);
		switch (dlm_status) {
		case DLMOD_CREATE:
			if (dlm || (name[11] != dlmod_next_index))
				return SNMP_ERR_RESOURCEUNAVAILABLE;
			dlm = dlmod_create_module();
			if (!dlm) 
				return SNMP_ERR_RESOURCEUNAVAILABLE;
			break;
		case DLMOD_LOAD:
			if (!dlm || dlm->status == DLMOD_LOADED) 
				return SNMP_ERR_RESOURCEUNAVAILABLE;
			dlmod_load_module(dlm);
			break;	
		case DLMOD_UNLOAD:
			if (!dlm || dlm->status != DLMOD_LOADED) 
				return SNMP_ERR_RESOURCEUNAVAILABLE;
			dlmod_unload_module(dlm);
			break;	
		case DLMOD_DELETE:
			if (!dlm || dlm->status == DLMOD_LOADED) 
				return SNMP_ERR_RESOURCEUNAVAILABLE;
			dlmod_delete_module(dlm);
			break;	
		default:
			return SNMP_ERR_WRONGVALUE;
		}
	}
	return SNMP_ERR_NOERROR;
}
