| /* |
| * Host Resources MIB - utility functions - hr_utils.c |
| * |
| */ |
| |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include <sys/types.h> |
| #if HAVE_NETINET_IN_H |
| #include <netinet/in.h> |
| #endif |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #include <ctype.h> |
| #if HAVE_STRING_H |
| #include <string.h> |
| #endif |
| #if HAVE_STDLIB_H |
| #include <stdlib.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 <net-snmp/types.h> |
| #include <net-snmp/library/snmp-tc.h> /* for "internal" definitions */ |
| #include <net-snmp/library/snmp_api.h> |
| |
| u_char * |
| date_n_time ( time_t *when, size_t *length) |
| { |
| struct tm *tm_p; |
| static u_char string[11]; |
| |
| /* |
| * Null time |
| */ |
| if ( when == NULL || *when == 0 || *when == (time_t)-1 ) { |
| string[0] = 0; |
| string[1] = 0; |
| string[2] = 1; |
| string[3] = 1; |
| string[4] = 0; |
| string[5] = 0; |
| string[6] = 0; |
| string[7] = 0; |
| *length = 8; |
| return string; |
| } |
| |
| |
| /* |
| * Basic 'local' time handling |
| */ |
| tm_p = localtime( when ); |
| * (short *)string = htons( tm_p->tm_year+1900 ); |
| string[2] = tm_p->tm_mon+1; |
| string[3] = tm_p->tm_mday; |
| string[4] = tm_p->tm_hour; |
| string[5] = tm_p->tm_min; |
| string[6] = tm_p->tm_sec; |
| string[7] = 0; |
| *length = 8; |
| |
| #ifndef cygwin |
| /* |
| * Timezone offset |
| */ |
| #ifndef SYSV |
| #ifndef aix |
| #define timezone tm_p->tm_gmtoff |
| #endif |
| #endif |
| if ( timezone > 0 ) |
| string[8] = '-'; |
| else |
| string[8] = '+'; |
| string[9] = abs(timezone)/3600; |
| string[10] = (abs(timezone) - string[9]*3600)/60; |
| *length = 11; |
| #endif |
| |
| #ifdef SYSV |
| /* |
| * Daylight saving time |
| */ |
| if ( tm_p->tm_isdst > 0 ) { |
| /* Assume add one hour */ |
| if ( string[8]=='-' ) |
| --string[9]; |
| else |
| ++string[9]; |
| |
| if ( string[9]==0 ) |
| string[8]='+'; |
| } |
| #endif |
| |
| return string; |
| } |
| |
| |
| time_t ctime_to_timet( char* string ) |
| { |
| struct tm tm; |
| |
| if ( strlen(string) < 24 ) |
| return 0; |
| |
| /* Month */ |
| if ( !strncmp( string+4, "Jan", 3 )) tm.tm_mon = 0; |
| else if ( !strncmp( string+4, "Feb", 3 )) tm.tm_mon = 1; |
| else if ( !strncmp( string+4, "Mar", 3 )) tm.tm_mon = 2; |
| else if ( !strncmp( string+4, "Apr", 3 )) tm.tm_mon = 3; |
| else if ( !strncmp( string+4, "May", 3 )) tm.tm_mon = 4; |
| else if ( !strncmp( string+4, "Jun", 3 )) tm.tm_mon = 5; |
| else if ( !strncmp( string+4, "Jul", 3 )) tm.tm_mon = 6; |
| else if ( !strncmp( string+4, "Aug", 3 )) tm.tm_mon = 7; |
| else if ( !strncmp( string+4, "Sep", 3 )) tm.tm_mon = 8; |
| else if ( !strncmp( string+4, "Oct", 3 )) tm.tm_mon = 9; |
| else if ( !strncmp( string+4, "Nov", 3 )) tm.tm_mon = 10; |
| else if ( !strncmp( string+4, "Dec", 3 )) tm.tm_mon = 11; |
| else return 0; |
| |
| tm.tm_mday = atoi(string+8); |
| tm.tm_hour = atoi(string+11); |
| tm.tm_min = atoi(string+14); |
| tm.tm_sec = atoi(string+17); |
| tm.tm_year = atoi(string+20) - 1900; |
| |
| /* |
| * Cope with timezone and DST |
| */ |
| |
| #ifdef SYSV |
| if ( daylight ) |
| tm.tm_isdst = 1; |
| |
| tm.tm_sec -= timezone; |
| #endif |
| |
| return( mktime( &tm )); |
| } |
| |
| /* blatantly lifted from opensmp */ |
| char |
| check_rowstatus_transition( int oldValue, int newValue, int storage_type ) |
| { |
| /* |
| // From the SNMPv2-TC MIB: |
| // STATE |
| // +--------------+-----------+-------------+------------- |
| // | A | B | C | D |
| // | |status col.|status column| |
| // |status column | is | is |status column |
| // ACTION |does not exist| notReady | notInService| is active |
| // --------------+--------------+-----------+-------------+------------- |
| // set status |noError ->D|inconsist- |inconsistent-|inconsistent- |
| // column to | or | entValue| Value| Value |
| // createAndGo |inconsistent- | | | |
| // | Value| | | |
| // --------------+--------------+-----------+-------------+------------- |
| // set status |noError see 1|inconsist- |inconsistent-|inconsistent- |
| // column to | or | entValue| Value| Value |
| // createAndWait |wrongValue | | | |
| // --------------+--------------+-----------+-------------+------------- |
| // set status |inconsistent- |inconsist- |noError |noError |
| // column to | Value| entValue| | |
| // active | | | | |
| // | | or | | |
| // | | | | |
| // | |see 2 ->D|see 8 ->D| ->D |
| // --------------+--------------+-----------+-------------+------------- |
| // set status |inconsistent- |inconsist- |noError |noError ->C |
| // column to | Value| entValue| | |
| // notInService | | | | |
| // | | or | | or |
| // | | | | |
| // | |see 3 ->C| ->C|see 6 |
| // --------------+--------------+-----------+-------------+------------- |
| // set status |noError |noError |noError |noError ->A |
| // column to | | | | or |
| // destroy | ->A| ->A| ->A|see 7 |
| // --------------+--------------+-----------+-------------+------------- |
| // set any other |see 4 |noError |noError |see 5 |
| // column to some| | | | |
| // value | | see 1| ->C| ->D |
| // --------------+--------------+-----------+-------------+------------- |
| |
| // (1) goto B or C, depending on information available to the |
| // agent. |
| |
| // (2) if other variable bindings included in the same PDU, |
| // provide values for all columns which are missing but |
| // required, and all columns have acceptable values, then |
| // return noError and goto D. |
| |
| // (3) if other variable bindings included in the same PDU, |
| // provide legal values for all columns which are missing but |
| // required, then return noError and goto C. |
| |
| // (4) at the discretion of the agent, the return value may be |
| // either: |
| |
| // inconsistentName: because the agent does not choose to |
| // create such an instance when the corresponding |
| // RowStatus instance does not exist, or |
| |
| // inconsistentValue: if the supplied value is |
| // inconsistent with the state of some other MIB object's |
| // value, or |
| |
| // noError: because the agent chooses to create the |
| // instance. |
| |
| // If noError is returned, then the instance of the status |
| // column must also be created, and the new state is B or C, |
| // depending on the information available to the agent. If |
| // inconsistentName or inconsistentValue is returned, the row |
| // remains in state A. |
| |
| // (5) depending on the MIB definition for the column/table, |
| // either noError or inconsistentValue may be returned. |
| |
| // (6) the return value can indicate one of the following |
| // errors: |
| |
| // wrongValue: because the agent does not support |
| // notInService (e.g., an agent which does not support |
| // createAndWait), or |
| |
| // inconsistentValue: because the agent is unable to take |
| // the row out of service at this time, perhaps because it |
| // is in use and cannot be de-activated. |
| |
| // (7) the return value can indicate the following error: |
| |
| // inconsistentValue: because the agent is unable to |
| // remove the row at this time, perhaps because it is in |
| // use and cannot be de-activated. |
| |
| // (8) the transition to D can fail, e.g., if the values of the |
| // conceptual row are inconsistent, then the error code would |
| // be inconsistentValue. |
| |
| // NOTE: Other processing of (this and other varbinds of) the |
| // set request may result in a response other than noError |
| // being returned, e.g., wrongValue, noCreation, etc. |
| */ |
| |
| switch (newValue) { |
| // these two end up being equivelent as far as checking the |
| // status goes, although the final states are based on the |
| // newValue. |
| case RS_ACTIVE: |
| case RS_NOTINSERVICE: |
| if (oldValue == RS_NOTINSERVICE || |
| oldValue == RS_ACTIVE) |
| ; |
| else |
| return SNMP_ERR_INCONSISTENTVALUE; |
| break; |
| |
| case RS_NOTREADY: |
| // Illegal set value. |
| return SNMP_ERR_INCONSISTENTVALUE; |
| break; |
| |
| case RS_CREATEANDGO: |
| if (oldValue != RS_NONEXISTENT) |
| // impossible, we already exist. |
| return SNMP_ERR_INCONSISTENTVALUE; |
| break; |
| |
| case RS_CREATEANDWAIT: |
| if (oldValue != RS_NONEXISTENT) |
| // impossible, we already exist. |
| return SNMP_ERR_INCONSISTENTVALUE; |
| break; |
| |
| case RS_DESTROY: |
| break; |
| |
| default: |
| return SNMP_ERR_INCONSISTENTVALUE; |
| break; |
| } |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| char |
| check_storage_transition( int oldValue, int newValue ){ |
| /* |
| // From the SNMPv2-TC MIB: |
| |
| // "Describes the memory realization of a conceptual row. A |
| // row which is volatile(2) is lost upon reboot. A row which |
| // is either nonVolatile(3), permanent(4) or readOnly(5), is |
| // backed up by stable storage. A row which is permanent(4) |
| // can be changed but not deleted. A row which is readOnly(5) |
| // cannot be changed nor deleted. |
| |
| // If the value of an object with this syntax is either |
| // permanent(4) or readOnly(5), it cannot be written. |
| // Conversely, if the value is either other(1), volatile(2) or |
| // nonVolatile(3), it cannot be modified to be permanent(4) or |
| // readOnly(5). (All illegal modifications result in a |
| // 'wrongValue' error.) |
| |
| // Every usage of this textual convention is required to |
| // specify the columnar objects which a permanent(4) row must |
| // at a minimum allow to be writable." |
| */ |
| switch (oldValue) { |
| case SNMP_STORAGE_PERMANENT: |
| case SNMP_STORAGE_READONLY: |
| return SNMP_ERR_INCONSISTENTVALUE; |
| |
| case SNMP_STORAGE_OTHER: |
| case SNMP_STORAGE_VOLATILE: |
| case SNMP_STORAGE_NONVOLATILE: |
| if (newValue == SNMP_STORAGE_PERMANENT || |
| newValue == SNMP_STORAGE_READONLY) |
| return SNMP_ERR_INCONSISTENTVALUE; |
| } |
| |
| return SNMP_ERR_NOERROR; |
| } |