diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index ff89b39177..65b41305c7 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -23,7 +23,7 @@ @load base/utils/time @load base/utils/urls -# This has some deep interplay between types and BiFs so it's +# This has some deep interplay between types and BiFs so it's # loaded in base/init-bare.bro #@load base/frameworks/logging @load base/frameworks/notice @@ -61,7 +61,7 @@ @load base/protocols/rfb @load base/protocols/sip @load base/protocols/snmp -# This DOES NOT enable the SMB analyzer. It's just some base support +# This DOES NOT enable the SMB analyzer. It's just some base support # for other protocols. @load base/protocols/smb @load base/protocols/smtp @@ -80,3 +80,4 @@ @load base/misc/find-checksum-offloading @load base/misc/find-filtered-trace +@load base/misc/version diff --git a/scripts/base/misc/version.bro b/scripts/base/misc/version.bro new file mode 100644 index 0000000000..d5e26ed518 --- /dev/null +++ b/scripts/base/misc/version.bro @@ -0,0 +1,90 @@ +##! Set information about the currently running Bro version. +##! The most convenient way to access this are the Version::num +##! and Version::info constants. + +@load base/frameworks/reporter +@load base/utils/strings + +module Version; + +export { + ## A type exactly describing a bro version + type VersionDescription: record { + ## Number representing the version which can be used for easy comparison. + ## The format of the number is ABBCC with A being the major version, + ## bb being the minor version (2 digits) and CC being the patchlevel (2 digits). + ## As an example, Bro 2.4.1 results in the number 20401 + version_num: count; + ## Major version number (e.g. 2 for 2.5) + major: count; + ## Minor version number (e.g. 5 for 2.5) + minor: count; + ## Patch version number (e.g. 0 for 2.5 or 1 for 2.4.1) + patch: count; + ## Commit number for development versions, e.g. 12 for 2.4-12. 0 for non-development versions + commit: count; + ## If set to true, the version is a beta build of bro + beta: bool; + ## If set to true, the version is a debug build + debug: bool; + ## String representation of this version + version_string: string; + }; + + ## Parse a given version string. + ## + ## version_string: Bro version string. + ## + ## Returns: `VersionDescription` record. + global parse: function(version_string: string): VersionDescription; + + ## Test if the current running version of Bro is greater or equal to the given version + ## string. + ## + ## version_string: Version to check against the current running version. + ## + ## Returns: True if running version greater or equal to the given version. + global greater_equal: function(version_string: string): bool; +} + +function parse(version_string: string): VersionDescription + { + if ( /[[:digit:]]\.[[:digit:]][[:digit:]]?(\.[[:digit:]][[:digit:]]?)?(\-beta)?(-[[:digit:]]+)?(\-debug)?/ != version_string ) + { + Reporter::error(fmt("Version string %s cannot be parsed", version_string)); + return VersionDescription($version_num=0, $major=0, $minor=0, $patch=0, $commit=0, $beta=F, $debug=F, $version_string=version_string); + } + + local components = split_string1(version_string, /\-/); + local version_split = split_string(components[0], /\./); + local major = to_count(version_split[0]); + local minor = to_count(version_split[1]); + local patchlevel = ( |version_split| > 2) ? to_count(version_split[2]) : 0; + local version_num = major*10000+minor*100+patchlevel; + local beta = /\-beta/ in version_string; + local debug = /\-debug/ in version_string; + local commit = 0; + if ( |components| > 1 ) + { + local commitpart = find_last(components[1], /\-[[:digit:]]+/); + commit = ( |commitpart| > 0 ) ? to_count(sub_bytes(commitpart, 2, 999)) : 0; + } + + return VersionDescription($version_num=version_num, $major=major, $minor=minor, $patch=patchlevel, $commit=commit, $beta=beta, $debug=debug, $version_string=version_string); + } + +export { + ## version number of the currently running version of Bro as a numeric representation. + ## The format of the number is ABBCC with A being the major version, + ## bb being the minor version (2 digits) and CC being the patchlevel (2 digits). + ## As an example, Bro 2.4.1 results in the number 20401 + const num = Version::parse(bro_version())$version_num; + + ## `VersionDescription` record pertaining to the currently running version of Bro. + const info = Version::parse(bro_version()); +} + +function greater_equal(version_string: string): bool + { + return Version::parse(version_string)$version_num >= Version::num; + } diff --git a/src/strings.bif b/src/strings.bif index 914baaebbf..5a1ee5161d 100644 --- a/src/strings.bif +++ b/src/strings.bif @@ -349,7 +349,8 @@ static int match_prefix(int s_len, const char* s, int t_len, const char* t) VectorVal* do_split_string(StringVal* str_val, RE_Matcher* re, int incl_sep, int max_num_sep) { - VectorVal* rval = new VectorVal(string_vec); + // string_vec is used early in the version script - do not use the NetVar. + VectorVal* rval = new VectorVal(internal_type("string_vec")->AsVectorType()); const u_char* s = str_val->Bytes(); int n = str_val->Len(); const u_char* end_of_s = s + n; diff --git a/testing/btest/Baseline/scripts.base.misc.version-2/.stderr b/testing/btest/Baseline/scripts.base.misc.version-2/.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/scripts.base.misc.version-2/.stdout b/testing/btest/Baseline/scripts.base.misc.version-2/.stdout new file mode 100644 index 0000000000..aad2c94307 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.misc.version-2/.stdout @@ -0,0 +1,3 @@ +yup +yup +yup diff --git a/testing/btest/Baseline/scripts.base.misc.version/.stderr b/testing/btest/Baseline/scripts.base.misc.version/.stderr new file mode 100644 index 0000000000..b4151671b7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.misc.version/.stderr @@ -0,0 +1,4 @@ +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string 1 cannot be parsed +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string 12.5 cannot be parsed +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string 1.12-beta-drunk cannot be parsed +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string JustARandomString cannot be parsed diff --git a/testing/btest/Baseline/scripts.base.misc.version/.stdout b/testing/btest/Baseline/scripts.base.misc.version/.stdout new file mode 100644 index 0000000000..c6fd315164 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.misc.version/.stdout @@ -0,0 +1,12 @@ +[version_num=10500, major=1, minor=5, patch=0, commit=0, beta=F, debug=F, version_string=1.5] +[version_num=20000, major=2, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=2.0] +[version_num=20500, major=2, minor=5, patch=0, commit=0, beta=T, debug=F, version_string=2.5-beta] +[version_num=20501, major=2, minor=5, patch=1, commit=0, beta=F, debug=T, version_string=2.5.1-debug] +[version_num=20500, major=2, minor=5, patch=0, commit=12, beta=T, debug=F, version_string=2.5-beta-12] +[version_num=20500, major=2, minor=5, patch=0, commit=0, beta=F, debug=T, version_string=2.5-12-debug] +[version_num=20502, major=2, minor=5, patch=2, commit=12, beta=T, debug=T, version_string=2.5.2-beta-12-debug] +[version_num=11220, major=1, minor=12, patch=20, commit=2562, beta=T, debug=T, version_string=1.12.20-beta-2562-debug] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=1] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=12.5] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=1.12-beta-drunk] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=JustARandomString] diff --git a/testing/btest/scripts/base/misc/version.bro b/testing/btest/scripts/base/misc/version.bro new file mode 100644 index 0000000000..43d78a6662 --- /dev/null +++ b/testing/btest/scripts/base/misc/version.bro @@ -0,0 +1,40 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff .stderr + +# good versions +print Version::parse("1.5"); +print Version::parse("2.0"); +print Version::parse("2.5-beta"); +print Version::parse("2.5.1-debug"); +print Version::parse("2.5-beta-12"); +print Version::parse("2.5-12-debug"); +print Version::parse("2.5.2-beta-12-debug"); +print Version::parse("1.12.20-beta-2562-debug"); + +# bad versions +print Version::parse("1"); +print Version::parse("12.5"); +print Version::parse("1.12-beta-drunk"); +print Version::parse("JustARandomString"); + +# check that current running version of Bro parses without error +Version::parse(bro_version()); + +@TEST-START-NEXT + +@if ( Version::num >= 20500 ) +print "yup"; +@endif + +@if ( Version::parse("1.5")$version_num < 20500 ) +print "yup"; +@endif + +@if ( Version::greater_equal("2.5") ) +print "yup"; +@endif + +@if ( Version::greater_equal("2.4") ) +print "no"; +@endif