/*
 * SNMP Trap
 * Copyright(c) 2000, Erick Engelke
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <snmp.h>
#include <rtos.h>
#include <net.h>

#define SNMP_TRAP_PORT 162

// #define DEBUG

#ifdef DEBUG
#include <ctype.h>
void dump(void *ptr, int len )
{
	 unsigned char *p = ptr;
	 int x, y, xy;
	 char ch;
         FILE *outfile;

         outfile = fopen("dump", "a+t" );
	 fprintf(outfile,"\n%u (0x%04x) bytes\n", len, len );
	 for ( y = 0 ; y < len ; y+= 16 ) {
		  fprintf(outfile,"\n%04x : ", y  );
		  for ( x = 0 ; x < 16 ; ++x ) {
				xy = x + y;
				fprintf(outfile, xy < len ? "%02x " : "   ", p[xy] );
		  }
		  fprintf(outfile," : ");
		  for ( x = 0 ; x < 16 ; ++x ) {
				xy = x + y;
				ch = p[ xy ];
				if ( ! isprint( ch )) ch = '*';
				fprintf(outfile, xy < len ? "%c" : "  ", ch );
		  }
	 }
	 fprintf(outfile,"\n");
         fclose(outfile);
}
#endif

void ascii2id( char *p, SNMP_OBJECT *lp )
{
    char *t;
    int i = 0;
    char *s, *sstart;

    s = sstart = kcalloc( strlen( p ) + 1, 1 );
    strcpy( s, p );

    do {
        if (( t = strchr( s , '.' )) != NULL ) *t = 0;
        lp->Id[ i ] = atol( s );
        if ( t != NULL ) *t = '.';  // repair it
        s = t + 1;
        i++;
    } while ( t );
    lp->IdLen = i;
    kfree( sstart );
}


static void copy_newoid( SNMP_OBJECT *dest, esnmp_oid *src )
{
    int i;
    for ( i = 0 ; i < src->oidlen; ++i )
        dest->Id[i] = src->oid[i];
    dest->IdLen = src->oidlen;
}

int snmp_trap( DWORD remote_ip, char *community, char *entOID, char *OID, DWORD agent,
        int genTrapType, int specTrapType, int valueType, void *value, int valueLen )
{
    return snmp_traps( remote_ip, community, entOID,
        1, &OID, agent, genTrapType, specTrapType, &valueType, &value, &valueLen );
}

/* Multiple traps in one */
int snmp_traps( DWORD remote_ip, char *community, char *entOID,
        int count, char **OID, DWORD agent,
        int genTrapType, int specTrapType, int *valueType, void **value, int *valueLen )
{
    SNMP_PDU           *pdu;
    SNMP_OBJECT        *list;
    BYTE               *buff;
    int                 i;

    BYTE                *buffptr;
    unsigned            encodedLength;
    udp_Socket *s;

#define SNMP_BUF_SIZE 2048
#define MAXOIDS 25

    if ( count >= MAXOIDS ) return( 1 );        // out of memory

    pdu = kcalloc( sizeof( SNMP_PDU ), MAXOIDS );
    list = kcalloc( sizeof( SNMP_OBJECT ), MAXOIDS );
    buff = kcalloc( SNMP_BUF_SIZE, 1 );
    s = kcalloc( sizeof( udp_Socket ), 1 );

    if ((s==NULL)||(buff==NULL)||(pdu==NULL)||(list==NULL)) {
        if ( s ) kfree( s );
        if ( buff ) kfree( buff );
        if ( list ) kfree( list );
        if ( pdu )  kfree( pdu );
        return( 1 );
    }

    buffptr = &buff[0];

    /* build the reply packet */
    pdu->Trap.Type = SNMP_PDU_TRAP;
    for(i = 0; i < SNMP_SIZE_BUFINT; ++i) {  // pack the rest with -1
        pdu->Trap.Id[i] = -1;
    }
    ascii2id( (entOID==NULL)? "0.0" : entOID, &pdu->Trap );

    if ( agent != 0 )
        pdu->Trap.IpAddress = intel( agent );
    else
        pdu->Trap.IpAddress = intel( my_ip_addr );           // my hostAddr
    pdu->Trap.General = genTrapType;     // (0-5) -> defined trap; 6 -> enterprise specific
    pdu->Trap.Specific = specTrapType;   // 0 unless above is 6
    pdu->Trap.Time = kupticks / 18L;


    // build the response
    memset( buff, -1, SNMP_BUF_SIZE );
    encodedLength = SNMP_BUF_SIZE;  // default buffer size
    for ( i = 0 ; i < count ; ++i ) {
        if ( OID == NULL )
            ascii2id( "1.3.6.1.2.1.1.0", &list[i] );
        else
            ascii2id( OID[i], &list[i] );

        list[i].Type = valueType[i]; // eg. SNMP_OCTETSTR;
        memcpy( list[i].Syntax.BufChr, value[i], valueLen[i] );
        list[i].SyntaxLen = valueLen[i];
    }

    i = SnmpEnc( &buffptr, &encodedLength, pdu, community, strlen(community), list, count ); // encode it for transport

    // write it out to the network

    udp_open( s, 0, remote_ip, SNMP_TRAP_PORT, NULL );
    tcp_tick(NULL );
#ifdef DEBUG
 dump( buffptr, encodedLength );
#endif
    sock_write( s, buffptr, encodedLength );
    sock_close( s );
    kfree( s );
    kfree( buff );
    kfree( list );
    kfree( pdu );
    return 0;
}

