diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 8d734ab8e6..715e8d9cf9 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -64,6 +64,13 @@ void BroDoc::SetPacketFilter(const std::string& s) packet_filter = s.substr(pos1 + 2, pos2 - 2); } +void BroDoc::AddPortAnalysis(const std::string& analyzer, + const std::string& ports) + { + std::string reST_string = analyzer + "::\n" + ports + "\n"; + port_analysis.push_back(reST_string); + } + void BroDoc::WriteDocFile() const { WriteToDoc("%s\n", source_filename.c_str()); @@ -83,6 +90,12 @@ void BroDoc::WriteDocFile() const WriteStringList(" :bro:script: `%s`\n", " :bro:script: `%s`\n\n", imports); + WriteSectionHeading("Port Analysis", '-'); + WriteStringList("%s", port_analysis); + + WriteSectionHeading("Packet Filter", '-'); + WriteToDoc("%s\n", packet_filter.c_str()); + WriteSectionHeading("Public Interface", '-'); WriteBroDocObjList(options, true, "Options", '~'); WriteBroDocObjList(state_vars, true, "State Variables", '~'); @@ -91,14 +104,9 @@ void BroDoc::WriteDocFile() const WriteBroDocObjList(events, true, "Events", '~'); WriteBroDocObjList(functions, true, "Functions", '~'); - WriteSectionHeading("Packet Filter", '-'); - WriteToDoc("%s\n", packet_filter.c_str()); - WriteSectionHeading("Private Interface", '-'); - WriteBroDocObjList(options, false, "Options", '~'); WriteBroDocObjList(state_vars, false, "State Variables", '~'); WriteBroDocObjList(types, false, "Types", '~'); - WriteBroDocObjList(notices, false, "Notices", '~'); WriteBroDocObjList(events, false, "Events", '~'); WriteBroDocObjList(functions, false, "Functions", '~'); } diff --git a/src/BroDoc.h b/src/BroDoc.h index adad10e3db..37adcc8b70 100644 --- a/src/BroDoc.h +++ b/src/BroDoc.h @@ -73,6 +73,15 @@ public: */ void SetPacketFilter(const std::string& s); + /** + * Schedules documentation of a given set of ports being associated + * with a particular analyzer as a result of the current script + * being loaded -- the way the "dpd_config" table is changed. + * @param analyzer An analyzer that changed the "dpd_config" table. + * @param ports The set of ports assigned to the analyzer in table. + */ + void AddPortAnalysis(const std::string& analyzer, const std::string& ports); + /** * Sets the author of the script. * The scanner should call this when it sees "## Author: ..." @@ -114,6 +123,7 @@ protected: std::list modules; std::list summary; std::list imports; + std::list port_analysis; std::list options; // identifiers with &redef attr std::list state_vars; // identifiers without &redef? diff --git a/src/scan.l b/src/scan.l index 41c9fc08f7..d47986b144 100644 --- a/src/scan.l +++ b/src/scan.l @@ -17,6 +17,8 @@ #include "broparse.h" #include "BroDoc.h" #include "BroBifDoc.h" +#include "Analyzer.h" +#include "AnalyzerTags.h" #include #include @@ -33,8 +35,6 @@ int nruntime = 0; // Track the @if... depth. ptr_compat_int current_depth = 0; -declare(List,ptr_compat_int); -typedef List(ptr_compat_int) int_list; int_list if_stack; int line_number = 1; @@ -72,6 +72,9 @@ void clear_reST_doc_comments(); // adds changes to capture_filter to the current script's reST documentation static void check_capture_filter_changes(); +// adds changes to dpd_config to the current script's reST documentation +static void check_dpd_config_changes(); + class FileInfo { public: FileInfo(string restore_module = ""); @@ -728,6 +731,7 @@ int yywrap() while ( input_files.length() > 0 ) { check_capture_filter_changes(); + check_dpd_config_changes(); if ( load_files_with_prefix(input_files[0]) ) { // Don't delete the filename - it's pointed to by @@ -741,6 +745,7 @@ int yywrap() (void) input_files.remove_nth(0); } check_capture_filter_changes(); + check_dpd_config_changes(); // Add redef statements for any X=Y command line parameters. if ( params.size() > 0 ) @@ -883,11 +888,49 @@ static void check_capture_filter_changes() ODesc desc; capture_filters->ID_Val()->Describe(&desc); last_reST_doc->SetPacketFilter(desc.Description()); - ( (TableVal*) capture_filters->ID_Val() )->RemoveAll(); + capture_filters->ID_Val()->AsTableVal()->RemoveAll(); } } } +static void check_dpd_config_changes() + { + if ( generate_documentation ) + { + // Lookup the "dpd_config" identifier, if it has any + // defined value, add it to the script's documentation, + // and clear the table so that it doesn't taint the + // documentation for subsequent scripts. + ID* dpd_config = global_scope()->Lookup("dpd_config"); + if ( ! dpd_config ) return; + + TableVal* dpd_table = dpd_config->ID_Val()->AsTableVal(); + ListVal* dpd_list = dpd_table->ConvertToList(); + for ( int i = 0; i < dpd_list->Length(); ++i ) + { + Val* key = dpd_list->Index(i); + if ( ! key ) continue; + Val* v = dpd_table->Lookup(key); + if ( ! v ) continue; + + int tag = key->AsListVal()->Index(0)->AsCount(); + ODesc valdesc; + valdesc.PushIndent(); + v->Describe(&valdesc); + + if ( tag < AnalyzerTag::Error || tag > AnalyzerTag::LastAnalyzer ) + { + fprintf(stderr, "Warning: skipped bad analyzer tag: %i\n", tag); + continue; + } + last_reST_doc->AddPortAnalysis( + Analyzer::GetTagName((AnalyzerTag::Tag)tag), + valdesc.Description()); + } + dpd_table->RemoveAll(); + } + } + void print_current_reST_doc_comments() { if ( ! reST_doc_comments ) return;