| #include <net-snmp/net-snmp-config.h> |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| #include <stddef.h> |
| |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| #include <net-snmp/agent/agent_callbacks.h> |
| #include <net-snmp/agent/agent_sysORTable.h> |
| #include <net-snmp/agent/sysORTable.h> |
| |
| typedef struct data_node_s { |
| struct sysORTable data; |
| struct data_node_s* next; |
| struct data_node_s* prev; |
| }* data_node; |
| |
| static data_node table = NULL; |
| |
| static void |
| erase(data_node entry) |
| { |
| entry->data.OR_uptime = netsnmp_get_agent_uptime(); |
| DEBUGMSGTL(("agent/sysORTable", "UNREG_SYSOR %p\n", &entry->data)); |
| snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR, |
| &entry->data); |
| free(entry->data.OR_oid); |
| free(entry->data.OR_descr); |
| if (entry->next == entry) |
| table = NULL; |
| else { |
| entry->next->prev = entry->prev; |
| entry->prev->next = entry->next; |
| if (entry == table) |
| table = entry->next; |
| } |
| free(entry); |
| } |
| |
| void |
| netsnmp_sysORTable_foreach(void (*f)(const struct sysORTable*, void*), void* c) |
| { |
| DEBUGMSGTL(("agent/sysORTable", "foreach(%p, %p)\n", f, c)); |
| if(table) { |
| data_node run = table; |
| do { |
| data_node tmp = run; |
| run = run->next; |
| f(&tmp->data, c); |
| } while(table && run != table); |
| } |
| } |
| |
| int |
| register_sysORTable_sess(oid * oidin, |
| size_t oidlen, |
| const char *descr, netsnmp_session * ss) |
| { |
| data_node entry; |
| |
| DEBUGMSGTL(("agent/sysORTable", "registering: ")); |
| DEBUGMSGOID(("agent/sysORTable", oidin, oidlen)); |
| DEBUGMSG(("agent/sysORTable", ", session %p\n", ss)); |
| |
| entry = (data_node)calloc(1, sizeof(struct data_node_s)); |
| if (entry == NULL) { |
| DEBUGMSGTL(("agent/sysORTable", "Failed to allocate new entry\n")); |
| return SYS_ORTABLE_REGISTRATION_FAILED; |
| } |
| |
| entry->data.OR_descr = strdup(descr); |
| if (entry->data.OR_descr == NULL) { |
| DEBUGMSGTL(("agent/sysORTable", "Failed to allocate new sysORDescr\n")); |
| free(entry); |
| return SYS_ORTABLE_REGISTRATION_FAILED; |
| } |
| |
| entry->data.OR_oid = (oid *) malloc(sizeof(oid) * oidlen); |
| if (entry->data.OR_oid == NULL) { |
| DEBUGMSGTL(("agent/sysORTable", "Failed to allocate new sysORID\n")); |
| free(entry->data.OR_descr); |
| free(entry); |
| return SYS_ORTABLE_REGISTRATION_FAILED; |
| } |
| |
| memcpy(entry->data.OR_oid, oidin, sizeof(oid) * oidlen); |
| entry->data.OR_oidlen = oidlen; |
| entry->data.OR_sess = ss; |
| |
| if(table) { |
| entry->next = table; |
| entry->prev = table->prev; |
| table->prev->next = entry; |
| table->prev = entry; |
| } else |
| table = entry->next = entry->prev = entry; |
| |
| entry->data.OR_uptime = netsnmp_get_agent_uptime(); |
| |
| snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, |
| SNMPD_CALLBACK_REG_SYSOR, &entry->data); |
| |
| return SYS_ORTABLE_REGISTERED_OK; |
| } |
| |
| int |
| register_sysORTable(oid * oidin, size_t oidlen, const char *descr) |
| { |
| return register_sysORTable_sess(oidin, oidlen, descr, NULL); |
| } |
| |
| int |
| unregister_sysORTable_sess(oid * oidin, |
| size_t oidlen, netsnmp_session * ss) |
| { |
| int any_unregistered = 0; |
| |
| DEBUGMSGTL(("agent/sysORTable", "sysORTable unregistering: ")); |
| DEBUGMSGOID(("agent/sysORTable", oidin, oidlen)); |
| DEBUGMSG(("agent/sysORTable", ", session %p\n", ss)); |
| |
| if(table) { |
| data_node run = table; |
| do { |
| data_node tmp = run; |
| run = run->next; |
| if (tmp->data.OR_sess == ss && |
| snmp_oid_compare(oidin, oidlen, |
| tmp->data.OR_oid, tmp->data.OR_oidlen) == 0) { |
| erase(tmp); |
| any_unregistered = 1; |
| } |
| } while(table && run != table); |
| } |
| |
| if (any_unregistered) { |
| DEBUGMSGTL(("agent/sysORTable", "unregistering successfull\n")); |
| return SYS_ORTABLE_UNREGISTERED_OK; |
| } else { |
| DEBUGMSGTL(("agent/sysORTable", "unregistering failed\n")); |
| return SYS_ORTABLE_NO_SUCH_REGISTRATION; |
| } |
| } |
| |
| |
| int |
| unregister_sysORTable(oid * oidin, size_t oidlen) |
| { |
| return unregister_sysORTable_sess(oidin, oidlen, NULL); |
| } |
| |
| |
| void |
| unregister_sysORTable_by_session(netsnmp_session * ss) |
| { |
| DEBUGMSGTL(("agent/sysORTable", |
| "sysORTable unregistering session %p\n", ss)); |
| |
| if(table) { |
| data_node run = table; |
| do { |
| data_node tmp = run; |
| run = run->next; |
| if (((ss->flags & SNMP_FLAGS_SUBSESSION) && |
| tmp->data.OR_sess == ss) || |
| (!(ss->flags & SNMP_FLAGS_SUBSESSION) && tmp->data.OR_sess && |
| tmp->data.OR_sess->subsession == ss)) |
| erase(tmp); |
| } while(table && run != table); |
| } |
| |
| DEBUGMSGTL(("agent/sysORTable", |
| "sysORTable unregistering session %p done\n", ss)); |
| } |
| |
| static int |
| register_sysOR_callback(int majorID, int minorID, void *serverarg, |
| void *clientarg) |
| { |
| struct sysORTable *parms = (struct sysORTable *) serverarg; |
| |
| return register_sysORTable_sess(parms->OR_oid, parms->OR_oidlen, |
| parms->OR_descr, parms->OR_sess); |
| } |
| |
| static int |
| unregister_sysOR_by_session_callback(int majorID, int minorID, |
| void *serverarg, void *clientarg) |
| { |
| netsnmp_session *session = (netsnmp_session *) serverarg; |
| |
| unregister_sysORTable_by_session(session); |
| |
| return 0; |
| } |
| |
| static int |
| unregister_sysOR_callback(int majorID, int minorID, void *serverarg, |
| void *clientarg) |
| { |
| struct sysORTable *parms = (struct sysORTable *) serverarg; |
| |
| return unregister_sysORTable_sess(parms->OR_oid, |
| parms->OR_oidlen, |
| parms->OR_sess); |
| } |
| |
| void |
| init_agent_sysORTable(void) |
| { |
| DEBUGMSGTL(("agent/sysORTable", "init_agent_sysORTable\n")); |
| |
| snmp_register_callback(SNMP_CALLBACK_APPLICATION, |
| SNMPD_CALLBACK_REQ_REG_SYSOR, |
| register_sysOR_callback, NULL); |
| snmp_register_callback(SNMP_CALLBACK_APPLICATION, |
| SNMPD_CALLBACK_REQ_UNREG_SYSOR, |
| unregister_sysOR_callback, NULL); |
| snmp_register_callback(SNMP_CALLBACK_APPLICATION, |
| SNMPD_CALLBACK_REQ_UNREG_SYSOR_SESS, |
| unregister_sysOR_by_session_callback, NULL); |
| } |
| |
| void |
| shutdown_agent_sysORTable(void) |
| { |
| DEBUGMSGTL(("agent/sysORTable", "shutdown_sysORTable\n")); |
| while(table) |
| erase(table); |
| } |