diff options
Diffstat (limited to 'snmplib/snmp-tc.c')
-rw-r--r-- | snmplib/snmp-tc.c | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/snmplib/snmp-tc.c b/snmplib/snmp-tc.c new file mode 100644 index 0000000..9622e45 --- /dev/null +++ b/snmplib/snmp-tc.c @@ -0,0 +1,460 @@ +/* + * 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 +#ifdef WIN32 +# include <sys/timeb.h> +#else +# include <sys/time.h> +#endif +# 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> + +/* + DateAndTime ::= TEXTUAL-CONVENTION + DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" + STATUS current + DESCRIPTION + "A date-time specification. + + field octets contents range + ----- ------ -------- ----- + 1 1-2 year* 0..65536 + 2 3 month 1..12 + 3 4 day 1..31 + 4 5 hour 0..23 + 5 6 minutes 0..59 + 6 7 seconds 0..60 + (use 60 for leap-second) + 7 8 deci-seconds 0..9 + 8 9 direction from UTC '+' / '-' + 9 10 hours from UTC* 0..13 + 10 11 minutes from UTC 0..59 + + * Notes: + - the value of year is in network-byte order + - daylight saving time in New Zealand is +13 + + For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be + displayed as: + + 1992-5-26,13:30:15.0,-4:0 + + Note that if only local time is known, then timezone + information (fields 8-10) is not present." + SYNTAX OCTET STRING (SIZE (8 | 11)) +*/ + +int +netsnmp_dateandtime_set_buf_from_vars(u_char *buf, size_t *bufsize, + u_short year, u_char month, u_char day, + u_char hour, u_char minutes, + u_char seconds, u_char deci_seconds, + int utc_offset_direction, + u_char utc_offset_hours, + u_char utc_offset_minutes) +{ + u_short tmp_year = htons(year); + + /* + * if we have a utc offset, need 11 bytes. Otherwise we + * just need 8 bytes. + */ + if(utc_offset_direction) { + if(*bufsize < 11) + return SNMPERR_RANGE; + + /* + * set utc offset data + */ + buf[8] = (utc_offset_direction < 0) ? '-' : '+'; + buf[9] = utc_offset_hours; + buf[10] = utc_offset_minutes; + *bufsize = 11; + } + else if(*bufsize < 8) + return SNMPERR_RANGE; + else + *bufsize = 8; + + /* + * set basic date/time data + */ + memcpy(buf, &tmp_year, sizeof(tmp_year)); + buf[2] = month; + buf[3] = day; + buf[4] = hour; + buf[5] = minutes; + buf[6] = seconds; + buf[7] = deci_seconds; + + return SNMPERR_SUCCESS; +} + +u_char * +date_n_time(time_t * when, size_t * length) +{ + struct tm *tm_p; + static u_char string[11]; + unsigned short yauron; + + /* + * 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); + yauron = tm_p->tm_year + 1900; + string[0] = (u_char)(yauron >> 8); + string[1] = (u_char)yauron; + 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 + */ + { +#ifdef STRUCT_TM_HAS_TM_GMTOFF + const int tzoffset = tm_p->tm_gmtoff; +#else + const int tzoffset = timezone; +#endif + if (tzoffset > 0) + string[8] = '-'; + else + string[8] = '+'; + string[9] = abs(tzoffset) / 3600; + string[10] = (abs(tzoffset) - 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 *str) +{ + struct tm tm; + + if (strlen(str) < 24) + return 0; + + /* + * Month + */ + if (!strncmp(str + 4, "Jan", 3)) + tm.tm_mon = 0; + else if (!strncmp(str + 4, "Feb", 3)) + tm.tm_mon = 1; + else if (!strncmp(str + 4, "Mar", 3)) + tm.tm_mon = 2; + else if (!strncmp(str + 4, "Apr", 3)) + tm.tm_mon = 3; + else if (!strncmp(str + 4, "May", 3)) + tm.tm_mon = 4; + else if (!strncmp(str + 4, "Jun", 3)) + tm.tm_mon = 5; + else if (!strncmp(str + 4, "Jul", 3)) + tm.tm_mon = 6; + else if (!strncmp(str + 4, "Aug", 3)) + tm.tm_mon = 7; + else if (!strncmp(str + 4, "Sep", 3)) + tm.tm_mon = 8; + else if (!strncmp(str + 4, "Oct", 3)) + tm.tm_mon = 9; + else if (!strncmp(str + 4, "Nov", 3)) + tm.tm_mon = 10; + else if (!strncmp(str + 4, "Dec", 3)) + tm.tm_mon = 11; + else + return 0; + + tm.tm_mday = atoi(str + 8); + tm.tm_hour = atoi(str + 11); + tm.tm_min = atoi(str + 14); + tm.tm_sec = atoi(str + 17); + tm.tm_year = atoi(str + 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) +{ + /* + * 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_WRONGVALUE; + 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_WRONGVALUE; + 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_NONE: + 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; +} |