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 ******************************************************************/
26 #include <net-snmp/net-snmp-config.h>
27 #include <net-snmp/net-snmp-includes.h>
28 #include <net-snmp/agent/net-snmp-agent-includes.h>
30 #include "util_funcs.h"
35 * Implementation headers
37 #include "agutil_api.h"
41 * File scope definitions section
45 * from MIB compilation
47 #define eventEntryFirstIndexBegin 11
50 #define EVENTDESCRIPTION 4
52 #define EVENTCOMMUNITY 6
53 #define EVENTLASTTIMESENT 7
57 #define Leaf_event_description 2
58 #define MIN_event_description 0
59 #define MAX_event_description 127
60 #define Leaf_event_type 3
61 #define Leaf_event_community 4
62 #define MIN_event_community 0
63 #define MAX_event_community 127
64 #define Leaf_event_last_time_sent 5
65 #define Leaf_eventOwner 6
66 #define Leaf_eventStatus 7
69 #define LOGEVENTINDEX 3
72 #define LOGDESCRIPTION 6
76 * defaults & limitations
79 #define MAX_LOG_ENTRIES_PER_CTRL 200
81 typedef struct data_struct_t {
82 struct data_struct_t *next;
85 char *log_description;
96 char *event_description;
97 char *event_community;
98 EVENT_TYPE_T event_type;
99 u_long event_last_time_sent;
103 u_long event_last_logged_index;
104 u_long event_number_of_log_entries;
105 DATA_ENTRY_T *log_list;
106 DATA_ENTRY_T *last_log_ptr;
114 static TABLE_DEFINTION_T EventCtrlTable;
115 static TABLE_DEFINTION_T *table_ptr = &EventCtrlTable;
118 * Control Table RowApi Callbacks
122 data_destructor(SCROLLER_T * scrlr, void *free_me)
124 DATA_ENTRY_T *lptr = free_me;
126 if (lptr->log_description)
127 AGFREE(lptr->log_description);
133 event_Create(RMON_ENTRY_T * eptr)
134 { /* create the body: alloc it and set defaults */
137 eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T));
140 body = (CRTL_ENTRY_T *) eptr->body;
146 body->event_description = NULL;
147 body->event_community = AGSTRDUP("public");
149 * ag_trace ("Dbg: created event_community=<%s>", body->event_community);
151 body->event_type = EVENT_NONE;
152 ROWDATAAPI_init(&body->scrlr,
153 MAX_LOG_ENTRIES_PER_CTRL,
154 MAX_LOG_ENTRIES_PER_CTRL,
155 sizeof(DATA_ENTRY_T), &data_destructor);
162 event_Clone(RMON_ENTRY_T * eptr)
163 { /* copy entry_bod -> clone */
164 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
165 CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp;
167 if (body->event_description)
168 clone->event_description = AGSTRDUP(body->event_description);
170 if (body->event_community)
171 clone->event_community = AGSTRDUP(body->event_community);
176 event_Copy(RMON_ENTRY_T * eptr)
178 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
179 CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp;
181 if (body->event_type != clone->event_type) {
182 body->event_type = clone->event_type;
185 if (clone->event_description) {
186 if (body->event_description)
187 AGFREE(body->event_description);
188 body->event_description = AGSTRDUP(clone->event_description);
191 if (clone->event_community) {
192 if (body->event_community)
193 AGFREE(body->event_community);
194 body->event_community = AGSTRDUP(clone->event_community);
201 event_Delete(RMON_ENTRY_T * eptr)
203 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr;
205 if (body->event_description)
206 AGFREE(body->event_description);
208 if (body->event_community)
209 AGFREE(body->event_community);
215 event_Activate(RMON_ENTRY_T * eptr)
216 { /* init logTable */
217 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
219 ROWDATAAPI_set_size(&body->scrlr,
220 body->scrlr.data_requested,
221 RMON1_ENTRY_VALID == eptr->status);
227 event_Deactivate(RMON_ENTRY_T * eptr)
228 { /* free logTable */
229 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body;
234 ROWDATAAPI_descructor(&body->scrlr);
240 write_eventControl(int action, u_char * var_val, u_char var_val_type,
241 size_t var_val_len, u_char * statP,
242 oid * name, size_t name_len)
246 int leaf_id, snmp_status;
247 static int prev_action = COMMIT;
249 CRTL_ENTRY_T *cloned_body;
259 return ROWAPI_do_another_action(name, eventEntryFirstIndexBegin,
260 action, &prev_action,
261 table_ptr, sizeof(CRTL_ENTRY_T));
265 * get values from PDU, check them and save them in the cloned entry
267 long_temp = name[eventEntryFirstIndexBegin];
268 leaf_id = (int) name[eventEntryFirstIndexBegin - 1];
269 hdr = ROWAPI_find(table_ptr, long_temp); /* it MUST be OK */
270 cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
271 body = (CRTL_ENTRY_T *) hdr->body;
273 case Leaf_event_description:
274 char_temp = AGMALLOC(1 + MAX_event_description);
276 return SNMP_ERR_TOOBIG;
277 snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
279 MAX_event_description,
281 if (SNMP_ERR_NOERROR != snmp_status) {
286 if (cloned_body->event_description)
287 AGFREE(cloned_body->event_description);
289 cloned_body->event_description = AGSTRDUP(char_temp);
291 * ag_trace ("rx: event_description=<%s>", cloned_body->event_description);
296 case Leaf_event_type:
297 snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
302 if (SNMP_ERR_NOERROR != snmp_status) {
305 cloned_body->event_type = long_temp;
307 case Leaf_event_community:
308 char_temp = AGMALLOC(1 + MAX_event_community);
310 return SNMP_ERR_TOOBIG;
311 snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
315 if (SNMP_ERR_NOERROR != snmp_status) {
320 if (cloned_body->event_community)
321 AGFREE(cloned_body->event_community);
323 cloned_body->event_community = AGSTRDUP(char_temp);
327 case Leaf_eventOwner:
329 AGFREE(hdr->new_owner);
330 hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
332 return SNMP_ERR_TOOBIG;
333 snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
336 1, NULL, hdr->new_owner);
337 if (SNMP_ERR_NOERROR != snmp_status) {
342 case Leaf_eventStatus:
343 snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
348 if (SNMP_ERR_NOERROR != snmp_status) {
351 hdr->new_status = long_temp;
354 ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
356 return SNMP_ERR_NOSUCHNAME;
357 } /* of switch by 'leaf_id' */
359 } /* of switch by actions */
361 prev_action = action;
362 return SNMP_ERR_NOERROR;
366 var_eventTable(struct variable *vp,
369 int exact, size_t * var_len, WriteMethod ** write_method)
371 static long long_ret;
372 static CRTL_ENTRY_T theEntry;
375 *write_method = write_eventControl;
376 hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
378 &theEntry, sizeof(CRTL_ENTRY_T));
382 *var_len = sizeof(long); /* default */
386 long_ret = hdr->ctrl_index;
387 return (unsigned char *) &long_ret;
388 case EVENTDESCRIPTION:
389 if (theEntry.event_description) {
390 *var_len = strlen(theEntry.event_description);
391 return (unsigned char *) theEntry.event_description;
394 return (unsigned char *) "";
397 long_ret = theEntry.event_type;
398 return (unsigned char *) &long_ret;
400 if (theEntry.event_community) {
401 *var_len = strlen(theEntry.event_community);
402 return (unsigned char *) theEntry.event_community;
405 return (unsigned char *) "";
407 case EVENTLASTTIMESENT:
408 long_ret = theEntry.event_last_time_sent;
409 return (unsigned char *) &long_ret;
412 *var_len = strlen(hdr->owner);
413 return (unsigned char *) hdr->owner;
416 return (unsigned char *) "";
419 long_ret = hdr->status;
420 return (unsigned char *) &long_ret;
422 ag_trace("EventControlTable: unknown vp->magic=%d",
430 event_extract_scroller(void *v_body)
432 CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) v_body;
437 var_logTable(struct variable *vp,
440 int exact, size_t * var_len, WriteMethod ** write_method)
442 static long long_ret;
443 static DATA_ENTRY_T theEntry;
447 *write_method = NULL;
448 hdr = ROWDATAAPI_header_DataEntry(vp, name, length, exact, var_len,
450 &event_extract_scroller,
451 sizeof(DATA_ENTRY_T), &theEntry);
455 ctrl = (CRTL_ENTRY_T *) hdr->body;
457 *var_len = sizeof(long); /* default */
461 long_ret = hdr->ctrl_index;
462 return (unsigned char *) &long_ret;
464 long_ret = theEntry.data_index;
465 return (unsigned char *) &long_ret;
467 long_ret = theEntry.log_time;
468 return (unsigned char *) &long_ret;
470 if (theEntry.log_description) {
471 *var_len = strlen(theEntry.log_description);
472 return (unsigned char *) theEntry.log_description;
475 return (unsigned char *) "";
485 * External API section
489 create_explanaition(CRTL_ENTRY_T * evptr, u_char is_rising,
490 u_long alarm_index, u_long event_index,
492 size_t alarmed_var_length,
493 u_long value, u_long the_threshold,
494 u_long sample_type, char *alarm_descr)
496 #define UNEQ_LENGTH (1 + 11 + 4 + 11 + 1 + 20)
497 char expl[UNEQ_LENGTH];
498 static char c_oid[SPRINT_MAX_LEN];
505 snprint_objid(c_oid, sizeof(c_oid)-1, alarmed_var, alarmed_var_length);
506 c_oid[sizeof(c_oid)-1] = '\0';
507 for (pch = c_oid;;) {
508 tmp = strchr(pch, '.');
511 if (isdigit(tmp[1]) || '"' == tmp[1])
516 snprintf(expl, UNEQ_LENGTH, "=%ld %s= %ld :%ld, %ld",
517 (unsigned long) value,
518 is_rising ? ">" : "<",
519 (unsigned long) the_threshold,
520 (long) alarm_index, (long) event_index);
521 sz = 3 + strlen(expl) + strlen(pch);
523 sz += strlen(alarm_descr);
525 descr = AGMALLOC(sz);
527 ag_trace("Can't allocate event description");
532 strcpy(descr, alarm_descr);
542 extern void send_enterprise_trap_vars(int, int, oid *, int,
543 netsnmp_variable_list *);
545 static netsnmp_variable_list *
546 oa_bind_var(netsnmp_variable_list * prev,
547 void *value, int type, size_t sz_val, oid * oid, size_t sz_oid)
549 netsnmp_variable_list *var;
551 var = (netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
553 ag_trace("FATAL: cannot malloc in oa_bind_var\n");
554 exit(-1); /* Sorry :( */
556 memset(var, 0, sizeof(netsnmp_variable_list));
557 var->next_variable = prev;
558 snmp_set_var_objid(var, oid, sz_oid);
559 snmp_set_var_value(var, (u_char *) value, sz_val);
566 event_send_trap(CRTL_ENTRY_T * evptr, u_char is_rising,
568 u_int value, u_int the_threshold,
569 oid * alarmed_var, size_t alarmed_var_length,
572 static oid rmon1_trap_oid[] = { 1, 3, 6, 1, 2, 1, 16, 0, 0 };
573 static oid alarm_index_oid[] =
574 { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 1 };
575 static oid alarmed_var_oid[] =
576 { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 3 };
577 static oid sample_type_oid[] =
578 { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 4 };
579 static oid value_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 5 };
580 static oid threshold_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 7 }; /* rising case */
581 netsnmp_variable_list *top = NULL;
585 * set the last 'oid' : risingAlarm or fallingAlarm
588 iii = OID_LENGTH(rmon1_trap_oid);
589 rmon1_trap_oid[iii - 1] = 1;
590 iii = OID_LENGTH(threshold_oid);
591 threshold_oid[iii - 1] = 7;
593 iii = OID_LENGTH(rmon1_trap_oid);
594 rmon1_trap_oid[iii - 1] = 0;
595 iii = OID_LENGTH(threshold_oid);
596 threshold_oid[iii - 1] = 8;
602 top = oa_bind_var(top, &alarm_index, ASN_INTEGER, sizeof(u_int),
603 alarm_index_oid, OID_LENGTH(alarm_index_oid));
606 oa_bind_var(top, alarmed_var, ASN_OBJECT_ID,
607 sizeof(oid) * alarmed_var_length, alarmed_var_oid,
608 OID_LENGTH(alarmed_var_oid));
610 top = oa_bind_var(top, &sample_type, ASN_INTEGER, sizeof(u_int),
611 sample_type_oid, OID_LENGTH(sample_type_oid));
613 top = oa_bind_var(top, &value, ASN_INTEGER, sizeof(u_int),
614 value_oid, OID_LENGTH(value_oid));
616 top = oa_bind_var(top, &the_threshold, ASN_INTEGER, sizeof(u_int),
617 threshold_oid, OID_LENGTH(threshold_oid));
620 send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC, 0,
622 OID_LENGTH(rmon1_trap_oid), top);
623 ag_trace("rmon trap has been sent");
624 snmp_free_varbind(top);
630 event_save_log(CRTL_ENTRY_T * body, char *event_descr)
632 register DATA_ENTRY_T *lptr;
634 lptr = ROWDATAAPI_locate_new_data(&body->scrlr);
636 ag_trace("Err: event_save_log:cannot locate ?");
640 lptr->log_time = body->event_last_time_sent;
641 lptr->log_description = AGSTRDUP(event_descr);
642 lptr->data_index = ROWDATAAPI_get_total_number(&body->scrlr);
645 * ag_trace ("log has been saved, data_index=%d", (int) lptr->data_index);
650 event_api_send_alarm(u_char is_rising,
654 size_t alarmed_var_length,
656 u_long value, u_long the_threshold, char *alarm_descr)
662 return SNMP_ERR_NOSUCHNAME;
665 ag_trace("event_api_send_alarm(%d,%d,%d,'%s')",
666 (int) is_rising, (int) alarm_index, (int) event_index,
669 eptr = ROWAPI_find(table_ptr, event_index);
672 * ag_trace ("event cannot find entry %ld", event_index);
674 return SNMP_ERR_NOSUCHNAME;
677 evptr = (CRTL_ENTRY_T *) eptr->body;
678 evptr->event_last_time_sent = AGUTIL_sys_up_time();
681 if (EVENT_TRAP == evptr->event_type
682 || EVENT_LOG_AND_TRAP == evptr->event_type) {
683 event_send_trap(evptr, is_rising, alarm_index, value,
684 the_threshold, alarmed_var, alarmed_var_length,
688 if (EVENT_LOG == evptr->event_type
689 || EVENT_LOG_AND_TRAP == evptr->event_type) {
690 register char *explain;
692 explain = create_explanaition(evptr, is_rising,
693 alarm_index, event_index,
694 alarmed_var, alarmed_var_length,
695 value, the_threshold,
696 sample_type, alarm_descr);
698 * if (explain) ag_trace ("Dbg:'%s'", explain);
700 event_save_log(evptr, explain);
705 return SNMP_ERR_NOERROR;
708 #if 1 /* debug, but may be used for init. TBD: may be token snmpd.conf ? */
710 add_event_entry(int ctrl_index,
711 char *event_description,
712 EVENT_TYPE_T event_type, char *event_community)
714 register RMON_ENTRY_T *eptr;
715 register CRTL_ENTRY_T *body;
718 ierr = ROWAPI_new(table_ptr, ctrl_index);
720 ag_trace("ROWAPI_new failed with %d", ierr);
724 eptr = ROWAPI_find(table_ptr, ctrl_index);
726 ag_trace("ROWAPI_find failed");
730 body = (CRTL_ENTRY_T *) eptr->body;
736 if (event_description) {
737 if (body->event_description)
738 AGFREE(body->event_description);
739 body->event_description = AGSTRDUP(event_description);
742 if (event_community) {
743 if (body->event_community)
744 AGFREE(body->event_community);
745 body->event_community = AGSTRDUP(event_community);
748 body->event_type = event_type;
750 eptr->new_status = RMON1_ENTRY_VALID;
751 ierr = ROWAPI_commit(table_ptr, ctrl_index);
753 ag_trace("ROWAPI_commit failed with %d", ierr);
761 * Registration & Initializatio section
764 oid eventTable_variables_oid[] =
765 { 1, 3, 6, 1, 2, 1, 16, 9, 1 };
766 oid logTable_variables_oid[] = { 1, 3, 6, 1, 2, 1, 16, 9, 2 };
768 struct variable2 eventTable_variables[] = {
770 * magic number , variable type, ro/rw , callback fn , L, oidsuffix
772 {EVENTINDEX, ASN_INTEGER, RONLY, var_eventTable, 2, {1, 1}},
773 {EVENTDESCRIPTION, ASN_OCTET_STR, RWRITE, var_eventTable, 2, {1, 2}},
774 {EVENTTYPE, ASN_INTEGER, RWRITE, var_eventTable, 2, {1, 3}},
775 {EVENTCOMMUNITY, ASN_OCTET_STR, RWRITE, var_eventTable, 2, {1, 4}},
776 {EVENTLASTTIMESENT, ASN_TIMETICKS, RONLY, var_eventTable, 2, {1, 5}},
777 {EVENTOWNER, ASN_OCTET_STR, RWRITE, var_eventTable, 2, {1, 6}},
778 {EVENTSTATUS, ASN_INTEGER, RWRITE, var_eventTable, 2, {1, 7}}
781 struct variable2 logTable_variables[] = {
783 * magic number , variable type, ro/rw , callback fn , L, oidsuffix
785 {LOGEVENTINDEX, ASN_INTEGER, RONLY, var_logTable, 2, {1, 1}},
786 {LOGINDEX, ASN_INTEGER, RONLY, var_logTable, 2, {1, 2}},
787 {LOGTIME, ASN_TIMETICKS, RONLY, var_logTable, 2, {1, 3}},
788 {LOGDESCRIPTION, ASN_OCTET_STR, RONLY, var_logTable, 2, {1, 4}}
795 REGISTER_MIB("eventTable", eventTable_variables, variable2,
796 eventTable_variables_oid);
797 REGISTER_MIB("logTable", logTable_variables, variable2,
798 logTable_variables_oid);
800 ROWAPI_init_table(&EventCtrlTable, "Event", 0, &event_Create, &event_Clone, &event_Delete, NULL, /* &event_Validate, */
801 &event_Activate, &event_Deactivate, &event_Copy);
803 add_event_entry(3, "Alarm", EVENT_LOG_AND_TRAP, NULL);
805 * add_event_entry (5, ">=", EVENT_LOG_AND_TRAP, NULL);