1 #include <net-snmp/net-snmp-config.h>
2 #if HAVE_STDLIB_H
3 #include <stdlib.h>
4 #endif
5 #if HAVE_STRING_H
6 #include <string.h>
7 #else
8 #include <strings.h>
9 #endif
10 #include <stddef.h>
11 
12 #include <net-snmp/net-snmp-includes.h>
13 #include <net-snmp/agent/net-snmp-agent-includes.h>
14 #include <net-snmp/agent/agent_callbacks.h>
15 #include <net-snmp/agent/agent_sysORTable.h>
16 #include <net-snmp/agent/sysORTable.h>
17 
18 typedef struct data_node_s {
19     struct sysORTable data;
20     struct data_node_s* next;
21     struct data_node_s* prev;
22 }* data_node;
23 
24 static data_node table = NULL;
25 
26 static void
erase(data_node entry)27 erase(data_node entry)
28 {
29     entry->data.OR_uptime = netsnmp_get_agent_uptime();
30     DEBUGMSGTL(("agent/sysORTable", "UNREG_SYSOR %p\n", &entry->data));
31     snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR,
32                         &entry->data);
33     free(entry->data.OR_oid);
34     free(entry->data.OR_descr);
35     if (entry->next == entry)
36         table = NULL;
37     else {
38         entry->next->prev = entry->prev;
39         entry->prev->next = entry->next;
40         if (entry == table)
41             table = entry->next;
42     }
43     free(entry);
44 }
45 
46 void
netsnmp_sysORTable_foreach(void (* f)(const struct sysORTable *,void *),void * c)47 netsnmp_sysORTable_foreach(void (*f)(const struct sysORTable*, void*), void* c)
48 {
49     DEBUGMSGTL(("agent/sysORTable", "foreach(%p, %p)\n", f, c));
50     if(table) {
51         data_node run = table;
52         do {
53             data_node tmp = run;
54             run = run->next;
55             f(&tmp->data, c);
56         } while(table && run != table);
57     }
58 }
59 
60 int
register_sysORTable_sess(oid * oidin,size_t oidlen,const char * descr,netsnmp_session * ss)61 register_sysORTable_sess(oid * oidin,
62                          size_t oidlen,
63                          const char *descr, netsnmp_session * ss)
64 {
65     data_node entry;
66 
67     DEBUGMSGTL(("agent/sysORTable", "registering: "));
68     DEBUGMSGOID(("agent/sysORTable", oidin, oidlen));
69     DEBUGMSG(("agent/sysORTable", ", session %p\n", ss));
70 
71     entry = (data_node)calloc(1, sizeof(struct data_node_s));
72     if (entry == NULL) {
73         DEBUGMSGTL(("agent/sysORTable", "Failed to allocate new entry\n"));
74         return SYS_ORTABLE_REGISTRATION_FAILED;
75     }
76 
77     entry->data.OR_descr = strdup(descr);
78     if (entry->data.OR_descr == NULL) {
79         DEBUGMSGTL(("agent/sysORTable", "Failed to allocate new sysORDescr\n"));
80         free(entry);
81         return SYS_ORTABLE_REGISTRATION_FAILED;
82     }
83 
84     entry->data.OR_oid = (oid *) malloc(sizeof(oid) * oidlen);
85     if (entry->data.OR_oid == NULL) {
86         DEBUGMSGTL(("agent/sysORTable", "Failed to allocate new sysORID\n"));
87         free(entry->data.OR_descr);
88         free(entry);
89         return SYS_ORTABLE_REGISTRATION_FAILED;
90     }
91 
92     memcpy(entry->data.OR_oid, oidin, sizeof(oid) * oidlen);
93     entry->data.OR_oidlen = oidlen;
94     entry->data.OR_sess = ss;
95 
96     if(table) {
97         entry->next = table;
98         entry->prev = table->prev;
99         table->prev->next = entry;
100         table->prev = entry;
101     } else
102         table = entry->next = entry->prev = entry;
103 
104     entry->data.OR_uptime = netsnmp_get_agent_uptime();
105 
106     snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
107                         SNMPD_CALLBACK_REG_SYSOR, &entry->data);
108 
109     return SYS_ORTABLE_REGISTERED_OK;
110 }
111 
112 int
register_sysORTable(oid * oidin,size_t oidlen,const char * descr)113 register_sysORTable(oid * oidin, size_t oidlen, const char *descr)
114 {
115     return register_sysORTable_sess(oidin, oidlen, descr, NULL);
116 }
117 
118 int
unregister_sysORTable_sess(oid * oidin,size_t oidlen,netsnmp_session * ss)119 unregister_sysORTable_sess(oid * oidin,
120                            size_t oidlen, netsnmp_session * ss)
121 {
122     int any_unregistered = 0;
123 
124     DEBUGMSGTL(("agent/sysORTable", "sysORTable unregistering: "));
125     DEBUGMSGOID(("agent/sysORTable", oidin, oidlen));
126     DEBUGMSG(("agent/sysORTable", ", session %p\n", ss));
127 
128     if(table) {
129         data_node run = table;
130         do {
131             data_node tmp = run;
132             run = run->next;
133             if (tmp->data.OR_sess == ss &&
134                 snmp_oid_compare(oidin, oidlen,
135                                  tmp->data.OR_oid, tmp->data.OR_oidlen) == 0) {
136                 erase(tmp);
137                 any_unregistered = 1;
138             }
139         } while(table && run != table);
140     }
141 
142     if (any_unregistered) {
143         DEBUGMSGTL(("agent/sysORTable", "unregistering successfull\n"));
144         return SYS_ORTABLE_UNREGISTERED_OK;
145     } else {
146         DEBUGMSGTL(("agent/sysORTable", "unregistering failed\n"));
147         return SYS_ORTABLE_NO_SUCH_REGISTRATION;
148     }
149 }
150 
151 
152 int
unregister_sysORTable(oid * oidin,size_t oidlen)153 unregister_sysORTable(oid * oidin, size_t oidlen)
154 {
155     return unregister_sysORTable_sess(oidin, oidlen, NULL);
156 }
157 
158 
159 void
unregister_sysORTable_by_session(netsnmp_session * ss)160 unregister_sysORTable_by_session(netsnmp_session * ss)
161 {
162     DEBUGMSGTL(("agent/sysORTable",
163                 "sysORTable unregistering session %p\n", ss));
164 
165    if(table) {
166         data_node run = table;
167         do {
168             data_node tmp = run;
169             run = run->next;
170             if (((ss->flags & SNMP_FLAGS_SUBSESSION) &&
171                  tmp->data.OR_sess == ss) ||
172                 (!(ss->flags & SNMP_FLAGS_SUBSESSION) && tmp->data.OR_sess &&
173                  tmp->data.OR_sess->subsession == ss))
174                 erase(tmp);
175         } while(table && run != table);
176     }
177 
178     DEBUGMSGTL(("agent/sysORTable",
179                 "sysORTable unregistering session %p done\n", ss));
180 }
181 
182 static int
register_sysOR_callback(int majorID,int minorID,void * serverarg,void * clientarg)183 register_sysOR_callback(int majorID, int minorID, void *serverarg,
184                         void *clientarg)
185 {
186     struct sysORTable *parms = (struct sysORTable *) serverarg;
187 
188     return register_sysORTable_sess(parms->OR_oid, parms->OR_oidlen,
189                                     parms->OR_descr, parms->OR_sess);
190 }
191 
192 static int
unregister_sysOR_by_session_callback(int majorID,int minorID,void * serverarg,void * clientarg)193 unregister_sysOR_by_session_callback(int majorID, int minorID,
194                                      void *serverarg, void *clientarg)
195 {
196     netsnmp_session *session = (netsnmp_session *) serverarg;
197 
198     unregister_sysORTable_by_session(session);
199 
200     return 0;
201 }
202 
203 static int
unregister_sysOR_callback(int majorID,int minorID,void * serverarg,void * clientarg)204 unregister_sysOR_callback(int majorID, int minorID, void *serverarg,
205                           void *clientarg)
206 {
207     struct sysORTable *parms = (struct sysORTable *) serverarg;
208 
209     return unregister_sysORTable_sess(parms->OR_oid,
210                                       parms->OR_oidlen,
211                                       parms->OR_sess);
212 }
213 
214 void
init_agent_sysORTable(void)215 init_agent_sysORTable(void)
216 {
217     DEBUGMSGTL(("agent/sysORTable", "init_agent_sysORTable\n"));
218 
219     snmp_register_callback(SNMP_CALLBACK_APPLICATION,
220                            SNMPD_CALLBACK_REQ_REG_SYSOR,
221                            register_sysOR_callback, NULL);
222     snmp_register_callback(SNMP_CALLBACK_APPLICATION,
223                            SNMPD_CALLBACK_REQ_UNREG_SYSOR,
224                            unregister_sysOR_callback, NULL);
225     snmp_register_callback(SNMP_CALLBACK_APPLICATION,
226                            SNMPD_CALLBACK_REQ_UNREG_SYSOR_SESS,
227                            unregister_sysOR_by_session_callback, NULL);
228 }
229 
230 void
shutdown_agent_sysORTable(void)231 shutdown_agent_sysORTable(void)
232 {
233     DEBUGMSGTL(("agent/sysORTable", "shutdown_sysORTable\n"));
234     while(table)
235         erase(table);
236 }
237