summaryrefslogtreecommitdiff
path: root/snmplib/snmp-tc.c
diff options
context:
space:
mode:
Diffstat (limited to 'snmplib/snmp-tc.c')
-rw-r--r--snmplib/snmp-tc.c460
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;
+}