SNMPD.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:9k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * eRTOS SNMP Server
  3.  * Copyright (c) 2000, 2001 Erick Engelke
  4.  */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <memory.h>
  9. #include <rtos.h>
  10. #include "snmp.h"
  11. #include <net.h>
  12. static esnmp_oid *oids = NULL;
  13. crit_x *_snmp_cs = NULL;
  14. void (*_snmp_prewalk)( int op,  SNMP_OBJECT *list ) = NULL;
  15. int (*_snmp_override)(  BYTE *com, int op, SNMP_OBJECT *list ) = NULL;
  16. /* If you need to process multi-MIB PDUs, set global variable snmpd_maxvars
  17.  * to some higher number inside your application, before you start the
  18.  * snmpd thread.  It is used to allocate buffers at thread start time
  19.  */
  20. #define SNMPD_MAXVARS 1
  21. int snmpd_maxvars = SNMPD_MAXVARS;
  22. //#define DEBUG
  23. #ifdef DEBUG
  24. print_oid( SNMP_OBJECT *oid, esnmp_oid *cmp  )
  25. {
  26.     int i;
  27.     if (oid != NULL )
  28.       for ( i = 0 ; i < oid->IdLen ; ++i )
  29.       {
  30.          dos_enter();
  31.          printf("%u.", oid->Id[i] );
  32.          dos_exit();
  33.       }
  34.     else
  35.       for ( i = 0 ; i < cmp->oidlen ; ++i )
  36.       {
  37.         dos_enter();
  38.         printf("%u.", cmp->oid[i] );
  39.         dos_exit();
  40.       }
  41. }
  42. #endif
  43. //---------------------------------------------------------------------
  44. // snmp_copyobjectid - copies "1.3.6..." to a reply packet and sets length
  45. void snmp_copyobjectid( DWORD * dest, char *source, UINT *len )
  46. {
  47.     char *t;
  48.     int i = 0;
  49.     char *s, *sstart;
  50.     /* get a working copy */
  51.     s = sstart = kcalloc( strlen( source ) + 1, 1 );
  52.     if ( s == NULL )
  53.       rt_halt("out of memory in SNMPD");
  54.     strcpy( s, source );
  55.     do {
  56.         if (( t = strchr( s , '.' )) != NULL ) *t = 0;
  57.         dest[ i ] = atol( s );
  58.         if ( t != NULL ) *t = '.';  // repair it
  59.         s = t + 1;
  60.         i++;
  61.     } while ( t );
  62.     *len = i;
  63.     kfree( sstart );
  64. }
  65. //---------------------------------------------------------------------
  66. static void copy_oid( SNMP_OBJECT *dest, SNMP_OBJECT *src )
  67. {
  68.     int i;
  69.     for ( i = 0 ; i < src->IdLen ; ++i )
  70.         dest->Id[i] = src->Id[i];
  71.     dest->IdLen = src->IdLen;
  72. }
  73. //---------------------------------------------------------------------
  74. //---------------------------------------------------------------------
  75. static void copy_newoid( SNMP_OBJECT *dest, esnmp_oid *src )
  76. {
  77.     int i;
  78.     for ( i = 0 ; i < src->oidlen; ++i )
  79.         dest->Id[i] = src->oid[i];
  80.     dest->IdLen = src->oidlen;
  81. }
  82. //---------------------------------------------------------------------
  83. void snmp_compile_oids( esnmp_oid *p )
  84. {
  85.     int i;
  86.     cs_new( &_snmp_cs );
  87.     cs_enter( _snmp_cs );
  88.     oids = p;
  89.     while ( p->oid[0] != -1 ) {
  90.         p->oidlen = 0;      /* safety if oid missing its -1 terminator */
  91.         for ( i = 0 ; i < SNMP_OID_SIZE ; ++i ) {
  92.             if ( p->oid[ i ] == -1 ) {
  93.                 p->oidlen = i;
  94.                 break;
  95.             }
  96.         }
  97.         p++;
  98.     }
  99.     cs_exit( _snmp_cs );
  100. }
  101. /*
  102.  * compare_oid - tell us if src is > (+1), = (0) or < (-1) cmp
  103.  */
  104. int _snmp_compare_oid( SNMP_OBJECT *src, esnmp_oid *cmp )
  105. {
  106.     long res;
  107.     int i;
  108.     for ( i = 0 ; (i < src->IdLen) && (i < cmp->oidlen) ; ++i ) {
  109.         res = src->Id[i] - cmp->oid[i];
  110.         if ( res < 0 ) return( -1 );
  111.         if ( res > 0 ) return( 1 );
  112.         /* = , continue */
  113.     }
  114.     /* got here, means they were equivalent so far */
  115.     res = src->IdLen - cmp->oidlen;
  116.     if ( res == 0 ) return( 0 );
  117.     if ( res < 0 ) return( 1 );
  118.     else return( -1 );
  119. }
  120. //---------------------------------------------------------------------
  121. #pragma argsused
  122. void snmpthread( DWORD dummy )
  123. {
  124.     SNMP_PDU        pdu;
  125.     SNMP_OBJECT     *list;
  126.     unsigned        listLen;
  127.     int             listi;
  128.     BYTE            com[16];
  129.     unsigned        comLen;
  130.     BYTE            *rqsBuffer, *rqs, *rqsSave;
  131.     unsigned        rqsLen;
  132.     int             op;
  133.     static udp_Socket sock;
  134.     int             socklistening;
  135.     int             res;
  136.     int i, j, rc;
  137.     esnmp_oid *cur;
  138.     int             useoverride;
  139.     if ((( list = kcalloc( sizeof( SNMP_OBJECT ), snmpd_maxvars )) == NULL ) ||
  140.         (( rqs = kcalloc( 2048, 1 )) == NULL ))
  141.         rt_halt("SNMPD, insufficient memory to start");
  142.     rqsSave = rqs; // save this buffer's address
  143.     socklistening = 0;
  144.     do {
  145.         if ( socklistening == 0 ) {
  146.             /* udp_open - use remote_IP=0, bind to first incoming IP address */
  147.             if (!udp_open( &sock, 161, 0, -1, NULL ))
  148.                 rt_halt("unable to open SNMP server socket");
  149.             socklistening = 1;
  150.         }
  151.         tcp_tick( NULL );
  152.         /* look for input */
  153.         if ( (rqsLen = sock_dataready( &sock )) == 0 ) {
  154.             rt_sleep( 10 );
  155.             continue;   /* no input */
  156.         }
  157.         /* we received an SNMP request, process it */
  158.         sock_fastread( &sock, rqs, 1024 );
  159.         SnmpDec(  rqs, rqsLen, &pdu, com, sizeof(com), &comLen, list, snmpd_maxvars, &listLen);
  160.         op = pdu.Type;
  161.         useoverride = 0;
  162.         /* build a reply packet */
  163.         pdu.Type = SNMP_PDU_RESPONSE;
  164.         pdu.Request.ErrorStatus = 0;
  165.         pdu.Request.ErrorIndex = 0;
  166.         if ( listLen > snmpd_maxvars )
  167.             listLen = snmpd_maxvars;
  168.         for ( listi = 0 ; listi < listLen ; ++listi ) {
  169.             /* search through for our OID */
  170.             res = 0;
  171.             /* serialize access to the table, incase there are different threads */
  172.             cs_enter( _snmp_cs );
  173.             /* user defined pre-walk function */
  174.             if ( _snmp_prewalk != NULL )
  175.                 (*_snmp_prewalk)( op, &list[listi] );
  176.             if ( _snmp_override != NULL ) {
  177.                 i = (*_snmp_override)( com, op, &list[listi] );
  178.                 if ( i == SNMP_NOOVERRIDE ) useoverride = 0;
  179.                 else {
  180.                     useoverride = 1;
  181.                     pdu.Request.ErrorStatus = i;
  182.                 }
  183.             }
  184.             /* walk through the oid table - if it exists */
  185.             if ( useoverride ) {
  186.                 /* user has supplied the packet */
  187.             }
  188.             else {
  189.                 if ( oids != NULL ) {
  190.                     for ( cur = oids ;  cur->oid[0] != -1 ; ++cur ) {
  191.                         if ( ( op == SNMP_PDU_GET ) || ( op == SNMP_PDU_SET )) {
  192.                             if ( _snmp_compare_oid( &list[listi] , cur ) == 0 ) {
  193.                                 res = 1;
  194.                                 break;
  195.                             }
  196.                         }
  197.                         if ( op == SNMP_PDU_NEXT ) {
  198.                             if ( _snmp_compare_oid( &list[listi] , cur ) < 0 ) {
  199.                                 res = 1;
  200.                                 break;
  201.                             }
  202.                         }
  203.                     }
  204.                 }
  205.                 if (( res == 0 ) || (cur == NULL)) {
  206.                     /* none found */
  207.                     pdu.Request.ErrorStatus = SNMP_NOSUCHNAME;
  208.                     pdu.Request.ErrorIndex = 0;
  209.                 } else {
  210.                     copy_newoid( &list[listi], cur );
  211.                     if ( cur->fn != NULL )
  212.                         pdu.Request.ErrorStatus = (*cur->fn)(
  213.                             &sock, com, op, &list[listi], cur->data1, cur->data2 );
  214.                     else {
  215.                         /* no function, use default formatting */
  216.                         if ( op == SNMP_PDU_SET )
  217.                             pdu.Request.ErrorStatus = SNMP_READONLY;
  218.                         else {
  219.                             list[listi].Type = cur->data1;
  220.                             switch ( cur->data1 ) {
  221.                                 case SNMP_DISPLAYSTR :
  222.                                     strcpy( list[listi].Syntax.BufChr, (char *)cur->data2 );
  223.                                     list[listi].SyntaxLen = strlen( (char*)cur->data2 );
  224.                                     break;
  225.                                 case SNMP_OBJECTID :
  226.                                     snmp_copyobjectid( list[listi].Syntax.BufInt,
  227.                                         (char *)cur->data2,
  228.                                          &(list[listi].SyntaxLen));
  229.                                     break;
  230.                                 default :   /* preserve other types */
  231.                                     list[listi].Syntax.LngInt = cur->data2;
  232.                                     break;
  233.                             }
  234.                         }
  235.                     }
  236.                 }
  237.             }
  238.             cs_exit( _snmp_cs );
  239.         }
  240.         rqsLen  = 1024; // 1024 matches the size of the kcalloc() above
  241.         rqs = rqsSave;  // restore the buffer pointer to the start of the buffer
  242.         rc = SnmpEnc(  &rqs, &rqsLen, &pdu, com,  comLen, list, listLen );
  243.         if( rc == 0 ) puts("SnmpEnc failed!");
  244.         sock_fastwrite( &sock, rqs, rqsLen );
  245.         sock_close( &sock );
  246.         /* open next snmp server */
  247.         socklistening = 0;
  248.     } while( 1 );
  249. }