| /* |
| * DisMan Schedule MIB: |
| * Core implementation of the schedTable MIB interface. |
| * See 'schedCore.c' for active behaviour of this table. |
| * |
| * (based on mib2c.table_data.conf output) |
| */ |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| #include "utilities/iquery.h" |
| #include "disman/schedule/schedCore.h" |
| #include "disman/schedule/schedTable.h" |
| |
| /** Initializes the schedTable module */ |
| void |
| init_schedTable(void) |
| { |
| static oid schedTable_oid[] = { 1, 3, 6, 1, 2, 1, 63, 1, 2 }; |
| size_t schedTable_oid_len = OID_LENGTH(schedTable_oid); |
| netsnmp_handler_registration *reg; |
| netsnmp_table_registration_info *table_info; |
| |
| DEBUGMSGTL(("disman:schedule:init", "Initializing table\n")); |
| /* |
| * Ensure the schedule table container is available... |
| */ |
| init_schedule_container(); |
| |
| /* |
| * ... then set up the MIB interface. |
| */ |
| reg = netsnmp_create_handler_registration("schedTable", |
| schedTable_handler, |
| schedTable_oid, |
| schedTable_oid_len, |
| HANDLER_CAN_RWRITE); |
| |
| table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); |
| netsnmp_table_helper_add_indexes(table_info, |
| ASN_OCTET_STR, /* index: schedOwner */ |
| ASN_OCTET_STR, /* index: schedName */ |
| 0); |
| table_info->min_column = COLUMN_SCHEDDESCR; |
| table_info->max_column = COLUMN_SCHEDTRIGGERS; |
| |
| netsnmp_tdata_register(reg, schedule_table, table_info); |
| } |
| |
| |
| /** handles requests for the schedTable table */ |
| int |
| schedTable_handler(netsnmp_mib_handler *handler, |
| netsnmp_handler_registration *reginfo, |
| netsnmp_agent_request_info *reqinfo, |
| netsnmp_request_info *requests) |
| { |
| |
| netsnmp_request_info *request; |
| netsnmp_table_request_info *tinfo; |
| netsnmp_tdata_row *row; |
| struct schedTable_entry *entry; |
| int recalculate = 0; |
| size_t len; |
| char *cp; |
| char owner[SCHED_STR1_LEN+1]; |
| char name[ SCHED_STR1_LEN+1]; |
| int ret; |
| |
| DEBUGMSGTL(("disman:schedule:mib", "Schedule handler (%d)\n", |
| reqinfo->mode)); |
| switch (reqinfo->mode) { |
| /* |
| * Read-support (also covers GetNext requests) |
| */ |
| case MODE_GET: |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| entry = (struct schedTable_entry *) |
| netsnmp_tdata_extract_entry(request); |
| tinfo = netsnmp_extract_table_info( request); |
| |
| switch (tinfo->colnum) { |
| case COLUMN_SCHEDDESCR: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->schedDescr, |
| strlen(entry->schedDescr)); |
| break; |
| case COLUMN_SCHEDINTERVAL: |
| snmp_set_var_typed_integer(request->requestvb, ASN_UNSIGNED, |
| entry->schedInterval); |
| break; |
| case COLUMN_SCHEDWEEKDAY: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| &entry->schedWeekDay, |
| sizeof(entry->schedWeekDay)); |
| break; |
| case COLUMN_SCHEDMONTH: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->schedMonth, |
| sizeof(entry->schedMonth)); |
| break; |
| case COLUMN_SCHEDDAY: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->schedDay, |
| sizeof(entry->schedDay)); |
| break; |
| case COLUMN_SCHEDHOUR: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->schedHour, |
| sizeof(entry->schedHour)); |
| break; |
| case COLUMN_SCHEDMINUTE: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->schedMinute, |
| sizeof(entry->schedMinute)); |
| break; |
| case COLUMN_SCHEDCONTEXTNAME: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->schedContextName, |
| strlen(entry->schedContextName)); |
| break; |
| case COLUMN_SCHEDVARIABLE: |
| snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID, |
| (u_char *)entry->schedVariable, |
| entry->schedVariable_len*sizeof(oid)); |
| break; |
| case COLUMN_SCHEDVALUE: |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, |
| entry->schedValue); |
| break; |
| case COLUMN_SCHEDTYPE: |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, |
| entry->schedType); |
| break; |
| case COLUMN_SCHEDADMINSTATUS: |
| ret = (entry->flags & SCHEDULE_FLAG_ENABLED ) ? |
| TV_TRUE : TV_FALSE; |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret); |
| break; |
| case COLUMN_SCHEDOPERSTATUS: |
| ret = (entry->flags & SCHEDULE_FLAG_ENABLED ) ? |
| TV_TRUE : TV_FALSE; |
| /* |
| * Check for one-shot entries that have already fired |
| */ |
| if ((entry->schedType == SCHED_TYPE_ONESHOT) && |
| (entry->schedLastRun != 0 )) |
| ret = 3; /* finished(3) */ |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret); |
| break; |
| case COLUMN_SCHEDFAILURES: |
| snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER, |
| entry->schedFailures); |
| break; |
| case COLUMN_SCHEDLASTFAILURE: |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, |
| entry->schedLastFailure); |
| break; |
| case COLUMN_SCHEDLASTFAILED: |
| /* |
| * Convert 'schedLastFailed' timestamp |
| * into DateAndTime string |
| */ |
| cp = date_n_time( &entry->schedLastFailed, &len ); |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| cp, len); |
| break; |
| case COLUMN_SCHEDSTORAGETYPE: |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, |
| entry->schedStorageType); |
| break; |
| case COLUMN_SCHEDROWSTATUS: |
| ret = (entry->flags & SCHEDULE_FLAG_ACTIVE ) ? |
| TV_TRUE : TV_FALSE; |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret); |
| break; |
| case COLUMN_SCHEDTRIGGERS: |
| snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER, |
| entry->schedTriggers); |
| break; |
| } |
| } |
| break; |
| |
| /* |
| * Write-support |
| */ |
| case MODE_SET_RESERVE1: |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| entry = (struct schedTable_entry *) |
| netsnmp_tdata_extract_entry(request); |
| tinfo = netsnmp_extract_table_info( request); |
| |
| switch (tinfo->colnum) { |
| case COLUMN_SCHEDDESCR: |
| ret = netsnmp_check_vb_type_and_max_size( |
| request->requestvb, ASN_OCTET_STR, SCHED_STR2_LEN); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDINTERVAL: |
| ret = netsnmp_check_vb_uint( request->requestvb ); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDWEEKDAY: |
| ret = netsnmp_check_vb_type_and_size( |
| request->requestvb, ASN_OCTET_STR, 1); |
| /* XXX - check for bit(7) set */ |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDMONTH: |
| ret = netsnmp_check_vb_type_and_size( /* max_size ?? */ |
| request->requestvb, ASN_OCTET_STR, 2); |
| /* XXX - check for bit(12)-bit(15) set */ |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDDAY: |
| ret = netsnmp_check_vb_type_and_size( /* max_size ?? */ |
| request->requestvb, ASN_OCTET_STR, 4+4); |
| /* XXX - check for bit(62) or bit(63) set */ |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDHOUR: |
| ret = netsnmp_check_vb_type_and_size( /* max_size ?? */ |
| request->requestvb, ASN_OCTET_STR, 3); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDMINUTE: |
| ret = netsnmp_check_vb_type_and_size( /* max_size ?? */ |
| request->requestvb, ASN_OCTET_STR, 8); |
| /* XXX - check for bit(60)-bit(63) set */ |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDCONTEXTNAME: |
| ret = netsnmp_check_vb_type_and_max_size( |
| request->requestvb, ASN_OCTET_STR, SCHED_STR1_LEN); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDVARIABLE: |
| ret = netsnmp_check_vb_oid( request->requestvb ); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDVALUE: |
| ret = netsnmp_check_vb_int( request->requestvb ); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDTYPE: |
| ret = netsnmp_check_vb_int_range( request->requestvb, |
| SCHED_TYPE_PERIODIC, SCHED_TYPE_ONESHOT ); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDADMINSTATUS: |
| ret = netsnmp_check_vb_truthvalue( request->requestvb ); |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, |
| SNMP_ERR_WRONGTYPE); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDSTORAGETYPE: |
| ret = netsnmp_check_vb_int_range( request->requestvb, |
| ST_NONE, ST_READONLY ); |
| /* XXX - check valid/consistent assignments */ |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| case COLUMN_SCHEDROWSTATUS: |
| ret = netsnmp_check_vb_rowstatus( request->requestvb, |
| (entry ? RS_ACTIVE: RS_NONEXISTENT)); |
| /* XXX - check consistency assignments */ |
| if (ret != SNMP_ERR_NOERROR) { |
| netsnmp_set_request_error(reqinfo, request, ret); |
| return SNMP_ERR_NOERROR; |
| } |
| break; |
| default: |
| netsnmp_set_request_error(reqinfo, request, |
| SNMP_ERR_NOTWRITABLE); |
| return SNMP_ERR_NOERROR; |
| } |
| } |
| break; |
| |
| case MODE_SET_RESERVE2: |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| tinfo = netsnmp_extract_table_info(request); |
| |
| switch (tinfo->colnum) { |
| case COLUMN_SCHEDROWSTATUS: |
| switch (*request->requestvb->val.integer) { |
| case RS_CREATEANDGO: |
| case RS_CREATEANDWAIT: |
| /* |
| * Create an (empty) new row structure |
| */ |
| memset(owner, 0, SCHED_STR1_LEN+1); |
| memset(name, 0, SCHED_STR1_LEN+1); |
| memcpy(owner, tinfo->indexes->val.string, |
| tinfo->indexes->val_len); |
| memcpy(name, tinfo->indexes->next_variable->val.string, |
| tinfo->indexes->next_variable->val_len); |
| row = schedTable_createEntry(owner, name); |
| if (!row) { |
| netsnmp_set_request_error(reqinfo, request, |
| SNMP_ERR_RESOURCEUNAVAILABLE); |
| return SNMP_ERR_NOERROR; |
| } |
| netsnmp_insert_tdata_row(request, row); |
| } |
| } |
| } |
| break; |
| |
| case MODE_SET_FREE: |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| tinfo = netsnmp_extract_table_info(request); |
| |
| switch (tinfo->colnum) { |
| case COLUMN_SCHEDROWSTATUS: |
| switch (*request->requestvb->val.integer) { |
| case RS_CREATEANDGO: |
| case RS_CREATEANDWAIT: |
| /* |
| * Tidy up after a failed row creation request |
| */ |
| entry = (struct schedTable_entry *) |
| netsnmp_tdata_extract_entry(request); |
| if (entry && |
| !(entry->flags & SCHEDULE_FLAG_VALID)) { |
| row = (netsnmp_tdata_row *) |
| netsnmp_tdata_extract_row(request); |
| schedTable_removeEntry(row); |
| } |
| } |
| } |
| } |
| break; |
| |
| case MODE_SET_ACTION: |
| for (request = requests; request; request = request->next) { |
| entry = (struct schedTable_entry *) |
| netsnmp_tdata_extract_entry(request); |
| if (!entry) { |
| /* |
| * New rows must be created via the RowStatus column |
| */ |
| netsnmp_set_request_error(reqinfo, request, |
| SNMP_ERR_NOCREATION); |
| /* or inconsistentName? */ |
| return SNMP_ERR_NOERROR; |
| } |
| } |
| break; |
| |
| case MODE_SET_UNDO: |
| break; |
| |
| case MODE_SET_COMMIT: |
| /* |
| * All these assignments are "unfailable", so it's |
| * (reasonably) safe to apply them in the Commit phase |
| */ |
| entry = NULL; |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| entry = (struct schedTable_entry *) |
| netsnmp_tdata_extract_entry(request); |
| tinfo = netsnmp_extract_table_info( request); |
| |
| switch (tinfo->colnum) { |
| case COLUMN_SCHEDDESCR: |
| memset(entry->schedDescr, 0, sizeof(entry->schedDescr)); |
| memcpy(entry->schedDescr, request->requestvb->val.string, |
| request->requestvb->val_len); |
| break; |
| case COLUMN_SCHEDINTERVAL: |
| entry->schedInterval = *request->requestvb->val.integer; |
| recalculate = 1; |
| break; |
| case COLUMN_SCHEDWEEKDAY: |
| entry->schedWeekDay = request->requestvb->val.string[0]; |
| recalculate = 1; |
| break; |
| case COLUMN_SCHEDMONTH: |
| entry->schedMonth[0] = request->requestvb->val.string[0]; |
| entry->schedMonth[1] = request->requestvb->val.string[1]; |
| recalculate = 1; |
| break; |
| case COLUMN_SCHEDDAY: |
| memset(entry->schedDay, 0, sizeof(entry->schedDay)); |
| memcpy(entry->schedDay, request->requestvb->val.string, |
| request->requestvb->val_len); |
| recalculate = 1; |
| break; |
| case COLUMN_SCHEDHOUR: |
| entry->schedHour[0] = request->requestvb->val.string[0]; |
| entry->schedHour[1] = request->requestvb->val.string[1]; |
| entry->schedHour[2] = request->requestvb->val.string[2]; |
| recalculate = 1; |
| break; |
| case COLUMN_SCHEDMINUTE: |
| memset(entry->schedMinute, 0, sizeof(entry->schedMinute)); |
| memcpy(entry->schedMinute, request->requestvb->val.string, |
| request->requestvb->val_len); |
| recalculate = 1; |
| break; |
| case COLUMN_SCHEDCONTEXTNAME: |
| memset(entry->schedContextName, 0, sizeof(entry->schedContextName)); |
| memcpy(entry->schedContextName, |
| request->requestvb->val.string, |
| request->requestvb->val_len); |
| break; |
| case COLUMN_SCHEDVARIABLE: |
| memset(entry->schedVariable, 0, sizeof(entry->schedVariable)); |
| memcpy(entry->schedVariable, |
| request->requestvb->val.string, |
| request->requestvb->val_len); |
| entry->schedVariable_len = |
| request->requestvb->val_len/sizeof(oid); |
| break; |
| case COLUMN_SCHEDVALUE: |
| entry->schedValue = *request->requestvb->val.integer; |
| break; |
| case COLUMN_SCHEDTYPE: |
| entry->schedType = *request->requestvb->val.integer; |
| break; |
| case COLUMN_SCHEDADMINSTATUS: |
| if (*request->requestvb->val.integer == TV_TRUE) |
| entry->flags |= SCHEDULE_FLAG_ENABLED; |
| else |
| entry->flags &= ~SCHEDULE_FLAG_ENABLED; |
| break; |
| case COLUMN_SCHEDSTORAGETYPE: |
| entry->schedStorageType = *request->requestvb->val.integer; |
| break; |
| case COLUMN_SCHEDROWSTATUS: |
| switch (*request->requestvb->val.integer) { |
| case RS_ACTIVE: |
| entry->flags |= SCHEDULE_FLAG_ACTIVE; |
| break; |
| case RS_CREATEANDGO: |
| entry->flags |= SCHEDULE_FLAG_ACTIVE; |
| entry->flags |= SCHEDULE_FLAG_VALID; |
| entry->session = |
| netsnmp_iquery_pdu_session(reqinfo->asp->pdu); |
| break; |
| case RS_CREATEANDWAIT: |
| entry->flags |= SCHEDULE_FLAG_VALID; |
| entry->session = |
| netsnmp_iquery_pdu_session(reqinfo->asp->pdu); |
| break; |
| |
| case RS_DESTROY: |
| row = (netsnmp_tdata_row *) |
| netsnmp_tdata_extract_row(request); |
| schedTable_removeEntry(row); |
| } |
| recalculate = 1; |
| break; |
| } |
| } |
| if (recalculate) { |
| netsnmp_assert(entry); |
| sched_nextTime(entry); |
| } |
| break; |
| } |
| return SNMP_ERR_NOERROR; |
| } |