int main(int argc, char **argv) { graph_t *prev = NULL; int r, rc = 0; Gvc = gvContextPlugins(lt_preloaded_symbols, DEMAND_LOADING); GvExitOnUsage = 1; gvParseArgs(Gvc, argc, argv); #ifndef _WIN32 signal(SIGUSR1, gvToggle); signal(SIGINT, intr); #ifndef NO_FPERR signal(SIGFPE, fperr); #endif #endif if (MemTest) { while (MemTest--) { /* Create a test graph */ G = create_test_graph(); /* Perform layout and cleanup */ gvLayoutJobs(Gvc, G); /* take layout engine from command line */ gvFreeLayout(Gvc, G); agclose (G); } } else if ((G = gvPluginsGraph(Gvc))) { gvLayoutJobs(Gvc, G); /* take layout engine from command line */ gvRenderJobs(Gvc, G); } else { while ((G = gvNextInputGraph(Gvc))) { if (prev) { gvFreeLayout(Gvc, prev); agclose(prev); } gvLayoutJobs(Gvc, G); /* take layout engine from command line */ gvRenderJobs(Gvc, G); gvFinalize(Gvc); r = agreseterrors(); rc = MAX(rc,r); prev = G; } } r = gvFreeContext(Gvc); return (MAX(rc,r)); }
void GraphvizAdapterImpl::finalize() { gvLayoutJobs(gvc_, g_); gvRenderJobs(gvc_, g_); gvFreeLayout(gvc_, g_); finalize_graph_(); finalize_context_(); }
/** * Render a tree to tree graph image via graphviz (dot) */ int r3_tree_render_file(const node * tree, const char * format, char * filename) { Agraph_t *g; /* set up a graphviz context - but only once even for multiple graphs */ static GVC_t *gvc; if (!gvc) { gvc = gvContext(); } /* Create a simple digraph */ g = agopen("g", Agdirected, 0); // create self node Agnode_t *ag_root = agnode(g, "{root}", 1); r3_tree_build_ag_nodes(g, ag_root, tree, 0); gvLayout(gvc, g, "dot"); gvRenderFilename(gvc, g, format, filename); gvFreeLayout(gvc, g); agclose(g); return 0; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d D O T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadDOTImage() reads a Graphviz image file and returns it. It allocates % the memory necessary for the new Image structure and returns a pointer to % the new image. % % The format of the ReadDOTImage method is: % % Image *ReadDOTImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadDOTImage(const ImageInfo *image_info,ExceptionInfo *exception) { char command[MaxTextExtent]; const char *option; graph_t *graph; Image *image; ImageInfo *read_info; MagickBooleanType status; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) return((Image *) NULL); read_info=CloneImageInfo(image_info); SetImageInfoBlob(read_info,(void *) NULL,0); (void) CopyMagickString(read_info->magick,"SVG",MaxTextExtent); (void) AcquireUniqueFilename(read_info->filename); (void) FormatLocaleString(command,MaxTextExtent,"-Tsvg -o%s %s", read_info->filename,image_info->filename); graph=agread(GetBlobFileHandle(image)); if (graph == (graph_t *) NULL) return ((Image *) NULL); option=GetImageOption(image_info,"dot:layout-engine"); if (option == (const char *) NULL) gvLayout(graphic_context,graph,(char *) "dot"); else gvLayout(graphic_context,graph,(char *) option); gvRenderFilename(graphic_context,graph,(char *) "svg",read_info->filename); gvFreeLayout(graphic_context,graph); /* Read SVG graph. */ image=ReadImage(read_info,exception); (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); if (image == (Image *) NULL) return((Image *) NULL); return(GetFirstImageInList(image)); }
__attribute__((used)) char* vizRenderFromString(const char *string, const char *format, const char *engine) { Agraph_t *graph; char *result; unsigned int length; if (context == NULL) { context = gvContext(); gvAddLibrary(context, &gvplugin_core_LTX_library); gvAddLibrary(context, &gvplugin_dot_layout_LTX_library); gvAddLibrary(context, &gvplugin_neato_layout_LTX_library); } graph = agmemread((char *) string); gvLayout(context, graph, engine); gvRenderData(context, graph, format, &result, &length); gvFreeLayout(context, graph); agclose(graph); return result; }
void GraphvizPlotter::plot() { if(path.length() == 0) { throw "Path is empty"; } if(name.length() == 0) { throw "Name is empty"; } // nacte nastaveny format grafu std::string format = getStringOutputFormat(); // vytvori konecne umisteni a nazev souboru std::string filename = path + name + "." + format; // vytvori potrebne struktury graphvizu GVC_t *gvc; Agraph_t *g; gvc = gvContext(); // parsovani ze struktury DOT do interni reprezentace graphvizu g = agmemread(getDot().c_str()); // pouziti defaultniho nastroje dot gvLayout(gvc, g, "dot"); // vykresleni grafu do souboru gvRenderFilename(gvc, g, format.c_str(), filename.c_str()); // uvolneni vsech struktur graphvizu z pameti gvFreeLayout(gvc, g); agclose(g); }
xme_status_t xme_hal_graphviz_generateImage ( const char* dotFilePath, const char* pngFilePath ) { FILE *fp; graph_t *graph; fopen_s(&fp, dotFilePath, "r"); XME_CHECK(fp != NULL, XME_STATUS_INTERNAL_ERROR); xme_hal_sync_enterCriticalSection(xme_hal_graphviz_mutex); graph = agread_usergets(fp, fgets); gvLayout(xme_hal_graphviz_gvc, graph, "dot"); gvRenderFilename(xme_hal_graphviz_gvc, graph, "png", pngFilePath); gvFreeLayout(xme_hal_graphviz_gvc, graph); agclose(graph); xme_hal_sync_leaveCriticalSection(xme_hal_graphviz_mutex); fclose(fp); return XME_STATUS_SUCCESS; }
GVSkeletonGraph::~GVSkeletonGraph(){ setlocale(LC_NUMERIC,"en_US.UTF-8"); gvFreeLayout(_context,_graph); agclose(_graph); gvFreeContext(_context); }
QGVScene::~QGVScene() { gvFreeLayout(_context->context(), _graph->graph()); agclose(_graph->graph()); gvFreeContext(_context->context()); delete _graph; delete _context; }
bool layout(Agraph_t *g, const char *engine) { int err; if (!g) return false; err = gvFreeLayout(gvc, g); /* ignore errors */ err = gvLayout(gvc, g, engine); return (! err); }
int main(int argc, char **argv) { graph_t *prev = NULL; Gvc = gvNEWcontext(Info, gvUsername()); gvParseArgs(Gvc, argc, argv); #ifndef WIN32 signal(SIGUSR1, gvToggle); signal(SIGINT, intr); #ifndef NO_FPERR fpinit(); signal(SIGFPE, fperr); #endif #endif if (MemTest) { while (1) { /* Create a test graph */ G = create_test_graph(); /* Perform layout and cleanup */ gvLayoutJobs(Gvc, G); /* take layout engine from command line */ gvFreeLayout(Gvc, G); /* Delete graph */ agclose(G); } } else { while ((G = gvNextInputGraph(Gvc))) { if (prev) { gvFreeLayout(Gvc, prev); agclose(prev); } gvLayoutJobs(Gvc, G); /* take layout engine from command line */ gvRenderJobs(Gvc, G); prev = G; } } return (gvFreeContext(Gvc)); }
void SkillGuiGraphDrawingArea::layout_graph() { if (__graph) { gvFreeLayout(__gvc, __graph); agclose(__graph); } __graph = agmemread((char *)__graph_dot.c_str()); if (__graph) { gvLayout(__gvc, __graph, (char *)"dot"); } }
void tcldot_layout(GVC_t *gvc, Agraph_t * g, char *engine) { char buf[256]; Agsym_t *a; int rc; gvFreeLayout(gvc, g); /* in case previously drawn */ /* support old behaviors if engine isn't specified*/ if (!engine || *engine == '\0') { if (agisdirected(g)) rc = gvlayout_select(gvc, "dot"); else rc = gvlayout_select(gvc, "neato"); } else { if (strcasecmp(engine, "nop") == 0) { Nop = 2; PSinputscale = POINTS_PER_INCH; rc = gvlayout_select(gvc, "neato"); } else { rc = gvlayout_select(gvc, engine); } if (rc == NO_SUPPORT) rc = gvlayout_select(gvc, "dot"); } if (rc == NO_SUPPORT) { fprintf(stderr, "Layout type: \"%s\" not recognized. Use one of:%s\n", engine, gvplugin_list(gvc, API_layout, engine)); return; } gvLayoutJobs(gvc, g); /* set bb attribute for basic layout. * doesn't yet include margins, scaling or page sizes because * those depend on the renderer being used. */ if (GD_drawing(g)->landscape) sprintf(buf, "%d %d %d %d", ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).UR.y), ROUND(GD_bb(g).UR.x)); else sprintf(buf, "%d %d %d %d", ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y)); if (!(a = agattr(g, AGRAPH, "bb", NULL))) a = agattr(g, AGRAPH, "bb", ""); agxset(g, a, buf); }
SkillGuiGraphDrawingArea::~SkillGuiGraphDrawingArea() { if (__graph) { gvFreeLayout(__gvc, __graph); agclose(__graph); } gvFreeContext(__gvc); //delete __fcd; delete __fcd_save; delete __fcd_open; delete __fcd_recording; delete __filter_pdf; delete __filter_svg; delete __filter_png; delete __filter_dot; }
SEXP Rgraphviz_doLayout(SEXP graph, SEXP layoutType, SEXP size) { /* Will perform a Graphviz layout on a graph */ Agraph_t *g; SEXP slotTmp, nLayout, cPoints, bb; /* Extract the Agraph_t pointer from the S4 object */ PROTECT(slotTmp = GET_SLOT(graph, install("agraph"))); CHECK_Rgraphviz_graph(slotTmp); g = R_ExternalPtrAddr(slotTmp); if (size != R_NilValue) { agsafeset(g, "size", CHAR(STRING_ELT(size, 0)), NULL); } /* Call the appropriate Graphviz layout routine */ gvLayout(gvc, g, CHAR(STRING_ELT(layoutType, 0))); /* if (!isInteger(layoutType)) error("layoutType must be an integer value"); else { gvLayout(gvc, g, layouts[INTEGER(layoutType)[0]]); } */ /* Here we want to extract information for the resultant S4 object */ PROTECT(nLayout = getNodeLayouts(g)); PROTECT(bb = getBoundBox(g)); PROTECT(cPoints = getEdgeLocs(g)); SET_SLOT(graph, Rf_install("agraph"), slotTmp); SET_SLOT(graph,Rf_install("AgNode"), nLayout); SET_SLOT(graph,Rf_install("laidout"), Rgraphviz_ScalarLogicalFromRbool(TRUE)); SET_SLOT(graph,Rf_install("AgEdge"), cPoints); SET_SLOT(graph,Rf_install("boundBox"), bb); SET_SLOT(graph,Rf_install("fg"), Rgraphviz_ScalarStringOrNull(agget(g, "fgcolor"))); SET_SLOT(graph,Rf_install("bg"), Rgraphviz_ScalarStringOrNull(agget(g, "bgcolor"))); UNPROTECT(4); /* free gvc after rendering */ gvFreeLayout(gvc, g); return(graph); }
int main(int argc, char **argv) { graph_t *g, *prev = NULL; GVC_t *gvc; gvc = gvContext(); gvParseArgs(gvc, argc, argv); while ((g = gvNextInputGraph(gvc))) { if (prev) { gvFreeLayout(gvc, prev); agclose(prev); } gvLayoutJobs(gvc, g); gvRenderJobs(gvc, g); prev = g; } return (gvFreeContext(gvc)); }
int main(int argc, char **argv) { Agraph_t *g; Agnode_t *n, *m; Agedge_t *e; Agsym_t *a; #ifdef NO_LAYOUT_OR_RENDERING aginit(); #else /* set up a graphviz context - but only once even for multiple graphs */ static GVC_t *gvc; if (!gvc) gvc = gvContext(); #endif /* Create a simple digraph */ g = agopen("g", AGDIGRAPH); n = agnode(g, "n"); m = agnode(g, "m"); e = agedge(g, n, m); /* Set an attribute - in this case one that affects the visible rendering */ agsafeset(n, "color", "red", ""); #ifdef NO_LAYOUT_OR_RENDERING /* Just write the graph without layout */ agwrite(g, stdout); #else /* Use the directed graph layout engine */ gvLayout(gvc, g, "dot"); /* Output in .dot format */ gvRender(gvc, g, "dot", stdout); gvFreeLayout(gvc, g); #endif agclose(g); return 0; }
static bool GenDrawFormatFile(Digraph& dg, VNG_Param& param, const string& fmt, char** result, unsigned int* length) { GVC_t* gvc = gvContext(); //创建图 Agraph_t* g = CreateGraph(dg, param); gvLayout(gvc,g,"dot"); //写入到缓存数组中 gvRenderData(gvc,g,fmt.c_str(), result, length); //gvFreeRenderData(result); gvFreeLayout(gvc,g); agclose(g); // gvfreecontext函数返回错误个数 // 错误数为0表示没有问题 return (gvFreeContext(gvc) == 0); }
GraphVizUtils::VerticesCoordinates GraphVizUtils::getVerticesCoordinates( GraphIF * graph, GraphVizEngine layoutEngine, GraphDimmention graphMaxWidth, GraphDimmention graphMaxHeight) { GVC_t *gvc { }; Agraph_t *g { }; std::string dotFormatedGraph { }; char * graphRenderedData { }; unsigned int length { }; VerticesCoordinates verticesCoordinates { }; std::stringstream ss { }; gvc = gvContext(); dotFormatedGraph = OutputUtils::impl::DOT::exportGraph(graph); g = agmemread(dotFormatedGraph.c_str()); gvLayout(gvc, g, EnumUtils::getGraphVizEngineString(layoutEngine)); gvRenderData(gvc, g, "plain", &graphRenderedData, &length); ss << graphRenderedData; switch (layoutEngine) { case GraphVizEngine::DOT: break; case GraphVizEngine::NEATO: verticesCoordinates = GraphVizUtils::impl::getVerticesCoordinatesAsNeato(ss, graph->getNumberOfVertices(), graphMaxWidth, graphMaxHeight); break; default: break; } gvFreeRenderData(graphRenderedData); gvFreeLayout(gvc, g); agclose(g); gvFreeContext(gvc); return verticesCoordinates; }
void EuclideanNetwork::show(std::string filename, const char* filetype) { GVC_t *gvc; Agraph_t *g; std::stringstream sStream; std::vector<Agnode_t *> vNodes; std::vector<Agedge_t *> vEdges; int i = 0; if (v < 1) return; gvc = gvContext(); g = agopen("g", Agundirected, 0); while (i < v) { sStream.str(""); sStream << i; vNodes.push_back(agnode(g, sStream.str().c_str(), 1)); sStream.str(""); sStream << x[i]*7 << "," << y[i]*7 << "!"; agsafeset(vNodes[vNodes.size()-1], "height", "0.4", ""); agsafeset(vNodes[vNodes.size()-1], "width", "0.4", ""); agsafeset(vNodes[vNodes.size()-1], "fixedsize", "true", ""); agsafeset(vNodes[vNodes.size()-1], "pos", sStream.str().c_str(), ""); i++; } for (std::set<Edge>::iterator x = e.begin(); x != e.end(); ++x) { sStream.str(""); sStream << ((*x).wage * scale); vEdges.push_back(agedge(g, vNodes[(*x).v1], vNodes[(*x).v2], sStream.str().c_str(), 1)); } gvLayout(gvc, g, "fdp"); gvRenderFilename(gvc, g, filetype, filename.c_str()); gvFreeLayout(gvc, g); agclose(g); gvFreeContext(gvc); return; }
/*---------------------------------------------------------------------------- * Perform a dot_cleanup and a graph closing. Call this function at the end of * call to draw_graph. */ void cls_inherit_free (AnjutaClassInheritance *plugin) { if (plugin->nodes) g_hash_table_destroy (plugin->nodes); plugin->nodes = NULL; /* Destroy graphics */ if (plugin->graph != NULL) { gvFreeLayout (plugin->gvc, plugin->graph); agclose (plugin->graph); } if (plugin->gvc != NULL ) { gvFreeContext (plugin->gvc); } plugin->graph = NULL; plugin->gvc = NULL; }
__attribute__((used)) char* vizRenderFromString(char *string, char *format) { GVC_t *context = gvContext(); gvAddLibrary(context, &gvplugin_core_LTX_library); gvAddLibrary(context, &gvplugin_dot_layout_LTX_library); Agraph_t *graph = agmemread(string); gvLayout(context, graph, "dot"); char *result; unsigned int length; gvRenderData(context, graph, format, &result, &length); gvFreeLayout(context, graph); agclose(graph); gvFinalize(context); gvFreeContext(context); return result; }
/*---------------------------------------------------------------------------- * draw the graph on the canvas. So nodes, edges, arrows, texts.. */ void cls_inherit_draw (AnjutaClassInheritance *plugin) { ClsBox bounds; gvLayout (plugin->gvc, plugin->graph, "dot"); /* set the size of the canvas. We need this to set the scrolling.. */ bounds.x1 = 0; bounds.y1 = 0; bounds.x2 = CANVAS_MIN_SIZE; bounds.y2 = CANVAS_MIN_SIZE; g_hash_table_foreach (plugin->nodes, (GHFunc) cls_node_ensure_draw, &bounds); /* Request extra 20px along x and y for 10px margin around the canvas */ foo_canvas_set_scroll_region (FOO_CANVAS (plugin->canvas), bounds.x1 - 10, bounds.y1 - 10, bounds.x2 + 10, bounds.y2 + 10); gvFreeLayout(plugin->gvc, plugin->graph); }
void GVLayout::updateLayout() { gvLayout (this->gvc, this->gvgraph, "dot"); //update all graphviz items in the layout for (int i=0; i<this->items.size(); i++) { GVItem *gv_item = this->items[i]; gv_item->updateLayout(); } // For debugging, this shows the content of the graph (ok for libgraph and libcgraph): //gvRender (this->gvc, this->gvgraph, "dot", stdout); // The original comment for gvFreeLayout() was: // free after update to avoid crashes when node are removed! // When gvc is used with cgraph, this actually causes a crash in Graphviz // 2.26.3 and 2.30.1, due to bug (in Graphviz) 2.32+ are immune. // The crash occurs on a subsequent call to gvLayout(). // See http://www.graphviz.org/mantisbt/view.php?id=2467 gvFreeLayout (this->gvc, this->gvgraph); }
int main (int argc, char* argv[]) { graph_t *g; graph_t *sg; FILE *fp; graph_t** cc; int i, ncc; GVC_t *gvc; gvc = gvContext(); if (argc > 1) fp = fopen(argv[1], "r"); else fp = stdin; g = agread(fp, 0); cc = ccomps(g, &ncc, (char*)0); for (i = 0; i < ncc; i++) { sg = cc[i]; nodeInduce (sg); gvLayout(gvc, sg, "neato"); } pack_graph (ncc, cc, g, 0); gvRender(gvc, g, "ps", stdout); for (i = 0; i < ncc; i++) { sg = cc[i]; gvFreeLayout(gvc, sg); agdelete(g, sg); } agclose(g); return (gvFreeContext(gvc)); }
void graph2png(const agent *a, const agent *n, const contr c, const contr r, const contr d, const char* filename) { const agent *p = n + N + 1; agent m = n[N]; GVC_t *gvc = gvContext(); Agraph_t* g = agopen("test", Agstrictundirected, 0); agsafeset(g, "overlap", "false", ""); Agnode_t* nodes[N]; do { nodes[*p] = agnode(g, names[*p], 1); p++; } while (--m); for (agent i = 1; i < E + 1; i++) if (!ISSET(c, i) && !ISSET(d, i)) { Agedge_t *e = agedge(g, nodes[X(a, i)], nodes[Y(a, i)], "", 1); if (ISSET(r, i)) agsafeset(e, "color", "red", ""); } gvLayout(gvc, g, "neato"); gvRenderFilename(gvc, g, "png", filename); gvFreeLayout(gvc, g); agclose(g); gvFreeContext(gvc); }
int main(int argc, char **argv) { Agraph_t *g; Agnode_t *n, *m; Agedge_t *e; GVC_t *gvc; /* set up a graphviz context */ gvc = gvContext(); /* parse command line args - minimally argv[0] sets layout engine */ gvParseArgs(gvc, argc, argv); /* Create a simple digraph */ g = agopen("g", AGDIGRAPH); n = agnode(g, "n"); m = agnode(g, "m"); e = agedge(g, n, m); /* Set an attribute - in this case one that affects the visible rendering */ agsafeset(n, "color", "red", ""); /* Compute a layout using layout engine from command line args */ gvLayoutJobs(gvc, g); /* Write the graph according to -T and -o options */ gvRenderJobs(gvc, g); /* Free layout data */ gvFreeLayout(gvc, g); /* Free graph structures */ agclose(g); /* close output file, free context, and return number of errors */ return (gvFreeContext(gvc)); }
void GVSkeletonGraph::applyLayout(){ setlocale(LC_NUMERIC,"en_US.UTF-8"); gvFreeLayout(_context, _graph); _gvLayout(_context, _graph, "dot"); }
void QGVScene::freeLayout() { gvFreeLayout(_context->context(), _graph->graph()); }
void* AI_alert_correlation_thread ( void *arg ) { int i; struct stat st; char corr_dot_file[4096] = { 0 }; #ifdef HAVE_LIBGVC char corr_ps_file [4096] = { 0 }; #endif double avg_correlation = 0.0, std_deviation = 0.0, corr_threshold = 0.0, kb_correlation = 0.0, bayesian_correlation = 0.0, neural_correlation = 0.0; size_t n_correlations = 0, n_corr_functions = 0, n_corr_weights = 0; FILE *fp = NULL; AI_alert_correlation_key corr_key; AI_alert_correlation *corr = NULL; AI_alert_type_pair_key pair_key; AI_alert_type_pair *pair = NULL, *unpair = NULL; AI_snort_alert *alert_iterator = NULL, *alert_iterator2 = NULL; pthread_t manual_corr_thread; #ifdef HAVE_LIBGVC char corr_png_file[4096] = { 0 }; GVC_t *gvc = NULL; graph_t *g = NULL; #endif double (**corr_functions)( const AI_snort_alert*, const AI_snort_alert* ) = NULL; double (**corr_weights)() = NULL; #ifdef HAVE_LIBPYTHON2_6 PyObject *pyA = NULL, *pyB = NULL; PyObject *pArgs = NULL, *pRet = NULL; PyObject **py_corr_functions = NULL; PyObject **py_weight_functions = NULL; size_t n_py_corr_functions = 0; size_t n_py_weight_functions = 0; double py_value = 0.0, py_weight = 0.0; py_corr_functions = AI_get_py_functions ( &n_py_corr_functions ); py_weight_functions = AI_get_py_weights ( &n_py_weight_functions ); #endif corr_functions = AI_get_corr_functions ( &n_corr_functions ); corr_weights = AI_get_corr_weights ( &n_corr_weights ); pthread_mutex_init ( &mutex, NULL ); /* Start the thread for parsing manual correlations from XML */ if ( pthread_create ( &manual_corr_thread, NULL, AI_manual_correlations_parsing_thread, NULL ) != 0 ) { AI_fatal_err ( "Failed to create the manual correlations parsing thread", __FILE__, __LINE__ ); } while ( 1 ) { sleep ( config->correlationGraphInterval ); if ( stat ( config->corr_rules_dir, &st ) < 0 ) { _dpd.errMsg ( "AIPreproc: Correlation rules directory '%s' not found, the correlation thread won't be active\n", config->corr_rules_dir ); pthread_exit (( void* ) 0 ); return ( void* ) 0; } /* Set the lock flag to true, and keep it this way until I've done with correlating alerts */ pthread_mutex_lock ( &mutex ); if ( alerts ) { AI_free_alerts ( alerts ); alerts = NULL; } if ( !( alerts = AI_get_clustered_alerts() )) { pthread_mutex_unlock ( &mutex ); continue; } if ( config->use_knowledge_base_correlation_index != 0 ) { AI_kb_index_init ( alerts ); } __AI_correlation_table_cleanup(); correlation_table = NULL; /* Fill the table of correlated alerts */ for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next ) { for ( alert_iterator2 = alerts; alert_iterator2; alert_iterator2 = alert_iterator2->next ) { if ( alert_iterator != alert_iterator2 && ! ( alert_iterator->gid == alert_iterator2->gid && alert_iterator->sid == alert_iterator2->sid && alert_iterator->rev == alert_iterator2->rev )) { if ( !( corr = ( AI_alert_correlation* ) malloc ( sizeof ( AI_alert_correlation )))) AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ ); corr_key.a = alert_iterator; corr_key.b = alert_iterator2; corr->key = corr_key; corr->correlation = 0.0; n_correlations = 0; kb_correlation = AI_kb_correlation_coefficient ( corr_key.a, corr_key.b ); bayesian_correlation = AI_alert_bayesian_correlation ( corr_key.a, corr_key.b ); neural_correlation = AI_alert_neural_som_correlation ( corr_key.a, corr_key.b ); /* Use the correlation indexes for which we have a value */ if ( bayesian_correlation != 0.0 && config->bayesianCorrelationInterval != 0 ) { corr->correlation += AI_bayesian_correlation_weight() * bayesian_correlation; n_correlations++; } if ( kb_correlation != 0.0 && config->use_knowledge_base_correlation_index ) { corr->correlation += kb_correlation; n_correlations++; } if ( neural_correlation != 0.0 && config->neuralNetworkTrainingInterval != 0 ) { corr->correlation += AI_neural_correlation_weight() * neural_correlation; n_correlations++; } /* Get the correlation indexes from extra correlation modules */ if (( corr_functions )) { for ( i=0; i < n_corr_functions; i++ ) { if ( corr_weights[i]() != 0.0 ) { corr->correlation += corr_weights[i]() * corr_functions[i] ( corr_key.a, corr_key.b ); n_correlations++; } } } #ifdef HAVE_LIBPYTHON2_6 if (( py_corr_functions )) { pyA = AI_alert_to_pyalert ( corr_key.a ); pyB = AI_alert_to_pyalert ( corr_key.b ); if ( pyA && pyB ) { for ( i=0; i < n_py_corr_functions; i++ ) { if ( !( pArgs = Py_BuildValue ( "(OO)", pyA, pyB ))) { PyErr_Print(); AI_fatal_err ( "Could not initialize the Python arguments for the call", __FILE__, __LINE__ ); } if ( !( pRet = PyEval_CallObject ( py_corr_functions[i], pArgs ))) { PyErr_Print(); AI_fatal_err ( "Could not call the correlation function from the Python module", __FILE__, __LINE__ ); } if ( !( PyArg_Parse ( pRet, "d", &py_value ))) { PyErr_Print(); AI_fatal_err ( "Could not parse the correlation value out of the Python correlation function", __FILE__, __LINE__ ); } Py_DECREF ( pRet ); Py_DECREF ( pArgs ); if ( !( pRet = PyEval_CallObject ( py_weight_functions[i], (PyObject*) NULL ))) { PyErr_Print(); AI_fatal_err ( "Could not call the correlation function from the Python module", __FILE__, __LINE__ ); } if ( !( PyArg_Parse ( pRet, "d", &py_weight ))) { PyErr_Print(); AI_fatal_err ( "Could not parse the correlation weight out of the Python correlation function", __FILE__, __LINE__ ); } Py_DECREF ( pRet ); if ( py_weight != 0.0 ) { corr->correlation += py_weight * py_value; n_correlations++; } } Py_DECREF ( pyA ); Py_DECREF ( pyB ); /* free ( pyA ); free ( pyB ); */ pyA = NULL; pyB = NULL; } } #endif if ( n_correlations != 0 ) { corr->correlation /= (double) n_correlations; } HASH_ADD ( hh, correlation_table, key, sizeof ( AI_alert_correlation_key ), corr ); } } } if ( HASH_COUNT ( correlation_table ) > 0 ) { avg_correlation = 0.0; std_deviation = 0.0; /* Compute the average correlation coefficient */ for ( corr = correlation_table; corr; corr = ( AI_alert_correlation* ) corr->hh.next ) { avg_correlation += corr->correlation; } avg_correlation /= (double) HASH_COUNT ( correlation_table ); /* Compute the standard deviation */ for ( corr = correlation_table; corr; corr = ( AI_alert_correlation* ) corr->hh.next ) { std_deviation += ( corr->correlation - avg_correlation ) * ( corr->correlation - avg_correlation ); } std_deviation = sqrt ( std_deviation / (double) HASH_COUNT ( correlation_table )); corr_threshold = avg_correlation + ( config->correlationThresholdCoefficient * std_deviation ); snprintf ( corr_dot_file, sizeof ( corr_dot_file ), "%s/correlated_alerts.dot", config->corr_alerts_dir ); if ( stat ( config->corr_alerts_dir, &st ) < 0 ) { if ( mkdir ( config->corr_alerts_dir, 0755 ) < 0 ) { AI_fatal_err ( "Unable to create directory the correlated alerts directory", __FILE__, __LINE__ ); } } else if ( !S_ISDIR ( st.st_mode )) { AI_fatal_err ( "The specified directory for correlated alerts is not a directory", __FILE__, __LINE__ ); } if ( !( fp = fopen ( corr_dot_file, "w" ))) AI_fatal_err ( "Could not write on the correlated alerts .dot file", __FILE__, __LINE__ ); fprintf ( fp, "digraph G {\n" ); /* Find correlated alerts */ for ( corr = correlation_table; corr; corr = ( AI_alert_correlation* ) corr->hh.next ) { pair_key.from_sid = corr->key.a->sid; pair_key.from_gid = corr->key.a->gid; pair_key.from_rev = corr->key.a->rev; pair_key.to_sid = corr->key.b->sid; pair_key.to_gid = corr->key.b->gid; pair_key.to_rev = corr->key.b->rev; HASH_FIND ( hh, manual_correlations, &pair_key, sizeof ( pair_key ), pair ); HASH_FIND ( hh, manual_uncorrelations, &pair_key, sizeof ( pair_key ), unpair ); /* Yes, BlackLight wrote this line of code in a pair of minutes and immediately * compiled it without a single error */ if ( !unpair && ( pair || ( corr->correlation >= corr_threshold && corr_threshold != 0.0 && corr->key.a->timestamp <= corr->key.b->timestamp && ! ( corr->key.a->gid == corr->key.b->gid && corr->key.a->sid == corr->key.b->sid && corr->key.a->rev == corr->key.b->rev ) && ( corr->key.a->ip_src_addr == corr->key.b->ip_src_addr || ( (corr->key.a->h_node[src_addr] && corr->key.b->h_node[src_addr]) ? ( corr->key.a->h_node[src_addr]->max_val == corr->key.b->h_node[src_addr]->max_val && corr->key.a->h_node[src_addr]->min_val == corr->key.b->h_node[src_addr]->min_val ) : 0 )) && ( corr->key.a->ip_dst_addr == corr->key.b->ip_dst_addr || ( (corr->key.a->h_node[dst_addr] && corr->key.b->h_node[dst_addr]) ? ( corr->key.a->h_node[dst_addr]->max_val == corr->key.b->h_node[dst_addr]->max_val && corr->key.a->h_node[dst_addr]->min_val == corr->key.b->h_node[dst_addr]->min_val ) : 0 )) ) ) ) { if ( !( corr->key.a->derived_alerts = ( AI_snort_alert** ) realloc ( corr->key.a->derived_alerts, (++corr->key.a->n_derived_alerts) * sizeof ( AI_snort_alert* )))) AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ ); if ( !( corr->key.b->parent_alerts = ( AI_snort_alert** ) realloc ( corr->key.b->parent_alerts, (++corr->key.b->n_parent_alerts) * sizeof ( AI_snort_alert* )))) AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ ); corr->key.a->derived_alerts[ corr->key.a->n_derived_alerts - 1 ] = corr->key.b; corr->key.b->parent_alerts [ corr->key.b->n_parent_alerts - 1 ] = corr->key.a; __AI_correlated_alerts_to_dot ( corr, fp ); if ( config->outdbtype != outdb_none ) { AI_store_correlation_to_db ( corr ); } } } fprintf ( fp, "}\n" ); fclose ( fp ); #ifdef HAVE_LIBGVC snprintf ( corr_png_file, sizeof ( corr_png_file ), "%s/correlated_alerts.png", config->corr_alerts_dir ); snprintf ( corr_ps_file , sizeof ( corr_ps_file ), "%s/correlated_alerts.ps" , config->corr_alerts_dir ); if ( !( gvc = gvContext() )) { pthread_mutex_unlock ( &mutex ); continue; } if ( !( fp = fopen ( corr_dot_file, "r" ))) { pthread_mutex_unlock ( &mutex ); continue; } if ( !( g = agread ( fp ))) { pthread_mutex_unlock ( &mutex ); continue; } gvLayout ( gvc, g, "dot" ); gvRenderFilename ( gvc, g, "png", corr_png_file ); gvRenderFilename ( gvc, g, "ps" , corr_ps_file ); gvFreeLayout ( gvc, g ); agclose ( g ); fclose ( fp ); #endif /* If no database output is defined, then the alerts have no alert_id, so we cannot use the * web interface for correlating them, as they have no unique identifier */ if ( config->outdbtype != outdb_none ) { if ( strlen ( config->webserv_dir ) != 0 ) { __AI_correlated_alerts_to_json (); } } } pthread_mutex_unlock ( &mutex ); } pthread_exit (( void* ) 0 ); return (void*) 0; } /* ----- end of function AI_alert_correlation_thread ----- */