Blame snmplib/snmp-tc.c

Packit fcad23
/*
Packit fcad23
 *  Host Resources MIB - utility functions - hr_utils.c
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
#include <sys/types.h>
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#include <ctype.h>
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if TIME_WITH_SYS_TIME
Packit fcad23
# include <sys/time.h>
Packit fcad23
# include <time.h>
Packit fcad23
#else
Packit fcad23
# if HAVE_SYS_TIME_H
Packit fcad23
#  include <sys/time.h>
Packit fcad23
# else
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/types.h>
Packit fcad23
#include <net-snmp/library/snmp-tc.h>   /* for "internal" definitions */
Packit fcad23
#include <net-snmp/library/snmp_api.h>
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(snmp_tc_all, libnetsnmp)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(netsnmp_dateandtime_set_buf_from_vars, netsnmp_unused)
Packit fcad23
netsnmp_feature_child_of(date_n_time, snmp_tc_all)
Packit fcad23
netsnmp_feature_child_of(ctime_to_timet, snmp_tc_all)
Packit fcad23
netsnmp_feature_child_of(check_rowstatus_with_storagetype_transition, snmp_tc_all)
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_NETSNMP_DATEANDTIME_SET_BUF_FROM_VARS
Packit fcad23
/*
Packit fcad23
  DateAndTime ::= TEXTUAL-CONVENTION
Packit fcad23
    DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
Packit fcad23
    STATUS       current
Packit fcad23
    DESCRIPTION
Packit fcad23
            "A date-time specification.
Packit fcad23
Packit fcad23
            field  octets  contents                  range
Packit fcad23
            -----  ------  --------                  -----
Packit fcad23
              1      1-2   year*                     0..65536
Packit fcad23
              2       3    month                     1..12
Packit fcad23
              3       4    day                       1..31
Packit fcad23
              4       5    hour                      0..23
Packit fcad23
              5       6    minutes                   0..59
Packit fcad23
              6       7    seconds                   0..60
Packit fcad23
                           (use 60 for leap-second)
Packit fcad23
              7       8    deci-seconds              0..9
Packit fcad23
              8       9    direction from UTC        '+' / '-'
Packit fcad23
              9      10    hours from UTC*           0..13
Packit fcad23
             10      11    minutes from UTC          0..59
Packit fcad23
Packit fcad23
            * Notes:
Packit fcad23
            - the value of year is in network-byte order
Packit fcad23
            - daylight saving time in New Zealand is +13
Packit fcad23
Packit fcad23
            For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
Packit fcad23
            displayed as:
Packit fcad23
Packit fcad23
                             1992-5-26,13:30:15.0,-4:0
Packit fcad23
Packit fcad23
            Note that if only local time is known, then timezone
Packit fcad23
            information (fields 8-10) is not present."
Packit fcad23
    SYNTAX       OCTET STRING (SIZE (8 | 11))
Packit fcad23
*/
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_dateandtime_set_buf_from_vars(u_char *buf, size_t *bufsize,
Packit fcad23
                                      u_short year, u_char month, u_char day,
Packit fcad23
                                      u_char hour, u_char minutes,
Packit fcad23
                                      u_char seconds, u_char deci_seconds,
Packit fcad23
                                      int utc_offset_direction,
Packit fcad23
                                      u_char utc_offset_hours,
Packit fcad23
                                      u_char utc_offset_minutes)
