1 #include <net-snmp/net-snmp-config.h>
2 #include <net-snmp/net-snmp-features.h>
3 
4 #include <sys/types.h>
5 #if HAVE_NETINET_IN_H
6 #include <netinet/in.h>
7 #endif
8 #if HAVE_NETDB_H
9 #include <netdb.h>
10 #endif
11 
12 #include <net-snmp/net-snmp-includes.h>
13 #include <net-snmp/agent/net-snmp-agent-includes.h>
14 
15 #include <net-snmp/agent/ds_agent.h>
16 #include <net-snmp/agent/instance.h>
17 #include <net-snmp/agent/table.h>
18 #include <net-snmp/agent/table_data.h>
19 #include <net-snmp/agent/table_dataset.h>
20 #include "net-snmp/agent/sysORTable.h"
21 #include "notification_log.h"
22 
23 netsnmp_feature_require(register_ulong_instance_context);
24 netsnmp_feature_require(register_read_only_counter32_instance_context);
25 netsnmp_feature_require(delete_table_data_set);
26 netsnmp_feature_require(table_dataset);
27 netsnmp_feature_require(date_n_time);
28 
29 /*
30  * column number definitions for table nlmLogTable
31  */
32 
33 #define COLUMN_NLMLOGINDEX		1
34 #define COLUMN_NLMLOGTIME		2
35 #define COLUMN_NLMLOGDATEANDTIME	3
36 #define COLUMN_NLMLOGENGINEID		4
37 #define COLUMN_NLMLOGENGINETADDRESS	5
38 #define COLUMN_NLMLOGENGINETDOMAIN	6
39 #define COLUMN_NLMLOGCONTEXTENGINEID	7
40 #define COLUMN_NLMLOGCONTEXTNAME	8
41 #define COLUMN_NLMLOGNOTIFICATIONID	9
42 
43 /*
44  * column number definitions for table nlmLogVariableTable
45  */
46 #define COLUMN_NLMLOGVARIABLEINDEX		1
47 #define COLUMN_NLMLOGVARIABLEID			2
48 #define COLUMN_NLMLOGVARIABLEVALUETYPE		3
49 #define COLUMN_NLMLOGVARIABLECOUNTER32VAL	4
50 #define COLUMN_NLMLOGVARIABLEUNSIGNED32VAL	5
51 #define COLUMN_NLMLOGVARIABLETIMETICKSVAL	6
52 #define COLUMN_NLMLOGVARIABLEINTEGER32VAL	7
53 #define COLUMN_NLMLOGVARIABLEOCTETSTRINGVAL	8
54 #define COLUMN_NLMLOGVARIABLEIPADDRESSVAL	9
55 #define COLUMN_NLMLOGVARIABLEOIDVAL		10
56 #define COLUMN_NLMLOGVARIABLECOUNTER64VAL	11
57 #define COLUMN_NLMLOGVARIABLEOPAQUEVAL		12
58 
59 static u_long   num_received = 0;
60 static u_long   num_deleted = 0;
61 
62 static u_long   max_logged = 1000;      /* goes against the mib default of infinite */
63 static u_long   max_age = 1440; /* 1440 = 24 hours, which is the mib default */
64 
65 static netsnmp_table_data_set *nlmLogTable;
66 static netsnmp_table_data_set *nlmLogVarTable;
67 
68 static oid nlm_module_oid[] = { SNMP_OID_MIB2, 92 }; /* NOTIFICATION-LOG-MIB::notificationLogMIB */
69 
70 static void
netsnmp_notif_log_remove_oldest(int count)71 netsnmp_notif_log_remove_oldest(int count)
72 {
73     netsnmp_table_row *deleterow, *tmprow, *deletevarrow;
74 
75     DEBUGMSGTL(("notification_log", "deleting %d log entry(s)\n", count));
76 
77     deleterow = netsnmp_table_data_set_get_first_row(nlmLogTable);
78     for (; count && deleterow; deleterow = tmprow, --count) {
79         /*
80          * delete contained varbinds
81          * xxx-rks: note that this assumes that only the default
82          * log is used (ie for the first nlmLogTable row, the
83          * first nlmLogVarTable rows will be the right ones).
84          * the right thing to do would be to do a find based on
85          * the nlmLogTable oid.
86          */
87         DEBUGMSGTL(("9:notification_log", "  deleting notification\n"));
88         DEBUGIF("9:notification_log") {
89             DEBUGMSGTL(("9:notification_log",
90                         " base oid:"));
91             DEBUGMSGOID(("9:notification_log", deleterow->index_oid,
92                          deleterow->index_oid_len));
93             DEBUGMSG(("9:notification_log", "\n"));
94         }
95         deletevarrow = netsnmp_table_data_set_get_first_row(nlmLogVarTable);
96         for (; deletevarrow; deletevarrow = tmprow) {
97 
98             tmprow = netsnmp_table_data_set_get_next_row(nlmLogVarTable,
99                                                           deletevarrow);
100 
101             DEBUGIF("9:notification_log") {
102                 DEBUGMSGTL(("9:notification_log",
103                             "         :"));
104                 DEBUGMSGOID(("9:notification_log", deletevarrow->index_oid,
105                              deletevarrow->index_oid_len));
106                 DEBUGMSG(("9:notification_log", "\n"));
107             }
108             if ((deleterow->index_oid_len == deletevarrow->index_oid_len - 1) &&
109                 snmp_oid_compare(deleterow->index_oid,
110                                  deleterow->index_oid_len,
111                                  deletevarrow->index_oid,
112                                  deleterow->index_oid_len) == 0) {
113                 DEBUGMSGTL(("9:notification_log", "    deleting varbind\n"));
114                 netsnmp_table_dataset_remove_and_delete_row(nlmLogVarTable,
115                                                              deletevarrow);
116             }
117             else
118                 break;
119         }
120 
121         /*
122          * delete the master row
123          */
124         tmprow = netsnmp_table_data_set_get_next_row(nlmLogTable, deleterow);
125         netsnmp_table_dataset_remove_and_delete_row(nlmLogTable,
126                                                      deleterow);
127         num_deleted++;
128     }
129     /** should have deleted all of them */
130     netsnmp_assert(0 == count);
131 }
132 
133 static void
check_log_size(unsigned int clientreg,void * clientarg)134 check_log_size(unsigned int clientreg, void *clientarg)
135 {
136     netsnmp_table_row *row;
137     netsnmp_table_data_set_storage *data;
138     u_long          count = 0;
139     u_long          uptime;
140 
141     uptime = netsnmp_get_agent_uptime();
142 
143     if (!nlmLogTable || !nlmLogTable->table )  {
144         DEBUGMSGTL(("notification_log", "missing log table\n"));
145         return;
146     }
147 
148     /*
149      * check max allowed count
150      */
151     count = netsnmp_table_set_num_rows(nlmLogTable);
152     DEBUGMSGTL(("notification_log",
153                 "logged notifications %lu; max %lu\n",
154                     count, max_logged));
155     if (count > max_logged) {
156         count = count - max_logged;
157         DEBUGMSGTL(("notification_log", "removing %lu extra notifications\n",
158                     count));
159         netsnmp_notif_log_remove_oldest(count);
160     }
161 
162     /*
163      * check max age
164      */
165     if (0 == max_age)
166         return;
167     count = 0;
168     for (row = netsnmp_table_data_set_get_first_row(nlmLogTable);
169          row;
170          row = netsnmp_table_data_set_get_next_row(nlmLogTable, row)) {
171 
172         data = (netsnmp_table_data_set_storage *) row->data;
173         data = netsnmp_table_data_set_find_column(data, COLUMN_NLMLOGTIME);
174 
175         if (uptime < ((u_long)(*(data->data.integer) + max_age * 100 * 60)))
176             break;
177         ++count;
178     }
179 
180     if (count) {
181         DEBUGMSGTL(("notification_log", "removing %lu expired notifications\n",
182                     count));
183         netsnmp_notif_log_remove_oldest(count);
184     }
185 }
186 
187 
188 /** Initialize the nlmLogVariableTable table by defining its contents and how it's structured */
189 static void
initialize_table_nlmLogVariableTable(const char * context)190 initialize_table_nlmLogVariableTable(const char * context)
191 {
192     static oid      nlmLogVariableTable_oid[] =
193         { 1, 3, 6, 1, 2, 1, 92, 1, 3, 2 };
194     size_t          nlmLogVariableTable_oid_len =
195         OID_LENGTH(nlmLogVariableTable_oid);
196     netsnmp_table_data_set *table_set;
197     netsnmp_handler_registration *reginfo;
198 
199     /*
200      * create the table structure itself
201      */
202     table_set = netsnmp_create_table_data_set("nlmLogVariableTable");
203     nlmLogVarTable = table_set;
204     nlmLogVarTable->table->store_indexes = 1;
205 
206     /***************************************************
207      * Adding indexes
208      */
209     /*
210      * declaring the nlmLogName index
211      */
212     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
213                 "adding index nlmLogName of type ASN_OCTET_STR to table nlmLogVariableTable\n"));
214     netsnmp_table_dataset_add_index(table_set, ASN_OCTET_STR);
215     /*
216      * declaring the nlmLogIndex index
217      */
218     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
219                 "adding index nlmLogIndex of type ASN_UNSIGNED to table nlmLogVariableTable\n"));
220     netsnmp_table_dataset_add_index(table_set, ASN_UNSIGNED);
221     /*
222      * declaring the nlmLogVariableIndex index
223      */
224     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
225                 "adding index nlmLogVariableIndex of type ASN_UNSIGNED to table nlmLogVariableTable\n"));
226     netsnmp_table_dataset_add_index(table_set, ASN_UNSIGNED);
227 
228     /*
229      * adding column nlmLogVariableID of type ASN_OBJECT_ID and access of
230      * ReadOnly
231      */
232     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
233                 "adding column nlmLogVariableID (#2) of type ASN_OBJECT_ID to table nlmLogVariableTable\n"));
234     netsnmp_table_set_add_default_row(table_set, COLUMN_NLMLOGVARIABLEID,
235                                       ASN_OBJECT_ID, 0, NULL, 0);
236     /*
237      * adding column nlmLogVariableValueType of type ASN_INTEGER and
238      * access of ReadOnly
239      */
240     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
241                 "adding column nlmLogVariableValueType (#3) of type ASN_INTEGER to table nlmLogVariableTable\n"));
242     netsnmp_table_set_add_default_row(table_set,
243                                       COLUMN_NLMLOGVARIABLEVALUETYPE,
244                                       ASN_INTEGER, 0, NULL, 0);
245     /*
246      * adding column nlmLogVariableCounter32Val of type ASN_COUNTER and
247      * access of ReadOnly
248      */
249     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
250                 "adding column nlmLogVariableCounter32Val (#4) of type ASN_COUNTER to table nlmLogVariableTable\n"));
251     netsnmp_table_set_add_default_row(table_set,
252                                       COLUMN_NLMLOGVARIABLECOUNTER32VAL,
253                                       ASN_COUNTER, 0, NULL, 0);
254     /*
255      * adding column nlmLogVariableUnsigned32Val of type ASN_UNSIGNED and
256      * access of ReadOnly
257      */
258     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
259                 "adding column nlmLogVariableUnsigned32Val (#5) of type ASN_UNSIGNED to table nlmLogVariableTable\n"));
260     netsnmp_table_set_add_default_row(table_set,
261                                       COLUMN_NLMLOGVARIABLEUNSIGNED32VAL,
262                                       ASN_UNSIGNED, 0, NULL, 0);
263     /*
264      * adding column nlmLogVariableTimeTicksVal of type ASN_TIMETICKS and
265      * access of ReadOnly
266      */
267     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
268                 "adding column nlmLogVariableTimeTicksVal (#6) of type ASN_TIMETICKS to table nlmLogVariableTable\n"));
269     netsnmp_table_set_add_default_row(table_set,
270                                       COLUMN_NLMLOGVARIABLETIMETICKSVAL,
271                                       ASN_TIMETICKS, 0, NULL, 0);
272     /*
273      * adding column nlmLogVariableInteger32Val of type ASN_INTEGER and
274      * access of ReadOnly
275      */
276     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
277                 "adding column nlmLogVariableInteger32Val (#7) of type ASN_INTEGER to table nlmLogVariableTable\n"));
278     netsnmp_table_set_add_default_row(table_set,
279                                       COLUMN_NLMLOGVARIABLEINTEGER32VAL,
280                                       ASN_INTEGER, 0, NULL, 0);
281     /*
282      * adding column nlmLogVariableOctetStringVal of type ASN_OCTET_STR
283      * and access of ReadOnly
284      */
285     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
286                 "adding column nlmLogVariableOctetStringVal (#8) of type ASN_OCTET_STR to table nlmLogVariableTable\n"));
287     netsnmp_table_set_add_default_row(table_set,
288                                       COLUMN_NLMLOGVARIABLEOCTETSTRINGVAL,
289                                       ASN_OCTET_STR, 0, NULL, 0);
290     /*
291      * adding column nlmLogVariableIpAddressVal of type ASN_IPADDRESS and
292      * access of ReadOnly
293      */
294     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
295                 "adding column nlmLogVariableIpAddressVal (#9) of type ASN_IPADDRESS to table nlmLogVariableTable\n"));
296     netsnmp_table_set_add_default_row(table_set,
297                                       COLUMN_NLMLOGVARIABLEIPADDRESSVAL,
298                                       ASN_IPADDRESS, 0, NULL, 0);
299     /*
300      * adding column nlmLogVariableOidVal of type ASN_OBJECT_ID and access
301      * of ReadOnly
302      */
303     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
304                 "adding column nlmLogVariableOidVal (#10) of type ASN_OBJECT_ID to table nlmLogVariableTable\n"));
305     netsnmp_table_set_add_default_row(table_set,
306                                       COLUMN_NLMLOGVARIABLEOIDVAL,
307                                       ASN_OBJECT_ID, 0, NULL, 0);
308     /*
309      * adding column nlmLogVariableCounter64Val of type ASN_COUNTER64 and
310      * access of ReadOnly
311      */
312     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
313                 "adding column nlmLogVariableCounter64Val (#11) of type ASN_COUNTER64 to table nlmLogVariableTable\n"));
314     netsnmp_table_set_add_default_row(table_set,
315                                       COLUMN_NLMLOGVARIABLECOUNTER64VAL,
316                                       ASN_COUNTER64, 0, NULL, 0);
317     /*
318      * adding column nlmLogVariableOpaqueVal of type ASN_OPAQUE and access
319      * of ReadOnly
320      */
321     DEBUGMSGTL(("initialize_table_nlmLogVariableTable",
322                 "adding column nlmLogVariableOpaqueVal (#12) of type ASN_OPAQUE to table nlmLogVariableTable\n"));
323     netsnmp_table_set_add_default_row(table_set,
324                                       COLUMN_NLMLOGVARIABLEOPAQUEVAL,
325                                       ASN_OPAQUE, 0, NULL, 0);
326 
327     /*
328      * registering the table with the master agent
329      */
330     /*
331      * note: if you don't need a subhandler to deal with any aspects of
332      * the request, change nlmLogVariableTable_handler to "NULL"
333      */
334     reginfo =
335         netsnmp_create_handler_registration ("nlmLogVariableTable",
336                                              NULL,
337                                              nlmLogVariableTable_oid,
338                                              nlmLogVariableTable_oid_len,
339                                              HANDLER_CAN_RWRITE);
340     if (NULL != context)
341         reginfo->contextName = strdup(context);
342     netsnmp_register_table_data_set(reginfo, table_set, NULL);
343 }
344 
345 /** Initialize the nlmLogTable table by defining its contents and how it's structured */
346 static void
initialize_table_nlmLogTable(const char * context)347 initialize_table_nlmLogTable(const char * context)
348 {
349     static oid      nlmLogTable_oid[] = { 1, 3, 6, 1, 2, 1, 92, 1, 3, 1 };
350     size_t          nlmLogTable_oid_len = OID_LENGTH(nlmLogTable_oid);
351     netsnmp_handler_registration *reginfo;
352 
353     /*
354      * create the table structure itself
355      */
356     nlmLogTable = netsnmp_create_table_data_set("nlmLogTable");
357 
358     /***************************************************
359      * Adding indexes
360      */
361     /*
362      * declaring the nlmLogIndex index
363      */
364     DEBUGMSGTL(("initialize_table_nlmLogTable",
365                 "adding index nlmLogName of type ASN_OCTET_STR to table nlmLogTable\n"));
366     netsnmp_table_dataset_add_index(nlmLogTable, ASN_OCTET_STR);
367 
368     DEBUGMSGTL(("initialize_table_nlmLogTable",
369                 "adding index nlmLogIndex of type ASN_UNSIGNED to table nlmLogTable\n"));
370     netsnmp_table_dataset_add_index(nlmLogTable, ASN_UNSIGNED);
371 
372     /*
373      * adding column nlmLogTime of type ASN_TIMETICKS and access of
374      * ReadOnly
375      */
376     DEBUGMSGTL(("initialize_table_nlmLogTable",
377                 "adding column nlmLogTime (#2) of type ASN_TIMETICKS to table nlmLogTable\n"));
378     netsnmp_table_set_add_default_row(nlmLogTable, COLUMN_NLMLOGTIME,
379                                       ASN_TIMETICKS, 0, NULL, 0);
380     /*
381      * adding column nlmLogDateAndTime of type ASN_OCTET_STR and access of
382      * ReadOnly
383      */
384     DEBUGMSGTL(("initialize_table_nlmLogTable",
385                 "adding column nlmLogDateAndTime (#3) of type ASN_OCTET_STR to table nlmLogTable\n"));
386     netsnmp_table_set_add_default_row(nlmLogTable,
387                                       COLUMN_NLMLOGDATEANDTIME,
388                                       ASN_OCTET_STR, 0, NULL, 0);
389     /*
390      * adding column nlmLogEngineID of type ASN_OCTET_STR and access of
391      * ReadOnly
392      */
393     DEBUGMSGTL(("initialize_table_nlmLogTable",
394                 "adding column nlmLogEngineID (#4) of type ASN_OCTET_STR to table nlmLogTable\n"));
395     netsnmp_table_set_add_default_row(nlmLogTable, COLUMN_NLMLOGENGINEID,
396                                       ASN_OCTET_STR, 0, NULL, 0);
397     /*
398      * adding column nlmLogEngineTAddress of type ASN_OCTET_STR and access
399      * of ReadOnly
400      */
401     DEBUGMSGTL(("initialize_table_nlmLogTable",
402                 "adding column nlmLogEngineTAddress (#5) of type ASN_OCTET_STR to table nlmLogTable\n"));
403     netsnmp_table_set_add_default_row(nlmLogTable,
404                                       COLUMN_NLMLOGENGINETADDRESS,
405                                       ASN_OCTET_STR, 0, NULL, 0);
406     /*
407      * adding column nlmLogEngineTDomain of type ASN_OBJECT_ID and access
408      * of ReadOnly
409      */
410     DEBUGMSGTL(("initialize_table_nlmLogTable",
411                 "adding column nlmLogEngineTDomain (#6) of type ASN_OBJECT_ID to table nlmLogTable\n"));
412     netsnmp_table_set_add_default_row(nlmLogTable,
413                                       COLUMN_NLMLOGENGINETDOMAIN,
414                                       ASN_OBJECT_ID, 0, NULL, 0);
415     /*
416      * adding column nlmLogContextEngineID of type ASN_OCTET_STR and
417      * access of ReadOnly
418      */
419     DEBUGMSGTL(("initialize_table_nlmLogTable",
420                 "adding column nlmLogContextEngineID (#7) of type ASN_OCTET_STR to table nlmLogTable\n"));
421     netsnmp_table_set_add_default_row(nlmLogTable,
422                                       COLUMN_NLMLOGCONTEXTENGINEID,
423                                       ASN_OCTET_STR, 0, NULL, 0);
424     /*
425      * adding column nlmLogContextName of type ASN_OCTET_STR and access of
426      * ReadOnly
427      */
428     DEBUGMSGTL(("initialize_table_nlmLogTable",
429                 "adding column nlmLogContextName (#8) of type ASN_OCTET_STR to table nlmLogTable\n"));
430     netsnmp_table_set_add_default_row(nlmLogTable,
431                                       COLUMN_NLMLOGCONTEXTNAME,
432                                       ASN_OCTET_STR, 0, NULL, 0);
433     /*
434      * adding column nlmLogNotificationID of type ASN_OBJECT_ID and access
435      * of ReadOnly
436      */
437     DEBUGMSGTL(("initialize_table_nlmLogTable",
438                 "adding column nlmLogNotificationID (#9) of type ASN_OBJECT_ID to table nlmLogTable\n"));
439     netsnmp_table_set_add_default_row(nlmLogTable,
440                                       COLUMN_NLMLOGNOTIFICATIONID,
441                                       ASN_OBJECT_ID, 0, NULL, 0);
442 
443     /*
444      * registering the table with the master agent
445      */
446     /*
447      * note: if you don't need a subhandler to deal with any aspects of
448      * the request, change nlmLogTable_handler to "NULL"
449      */
450     reginfo =
451         netsnmp_create_handler_registration("nlmLogTable", NULL,
452                                             nlmLogTable_oid,
453                                             nlmLogTable_oid_len,
454                                             HANDLER_CAN_RWRITE);
455     if (NULL != context)
456         reginfo->contextName = strdup(context);
457     netsnmp_register_table_data_set(reginfo, nlmLogTable, NULL);
458 
459     /*
460      * hmm...  5 minutes seems like a reasonable time to check for out
461      * dated notification logs right?
462      */
463     snmp_alarm_register(300, SA_REPEAT, check_log_size, NULL);
464 }
465 
466 static int
notification_log_config_handler(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)467 notification_log_config_handler(netsnmp_mib_handler *handler,
468                                 netsnmp_handler_registration *reginfo,
469                                 netsnmp_agent_request_info *reqinfo,
470                                 netsnmp_request_info *requests)
471 {
472     /*
473      *this handler exists only to act as a trigger when the
474      * configuration variables get set to a value and thus
475      * notifications must be possibly deleted from our archives.
476      */
477 #ifndef NETSNMP_NO_WRITE_SUPPORT
478     if (reqinfo->mode == MODE_SET_COMMIT)
479         check_log_size(0, NULL);
480 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
481     return SNMP_ERR_NOERROR;
482 }
483 
484 void
init_notification_log(void)485 init_notification_log(void)
486 {
487     static oid      my_nlmStatsGlobalNotificationsLogged_oid[] =
488         { 1, 3, 6, 1, 2, 1, 92, 1, 2, 1, 0 };
489     static oid      my_nlmStatsGlobalNotificationsBumped_oid[] =
490         { 1, 3, 6, 1, 2, 1, 92, 1, 2, 2, 0 };
491     static oid      my_nlmConfigGlobalEntryLimit_oid[] =
492         { 1, 3, 6, 1, 2, 1, 92, 1, 1, 1, 0 };
493     static oid      my_nlmConfigGlobalAgeOut_oid[] =
494         { 1, 3, 6, 1, 2, 1, 92, 1, 1, 2, 0 };
495     char * context;
496     char * apptype;
497 
498     context = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
499                                     NETSNMP_DS_NOTIF_LOG_CTX);
500 
501     DEBUGMSGTL(("notification_log", "registering with '%s' context\n",
502                    SNMP_STRORNULL(context)));
503 
504     /*
505      * static variables
506      */
507     netsnmp_register_read_only_counter32_instance_context
508         ("nlmStatsGlobalNotificationsLogged",
509          my_nlmStatsGlobalNotificationsLogged_oid,
510          OID_LENGTH(my_nlmStatsGlobalNotificationsLogged_oid),
511          &num_received, NULL, context);
512 
513     netsnmp_register_read_only_counter32_instance_context
514         ("nlmStatsGlobalNotificationsBumped",
515          my_nlmStatsGlobalNotificationsBumped_oid,
516          OID_LENGTH(my_nlmStatsGlobalNotificationsBumped_oid),
517          &num_deleted, NULL, context);
518 
519     netsnmp_register_ulong_instance_context("nlmConfigGlobalEntryLimit",
520                                             my_nlmConfigGlobalEntryLimit_oid,
521                                             OID_LENGTH
522                                             (my_nlmConfigGlobalEntryLimit_oid),
523                                             &max_logged,
524                                             notification_log_config_handler,
525                                             context);
526 
527     netsnmp_register_ulong_instance_context("nlmConfigGlobalAgeOut",
528                                             my_nlmConfigGlobalAgeOut_oid,
529                                             OID_LENGTH
530                                             (my_nlmConfigGlobalAgeOut_oid),
531                                             &max_age,
532                                             notification_log_config_handler,
533                                             context);
534 
535     /*
536      * tables
537      */
538     initialize_table_nlmLogVariableTable(context);
539     initialize_table_nlmLogTable(context);
540 
541     /*
542      * disable flag
543      */
544     apptype = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
545                                     NETSNMP_DS_LIB_APPTYPE);
546     netsnmp_ds_register_config(ASN_BOOLEAN, apptype, "dontRetainLogs",
547                                NETSNMP_DS_APPLICATION_ID,
548                                NETSNMP_DS_AGENT_DONT_RETAIN_NOTIFICATIONS);
549     netsnmp_ds_register_config(ASN_BOOLEAN, apptype, "doNotRetainNotificationLogs",
550                                NETSNMP_DS_APPLICATION_ID,
551                                NETSNMP_DS_AGENT_DONT_RETAIN_NOTIFICATIONS);
552 #if 0
553     /* xxx-rks: config for max size; should be peristent too, & tied to mib */
554     netsnmp_ds_register_config(ASN_INTEGER,
555                                netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
556                                                      NETSNMP_DS_LIB_APPTYPE),
557                                "notificationLogMax",
558                                NETSNMP_DS_APPLICATION_ID,
559                                NETSNMP_DS_AGENT_NOTIF_LOG_MAX);
560 #endif
561 
562     REGISTER_SYSOR_ENTRY(nlm_module_oid,
563         "The MIB module for logging SNMP Notifications.");
564 }
565 
566 void
shutdown_notification_log(void)567 shutdown_notification_log(void)
568 {
569     max_logged = 0;
570     check_log_size(0, NULL);
571     netsnmp_delete_table_data_set(nlmLogTable);
572     nlmLogTable = NULL;
573 
574     UNREGISTER_SYSOR_ENTRY(nlm_module_oid);
575 }
576 
577 void
log_notification(netsnmp_pdu * pdu,netsnmp_transport * transport)578 log_notification(netsnmp_pdu *pdu, netsnmp_transport *transport)
579 {
580     long            tmpl;
581     netsnmp_table_row *row;
582 
583     static u_long   default_num = 0;
584 
585     static oid      snmptrapoid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
586     size_t          snmptrapoid_len = OID_LENGTH(snmptrapoid);
587     netsnmp_variable_list *vptr;
588     u_char         *logdate;
589     size_t          logdate_size;
590     time_t          timetnow;
591 
592     u_long          vbcount = 0;
593     u_long          tmpul;
594     int             col;
595     netsnmp_pdu    *orig_pdu = pdu;
596 
597     if (!nlmLogVarTable
598         || netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
599                                   NETSNMP_DS_APP_DONT_LOG)) {
600         return;
601     }
602 
603     DEBUGMSGTL(("notification_log", "logging something\n"));
604     row = netsnmp_create_table_data_row();
605 
606     ++num_received;
607     default_num++;
608 
609     /*
610      * indexes to the table
611      */
612     netsnmp_table_row_add_index(row, ASN_OCTET_STR, "default",
613                                 strlen("default"));
614     netsnmp_table_row_add_index(row, ASN_UNSIGNED, &default_num,
615                                 sizeof(default_num));
616 
617     /*
618      * add the data
619      */
620     tmpl = netsnmp_get_agent_uptime();
621     netsnmp_set_row_column(row, COLUMN_NLMLOGTIME, ASN_TIMETICKS,
622                            &tmpl, sizeof(tmpl));
623     time(&timetnow);
624     logdate = date_n_time(&timetnow, &logdate_size);
625     netsnmp_set_row_column(row, COLUMN_NLMLOGDATEANDTIME, ASN_OCTET_STR,
626                            logdate, logdate_size);
627     netsnmp_set_row_column(row, COLUMN_NLMLOGENGINEID, ASN_OCTET_STR,
628                            pdu->securityEngineID,
629                            pdu->securityEngineIDLen);
630     if (transport && transport->domain == netsnmpUDPDomain) {
631         /*
632          * check for the udp domain
633          */
634         struct sockaddr_in *addr =
635             (struct sockaddr_in *) pdu->transport_data;
636         if (addr) {
637             char            buf[sizeof(in_addr_t) +
638                                 sizeof(addr->sin_port)];
639             in_addr_t       locaddr = htonl(addr->sin_addr.s_addr);
640             u_short         portnum = htons(addr->sin_port);
641             memcpy(buf, &locaddr, sizeof(in_addr_t));
642             memcpy(buf + sizeof(in_addr_t), &portnum,
643                    sizeof(addr->sin_port));
644             netsnmp_set_row_column(row, COLUMN_NLMLOGENGINETADDRESS,
645                                    ASN_OCTET_STR, buf,
646                                    sizeof(in_addr_t) +
647                                    sizeof(addr->sin_port));
648         }
649     }
650     if (transport)
651         netsnmp_set_row_column(row, COLUMN_NLMLOGENGINETDOMAIN,
652                                ASN_OBJECT_ID,
653                                transport->domain,
654                                sizeof(oid) * transport->domain_length);
655     netsnmp_set_row_column(row, COLUMN_NLMLOGCONTEXTENGINEID,
656                            ASN_OCTET_STR, pdu->contextEngineID,
657                            pdu->contextEngineIDLen);
658     netsnmp_set_row_column(row, COLUMN_NLMLOGCONTEXTNAME, ASN_OCTET_STR,
659                            pdu->contextName, pdu->contextNameLen);
660 
661     if (pdu->command == SNMP_MSG_TRAP)
662 	pdu = convert_v1pdu_to_v2(orig_pdu);
663     for (vptr = pdu->variables; vptr; vptr = vptr->next_variable) {
664         if (snmp_oid_compare(snmptrapoid, snmptrapoid_len,
665                              vptr->name, vptr->name_length) == 0) {
666             netsnmp_set_row_column(row, COLUMN_NLMLOGNOTIFICATIONID,
667                                    ASN_OBJECT_ID, vptr->val.string,
668                                    vptr->val_len);
669         } else {
670             netsnmp_table_row *myrow;
671             myrow = netsnmp_create_table_data_row();
672 
673             /*
674              * indexes to the table
675              */
676             netsnmp_table_row_add_index(myrow, ASN_OCTET_STR, "default",
677                                         strlen("default"));
678             netsnmp_table_row_add_index(myrow, ASN_UNSIGNED, &default_num,
679                                         sizeof(default_num));
680             vbcount++;
681             netsnmp_table_row_add_index(myrow, ASN_UNSIGNED, &vbcount,
682                                         sizeof(vbcount));
683 
684             /*
685              * OID
686              */
687             netsnmp_set_row_column(myrow, COLUMN_NLMLOGVARIABLEID,
688                                    ASN_OBJECT_ID, vptr->name,
689                                    vptr->name_length * sizeof(oid));
690 
691             /*
692              * value
693              */
694             switch (vptr->type) {
695             case ASN_OBJECT_ID:
696                 tmpul = 7;
697                 col = COLUMN_NLMLOGVARIABLEOIDVAL;
698                 break;
699 
700             case ASN_INTEGER:
701                 tmpul = 4;
702                 col = COLUMN_NLMLOGVARIABLEINTEGER32VAL;
703                 break;
704 
705             case ASN_UNSIGNED:
706                 tmpul = 2;
707                 col = COLUMN_NLMLOGVARIABLEUNSIGNED32VAL;
708                 break;
709 
710             case ASN_COUNTER:
711                 tmpul = 1;
712                 col = COLUMN_NLMLOGVARIABLECOUNTER32VAL;
713                 break;
714 
715             case ASN_TIMETICKS:
716                 tmpul = 3;
717                 col = COLUMN_NLMLOGVARIABLETIMETICKSVAL;
718                 break;
719 
720             case ASN_OCTET_STR:
721                 tmpul = 6;
722                 col = COLUMN_NLMLOGVARIABLEOCTETSTRINGVAL;
723                 break;
724 
725             case ASN_IPADDRESS:
726                 tmpul = 5;
727                 col = COLUMN_NLMLOGVARIABLEIPADDRESSVAL;
728                 break;
729 
730             case ASN_COUNTER64:
731                 tmpul = 8;
732                 col = COLUMN_NLMLOGVARIABLECOUNTER64VAL;
733                 break;
734 
735             case ASN_OPAQUE:
736                 tmpul = 9;
737                 col = COLUMN_NLMLOGVARIABLEOPAQUEVAL;
738                 break;
739 
740             default:
741                 /*
742                  * unsupported
743                  */
744                 DEBUGMSGTL(("notification_log",
745                             "skipping type %d\n", vptr->type));
746                 (void)netsnmp_table_dataset_delete_row(myrow);
747                 continue;
748             }
749             netsnmp_set_row_column(myrow, COLUMN_NLMLOGVARIABLEVALUETYPE,
750                                    ASN_INTEGER, & tmpul,
751                                    sizeof(tmpul));
752             netsnmp_set_row_column(myrow, col, vptr->type,
753                                    vptr->val.string, vptr->val_len);
754             DEBUGMSGTL(("notification_log",
755                         "adding a row to the variables table\n"));
756             netsnmp_table_dataset_add_row(nlmLogVarTable, myrow);
757         }
758     }
759 
760     if (pdu != orig_pdu)
761         snmp_free_pdu( pdu );
762 
763     /*
764      * store the row
765      */
766     netsnmp_table_dataset_add_row(nlmLogTable, row);
767 
768     check_log_size(0, NULL);
769     DEBUGMSGTL(("notification_log", "done logging something\n"));
770 }
771