/************************************************************** * Copyright (C) 2001 Tali Rozin, Optical Access * * All Rights Reserved * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * TALI ROZIN DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * ALEX ROZIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. ******************************************************************/ #include #if HAVE_STDLIB #include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #if HAVE_UNISTD_H #include #endif #include #include #include "statistics.h" /* * Implementation headers */ #include "agutil_api.h" #include "row_api.h" /* * File scope definitions section */ /* * from MIB compilation */ #define MIB_DESCR "EthStat" #define etherStatsEntryFirstIndexBegin 11 #define IDetherStatsDroppedFrames 1 #define IDetherStatsCreateTime 2 #define IDetherStatsIndex 3 #define IDetherStatsDataSource 4 #define IDetherStatsDropEvents 5 #define IDetherStatsOctets 6 #define IDetherStatsPkts 7 #define IDetherStatsBroadcastPkts 8 #define IDetherStatsMulticastPkts 9 #define IDetherStatsCRCAlignErrors 10 #define IDetherStatsUndersizePkts 11 #define IDetherStatsOversizePkts 12 #define IDetherStatsFragments 13 #define IDetherStatsJabbers 14 #define IDetherStatsCollisions 15 #define IDetherStatsPkts64Octets 16 #define IDetherStatsPkts65to127Octets 17 #define IDetherStatsPkts128to255Octets 18 #define IDetherStatsPkts256to511Octets 19 #define IDetherStatsPkts512to1023Octets 20 #define IDetherStatsPkts1024to1518Octets 21 #define IDetherStatsOwner 22 #define IDetherStatsStatus 23 #define Leaf_etherStatsDataSource 2 #define Leaf_etherStatsOwner 20 #define Leaf_etherStatsStatus 21 #define MIN_etherStatsIndex 1 #define MAX_etherStatsIndex 65535 typedef struct { VAR_OID_T data_source; u_long etherStatsCreateTime; ETH_STATS_T eth; } CRTL_ENTRY_T; /* * Main section */ static TABLE_DEFINTION_T StatCtrlTable; static TABLE_DEFINTION_T * table_ptr = & StatCtrlTable; /* * Control Table RowApi Callbacks */ int stat_Create(RMON_ENTRY_T * eptr) { /* create the body: alloc it and set defaults */ CRTL_ENTRY_T *body; static VAR_OID_T data_src_if_index_1 = { 11, {1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 1} }; eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T)); if (!eptr->body) return -3; body = (CRTL_ENTRY_T *) eptr->body; /* * set defaults */ memcpy(&body->data_source, &data_src_if_index_1, sizeof(VAR_OID_T)); body->data_source.objid[body->data_source.length - 1] = eptr->ctrl_index; eptr->owner = AGSTRDUP("Startup Mgmt"); memset(&body->eth, 0, sizeof(ETH_STATS_T)); return 0; } int stat_Validate(RMON_ENTRY_T * eptr) { /* * T.B.D. (system dependent) check valid inteface in body->data_source; */ return 0; } int stat_Activate(RMON_ENTRY_T * eptr) { CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; body->etherStatsCreateTime = AGUTIL_sys_up_time(); return 0; } int stat_Copy(RMON_ENTRY_T * eptr) { CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; CRTL_ENTRY_T *clone = (CRTL_ENTRY_T *) eptr->tmp; if (snmp_oid_compare (clone->data_source.objid, clone->data_source.length, body->data_source.objid, body->data_source.length)) { memcpy(&body->data_source, &clone->data_source, sizeof(VAR_OID_T)); } return 0; } int stat_Deactivate(RMON_ENTRY_T * eptr) { CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; memset(&body->eth, 0, sizeof(ETH_STATS_T)); return 0; } /*************************************************** * Function:var_etherStats2Entry * Purpose: Handles the request for etherStats2Entry variable instances ***************************************************/ u_char * var_etherStats2Entry(struct variable * vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { static long long_return; static CRTL_ENTRY_T theEntry; RMON_ENTRY_T *hdr; *write_method = NULL; hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len, table_ptr, &theEntry, sizeof(CRTL_ENTRY_T)); if (!hdr) return NULL; *var_len = sizeof(long); /* default */ switch (vp->magic) { case IDetherStatsDroppedFrames: long_return = 0; return (u_char *) & long_return; case IDetherStatsCreateTime: long_return = theEntry.etherStatsCreateTime; return (u_char *) & long_return; default: ag_trace("%s: unknown vp->magic=%d", table_ptr->name, (int) vp->magic); ERROR_MSG(""); }; /* of switch by 'vp->magic' */ return NULL; } /*************************************************** * Function:write_etherStatsEntry ***************************************************/ static int write_etherStatsEntry(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t name_len) { long long_temp; int leaf_id, snmp_status; static int prev_action = COMMIT; RMON_ENTRY_T *hdr; CRTL_ENTRY_T *cloned_body; CRTL_ENTRY_T *body; switch (action) { case RESERVE1: case FREE: case UNDO: case ACTION: case COMMIT: default: snmp_status = ROWAPI_do_another_action(name, etherStatsEntryFirstIndexBegin, action, &prev_action, table_ptr, sizeof(CRTL_ENTRY_T)); if (SNMP_ERR_NOERROR != snmp_status) { ag_trace("failed action %d with %d", action, snmp_status); } break; case RESERVE2: /* * get values from PDU, check them and save them in the cloned entry */ long_temp = name[etherStatsEntryFirstIndexBegin]; leaf_id = (int) name[etherStatsEntryFirstIndexBegin - 1]; hdr = ROWAPI_find(table_ptr, long_temp); /* it MUST be OK */ cloned_body = (CRTL_ENTRY_T *) hdr->tmp; body = (CRTL_ENTRY_T *) hdr->body; switch (leaf_id) { case Leaf_etherStatsDataSource: snmp_status = AGUTIL_get_oid_value(var_val, var_val_type, var_val_len, &cloned_body->data_source); if (SNMP_ERR_NOERROR != snmp_status) { return snmp_status; } if (RMON1_ENTRY_UNDER_CREATION != hdr->status && snmp_oid_compare(cloned_body->data_source.objid, cloned_body->data_source.length, body->data_source.objid, body->data_source.length)) return SNMP_ERR_BADVALUE; break; break; case Leaf_etherStatsOwner: if (hdr->new_owner) AGFREE(hdr->new_owner); hdr->new_owner = AGMALLOC(MAX_OWNERSTRING); if (!hdr->new_owner) return SNMP_ERR_TOOBIG; snmp_status = AGUTIL_get_string_value(var_val, var_val_type, var_val_len, MAX_OWNERSTRING, 1, NULL, hdr->new_owner); if (SNMP_ERR_NOERROR != snmp_status) { return snmp_status; } break; case Leaf_etherStatsStatus: snmp_status = AGUTIL_get_int_value(var_val, var_val_type, var_val_len, RMON1_ENTRY_VALID, RMON1_ENTRY_INVALID, &long_temp); if (SNMP_ERR_NOERROR != snmp_status) { ag_trace("cannot browse etherStatsStatus"); return snmp_status; } hdr->new_status = long_temp; break; break; default: ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name, (int) leaf_id); return SNMP_ERR_NOSUCHNAME; } /* of switch by 'leaf_id' */ break; } /* of switch by 'action' */ prev_action = action; return SNMP_ERR_NOERROR; } /*************************************************** * Function:var_etherStatsEntry * Purpose: Handles the request for etherStatsEntry variable instances ***************************************************/ u_char * var_etherStatsEntry(struct variable * vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { static unsigned char zero_octet_string[1]; static long long_return; static CRTL_ENTRY_T theEntry; RMON_ENTRY_T *hdr; *write_method = write_etherStatsEntry; hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len, table_ptr, &theEntry, sizeof(CRTL_ENTRY_T)); if (!hdr) return NULL; if (RMON1_ENTRY_VALID == hdr->status) SYSTEM_get_eth_statistics(&theEntry.data_source, &theEntry.eth); *var_len = sizeof(long); switch (vp->magic) { case IDetherStatsIndex: long_return = hdr->ctrl_index; return (u_char *) & long_return; case IDetherStatsDataSource: *var_len = sizeof(oid) * theEntry.data_source.length; return (unsigned char *) theEntry.data_source.objid; case IDetherStatsDropEvents: long_return = 0; /* theEntry.eth.etherStatsDropEvents; */ return (u_char *) & long_return; case IDetherStatsOctets: long_return = theEntry.eth.octets; return (u_char *) & long_return; case IDetherStatsPkts: long_return = theEntry.eth.packets; return (u_char *) & long_return; case IDetherStatsBroadcastPkts: long_return = theEntry.eth.bcast_pkts; return (u_char *) & long_return; case IDetherStatsMulticastPkts: long_return = theEntry.eth.mcast_pkts; return (u_char *) & long_return; case IDetherStatsCRCAlignErrors: long_return = theEntry.eth.crc_align; return (u_char *) & long_return; case IDetherStatsUndersizePkts: long_return = theEntry.eth.undersize; return (u_char *) & long_return; case IDetherStatsOversizePkts: long_return = theEntry.eth.oversize; return (u_char *) & long_return; case IDetherStatsFragments: long_return = theEntry.eth.fragments; return (u_char *) & long_return; case IDetherStatsJabbers: long_return = theEntry.eth.jabbers; return (u_char *) & long_return; case IDetherStatsCollisions: long_return = theEntry.eth.collisions; return (u_char *) & long_return; case IDetherStatsPkts64Octets: long_return = theEntry.eth.pkts_64; return (u_char *) & long_return; case IDetherStatsPkts65to127Octets: long_return = theEntry.eth.pkts_65_127; return (u_char *) & long_return; case IDetherStatsPkts128to255Octets: long_return = theEntry.eth.pkts_128_255; return (u_char *) & long_return; case IDetherStatsPkts256to511Octets: long_return = theEntry.eth.pkts_256_511; return (u_char *) & long_return; case IDetherStatsPkts512to1023Octets: long_return = theEntry.eth.pkts_512_1023; return (u_char *) & long_return; case IDetherStatsPkts1024to1518Octets: long_return = theEntry.eth.pkts_1024_1518; return (u_char *) & long_return; case IDetherStatsOwner: if (hdr->owner) { *var_len = strlen(hdr->owner); return (unsigned char *) hdr->owner; } else { *var_len = 0; return zero_octet_string; } case IDetherStatsStatus: long_return = hdr->status; return (u_char *) & long_return; default: ERROR_MSG(""); }; /* of switch by 'vp->magic' */ return NULL; } #if 1 /* debug, but may be used for init. TBD: may be token snmpd.conf ? */ int add_statistics_entry(int ctrl_index, int ifIndex) { int ierr; ierr = ROWAPI_new(table_ptr, ctrl_index); switch (ierr) { case -1: ag_trace("max. number exedes\n"); break; case -2: ag_trace("malloc failed"); break; case -3: ag_trace("ClbkCreate failed"); break; case 0: break; default: ag_trace("Unknown code %d", ierr); break; } if (!ierr) { register RMON_ENTRY_T *eptr = ROWAPI_find(table_ptr, ctrl_index); if (!eptr) { ag_trace("cannot find it"); ierr = -4; } else { CRTL_ENTRY_T *body = (CRTL_ENTRY_T *) eptr->body; body->data_source.objid[body->data_source.length - 1] = ifIndex; eptr->new_status = RMON1_ENTRY_VALID; ierr = ROWAPI_commit(table_ptr, ctrl_index); if (ierr) { ag_trace("ROWAPI_commit returned %d", ierr); } } } return ierr; } #endif /*************************************************** * define Variables callbacks ***************************************************/ oid oidstatisticsVariablesOid[] = { 1, 3, 6, 1, 2, 1, 16, 1 }; struct variable7 oidstatisticsVariables[] = { {IDetherStatsIndex, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 1}}, {IDetherStatsDataSource, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE, var_etherStatsEntry, 3, {1, 1, 2}}, {IDetherStatsDropEvents, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 3}}, {IDetherStatsOctets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 4}}, {IDetherStatsPkts, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 5}}, {IDetherStatsBroadcastPkts, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 6}}, {IDetherStatsMulticastPkts, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 7}}, {IDetherStatsCRCAlignErrors, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 8}}, {IDetherStatsUndersizePkts, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 9}}, {IDetherStatsOversizePkts, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 10}}, {IDetherStatsFragments, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 11}}, {IDetherStatsJabbers, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 12}}, {IDetherStatsCollisions, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 13}}, {IDetherStatsPkts64Octets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 14}}, {IDetherStatsPkts65to127Octets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 15}}, {IDetherStatsPkts128to255Octets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 16}}, {IDetherStatsPkts256to511Octets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 17}}, {IDetherStatsPkts512to1023Octets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 18}}, {IDetherStatsPkts1024to1518Octets, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStatsEntry, 3, {1, 1, 19}}, {IDetherStatsOwner, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, var_etherStatsEntry, 3, {1, 1, 20}}, {IDetherStatsStatus, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, var_etherStatsEntry, 3, {1, 1, 21}}, {IDetherStatsDroppedFrames, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_etherStats2Entry, 3, {4, 1, 1}}, {IDetherStatsCreateTime, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY, var_etherStats2Entry, 3, {4, 1, 2}}, }; /*************************************************** * Function:init_statistics * Purpose: register statistics objects in the agent ***************************************************/ void init_statistics(void) { REGISTER_MIB(MIB_DESCR, oidstatisticsVariables, variable7, oidstatisticsVariablesOid); ROWAPI_init_table(&StatCtrlTable, MIB_DESCR, 0, &stat_Create, NULL, /* &stat_Clone, */ NULL, /* &stat_Delete, */ &stat_Validate, &stat_Activate, &stat_Deactivate, &stat_Copy); #if 0 /* debug */ { int iii; for (iii = 1; iii < 6; iii++) { add_statistics_entry(iii, iii); } add_statistics_entry(10, 16); add_statistics_entry(12, 11); } #endif } /* * end of file statistics.c */