Packit fcad23
{
Packit fcad23
    u_short tmp_year = htons(year);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * if we have a utc offset, need 11 bytes. Otherwise we
Packit fcad23
     * just need 8 bytes.
Packit fcad23
     */
Packit fcad23
    if(utc_offset_direction) {
Packit fcad23
        if(*bufsize < 11)
Packit fcad23
            return SNMPERR_RANGE;
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * set utc offset data
Packit fcad23
         */
Packit fcad23
        buf[8] = (utc_offset_direction < 0) ? '-' : '+';
Packit fcad23
        buf[9] = utc_offset_hours;
Packit fcad23
        buf[10] = utc_offset_minutes;
Packit fcad23
        *bufsize = 11;
Packit fcad23
    }
Packit fcad23
    else if(*bufsize < 8)
Packit fcad23
        return SNMPERR_RANGE;
Packit fcad23
    else
Packit fcad23
        *bufsize = 8;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * set basic date/time data
Packit fcad23
     */
Packit fcad23
    memcpy(buf, &tmp_year, sizeof(tmp_year));
Packit fcad23
    buf[2] = month;
Packit fcad23
    buf[3] = day;
Packit fcad23
    buf[4] = hour;
Packit fcad23
    buf[5] = minutes;
Packit fcad23
    buf[6] = seconds;
Packit fcad23
    buf[7] = deci_seconds;
Packit fcad23
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_NETSNMP_DATEANDTIME_SET_BUF_FROM_VARS */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_DATE_N_TIME
Packit fcad23
u_char         *
Packit fcad23
date_n_time(const time_t * when, size_t * length)
Packit fcad23
{
Packit fcad23
    struct tm      *tm_p;
Packit fcad23
    static u_char   string[11];
Packit fcad23
    unsigned short yauron;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Null time
Packit fcad23
     */
Packit fcad23
    if (when == NULL || *when == 0 || *when == (time_t) - 1) {
Packit fcad23
        string[0] = 0;
Packit fcad23
        string[1] = 0;
Packit fcad23
        string[2] = 1;
Packit fcad23
        string[3] = 1;
Packit fcad23
        string[4] = 0;
Packit fcad23
        string[5] = 0;
Packit fcad23
        string[6] = 0;
Packit fcad23
        string[7] = 0;
Packit fcad23
        *length = 8;
Packit fcad23
        return string;
Packit fcad23
    }
Packit fcad23
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Basic 'local' time handling
Packit fcad23
     */
Packit fcad23
    tm_p = localtime(when);
Packit fcad23
    yauron = tm_p->tm_year + 1900;
Packit fcad23
    string[0] = (u_char)(yauron >> 8);
Packit fcad23
    string[1] = (u_char)yauron;
Packit fcad23
    string[2] = tm_p->tm_mon + 1;
Packit fcad23
    string[3] = tm_p->tm_mday;
Packit fcad23
    string[4] = tm_p->tm_hour;
Packit fcad23
    string[5] = tm_p->tm_min;
Packit fcad23
    string[6] = tm_p->tm_sec;
Packit fcad23
    string[7] = 0;
Packit fcad23
    *length = 8;
Packit fcad23
Packit fcad23
#if defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_TIMEZONE_VARIABLE)
Packit fcad23
    /*
Packit fcad23
     * Timezone offset
Packit fcad23
     */
Packit fcad23
    {
Packit fcad23
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
Packit fcad23
    const int tzoffset = -tm_p->tm_gmtoff;   /* Seconds east of UTC */
Packit fcad23
#else
Packit fcad23
    const int tzoffset = timezone;           /* Seconds west of UTC */
Packit fcad23
#endif
Packit fcad23
    if (tzoffset > 0)
Packit fcad23
        string[8] = '-';
Packit fcad23
    else
Packit fcad23
        string[8] = '+';
Packit fcad23
    string[9] = abs(tzoffset) / 3600;
Packit fcad23
    string[10] = (abs(tzoffset) - string[9] * 3600) / 60;
Packit fcad23
    *length = 11;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if defined(SYSV) && !HAVE_STRUCT_TM_TM_GMTOFF
Packit fcad23
    /*
Packit fcad23
     * Daylight saving time
Packit fcad23
     */
Packit fcad23
    if (tm_p->tm_isdst > 0) {
Packit fcad23
        /*
Packit fcad23
         * Assume add one hour 
Packit fcad23
         */
Packit fcad23
        if (string[8] == '-')
Packit fcad23
            --string[9];
Packit fcad23
        else
Packit fcad23
            ++string[9];
Packit fcad23
Packit fcad23
        if (string[9] == 0)
Packit fcad23
            string[8] = '+';
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    return string;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_DATE_N_TIME */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CTIME_TO_TIMET
Packit fcad23
time_t
Packit fcad23
ctime_to_timet(const char *str)
Packit fcad23
{
Packit fcad23
    struct tm       tm;
Packit fcad23
Packit fcad23
    if (strlen(str) < 24)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Month 
Packit fcad23
     */
Packit fcad23
    if (!strncmp(str + 4, "Jan", 3))
Packit fcad23
        tm.tm_mon = 0;
Packit fcad23
    else if (!strncmp(str + 4, "Feb", 3))
Packit fcad23
        tm.tm_mon = 1;
Packit fcad23
    else if (!strncmp(str + 4, "Mar", 3))
Packit fcad23
        tm.tm_mon = 2;
Packit fcad23
    else if (!strncmp(str + 4, "Apr", 3))
Packit fcad23
        tm.tm_mon = 3;
Packit fcad23
    else if (!strncmp(str + 4, "May", 3))
Packit fcad23
        tm.tm_mon = 4;
Packit fcad23
    else if (!strncmp(str + 4, "Jun", 3))
Packit fcad23
        tm.tm_mon = 5;
Packit fcad23
    else if (!strncmp(str + 4, "Jul", 3))
Packit fcad23
        tm.tm_mon = 6;
Packit fcad23
    else if (!strncmp(str + 4, "Aug", 3))
Packit fcad23
        tm.tm_mon = 7;
Packit fcad23
    else if (!strncmp(str + 4, "Sep", 3))
Packit fcad23
        tm.tm_mon = 8;
Packit fcad23
    else if (!strncmp(str + 4, "Oct", 3))
Packit fcad23
        tm.tm_mon = 9;
Packit fcad23
    else if (!strncmp(str + 4, "Nov", 3))
Packit fcad23
        tm.tm_mon = 10;
Packit fcad23
    else if (!strncmp(str + 4, "Dec", 3))
Packit fcad23
        tm.tm_mon = 11;
Packit fcad23
    else
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    tm.tm_mday = atoi(str + 8);
Packit fcad23
    tm.tm_hour = atoi(str + 11);
Packit fcad23
    tm.tm_min = atoi(str + 14);
Packit fcad23
    tm.tm_sec = atoi(str + 17);
Packit fcad23
    tm.tm_year = atoi(str + 20) - 1900;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  Cope with timezone and DST
Packit fcad23
     */
Packit fcad23
Packit fcad23
#ifdef HAVE_STRUCT_TIME_TM_ISDST
Packit fcad23
    tm.tm_isdst = !!daylight;
Packit fcad23
    tm.tm_sec -= timezone;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    return (mktime(&tm));
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CTIME_TO_TIMET */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * blatantly lifted from opensnmp 
Packit fcad23
 */
Packit fcad23
char
Packit fcad23
check_rowstatus_transition(int oldValue, int newValue)
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * From the SNMPv2-TC MIB:
Packit fcad23
     *                                          STATE
Packit fcad23
     *               +--------------+-----------+-------------+-------------
Packit fcad23
     *               |      A       |     B     |      C      |      D
Packit fcad23
     *               |              |status col.|status column|
Packit fcad23
     *               |status column |    is     |      is     |status column
Packit fcad23
     *     ACTION    |does not exist|  notReady | notInService|  is active
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     * set status    |noError    ->D|inconsist- |inconsistent-|inconsistent-
Packit fcad23
     * column to     |       or     |   entValue|        Value|        Value
Packit fcad23
     * createAndGo   |inconsistent- |           |             |
Packit fcad23
     *               |         Value|           |             |
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     * set status    |noError  see 1|inconsist- |inconsistent-|inconsistent-
Packit fcad23
     * column to     |       or     |   entValue|        Value|        Value
Packit fcad23
     * createAndWait |wrongValue    |           |             |
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     * set status    |inconsistent- |inconsist- |noError      |noError
Packit fcad23
     * column to     |         Value|   entValue|             |
Packit fcad23
     * active        |              |           |             |
Packit fcad23
     *               |              |     or    |             |
Packit fcad23
     *               |              |           |             |
Packit fcad23
     *               |              |see 2   ->D|see 8     ->D|          ->D
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     * set status    |inconsistent- |inconsist- |noError      |noError   ->C
Packit fcad23
     * column to     |         Value|   entValue|             |
Packit fcad23
     * notInService  |              |           |             |
Packit fcad23
     *               |              |     or    |             |      or
Packit fcad23
     *               |              |           |             |
Packit fcad23
     *               |              |see 3   ->C|          ->C|see 6
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     * set status    |noError       |noError    |noError      |noError   ->A
Packit fcad23
     * column to     |              |           |             |      or
Packit fcad23
     * destroy       |           ->A|        ->A|          ->A|see 7
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     * set any other |see 4         |noError    |noError      |see 5
Packit fcad23
     * column to some|              |           |             |
Packit fcad23
     * value         |              |      see 1|          ->C|          ->D
Packit fcad23
     * --------------+--------------+-----------+-------------+-------------
Packit fcad23
     
Packit fcad23
     *             (1) goto B or C, depending on information available to the
Packit fcad23
     *             agent.
Packit fcad23
     
Packit fcad23
     *             (2) if other variable bindings included in the same PDU,
Packit fcad23
     *             provide values for all columns which are missing but
Packit fcad23
     *             required, and all columns have acceptable values, then
Packit fcad23
     *             return noError and goto D.
Packit fcad23
     
Packit fcad23
     *             (3) if other variable bindings included in the same PDU,
Packit fcad23
     *             provide legal values for all columns which are missing but
Packit fcad23
     *             required, then return noError and goto C.
Packit fcad23
     
Packit fcad23
     *             (4) at the discretion of the agent, the return value may be
Packit fcad23
     *             either:
Packit fcad23
     
Packit fcad23
     *                  inconsistentName:  because the agent does not choose to
Packit fcad23
     *                  create such an instance when the corresponding
Packit fcad23
     *                  RowStatus instance does not exist, or
Packit fcad23
     
Packit fcad23
     *                  inconsistentValue:  if the supplied value is
Packit fcad23
     *                  inconsistent with the state of some other MIB object's
Packit fcad23
     *                  value, or
Packit fcad23
     
Packit fcad23
     *                  noError: because the agent chooses to create the
Packit fcad23
     *                  instance.
Packit fcad23
     
Packit fcad23
     *             If noError is returned, then the instance of the status
Packit fcad23
     *             column must also be created, and the new state is B or C,
Packit fcad23
     *             depending on the information available to the agent.  If
Packit fcad23
     *             inconsistentName or inconsistentValue is returned, the row
Packit fcad23
     *             remains in state A.
Packit fcad23
     
Packit fcad23
     *             (5) depending on the MIB definition for the column/table,
Packit fcad23
     *             either noError or inconsistentValue may be returned.
Packit fcad23
     
Packit fcad23
     *             (6) the return value can indicate one of the following
Packit fcad23
     *             errors:
Packit fcad23
     
Packit fcad23
     *                  wrongValue: because the agent does not support
Packit fcad23
     *                  notInService (e.g., an agent which does not support
Packit fcad23
     *                  createAndWait), or
Packit fcad23
     
Packit fcad23
     *                  inconsistentValue: because the agent is unable to take
Packit fcad23
     *                  the row out of service at this time, perhaps because it
Packit fcad23
     *                  is in use and cannot be de-activated.
Packit fcad23
     
Packit fcad23
     *             (7) the return value can indicate the following error:
Packit fcad23
     
Packit fcad23
     *                  inconsistentValue: because the agent is unable to
Packit fcad23
     *                  remove the row at this time, perhaps because it is in
Packit fcad23
     *                  use and cannot be de-activated.
Packit fcad23
     
Packit fcad23
     *             (8) the transition to D can fail, e.g., if the values of the
Packit fcad23
     *             conceptual row are inconsistent, then the error code would
Packit fcad23
     *             be inconsistentValue.
Packit fcad23
     
Packit fcad23
     *             NOTE: Other processing of (this and other varbinds of) the
Packit fcad23
     *             set request may result in a response other than noError
Packit fcad23
     *             being returned, e.g., wrongValue, noCreation, etc.
Packit fcad23
     */
Packit fcad23
Packit fcad23
    switch (newValue) {
Packit fcad23
        /*
Packit fcad23
         * these two end up being equivelent as far as checking the 
Packit fcad23
         * status goes, although the final states are based on the 
Packit fcad23
         * newValue. 
Packit fcad23
         */
Packit fcad23
    case RS_ACTIVE:
Packit fcad23
    case RS_NOTINSERVICE:
Packit fcad23
        if (oldValue == RS_NOTINSERVICE || oldValue == RS_ACTIVE)
Packit fcad23
            ;
Packit fcad23
        else
Packit fcad23
            return SNMP_ERR_INCONSISTENTVALUE;
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case RS_NOTREADY:
Packit fcad23
        /*
Packit fcad23
         * Illegal set value. 
Packit fcad23
         */
Packit fcad23
        return SNMP_ERR_WRONGVALUE;
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case RS_CREATEANDGO:
Packit fcad23
    case RS_CREATEANDWAIT:
Packit fcad23
        if (oldValue != RS_NONEXISTENT)
Packit fcad23
            /*
Packit fcad23
             * impossible, we already exist. 
Packit fcad23
             */
Packit fcad23
            return SNMP_ERR_INCONSISTENTVALUE;
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case RS_DESTROY:
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    default:
Packit fcad23
        return SNMP_ERR_WRONGVALUE;
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return SNMP_ERR_NOERROR;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CHECK_ROWSTATUS_WITH_STORAGETYPE_TRANSITION
Packit fcad23
char
Packit fcad23
check_rowstatus_with_storagetype_transition(int oldValue, int newValue,
Packit fcad23
                                            int oldStorage)
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * can not destroy permanent or readonly rows
Packit fcad23
     */
Packit fcad23
    if ((RS_DESTROY == newValue) &&
Packit fcad23
        ((SNMP_STORAGE_PERMANENT == oldStorage) ||
Packit fcad23
         (SNMP_STORAGE_READONLY == oldStorage)))
Packit fcad23
        return SNMP_ERR_WRONGVALUE;
Packit fcad23
Packit fcad23
    return check_rowstatus_transition(oldValue, newValue);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CHECK_ROWSTATUS_WITH_STORAGETYPE_TRANSITION */
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(check_storage_transition, snmp_tc_all)
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CHECK_STORAGE_TRANSITION
Packit fcad23
char
Packit fcad23
check_storage_transition(int oldValue, int newValue)
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * From the SNMPv2-TC MIB:
Packit fcad23
     
Packit fcad23
     *             "Describes the memory realization of a conceptual row.  A
Packit fcad23
     *             row which is volatile(2) is lost upon reboot.  A row which
Packit fcad23
     *             is either nonVolatile(3), permanent(4) or readOnly(5), is
Packit fcad23
     *             backed up by stable storage.  A row which is permanent(4)
Packit fcad23
     *             can be changed but not deleted.  A row which is readOnly(5)
Packit fcad23
     *             cannot be changed nor deleted.
Packit fcad23
     
Packit fcad23
     *             If the value of an object with this syntax is either
Packit fcad23
     *             permanent(4) or readOnly(5), it cannot be written.
Packit fcad23
     *             Conversely, if the value is either other(1), volatile(2) or
Packit fcad23
     *             nonVolatile(3), it cannot be modified to be permanent(4) or
Packit fcad23
     *             readOnly(5).  (All illegal modifications result in a
Packit fcad23
     *             'wrongValue' error.)
Packit fcad23
     
Packit fcad23
     *             Every usage of this textual convention is required to
Packit fcad23
     *             specify the columnar objects which a permanent(4) row must
Packit fcad23
     *             at a minimum allow to be writable."
Packit fcad23
     */
Packit fcad23
    switch (oldValue) {
Packit fcad23
    case SNMP_STORAGE_PERMANENT:
Packit fcad23
    case SNMP_STORAGE_READONLY:
Packit fcad23
        return SNMP_ERR_INCONSISTENTVALUE;
Packit fcad23
Packit fcad23
    case SNMP_STORAGE_NONE:
Packit fcad23
    case SNMP_STORAGE_OTHER:
Packit fcad23
    case SNMP_STORAGE_VOLATILE:
Packit fcad23
    case SNMP_STORAGE_NONVOLATILE:
Packit fcad23
        if (newValue == SNMP_STORAGE_PERMANENT ||
Packit fcad23
            newValue == SNMP_STORAGE_READONLY)
Packit fcad23
            return SNMP_ERR_INCONSISTENTVALUE;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return SNMP_ERR_NOERROR;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CHECK_STORAGE_TRANSITION */