I've written a traphandler in C that is executed by snmptrapd when a
trap comes in.  snmptrapd spits out all information via STDOUT.  Is
there a way to get the actual data instead of the ASCII version of the
trap.  I would like to use the net-snmp libraries in my traphandler to
parse the data instead of using string functions.   Should I deprecate
use of snmptrapd and simply write a daemon that listens for the UDP trap
then it uses the net-snmp libraries to parse the data out of that trap?

Here is the trap handler code.  It simply expects that the output of the
snmptrapd program be of a certain type.  Don't let the code confuse
you.  It simply sends the trap to a remote server via TCP and the data
is in XML format.  I want to keep the XML stuff and transmission to the
remote agent but I'm not sure if I'm parsing correctly.  It works on our
device's mibs but other people's mibs may be different.  In our device
we simply send a trap with one variable and one value.  So if there is a
device that sends multiple variables this code will only catch the first
variable.  That needs to be fixed. 







/* $Id: traphandle.c,v 1.3 2004/10/14 19:33:50 cfowler Exp $ */

/**
 * Traphandle
 *
 * Program is called by snmptrapd on reception of
 * trap.  It will then parse it into an XML message
 * for sending to SAM
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "config.h"
#include "libobj.h"
#include "ops.h"

#define RETRY_INTERVAL 120 /* Seconds between AMAD connection retries */


static void
sig(int s) {
	switch(s) {
		case SIGSEGV:
			log_info("recevied SIGSEGV!\n");
			exit(0);
		default:
			break;
	}

	signal(s, sig);
}

/**
 * Function will send our message to another host via UDP
 * This is transmit and pray only
 */
static int
send_udp_msg(const char *data, size_t len, const char *host, int port) {
	int s;
	struct sockaddr_in sin ;

	if((s =  socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		return -1;
	} 

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = inet_addr(host);
	sendto(s, data, len, MSG_DONTWAIT, (struct sockaddr *)&sin, sizeof(sin));

	close(s);
	return 0;
}

static void
release_parent(void) {
	pid_t pid;

	switch((pid = fork())) {
		case -1: exit(1);
		case 0: break;
		default: exit(0);
	}

	return;
}

 
static int
get_date(void) {
	time_t t = time(NULL);
	return t;
}

static void
amad_response(const char *msg) {
	log_info("GOT: %s", msg);
}

static void
log_trap(OBJ_STRING *str) {
	FILE *fp;
	char *copy = strdup(obj_String_getText(str));
	char *hName, *ip, *data, *uptime, *ptr, *type, *varN, *varV;
	char *template = strdup("/var/spool/traps/SNMP.XXXXXX");
	int f;
	struct config *cfgptr;
	OBJ_STRING *xml = NULL;
	char my_host[128];
	int c = 1;


	gethostname(my_host, sizeof(my_host));
	
	if((f = mkstemp(template)) == -1) {
		log_err("Could not create spool file.\n");
	}

	if((hName = strtok(copy, "\n")) == NULL) {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((ip = strtok(NULL, "\n")) == NULL) {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((ptr = strtok(NULL, "\n")) == NULL) {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((ptr = strchr(ptr, ' ')) != NULL) {
		ptr++;
		uptime = ptr;
	} else {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((ptr = strtok(NULL, "\n")) == NULL) {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((ptr = strchr(ptr, ' ')) != NULL) {
		ptr++;
		type = ptr;
	} else {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((varN = strtok(NULL, "\n")) == NULL) {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((ptr = strchr(varN, ' ')) != NULL) {
		*ptr++ = 0;
		varV = ptr;
	} else {
		log_info("Invalid SNMP trap format received!");
		free(copy);
		return;
	}

	if((cfgptr = getcfgptr(false)) == NULL ) {
		return;
	}
	
	/*
	 * Bild the XML trap
	 */
	xml = obj_String_new_01("<alarm ens=\"%s\">\r\n", my_host);
	obj_String_append_01(xml, " <snmp date=\"%d\" host=\"%s\" ip=\"%s\">\r\n", get_date(), hName, ip);
	obj_String_append_01(xml, "  <uptime>%s</uptime>\r\n", uptime);
	obj_String_append_01(xml, "  <name>%s</name>\r\n", type);
	obj_String_append_01(xml, "  <var id=\"%d\" name=\"%s\" val=\"%s\"/>\r\n", c, varN, varV);
	obj_String_append_01(xml, " </snmp>\r\n");
	obj_String_append_01(xml, "</alarm>\r\n");

	while(1) {

		/*
		 * Make our initial SAM connection
		 */
		if((fp = sam_open(&cfgptr->ama, 5)) == NULL) {
			log_info("Failed to connect to SAM server. Will retry in %d seconds.\n", RETRY_INTERVAL);
			sleep(RETRY_INTERVAL);
			continue;
		}

		/*
		 * Login to AMAD server
		 */
		if(sam_login(fp, &cfgptr->ama) != 0) {
			fclose(fp);
			log_info("Failed to login to SAM server. Will retry in %d seconds.\n", RETRY_INTERVAL);
			sleep(RETRY_INTERVAL);
			continue;
		}

		if(sam_cmd_response(fp, amad_response, "alrm\r\n") != 220)	{
			fclose(fp);
			log_info("Failed to get a response to the alarm command. Will retry in %d seconds.\n", RETRY_INTERVAL);
			sleep(RETRY_INTERVAL);
			continue;
		}

		fputs(obj_String_getText(xml), fp);
		sam_cmd_response(fp, amad_response, ".\r\n");
		sam_cmd_response(fp, amad_response, "quit\r\n");
		break;
	}


	relcfgptr(cfgptr);
	obj_String_delete(xml);
	free(copy);

	return;
}

int
traphandle(int argc, char **argv) {
	char buffer[1024];
	OBJ_STRING *str = NULL;
	struct config *cfgptr = NULL;


	signal(SIGSEGV, sig);

	if((cfgptr = getcfgptr(false)) == NULL) {
		log_info("could not get config!\n");
		exit(1);
	}

	/*
	 * Validate we are to forward to SAM
	 */
	if(IS_SNMP_FORWARD_SAM(cfgptr->snmp.flags) != 1) {
		return 0;
	}

	/*
	 * Validate we have a sam server ocnfigured
	 */
	if(cfgptr->ama.server == 0) {
		return 0;
	}

	log_info("Received trap");

	while(!feof(stdin)) {
		fgets(buffer, sizeof(buffer), stdin);
		if(str == NULL) {
			str = obj_String_new(buffer);
		} else {
			obj_String_append(str, buffer);
		}
	}

	/*
	 * Do not let sbnmptrapd block while we process
	 * this data.  Release it to respond to other traps
	 */
	release_parent();
	log_trap(str);
	return 0;
}

/* vi: set ts=2 sw=2: */

Reply via email to