diff options
Diffstat (limited to 'agent/mibgroup/disman/schedule/schedConf.c')
-rw-r--r-- | agent/mibgroup/disman/schedule/schedConf.c | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/agent/mibgroup/disman/schedule/schedConf.c b/agent/mibgroup/disman/schedule/schedConf.c new file mode 100644 index 0000000..2e67b73 --- /dev/null +++ b/agent/mibgroup/disman/schedule/schedConf.c @@ -0,0 +1,427 @@ +/* + * DisMan Schedule MIB: + * Implementation of the schedule MIB config handling + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include <ctype.h> +#include "disman/schedule/schedCore.h" +#include "disman/schedule/schedConf.h" + +static int schedEntries; + +/** Initializes the schedConf module */ +void +init_schedConf(void) +{ + DEBUGMSGTL(("disman:schedule:init", "Initializing config module\n")); + init_schedule_container(); + + /* + * Register public configuration directives + */ + snmpd_register_config_handler("repeat", parse_sched_periodic, NULL, + "repeat period OID = value"); + snmpd_register_config_handler("cron", parse_sched_timed, NULL, + "cron * * * * * OID = value"); + snmpd_register_config_handler("at", parse_sched_timed, NULL, + "at * * * * * OID = value"); + + /* + * Register internal configuration directive, + * and arrange for dynamically configured entries to be saved + */ + snmpd_register_config_handler("_schedTable", parse_schedTable, NULL, NULL); + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, + store_schedTable, NULL); + schedEntries = 0; +} + + +/* ======================================================= + * + * Handlers for user-configured (static) scheduled actions + * + * ======================================================= */ + +void +parse_sched_periodic( const char *token, char *line ) +{ + netsnmp_tdata_row *row; + struct schedTable_entry *entry; + char buf[24]; + long frequency; + long value; + size_t tmpint; + oid variable[ MAX_OID_LEN], *var_ptr = variable; + size_t var_len = MAX_OID_LEN; + + schedEntries++; + sprintf(buf, "_conf%03d", schedEntries); + + DEBUGMSGTL(( "disman:schedule:conf", "periodic: %s %s\n", token, line)); + /* + * Parse the configure directive line + */ + line = read_config_read_data(ASN_INTEGER, line, &frequency, &tmpint); + line = read_config_read_data(ASN_OBJECT_ID, line, &var_ptr, &var_len); + if (var_len == 0) { + config_perror("invalid specification for schedVariable"); + return; + } + /* + * Skip over optional assignment in "var = value" + */ + while (line && isspace(*line)) + line++; + if (line && *line == '=' ) { + line++; + while (line && isspace(*line)) { + line++; + } + } + line = read_config_read_data(ASN_INTEGER, line, &value, &tmpint); + + /* + * Create an entry in the schedTable + */ + row = schedTable_createEntry( "snmpd.conf", buf ); + if (!row || !row->data) { + config_perror("create schedule entry failure"); + return; + } + entry = (struct schedTable_entry *)row->data; + + entry->schedInterval = frequency; + entry->schedValue = value; + entry->schedVariable_len = var_len; + memcpy(entry->schedVariable, variable, var_len*sizeof(oid)); + + entry->schedType = SCHED_TYPE_PERIODIC; + entry->schedStorageType = ST_READONLY; /* or PERMANENT */ + entry->flags = SCHEDULE_FLAG_ENABLED | + SCHEDULE_FLAG_ACTIVE | + SCHEDULE_FLAG_VALID; + entry->session = netsnmp_query_get_default_session(); + sched_nextTime( entry ); +} + + +/* + * Timed-schedule utility: + * Convert from a cron-style specification to the equivalent set + * of bits. Note that minute, hour and weekday crontab fields are + * 0-based, while day and month more naturally start from 1. + */ +void +_sched_convert_bits( char *cron_spec, char *bit_buf, + int bit_buf_len, int max_val, int startAt1 ) { + char *cp = cron_spec; + char b[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + int val, major, minor; + int overshoot; + + if (!cron_spec || !bit_buf) + return; + + /* + * Wildcard field - set all bits + */ + if ( *cp == '*' ) { + memset( bit_buf, 0xff, bit_buf_len ); + + /* + * An "all-bits" specification may not be an exact multiple of 8. + * Work out how far we've overshot things, and tidy up the excess. + */ + overshoot = 8*bit_buf_len-max_val; + while ( overshoot > 0 ) { + bit_buf[ bit_buf_len-1 ] ^= b[8-overshoot]; + overshoot--; + } + return; + } + + /* + * Otherwise, clear the bit string buffer, + * and start calculating which bits to set + */ + memset( bit_buf, 0, bit_buf_len ); + + while (1) { + sscanf( cp, "%d", &val); + /* Handle negative day specification */ + if ( val < 0 ) { + val = max_val - val; + } + if ( startAt1 ) + val--; + major = val/8; + minor = val%8; + bit_buf[ major ] |= b[minor]; + + /* XXX - ideally we should handle "X-Y" syntax as well */ + while (*cp && *cp!=',') + cp++; + if (!*cp) + break; + cp++; + } +} + +void +parse_sched_timed( const char *token, char *line ) +{ + netsnmp_tdata_row *row; + struct schedTable_entry *entry; + char buf[24], *cp; + + char minConf[512]; size_t min_len = sizeof(minConf); char minVal[8]; + char hourConf[512]; size_t hour_len = sizeof(hourConf); char hourVal[3]; + char dateConf[512]; size_t date_len = sizeof(dateConf); char dateVal[8]; + char monConf[512]; size_t mon_len = sizeof(monConf); char monVal[2]; + char dayConf[512]; size_t day_len = sizeof(dayConf); char dayVal; + + long value; + size_t tmpint; + oid variable[ MAX_OID_LEN], *var_ptr = variable; + size_t var_len = MAX_OID_LEN; + + schedEntries++; + sprintf(buf, "_conf%03d", schedEntries); + + DEBUGMSGTL(( "sched", "config: %s %s\n", token, line)); + /* + * Parse the configure directive line + */ + cp = minConf; + line = read_config_read_data(ASN_OCTET_STR, line, &cp, &min_len); + cp = hourConf; + line = read_config_read_data(ASN_OCTET_STR, line, &cp, &hour_len); + cp = dateConf; + line = read_config_read_data(ASN_OCTET_STR, line, &cp, &date_len); + cp = monConf; + line = read_config_read_data(ASN_OCTET_STR, line, &cp, &mon_len); + cp = dayConf; + line = read_config_read_data(ASN_OCTET_STR, line, &cp, &day_len); + if (!line) { + config_perror("invalid schedule time specification"); + return; + } + + line = read_config_read_data(ASN_OBJECT_ID, line, &var_ptr, &var_len); + if (var_len == 0) { + config_perror("invalid specification for schedVariable"); + return; + } + /* + * Skip over optional assignment in "var = value" + */ + while (line && isspace(*line)) + line++; + if ( *line == '=' ) { + line++; + while (line && isspace(*line)) { + line++; + } + } + line = read_config_read_data(ASN_INTEGER, line, &value, &tmpint); + + /* + * Convert from cron-style specifications into bits + */ + _sched_convert_bits( minConf, minVal, 8, 60, 0 ); + _sched_convert_bits( hourConf, hourVal, 3, 24, 0 ); + memset(dateVal+4, 0, 4); /* Clear the reverse day bits */ + _sched_convert_bits( dateConf, dateVal, 4, 31, 1 ); + _sched_convert_bits( monConf, monVal, 2, 12, 1 ); + _sched_convert_bits( dayConf, &dayVal, 1, 8, 0 ); + if ( dayVal & 0x01 ) { /* sunday(7) = sunday(0) */ + dayVal |= 0x80; + dayVal &= 0xfe; + } + + /* + * Create an entry in the schedTable + */ + row = schedTable_createEntry("snmpd.conf", buf); + if (!row || !row->data) { + config_perror("create schedule entry failure"); + return; + } + entry = (struct schedTable_entry *)row->data; + + entry->schedWeekDay = dayVal; + memcpy(entry->schedMonth, monVal, 2); + memcpy(entry->schedDay, dateVal, 4+4); + memcpy(entry->schedHour, hourVal, 3); + memcpy(entry->schedMinute, minVal, 8); + + memcpy(entry->schedVariable, variable, var_len*sizeof(oid)); + entry->schedVariable_len = var_len; + entry->schedValue = value; + + if ( !strcmp( token, "at" )) + entry->schedType = SCHED_TYPE_ONESHOT; + else + entry->schedType = SCHED_TYPE_CALENDAR; + entry->schedStorageType = ST_READONLY; /* or PERMANENT */ + entry->flags = SCHEDULE_FLAG_ENABLED | + SCHEDULE_FLAG_ACTIVE | + SCHEDULE_FLAG_VALID; + entry->session = netsnmp_query_get_default_session(); + sched_nextTime( entry ); +} + + +/* ======================================== + * + * Handlers for persistent schedule entries + * + * ======================================== */ + +void +parse_schedTable( const char *token, char *line ) +{ + char owner[SCHED_STR1_LEN+1]; + char name[ SCHED_STR1_LEN+1]; + char time_bits[22]; /* schedWeekDay..schedMinute */ + void *vp; + size_t len; + netsnmp_tdata_row *row; + struct schedTable_entry *entry; + + DEBUGMSGTL(("disman:schedule:conf", "Parsing schedTable config... ")); + + /* + * Read in the index information for this entry + * and create a (non-fixed) data structure for it. + */ + memset( owner, 0, sizeof(owner)); + memset( name, 0, sizeof(name)); + len = SCHED_STR1_LEN; vp = owner; + line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len); + len = SCHED_STR1_LEN; vp = name; + line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len); + row = schedTable_createEntry(owner, name); + if (!row || !row->data) { + config_perror("create schedule entry failure"); + return; + } + entry = (struct schedTable_entry *)row->data; + DEBUGMSG(("disman:schedule:conf", "(%s, %s) ", owner, name)); + + /* + * Read in the column values. + */ + len = SCHED_STR2_LEN; vp = entry->schedDescr; + line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len); + line = read_config_read_data(ASN_UNSIGNED, line, + &entry->schedInterval, NULL); + /* Unpick the various timed bits */ + len = 22; vp = time_bits; + line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len); + entry->schedWeekDay = time_bits[0]; + entry->schedMonth[0] = time_bits[1]; + entry->schedMonth[1] = time_bits[2]; + entry->schedHour[0] = time_bits[11]; + entry->schedHour[1] = time_bits[12]; + entry->schedHour[2] = time_bits[13]; + memcpy(entry->schedDay, time_bits+3, 8); + memcpy(entry->schedMinute, time_bits+14, 8); + + len = SCHED_STR1_LEN; vp = entry->schedContextName; + line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len); + len = MAX_OID_LEN; vp = entry->schedVariable; + line = read_config_read_data(ASN_OBJECT_ID, line, &vp, &len); + entry->schedVariable_len = len; + line = read_config_read_data(ASN_INTEGER, line, + &entry->schedValue, NULL); + line = read_config_read_data(ASN_UNSIGNED, line, + &entry->schedType, NULL); + line = read_config_read_data(ASN_UNSIGNED, line, &len, NULL); + entry->flags |= (len /* & WHAT ?? */); + /* XXX - Will need to read in the 'iquery' access information */ + entry->flags |= SCHEDULE_FLAG_VALID; + + DEBUGMSG(("disman:schedule:conf", "\n")); +} + +/* + * Save dynamically-configured schedTable entries into persistent storage + */ +int +store_schedTable(int majorID, int minorID, void *serverarg, void *clientarg) +{ + char line[SNMP_MAXBUF]; + char time_bits[22]; /* schedWeekDay..schedMinute */ + char *cptr; + void *vp; + size_t tint; + netsnmp_tdata_row *row; + struct schedTable_entry *entry; + + + DEBUGMSGTL(( "disman:schedule:conf", "Storing schedTable:\n")); + + for (row = netsnmp_tdata_row_first( schedule_table ); + row; + row = netsnmp_tdata_row_next( schedule_table, row )) { + + if (!row->data) + continue; + entry = (struct schedTable_entry *)row->data; + + /* + * Only save (dynamically-created) 'nonVolatile' entries + * (XXX - what about dynamic 'permanent' entries ??) + */ + if (entry->schedStorageType != ST_NONVOLATILE ) + continue; + DEBUGMSGTL(( "disman:schedule:conf", " Storing (%s, %s)\n", + entry->schedOwner, entry->schedName)); + + memset(line, 0, sizeof(line)); + strcpy(line, "_schedTable "); + cptr = line + strlen(line); + + vp = entry->schedOwner; tint = strlen( vp ); + cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint ); + vp = entry->schedName; tint = strlen( vp ); + cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint ); + vp = entry->schedDescr; tint = strlen( vp ); + cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint ); + tint = entry->schedInterval; + cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL ); + + /* Combine all the timed bits into a single field */ + time_bits[0] = entry->schedWeekDay; + time_bits[1] = entry->schedMonth[0]; + time_bits[2] = entry->schedMonth[1]; + time_bits[11] = entry->schedHour[0]; + time_bits[12] = entry->schedHour[1]; + time_bits[13] = entry->schedHour[2]; + memcpy(time_bits+3, entry->schedDay, 8); + memcpy(time_bits+14, entry->schedMinute, 8); + vp = time_bits; tint = 22; + cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint ); + + vp = entry->schedContextName; tint = strlen( vp ); + cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint ); + vp = entry->schedVariable; + tint = entry->schedVariable_len; + cptr = read_config_store_data(ASN_OBJECT_ID, cptr, &vp, &tint ); + tint = entry->schedValue; + cptr = read_config_store_data(ASN_INTEGER, cptr, &tint, NULL ); + tint = entry->schedType; + cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL ); + tint = entry->flags /* & WHAT ?? */; + cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL ); + /* XXX - Need to store the 'iquery' access information */ + snmpd_store_config(line); + } + DEBUGMSGTL(( "disman:schedule:conf", " done.\n")); + return SNMPERR_SUCCESS; +} |