#ifdef NEVER
int snmp_trap( DWORD remote_ip, char *community, char *OID, DWORD agent,
        int genTrapType, int specTrapType, int valueType, void *value, int valueLen )
{
    SNMP_PDU           *pdu;
    SNMP_OBJECT        *list;
    BYTE               *buff;

    BYTE                *buffptr;
    unsigned            encodedLength;
    int i;
    udp_Socket *s;


    pdu = kcalloc( sizeof( SNMP_PDU ), 1 );
    list = kcalloc( sizeof( SNMP_OBJECT ), 1 );
    buff = kcalloc( 2048, 1 );
    s = kcalloc( sizeof( udp_Socket ), 1 );

    if ((s==NULL)||(buff==NULL)||(pdu==NULL)||(list==NULL)) {
        if ( s ) kfree( s );
        if ( buff ) kfree( buff );
        if ( list ) kfree( list );
        if ( pdu )  kfree( pdu );
        return( 1 );
    }

    buffptr = &buff[0];

    /* build the reply packet */
    pdu->Trap.Type = SNMP_PDU_TRAP;

    for(i = 0; i < SNMP_SIZE_BUFINT; ++i) {  // pack the rest with -1
        pdu->Trap.Id[i] = -1;
    }
    ascii2id( "5.6.7.8.9", &pdu->Trap );

    if ( agent != 0 )
        pdu->Trap.IpAddress = intel( agent );
    else
        pdu->Trap.IpAddress = intel( my_ip_addr );           // my hostAddr
    pdu->Trap.General = genTrapType;     // (0-5) -> defined trap; 6 -> enterprise specific
    pdu->Trap.Specific = specTrapType;   // 0 unless above is 6
    pdu->Trap.Time = kupticks / 18L;


    // build the response
    ascii2id( "1.3.6.1.2.1.1.0", &list[0] );

    list[0].Type = valueType; // eg. SNMP_OCTETSTR;
    memcpy( list[0].Syntax.BufChr, value, valueLen );
// eg. like strcpy( (char *)list[0].Syntax.BufChr, "foo" );

    list[0].SyntaxLen = valueLen; // strlen( (const char *)list[0].Syntax.BufChr );

    encodedLength = 2048;                                               // default buffer size
//    for(i = 0; i<2048; ++i)  buff[i]=-1;
    memset( buff, -1, 2048 );

    i = SnmpEnc( &buffptr, &encodedLength, pdu, community, strlen(community), list, 1 );      // encode it for transport

    // write it out to the network


    udp_open( s, 0, remote_ip, SNMP_TRAP_PORT, NULL );
    tcp_tick(NULL );
#ifdef DEBUG
    dump( buffptr, encodedLength );
#endif // DEBUG
    sock_write( s, buffptr, encodedLength );
    sock_close( s );
    kfree( s );
    kfree( buff );
    kfree( list );
    kfree( pdu );
    return 0;
}
#endif NEVER

