/* 1219, Fri 1 May 98 NM_ST.C: DIsplay status of a NeTraMet meter Copyright (C) 1997-2002 by Nevil Brownlee, CAIDA | University of Auckland */ /* * $Log: nm_st.c,v $ * Revision 1.1.1.2.2.12 2002/02/23 01:57:19 nevil * Moving srl examples to examples/ directory. Modified examples/Makefile.in * * Revision 1.1.1.2.2.8 2000/08/08 19:44:44 nevil * 44b8 release * * Revision 1.1.1.2.2.3 2000/06/06 03:38:10 nevil * Combine NEW_ATR with TCP_ATR, various bug fixes * * Revision 1.1.1.2 1999/10/03 21:06:16 nevil * *** empty log message *** * * Revision 1.1.1.1.2.2 1999/09/22 05:38:35 nevil * Improve code to work properly on 64-bit machines * - Add OS=ALPHA handling to configure.in * - Clean up the Alpha compiler warnings * - Change all the snmp-related code to use Bit32 instead of unsigned long * * Revision 1.1.1.1.2.1 1999/01/08 01:38:29 nevil * Distribution file for 4.3b7 * * Revision 1.1.1.1 1998/11/16 03:57:27 nevil * Import of NeTraMet 4.3b3 * * Revision 1.1.1.1 1998/11/16 03:22:00 nevil * Import of release 4.3b3 * * Revision 1.1.1.1.2.1 1998/11/11 23:14:38 nevil * Only include malloc.h if we HAVE_MALLOC_H * * Revision 1.1.1.1 1998/10/28 20:31:24 nevil * Import of NeTraMet 4.3b1 * * Revision 1.1.3.2 1998/10/18 23:44:08 nevil * Added Nicolai's patches, some 'tidying up' of the source * * Revision 1.1.3.1 1998/10/13 02:48:20 nevil * Import of Nicolai's 4.2.2 * * Revision 1.1.1.1 1998/08/24 12:09:28 nguba * NetraMet 4.2 Original Distribution */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_SYS_SELECT_H # include #endif #if HAVE_MALLOC_H # include #endif #include #define EXTSNMP #include "ausnmp.h" #include "asn1.h" #include "snmp.h" #include "snmpimpl.h" #include "snmpapi.h" #include "snmpclnt.h" #include "mib.h" #define EXTERN #include "nmc.h" #include "nmc_c64.h" int request_stop = 0; void sigint_handler(int x) { request_stop = 1; } unsigned int max_flows; char meter[NAME_LN], owner[NAME_LN], community[NAME_LN]; unsigned int def_sync, def_sample_interval, def_lag, def_download, def_no_write_meter; int no_user_format, plain_format; void no_write_warning(struct meter_status *ms) { if (ms->no_write_warned) return; fprintf(stdout,"Community %s doesn't have write access to meter %s!\n" " Collections won't trigger recovery of idle flows <<<\n", ms->community,ms->name); ms->no_write_warned = 1; } void add_event(struct calendar_entry *entry, struct meter_status *ms) { struct calendar_entry *cp, *lcp; entry->next_event = ms->next_event; entry->ms = ms; entry->next = NULL; if (calendar == NULL) { /* First entry in queue */ calendar = entry; return; } lcp = NULL; cp = calendar; do { if (ms->next_event < cp->next_event) { entry->next = cp; if (lcp == NULL) calendar = entry; /* Add to head */ else lcp->next = entry; /* Link into queue */ return; } lcp = cp; cp = cp->next; } while (cp != NULL); lcp->next = entry; /* Add to tail */ } void ruleset_row(struct meter_status *ms, struct row_info *rip) { struct meter_rule_info mri; printf("rUleset %d: Status=%d, Owner=%s, Name='%s'\n", rip->tr_Index, rip->tr_Status, rip->tr_Owner, rip->tr_Name); if (strcmp(rip->tr_Owner, "NeTraMet") == 0) { /* We've found NeTraMet meter's default ruleset */ ms->d_ruleset.ri_Index = rip->tr_Index; } #if 0 if (strcmp(rip->tr_Owner, ms->owner_name) == 0) { mri.ri_Index = rip->tr_Index; ruleset_util(ms, RU_DESTROY, &mri); } #endif } void manager_row(struct meter_status *ms, struct row_info *rip) { printf("mAnager %d: Status=%d, Owner=%s\n", rip->tr_Index, rip->tr_Status, rip->tr_Owner); #if 0 if (strcmp(rip->tr_Owner, ms->owner_name) == 0 || strcmp(rip->tr_Owner, "NeTraMet") == 0) { ms->mi_u_Index = rip->tr_Index; task_util(ms, TU_DESTROY); } #endif } void reader_row(struct meter_status *ms, struct row_info *rip) { printf("rEader %d: Status=%d, Owner=%s\n", rip->tr_Index, rip->tr_Status, rip->tr_Owner); #if 0 if (strcmp(rip->tr_Owner, ms->owner_name) == 0) { ms->ci_u_Index = rip->tr_Index; reader_util(ms, CU_DESTROY, CU_UTIL); } #endif } int create_meter(struct meter_status *ms, time_t first_t, char *pn) { struct calendar_entry *entry; int a,b,n, syntax; if (ms->name[0] == '\0' || ms->community[0] == '\0') { fprintf(stdout,"Meter name or community not specified !!!\n"); return 0; } if (testing) printf("About to create_meter name=%s, community=%s\n", ms->name, ms->community); if (!start_snmp_session(ms)) return 0; ms->statsreqd = 1; /* Always want stats for nm_st! */ ms->status = MT_MANAGE; if (meter_info(ms)) { ms->status |= (MT_UP | MT_INFO); ms->next_event = ms->next_sample = first_t; /* Get first sample immediately */ entry = (struct calendar_entry *)calloc( sizeof(struct calendar_entry), 1); add_event(entry,ms); if (testing) printf("t=%u, next_event=%u, next_keepalive=%u, next_sample=%u\n", first_t, ms->next_event, ms->next_keepalive, ms->next_sample); #ifndef _AIX if (!meter_is_current(ms)) { fprintf(stdout,"Warning: meter %s (version %s) not same as %s!\n", ms->name,ms->version, pn); } #endif if (ms->MaxFlows > max_flows) max_flows = ms->MaxFlows; } else { fprintf(stdout,"Couldn't get meter info from %s!\n" " Does community %s have read or write access to the meter?\n", ms->name,ms->community); return 0; } set_meter_params(ms); search_table(ms, ST_RULESET, ruleset_row); search_table(ms, ST_MANAGER, manager_row); search_table(ms, ST_READER, reader_row); ++nmeters; } int main(int argc, char *argv[]) { int syntax; char *ap, arg[NAME_LN]; int a, j; time_t t1,t2; int busy_seconds; struct meter_status *ms, *nms; struct calendar_entry *cp; struct meter_rule_info mri; struct stat stat_buf; char have_config_file; FILE *cnf; char download_only; if (argc < 2) { fprintf(stderr,"%s [options] meter-name community\n\n", argv[0]); exit(0); } signal(SIGINT, sigint_handler); signal(SIGTERM, sigint_handler); fprintf(stdout,"nm_st: Meter status display for NeTraMet: v" ver_str "\n"); /* Check on meter version done in nmc_snmp.c */ incl_depth = syntax = verbose = testing = listrules = standard = 0; def_sync = 1; /* Samples synchronised with TOD clock */ def_sample_interval = 120; /* Default 2 minutes */ def_lag = 0; /* No time lag for collections */ meter[0] = owner[0] = community[0] = '\0'; max_flows = 0; def_download = 0; /* Download rule sets on startup */ def_no_write_meter = 0; plain_format = 0; for (a = 1; a < argc; ++a) { if (argv[a][0] == '-') { ap = argv[a]+2; switch (argv[a][1]) { case 'a': if (*ap == '\0') ap = argv[++a]; def_lag = atoi(ap); break; case 'c': if (*ap == '\0') ap = argv[++a]; j = atoi(ap); if (j == 0) download_only = 1; else def_sample_interval = j; break; case 'd': snmp_dump_packet++; break; case 'm': if (*ap == '\0') ap = argv[++a]; au_snmp_port = atoi(ap); break; case 'p': plain_format++; break; case 's': syntax++; break; case 't': testing++; break; case 'u': def_sync = 0; /* Unsynchronised */ break; case 'v': verbose++; break; case 'w': if (*ap == '\0') ap = argv[++a]; def_download = atoi(ap); break; case 'x': def_no_write_meter++; break; case 'S': standard++; break; default: fprintf(stderr,"Invalid option: -%c\n", argv[a][1]); break; } continue; } if (meter[0] == '\0') strcpy(meter,argv[a]); else if (community[0] == '\0') strcpy(community,argv[a]); else if (owner[0] == '\0') { strncpy(owner,argv[a],NAMESZ); owner[NAMESZ] = '\0'; } } init_mib(); /* Initialise SNMP handler */ first_meter = (struct meter_status *)calloc (sizeof(struct meter_status), 1); strcpy(first_meter->name,meter); strcpy((char *)first_meter->owner_name, owner[0] != '\0' ? owner : "nm_rc"); strcpy((char *)first_meter->community, community[0] != '\0' ? community : "public"); first_meter->synchronised = def_sync; first_meter->sample_interval = def_sample_interval; first_meter->lag_seconds = def_lag; first_meter->download_level = def_download; first_meter->no_write_meter = 1; first_meter->write_OK = 1; first_meter->lag_seconds = def_lag; time(&t1); for (nmeters = 0, ms = first_meter; ms; ms = ms->next) create_meter(ms, t1, argv[0]); if (nmeters == 0) { fprintf(stderr,"No meters to monitor !!!\n"); exit(0); } for (;;) { for (;;) { time(&t1); if (calendar->next_event > t1) break; /* Wait a while */ cp = calendar; calendar = cp->next; /* Take entry from queue */ ms = cp->ms; if (ms->status & MT_MANAGE) monitor(ms); add_event(cp,ms); } if (testing) fflush(stdout); time(&t1); if (calendar->next_event > t1) sleep(calendar->next_event-t1); if (request_stop) { /* Set by sigint_handler() */ #if 0 reader_util(ms, CU_DESTROY, CU_CURRENT); /* reader_util(ms, CU_DESTROY, CU_DEFAULT); */ ms->mi_u_Index = ms->mi_Index; task_util(ms, TU_DESTROY); ruleset_util(ms, RU_DESTROY, &ms->c_ruleset); #endif exit(1); } } } void monitor(struct meter_status *ms) /* Called every interval for each meter */ { time_t t, nst,si; char *ts; int a,col, reachable, keepalive, s_statsreqd, i,j; unsigned long last_uptime, tb, tp; char fdfbuf[250], *fbp; struct flow_info *fp; unsigned int fi, t_count,x; struct display_data *ddp, *mdp; char buf[50], *bp; time(&t); ts = fmt_time(&t); if (!ms->write_OK) no_write_warning(ms); last_uptime = ms->uptime; s_statsreqd = ms->statsreqd; /* Save stats request through keepalive */ reachable = 1; if (meter_info(ms) == 0) { /* Lost contact */ if (ms->status & MT_UP) { /* Was up */ fprintf(stdout,"%s -- %s: No response\n", ts,ms->name); } ms->status &= ~MT_UP; /* Mark as 'down' */ reachable = 0; } else if (!(ms->status & MT_UP)) { /* Have contact now, was down */ fprintf(stdout,"%s -- %s: Regained contact\n", ts,ms->name); ms->write_OK = 1; ms->no_write_warned = 0; } ms->status |= MT_UP; ms->statsreqd = s_statsreqd; /* Restore stats request from rule file */ /* Meter processing .. */ if (reachable) { ts[8] = '\0'; /* Only want hh:mm:ss */ fprintf(stdout,"%s: %u flows, %u recovered, %u.%u%% idle\n", ts, ms->NbrFlows, ms->FlowsRecovered, ms->MinIdle1000/10,ms->MinIdle1000%10); } if (testing) printf("Sample: t=%u",ms->next_event); if (ms->synchronised) { nst = ms->next_sample + (si = ms->sample_interval); ms->next_sample = (nst / si) * si + ms->lag_seconds; } else ms->next_sample += ms->sample_interval; ms->next_event = ms->next_sample; if (testing) printf(", sync=%d, next_sample=%u, next_keepalive=%u\n", ms->synchronised, ms->next_sample, ms->next_keepalive); }