/* * traptime.c - It is an example of how to modify snmptrapd to * measure the time and reliability of the trap system. * * Modified from the Carnegie Mellon University * snmpd. * E. Pasqualucci 7-11-1996 * */ /* Standard include files */ #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <sys/time.h> #include <sys/socket.h> #include <net/if.h> #include <sys/ioctl.h> #include <sys/file.h> #include <nlist.h> #include <errno.h> #include <syslog.h> /* SNMP standard include files */ #include "compat.h" #include "snmp.h" #include "asn1.h" #include "snmp_impl.h" #include "snmp_api.h" #include "snmp_client.h" #include "party.h" #include "context.h" #include "view.h" #include "acl.h" /* Other definitions */ #define NUM_NETWORKS 16 /* max number of interfaces to check */ #ifndef IFF_LOOPBACK #define IFF_LOOPBACK 0 #endif #define LOOPBACK 0x7f000001 /* Specific include files */ #include "traptime_protos.h" #include "traptime.h" /* Global variables */ int nrec = 0; int nsend = 0; int nerror = 0; int nlast = 10000; extern int errno; int snmp_dump_packet = 0; int Print = 0; char default_community[] = "public"; char description[] = "0"; char *gateway = NULL; char *community = default_community; struct snmp_session *ss; struct snmp_session *send_ss; struct snmp_pdu *send_pdu; oid objid_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; oid objid_sysdescr[] = {1, 3, 6, 1, 2, 1, 1, 1, 0}; struct timeval t0, t1; char *traptime_trap_description (int trap) { switch(trap){ case SNMP_TRAP_COLDSTART: return "Cold Start"; case SNMP_TRAP_WARMSTART: return "Warm Start"; case SNMP_TRAP_LINKDOWN: return "Link Down"; case SNMP_TRAP_LINKUP: return "Link Up"; case SNMP_TRAP_AUTHFAIL: return "Authentication Failure"; case SNMP_TRAP_EGPNEIGHBORLOSS: return "EGP Neighbor Loss"; case SNMP_TRAP_ENTERPRISESPECIFIC: return "Enterprise Specific"; default: return "Unknown Type"; } } char *uptime_string(register u_int timeticks, char *buf) { int seconds, minutes, hours, days; timeticks /= 100; days = timeticks / (60 * 60 * 24); timeticks %= (60 * 60 * 24); hours = timeticks / (60 * 60); timeticks %= (60 * 60); minutes = timeticks / 60; seconds = timeticks % 60; if (days == 0){ sprintf(buf, "%d:%02d:%02d", hours, minutes, seconds); } else if (days == 1) { sprintf(buf, "%d day, %d:%02d:%02d", days, hours, minutes, seconds); } else { sprintf(buf, "%d days, %d:%02d:%02d", days, hours, minutes, seconds); } return buf; } void traptime_exit (void) { struct timeval tdiff; gettimeofday (&t1, (struct timezone *) 0); printf (" nrec %d nsend %d nerror %d\n", nrec, nsend, nerror); snmp_close (ss); snmp_close (send_ss); printf (" time needed = %d sec %d usec\n", t1.tv_sec-t0.tv_sec, t1.tv_usec-t0.tv_usec); exit (1); } int traptime_input (int op, struct snmp_session *session, int reqid, struct snmp_pdu *pdu, void *magic) { struct variable_list *vars; char buf[TRAPTIME_MAXBUFLEN]; static int flag = 0; if (!flag) { gettimeofday (&t0, (struct timezone *) 0); ++flag; } if (op == RECEIVED_MESSAGE && pdu->command == TRP_REQ_MSG) { if (Print) { printf("%s: %s Trap (%d) Uptime: %s\n", inet_ntoa(pdu->agent_addr.sin_addr), traptime_trap_description(pdu->trap_type), pdu->specific_type, uptime_string(pdu->time, buf)); for(vars = pdu->variables; vars; vars = vars->next_variable) print_variable(vars->name, vars->name_length, vars); } #ifndef __Lynx__ else { syslog(LOG_WARNING, "%s: %s Trap (%d) Uptime: %s\n", inet_ntoa(pdu->agent_addr.sin_addr), traptime_trap_description(pdu->trap_type), pdu->specific_type, uptime_string(pdu->time, buf)); } #endif ++nrec; if (snmp_send(send_ss, send_pdu)== 0) ++nerror; else ++nsend; } else if (op == TIMED_OUT) { printf("Timeout: This shouldn't happen!\n"); } if (nrec == nlast) traptime_exit (); } void init_syslog (void) { #ifndef __Lynx__ /* * These definitions handle 4.2 systems without additional syslog facilities. */ #ifndef LOG_CONS #define LOG_CONS 0 /* Don't bother if not defined... */ #endif #ifndef LOG_LOCAL0 #define LOG_LOCAL0 0 #endif /* * All messages will be logged to the local0 facility and will be sent to * the console if syslog doesn't work. */ openlog("snmptrapd", LOG_CONS, LOG_LOCAL0); syslog(LOG_INFO, "Starting snmptrapd"); #endif } void usage (void) { printf("Usage: traptime [-p] [-d] -g gateway [-c community] [-n number]\n"); } void init_options (int argc, char **argv) { int arg; for(arg = 1; arg < argc; arg++) if (argv[arg][0] == '-') { switch(argv[arg][1]) { case 'd': snmp_dump_packet++; break; case 'p': Print++; break; case 'g': gateway = argv[++arg]; break; case 'c': community = argv[++arg]; break; case 'n': nlast = atoi(argv[++arg]); break; default: printf("invalid option: -%c\n", argv[arg][1]); usage (); break; } } } struct snmp_session *traptime_init_snmp_trap_session (void) { struct snmp_session send_session; struct snmp_session session, *traptime_ss; bzero((char *)&session, sizeof(struct snmp_session)); session.peername = NULL; session.community = NULL; session.community_len = 0; session.retries = SNMP_DEFAULT_RETRIES; session.timeout = SNMP_DEFAULT_TIMEOUT; session.authenticator = NULL; session.callback = traptime_input; session.callback_magic = NULL; session.local_port = TRAPTIME_PORT; traptime_ss = snmp_open(&session); bzero((char *)&send_session, sizeof(struct snmp_session)); send_session.peername = gateway; send_session.community = (u_char *)community; send_session.community_len = strlen(community); send_session.retries = SNMP_DEFAULT_RETRIES; send_session.timeout = SNMP_DEFAULT_TIMEOUT; send_session.authenticator = NULL; send_session.callback = NULL; send_session.callback_magic = NULL; send_session.remote_port = TRAPTIME_PORT; send_ss = snmp_open(&send_session); if (send_ss == NULL){ printf("Couldn't open snmp to send traps\n"); exit(-1); } return traptime_ss; } int get_myaddr (void) { int sd; struct ifconf ifc; struct ifreq conf[NUM_NETWORKS], *ifrp, ifreq; struct sockaddr_in *in_addr; int count; int interfaces; /* number of interfaces returned by ioctl */ if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return 0; ifc.ifc_len = sizeof(conf); ifc.ifc_buf = (caddr_t)conf; if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0){ close(sd); return 0; } ifrp = ifc.ifc_req; interfaces = ifc.ifc_len / sizeof(struct ifreq); for(count = 0; count < interfaces; count++, ifrp++){ ifreq = *ifrp; if (ioctl(sd, SIOCGIFFLAGS, (char *)&ifreq) < 0) continue; in_addr = (struct sockaddr_in *)&ifrp->ifr_addr; if ((ifreq.ifr_flags & IFF_UP) && (ifreq.ifr_flags & IFF_RUNNING) && !(ifreq.ifr_flags & IFF_LOOPBACK) && in_addr->sin_addr.s_addr != LOOPBACK){ close(sd); return in_addr->sin_addr.s_addr; } } close(sd); return 0; } void init_send_pdu (void) { struct variable_list *vars; send_pdu = snmp_pdu_create(TRP_REQ_MSG); send_pdu->enterprise = (oid *)malloc(sizeof(objid_enterprise)); bcopy((char *)objid_enterprise, (char *)send_pdu->enterprise, sizeof(objid_enterprise)); send_pdu->enterprise_length = sizeof(objid_enterprise) / sizeof(oid); send_pdu->agent_addr.sin_addr.s_addr = get_myaddr(); send_pdu->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC; send_pdu->specific_type = 0; send_pdu->time = 0; send_pdu->variables = vars = (struct variable_list *)malloc(sizeof(struct variable_list)); vars->next_variable = NULL; vars->name = (oid *)malloc(sizeof(objid_sysdescr)); bcopy((char *)objid_sysdescr, (char *)vars->name, sizeof(objid_sysdescr)); vars->name_length = sizeof(objid_sysdescr) / sizeof(oid); vars->type = ASN_OCTET_STR; vars->val.string = (u_char *)malloc(strlen(description) + 1); strcpy((char *)vars->val.string, description); vars->val_len = strlen(description); } void traptime_init (int argc, char **argv) { init_syslog(); init_mib(); init_options (argc, argv); if ((ss = traptime_init_snmp_trap_session()) == NULL) { printf("Couldn't open snmp\n"); exit(-1); } init_send_pdu(); } int traptime_main_loop (void) { int count, numfds, block; fd_set fdset; struct timeval timeout, *tvp; while (1) { numfds = 0; FD_ZERO(&fdset); block = 1; tvp = &timeout; timerclear(tvp); snmp_select_info(&numfds, &fdset, tvp, &block); if (block == 1) tvp = NULL; /* block without timeout */ #if defined (_HPUX_SOURCE) && defined (V9) count = select (numfds, (int *) &fdset, 0, 0, tvp); #else count = select (numfds, &fdset, 0, 0, tvp); #endif if (count > 0) snmp_read(&fdset); else switch(count) { case 0: snmp_timeout(); break; case -1: if (errno != EINTR) perror("select"); return -1; default: printf("select returned %d\n", count); return -1; } } } main (int argc, char **argv) { traptime_init (argc, argv); traptime_main_loop(); }