1
/**************************************************************
2
* Copyright (C) 2001 Alex Rozin, Optical Access
6
* Permission to use, copy, modify and distribute this software and its
7
* documentation for any purpose and without fee is hereby granted,
8
* provided that the above copyright notice appear in all copies and that
9
* both that copyright notice and this permission notice appear in
10
* supporting documentation.
12
* ALEX ROZIN DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
14
* ALEX ROZIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
15
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
16
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
17
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
19
******************************************************************/
21
#include <net-snmp/net-snmp-config.h>
26
#if TIME_WITH_SYS_TIME
28
# include <sys/timeb.h>
30
# include <sys/time.h>
35
# include <sys/time.h>
45
#include <net-snmp/net-snmp-includes.h>
46
#include <net-snmp/agent/net-snmp-agent-includes.h>
48
#include "util_funcs.h"
53
* Implementation headers
55
#include "agutil_api.h"
59
* File scope definitions section
63
* from MIB compilation
65
#define eventEntryFirstIndexBegin 11
68
#define EVENTDESCRIPTION 4
70
#define EVENTCOMMUNITY 6
71
#define EVENTLASTTIMESENT 7
75
#define Leaf_event_description 2
76
#define MIN_event_description 0
77
#define MAX_event_description 127
78
#define Leaf_event_type 3
79
#define Leaf_event_community 4
80
#define MIN_event_community 0
81
#define MAX_event_community 127
82
#define Leaf_event_last_time_sent 5
83
#define Leaf_eventOwner 6
84
#define Leaf_eventStatus 7
87
#define LOGEVENTINDEX 3
90
#define LOGDESCRIPTION 6
94
* defaults & limitations
97
#define MAX_LOG_ENTRIES_PER_CTRL 200
99
typedef struct data_struct_t {
100
struct data_struct_t *next;
103
char *log_description;
114
char *event_description;
115
char *event_community;
116
EVENT_TYPE_T event_type;
117
u_long event_last_time_sent;
121
u_long event_last_logged_index;
122
u_long event_number_of_log_entries;
123
DATA_ENTRY_T *log_list;
124
DATA_ENTRY_T *last_log_ptr;
132
static TABLE_DEFINTION_T EventCtrlTable;
133
static TABLE_DEFINTION_T *table_ptr = &EventCtrlTable;
136
* Control Table RowApi Callbacks
140
data_destructor(SCROLLER_T * scrlr, void *free_me)
142
DATA_ENTRY_T *lptr = free_me;
144
if (lptr->log_description)
145
AGFREE(lptr->log_description);
151
event_Create(RMON_ENTRY_T * eptr)
152
{ /* create the body: alloc it and set defaults */
155
eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T));
158
body = (CRTL_ENTRY_T *) eptr->body;
164
body->event_description = NULL;
165
body->event_community = AGSTRDUP("public");
167
* ag_trace ("Dbg: created event_community=<%s>", body->event_community);
169
body->event_type = EVENT_NONE;
170
ROWDATAAPI_init(&body->scrlr,
171
MAX_LOG_ENTRIES_PER_CTRL,
172
MAX_LOG_ENTRIES_PER_CTRL,
173
sizeof(DATA_ENTRY_T), &data_destructor);
180
event_Clone(RMON_ENTRY_T * eptr)
181
{ /* copy entry_bod -> clone */
182
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
183
CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp;
185
if (body->event_description)
186
clone->event_description = AGSTRDUP(body->event_description);
188
if (body->event_community)
189
clone->event_community = AGSTRDUP(body->event_community);
194
event_Copy(RMON_ENTRY_T * eptr)
196
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
197
CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp;
199
if (body->event_type != clone->event_type) {
200
body->event_type = clone->event_type;
203
if (clone->event_description) {
204
if (body->event_description)
205
AGFREE(body->event_description);
206
body->event_description = AGSTRDUP(clone->event_description);
209
if (clone->event_community) {
210
if (body->event_community)
211
AGFREE(body->event_community);
212
body->event_community = AGSTRDUP(clone->event_community);
219
event_Delete(RMON_ENTRY_T * eptr)
221
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr;
223
if (body->event_description)
224
AGFREE(body->event_description);
226
if (body->event_community)
227
AGFREE(body->event_community);
233
event_Activate(RMON_ENTRY_T * eptr)
234
{ /* init logTable */
235
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
237
ROWDATAAPI_set_size(&body->scrlr,
238
body->scrlr.data_requested,
239
(u_char)(RMON1_ENTRY_VALID == eptr->status) );
245
event_Deactivate(RMON_ENTRY_T * eptr)
246
{ /* free logTable */
247
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
252
ROWDATAAPI_descructor(&body->scrlr);
258
write_eventControl(int action, u_char * var_val, u_char var_val_type,
259
size_t var_val_len, u_char * statP,
260
oid * name, size_t name_len)
264
int leaf_id, snmp_status;
265
static int prev_action = COMMIT;
267
CRTL_ENTRY_T *cloned_body;
277
return ROWAPI_do_another_action(name, eventEntryFirstIndexBegin,
278
action, &prev_action,
279
table_ptr, sizeof(CRTL_ENTRY_T));
283
* get values from PDU, check them and save them in the cloned entry
285
long_temp = name[eventEntryFirstIndexBegin];
286
leaf_id = (int) name[eventEntryFirstIndexBegin - 1];
287
hdr = ROWAPI_find(table_ptr, long_temp); /* it MUST be OK */
288
cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
289
body = (CRTL_ENTRY_T *) hdr->body;
291
case Leaf_event_description:
292
char_temp = AGMALLOC(1 + MAX_event_description);
294
return SNMP_ERR_TOOBIG;
295
snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
297
MAX_event_description,
299
if (SNMP_ERR_NOERROR != snmp_status) {
304
if (cloned_body->event_description)
305
AGFREE(cloned_body->event_description);
307
cloned_body->event_description = AGSTRDUP(char_temp);
309
* ag_trace ("rx: event_description=<%s>", cloned_body->event_description);
314
case Leaf_event_type:
315
snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
320
if (SNMP_ERR_NOERROR != snmp_status) {
323
cloned_body->event_type = long_temp;
325
case Leaf_event_community:
326
char_temp = AGMALLOC(1 + MAX_event_community);
328
return SNMP_ERR_TOOBIG;
329
snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
333
if (SNMP_ERR_NOERROR != snmp_status) {
338
if (cloned_body->event_community)
339
AGFREE(cloned_body->event_community);
341
cloned_body->event_community = AGSTRDUP(char_temp);
345
case Leaf_eventOwner:
347
AGFREE(hdr->new_owner);
348
hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
350
return SNMP_ERR_TOOBIG;
351
snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
354
1, NULL, hdr->new_owner);
355
if (SNMP_ERR_NOERROR != snmp_status) {
360
case Leaf_eventStatus:
361
snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
366
if (SNMP_ERR_NOERROR != snmp_status) {
369
hdr->new_status = long_temp;
372
ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
374
return SNMP_ERR_NOSUCHNAME;
375
} /* of switch by 'leaf_id' */
377
} /* of switch by actions */
379
prev_action = action;
380
return SNMP_ERR_NOERROR;
384
var_eventTable(struct variable *vp,
387
int exact, size_t * var_len, WriteMethod ** write_method)
389
static long long_ret;
390
static CRTL_ENTRY_T theEntry;
393
*write_method = write_eventControl;
394
hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
396
&theEntry, sizeof(CRTL_ENTRY_T));
400
*var_len = sizeof(long); /* default */
404
long_ret = hdr->ctrl_index;
405
return (unsigned char *) &long_ret;
406
case EVENTDESCRIPTION:
407
if (theEntry.event_description) {
408
*var_len = strlen(theEntry.event_description);
409
return (unsigned char *) theEntry.event_description;
412
return (unsigned char *) "";
415
long_ret = theEntry.event_type;
416
return (unsigned char *) &long_ret;
418
if (theEntry.event_community) {
419
*var_len = strlen(theEntry.event_community);
420
return (unsigned char *) theEntry.event_community;
423
return (unsigned char *) "";
425
case EVENTLASTTIMESENT:
426
long_ret = theEntry.event_last_time_sent;
427
return (unsigned char *) &long_ret;
430
*var_len = strlen(hdr->owner);
431
return (unsigned char *) hdr->owner;
434
return (unsigned char *) "";
437
long_ret = hdr->status;
438
return (unsigned char *) &long_ret;
440
ag_trace("EventControlTable: unknown vp->magic=%d",
448
event_extract_scroller(void *v_body)
450
CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) v_body;
455
var_logTable(struct variable *vp,
458
int exact, size_t * var_len, WriteMethod ** write_method)
460
static long long_ret;
461
static DATA_ENTRY_T theEntry;
465
*write_method = NULL;
466
hdr = ROWDATAAPI_header_DataEntry(vp, name, length, exact, var_len,
468
&event_extract_scroller,
469
sizeof(DATA_ENTRY_T), &theEntry);
473
ctrl = (CRTL_ENTRY_T *) hdr->body;
475
*var_len = sizeof(long); /* default */
479
long_ret = hdr->ctrl_index;
480
return (unsigned char *) &long_ret;
482
long_ret = theEntry.data_index;
483
return (unsigned char *) &long_ret;
485
long_ret = theEntry.log_time;
486
return (unsigned char *) &long_ret;
488
if (theEntry.log_description) {
489
*var_len = strlen(theEntry.log_description);
490
return (unsigned char *) theEntry.log_description;
493
return (unsigned char *) "";
503
* External API section
507
create_explanaition(CRTL_ENTRY_T * evptr, u_char is_rising,
508
u_long alarm_index, u_long event_index,
510
size_t alarmed_var_length,
511
u_long value, u_long the_threshold,
512
u_long sample_type, char *alarm_descr)
514
#define UNEQ_LENGTH (1 + 11 + 4 + 11 + 1 + 20)
515
char expl[UNEQ_LENGTH];
516
static char c_oid[SPRINT_MAX_LEN];
523
snprint_objid(c_oid, sizeof(c_oid)-1, alarmed_var, alarmed_var_length);
524
c_oid[sizeof(c_oid)-1] = '\0';
525
for (pch = c_oid;;) {
526
tmp = strchr(pch, '.');
529
if (isdigit(tmp[1]) || '"' == tmp[1])
534
snprintf(expl, UNEQ_LENGTH, "=%ld %s= %ld :%ld, %ld",
535
(unsigned long) value,
536
is_rising ? ">" : "<",
537
(unsigned long) the_threshold,
538
(long) alarm_index, (long) event_index);
539
sz = 3 + strlen(expl) + strlen(pch);
541
sz += strlen(alarm_descr);
543
descr = AGMALLOC(sz);
545
ag_trace("Can't allocate event description");
550
strcpy(descr, alarm_descr);
560
extern void send_enterprise_trap_vars(int, int, oid *, int,
561
netsnmp_variable_list *);
563
static netsnmp_variable_list *
564
oa_bind_var(netsnmp_variable_list * prev,
565
void *value, int type, size_t sz_val, oid * oid, size_t sz_oid)
567
netsnmp_variable_list *var;
569
var = (netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
571
ag_trace("FATAL: cannot malloc in oa_bind_var\n");
572
exit(-1); /* Sorry :( */
574
memset(var, 0, sizeof(netsnmp_variable_list));
575
var->next_variable = prev;
576
snmp_set_var_objid(var, oid, sz_oid);
577
snmp_set_var_value(var, (u_char *) value, sz_val);
584
event_send_trap(CRTL_ENTRY_T * evptr, u_char is_rising,
586
u_int value, u_int the_threshold,
587
oid * alarmed_var, size_t alarmed_var_length,
590
static oid rmon1_trap_oid[] = { 1, 3, 6, 1, 2, 1, 16, 0, 0 };
591
static oid alarm_index_oid[] =
592
{ 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 1 };
593
static oid alarmed_var_oid[] =
594
{ 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 3 };
595
static oid sample_type_oid[] =
596
{ 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 4 };
597
static oid value_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 5 };
598
static oid threshold_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 7 }; /* rising case */
599
netsnmp_variable_list *top = NULL;
603
* set the last 'oid' : risingAlarm or fallingAlarm
606
iii = OID_LENGTH(rmon1_trap_oid);
607
rmon1_trap_oid[iii - 1] = 1;
608
iii = OID_LENGTH(threshold_oid);
609
threshold_oid[iii - 1] = 7;
611
iii = OID_LENGTH(rmon1_trap_oid);
612
rmon1_trap_oid[iii - 1] = 0;
613
iii = OID_LENGTH(threshold_oid);
614
threshold_oid[iii - 1] = 8;
620
top = oa_bind_var(top, &alarm_index, ASN_INTEGER, sizeof(u_int),
621
alarm_index_oid, OID_LENGTH(alarm_index_oid));
624
oa_bind_var(top, alarmed_var, ASN_OBJECT_ID,
625
sizeof(oid) * alarmed_var_length, alarmed_var_oid,
626
OID_LENGTH(alarmed_var_oid));
628
top = oa_bind_var(top, &sample_type, ASN_INTEGER, sizeof(u_int),
629
sample_type_oid, OID_LENGTH(sample_type_oid));
631
top = oa_bind_var(top, &value, ASN_INTEGER, sizeof(u_int),
632
value_oid, OID_LENGTH(value_oid));
634
top = oa_bind_var(top, &the_threshold, ASN_INTEGER, sizeof(u_int),
635
threshold_oid, OID_LENGTH(threshold_oid));
638
send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC, 0,
640
OID_LENGTH(rmon1_trap_oid), top);
641
ag_trace("rmon trap has been sent");
642
snmp_free_varbind(top);
648
event_save_log(CRTL_ENTRY_T * body, char *event_descr)
650
register DATA_ENTRY_T *lptr;
652
lptr = ROWDATAAPI_locate_new_data(&body->scrlr);
654
ag_trace("Err: event_save_log:cannot locate ?");
658
lptr->log_time = body->event_last_time_sent;
659
lptr->log_description = AGSTRDUP(event_descr);
660
lptr->data_index = ROWDATAAPI_get_total_number(&body->scrlr);
663
* ag_trace ("log has been saved, data_index=%d", (int) lptr->data_index);
668
event_api_send_alarm(u_char is_rising,
672
size_t alarmed_var_length,
674
u_long value, u_long the_threshold, char *alarm_descr)
680
return SNMP_ERR_NOSUCHNAME;
683
ag_trace("event_api_send_alarm(%d,%d,%d,'%s')",
684
(int) is_rising, (int) alarm_index, (int) event_index,
687
eptr = ROWAPI_find(table_ptr, event_index);
690
* ag_trace ("event cannot find entry %ld", event_index);
692
return SNMP_ERR_NOSUCHNAME;
695
evptr = (CRTL_ENTRY_T *) eptr->body;
696
evptr->event_last_time_sent = AGUTIL_sys_up_time();
699
if (EVENT_TRAP == evptr->event_type
700
|| EVENT_LOG_AND_TRAP == evptr->event_type) {
701
event_send_trap(evptr, is_rising, alarm_index, value,
702
the_threshold, alarmed_var, alarmed_var_length,
706
if (EVENT_LOG == evptr->event_type
707
|| EVENT_LOG_AND_TRAP == evptr->event_type) {
708
register char *explain;
710
explain = create_explanaition(evptr, is_rising,
711
alarm_index, event_index,
712
alarmed_var, alarmed_var_length,
713
value, the_threshold,
714
sample_type, alarm_descr);
716
* if (explain) ag_trace ("Dbg:'%s'", explain);
718
event_save_log(evptr, explain);
723
return SNMP_ERR_NOERROR;
726
#if 1 /* debug, but may be used for init. TBD: may be token snmpd.conf ? */
728
add_event_entry(int ctrl_index,
729
char *event_description,
730
EVENT_TYPE_T event_type, char *event_community)
732
register RMON_ENTRY_T *eptr;
733
register CRTL_ENTRY_T *body;
736
ierr = ROWAPI_new(table_ptr, ctrl_index);
738
ag_trace("ROWAPI_new failed with %d", ierr);
742
eptr = ROWAPI_find(table_ptr, ctrl_index);
744
ag_trace("ROWAPI_find failed");
748
body = (CRTL_ENTRY_T *) eptr->body;
754
if (event_description) {
755
if (body->event_description)
756
AGFREE(body->event_description);
757
body->event_description = AGSTRDUP(event_description);
760
if (event_community) {
761
if (body->event_community)
762
AGFREE(body->event_community);
763
body->event_community = AGSTRDUP(event_community);
766
body->event_type = event_type;
768
eptr->new_status = RMON1_ENTRY_VALID;
769
ierr = ROWAPI_commit(table_ptr, ctrl_index);
771
ag_trace("ROWAPI_commit failed with %d", ierr);
779
* Registration & Initializatio section
782
oid eventTable_variables_oid[] =
783
{ 1, 3, 6, 1, 2, 1, 16, 9, 1 };
784
oid logTable_variables_oid[] = { 1, 3, 6, 1, 2, 1, 16, 9, 2 };
786
struct variable2 eventTable_variables[] = {
788
* magic number , variable type, ro/rw , callback fn , L, oidsuffix
790
{EVENTINDEX, ASN_INTEGER, RONLY, var_eventTable, 2, {1, 1}},
791
{EVENTDESCRIPTION, ASN_OCTET_STR, RWRITE, var_eventTable, 2, {1, 2}},
792
{EVENTTYPE, ASN_INTEGER, RWRITE, var_eventTable, 2, {1, 3}},
793
{EVENTCOMMUNITY, ASN_OCTET_STR, RWRITE, var_eventTable, 2, {1, 4}},
794
{EVENTLASTTIMESENT, ASN_TIMETICKS, RONLY, var_eventTable, 2, {1, 5}},
795
{EVENTOWNER, ASN_OCTET_STR, RWRITE, var_eventTable, 2, {1, 6}},
796
{EVENTSTATUS, ASN_INTEGER, RWRITE, var_eventTable, 2, {1, 7}}
799
struct variable2 logTable_variables[] = {
801
* magic number , variable type, ro/rw , callback fn , L, oidsuffix
803
{LOGEVENTINDEX, ASN_INTEGER, RONLY, var_logTable, 2, {1, 1}},
804
{LOGINDEX, ASN_INTEGER, RONLY, var_logTable, 2, {1, 2}},
805
{LOGTIME, ASN_TIMETICKS, RONLY, var_logTable, 2, {1, 3}},
806
{LOGDESCRIPTION, ASN_OCTET_STR, RONLY, var_logTable, 2, {1, 4}}
813
REGISTER_MIB("eventTable", eventTable_variables, variable2,
814
eventTable_variables_oid);
815
REGISTER_MIB("logTable", logTable_variables, variable2,
816
logTable_variables_oid);
818
ROWAPI_init_table(&EventCtrlTable, "Event", 0, &event_Create, &event_Clone, &event_Delete, NULL, /* &event_Validate, */
819
&event_Activate, &event_Deactivate, &event_Copy);
821
add_event_entry(3, "Alarm", EVENT_LOG_AND_TRAP, NULL);
823
* add_event_entry (5, ">=", EVENT_LOG_AND_TRAP, NULL);