net-snmp 5.7
|
00001 /* 00002 * Host Resources MIB - utility functions - hr_utils.c 00003 * 00004 */ 00005 00006 00007 #include <net-snmp/net-snmp-config.h> 00008 #include <net-snmp/net-snmp-features.h> 00009 #include <sys/types.h> 00010 #if HAVE_STDLIB_H 00011 #include <stdlib.h> 00012 #endif 00013 #include <ctype.h> 00014 #if HAVE_STRING_H 00015 #include <string.h> 00016 #endif 00017 #if HAVE_NETINET_IN_H 00018 #include <netinet/in.h> 00019 #endif 00020 00021 #if TIME_WITH_SYS_TIME 00022 # include <sys/time.h> 00023 # include <time.h> 00024 #else 00025 # if HAVE_SYS_TIME_H 00026 # include <sys/time.h> 00027 # else 00028 # include <time.h> 00029 # endif 00030 #endif 00031 00032 #include <net-snmp/types.h> 00033 #include <net-snmp/library/snmp-tc.h> /* for "internal" definitions */ 00034 #include <net-snmp/library/snmp_api.h> 00035 00036 netsnmp_feature_child_of(snmp_tc_all, libnetsnmp) 00037 00038 netsnmp_feature_child_of(netsnmp_dateandtime_set_buf_from_vars, netsnmp_unused) 00039 netsnmp_feature_child_of(date_n_time, snmp_tc_all) 00040 netsnmp_feature_child_of(ctime_to_timet, snmp_tc_all) 00041 netsnmp_feature_child_of(check_rowstatus_with_storagetype_transition, snmp_tc_all) 00042 00043 #ifndef NETSNMP_FEATURE_REMOVE_NETSNMP_DATEANDTIME_SET_BUF_FROM_VARS 00044 /* 00045 DateAndTime ::= TEXTUAL-CONVENTION 00046 DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" 00047 STATUS current 00048 DESCRIPTION 00049 "A date-time specification. 00050 00051 field octets contents range 00052 ----- ------ -------- ----- 00053 1 1-2 year* 0..65536 00054 2 3 month 1..12 00055 3 4 day 1..31 00056 4 5 hour 0..23 00057 5 6 minutes 0..59 00058 6 7 seconds 0..60 00059 (use 60 for leap-second) 00060 7 8 deci-seconds 0..9 00061 8 9 direction from UTC '+' / '-' 00062 9 10 hours from UTC* 0..13 00063 10 11 minutes from UTC 0..59 00064 00065 * Notes: 00066 - the value of year is in network-byte order 00067 - daylight saving time in New Zealand is +13 00068 00069 For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be 00070 displayed as: 00071 00072 1992-5-26,13:30:15.0,-4:0 00073 00074 Note that if only local time is known, then timezone 00075 information (fields 8-10) is not present." 00076 SYNTAX OCTET STRING (SIZE (8 | 11)) 00077 */ 00078 00079 int 00080 netsnmp_dateandtime_set_buf_from_vars(u_char *buf, size_t *bufsize, 00081 u_short year, u_char month, u_char day, 00082 u_char hour, u_char minutes, 00083 u_char seconds, u_char deci_seconds, 00084 int utc_offset_direction, 00085 u_char utc_offset_hours, 00086 u_char utc_offset_minutes) 00087 { 00088 u_short tmp_year = htons(year); 00089 00090 /* 00091 * if we have a utc offset, need 11 bytes. Otherwise we 00092 * just need 8 bytes. 00093 */ 00094 if(utc_offset_direction) { 00095 if(*bufsize < 11) 00096 return SNMPERR_RANGE; 00097 00098 /* 00099 * set utc offset data 00100 */ 00101 buf[8] = (utc_offset_direction < 0) ? '-' : '+'; 00102 buf[9] = utc_offset_hours; 00103 buf[10] = utc_offset_minutes; 00104 *bufsize = 11; 00105 } 00106 else if(*bufsize < 8) 00107 return SNMPERR_RANGE; 00108 else 00109 *bufsize = 8; 00110 00111 /* 00112 * set basic date/time data 00113 */ 00114 memcpy(buf, &tmp_year, sizeof(tmp_year)); 00115 buf[2] = month; 00116 buf[3] = day; 00117 buf[4] = hour; 00118 buf[5] = minutes; 00119 buf[6] = seconds; 00120 buf[7] = deci_seconds; 00121 00122 return SNMPERR_SUCCESS; 00123 } 00124 #endif /* NETSNMP_FEATURE_REMOVE_NETSNMP_DATEANDTIME_SET_BUF_FROM_VARS */ 00125 00126 #ifndef NETSNMP_FEATURE_REMOVE_DATE_N_TIME 00127 u_char * 00128 date_n_time(const time_t * when, size_t * length) 00129 { 00130 struct tm *tm_p; 00131 static u_char string[11]; 00132 unsigned short yauron; 00133 00134 /* 00135 * Null time 00136 */ 00137 if (when == NULL || *when == 0 || *when == (time_t) - 1) { 00138 string[0] = 0; 00139 string[1] = 0; 00140 string[2] = 1; 00141 string[3] = 1; 00142 string[4] = 0; 00143 string[5] = 0; 00144 string[6] = 0; 00145 string[7] = 0; 00146 *length = 8; 00147 return string; 00148 } 00149 00150 00151 /* 00152 * Basic 'local' time handling 00153 */ 00154 tm_p = localtime(when); 00155 yauron = tm_p->tm_year + 1900; 00156 string[0] = (u_char)(yauron >> 8); 00157 string[1] = (u_char)yauron; 00158 string[2] = tm_p->tm_mon + 1; 00159 string[3] = tm_p->tm_mday; 00160 string[4] = tm_p->tm_hour; 00161 string[5] = tm_p->tm_min; 00162 string[6] = tm_p->tm_sec; 00163 string[7] = 0; 00164 *length = 8; 00165 00166 #ifndef cygwin 00167 /* 00168 * Timezone offset 00169 */ 00170 { 00171 #ifdef HAVE_STRUCT_TM_TM_GMTOFF 00172 const int tzoffset = -tm_p->tm_gmtoff; /* Seconds east of UTC */ 00173 #else 00174 const int tzoffset = timezone; /* Seconds west of UTC */ 00175 #endif 00176 if (tzoffset > 0) 00177 string[8] = '-'; 00178 else 00179 string[8] = '+'; 00180 string[9] = abs(tzoffset) / 3600; 00181 string[10] = (abs(tzoffset) - string[9] * 3600) / 60; 00182 *length = 11; 00183 } 00184 #endif 00185 00186 #if defined(SYSV) && !HAVE_STRUCT_TM_TM_GMTOFF 00187 /* 00188 * Daylight saving time 00189 */ 00190 if (tm_p->tm_isdst > 0) { 00191 /* 00192 * Assume add one hour 00193 */ 00194 if (string[8] == '-') 00195 --string[9]; 00196 else 00197 ++string[9]; 00198 00199 if (string[9] == 0) 00200 string[8] = '+'; 00201 } 00202 #endif 00203 00204 return string; 00205 } 00206 #endif /* NETSNMP_FEATURE_REMOVE_DATE_N_TIME */ 00207 00208 #ifndef NETSNMP_FEATURE_REMOVE_CTIME_TO_TIMET 00209 time_t 00210 ctime_to_timet(const char *str) 00211 { 00212 struct tm tm; 00213 00214 if (strlen(str) < 24) 00215 return 0; 00216 00217 /* 00218 * Month 00219 */ 00220 if (!strncmp(str + 4, "Jan", 3)) 00221 tm.tm_mon = 0; 00222 else if (!strncmp(str + 4, "Feb", 3)) 00223 tm.tm_mon = 1; 00224 else if (!strncmp(str + 4, "Mar", 3)) 00225 tm.tm_mon = 2; 00226 else if (!strncmp(str + 4, "Apr", 3)) 00227 tm.tm_mon = 3; 00228 else if (!strncmp(str + 4, "May", 3)) 00229 tm.tm_mon = 4; 00230 else if (!strncmp(str + 4, "Jun", 3)) 00231 tm.tm_mon = 5; 00232 else if (!strncmp(str + 4, "Jul", 3)) 00233 tm.tm_mon = 6; 00234 else if (!strncmp(str + 4, "Aug", 3)) 00235 tm.tm_mon = 7; 00236 else if (!strncmp(str + 4, "Sep", 3)) 00237 tm.tm_mon = 8; 00238 else if (!strncmp(str + 4, "Oct", 3)) 00239 tm.tm_mon = 9; 00240 else if (!strncmp(str + 4, "Nov", 3)) 00241 tm.tm_mon = 10; 00242 else if (!strncmp(str + 4, "Dec", 3)) 00243 tm.tm_mon = 11; 00244 else 00245 return 0; 00246 00247 tm.tm_mday = atoi(str + 8); 00248 tm.tm_hour = atoi(str + 11); 00249 tm.tm_min = atoi(str + 14); 00250 tm.tm_sec = atoi(str + 17); 00251 tm.tm_year = atoi(str + 20) - 1900; 00252 00253 /* 00254 * Cope with timezone and DST 00255 */ 00256 00257 #ifdef SYSV 00258 if (daylight) 00259 tm.tm_isdst = 1; 00260 00261 tm.tm_sec -= timezone; 00262 #endif 00263 00264 return (mktime(&tm)); 00265 } 00266 #endif /* NETSNMP_FEATURE_REMOVE_CTIME_TO_TIMET */ 00267 00268 /* 00269 * blatantly lifted from opensnmp 00270 */ 00271 char 00272 check_rowstatus_transition(int oldValue, int newValue) 00273 { 00274 /* 00275 * From the SNMPv2-TC MIB: 00276 * STATE 00277 * +--------------+-----------+-------------+------------- 00278 * | A | B | C | D 00279 * | |status col.|status column| 00280 * |status column | is | is |status column 00281 * ACTION |does not exist| notReady | notInService| is active 00282 * --------------+--------------+-----------+-------------+------------- 00283 * set status |noError ->D|inconsist- |inconsistent-|inconsistent- 00284 * column to | or | entValue| Value| Value 00285 * createAndGo |inconsistent- | | | 00286 * | Value| | | 00287 * --------------+--------------+-----------+-------------+------------- 00288 * set status |noError see 1|inconsist- |inconsistent-|inconsistent- 00289 * column to | or | entValue| Value| Value 00290 * createAndWait |wrongValue | | | 00291 * --------------+--------------+-----------+-------------+------------- 00292 * set status |inconsistent- |inconsist- |noError |noError 00293 * column to | Value| entValue| | 00294 * active | | | | 00295 * | | or | | 00296 * | | | | 00297 * | |see 2 ->D|see 8 ->D| ->D 00298 * --------------+--------------+-----------+-------------+------------- 00299 * set status |inconsistent- |inconsist- |noError |noError ->C 00300 * column to | Value| entValue| | 00301 * notInService | | | | 00302 * | | or | | or 00303 * | | | | 00304 * | |see 3 ->C| ->C|see 6 00305 * --------------+--------------+-----------+-------------+------------- 00306 * set status |noError |noError |noError |noError ->A 00307 * column to | | | | or 00308 * destroy | ->A| ->A| ->A|see 7 00309 * --------------+--------------+-----------+-------------+------------- 00310 * set any other |see 4 |noError |noError |see 5 00311 * column to some| | | | 00312 * value | | see 1| ->C| ->D 00313 * --------------+--------------+-----------+-------------+------------- 00314 00315 * (1) goto B or C, depending on information available to the 00316 * agent. 00317 00318 * (2) if other variable bindings included in the same PDU, 00319 * provide values for all columns which are missing but 00320 * required, and all columns have acceptable values, then 00321 * return noError and goto D. 00322 00323 * (3) if other variable bindings included in the same PDU, 00324 * provide legal values for all columns which are missing but 00325 * required, then return noError and goto C. 00326 00327 * (4) at the discretion of the agent, the return value may be 00328 * either: 00329 00330 * inconsistentName: because the agent does not choose to 00331 * create such an instance when the corresponding 00332 * RowStatus instance does not exist, or 00333 00334 * inconsistentValue: if the supplied value is 00335 * inconsistent with the state of some other MIB object's 00336 * value, or 00337 00338 * noError: because the agent chooses to create the 00339 * instance. 00340 00341 * If noError is returned, then the instance of the status 00342 * column must also be created, and the new state is B or C, 00343 * depending on the information available to the agent. If 00344 * inconsistentName or inconsistentValue is returned, the row 00345 * remains in state A. 00346 00347 * (5) depending on the MIB definition for the column/table, 00348 * either noError or inconsistentValue may be returned. 00349 00350 * (6) the return value can indicate one of the following 00351 * errors: 00352 00353 * wrongValue: because the agent does not support 00354 * notInService (e.g., an agent which does not support 00355 * createAndWait), or 00356 00357 * inconsistentValue: because the agent is unable to take 00358 * the row out of service at this time, perhaps because it 00359 * is in use and cannot be de-activated. 00360 00361 * (7) the return value can indicate the following error: 00362 00363 * inconsistentValue: because the agent is unable to 00364 * remove the row at this time, perhaps because it is in 00365 * use and cannot be de-activated. 00366 00367 * (8) the transition to D can fail, e.g., if the values of the 00368 * conceptual row are inconsistent, then the error code would 00369 * be inconsistentValue. 00370 00371 * NOTE: Other processing of (this and other varbinds of) the 00372 * set request may result in a response other than noError 00373 * being returned, e.g., wrongValue, noCreation, etc. 00374 */ 00375 00376 switch (newValue) { 00377 /* 00378 * these two end up being equivelent as far as checking the 00379 * status goes, although the final states are based on the 00380 * newValue. 00381 */ 00382 case RS_ACTIVE: 00383 case RS_NOTINSERVICE: 00384 if (oldValue == RS_NOTINSERVICE || oldValue == RS_ACTIVE) 00385 ; 00386 else 00387 return SNMP_ERR_INCONSISTENTVALUE; 00388 break; 00389 00390 case RS_NOTREADY: 00391 /* 00392 * Illegal set value. 00393 */ 00394 return SNMP_ERR_WRONGVALUE; 00395 break; 00396 00397 case RS_CREATEANDGO: 00398 case RS_CREATEANDWAIT: 00399 if (oldValue != RS_NONEXISTENT) 00400 /* 00401 * impossible, we already exist. 00402 */ 00403 return SNMP_ERR_INCONSISTENTVALUE; 00404 break; 00405 00406 case RS_DESTROY: 00407 break; 00408 00409 default: 00410 return SNMP_ERR_WRONGVALUE; 00411 break; 00412 } 00413 00414 return SNMP_ERR_NOERROR; 00415 } 00416 00417 #ifndef NETSNMP_FEATURE_REMOVE_CHECK_ROWSTATUS_WITH_STORAGETYPE_TRANSITION 00418 char 00419 check_rowstatus_with_storagetype_transition(int oldValue, int newValue, 00420 int oldStorage) 00421 { 00422 /* 00423 * can not destroy permanent or readonly rows 00424 */ 00425 if ((RS_DESTROY == newValue) && 00426 ((SNMP_STORAGE_PERMANENT == oldStorage) || 00427 (SNMP_STORAGE_READONLY == oldStorage))) 00428 return SNMP_ERR_WRONGVALUE; 00429 00430 return check_rowstatus_transition(oldValue, newValue); 00431 } 00432 #endif /* NETSNMP_FEATURE_REMOVE_CHECK_ROWSTATUS_WITH_STORAGETYPE_TRANSITION */ 00433 00434 netsnmp_feature_child_of(check_storage_transition, snmp_tc_all) 00435 #ifndef NETSNMP_FEATURE_REMOVE_CHECK_STORAGE_TRANSITION 00436 char 00437 check_storage_transition(int oldValue, int newValue) 00438 { 00439 /* 00440 * From the SNMPv2-TC MIB: 00441 00442 * "Describes the memory realization of a conceptual row. A 00443 * row which is volatile(2) is lost upon reboot. A row which 00444 * is either nonVolatile(3), permanent(4) or readOnly(5), is 00445 * backed up by stable storage. A row which is permanent(4) 00446 * can be changed but not deleted. A row which is readOnly(5) 00447 * cannot be changed nor deleted. 00448 00449 * If the value of an object with this syntax is either 00450 * permanent(4) or readOnly(5), it cannot be written. 00451 * Conversely, if the value is either other(1), volatile(2) or 00452 * nonVolatile(3), it cannot be modified to be permanent(4) or 00453 * readOnly(5). (All illegal modifications result in a 00454 * 'wrongValue' error.) 00455 00456 * Every usage of this textual convention is required to 00457 * specify the columnar objects which a permanent(4) row must 00458 * at a minimum allow to be writable." 00459 */ 00460 switch (oldValue) { 00461 case SNMP_STORAGE_PERMANENT: 00462 case SNMP_STORAGE_READONLY: 00463 return SNMP_ERR_INCONSISTENTVALUE; 00464 00465 case SNMP_STORAGE_NONE: 00466 case SNMP_STORAGE_OTHER: 00467 case SNMP_STORAGE_VOLATILE: 00468 case SNMP_STORAGE_NONVOLATILE: 00469 if (newValue == SNMP_STORAGE_PERMANENT || 00470 newValue == SNMP_STORAGE_READONLY) 00471 return SNMP_ERR_INCONSISTENTVALUE; 00472 } 00473 00474 return SNMP_ERR_NOERROR; 00475 } 00476 #endif /* NETSNMP_FEATURE_REMOVE_CHECK_STORAGE_TRANSITION */