SNMPD.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:9k
- /*
- * eRTOS SNMP Server
- * Copyright (c) 2000, 2001 Erick Engelke
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <memory.h>
- #include <rtos.h>
- #include "snmp.h"
- #include <net.h>
- static esnmp_oid *oids = NULL;
- crit_x *_snmp_cs = NULL;
- void (*_snmp_prewalk)( int op, SNMP_OBJECT *list ) = NULL;
- int (*_snmp_override)( BYTE *com, int op, SNMP_OBJECT *list ) = NULL;
- /* If you need to process multi-MIB PDUs, set global variable snmpd_maxvars
- * to some higher number inside your application, before you start the
- * snmpd thread. It is used to allocate buffers at thread start time
- */
- #define SNMPD_MAXVARS 1
- int snmpd_maxvars = SNMPD_MAXVARS;
- //#define DEBUG
- #ifdef DEBUG
- print_oid( SNMP_OBJECT *oid, esnmp_oid *cmp )
- {
- int i;
- if (oid != NULL )
- for ( i = 0 ; i < oid->IdLen ; ++i )
- {
- dos_enter();
- printf("%u.", oid->Id[i] );
- dos_exit();
- }
- else
- for ( i = 0 ; i < cmp->oidlen ; ++i )
- {
- dos_enter();
- printf("%u.", cmp->oid[i] );
- dos_exit();
- }
- }
- #endif
- //---------------------------------------------------------------------
- // snmp_copyobjectid - copies "1.3.6..." to a reply packet and sets length
- void snmp_copyobjectid( DWORD * dest, char *source, UINT *len )
- {
- char *t;
- int i = 0;
- char *s, *sstart;
- /* get a working copy */
- s = sstart = kcalloc( strlen( source ) + 1, 1 );
- if ( s == NULL )
- rt_halt("out of memory in SNMPD");
- strcpy( s, source );
- do {
- if (( t = strchr( s , '.' )) != NULL ) *t = 0;
- dest[ i ] = atol( s );
- if ( t != NULL ) *t = '.'; // repair it
- s = t + 1;
- i++;
- } while ( t );
- *len = i;
- kfree( sstart );
- }
- //---------------------------------------------------------------------
- static void copy_oid( SNMP_OBJECT *dest, SNMP_OBJECT *src )
- {
- int i;
- for ( i = 0 ; i < src->IdLen ; ++i )
- dest->Id[i] = src->Id[i];
- dest->IdLen = src->IdLen;
- }
- //---------------------------------------------------------------------
- //---------------------------------------------------------------------
- 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;
- }
- //---------------------------------------------------------------------
- void snmp_compile_oids( esnmp_oid *p )
- {
- int i;
- cs_new( &_snmp_cs );
- cs_enter( _snmp_cs );
- oids = p;
- while ( p->oid[0] != -1 ) {
- p->oidlen = 0; /* safety if oid missing its -1 terminator */
- for ( i = 0 ; i < SNMP_OID_SIZE ; ++i ) {
- if ( p->oid[ i ] == -1 ) {
- p->oidlen = i;
- break;
- }
- }
- p++;
- }
- cs_exit( _snmp_cs );
- }
- /*
- * compare_oid - tell us if src is > (+1), = (0) or < (-1) cmp
- */
- int _snmp_compare_oid( SNMP_OBJECT *src, esnmp_oid *cmp )
- {
- long res;
- int i;
- for ( i = 0 ; (i < src->IdLen) && (i < cmp->oidlen) ; ++i ) {
- res = src->Id[i] - cmp->oid[i];
- if ( res < 0 ) return( -1 );
- if ( res > 0 ) return( 1 );
- /* = , continue */
- }
- /* got here, means they were equivalent so far */
- res = src->IdLen - cmp->oidlen;
- if ( res == 0 ) return( 0 );
- if ( res < 0 ) return( 1 );
- else return( -1 );
- }
- //---------------------------------------------------------------------
- #pragma argsused
- void snmpthread( DWORD dummy )
- {
- SNMP_PDU pdu;
- SNMP_OBJECT *list;
- unsigned listLen;
- int listi;
- BYTE com[16];
- unsigned comLen;
- BYTE *rqsBuffer, *rqs, *rqsSave;
- unsigned rqsLen;
- int op;
- static udp_Socket sock;
- int socklistening;
- int res;
- int i, j, rc;
- esnmp_oid *cur;
- int useoverride;
- if ((( list = kcalloc( sizeof( SNMP_OBJECT ), snmpd_maxvars )) == NULL ) ||
- (( rqs = kcalloc( 2048, 1 )) == NULL ))
- rt_halt("SNMPD, insufficient memory to start");
- rqsSave = rqs; // save this buffer's address
- socklistening = 0;
- do {
- if ( socklistening == 0 ) {
- /* udp_open - use remote_IP=0, bind to first incoming IP address */
- if (!udp_open( &sock, 161, 0, -1, NULL ))
- rt_halt("unable to open SNMP server socket");
- socklistening = 1;
- }
- tcp_tick( NULL );
- /* look for input */
- if ( (rqsLen = sock_dataready( &sock )) == 0 ) {
- rt_sleep( 10 );
- continue; /* no input */
- }
- /* we received an SNMP request, process it */
- sock_fastread( &sock, rqs, 1024 );
- SnmpDec( rqs, rqsLen, &pdu, com, sizeof(com), &comLen, list, snmpd_maxvars, &listLen);
- op = pdu.Type;
- useoverride = 0;
- /* build a reply packet */
- pdu.Type = SNMP_PDU_RESPONSE;
- pdu.Request.ErrorStatus = 0;
- pdu.Request.ErrorIndex = 0;
- if ( listLen > snmpd_maxvars )
- listLen = snmpd_maxvars;
- for ( listi = 0 ; listi < listLen ; ++listi ) {
- /* search through for our OID */
- res = 0;
- /* serialize access to the table, incase there are different threads */
- cs_enter( _snmp_cs );
- /* user defined pre-walk function */
- if ( _snmp_prewalk != NULL )
- (*_snmp_prewalk)( op, &list[listi] );
- if ( _snmp_override != NULL ) {
- i = (*_snmp_override)( com, op, &list[listi] );
- if ( i == SNMP_NOOVERRIDE ) useoverride = 0;
- else {
- useoverride = 1;
- pdu.Request.ErrorStatus = i;
- }
- }
- /* walk through the oid table - if it exists */
- if ( useoverride ) {
- /* user has supplied the packet */
- }
- else {
- if ( oids != NULL ) {
- for ( cur = oids ; cur->oid[0] != -1 ; ++cur ) {
- if ( ( op == SNMP_PDU_GET ) || ( op == SNMP_PDU_SET )) {
- if ( _snmp_compare_oid( &list[listi] , cur ) == 0 ) {
- res = 1;
- break;
- }
- }
- if ( op == SNMP_PDU_NEXT ) {
- if ( _snmp_compare_oid( &list[listi] , cur ) < 0 ) {
- res = 1;
- break;
- }
- }
- }
- }
- if (( res == 0 ) || (cur == NULL)) {
- /* none found */
- pdu.Request.ErrorStatus = SNMP_NOSUCHNAME;
- pdu.Request.ErrorIndex = 0;
- } else {
- copy_newoid( &list[listi], cur );
- if ( cur->fn != NULL )
- pdu.Request.ErrorStatus = (*cur->fn)(
- &sock, com, op, &list[listi], cur->data1, cur->data2 );
- else {
- /* no function, use default formatting */
- if ( op == SNMP_PDU_SET )
- pdu.Request.ErrorStatus = SNMP_READONLY;
- else {
- list[listi].Type = cur->data1;
- switch ( cur->data1 ) {
- case SNMP_DISPLAYSTR :
- strcpy( list[listi].Syntax.BufChr, (char *)cur->data2 );
- list[listi].SyntaxLen = strlen( (char*)cur->data2 );
- break;
- case SNMP_OBJECTID :
- snmp_copyobjectid( list[listi].Syntax.BufInt,
- (char *)cur->data2,
- &(list[listi].SyntaxLen));
- break;
- default : /* preserve other types */
- list[listi].Syntax.LngInt = cur->data2;
- break;
- }
- }
- }
- }
- }
- cs_exit( _snmp_cs );
- }
- rqsLen = 1024; // 1024 matches the size of the kcalloc() above
- rqs = rqsSave; // restore the buffer pointer to the start of the buffer
- rc = SnmpEnc( &rqs, &rqsLen, &pdu, com, comLen, list, listLen );
- if( rc == 0 ) puts("SnmpEnc failed!");
- sock_fastwrite( &sock, rqs, rqsLen );
- sock_close( &sock );
- /* open next snmp server */
- socklistening = 0;
- } while( 1 );
- }