From 1d06320825d2a9e214cc324c2b2e833aba3edf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Thu, 15 Mar 2007 16:49:24 +0000 Subject: added the snmp-external (this has been lying on my harddisk for ages) svn path=/trunk/externals/iem/snmp/; revision=7492 --- Make.config.in | 31 +++++++ Makefile | 84 ++++++++++++++++++ TODO.txt | 20 +++++ configure.ac | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++ snmpget-help.pd | 25 ++++++ 6 files changed, 667 insertions(+) create mode 100644 Make.config.in create mode 100644 Makefile create mode 100644 TODO.txt create mode 100644 configure.ac create mode 100644 get.c create mode 100644 snmpget-help.pd diff --git a/Make.config.in b/Make.config.in new file mode 100644 index 0000000..42a0ed4 --- /dev/null +++ b/Make.config.in @@ -0,0 +1,31 @@ +LIBNAME=@LIBNAME@ + +# when build as a library this holds a pre-processor define +# (e.g. "-DBUILD_LIBRARY") +# when build as single externals this is empty +BUILDLIBRARY =@BUILDLIBRARY@ + +PREFIX =@prefix@@PDLIBDIR@ + +INSTALL_BIN=$(DESTDIR)$(PREFIX)/lib/pd/extra/$(LIBNAME) +INSTALL_DOC=$(DESTDIR)$(PREFIX)/lib/pd/@REFERENCEPATH@$(LIBNAME) + +EXT = @EXT@ +DEFS = @DFLAGS@ +IFLAGS = -I. @INCLUDES@ $(INCLUDES) +MAKEDEP_FLAGS = @MAKEDEP_FLAGS@ + +CC = @CC@ +LD = @LD@ +STRIP = @STRIP@ +STRIPFLAGS= @STRIPFLAGS@ + +AFLAGS = +LFLAGS = @LFLAGS@ +WFLAGS = + +TARNAME = $(LIBNAME).tgz + +CONFIGUREFLAGS = @CONFIGUREFLAGS@ +CFLAGS = $(DEFS) $(IFLAGS) $(BUILDLIBRARY) -DPD $(WFLAGS) @CFLAGS@ $(CFLAGS) +LIBS = @LIBS@ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..96f86a2 --- /dev/null +++ b/Makefile @@ -0,0 +1,84 @@ +default: all + +.PHONEY: default all everything dist \ + clean realclean distclean \ + install install-bin install-doc install-abs \ + tests + +HELPERSOURCES= +OBJECTSOURCES=$(sort $(filter-out $(HELPERSOURCES), $(filter %.c, $(wildcard *.c)))) +SOURCES=$(OBJECTSOURCES) $(HELPERSOURCES) + + +configure: configure.ac + autoconf + +-include $(SOURCES:.c=.d) + +Make.config: Make.config.in configure + ./configure $(CONFIGUREFLAGS) + +-include Make.config + + +## 2nd only generate depend-files when we have Make.config included +## and thus MAKEDEP_FLAGS defined +ifdef MAKEDEP_FLAGS +## dependencies: as proposed by the GNU-make documentation +## see http://www.gnu.org/software/make/manual/html_node/make_47.html#SEC51 +%.d: %.c + @set -e; rm -f $@; \ + $(CPP) $(MAKEDEP_FLAGS) $(Z_CFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ +endif + +.SUFFIXES: .$(EXT) + +TARGETS = $(SOURCES:.c=.o) + +OBJECTS = $(OBJECTSOURCES:.c=.$(EXT)) + + +## if $(BUILDLIBRARY) is defined, we build everything as a single library +## else we build separate externals +ifneq "$(BUILDLIBRARY)" "" +all: $(LIBNAME) + cp $(LIBNAME).$(EXT) .. +else +all: $(OBJECTS) +endif + +$(OBJECTS): %.$(EXT) : %.o + $(LD) $(LFLAGS) -o $@ $*.o $(LIBS) + $(STRIP) $(STRIPFLAGS) $@ + + +$(LIBNAME): $(TARGETS) + $(LD) $(LFLAGS) -o $@.$(EXT) *.o $(LIBS) + $(STRIP) $(STRIPFLAGS) $(LIBNAME).$(EXT) + +$(TARGETS): %.o : %.c + $(CC) $(Z_CFLAGS) -c -o $@ $*.c + +clean: + -rm -f *.$(EXT) *.o + +realclean: clean + -rm -f *~ _* config.* + -rm -f *.d *.d.* + +distclean: realclean + -rm -f Make.config ../*.$(EXT) + -rm -f *.exp *.lib *.ncb *.opt *.plg + -rm -rf autom4te.cache/ + +install: install-bin install-doc + +install-bin: + -install -d $(INSTALL_BIN) + -install -m 644 $(LIBNAME).$(EXT) $(INSTALL_BIN) + +install-doc: + +everything: clean all install distclean diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..bac0e61 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,20 @@ +SOONER: + get + walk + set + +LATER: + df + delta + table + status + +EVEN LATER: + bulkget + bulkwalk + delta + getnext + table + test + translate + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..4b752f7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,267 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(get.c) + +LIBNAME=snmp + + +dnl Checks for programs. +AC_PROG_CC + +AC_SUBST(STK) +AC_SUBST(DFLAGS) +AC_SUBST(LFLAGS) +AC_SUBST(EXT) +AC_SUBST(LD) +AC_SUBST(STRIP) +AC_SUBST(STRIPFLAGS) +AC_SUBST(IEMMATRIX_VERSION) +AC_SUBST(REFERENCEPATH) +AC_SUBST(PDLIBDIR) +AC_SUBST(INCLUDES) +AC_SUBST(LIBNAME) +AC_SUBST(CONFIGUREFLAGS) + +## store the flags passed to us +## is there no way to get the flags without quotes? +#CONFIGUREFLAGS=${ac_configure_args} +## and is this solution portable? time will show.... +CONFIGUREFLAGS=$(echo ${ac_configure_args} | sed "s/'//g") + + +AC_ARG_WITH(pdversion, [ --with-pdversion= enforce a certain pd-version (e.g. 0.37)]) +AC_ARG_WITH(extension, [ --with-extension= enforce a certain extension for the dynamic library (e.g. dll)]) +AC_ARG_WITH(pdpath, [ --with-pd= where to look for pd-headers and and -libs]) +AC_ARG_ENABLE(PIC, [ --disable-PIC disable compilation with PIC-flag]) + +dnl Checks for libraries. +dnl Replace `main' with a function in -lc: +AC_CHECK_LIB(c, main) +AC_CHECK_LIB(crtdll, fclose) + +dnl Replace `main' with a function in -lm: +AC_CHECK_LIB(m, main) +dnl Replace `main' with a function in -lpthread: +dnl AC_CHECK_LIB(pthread, main) +dnl Replace `main' with a function in -lstk: +dnl AC_CHECK_LIB(stk, main, STK=yes) + + +if test "x$with_pd" != "x"; then + if test -d "${with_pd}/src"; then + INCLUDES="-I${with_pd}/src ${INCLUDES}" + fi + if test -d "${with_pd}/bin"; then + LIBS="-L${with_pd}/bin ${LIBS}" + fi +fi + +if test "x$includedir" != "x"; then + for id in $includedir + do + if test -d $id; then INCLUDES="-I$id $INCLUDES"; fi + done +fi +if test "x$libdir" != "x"; then + for id in $libdir + do + if test -d $id; then LIBS="-L$id $LIBS"; fi + done +fi + +AC_CHECK_LIB(pd, nullfn) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(stdlib.h stdio.h string.h math.h time.h sys/time.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_TIME + +dnl Checks for library functions. +AC_FUNC_MMAP +AC_CHECK_FUNCS(select socket strerror) + + +### make-depend flags +if test "x$ac_cv_c_compiler_gnu" = "xyes"; then + AC_SUBST(MAKEDEP_FLAGS, "-MM") +else + AC_SUBST(MAKEDEP_FLAGS, "-M") +fi + +dnl check for "-mms-bitfields" cflag +dnl why is there no generic compiler-check for a given flag ? +dnl it would make things so easy: AC_CHECK_FLAG([-mms-bitfields],,) +AC_MSG_CHECKING("ms-bitfields") +cat > conftest.c << EOF +int main(){ + return 0; +} +EOF +if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -mms-bitfields > /dev/null 2>&1 +then + echo "yes" + CFLAGS="${CFLAGS} -mms-bitfields" +else + echo "no" +fi + + + + +dnl isn't there a better way to check for good linker/stripper ? + +dnl if we don't have $LD set, we set it to $(CC) +dnl LD=${LD:=$CC} +if test "x$LD" = "x" +then + if test "x$host" != "x" + then + LD=${host}-ld + if $(which ${LD} > /dev/null) + then + : + else + LD="" + fi + fi +fi +LD=${LD:=$CC} + +dnl if we don't have $STRIP set, we set it to ${host}-strip or strip +AC_CHECK_TOOL([STRIP], [strip], [true]) +AC_MSG_CHECKING([if strip is GNU strip]) +if $STRIP -V 2>&1 | grep GNU > /dev/null +then + AC_SUBST(STRIPFLAGS, "--strip-unneeded") + AC_MSG_RESULT([yes]) +else + AC_SUBST(STRIPFLAGS,"-x") + AC_MSG_RESULT([no]) +fi + +DFLAGS="" + + +if test "x$enable_PIC" != "xno"; then +AC_MSG_CHECKING("PIC") +cat > conftest.c << EOF +int main(){ + return 0; +} +EOF +if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -fPIC > /dev/null 2>&1 +then + echo "yes" + CFLAGS="${CFLAGS} -fPIC" +else + echo "no" +fi +fi + + +dnl +dnl OK, checks for machines are here now +dnl +if test `uname -s` = Linux; +then + LFLAGS="-export_dynamic -shared" + CFLAGS="$CFLAGS" + EXT=pd_linux +fi + +dnl This should use '-bundle_loader /path/to/pd/bin/pd' instead of'-undefined suppress' +dnl then strip might do something +if test `uname -s` = Darwin; +then + LD=cc + LFLAGS="-bundle -undefined suppress -flat_namespace" + EXT=pd_darwin +fi + +if test `uname | sed -e 's/^MINGW.*/NT/'` = NT; +then + LD=gcc + INCLUDES="-I@prefix@/src" + DFLAGS="-D__WIN32__" + LFLAGS="-shared @prefix@/bin/pd.dll" + EXT=dll +else + PDLIBDIR="/lib/pd" +fi + +if test `uname -s` = IRIX64; +then + LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -shared -rdata_shared" + EXT=pd_irix6 + dnl DFLAGS="-DUNIX -DIRIX6" +fi + +if test `uname -s` = IRIX32; +then + LFLAGS="-o32 -DUNIX -DIRIX -O2 + -shared -rdata_shared" + EXT=pd_irix5 + dnl DFLAGS="-DUNIX -DIRIX5" +fi + + +if test "x$with_extension" != "x" +then + EXT=$with_extension +fi + + +dnl Checks for pd-version, to set the correct help-path +AC_MSG_CHECKING("pd\>=0.37") + +if test "$with_pdversion" != "" +then +echo -n "($with_pdversion)... " + PD_VERSION="$with_pdversion" +else +if test "x$cross_compiling" = "xno" +then + +cat > conftest.c << EOF +#include +#include "m_pd.h" +int main(){ + printf("%d.%d\n", PD_MAJOR_VERSION, PD_MINOR_VERSION); + return 0; +} +EOF + + if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1 + then + PD_VERSION=`./conftest.o` + else + PD_VERSION="" + fi + echo -n $PD_VERSION +else +dnl we are cross-compiling... + echo -n "(X)..." + PD_VERSION="0.38" +fi +fi + +let PD_MAJORVERSION=`echo $PD_VERSION | cut -d"." -f1`+0 +let PD_MINORVERSION=`echo $PD_VERSION | cut -d"." -f2`+0 + + + +if test "$PD_MAJORVERSION" -gt 0 || test "$PD_MINORVERSION" -ge 37 +then + REFERENCEPATH=extra/ + echo " yes" +else + REFERENCEPATH=doc/5.reference/ + echo " no" +fi + +AC_OUTPUT(Make.config) + +rm -f conftest.* diff --git a/get.c b/get.c new file mode 100644 index 0000000..ee2c873 --- /dev/null +++ b/get.c @@ -0,0 +1,240 @@ +/****************************************************** + * + * snmp/get - implementation file + * + * copyleft (c) IOhannes m zmölnig + * + * 2006:forum::für::umläute:2006 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +/* 2402:forum::für::umläute:2006 */ + +#include +#include +#include + +#include "m_pd.h" + +/* ------------------------- snmpget ------------------------------- */ + +static t_class *snmpget_class; + +typedef struct _snmpget +{ + t_object x_obj; + + netsnmp_session*x_session; + + t_outlet*out_data, *out_err; + int x_raw; /* if set, the raw string is output; no interpretation is done */ +} t_snmpget; + +static void snmpget_get(t_snmpget *x, t_symbol *s) +{ + if(NULL!=x->x_session){ + oid name[MAX_OID_LEN]; + size_t name_length=MAX_OID_LEN; + netsnmp_variable_list *vars; + netsnmp_pdu *pdu,*response; + int err=0; + char*symname=s->s_name; + + if(!snmp_parse_oid(symname, name, &name_length)){ + error("snmpget: bad OID %d", name_length); + snmp_perror(symname); + return; + } + pdu = snmp_pdu_create(SNMP_MSG_GET); + snmp_add_null_var(pdu, name, name_length); + err=snmp_synch_response(x->x_session, pdu, &response); + if(STAT_SUCCESS == err){ + if(SNMP_ERR_NOERROR == response->errstat){ + for (vars = response->variables; vars; + vars = vars->next_variable) { + char mybuf[MAXPDSTRING]; + t_binbuf *bbuf = binbuf_new(); + int type=vars->type; + //print_variable(vars->name, vars->name_length, vars); + //print_value(vars->name, vars->name_length, vars); + /* + INTEGER = 2 + Counter32 = 65 + Gauge32 = 66 + + Hex-STRING = 4 + STRING = 4 + + IpAddress = 64 + Network Address: 64 + + OID = 6 + Timeticks = 67 + */ + //post("type: %d", vars->type); + if(0==x->x_raw) { + switch(type) { + case ASN_TIMETICKS: + case ASN_GAUGE: case ASN_COUNTER: + case ASN_INTEGER: + { + long v=(long)(*vars->val.integer); + outlet_float(x->out_data, (t_float)v); + } + break; + /* + case ASN_OCTET_STR: + { + outlet_symbol(x->out_data, gensym(vars->val.string)); + } + break; + */ + default: + snprint_value(mybuf, sizeof(mybuf), vars->name, vars->name_length, vars); + binbuf_text(bbuf, mybuf, strlen(mybuf)); + int ac=binbuf_getnatom(bbuf); + t_atom*av=binbuf_getvec(bbuf); + outlet_list(x->out_data, + gensym("list"), + ac, av); + } + } else { + t_atom atm, *ap; + ap=&atm; + snprint_value(mybuf, sizeof(mybuf), vars->name, vars->name_length, vars); + SETSYMBOL(ap, gensym(mybuf)); + outlet_anything(x->out_data, gensym("raw"), 1, ap); + } + if(bbuf)binbuf_free(bbuf); + } + } + } else { + error("[snmp/get] error while synching"); + } + snmp_free_pdu(response); + } else { + pd_error(x, "[snmp/get] not connected"); + } +} + + + +/* + connect [:] +*/ +static void snmpget_connect(t_snmpget *x, t_symbol *hostport, t_symbol*comm) +{ + if(x->x_session==NULL) { + SOCK_STARTUP; + netsnmp_session session; + + int len=0; + char*cdummy; + + char*peername=0; + int peerport=-1; + + char*community=0; + + if(0!=comm && &s_!=comm) + community=comm->s_name; + + for(cdummy=hostport->s_name; *cdummy!=0 && *cdummy!=':'; cdummy++, len++); + + if(*cdummy==':') { + // there is a port hidden in this string! + peerport=(int)strtol(cdummy+1, (char **)NULL, 10); + } + + peername=(char*)getbytes(sizeof(char)*len+1); + strncpy(peername, hostport->s_name, len); + peername[len]=0; + snmp_sess_init(&session); + + session.version=SNMP_VERSION_1; + session.peername=peername; + + if(peerport>0 && peerport<65536) { + session.remote_port=peerport; + } + + if(0!=community) { + session.community=(unsigned char*)community; + session.community_len=strlen(community); + } + x->x_session = snmp_open(&session); + freebytes(peername, len); + + if(x->x_session==NULL){ + SOCK_CLEANUP; + outlet_float(x->out_err, 0); + return; + } + } else { + pd_error(x, "[snmp/get] already connected"); + } + outlet_float(x->out_err, 1); +} +static void snmpget_dodisconnect(t_snmpget *x) +{ + if(x->x_session){ + snmp_close(x->x_session); + SOCK_CLEANUP; + } + x->x_session=NULL; + outlet_float(x->out_err, 0); +} +static void snmpget_disconnect(t_snmpget *x) { + if(x->x_session) + snmpget_dodisconnect(x); + else + pd_error(x, "[snmp/get] not connected!"); +} + +static void snmpget_raw(t_snmpget *x, t_float f) { + int i=(int)f; + x->x_raw=(i>0); +} + +static void *snmpget_free(t_snmpget *x) +{ + snmpget_disconnect(x); + outlet_free(x->out_err); + outlet_free(x->out_data); +} + +static void *snmpget_new(t_symbol*s, int argc, t_atom*argv) +{ + t_snmpget *x = (t_snmpget *)pd_new(snmpget_class); + + x->out_data=outlet_new(&x->x_obj, 0); + x->out_err=outlet_new(&x->x_obj, &s_float); + + x->x_session=0; + x->x_raw=0; + + return (x); +} + +void snmpget_setup(void) +{ + init_snmp("snmp4pd"); + + snmpget_class = class_new(gensym("snmpget"), (t_newmethod)snmpget_new, + 0, sizeof(t_snmpget), 0, A_GIMME, 0); + class_addmethod(snmpget_class, (t_method)snmpget_get, gensym("get"), A_SYMBOL, 0); + class_addmethod(snmpget_class, (t_method)snmpget_connect, gensym("connect"), A_SYMBOL, A_DEFSYM, 0); + class_addmethod(snmpget_class, (t_method)snmpget_disconnect, gensym("disconnect"), 0); + class_addmethod(snmpget_class, (t_method)snmpget_raw, gensym("raw"), A_FLOAT, 0); +} + +void get_setup(void) +{ + snmpget_setup(); +} diff --git a/snmpget-help.pd b/snmpget-help.pd new file mode 100644 index 0000000..895f001 --- /dev/null +++ b/snmpget-help.pd @@ -0,0 +1,25 @@ +#N canvas 0 0 849 365 10; +#X msg 121 92 connect; +#X obj 100 125 snmpget; +#X msg 152 159 disconnect; +#X msg 208 99 get system; +#X msg 47 55 get; +#X msg 185 128 get SNMPv2-MIB::system.sysUpTime.0; +#X obj 158 65 t b b; +#X msg 157 38 bang; +#X obj 65 210 print result; +#X msg 223 75 get bibabo; +#X msg 248 173 get SNMPv2-MIB::system.sysDescr.0; +#X msg 251 200 get system.sysDescr.0; +#X connect 0 0 1 0; +#X connect 1 0 8 0; +#X connect 2 0 1 0; +#X connect 3 0 1 0; +#X connect 4 0 1 0; +#X connect 5 0 1 0; +#X connect 6 0 5 0; +#X connect 6 1 0 0; +#X connect 7 0 6 0; +#X connect 9 0 1 0; +#X connect 10 0 1 0; +#X connect 11 0 1 0; -- cgit v1.2.1