/* * Compare two cells * * Return: * -3 c1<c2 because c1 is not recognized and c2 is string * -2 c1<c2 because c1 is number and c2 isn't * -1 c1<c2 * 0 c1=c2 string=string, number=number, or both have unrecognized types * 1 c1>c2 * 2 c1>c2 because c1 is string and c2 isn't * 3 c1>c2 because c1 is not recognized and c2 is number */ static int treeCompare(nbCELL context,nbCELL c1,nbCELL c2){ int c1Type,c2Type; char *c1Str,*c2Str; double c1Real,c2Real; c1Type=nbCellGetType(context,c1); c2Type=nbCellGetType(context,c2); if(c1Type==NB_TYPE_STRING){ if(c2Type==NB_TYPE_STRING){ c1Str=nbCellGetString(context,c1); c2Str=nbCellGetString(context,c2); return(strcmp(c1Str,c2Str)); } else return(2); } else if(c1Type==NB_TYPE_REAL){ if(c2Type==NB_TYPE_REAL){ c1Real=nbCellGetReal(context,c1); c2Real=nbCellGetReal(context,c2); if(c1Real<c2Real) return(-1); else if(c1Real==c2Real) return(0); else return(1); } else return(-2); } else{ if(c2Type==NB_TYPE_STRING) return(3); else if(c2Type==NB_TYPE_REAL) return(-3); else return(0); } }
static void baselineAlert(nbCELL context,BTreeSkill *skillHandle,BTree *tree,BTreeNode *node,nbCELL element[],int qualifiers,double deviation){ char cmd[1024]; char *cmdcur; int i; double limit,threshold; //nbLogMsg(context,0,'T',"baselineAlert called with qualifiers=%d threshold=%g",qualifiers,deviation); strcpy(cmd,"alert _measure=\""); cmdcur=cmd+strlen(cmd); // 2012-01-14 eat - VI 850-0.8.13-3 FP replaced strchr(cmdcur,0) with cmd+strlen(cmd) for(i=0;i<qualifiers;i++){ switch(nbCellGetType(context,element[i])){ case NB_TYPE_STRING: sprintf(cmdcur,"%s.",nbCellGetString(context,element[i])); break; case NB_TYPE_REAL: sprintf(cmdcur,"%f.",nbCellGetReal(context,element[i])); break; default: strcpy(cmdcur,"?."); } cmdcur+=strlen(cmdcur); // 2012-01-14 eat - VID 857-0.8.13-3 FP replaced strchr(cmdcur,0) with +=strlen(cmdcur) } if(*(cmdcur-1)=='.') cmdcur--; if(node->value<node->average) limit=node->average-node->threshold; else limit=node->average+node->threshold; node->level++; if(node->threshold<=0) return; // make sure we don't loop here while((threshold=node->threshold*2) && deviation>threshold) node->level++,node->threshold=threshold; sprintf(cmdcur,"\",_value=%.10g,_average=%.10g,_sigma=%.10g,_deviation=%.10g,_threshold=%.10g,_limit=%.10g,_level=%d;",node->value,node->average,node->deviation*1.25,deviation,node->threshold,limit,node->level); nbActionCmd(context,cmd,0); node->threshold=threshold; }
/* * construct() method * * define <term> node <skill>[("<ident>")][:<text>] * * <ident> - name of translator file * <text> - flag keywords * trace - display input packets * dump - display dump of syslog packets * silent - don't echo generated NodeBrain commands * * define logger node syslog.logger("foobar"); */ void *loggerConstruct(nbCELL context,void *skillHandle,nbCELL arglist,char *text){ NB_MOD_Logger *logger; nbCELL cell=NULL; nbSET argSet; char *cursor=text,*delim,saveDelim; int trace=0,dump=0,echo=1; char *ident="nodebrain"; argSet=nbListOpen(context,arglist); cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ if(nbCellGetType(context,cell)!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"First argument must be string message identifier"); return(NULL); } ident=strdup(nbCellGetString(context,cell)); if(!ident) nbExit("loggerConstruct: out of memory"); // 2013-01-17 eat - VID 6546 } cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ nbLogMsg(context,0,'E',"The syslog.logger skill only accepts one argument."); return(NULL); } while(*cursor==' ') cursor++; while(*cursor!=';' && *cursor!=0){ delim=strchr(cursor,' '); if(delim==NULL) delim=strchr(cursor,','); if(delim==NULL) delim=strchr(cursor,';'); if(delim==NULL) delim=cursor+strlen(cursor); saveDelim=*delim; *delim=0; if(strcmp(cursor,"trace")==0){trace=1;} else if(strcmp(cursor,"dump")==0){trace=1;dump=1;} else if(strcmp(cursor,"silent")==0) echo=0; *delim=saveDelim; cursor=delim; if(*cursor==',') cursor++; while(*cursor==' ' || *cursor==',') cursor++; } logger=nbAlloc(sizeof(NB_MOD_Logger)); logger->ident=ident; logger->trace=trace; logger->dump=dump; logger->echo=echo; openlog(logger->ident,LOG_PID,LOG_LOCAL0); return(logger); }
/* * Convert cell value to cell expression * NOTE: This should be a part of the NodeBrain API */ static int treeStoreValue(nbCELL context,nbCELL cell,char *cursor,size_t len){ int cellType,n=-1; double real; char *string; if(cell==NB_CELL_UNKNOWN){ n=snprintf(cursor,len,"%s","?"); } else{ cellType=nbCellGetType(context,cell); if(cellType==NB_TYPE_STRING){ string=nbCellGetString(context,cell); n=snprintf(cursor,len,"\"%s\"",string); // 2013-01-14 eat - VID 4200-0.8.13-3 } else if(cellType==NB_TYPE_REAL){ real=nbCellGetReal(context,cell); n=snprintf(cursor,len,"%.10g",real); } } if(n>=len) return(-1); return(n); }
/* * construct() method * * define <term> node <skill>[(<args>)][:<text>] * * <args> - port_number or "interface_address[:port_number]" * <text> - flag keywords * trace - display input packets * dump - display dump of SNMP UDP packets * silent - don't echo generated NodeBrain commands * * define snmptrap node snmptrap; * define snmptrap node snmptrap:dump,silent; * define snmptrap node snmptrap("127.0.0.1"); * define snmptrap node snmptrap(50162); * define snmptrap node snmptrap("127.0.0.1:50162"); * define snmptrap node snmptrap("127.0.0.1:50162"):silent; */ static void *serverConstruct(nbCELL context,void *skillHandle,nbCELL arglist,char *text){ NB_MOD_Snmptrap *snmptrap; nbCELL cell=NULL; nbSET argSet; char *cursor=text,*delim,saveDelim; double r,d; char interfaceAddr[16]; unsigned int port=162; int type,trace=0,dump=0,echo=1; int len; char *str; *interfaceAddr=0; argSet=nbListOpen(context,arglist); cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ type=nbCellGetType(context,cell); if(type==NB_TYPE_STRING){ str=nbCellGetString(context,cell); delim=strchr(str,':'); if(delim==NULL) len=strlen(str); else len=delim-str; if(len>15){ nbLogMsg(context,0,'E',"Inteface IP address may not be greater than 15 characters"); nbCellDrop(context,cell); return(NULL); } strncpy(interfaceAddr,str,len); *(interfaceAddr+len)=0; if(delim!=NULL){ delim++; port=(unsigned int)atoi(delim); } nbCellDrop(context,cell); } else if(type==NB_TYPE_REAL){ r=nbCellGetReal(context,cell); nbCellDrop(context,cell); port=(unsigned int)r; d=port; if(d!=r || d==0){ nbLogMsg(context,0,'E',"Expecting non-zero integer UDP port number"); return(NULL); } } else{ nbLogMsg(context,0,'E',"Expecting interface (\"address[:port]\") or (port) as argument list"); return(NULL); } cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ nbLogMsg(context,0,'E',"Only one argument expected - ignoring additional arguments"); nbCellDrop(context,cell); } } if(*text!=0){ cursor=text; while(*cursor==' ') cursor++; while(*cursor!=';' && *cursor!=0){ delim=strchr(cursor,' '); if(delim==NULL) delim=strchr(cursor,','); if(delim==NULL) delim=strchr(cursor,';'); if(delim==NULL) delim=cursor+strlen(cursor); // 2013-01-14 eat - VID 969-0.8.13-3 FP but replaced strchr(cursor,0) saveDelim=*delim; *delim=0; if(strcmp(cursor,"trace")==0){trace=1;} else if(strcmp(cursor,"dump")==0){trace=1;dump=1;} else if(strcmp(cursor,"silent")==0) echo=0; *delim=saveDelim; cursor=delim; if(*cursor==',') cursor++; while(*cursor==' ') cursor++; } } snmptrap=nbAlloc(sizeof(NB_MOD_Snmptrap)); snmptrap->socket=0; strcpy(snmptrap->interfaceAddr,interfaceAddr); snmptrap->port=port; snmptrap->trace=trace; snmptrap->dump=dump; snmptrap->echo=echo; snmptrap->handlerContext=NULL; snmptrap->syntaxContext=NULL; snmptrap->attributeContext=NULL; nbListenerEnableOnDaemon(context); // sign up to enable when we daemonize return(snmptrap); }
/* * Translate an SNMP V1 or V2 Trap to a NodeBrain ALERT command * * alert '<oid>'=<value>,...; * * Here's an example of a full alert with a single <variable-binding>. * * *** include example here *** */ static char *translate(NB_MOD_Snmptrap *snmptrap,unsigned char *buf,int len,char *cmd,int cmdlen,char **handlerNameP){ char *cmdcur=cmd; char *cmdend=cmdcur+cmdlen; unsigned char *cursor=buf; unsigned char *bufend=buf+len; unsigned char *enterpriseOid; int objlen,generic; char *msg,version,senderAddr[40]; char trapOID[64],*trapOIDCur; // value of '1.3.6.1.6.3.1.1.4.1.0' (SNMP_TRAP_OID) //char *handler; nbCELL cell; char *oid,*value,*syntax,*attribute; fprintf(stderr,"translate: called\n"); fflush(stderr); *trapOID=0; if(*cursor!=0x30) return("packet not recognized"); cursor++; objlen=getObjectLength(&cursor,bufend); if(objlen<0) return("trap length error"); if(*cursor!=0x02 || *(cursor+1)!=0x01) return("expecting 02.01 to start trap"); cursor+=2; version=*cursor; cursor++; sprintf(cmdcur,"alert '1.3.6.1.6.3.18.1.4'="); // snmpTrapCommunity OID cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 976-0.8.13-3 FP but replaced strchr(cmdcur,0) if(*cursor!=0x04) return("expecting type 04 (string) for community string"); if(NULL!=(msg=translateValue(&cursor,bufend,&cmdcur,cmdend,""))) return(msg); fprintf(stderr,"translate: checking version specific stuff\n"); fflush(stderr); switch(version){ case 0: /* snmpV1 trap */ if(*cursor!=0xA4) return("expecting 0xA4 for V1 trap"); cursor++; objlen=getObjectLength(&cursor,bufend); if(objlen<0) return("buffer length confusion"); if(*cursor!=0x06) return("expecting 0x06 for enterprise OID"); strcpy(cmdcur,",'1.3.6.1.6.3.1.1.4.3'="); cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 4157-0.8.13-3 FP but replaced strchr(cmdcur,0) enterpriseOid=cursor; if(NULL!=(msg=translateValue(&cursor,bufend,&cmdcur,cmdend,""))) return(msg); if(*cursor!=0x40) return("expecting 0x40 for address"); strcpy(cmdcur,",'1.3.6.1.6.3.18.1.3'="); cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 4165-0.8.13-3 FP but replaced strchr(cmdcur,0) if(NULL!=(msg=translateValue(&cursor,bufend,&cmdcur,cmdend,""))) return(msg); if(*cursor!=0x02) return("expecting integer for trap generic type"); cursor++; if(*cursor>1) return("generic trap type length error - expecting 1"); cursor++; generic=*cursor; cursor++; if(*cursor!=0x02) return("expecting integer for trap specific type"); strcpy(cmdcur,",'1.3.6.1.6.3.1.1.4.1.0'="); // snmpTrapOID.0 cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 4162-0.8.13-3 FP but replaced strchr(cmdcur,0) if(generic!=6){ sprintf(cmdcur,"\"1.3.6.1.6.3.1.1.5.%d\"",(*cursor)+1); // see RFC 3584 cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 4156-0.8.13-3 FP but replaced strchr(cmdcur,0) cursor++; objlen=getObjectLength(&cursor,bufend); // step over trap specific type if(objlen<0) return("buffer length confusion"); } else{ trapOIDCur=cmdcur+1; //save location of trapOId if(NULL!=(msg=translateValue(&enterpriseOid,bufend,&cmdcur,cmdend,""))) return(msg); cmdcur--; // back up over ending quote to extend this enterprise oid strcpy(cmdcur,".0."); cmdcur+=3; if(NULL!=(msg=translateValue(&cursor,bufend,&cmdcur,cmdend,""))) return(msg); *trapOID='\''; objlen=cmdcur-trapOIDCur; strncpy(trapOID+1,trapOIDCur,objlen); *(trapOID+objlen+1)='\''; *(trapOID+objlen+2)=0; *cmdcur='"'; cmdcur++; } if(*cursor!=0x43) return("expecting 0x43 for uptime"); strcpy(cmdcur,",'1.3.6.1.2.1.1.3.0'="); cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 966-0.8.13-3 FP but replaced strchr(cmdcur,0) if(NULL!=(msg=translateValue(&cursor,bufend,&cmdcur,cmdend,""))) return(msg); break; case 1: /* snmpV2 trap */ if(*cursor!=0xA7) return("expecting 0xA7 for trap"); cursor++; objlen=getObjectLength(&cursor,bufend); if(objlen<0) return("buffer length confusion"); if(*cursor!=0x02) return("expecting 0x02 for variable 1"); cursor++; objlen=getObjectLength(&cursor,bufend); if(objlen<0) return("variable 1 length error"); cursor+=objlen; if(*cursor!=0x02 || *(cursor+1)!=0x01 || *(cursor+2)!=0x00 || *(cursor+3)!=0x02 || *(cursor+4)!=0x01 || *(cursor+5)!=0x00) return("V2:expecting 02 01 00 02 01 00 to start trap"); cursor+=6; // Insert the sender's address - don't worry, this will be overridden if sender supplies in variable bindings sprintf(cmdcur,",'1.3.6.1.6.3.18.1.3'=\"%s\"",nbIpGetAddrString(senderAddr,snmptrap->sourceAddr)); cmdcur+=strlen(cmdcur); // 2013-01-14 eat - VID 980-0.8.13-3 FP but replaced strchr(cmdcur,0) break; default: return("unrecognized trap version"); } fprintf(stderr,"translate: checking for handler\n"); fflush(stderr); fprintf(stderr,"translate: processing variable bindings\n"); fflush(stderr); // Variable bindings same for V1 and V2 if(*cursor!=0x30) return("expecting 0x30 for variable binding list"); cursor++; objlen=getObjectLength(&cursor,bufend); if(objlen<0) return("variable binding list length error"); while(cursor<bufend){ if(*cursor!=0x30) return("expecting 0x30 for variable binding"); cursor++; objlen=getObjectLength(&cursor,bufend); if(objlen<0) return("variable binding length error"); if(*cursor!=0x06) return("expecting OID on left side of variable binding"); cursor++; *cmdcur=','; cmdcur++; oid=cmdcur; // save location of OID *cmdcur='\''; cmdcur++; if((msg=translateOid(&cursor,bufend,&cmdcur,cmdend))!=NULL) return(msg); *cmdcur='\''; cmdcur++; *cmdcur=0; // look up syntax for value representation if(snmptrap->syntaxContext && (cell=nbTermLocateHere(snmptrap->syntaxContext,oid))!=NULL && (cell=nbTermGetDefinition(snmptrap->syntaxContext,cell))!=NULL && nbCellGetType(snmptrap->syntaxContext,cell)==NB_TYPE_STRING){ syntax=nbCellGetString(snmptrap->syntaxContext,cell); } else syntax=""; // look up attribute name and replace if found if(snmptrap->attributeContext && (cell=nbTermLocateHere(snmptrap->attributeContext,oid))!=NULL && (cell=nbTermGetDefinition(snmptrap->attributeContext,cell))!=NULL && nbCellGetType(snmptrap->attributeContext,cell)==NB_TYPE_STRING){ attribute=nbCellGetString(snmptrap->attributeContext,cell); strcpy(oid,attribute); cmdcur=strchr(oid,0); } *cmdcur='='; cmdcur++; value=cmdcur; if((msg=translateValue(&cursor,bufend,&cmdcur,cmdend,syntax))!=NULL) return(msg); if(strncmp(oid,"'1.3.6.1.6.3.1.1.4.1.0'",23)==0 && *value=='"'){ oid=trapOID; *oid='\''; oid++; value++; while(value<cmdcur && *value!='"') *oid=*value,oid++,value++; *oid='\''; oid++; *oid=0; } } *cmdcur=0; // Check for handler if(snmptrap->handlerContext && (cell=nbTermLocateHere(snmptrap->handlerContext,trapOID))!=NULL && (cell=nbTermGetDefinition(snmptrap->handlerContext,cell))!=NULL && nbCellGetType(snmptrap->handlerContext,cell)==NB_TYPE_STRING){ *handlerNameP=nbCellGetString(snmptrap->handlerContext,cell); //handler=nbCellGetString(snmptrap->handlerContext,cell); //strcpy(cmd,handler); //cmdcur=strchr(cmd,0); //*cmdcur=':'; //cmdcur++; //strcpy(cmdcur,trapOID); //cmdcur=strchr(cmdcur,0); } fprintf(stderr,"translate: returning\n"); fflush(stderr); return(NULL); }
/* * construct() method * * define <term> node <skill>[("<ident>"[,<uri>])][:<text>] * * <ident> - name of translator file * <uri> - <proto>://<spec> * * <proto> - only "udp" supported currently * <spec> - only local domain socket file supported currently * * <text> - flag keywords * trace - display input packets * dump - display dump of syslog packets * silent - don't echo generated NodeBrain commands * * define syslog node syslog.client("foobar"); */ void *clientConstruct(nbCELL context,void *skillHandle,nbCELL arglist,char *text){ NB_MOD_Client *client; nbCELL cell=NULL; nbSET argSet; char *cursor=text,*delim,saveDelim; int trace=0,dump=0,echo=1; char *ident="nodebrain"; char *uri="udp://127.0.0.1:514"; char *socketname=uri+6; int sd; argSet=nbListOpen(context,arglist); cell=nbListGetCellValue(context,&argSet); if(cell){ if(nbCellGetType(context,cell)!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"First argument must be string message identifier"); return(NULL); } ident=strdup(nbCellGetString(context,cell)); if(!ident) nbExit("clientConstruct: Out of memory - terminating"); nbCellDrop(context,cell); } cell=nbListGetCellValue(context,&argSet); if(cell){ if(nbCellGetType(context,cell)!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"Second argument must be string uri"); return(NULL); } uri=strdup(nbCellGetString(context,cell)); if(!uri) nbExit("clientConstruct: Out of memory - terminating"); nbCellDrop(context,cell); cell=nbListGetCellValue(context,&argSet); if(cell){ nbLogMsg(context,0,'E',"The syslog.client skill only accepts two arguments."); return(NULL); } } while(*cursor==' ') cursor++; while(*cursor!=';' && *cursor!=0){ delim=strchr(cursor,' '); if(delim==NULL) delim=strchr(cursor,','); if(delim==NULL) delim=strchr(cursor,';'); if(delim==NULL) delim=cursor+strlen(cursor); saveDelim=*delim; *delim=0; if(strcmp(cursor,"trace")==0){trace=1;} else if(strcmp(cursor,"dump")==0){trace=1;dump=1;} else if(strcmp(cursor,"silent")==0) echo=0; *delim=saveDelim; cursor=delim; if(*cursor==',') cursor++; while(*cursor==' ' || *cursor==',') cursor++; } // figure out the uri if(strncmp(uri,"udp://",6)){ nbLogMsg(context,0,'E',"Expecting uri to start with 'udp://' - found %s",uri); return(NULL); } socketname=uri+6; // add code here to determine if local or remote sd=socket(AF_UNIX,SOCK_DGRAM,0); if(sd<0){ nbLogMsg(context,0,'E',"Unable to obtain socket for %s",uri); return(NULL); } client=nbAlloc(sizeof(NB_MOD_Client)); client->ident=ident; client->uri=uri; client->un_addr.sun_family=AF_UNIX; sprintf(client->un_addr.sun_path,"%s",socketname); client->socket=sd; client->trace=trace; client->dump=dump; client->echo=echo; return(client); }
/* * construct() method * * define <term> node <skill>("<translator>",[<binding>])[:<text>] * * <translator> - name of translator file * <binding> - port_number or "interface_address[:port_number]" * <text> - flag keywords * trace - display input packets * dump - display dump of syslog packets * silent - don't echo generated NodeBrain commands * * define syslog node syslog.server("syslog.nbx"); * define syslog node syslog.server("syslog.nbx"):dump,silent; * define syslog node syslog.server("syslog.nbx","127.0.0.1"); * define syslog node syslog.server("syslog.nbx",50162); * define syslog node syslog.server("syslog.nbx","127.0.0.1:50162"); * define syslog node syslog.server("syslog.nbx","127.0.0.1:50162"):silent; */ void *serverConstruct(nbCELL context,void *skillHandle,nbCELL arglist,char *text){ NB_MOD_Server *server; nbCELL cell=NULL; nbSET argSet; char *cursor=text,*delim,saveDelim; double r,d; char interfaceAddr[512]; unsigned int port=514; int type,trace=0,dump=0,echo=1; int len; char *str; char *transfilename; nbCELL translator; char *uri="";; *interfaceAddr=0; argSet=nbListOpen(context,arglist); cell=nbListGetCellValue(context,&argSet); if(cell==NULL){ nbLogMsg(context,0,'E',"Translator configuration file required as first argument"); return(NULL); } type=nbCellGetType(context,cell); if(type!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"First argument must be string identifying translator configuration file"); return(NULL); } transfilename=nbCellGetString(context,cell); translator=nbTranslatorCompile(context,0,transfilename); if(translator==NULL){ nbLogMsg(context,0,'E',"Unable to load translator '%s'",transfilename); return(NULL); } cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ type=nbCellGetType(context,cell); if(type==NB_TYPE_STRING){ str=nbCellGetString(context,cell); uri=strdup(str); if(!uri) nbExit("serverConstruct: Out of memory - terminating"); if(strncmp(str,"udp://",6)==0) str+=6; // allow for uri delim=strchr(str,':'); if(delim==NULL) len=strlen(str); else len=delim-str; if(len>15 && *str>='0' && *str<='9'){ nbLogMsg(context,0,'E',"Inteface IP address may not be greater than 15 characters"); nbCellDrop(context,cell); return(NULL); } if(len>sizeof(interfaceAddr)-1){ nbLogMsg(context,0,'E',"Socket specification too long for buffer at--->%s",str); nbCellDrop(context,cell); return(NULL); } strncpy(interfaceAddr,str,len); *(interfaceAddr+len)=0; if(delim!=NULL){ delim++; port=(unsigned int)atoi(delim); } nbCellDrop(context,cell); } else if(type==NB_TYPE_REAL){ r=nbCellGetReal(context,cell); nbCellDrop(context,cell); port=(unsigned int)r; d=port; if(d!=r || d==0){ nbLogMsg(context,0,'E',"Expecting non-zero integer UDP port number"); return(NULL); } } else{ nbLogMsg(context,0,'E',"Expecting (\"file\") or (\"address[:port]\") or (port) as argument list"); return(NULL); } cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ nbLogMsg(context,0,'E',"The syslog skill only accepts two argument."); return(NULL); } } while(*cursor==' ') cursor++; while(*cursor!=';' && *cursor!=0){ delim=strchr(cursor,' '); if(delim==NULL) delim=strchr(cursor,','); if(delim==NULL) delim=strchr(cursor,';'); if(delim==NULL) delim=cursor+strlen(cursor); saveDelim=*delim; *delim=0; if(strcmp(cursor,"trace")==0){trace=1;} else if(strcmp(cursor,"dump")==0){trace=1;dump=1;} else if(strcmp(cursor,"silent")==0) echo=0; *delim=saveDelim; cursor=delim; if(*cursor==',') cursor++; while(*cursor==' ' || *cursor==',') cursor++; } server=nbAlloc(sizeof(NB_MOD_Server)); server->uri=uri; server->socket=0; strcpy(server->interfaceAddr,interfaceAddr); server->port=port; server->translator=translator; server->trace=trace; server->dump=dump; server->echo=echo; nbLogMsg(context,0,'I',"calling nbListenerEnableOnDaemon"); nbListenerEnableOnDaemon(context); // sign up to enable when we daemonize return(server); }
/* * construct() method * * define <term> node <skill>[(<args>)][:<text>] * * define <term> node audit("<filename>","<translator>",<schedule>); */ static void *auditConstruct(nbCELL context,void *skillHandle,nbCELL arglist,char *text){ nbAudit *audit; nbCELL fileNameCell,translatorNameCell,scheduleCell,nullCell; nbSET argSet; int type; char *fileName,*translatorName; nbCELL translatorCell; //nbLogMsg(context,0,'T',"auditConstruct: called"); argSet=nbListOpen(context,arglist); fileNameCell=nbListGetCellValue(context,&argSet); if(fileNameCell==NULL){ nbLogMsg(context,0,'E',"Expecting string file name as first parameter"); return(NULL); } type=nbCellGetType(context,fileNameCell); if(type!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"Expecting string file name as first parameter"); return(NULL); } fileName=nbCellGetString(context,fileNameCell); translatorNameCell=nbListGetCellValue(context,&argSet); if(translatorNameCell==NULL){ nbLogMsg(context,0,'E',"Expecting string translator name as second parameter"); return(NULL); } type=nbCellGetType(context,translatorNameCell); if(type!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"Expecting string translator name as second parameter"); return(NULL); } translatorName=nbCellGetString(context,translatorNameCell); scheduleCell=nbListGetCell(context,&argSet); // get schedule cell - not value nullCell=nbListGetCellValue(context,&argSet); if(nullCell!=NULL){ nbLogMsg(context,0,'E',"The audit skill only accepts three parameters."); return(NULL); } translatorCell=nbTranslatorCompile(context,0,translatorName); if(translatorCell==NULL){ nbLogMsg(context,0,'E',"Unable to load translator '%s'",translatorName); return(NULL); } audit=nbAlloc(sizeof(struct NB_MOD_AUDIT)); audit->file=NULL; audit->pos=0; audit->fileNameCell=fileNameCell; audit->fileName=fileName; audit->translatorNameCell=translatorNameCell; audit->translatorName=translatorName; audit->translatorCell=nbCellGrab(context,translatorCell); audit->scheduleCell=scheduleCell; audit->synapseCell=NULL; audit->trace=0; nbListenerEnableOnDaemon(context); // sign up to enable when we daemonize if(audit->trace) nbLogMsg(context,0,'T',"auditConstruct: returning"); return(audit); }
/* * assert() method * * assert <node>[(args)][=<value>] * * assert table("a",2,"hello")=5; # set value to 5 * assert table("a",2,"hello"); # set value to 1 * assert !table("a",2,"hello"); # set value to 0 * assert ?table("a",2,"hello"); # remove from table * assert table("a",2,"hello")=?? # remove from table * */ static int baselineAssert(nbCELL context,void *skillHandle,BTree *tree,nbCELL arglist,nbCELL value){ NB_TreePath path; BTreeNode *node=NULL,**nodeP=&tree->root; nbCELL argCell; nbSET argSet; int cellType; double real; int qualifiers=0; nbCELL element[32]; double deviation; if(arglist==NULL) return(0); // perhaps we should set the value of the tree itself argSet=nbListOpen(context,arglist); if(value==NB_CELL_UNKNOWN){ if(argSet==NULL && tree->root!=NULL) tree->root=removeTree(context,tree,tree->root); else removeNode(context,tree,&tree->root,&argSet); return(0); } cellType=nbCellGetType(context,value); if(cellType!=NB_TYPE_REAL){ nbLogMsg(context,0,'E',"Value must be a number"); return(0); } real=nbCellGetReal(context,value); if(argSet==NULL) return(0); argCell=nbListGetCellValue(context,&argSet); while(argCell!=NULL){ element[qualifiers]=argCell; qualifiers++; if(tree->options&BTREE_OPTION_ORDER) node=nbTreeLocateValue(&path,argCell,(NB_TreeNode **)nodeP,treeCompare,context); else node=nbTreeLocate(&path,argCell,(NB_TreeNode **)nodeP); if(node==NULL){ node=nbAlloc(sizeof(BTreeNode)); memset(node,0,sizeof(BTreeNode)); nbTreeInsert(&path,(NB_TreeNode *)node); nodeP=&(node->root); while((argCell=nbListGetCellValue(context,&argSet))!=NULL){ node=nbAlloc(sizeof(BTreeNode)); memset(node,0,sizeof(BTreeNode)); node->bnode.key=(void *)argCell; *nodeP=node; nodeP=&(node->root); } node->value=real; // note we don't set deviation, threshold and level until the end of the period. return(0); } nodeP=&(node->root); nbCellDrop(context,argCell); argCell=nbListGetCellValue(context,&argSet); } if(tree->options&BTREE_OPTION_SUM){ // need to check for zero average and deviation here! node->value+=real; if(node->average==0 && node->deviation==0) return(0); deviation=fabs(node->value-node->average); if(node->value>node->average && deviation>node->threshold) baselineAlert(context,skillHandle,tree,node,element,qualifiers,deviation); } else{ node->value=real; // update value and check limits if(node->average==0 && node->deviation==0) return(0); deviation=fabs(node->value-node->average); if(deviation>node->threshold) baselineAlert(context,skillHandle,tree,node,element,qualifiers,deviation); } return(0); }
/* * construct() method * * define <term> node <skill>[(<args>)][:<text>] * * define <term> node baseline("<directory>",<weight>,<tolerance>,<cycle>,<interval>)[:<options>]; */ static void *baselineConstruct(nbCELL context,BTreeSkill *skillHandle,nbCELL arglist,char *text){ int options=0; nbCELL found=NULL; nbCELL notfound=NULL; nbCELL cell; BTree *tree; char *cursor=text,*delim,ident[256]; int len; nbSET argSet; char *directory; double weight=0.5,tolerance=3,cycle=7*24*60,periods=24; double interval=60; argSet=nbListOpen(context,arglist); cell=nbListGetCellValue(context,&argSet); if(cell==NULL || nbCellGetType(context,cell)!=NB_TYPE_STRING){ nbLogMsg(context,0,'E',"Baseline directory string required as first argument"); return(NULL); } directory=nbCellGetString(context,cell); // we don't drop this cell because we reference it cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ if(nbCellGetType(context,cell)!=NB_TYPE_REAL || (weight=nbCellGetReal(context,cell))<0 || weight>1){ nbLogMsg(context,0,'E',"Second argument must be numeric weight between 0 and 1"); return(NULL); } nbCellDrop(context,cell); cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ if(nbCellGetType(context,cell)!=NB_TYPE_REAL || (tolerance=nbCellGetReal(context,cell))<0){ nbLogMsg(context,0,'E',"Third argument must be non-negative numeric tolerance"); return(NULL); } nbCellDrop(context,cell); cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ if(nbCellGetType(context,cell)!=NB_TYPE_REAL || (cycle=nbCellGetReal(context,cell))<1 || cycle!=(int)cycle){ nbLogMsg(context,0,'E',"Forth argument must be positive integer number of minutes in a cycle"); return(NULL); } nbCellDrop(context,cell); cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ if(nbCellGetType(context,cell)!=NB_TYPE_REAL || (interval=nbCellGetReal(context,cell))<1 || interval!=(int)interval || (periods=cycle/interval)<1 || periods!=(int)periods){ nbLogMsg(context,0,'E',"Fifth argument must be positive integer number of minutes in an interval by which %d is evenly divisable",cycle); return(NULL); } nbCellDrop(context,cell); cell=nbListGetCellValue(context,&argSet); if(cell!=NULL){ nbLogMsg(context,0,'E',"Only five arguments supported"); return(NULL); } } } } } if(skillHandle!=NULL && skillHandle->trace) nbLogMsg(context,0,'T',"baselineConstruct() called"); while(*cursor==' ') cursor++; while(*cursor!=0 && *cursor!=';'){ delim=cursor; while(*delim>='a' && *delim<='z') delim++; len=delim-cursor; if(len>sizeof(ident)-1){ nbLogMsg(context,0,'E',"Option not recognized at \"%s\".",cursor); return(NULL); } strncpy(ident,cursor,len); *(ident+len)=0; cursor=delim; while(*cursor==' ') cursor++; if(strcmp(ident,"trace")==0) options|=BTREE_OPTION_TRACE; else if(strcmp(ident,"order")==0) options|=BTREE_OPTION_ORDER; else if(strcmp(ident,"partition")==0) options|=BTREE_OPTION_PARTITION|BTREE_OPTION_ORDER; else if(strcmp(ident,"sum")==0) options|=BTREE_OPTION_SUM; else if(strcmp(ident,"static")==0) options|=BTREE_OPTION_STATIC; else if(strcmp(ident,"found")==0 || strcmp(ident,"notfound")==0){ if(*cursor!='='){ nbLogMsg(context,0,'E',"Expecting '=' at \"%s\".",cursor); return(NULL); } cursor++; cell=nbCellParse(context,&cursor); if(cell==NULL){ nbLogMsg(context,0,'E',"Syntax error in cell expression."); return(NULL); } if(strcmp(ident,"found")==0) found=cell; else notfound=cell; } else{ nbLogMsg(context,0,'E',"Option not recognized at \"%s\".",cursor); return(NULL); } while(*cursor==' ') cursor++; if(*cursor==','){ cursor++; while(*cursor==' ') cursor++; } else if(*cursor!=0 && *cursor!=';'){ nbLogMsg(context,0,'E',"Expecting ',' ';' or end of line at \"%s\".",cursor); return(NULL); } } if(notfound==NULL) notfound=NB_CELL_UNKNOWN; if(found==NULL) found=notfound; tree=(BTree *)nbAlloc(sizeof(BTree)); tree->options=options; tree->notfound=notfound; tree->found=found; tree->root=NULL; tree->directory=directory; tree->cycle=cycle*60; tree->periods=periods; tree->interval=interval*60; tree->weight=weight; tree->tolerance=tolerance*1.25; nbListenerEnableOnDaemon(context); // sign up to enable when we daemonize return(tree); }