diff options
| author | root <[email protected]> | 2024-09-03 07:01:58 +0000 |
|---|---|---|
| committer | root <[email protected]> | 2024-09-03 07:01:58 +0000 |
| commit | 6f1ac6b36b28d082cebf8e4c3eeedd592c1946f9 (patch) | |
| tree | 5c664bc282e5c01b634430531e43dae44dc50538 | |
| parent | a8206cffc0ba55c6cb2b0b1054860ee28ec4a0b8 (diff) | |
add socks_decoder, stratum_decoder and session_flags
160 files changed, 11861 insertions, 1 deletions
diff --git a/decoders/CMakeLists.txt b/decoders/CMakeLists.txt index 2d71d23..8b3f7a9 100644 --- a/decoders/CMakeLists.txt +++ b/decoders/CMakeLists.txt @@ -1,2 +1,5 @@ add_subdirectory(http) add_subdirectory(lpi) +add_subdirectory(socks) +add_subdirectory(stratum) +add_subdirectory(session_flags)
\ No newline at end of file diff --git a/decoders/session_flags/CMakeLists.txt b/decoders/session_flags/CMakeLists.txt new file mode 100644 index 0000000..3302328 --- /dev/null +++ b/decoders/session_flags/CMakeLists.txt @@ -0,0 +1,15 @@ +add_subdirectory(mesa_sts) +add_definitions(-fPIC) + +set(SESSION_FLAGS_SRC session_flags_plugin.cpp session_flags.cpp fet.cpp tunneling.cpp onlinemean.c) + +add_library(session_flags STATIC ${SESSION_FLAGS_SRC}) +add_library(session_flags_dyn SHARED ${SESSION_FLAGS_SRC}) +set_target_properties(session_flags PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/version.map") +target_include_directories(session_flags PUBLIC ${CMAKE_SOURCE_DIR}/deps/) +include_directories(${CMAKE_BINARY_DIR}/vendors/cjson/src/cjson/include) +target_link_libraries(session_flags toml cjson-static hyperscan_static hyperscan_runtime_static libmesa_sts) +set_target_properties(session_flags PROPERTIES PREFIX "") + +set_target_properties(session_flags_dyn PROPERTIES PREFIX "") +target_link_libraries(session_flags_dyn toml cjson-static hyperscan_static hyperscan_runtime_static libmesa_sts)
\ No newline at end of file diff --git a/decoders/session_flags/fet.cpp b/decoders/session_flags/fet.cpp new file mode 100644 index 0000000..61327d4 --- /dev/null +++ b/decoders/session_flags/fet.cpp @@ -0,0 +1,123 @@ +/*ref: https://github.com/apernet/OpenGFW/blob/1dce82745d0bc8b3813aea147954ba3a2294ef30/analyzer/tcp/fet.go +https://www.usenix.org/system/files/usenixsecurity23-wu-mingshi.pdf +*/ + +#include <string.h> +#include <stdlib.h> +#include "fet.h" + +bool isPrintable(unsigned char b) { + return b >= 0x20 && b <= 0x7e; +} + +int popCount(unsigned char b) { + int count = 0; + while (b != 0) { + count += (int)(b & 1); + b >>= 1; + } + return count; +} + +float averagePopCount(const unsigned char* bytes, int bytes_len) { + if (bytes_len == 0) { + return 0; + } + int total = 0; + for (int i = 0; i < bytes_len; i++) { + total += popCount(bytes[i]); + } + return (float)total / (float)bytes_len; +} + +bool isFirstSixPrintable(const unsigned char* bytes, int bytes_len) { + if (bytes_len < 6) { + return false; + } + for (int i = 0; i < 6; i++) { + if (!isPrintable(bytes[i])) { + return false; + } + } + return true; +} + +float printablePercentage(const unsigned char* bytes, int bytes_len) { + if (bytes_len == 0) { + return 0; + } + int count = 0; + for (int i = 0; i < bytes_len; i++) { + if (isPrintable(bytes[i])) { + count++; + } + } + return (float)count / (float)bytes_len; +} + +int contiguousPrintable(const unsigned char* bytes, int bytes_len) { + if (bytes_len == 0) { + return 0; + } + int maxCount = 0; + int current = 0; + for (int i = 0; i < bytes_len; i++) { + if (isPrintable(bytes[i])) { + current++; + } else { + if (current > maxCount) { + maxCount = current; + } + current = 0; + } + } + if (current > maxCount) { + maxCount = current; + } + return maxCount; +} + +bool isTLS(const unsigned char* bytes, int bytes_len) { + if (bytes_len < 3) { + return false; + } + // "We observe that the GFW exempts any connection whose first + // three bytes match the following regular expression: + // [\x16-\x17]\x03[\x00-\x09]" - from the paper in Section 4.3 + if (bytes[0] >= 0x16 && bytes[0] <= 0x17 && + bytes[1] == 0x03 && bytes[2] <= 0x09) { + return true; + } + + return false; +} + +bool isHTTP(const unsigned char* bytes, int bytes_len) { + if (bytes_len < 3) { + return false; + } + + // HTTP request + bool result = memcmp(bytes, "GET", 3) == 0 || memcmp(bytes, "HEA", 3) == 0 || memcmp(bytes, "POS", 3) == 0 || + memcmp(bytes, "PUT", 3) == 0 || memcmp(bytes, "DEL", 3) == 0 || memcmp(bytes, "CON", 3) == 0 || + memcmp(bytes, "OPT", 3) == 0 || memcmp(bytes, "TRA", 3) == 0 || memcmp(bytes, "PAT", 3) == 0; + + return result; +} + +int is_data_fet(unsigned char* data, int data_len, struct fet_detail* detail) { + if (data_len == 0) { + return 0; + } + float ex1 = averagePopCount(data, data_len); + bool ex2 = isFirstSixPrintable(data, data_len); + float ex3 = printablePercentage(data, data_len); + int ex4 = contiguousPrintable(data, data_len); + bool ex5 = isTLS(data, data_len); + bool ex6 = isHTTP(data, data_len); + bool exempt = (ex1 <= 3.4 || ex1 >= 4.6) || ex2 || ex3 > 0.5 || ex4 > 20 || ex5 || ex6; + + detail->is_tls = ex5; + + return !exempt; +}
\ No newline at end of file diff --git a/decoders/session_flags/fet.h b/decoders/session_flags/fet.h new file mode 100644 index 0000000..d752ec3 --- /dev/null +++ b/decoders/session_flags/fet.h @@ -0,0 +1,7 @@ +#pragma once + +struct fet_detail { + bool is_tls; +}; + +int is_data_fet(unsigned char* data, int data_len, struct fet_detail* detail);
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/CMakeLists.txt b/decoders/session_flags/mesa_sts/CMakeLists.txt new file mode 100644 index 0000000..fc6f629 --- /dev/null +++ b/decoders/session_flags/mesa_sts/CMakeLists.txt @@ -0,0 +1,15 @@ + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/) + +file(GLOB STS_SRC + "src/*.c" +) + +#add_compile_options(-Wno-error=unused-parameter -Wno-unused-but-set-variable -Wno-error=misleading-indentation -Wno-unused-variable -Wno-maybe-uninitialized -Wno-error=unused-function) +add_library(libmesa_sts ${STS_SRC}) +target_include_directories(libmesa_sts PUBLIC ${CMAKE_SOURCE_DIR}/decoders/session_flags/mesa_sts/include) +target_compile_options(libmesa_sts PRIVATE -Wno-error=unused-parameter -Wno-unused-but-set-variable -Wno-error=misleading-indentation -Wno-unused-variable -Wno-maybe-uninitialized -Wno-error=unused-function) +set_target_properties(libmesa_sts PROPERTIES LINK_FLAGS + "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/version.map") + +add_subdirectory(test) diff --git a/decoders/session_flags/mesa_sts/include/mesa_sts.h b/decoders/session_flags/mesa_sts/include/mesa_sts.h new file mode 100644 index 0000000..ee56102 --- /dev/null +++ b/decoders/session_flags/mesa_sts/include/mesa_sts.h @@ -0,0 +1,57 @@ +#ifndef _MESA_STS_H_ +#define _MESA_STS_H_ + +#define STS_RANDOM_JUDGE_NUM 15 + +#define STS_SET_FLAG(flag, idx) (flag |= (1 << idx)) +#define STS_TEST_FLAG(flag, idx) (flag & (1 << idx)) + +enum sts_random_judge_list_idx +{ + STS_FREQUENCY = 0, + STS_BLOCK_FREQUENCY, + STS_CUMULATIVE_SUMS, + STS_RUNS, + STS_LONGEST_RUN, + STS_RANK, + STS_NON_OVERLAPPING_TEMPLATE_MATCHING, + STS_OVERLAPPING_TEMPLATE_MATCHING, + STS_UNIVERSAL, + STS_RANDOM_EXCURSIONS, + STS_RANDOM_EXCURSIONS_VARIANT, + STS_POKER_DETECT, + STS_RUNS_DISTRIBUTION, + STS_SELF_CORRELATION, + STS_BINARY_DERIVATE, + STS_RANDOM_IDX_MAX +}; + +struct sts_result { + unsigned char frequency; + unsigned char block_frequency; + unsigned char cumulative_sums; + unsigned char runs; + unsigned char longest_run; + unsigned char rank; + unsigned char non_overlapping_template_matching; + unsigned char overlapping_template_matching; + unsigned char universal; + unsigned char random_excursions; + unsigned char random_excursions_variant; + unsigned char poker_detect; + unsigned char runs_distribution; + unsigned char self_correlation; + unsigned char binary_derivative; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int mesa_statistical_test_suite(void* data,unsigned int datalen, struct sts_result* result, unsigned int random_judge_switch_flag); + +#ifdef __cplusplus +} +#endif + +#endif /* _MESA_STS_H_ */ diff --git a/decoders/session_flags/mesa_sts/src/approximateEntropy.c b/decoders/session_flags/mesa_sts/src/approximateEntropy.c new file mode 100644 index 0000000..b386056 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/approximateEntropy.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + A P P R O X I M A T E E N T R O P Y T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +ApproximateEntropy(int m, int n, BitSequence *epsilon) +{ + int i, j, k, r, blockSize, seqLength, powLen, index; + double sum, numOfBlocks, ApEn[2], apen, chi_squared, p_value; + unsigned int *P; + + seqLength = n; + r = 0; + + for ( blockSize=m; blockSize<=m+1; blockSize++ ) { + if ( blockSize == 0 ) { + ApEn[0] = 0.00; + r++; + } + else { + numOfBlocks = (double)seqLength; + powLen = (int)pow(2, blockSize+1)-1; + if ( (P = (unsigned int*)calloc(powLen,sizeof(unsigned int)))== NULL ) { + return 0; + } + for ( i=1; i<powLen-1; i++ ) + P[i] = 0; + for ( i=0; i<numOfBlocks; i++ ) { /* COMPUTE FREQUENCY */ + k = 1; + for ( j=0; j<blockSize; j++ ) { + k <<= 1; + if ( (int)epsilon[(i+j) % seqLength] == 1 ) + k++; + } + P[k-1]++; + } + /* DISPLAY FREQUENCY */ + sum = 0.0; + index = (int)pow(2, blockSize)-1; + for ( i=0; i<(int)pow(2, blockSize); i++ ) { + if ( P[index] > 0 ) + sum += P[index]*log(P[index]/numOfBlocks); + index++; + } + sum /= numOfBlocks; + ApEn[r] = sum; + r++; + free(P); + } + } + apen = ApEn[0] - ApEn[1]; + + chi_squared = 2.0*seqLength*(log(2) - apen); + p_value = cephes_igamc(pow(2, m-1), chi_squared/2.0); + + if ( m > (int)(log(seqLength)/log(2)-5) ) { + return 0; + } + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/binaryDerivate.c b/decoders/session_flags/mesa_sts/src/binaryDerivate.c new file mode 100644 index 0000000..6d2dc4a --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/binaryDerivate.c @@ -0,0 +1,30 @@ +#include <math.h> +#include "include/stat_fncs.h" + +int BinaryDerivate(int k, int n, BitSequence *epsilon, int epsilon_l) +{ + int i = 0, j = 0; + int Sn_k = 0; + int n_k = n - k; + double V = 0.0, p_value = 0.0, sqrt2 = 1.41421356237309504880; + + for (i = 0; i < k; ++i) { + for (j = 0; j < epsilon_l - 1; ++j) { + epsilon[j] = epsilon[j] ^ epsilon[j + 1]; + } + } + + for (i = 0; i < n_k; ++i) { + Sn_k += (2 * (int)epsilon[i]) - 1; + } + + V = fabs(Sn_k) / sqrt(n_k); + + p_value = erfc(fabs(V) / sqrt2); + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/blockFrequency.c b/decoders/session_flags/mesa_sts/src/blockFrequency.c new file mode 100644 index 0000000..ba4ad34 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/blockFrequency.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + B L O C K F R E Q U E N C Y T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +BlockFrequency(int M, int n, BitSequence *epsilon) +{ + int i, j, N, blockSum; + double p_value, sum, pi, v, chi_squared; + + N = n/M; /* # OF SUBSTRING BLOCKS */ + sum = 0.0; + + for ( i=0; i<N; i++ ) { + blockSum = 0; + for ( j=0; j<M; j++ ) + blockSum += epsilon[j+i*M]; + pi = (double)blockSum/(double)M; + v = pi - 0.5; + sum += v*v; + } + chi_squared = 4.0 * M * sum; + p_value = cephes_igamc(N/2.0, chi_squared/2.0); + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +} diff --git a/decoders/session_flags/mesa_sts/src/bytesToBitSequence.c b/decoders/session_flags/mesa_sts/src/bytesToBitSequence.c new file mode 100644 index 0000000..5953702 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/bytesToBitSequence.c @@ -0,0 +1,31 @@ +#include "include/stat_fncs.h" + +static unsigned char _compute(unsigned char b, unsigned char factor) +{ + if ((factor & b) == factor) { + return 0x01; + } else { + return 0x00; + } +} + +int BytesToBitSequence(unsigned char *in, int inl, BitSequence *outbuf, int bufsize) +{ + int j = 0, i = 0; + if (bufsize < inl * 8) { + return 0; + } + + for (i = 0; i < inl; ++i) { + j = i * 8; + outbuf[j] = (BitSequence) (_compute(in[i], 0x80)); + outbuf[j + 1] = (BitSequence) (_compute(in[i], 0x40)); + outbuf[j + 2] = (BitSequence) (_compute(in[i], 0x20)); + outbuf[j + 3] = (BitSequence) (_compute(in[i], 0x10)); + outbuf[j + 4] = (BitSequence) (_compute(in[i], 0x08)); + outbuf[j + 5] = (BitSequence) (_compute(in[i], 0x04)); + outbuf[j + 6] = (BitSequence) (_compute(in[i], 0x02)); + outbuf[j + 7] = (BitSequence) (_compute(in[i], 0x01)); + } + return 1; +} diff --git a/decoders/session_flags/mesa_sts/src/cephes.c b/decoders/session_flags/mesa_sts/src/cephes.c new file mode 100644 index 0000000..a419f27 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/cephes.c @@ -0,0 +1,348 @@ +#include <stdio.h> +#include <math.h> +#include "include/cephes.h" + +static const double rel_error = 1E-12; + +double MACHEP = 1.11022302462515654042E-16; // 2**-53 +double MAXLOG = 7.09782712893383996732224E2; // log(MAXNUM) +double MAXNUM = 1.7976931348623158E308; // 2**1024*(1-MACHEP) +double PI = 3.14159265358979323846; // pi, duh! + +static double big = 4.503599627370496e15; +static double biginv = 2.22044604925031308085e-16; + +int sgngam = 0; + +double +cephes_igamc(double a, double x) +{ + double ans, ax, c, yc, r, t, y, z; + double pk, pkm1, pkm2, qk, qkm1, qkm2; + + if ( (x <= 0) || ( a <= 0) ) + return( 1.0 ); + + if ( (x < 1.0) || (x < a) ) + return( 1.e0 - cephes_igam(a,x) ); + + ax = a * log(x) - x - cephes_lgam(a); + + if ( ax < -MAXLOG ) { + printf("igamc: UNDERFLOW\n"); + return 0.0; + } + ax = exp(ax); + + /* continued fraction */ + y = 1.0 - a; + z = x + y + 1.0; + c = 0.0; + pkm2 = 1.0; + qkm2 = x; + pkm1 = x + 1.0; + qkm1 = z * x; + ans = pkm1/qkm1; + + do { + c += 1.0; + y += 1.0; + z += 2.0; + yc = y * c; + pk = pkm1 * z - pkm2 * yc; + qk = qkm1 * z - qkm2 * yc; + if ( qk != 0 ) { + r = pk/qk; + t = fabs( (ans - r)/r ); + ans = r; + } + else + t = 1.0; + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + if ( fabs(pk) > big ) { + pkm2 *= biginv; + pkm1 *= biginv; + qkm2 *= biginv; + qkm1 *= biginv; + } + } while ( t > MACHEP ); + + return ans*ax; +} + +double +cephes_igam(double a, double x) +{ + double ans, ax, c, r; + + if ( (x <= 0) || ( a <= 0) ) + return 0.0; + + if ( (x > 1.0) && (x > a ) ) + return 1.e0 - cephes_igamc(a,x); + + /* Compute x**a * exp(-x) / gamma(a) */ + ax = a * log(x) - x - cephes_lgam(a); + if ( ax < -MAXLOG ) { + printf("igam: UNDERFLOW\n"); + return 0.0; + } + ax = exp(ax); + + /* power series */ + r = a; + c = 1.0; + ans = 1.0; + + do { + r += 1.0; + c *= x/r; + ans += c; + } while ( c/ans > MACHEP ); + + return ans * ax/a; +} + +union A_Array { + double d[5]; + unsigned short us[20]; +}; + + +union BC_Array { + double d[6]; + unsigned short us[24]; +}; + +/* A[]: Stirling's formula expansion of log gamma + * B[], C[]: log gamma function between 2 and 3 + */ + +/**/ +static union A_Array A = { + .us = { + 0x6661,0x2733,0x9850,0x3f4a, + 0xe943,0xb580,0x7fbd,0xbf43, + 0x5ebb,0x20dc,0x019f,0x3f4a, + 0xa5a1,0x16b0,0xc16c,0xbf66, + 0x554b,0x5555,0x5555,0x3fb5 + } +}; +static union BC_Array B = { + .us = { + 0x6761,0x8ff3,0x8901,0xc095, + 0xb93e,0x355b,0xf234,0xc0e2, + 0x89e5,0xf890,0x3d73,0xc114, + 0xdb51,0xf994,0xbc82,0xc131, + 0xf20b,0x0219,0x4589,0xc13a, + 0x055e,0x5418,0x0c67,0xc12a + } +}; +static union BC_Array C = { + /*0x0000,0x0000,0x0000,0x3ff0,*/ + .us = { + 0x12b2,0x1cf3,0xfd0d,0xc075, + 0xd757,0x7b89,0xaa0d,0xc0d0, + 0x4c9b,0xb974,0xeb84,0xc10a, + 0x0043,0x7195,0x6286,0xc131, + 0xf34c,0x892f,0x5255,0xc143, + 0xe14a,0x6a11,0xce4b,0xc13e + } +}; + +#define MAXLGM 2.556348e305 + + +/* Logarithm of gamma function */ +double +cephes_lgam(double x) +{ + double p, q, u, w, z; + int i; + + sgngam = 1; + + if ( x < -34.0 ) { + q = -x; + w = cephes_lgam(q); /* note this modifies sgngam! */ + p = floor(q); + if ( p == q ) { +lgsing: + goto loverf; + } + i = (int)p; + if ( (i & 1) == 0 ) + sgngam = -1; + else + sgngam = 1; + z = q - p; + if ( z > 0.5 ) { + p += 1.0; + z = p - q; + } + z = q * sin( PI * z ); + if ( z == 0.0 ) + goto lgsing; + /* z = log(PI) - log( z ) - w;*/ + z = log(PI) - log( z ) - w; + return z; + } + + if ( x < 13.0 ) { + z = 1.0; + p = 0.0; + u = x; + while ( u >= 3.0 ) { + p -= 1.0; + u = x + p; + z *= u; + } + while ( u < 2.0 ) { + if ( u == 0.0 ) + goto lgsing; + z /= u; + p += 1.0; + u = x + p; + } + if ( z < 0.0 ) { + sgngam = -1; + z = -z; + } + else + sgngam = 1; + if ( u == 2.0 ) + return( log(z) ); + p -= 2.0; + x = x + p; + p = x * cephes_polevl( x, (double *)B.d, 5 ) / cephes_p1evl( x, (double *)C.d, 6); + + return log(z) + p; + } + + if ( x > MAXLGM ) { +loverf: + printf("lgam: OVERFLOW\n"); + + return sgngam * MAXNUM; + } + + q = ( x - 0.5 ) * log(x) - x + log( sqrt( 2*PI ) ); + if ( x > 1.0e8 ) + return q; + + p = 1.0/(x*x); + if ( x >= 1000.0 ) + q += (( 7.9365079365079365079365e-4 * p + - 2.7777777777777777777778e-3) *p + + 0.0833333333333333333333) / x; + else + q += cephes_polevl( p, (double *)A.d, 4 ) / x; + + return q; +} + +double +cephes_polevl(double x, double *coef, int N) +{ + double ans; + int i; + double *p; + + p = coef; + ans = *p++; + i = N; + + do + ans = ans * x + *p++; + while ( --i ); + + return ans; +} + +double +cephes_p1evl(double x, double *coef, int N) +{ + double ans; + double *p; + int i; + + p = coef; + ans = x + *p++; + i = N-1; + + do + ans = ans * x + *p++; + while ( --i ); + + return ans; +} + +double +cephes_erf(double x) +{ + static const double two_sqrtpi = 1.128379167095512574; + double sum = x, term = x, xsqr = x * x; + int j = 1; + + if ( fabs(x) > 2.2 ) + return 1.0 - cephes_erfc(x); + + do { + term *= xsqr/j; + sum -= term/(2*j+1); + j++; + term *= xsqr/j; + sum += term/(2*j+1); + j++; + } while ( fabs(term)/sum > rel_error ); + + return two_sqrtpi*sum; +} + +double +cephes_erfc(double x) +{ + static const double one_sqrtpi = 0.564189583547756287; + double a = 1, b = x, c = x, d = x*x + 0.5; + double q1, q2 = b/d, n = 1.0, t; + + if ( fabs(x) < 2.2 ) + return 1.0 - cephes_erf(x); + if ( x < 0 ) + return 2.0 - cephes_erfc(-x); + + do { + t = a*n + b*x; + a = b; + b = t; + t = c*n + d*x; + c = d; + d = t; + n += 0.5; + q1 = q2; + q2 = b/d; + } while ( fabs(q1-q2)/q2 > rel_error ); + + return one_sqrtpi*exp(-x*x)*q2; +} + + +double +cephes_normal(double x) +{ + double arg, result, sqrt2=1.414213562373095048801688724209698078569672; + + if (x > 0) { + arg = x/sqrt2; + result = 0.5 * ( 1 + erf(arg) ); + } + else { + arg = -x/sqrt2; + result = 0.5 * (erfc(arg) ); + } + + return( result); +} diff --git a/decoders/session_flags/mesa_sts/src/cusum.c b/decoders/session_flags/mesa_sts/src/cusum.c new file mode 100644 index 0000000..d9be4e1 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/cusum.c @@ -0,0 +1,95 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + C U M U L A T I V E S U M S T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +CumulativeSums(int n, BitSequence *epsilon) +{ + int S, sup, inf, z=1, zrev, k; + double sum1, sum2, p_value; + + S = 0; + sup = 0; + inf = 0; + for ( k=0; k<n; k++ ) { + epsilon[k] ? S++ : S--; + if ( S > sup ) + sup++; + if ( S < inf ) + inf--; + z = (sup > -inf) ? sup : -inf; + zrev = (sup-S > S-inf) ? sup-S : S-inf; + } + + // forward + sum1 = 0.0; + for ( k=(-n/z+1)/4; k<=(n/z-1)/4; k++ ) { + sum1 += cephes_normal(((4*k+1)*z)/sqrt(n)); + sum1 -= cephes_normal(((4*k-1)*z)/sqrt(n)); + } + sum2 = 0.0; + for ( k=(-n/z-3)/4; k<=(n/z-1)/4; k++ ) { + sum2 += cephes_normal(((4*k+3)*z)/sqrt(n)); + sum2 -= cephes_normal(((4*k+1)*z)/sqrt(n)); + } + + p_value = 1.0 - sum1 + sum2; + +// fprintf(stats[TEST_CUSUM], "\t\t CUMULATIVE SUMS (FORWARD) TEST\n"); +// fprintf(stats[TEST_CUSUM], "\t\t-------------------------------------------\n"); +// fprintf(stats[TEST_CUSUM], "\t\tCOMPUTATIONAL INFORMATION:\n"); +// fprintf(stats[TEST_CUSUM], "\t\t-------------------------------------------\n"); +// fprintf(stats[TEST_CUSUM], "\t\t(a) The maximum partial sum = %d\n", z); +// fprintf(stats[TEST_CUSUM], "\t\t-------------------------------------------\n"); + + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { +// fprintf(stats[TEST_CUSUM], "\t\tWARNING: P_VALUE IS OUT OF RANGE\n"); + return 0; + } + +// fprintf(stats[TEST_CUSUM], "%s\t\tp_value = %f\n\n", p_value < ALPHA ? "FAILURE" : "SUCCESS", p_value); +// fprintf(results[TEST_CUSUM], "%f\n", p_value); + if (p_value < ALPHA) { + return 0; + } + + // backwards + sum1 = 0.0; + for ( k=(-n/zrev+1)/4; k<=(n/zrev-1)/4; k++ ) { + sum1 += cephes_normal(((4*k+1)*zrev)/sqrt(n)); + sum1 -= cephes_normal(((4*k-1)*zrev)/sqrt(n)); + } + sum2 = 0.0; + for ( k=(-n/zrev-3)/4; k<=(n/zrev-1)/4; k++ ) { + sum2 += cephes_normal(((4*k+3)*zrev)/sqrt(n)); + sum2 -= cephes_normal(((4*k+1)*zrev)/sqrt(n)); + } + p_value = 1.0 - sum1 + sum2; + +// fprintf(stats[TEST_CUSUM], "\t\t CUMULATIVE SUMS (REVERSE) TEST\n"); +// fprintf(stats[TEST_CUSUM], "\t\t-------------------------------------------\n"); +// fprintf(stats[TEST_CUSUM], "\t\tCOMPUTATIONAL INFORMATION:\n"); +// fprintf(stats[TEST_CUSUM], "\t\t-------------------------------------------\n"); +// fprintf(stats[TEST_CUSUM], "\t\t(a) The maximum partial sum = %d\n", zrev); +// fprintf(stats[TEST_CUSUM], "\t\t-------------------------------------------\n"); + + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { +// fprintf(stats[TEST_CUSUM], "\t\tWARNING: P_VALUE IS OUT OF RANGE\n"); + return 0; + } + +// fprintf(stats[TEST_CUSUM], "%s\t\tp_value = %f\n\n", p_value < ALPHA ? "FAILURE" : "SUCCESS", p_value); fflush(stats[TEST_CUSUM]); +// fprintf(results[TEST_CUSUM], "%f\n", p_value); fflush(results[TEST_CUSUM]); + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/dfft.c b/decoders/session_flags/mesa_sts/src/dfft.c new file mode 100644 index 0000000..71c0efd --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/dfft.c @@ -0,0 +1,1462 @@ +/* Notes from RFB: + +Looks like the user-level routines are: + +Real FFT + +void __ogg_fdrffti(int n, double *wsave, int *ifac) +void __ogg_fdrfftf(int n, double *r, double *wsave, int *ifac) +void __ogg_fdrfftb(int n, double *r, double *wsave, int *ifac) + +__ogg_fdrffti == initialization +__ogg_fdrfftf == forward transform +__ogg_fdrfftb == backward transform + +Parameters are +n == length of sequence +r == sequence to be transformed (input) +== transformed sequence (output) +wsave == work array of length 2n (allocated by caller) +ifac == work array of length 15 (allocated by caller) + +Cosine quarter-wave FFT + +void __ogg_fdcosqi(int n, double *wsave, int *ifac) +void __ogg_fdcosqf(int n, double *x, double *wsave, int *ifac) +void __ogg_fdcosqb(int n, double *x, double *wsave, int *ifac) +*/ + +/******************************************************************** +* * +* THIS FILE IS PART OF THE OggSQUISH SOFTWARE CODEC SOURCE CODE. * +* * +******************************************************************** + +file: fft.c +function: Fast discrete Fourier and cosine transforms and inverses +author: Monty <[email protected]> +modifications by: Monty +last modification date: Jul 1 1996 + +********************************************************************/ + +/* These Fourier routines were originally based on the Fourier +routines of the same names from the NETLIB bihar and fftpack +fortran libraries developed by Paul N. Swarztrauber at the National +Center for Atmospheric Research in Boulder, CO USA. They have been +reimplemented in C and optimized in a few ways for OggSquish. */ + +/* As the original fortran libraries are public domain, the C Fourier +routines in this file are hereby released to the public domain as +well. The C routines here produce output exactly equivalent to the +original fortran routines. Of particular interest are the facts +that (like the original fortran), these routines can work on +arbitrary length vectors that need not be powers of two in +length. */ + +#include <math.h> +#define STIN static + +static void drfti1(int n, double *wa, int *ifac) +{ + static const int ntryh[4] = { 4,2,3,5 }; + static double tpi = 6.28318530717958647692528676655900577; + double arg, argh, argld, fi; + int ntry=0,i,j=-1; + int k1, l1, l2, ib; + int ld, ii, ip, is, nq, nr; + int ido, ipm, nfm1; + int nl=n; + int nf=0; + +L101: + j++; + if ( j < 4 ) + ntry = ntryh[j]; + else + ntry += 2; + +L104: + nq = nl/ntry; + nr = nl-ntry*nq; + if ( nr != 0 ) + goto L101; + + nf++; + ifac[nf+1] = ntry; + nl = nq; + if ( ntry != 2 ) + goto L107; + if ( nf == 1 ) + goto L107; + + for ( i=1; i<nf; i++ ) { + ib = nf-i+1; + ifac[ib+1] = ifac[ib]; + } + ifac[2] = 2; + +L107: + if( nl != 1 ) + goto L104; + ifac[0] = n; + ifac[1] = nf; + argh = tpi/n; + is = 0; + nfm1 = nf-1; + l1 = 1; + + if ( nfm1 == 0 ) + return; + + for ( k1=0; k1<nfm1; k1++ ) { + ip = ifac[k1+2]; + ld = 0; + l2 = l1*ip; + ido = n/l2; + ipm = ip-1; + + for ( j=0; j<ipm; j++ ) { + ld += l1; + i = is; + argld = (double)ld*argh; + fi = 0.0; + for ( ii=2; ii<ido; ii+=2 ) { + fi += 1.0; + arg = fi*argld; + wa[i++] = cos(arg); + wa[i++] = sin(arg); + } + is += ido; + } + l1 = l2; + } +} + +void __ogg_fdrffti(int n, double *wsave, int *ifac) +{ + if ( n == 1 ) + return; + drfti1(n, wsave+n, ifac); +} + +#ifdef LBBBBBBBBBBBBB + +void __ogg_fdcosqi(int n, double *wsave, int *ifac) +{ + static double pih = 1.57079632679489661923132169163975; + static int k; + static double fk, dt; + + dt = pih/n; + fk = 0.0; + for ( k=0; k<n; k++ ) { + fk += 1.0; + wsave[k] = cos(fk*dt); + } + + __ogg_fdrffti(n, wsave+n,ifac); +} + +#endif + +STIN void dradf2(int ido, int l1, double *cc, double *ch, double *wa1) +{ + int i , k; + double ti2 , tr2; + int t0 , t1, t2, t3, t4, t5, t6; + + t1 = 0; + t0 = (t2 = l1*ido); + t3 = ido<<1; + for ( k=0; k<l1; k++ ) { + ch[t1<<1] = cc[t1]+cc[t2]; + ch[(t1<<1)+t3-1] = cc[t1]-cc[t2]; + t1 += ido; + t2 += ido; + } + + if ( ido < 2 ) + return; + if ( ido == 2 ) + goto L105; + + t1 = 0; + t2 = t0; + for ( k=0; k<l1; k++ ) { + t3 = t2; + t4 = (t1<<1)+(ido<<1); + t5 = t1; + t6 = t1+t1; + for ( i=2; i<ido; i+=2 ) { + t3 += 2; + t4 -= 2; + t5 += 2; + t6 += 2; + tr2 = wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3]; + ti2 = wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1]; + ch[t6] = cc[t5]+ti2; + ch[t4] = ti2-cc[t5]; + ch[t6-1] = cc[t5-1]+tr2; + ch[t4-1] = cc[t5-1]-tr2; + } + t1 += ido; + t2 += ido; + } + + if ( ido%2 == 1 ) + return; + +L105: + t3 = (t2 = (t1 = ido)-1); + t2 += t0; + for ( k=0; k<l1; k++ ) { + ch[t1] = -cc[t2]; + ch[t1-1] = cc[t3]; + t1 += ido<<1; + t2 += ido; + t3 += ido; + } +} + +STIN void dradf4(int ido, int l1, double *cc, double *ch, double *wa1, + double *wa2, double *wa3) +{ + static double hsqt2 = .70710678118654752440084436210485; + int i, k, t0, t1, t2, t3, t4, t5, t6; + double ci2, ci3, ci4, cr2, cr3, cr4; + double ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; + + t0 = l1*ido; + t1 = t0; + t4 = t1<<1; + t2 = t1+(t1<<1); + t3 = 0; + + for ( k=0; k<l1; k++ ) { + tr1 = cc[t1]+cc[t2]; + tr2 = cc[t3]+cc[t4]; + ch[t5 = t3<<2] = tr1+tr2; + ch[(ido<<2)+t5-1] = tr2-tr1; + ch[(t5 += (ido<<1))-1] = cc[t3]-cc[t4]; + ch[t5] = cc[t2]-cc[t1]; + + t1 += ido; + t2 += ido; + t3 += ido; + t4 += ido; + } + + if ( ido < 2 ) + return; + if ( ido == 2 ) + goto L105; + + t1 = 0; + for ( k=0; k<l1; k++ ) { + t2 = t1; + t4 = t1<<2; + t5 = (t6 = ido<<1)+t4; + for ( i=2; i<ido; i+=2 ) { + t3 = (t2 += 2); + t4 += 2; + t5 -= 2; + + t3 += t0; + cr2 = wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3]; + ci2 = wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1]; + t3 += t0; + cr3 = wa2[i-2]*cc[t3-1]+wa2[i-1]*cc[t3]; + ci3 = wa2[i-2]*cc[t3]-wa2[i-1]*cc[t3-1]; + t3 += t0; + cr4 = wa3[i-2]*cc[t3-1]+wa3[i-1]*cc[t3]; + ci4 = wa3[i-2]*cc[t3]-wa3[i-1]*cc[t3-1]; + + tr1 = cr2+cr4; + tr4 = cr4-cr2; + ti1 = ci2+ci4; + ti4 = ci2-ci4; + ti2 = cc[t2]+ci3; + ti3 = cc[t2]-ci3; + tr2 = cc[t2-1]+cr3; + tr3 = cc[t2-1]-cr3; + + + ch[t4-1] = tr1+tr2; + ch[t4] = ti1+ti2; + + ch[t5-1] = tr3-ti4; + ch[t5] = tr4-ti3; + + ch[t4+t6-1] = ti4+tr3; + ch[t4+t6] = tr4+ti3; + + ch[t5+t6-1] = tr2-tr1; + ch[t5+t6] = ti1-ti2; + } + t1 += ido; + } + if ( ido%2 == 1 ) + return; + +L105: + + t2 = (t1 = t0+ido-1)+(t0<<1); + t3 = ido<<2; + t4 = ido; + t5 = ido<<1; + t6 = ido; + + for ( k=0; k<l1; k++ ) { + ti1 = -hsqt2*(cc[t1]+cc[t2]); + tr1 = hsqt2*(cc[t1]-cc[t2]); + ch[t4-1] = tr1+cc[t6-1]; + ch[t4+t5-1] = cc[t6-1]-tr1; + ch[t4] = ti1-cc[t1+t0]; + ch[t4+t5] = ti1+cc[t1+t0]; + t1 += ido; + t2 += ido; + t4 += t3; + t6 += ido; + } +} + +STIN void dradfg(int ido, int ip, int l1, int idl1, double *cc, double *c1, + double *c2, double *ch, double *ch2, double *wa) +{ + static double tpi = 6.28318530717958647692528676655900577; + int idij, ipph, i, j, k, l, ic, ik, is; + int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + double dc2, ai1, ai2, ar1, ar2, ds2; + int nbd; + double dcp, arg, dsp, ar1h, ar2h; + int idp2, ipp2; + + arg = tpi/(double)ip; + dcp = cos(arg); + dsp = sin(arg); + ipph = (ip+1)>>1; + ipp2 = ip; + idp2 = ido; + nbd = (ido-1)>>1; + t0 = l1*ido; + t10 = ip*ido; + + if ( ido == 1 ) + goto L119; + for ( ik=0; ik<idl1; ik++ ) + ch2[ik] = c2[ik]; + + t1 = 0; + for ( j=1; j<ip; j++ ) { + t1 += t0; + t2 = t1; + for ( k=0; k<l1; k++ ) { + ch[t2] = c1[t2]; + t2 += ido; + } + } + + is = -ido; + t1 = 0; + if ( nbd > l1 ) { + for ( j=1; j<ip; j++ ) { + t1 += t0; + is += ido; + t2 = -ido+t1; + for ( k=0; k<l1; k++ ) { + idij = is-1; + t2 += ido; + t3 = t2; + for ( i=2; i<ido; i+=2 ) { + idij += 2; + t3 += 2; + ch[t3-1] = wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3]; + ch[t3] = wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1]; + } + } + } + } + else { + for ( j=1; j<ip; j++ ) { + is += ido; + idij = is-1; + t1 += t0; + t2 = t1; + for ( i=2; i<ido; i+=2 ) { + idij += 2; + t2 += 2; + t3 = t2; + for ( k=0; k<l1; k++ ) { + ch[t3-1] = wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3]; + ch[t3] = wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1]; + t3 += ido; + } + } + } + } + + t1 = 0; + t2 = ipp2*t0; + if( nbd < l1 ) { + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + for ( i=2; i<ido; i+=2 ) { + t3 += 2; + t4 += 2; + t5 = t3-ido; + t6 = t4-ido; + for ( k=0; k<l1; k++ ) { + t5 += ido; + t6 += ido; + c1[t5-1] = ch[t5-1]+ch[t6-1]; + c1[t6-1] = ch[t5]-ch[t6]; + c1[t5] = ch[t5]+ch[t6]; + c1[t6] = ch[t6-1]-ch[t5-1]; + } + } + } + } + else { + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + for ( k=0; k<l1; k++ ) { + t5 = t3; + t6 = t4; + for ( i=2; i<ido; i+=2 ) { + t5 += 2; + t6 += 2; + c1[t5-1] = ch[t5-1]+ch[t6-1]; + c1[t6-1] = ch[t5]-ch[t6]; + c1[t5] = ch[t5]+ch[t6]; + c1[t6] = ch[t6-1]-ch[t5-1]; + } + t3 += ido; + t4 += ido; + } + } + } + +L119: + for ( ik=0; ik<idl1; ik++ ) + c2[ik] = ch2[ik]; + + t1 = 0; + t2 = ipp2*idl1; + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1-ido; + t4 = t2-ido; + for ( k=0; k<l1; k++ ) { + t3 += ido; + t4 += ido; + c1[t3] = ch[t3]+ch[t4]; + c1[t4] = ch[t4]-ch[t3]; + } + } + + ar1 = 1.0; + ai1 = 0.0; + t1 = 0; + t2 = ipp2*idl1; + t3 = (ip-1)*idl1; + for ( l=1; l<ipph; l++ ) { + t1 += idl1; + t2 -= idl1; + ar1h = dcp*ar1-dsp*ai1; + ai1 = dcp*ai1+dsp*ar1; + ar1 = ar1h; + t4 = t1; + t5 = t2; + t6 = t3; + t7 = idl1; + + for ( ik=0; ik<idl1; ik++ ) { + ch2[t4++] = c2[ik]+ar1*c2[t7++]; + ch2[t5++] = ai1*c2[t6++]; + } + + dc2 = ar1; + ds2 = ai1; + ar2 = ar1; + ai2 = ai1; + + t4 = idl1; + t5 = (ipp2-1)*idl1; + for ( j=2; j<ipph; j++ ) { + t4 += idl1; + t5 -= idl1; + + ar2h = dc2*ar2-ds2*ai2; + ai2 = dc2*ai2+ds2*ar2; + ar2 = ar2h; + + t6 = t1; + t7 = t2; + t8 = t4; + t9 = t5; + for ( ik=0; ik<idl1; ik++ ) { + ch2[t6++] += ar2*c2[t8++]; + ch2[t7++] += ai2*c2[t9++]; + } + } + } + + t1 = 0; + for ( j=1; j<ipph; j++ ) { + t1 += idl1; + t2 = t1; + for ( ik=0; ik<idl1; ik++ ) + ch2[ik] += c2[t2++]; + } + + if ( ido < l1 ) + goto L132; + + t1 = 0; + t2 = 0; + for ( k=0; k<l1; k++ ) { + t3 = t1; + t4 = t2; + for ( i=0; i<ido; i++ ) + cc[t4++] = ch[t3++]; + t1 += ido; + t2 += t10; + } + + goto L135; + +L132: + for ( i=0; i<ido; i++ ) { + t1 = i; + t2 = i; + for ( k=0; k<l1; k++ ) { + cc[t2] = ch[t1]; + t1 += ido; + t2 += t10; + } + } + +L135: + t1 = 0; + t2 = ido<<1; + t3 = 0; + t4 = ipp2*t0; + for ( j=1; j<ipph; j++ ) { + + t1 += t2; + t3 += t0; + t4 -= t0; + + t5 = t1; + t6 = t3; + t7 = t4; + + for ( k=0; k<l1; k++ ) { + cc[t5-1] = ch[t6]; + cc[t5] = ch[t7]; + t5 += t10; + t6 += ido; + t7 += ido; + } + } + + if ( ido == 1 ) + return; + if ( nbd < l1 ) + goto L141; + + t1 = -ido; + t3 = 0; + t4 = 0; + t5 = ipp2*t0; + for ( j=1; j<ipph; j++ ) { + t1 += t2; + t3 += t2; + t4 += t0; + t5 -= t0; + t6 = t1; + t7 = t3; + t8 = t4; + t9 = t5; + for ( k=0; k<l1; k++ ) { + for ( i=2; i<ido; i+=2 ) { + ic = idp2-i; + cc[i+t7-1] = ch[i+t8-1]+ch[i+t9-1]; + cc[ic+t6-1] = ch[i+t8-1]-ch[i+t9-1]; + cc[i+t7] = ch[i+t8]+ch[i+t9]; + cc[ic+t6] = ch[i+t9]-ch[i+t8]; + } + t6 += t10; + t7 += t10; + t8 += ido; + t9 += ido; + } + } + return; + +L141: + + t1 = -ido; + t3 = 0; + t4 = 0; + t5 = ipp2*t0; + for ( j=1; j<ipph; j++ ) { + t1 += t2; + t3 += t2; + t4 += t0; + t5 -= t0; + for ( i=2; i<ido; i+=2 ) { + t6 = idp2+t1-i; + t7 = i+t3; + t8 = i+t4; + t9 = i+t5; + for ( k=0; k<l1; k++ ) { + cc[t7-1] = ch[t8-1]+ch[t9-1]; + cc[t6-1] = ch[t8-1]-ch[t9-1]; + cc[t7] = ch[t8]+ch[t9]; + cc[t6] = ch[t9]-ch[t8]; + t6 += t10; + t7 += t10; + t8 += ido; + t9 += ido; + } + } + } +} + +STIN void drftf1(int n, double *c, double *ch, double *wa, int *ifac) +{ + int i, k1, l1, l2; + int na, kh, nf; + int ip, iw, ido, idl1, ix2, ix3; + + nf = ifac[1]; + na = 1; + l2 = n; + iw = n; + + for ( k1=0; k1<nf; k1++ ) { + kh = nf-k1; + ip = ifac[kh+1]; + l1 = l2/ip; + ido = n/l2; + idl1 = ido*l1; + iw -= (ip-1)*ido; + na = 1-na; + + if ( ip!=4 ) + goto L102; + + ix2 = iw+ido; + ix3 = ix2+ido; + if ( na != 0 ) + dradf4(ido, l1, ch, c, wa+iw-1, wa+ix2-1, wa+ix3-1); + else + dradf4(ido, l1, c, ch, wa+iw-1, wa+ix2-1, wa+ix3-1); + goto L110; + +L102: + if ( ip != 2 ) + goto L104; + if ( na != 0 ) + goto L103; + + dradf2(ido, l1, c, ch, wa+iw-1); + goto L110; + +L103: + dradf2(ido, l1, ch, c, wa+iw-1); + goto L110; + +L104: + if ( ido == 1 ) + na = 1-na; + if ( na != 0 ) + goto L109; + + dradfg(ido, ip, l1, idl1, c, c, c, ch, ch, wa+iw-1); + na = 1; + goto L110; + +L109: + dradfg(ido, ip, l1, idl1, ch, ch, ch, c, c, wa+iw-1); + na = 0; + +L110: + l2=l1; + } + + if ( na == 1 ) + return; + + for ( i=0; i<n; i++ ) + c[i] = ch[i]; +} + +void __ogg_fdrfftf(int n, double *r, double *wsave, int *ifac) +{ + if ( n==1 ) + return; + drftf1(n, r, wsave, wsave+n, ifac); +} + +#ifdef LBBBBBBBBBBBBBBBB + +STIN void dcsqf1(int n, double *x, double *w, double *xh, int *ifac) +{ + int modn, i, k, kc; + int np2, ns2; + double xim1; + + ns2 = (n+1)>>1; + np2 = n; + + kc = np2; + for ( k=1; k<ns2; k++ ) { + kc--; + xh[k] = x[k]+x[kc]; + xh[kc] = x[k]-x[kc]; + } + + modn = n%2; + if ( modn == 0 ) + xh[ns2] = x[ns2]+x[ns2]; + + for ( k=1; k<ns2; k++ ) { + kc = np2-k; + x[k] = w[k-1]*xh[kc]+w[kc-1]*xh[k]; + x[kc] = w[k-1]*xh[k]-w[kc-1]*xh[kc]; + } + + if ( modn == 0 ) + x[ns2] = w[ns2-1]*xh[ns2]; + + __ogg_fdrfftf(n, x, xh, ifac); + + for ( i=2; i<n; i+=2 ) { + xim1 = x[i-1]-x[i]; + x[i] = x[i-1]+x[i]; + x[i-1] = xim1; + } +} + +void __ogg_fdcosqf(int n, double *x, double *wsave, int *ifac) +{ + static double sqrt2=1.4142135623730950488016887242097; + double tsqx; + + switch(n) { + case 0: + case 1: + return; + case 2: + tsqx = sqrt2*x[1]; + x[1] = x[0]-tsqx; + x[0] += tsqx; + return; + default: + dcsqf1(n, x, wsave, wsave+n, ifac); + return; + } +} + +STIN void dradb2(int ido, int l1, double *cc, double *ch, double *wa1) +{ + int i, k, t0, t1, t2, t3, t4, t5, t6; + double ti2, tr2; + + t0 = l1*ido; + + t1 = 0; + t2 = 0; + t3 = (ido<<1)-1; + for ( k=0; k<l1; k++ ) { + ch[t1] = cc[t2]+cc[t3+t2]; + ch[t1+t0] = cc[t2]-cc[t3+t2]; + t2 = (t1 += ido)<<1; + } + + if ( ido < 2 ) + return; + if ( ido == 2 ) + goto L105; + + t1 = 0; + t2 = 0; + for ( k=0; k<l1; k++ ) { + t3 = t1; + t5 = (t4 = t2)+(ido<<1); + t6 = t0+t1; + for ( i=2; i<ido; i+=2 ) { + t3 += 2; + t4 += 2; + t5 -= 2; + t6 += 2; + ch[t3-1] = cc[t4-1]+cc[t5-1]; + tr2 = cc[t4-1]-cc[t5-1]; + ch[t3] = cc[t4]-cc[t5]; + ti2 = cc[t4]+cc[t5]; + ch[t6-1] = wa1[i-2]*tr2-wa1[i-1]*ti2; + ch[t6] = wa1[i-2]*ti2+wa1[i-1]*tr2; + } + t2 = (t1 += ido)<<1; + } + + if ( ido%2 == 1 ) + return; + +L105: + t1 = ido-1; + t2 = ido-1; + for ( k=0; k<l1; k++ ) { + ch[t1] = cc[t2]+cc[t2]; + ch[t1+t0] = -(cc[t2+1]+cc[t2+1]); + t1 += ido; + t2 += ido<<1; + } +} + +STIN void dradb3(int ido, int l1, double *cc, double *ch, double *wa1, double *wa2) +{ + static double taur = -.5; + static double taui = .86602540378443864676372317075293618; + int i, k, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + double ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; + + t0 = l1*ido; + t1 = 0; + t2 = t0<<1; + t3 = ido<<1; + t4 = ido+(ido<<1); + t5 = 0; + for ( k=0; k<l1; k++ ) { + tr2 = cc[t3-1]+cc[t3-1]; + cr2 = cc[t5]+(taur*tr2); + ch[t1] = cc[t5]+tr2; + ci3 = taui*(cc[t3]+cc[t3]); + ch[t1+t0] = cr2-ci3; + ch[t1+t2] = cr2+ci3; + t1 += ido; + t3 += t4; + t5 += t4; + } + + if ( ido == 1 ) + return; + + t1 = 0; + t3 = ido<<1; + for ( k=0; k<l1; k++ ) { + t7 = t1+(t1<<1); + t6 = (t5 = t7+t3); + t8 = t1; + t10 = (t9 = t1+t0)+t0; + + for ( i=2; i<ido; i+=2 ) { + t5 += 2; + t6 -= 2; + t7 += 2; + t8 += 2; + t9 += 2; + t10 += 2; + tr2 = cc[t5-1]+cc[t6-1]; + cr2 = cc[t7-1]+(taur*tr2); + ch[t8-1] = cc[t7-1]+tr2; + ti2 = cc[t5]-cc[t6]; + ci2 = cc[t7]+(taur*ti2); + ch[t8] = cc[t7]+ti2; + cr3 = taui*(cc[t5-1]-cc[t6-1]); + ci3 = taui*(cc[t5]+cc[t6]); + dr2 = cr2-ci3; + dr3 = cr2+ci3; + di2 = ci2+cr3; + di3 = ci2-cr3; + ch[t9-1] = wa1[i-2]*dr2-wa1[i-1]*di2; + ch[t9] = wa1[i-2]*di2+wa1[i-1]*dr2; + ch[t10-1] = wa2[i-2]*dr3-wa2[i-1]*di3; + ch[t10] = wa2[i-2]*di3+wa2[i-1]*dr3; + } + t1+=ido; + } +} + +STIN void dradb4(int ido, int l1, double *cc, double *ch, double *wa1, + double *wa2, double *wa3) +{ + static double sqrt2=1.4142135623730950488016887242097; + int i, k, t0, t1, t2, t3, t4, t5, t6, t7, t8; + double ci2, ci3, ci4, cr2, cr3, cr4; + double ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; + + t0 = l1*ido; + t1 = 0; + t2 = ido<<2; + t3 = 0; + t6 = ido<<1; + for ( k=0; k<l1; k++ ) { + t4 = t3+t6; + t5 = t1; + tr3 = cc[t4-1]+cc[t4-1]; + tr4 = cc[t4]+cc[t4]; + tr1 = cc[t3]-cc[(t4+=t6)-1]; + tr2 = cc[t3]+cc[t4-1]; + ch[t5] = tr2+tr3; + ch[t5+=t0] = tr1-tr4; + ch[t5+=t0] = tr2-tr3; + ch[t5+=t0] = tr1+tr4; + t1 += ido; + t3 += t2; + } + + if ( ido < 2 ) + return; + if ( ido == 2 ) + goto L105; + + t1 = 0; + for ( k=0; k<l1; k++ ) { + t5 = (t4 = (t3 = (t2 = t1<<2)+t6))+t6; + t7 = t1; + for ( i=2; i<ido; i+=2 ) { + t2 += 2; + t3 += 2; + t4 -= 2; + t5 -= 2; + t7 += 2; + ti1 = cc[t2]+cc[t5]; + ti2 = cc[t2]-cc[t5]; + ti3 = cc[t3]-cc[t4]; + tr4 = cc[t3]+cc[t4]; + tr1 = cc[t2-1]-cc[t5-1]; + tr2 = cc[t2-1]+cc[t5-1]; + ti4 = cc[t3-1]-cc[t4-1]; + tr3 = cc[t3-1]+cc[t4-1]; + ch[t7-1] = tr2+tr3; + cr3 = tr2-tr3; + ch[t7] = ti2+ti3; + ci3 = ti2-ti3; + cr2 = tr1-tr4; + cr4 = tr1+tr4; + ci2 = ti1+ti4; + ci4 = ti1-ti4; + + ch[(t8 = t7+t0)-1] = wa1[i-2]*cr2-wa1[i-1]*ci2; + ch[t8] = wa1[i-2]*ci2+wa1[i-1]*cr2; + ch[(t8 += t0)-1] = wa2[i-2]*cr3-wa2[i-1]*ci3; + ch[t8] = wa2[i-2]*ci3+wa2[i-1]*cr3; + ch[(t8 += t0)-1] = wa3[i-2]*cr4-wa3[i-1]*ci4; + ch[t8] = wa3[i-2]*ci4+wa3[i-1]*cr4; + } + t1 += ido; + } + + if ( ido%2 == 1) + return; + +L105: + + t1 = ido; + t2 = ido<<2; + t3 = ido-1; + t4 = ido+(ido<<1); + for ( k=0; k<l1; k++ ) { + t5 = t3; + ti1 = cc[t1]+cc[t4]; + ti2 = cc[t4]-cc[t1]; + tr1 = cc[t1-1]-cc[t4-1]; + tr2 = cc[t1-1]+cc[t4-1]; + ch[t5] = tr2+tr2; + ch[t5+=t0] = sqrt2*(tr1-ti1); + ch[t5+=t0] = ti2+ti2; + ch[t5+=t0] = -sqrt2*(tr1+ti1); + + t3 += ido; + t1 += t2; + t4 += t2; + } +} + +STIN void dradbg(int ido, int ip, int l1, int idl1, double *cc, double *c1, + double *c2, double *ch, double *ch2, double *wa) +{ + static double tpi=6.28318530717958647692528676655900577; + int idij, ipph, i, j, k, l, ik, is; + int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12; + double dc2, ai1, ai2, ar1,ar2, ds2; + int nbd; + double dcp, arg, dsp, ar1h, ar2h; + int ipp2; + + t10 = ip*ido; + t0 = l1*ido; + arg = tpi/(double)ip; + dcp = cos(arg); + dsp = sin(arg); + nbd = (ido-1)>>1; + ipp2 = ip; + ipph = (ip+1)>>1; + if ( ido < l1 ) + goto L103; + + t1 = 0; + t2 = 0; + for ( k=0; k<l1; k++ ) { + t3 = t1; + t4 = t2; + for ( i=0; i<ido; i++ ) { + ch[t3] = cc[t4]; + t3++; + t4++; + } + t1 += ido; + t2 += t10; + } + goto L106; + +L103: + t1 = 0; + for ( i=0; i<ido; i++ ) { + t2 = t1; + t3 = t1; + for ( k=0; k<l1; k++ ) { + ch[t2] = cc[t3]; + t2 += ido; + t3 += t10; + } + t1++; + } + +L106: + t1 = 0; + t2 = ipp2*t0; + t7 = (t5 = ido<<1); + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + t6 = t5; + for ( k=0; k<l1; k++ ) { + ch[t3] = cc[t6-1]+cc[t6-1]; + ch[t4] = cc[t6]+cc[t6]; + t3 += ido; + t4 += ido; + t6 += t10; + } + t5 += t7; + } + + if (ido == 1) + goto L116; + if ( nbd < l1 ) + goto L112; + + t1 = 0; + t2 = ipp2*t0; + t7 = 0; + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + + t7 += (ido<<1); + t8 = t7; + for ( k=0; k<l1; k++ ) { + t5 = t3; + t6 = t4; + t9 = t8; + t11 = t8; + for ( i=2; i<ido; i+=2 ) { + t5 += 2; + t6 += 2; + t9 += 2; + t11 -= 2; + ch[t5-1] = cc[t9-1]+cc[t11-1]; + ch[t6-1] = cc[t9-1]-cc[t11-1]; + ch[t5] = cc[t9]-cc[t11]; + ch[t6] = cc[t9]+cc[t11]; + } + t3 += ido; + t4 += ido; + t8 += t10; + } + } + goto L116; + +L112: + t1 = 0; + t2 = ipp2*t0; + t7 = 0; + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + t7 += (ido<<1); + t8 = t7; + t9 = t7; + for ( i=2; i<ido; i+=2 ) { + t3 += 2; + t4 += 2; + t8 += 2; + t9 -= 2; + t5 = t3; + t6 = t4; + t11 = t8; + t12 = t9; + for ( k=0; k<l1; k++ ) { + ch[t5-1] = cc[t11-1]+cc[t12-1]; + ch[t6-1] = cc[t11-1]-cc[t12-1]; + ch[t5] = cc[t11]-cc[t12]; + ch[t6] = cc[t11]+cc[t12]; + t5 += ido; + t6 += ido; + t11 += t10; + t12 += t10; + } + } + } + +L116: + ar1 = 1.0; + ai1 = 0.0; + t1 = 0; + t9 = (t2 = ipp2*idl1); + t3 = (ip-1)*idl1; + for ( l=1; l<ipph; l++ ) { + t1 += idl1; + t2 -= idl1; + + ar1h = dcp*ar1-dsp*ai1; + ai1 = dcp*ai1+dsp*ar1; + ar1 = ar1h; + t4 = t1; + t5 = t2; + t6 = 0; + t7 = idl1; + t8 = t3; + for ( ik=0; ik<idl1; ik++ ) { + c2[t4++] = ch2[t6++]+ar1*ch2[t7++]; + c2[t5++] = ai1*ch2[t8++]; + } + dc2 = ar1; + ds2 = ai1; + ar2 = ar1; + ai2 = ai1; + + t6 = idl1; + t7 = t9-idl1; + for ( j=2; j<ipph; j++ ) { + t6 += idl1; + t7 -= idl1; + ar2h = dc2*ar2-ds2*ai2; + ai2 = dc2*ai2+ds2*ar2; + ar2 = ar2h; + t4 = t1; + t5 = t2; + t11 = t6; + t12 = t7; + for ( ik=0; ik<idl1; ik++ ) { + c2[t4++] += ar2*ch2[t11++]; + c2[t5++] += ai2*ch2[t12++]; + } + } + } + + t1 = 0; + for ( j=1; j<ipph; j++ ) { + t1 += idl1; + t2 = t1; + for ( ik=0; ik<idl1; ik++ ) + ch2[ik] += ch2[t2++]; + } + + t1 = 0; + t2 = ipp2*t0; + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + for ( k=0; k<l1; k++ ) { + ch[t3] = c1[t3]-c1[t4]; + ch[t4] = c1[t3]+c1[t4]; + t3 += ido; + t4 += ido; + } + } + + if ( ido == 1 ) + goto L132; + if ( nbd < l1 ) + goto L128; + + t1 = 0; + t2 = ipp2*t0; + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + for ( k=0; k<l1; k++ ) { + t5 = t3; + t6 = t4; + for ( i=2; i<ido; i+=2 ) { + t5 += 2; + t6 += 2; + ch[t5-1] = c1[t5-1]-c1[t6]; + ch[t6-1] = c1[t5-1]+c1[t6]; + ch[t5] = c1[t5]+c1[t6-1]; + ch[t6] = c1[t5]-c1[t6-1]; + } + t3 += ido; + t4 += ido; + } + } + goto L132; + +L128: + t1 = 0; + t2 = ipp2*t0; + for ( j=1; j<ipph; j++ ) { + t1 += t0; + t2 -= t0; + t3 = t1; + t4 = t2; + for ( i=2; i<ido; i+=2 ) { + t3 += 2; + t4 += 2; + t5 = t3; + t6 = t4; + for ( k=0; k<l1; k++ ) { + ch[t5-1] = c1[t5-1]-c1[t6]; + ch[t6-1] = c1[t5-1]+c1[t6]; + ch[t5] = c1[t5]+c1[t6-1]; + ch[t6] = c1[t5]-c1[t6-1]; + t5 += ido; + t6 += ido; + } + } + } + +L132: + if ( ido == 1 ) + return; + + for ( ik=0; ik<idl1; ik++ ) + c2[ik] = ch2[ik]; + + t1 = 0; + for ( j=1; j<ip; j++ ) { + t2 = (t1 += t0); + for ( k=0; k<l1; k++ ) { + c1[t2] = ch[t2]; + t2 += ido; + } + } + + if ( nbd > l1 ) + goto L139; + + is = -ido-1; + t1 =0; + for ( j=1; j<ip; j++ ) { + is += ido; + t1 += t0; + idij = is; + t2 = t1; + for ( i=2; i<ido; i+=2 ) { + t2 += 2; + idij += 2; + t3 = t2; + for ( k=0; k<l1; k++ ) { + c1[t3-1] = wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3]; + c1[t3] = wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1]; + t3 += ido; + } + } + } + return; + +L139: + is = -ido-1; + t1 = 0; + for ( j=1; j<ip; j++ ) { + is += ido; + t1 += t0; + t2 = t1; + for ( k=0; k<l1; k++ ) { + idij = is; + t3 = t2; + for ( i=2; i<ido; i+=2 ) { + idij += 2; + t3 += 2; + c1[t3-1] = wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3]; + c1[t3] = wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1]; + } + t2 += ido; + } + } +} + +STIN void drftb1(int n, double *c, double *ch, double *wa, int *ifac) +{ + int i, k1, l1, l2; + int na; + int nf, ip, iw, ix2, ix3, ido, idl1; + + nf = ifac[1]; + na = 0; + l1 = 1; + iw = 1; + + for ( k1=0; k1<nf; k1++ ) { + ip = ifac[k1 + 2]; + l2 = ip*l1; + ido = n/l2; + idl1 = ido*l1; + if ( ip != 4 ) + goto L103; + ix2 = iw+ido; + ix3 = ix2+ido; + + if ( na != 0 ) + dradb4(ido, l1, ch, c, wa+iw-1, wa+ix2-1, wa+ix3-1); + else + dradb4(ido, l1, c, ch, wa+iw-1, wa+ix2-1, wa+ix3-1); + na = 1-na; + goto L115; + +L103: + if ( ip != 2 ) + goto L106; + + if ( na != 0 ) + dradb2(ido, l1, ch, c, wa+iw-1); + else + dradb2(ido, l1, c, ch, wa+iw-1); + na = 1-na; + goto L115; + +L106: + if ( ip != 3 ) + goto L109; + + ix2 = iw+ido; + if ( na != 0 ) + dradb3(ido, l1, ch, c, wa+iw-1, wa+ix2-1); + else + dradb3(ido, l1, c, ch, wa+iw-1, wa+ix2-1); + na = 1-na; + goto L115; + +L109: + /* The radix five case can be translated later..... */ + /* if(ip!=5)goto L112; + + ix2=iw+ido; + ix3=ix2+ido; + ix4=ix3+ido; + if ( na != 0 ) + dradb5(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1); + else + dradb5(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1); + na=1-na; + goto L115; + +L112:*/ + if ( na != 0 ) + dradbg(ido, ip, l1, idl1, ch, ch, ch, c, c, wa+iw-1); + else + dradbg(ido, ip, l1, idl1, c, c, c, ch, ch, wa+iw-1); + if ( ido == 1 ) + na = 1-na; + +L115: + l1 = l2; + iw += (ip-1)*ido; + } + + if ( na == 0 ) + return; + + for ( i=0; i<n; i++ ) + c[i] = ch[i]; +} + +void __ogg_fdrfftb(int n, double *r, double *wsave, int *ifac) +{ + if ( n == 1 ) + return; + drftb1(n, r, wsave, wsave+n, ifac); +} + +STIN void dcsqb1(int n, double *x, double *w, double *xh, int *ifac) +{ + int modn, i, k, kc; + int np2, ns2; + double xim1; + + ns2 = (n+1)>>1; + np2 = n; + + for ( i=2; i<n; i+=2 ) { + xim1 = x[i-1]+x[i]; + x[i] -= x[i-1]; + x[i-1] = xim1; + } + + x[0] += x[0]; + modn = n%2; + if ( modn == 0 ) + x[n-1] += x[n-1]; + + __ogg_fdrfftb(n, x, xh, ifac); + + kc = np2; + for ( k=1; k<ns2; k++ ) { + kc--; + xh[k] = w[k-1]*x[kc]+w[kc-1]*x[k]; + xh[kc] = w[k-1]*x[k]-w[kc-1]*x[kc]; + } + + if ( modn == 0 ) + x[ns2] = w[ns2-1]*(x[ns2]+x[ns2]); + + kc = np2; + for ( k=1; k<ns2; k++ ) { + kc--; + x[k] = xh[k]+xh[kc]; + x[kc] = xh[k]-xh[kc]; + } + x[0] += x[0]; +} + +void __ogg_fdcosqb(int n, double *x, double *wsave, int *ifac) +{ + static double tsqrt2 = 2.8284271247461900976033774484194; + double x1; + + if ( n < 2 ) { + x[0] *= 4; + return; + } + if ( n == 2 ) { + x1 = (x[0]+x[1])*4; + x[1] = tsqrt2*(x[0]-x[1]); + x[0] = x1; + return; + } + + dcsqb1(n, x, wsave, wsave+n, ifac); +} +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/discreteFourierTransform.c b/decoders/session_flags/mesa_sts/src/discreteFourierTransform.c new file mode 100644 index 0000000..397ceec --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/discreteFourierTransform.c @@ -0,0 +1,60 @@ +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + D I S C R E T E F O U R I E R T R A N S F O R M T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +void __ogg_fdrffti(int n, double *wsave, int *ifac); +void __ogg_fdrfftf(int n, double *X, double *wsave, int *ifac); + +int +DiscreteFourierTransform(int n, BitSequence *epsilon) +{ + double p_value, upperBound, percentile, N_l, N_o, d, *m, *X, *wsave; + int i, count, ifac[15]; + + if ( ((X = (double*) calloc(n,sizeof(double))) == NULL) || + ((wsave = (double *)calloc(2*n,sizeof(double))) == NULL) || + ((m = (double*)calloc(n/2+1, sizeof(double))) == NULL) ) { + if( X != NULL ) + free(X); + if( wsave != NULL ) + free(wsave); + if( m != NULL ) + free(m); + return 0; + } + for ( i=0; i<n; i++ ) + X[i] = 2*(int)epsilon[i] - 1; + + __ogg_fdrffti(n, wsave, ifac); /* INITIALIZE WORK ARRAYS */ + __ogg_fdrfftf(n, X, wsave, ifac); /* APPLY FORWARD FFT */ + + m[0] = sqrt(X[0]*X[0]); /* COMPUTE MAGNITUDE */ + + for ( i=0; i<n/2; i++ ) + m[i+1] = sqrt(pow(X[2*i+1],2)+pow(X[2*i+2],2)); + count = 0; /* CONFIDENCE INTERVAL */ + upperBound = sqrt(2.995732274*n); + for ( i=0; i<n/2; i++ ) + if ( m[i] < upperBound ) + count++; + percentile = (double)count/(n/2)*100; + N_l = (double) count; /* number of peaks less than h = sqrt(3*n) */ + N_o = (double) 0.95*n/2.0; + d = (N_l - N_o)/sqrt(n/4.0*0.95*0.05); + p_value = erfc(fabs(d)/sqrt(2.0)); + + free(X); + free(wsave); + free(m); + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +} diff --git a/decoders/session_flags/mesa_sts/src/frequency.c b/decoders/session_flags/mesa_sts/src/frequency.c new file mode 100644 index 0000000..8950e3a --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/frequency.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include "include/externs.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + F R E Q U E N C Y T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +Frequency(int n, BitSequence *epsilon) +{ + int i; + double f, s_obs, p_value, sum, sqrt2 = 1.41421356237309504880; + + sum = 0.0; + for ( i=0; i<n; i++ ) + sum += 2*(int)epsilon[i]-1; + s_obs = fabs(sum)/sqrt(n); + f = s_obs/sqrt2; + p_value = erfc(f); + +// fprintf(stats[TEST_FREQUENCY], "\t\t\t FREQUENCY TEST\n"); +// fprintf(stats[TEST_FREQUENCY], "\t\t---------------------------------------------\n"); +// fprintf(stats[TEST_FREQUENCY], "\t\tCOMPUTATIONAL INFORMATION:\n"); +// fprintf(stats[TEST_FREQUENCY], "\t\t---------------------------------------------\n"); +// fprintf(stats[TEST_FREQUENCY], "\t\t(a) The nth partial sum = %d\n", (int)sum); +// fprintf(stats[TEST_FREQUENCY], "\t\t(b) S_n/n = %f\n", sum/n); +// fprintf(stats[TEST_FREQUENCY], "\t\t---------------------------------------------\n"); + +// fprintf(stats[TEST_FREQUENCY], "%s\t\tp_value = %f\n\n", p_value < ALPHA ? "FAILURE" : "SUCCESS", p_value); fflush(stats[TEST_FREQUENCY]); +// fprintf(results[TEST_FREQUENCY], "%f\n", p_value); fflush(results[TEST_FREQUENCY]); + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +} diff --git a/decoders/session_flags/mesa_sts/src/genutils.c b/decoders/session_flags/mesa_sts/src/genutils.c new file mode 100644 index 0000000..df7ddc2 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/genutils.c @@ -0,0 +1,667 @@ +/* + * file: mp.c + * + * DESCRIPTION + * + * These functions comprise a multi-precision integer arithmetic + * and discrete function package. + */ + +#include "include/genutils.h" + +#define MAXPLEN 384 + + +/***************************************** +** greater - Test if x > y * +** * +** Returns TRUE (1) if x greater than y, * +** otherwise FALSE (0). * +** * +** Parameters: * +** * +** x Address of array x * +** y Address of array y * +** l Length both x and y in bytes * +** * +******************************************/ +int greater(BYTE *x, BYTE *y, int l) +{ + int i; + + for ( i=0; i<l; i++ ) + if ( x[i] != y[i] ) + break; + + if ( i == l ) + return 0; + + if ( x[i] > y[i] ) + return 1; + + return 0; +} + + +/***************************************** +** less - Test if x < y * +** * +** Returns TRUE (1) if x less than y, * +** otherwise FALSE (0). * +** * +** Parameters: * +** * +** x Address of array x * +** y Address of array y * +** l Length both x and y in bytes * +** * +******************************************/ +int less(BYTE *x, BYTE *y, int l) +{ + int i; + + for ( i=0; i<l; i++ ) + if ( x[i] != y[i] ) + break; + + if ( i == l ) { + return 0; + } + + if ( x[i] < y[i] ) { + return 1; + } + + return 0; +} + + +/***************************************** +** bshl - shifts array left * +** by one bit. * +** * +** x = x * 2 * +** * +** Parameters: * +** * +** x Address of array x * +** l Length array x in bytes * +** * +******************************************/ +BYTE bshl(BYTE *x, int l) +{ + BYTE *p; + int c1, c2; + + p = x + l - 1; + c1 = 0; + c2 = 0; + while ( p != x ) { + if ( *p & 0x80 ) + c2 = 1; + *p <<= 1; /* shift the word left once (ls bit = 0) */ + if ( c1 ) + *p |= 1; + c1 = c2; + c2 = 0; + p--; + } + + if ( *p & 0x80 ) + c2 = 1; + *p <<= 1; /* shift the word left once (ls bit = 0) */ + if ( c1 ) + *p |= (DIGIT)1; + + return (BYTE)c2; +} + + +/***************************************** +** bshr - shifts array right * +** by one bit. * +** * +** x = x / 2 * +** * +** Parameters: * +** * +** x Address of array x * +** l Length array x in bytes * +** * +******************************************/ +void bshr(BYTE *x, int l) +{ + BYTE *p; + int c1,c2; + + p = x; + c1 = 0; + c2 = 0; + while ( p != x+l-1 ) { + if ( *p & 0x01 ) + c2 = 1; + *p >>= 1; /* shift the word right once (ms bit = 0) */ + if ( c1 ) + *p |= 0x80; + c1 = c2; + c2 = 0; + p++; + } + + *p >>= 1; /* shift the word right once (ms bit = 0) */ + if ( c1 ) + *p |= 0x80; +} + + +/***************************************** +** Mult - Multiply two integers * +** * +** A = B * C * +** * +** Parameters: * +** * +** A Address of the result * +** B Address of the multiplier * +** C Address of the multiplicand * +** LB Length of B in bytes * +** LC Length of C in bytes * +** * +** NOTE: A MUST be LB+LC in length * +** * +******************************************/ +int Mult(BYTE *A, BYTE *B, int LB, BYTE *C, int LC) +{ + int i, j, k, LA; + DIGIT result; + + LA = LB + LC; + + for ( i=LB-1; i>=0; i-- ) { + result = 0; + for ( j=LC-1; j>=0; j-- ) { + k = i+j+1; + result = (DIGIT)A[k] + ((DIGIT)(B[i] * C[j])) + (result >> 8); + A[k] = (BYTE)result; + } + A[--k] = (BYTE)(result >> 8); + } + + return 0; +} + + +void ModSqr(BYTE *A, BYTE *B, int LB, BYTE *M, int LM) +{ + + Square(A, B, LB); + Mod(A, 2*LB, M, LM); +} + +void ModMult(BYTE *A, BYTE *B, int LB, BYTE *C, int LC, BYTE *M, int LM) +{ + Mult(A, B, LB, C, LC); + Mod(A, (LB+LC), M, LM); +} + + +/***************************************** +** smult - Multiply array by a scalar. * +** * +** A = b * C * +** * +** Parameters: * +** * +** A Address of the result * +** b Scalar (1 BYTE) * +** C Address of the multiplicand * +** L Length of C in bytes * +** * +** NOTE: A MUST be L+1 in length * +** * +******************************************/ +void smult(BYTE *A, BYTE b, BYTE *C, int L) +{ + int i; + DIGIT result; + + result = 0; + for ( i=L-1; i>0; i-- ) { + result = A[i] + ((DIGIT)b * C[i]) + (result >> 8); + A[i] = (BYTE)(result & 0xff); + A[i-1] = (BYTE)(result >> 8); + } +} + +/***************************************** +** Square() - Square an integer * +** * +** A = B^2 * +** * +** Parameters: * +** * +** A Address of the result * +** B Address of the operand * +** L Length of B in bytes * +** * +** NOTE: A MUST be 2*L in length * +** * +******************************************/ +void Square(BYTE *A, BYTE *B, int L) +{ + Mult(A, B, L, B, L); +} + +/***************************************** +** ModExp - Modular Exponentiation * +** * +** A = B ** C (MOD M) * +** * +** Parameters: * +** * +** A Address of result * +** B Address of mantissa * +** C Address of exponent * +** M Address of modulus * +** LB Length of B in bytes * +** LC Length of C in bytes * +** LM Length of M in bytes * +** * +** NOTE: The integer B must be less * +** than the modulus M. * +** NOTE: A must be at least 3*LM * +** bytes long. However, the * +** result stored in A will be * +** only LM bytes long. * +******************************************/ +void ModExp(BYTE *A, BYTE *B, int LB, BYTE *C, int LC, BYTE *M, int LM) +{ + BYTE wmask; + int bits; + + bits = LC*8; + wmask = 0x80; + + A[LM-1] = 1; + + while ( !sniff_bit(C,wmask) ) { + wmask >>= 1; + bits--; + if ( !wmask ) { + wmask = 0x80; + C++; + } + } + + while ( bits-- ) { + memset(A+LM, 0x00, LM*2); + + /* temp = A*A (MOD M) */ + ModSqr(A+LM, A,LM, M,LM); + + /* A = lower L bytes of temp */ + memcpy(A, A+LM*2, LM); + memset(A+LM, 0x00, 2*LM); + + if ( sniff_bit(C,wmask) ) { + memset(A+LM, 0x00, (LM+LB)); + ModMult(A+LM, B,LB, A,LM, M,LM); /* temp = B * A (MOD M) */ + memcpy(A, A+LM+(LM+LB)-LM, LM); /* A = lower LM bytes of temp */ + memset(A+LM, 0x00, 2*LM); + } + + wmask >>= 1; + if ( !wmask ) { + wmask = 0x80; + C++; + } + } +} + + +/* DivMod: + * + * computes: + * quot = x / n + * rem = x % n + * returns: + * length of "quot" + * + * len of rem is lenx+1 + */ +int DivMod(BYTE *x, int lenx, BYTE *n, int lenn, BYTE *quot, BYTE *rem) +{ + BYTE *tx, *tn, *ttx, *ts, bmult[1]; + int i, shift, lgth_x, lgth_n, t_len, lenq; + DIGIT tMSn, mult; + unsigned long tMSx; + int underflow; + + tx = x; + tn = n; + + /* point to the MSD of n */ + for ( i=0, lgth_n=lenn; i<lenn; i++, lgth_n-- ) { + if ( *tn ) + break; + tn++; + } + if ( !lgth_n ) + return 0; + + /* point to the MSD of x */ + for ( i=0, lgth_x=lenx; i<lenx; i++, lgth_x-- ) { + if ( *tx ) + break; + tx++; + } + if ( !lgth_x ) + return 0; + + if ( lgth_x < lgth_n ) + lenq = 1; + else + lenq = lgth_x - lgth_n + 1; + memset(quot, 0x00, lenq); + + /* Loop while x > n, WATCH OUT if lgth_x == lgth_n */ + while ( (lgth_x > lgth_n) || ((lgth_x == lgth_n) && !less(tx, tn, lgth_n)) ) { + shift = 1; + if ( lgth_n == 1 ) { + if ( *tx < *tn ) { + tMSx = (DIGIT) (((*tx) << 8) | *(tx+1)); + tMSn = *tn; + shift = 0; + } + else { + tMSx = *tx; + tMSn = *tn; + } + } + else if ( lgth_n > 1 ) { + tMSx = (DIGIT) (((*tx) << 8) | *(tx+1)); + tMSn = (DIGIT) (((*tn) << 8) | *(tn+1)); + if ( (tMSx < tMSn) || ((tMSx == tMSn) && less(tx, tn, lgth_n)) ) { + tMSx = (tMSx << 8) | *(tx+2); + shift = 0; + } + } + else { + tMSx = (DIGIT) (((*tx) << 8) | *(tx+1)); + tMSn = *tn; + shift = 0; + } + + mult = (DIGIT) (tMSx / tMSn); + if ( mult > 0xff ) + mult = 0xff; + bmult[0] = mult & 0xff; + + ts = rem; + do { + memset(ts, 0x00, lgth_x+1); + Mult(ts, tn, lgth_n, bmult, 1); + + underflow = 0; + if ( shift ) { + if ( ts[0] != 0 ) + underflow = 1; + else { + for ( i=0; i<lgth_x; i++ ) + ts[i] = ts[i+1]; + ts[lgth_x] = 0x00; + } + } + if ( greater(ts, tx, lgth_x) || underflow ) { + bmult[0]--; + underflow = 1; + } + else + underflow = 0; + } while ( underflow ); + sub(tx, lgth_x, ts, lgth_x); + if ( shift ) + quot[lenq - (lgth_x - lgth_n) - 1] = bmult[0]; + else + quot[lenq - (lgth_x - lgth_n)] = bmult[0]; + + ttx = tx; + t_len = lgth_x; + for ( i=0, lgth_x=t_len; i<t_len; i++, lgth_x-- ) { + if ( *ttx ) + break; + ttx++; + } + tx = ttx; + } + memset(rem, 0x00, lenn); + if ( lgth_x ) + memcpy(rem+lenn-lgth_x, tx, lgth_x); + + return lenq; +} + + +/* + * Mod - Computes an integer modulo another integer + * + * x = x (mod n) + * + */ +void Mod(BYTE *x, int lenx, BYTE *n, int lenn) +{ + BYTE quot[MAXPLEN+1], rem[2*MAXPLEN+1]; + + memset(quot, 0x00, sizeof(quot)); + memset(rem, 0x00, sizeof(rem)); + if ( DivMod(x, lenx, n, lenn, quot, rem) ) { + memset(x, 0x00, lenx); + memcpy(x+lenx-lenn, rem, lenn); + } +} + +/* + * Div - Computes the integer division of two numbers + * + * x = x / n + * + */ +void Div(BYTE *x, int lenx, BYTE *n, int lenn) +{ + BYTE quot[MAXPLEN+1], rem[2*MAXPLEN+1]; + int lenq; + + memset(quot, 0x00, sizeof(quot)); + memset(rem, 0x00, sizeof(rem)); + if ( (lenq = DivMod(x, lenx, n, lenn, quot, rem)) != 0 ) { + memset(x, 0x00, lenx); + memcpy(x+lenx-lenq, quot, lenq); + } +} + + +/***************************************** +** sub - Subtract two integers * +** * +** A = A - B * +** * +** * +** Parameters: * +** * +** A Address of subtrahend integer * +** B Address of subtractor integer * +** L Length of A and B in bytes * +** * +** NOTE: In order to save RAM, B is * +** two's complemented twice, * +** rather than using a copy of B * +** * +******************************************/ +void sub(BYTE *A, int LA, BYTE *B, int LB) +{ + BYTE *tb; + + tb = (BYTE *)calloc(LA, 1); + memcpy(tb, B, LB); + negate(tb, LB); + add(A, LA, tb, LA); + + FREE(tb); +} + + +/***************************************** +** negate - Negate an integer * +** * +** A = -A * +** * +** * +** Parameters: * +** * +** A Address of integer to negate * +** L Length of A in bytes * +** * +******************************************/ +int negate(BYTE *A, int L) +{ + int i, tL; + DIGIT accum; + + /* Take one's complement of A */ + for ( i=0; i<L; i++ ) + A[i] = ~(A[i]); + + /* Add one to get two's complement of A */ + accum = 1; + tL = L-1; + while ( accum && (tL >= 0) ) { + accum += A[tL]; + A[tL--] = (BYTE)(accum & 0xff); + accum = accum >> 8; + } + + return accum; +} + + +/* + * add() + * + * A = A + B + * + * LB must be <= LA + * + */ +BYTE add(BYTE *A, int LA, BYTE *B, int LB) +{ + int i, indexA, indexB; + DIGIT accum; + + indexA = LA - 1; /* LSD of result */ + indexB = LB - 1; /* LSD of B */ + + accum = 0; + for ( i = 0; i < LB; i++ ) { + accum += A[indexA]; + accum += B[indexB--]; + A[indexA--] = (BYTE)(accum & 0xff); + accum = accum >> 8; + } + + if ( LA > LB ) + while ( accum && (indexA >= 0) ) { + accum += A[indexA]; + A[indexA--] = (BYTE)(accum & 0xff); + accum = accum >> 8; + } + + return (BYTE)accum; +} + + +void prettyprintBstr(char *S, BYTE *A, int L) +{ + int i, extra, ctrb, ctrl; + + if ( L == 0 ) + printf("%s <empty>", S); + else + printf("%s\n\t", S); + extra = L % 24; + if ( extra ) { + ctrb = 0; + for ( i=0; i<24-extra; i++ ) { + printf(" "); + if ( ++ctrb == 4) { + printf(" "); + ctrb = 0; + } + } + + for ( i=0; i<extra; i++ ) { + printf("%02X", A[i]); + if ( ++ctrb == 4) { + printf(" "); + ctrb = 0; + } + } + printf("\n\t"); + } + + ctrb = ctrl = 0; + for ( i=extra; i<L; i++ ) { + printf("%02X", A[i]); + if ( ++ctrb == 4) { + ctrl++; + if ( ctrl == 6 ) { + printf("\n\t"); + ctrl = 0; + } + else + printf(" "); + ctrb = 0; + } + } + printf("\n\n"); +} + + +/**********************************************************************/ +/* Performs byte reverse for PC based implementation (little endian) */ +/**********************************************************************/ +void byteReverse(unsigned long *buffer, int byteCount) +{ + unsigned long value; + int count; + + byteCount /= sizeof( unsigned long ); + for( count = 0; count < byteCount; count++ ) { + value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 ); + buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 ); + } +} + +void +ahtopb (char *ascii_hex, BYTE *p_binary, int bin_len) +{ + BYTE nibble; + int i; + + for ( i=0; i<bin_len; i++ ) { + nibble = ascii_hex[i * 2]; + if ( nibble > 'F' ) + nibble -= 0x20; + if ( nibble > '9' ) + nibble -= 7; + nibble -= '0'; + p_binary[i] = nibble << 4; + + nibble = ascii_hex[i * 2 + 1]; + if ( nibble > 'F' ) + nibble -= 0x20; + if ( nibble > '9' ) + nibble -= 7; + nibble -= '0'; + p_binary[i] += nibble; + } +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/cephes.h b/decoders/session_flags/mesa_sts/src/include/cephes.h new file mode 100644 index 0000000..64c2b1f --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/cephes.h @@ -0,0 +1,13 @@ +#ifndef _NIST_CEPHES_H_ +#define _NIST_CEPHES_H_ + +double cephes_igamc(double a, double x); +double cephes_igam(double a, double x); +double cephes_lgam(double x); +double cephes_p1evl(double x, double *coef, int N); +double cephes_polevl(double x, double *coef, int N); +double cephes_erf(double x); +double cephes_erfc(double x); +double cephes_normal(double x); + +#endif /* _CEPHES_H_ */ diff --git a/decoders/session_flags/mesa_sts/src/include/config.h b/decoders/session_flags/mesa_sts/src/include/config.h new file mode 100644 index 0000000..f31f50f --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/config.h @@ -0,0 +1,52 @@ + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef _NIST_CONFIG_H_ +#define _NIST_CONFIG_H_ + +#define WINDOWS32 +//#define PROTOTYPES +//#define LITTLE_ENDIAN +//#define LOWHI + +/* + * AUTO DEFINES (DON'T TOUCH!) + */ + +#ifndef CSTRTD +typedef char *CSTRTD; +#endif +#ifndef BSTRTD +typedef unsigned char *BSTRTD; +#endif + +#ifndef BYTE +typedef unsigned char BYTE; +#endif +#ifndef UINT +typedef unsigned int UINT; +#endif +#ifndef USHORT +typedef unsigned short USHORT; +#endif +//#ifndef ULONG +//typedef unsigned long ULONG; +//#endif +#ifndef DIGIT +typedef USHORT DIGIT; /* 16-bit word */ +#endif +#ifndef DBLWORD +typedef unsigned long DBLWORD; /* 32-bit word */ +#endif + +#ifndef WORD64 +typedef unsigned long WORD64[2]; /* 64-bit word */ +#endif + +#endif /* _CONFIG_H_ */ + +#if defined(__cplusplus) +} +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/decls.h b/decoders/session_flags/mesa_sts/src/include/decls.h new file mode 100644 index 0000000..510ae47 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/decls.h @@ -0,0 +1,24 @@ +#ifndef _NIST_DECLS_H_ +#define _NIST_DECLS_H_ + +#include <stdio.h> +#include "defs.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + G L O B A L D A T A S T R U C T U R E S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +BitSequence *epsilon; // BIT STREAM +TP tp; // TEST PARAMETER STRUCTURE +FILE *stats[NUMOFTESTS+1]; // FILE OUTPUT STREAM +FILE *results[NUMOFTESTS+1]; // FILE OUTPUT STREAM +FILE *freqfp; // FILE OUTPUT STREAM +FILE *summary; // FILE OUTPUT STREAM +int testVector[NUMOFTESTS+1]; + +char generatorDir[NUMOFGENERATORS][20] = { "AlgorithmTesting", "LCG", "QCG1", "QCG2","CCG", "XOR", + "MODEXP", "BBS", "MS", "G-SHA1" }; + + + +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/defs.h b/decoders/session_flags/mesa_sts/src/include/defs.h new file mode 100644 index 0000000..e0e93f7 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/defs.h @@ -0,0 +1,73 @@ +#ifndef _NIST_DEFS_H_ +#define _NIST_DEFS_H_ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + D E B U G G I N G A I D E S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "config.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + M A C R O S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define MAX(x,y) ((x) < (y) ? (y) : (x)) +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#define isNonPositive(x) ((x) <= 0.e0 ? 1 : 0) +#define isPositive(x) ((x) > 0.e0 ? 1 : 0) +#define isNegative(x) ((x) < 0.e0 ? 1 : 0) +#define isGreaterThanOne(x) ((x) > 1.e0 ? 1 : 0) +#define isZero(x) ((x) == 0.e0 ? 1 : 0) +#define isOne(x) ((x) == 1.e0 ? 1 : 0) + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + G L O B A L C O N S T A N T S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define ALPHA 0.01 /* SIGNIFICANCE LEVEL */ +#define MAXNUMOFTEMPLATES 148 /* APERIODIC TEMPLATES: 148=>temp_length=9 */ + +#define NUMOFGENERATORS 10 /* MAX PRNGs */ +#define MAXFILESPERMITTEDFORPARTITION 148 + +#define TEST_FREQUENCY 1 +#define TEST_BLOCK_FREQUENCY 2 +#define TEST_CUSUM 3 +#define TEST_RUNS 4 +#define TEST_LONGEST_RUN 5 +#define TEST_RANK 6 +#define TEST_FFT 7 +#define TEST_NONPERIODIC 8 +#define TEST_OVERLAPPING 9 +#define TEST_UNIVERSAL 10 +#define TEST_APEN 11 +#define TEST_RND_EXCURSION 12 +#define TEST_RND_EXCURSION_VAR 13 +#define TEST_SERIAL 14 +#define TEST_LINEARCOMPLEXITY 15 +#define TEST_POKER_DETECT 16 +#define TEST_RUNS_DISTRIBUTION 17 +#define TEST_BIN_DERIVATE 18 +#define TEST_SELF_CORR 19 + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + G L O B A L D A T A S T R U C T U R E S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +typedef unsigned char BitSequence; + +typedef struct _testParameters { + int n; + int blockFrequencyBlockLength; + int nonOverlappingTemplateBlockLength; + int overlappingTemplateBlockLength; + int serialBlockLength; + int linearComplexitySequenceLength; + int approximateEntropyBlockLength; + int PokerDetectMLength; + int BinaryDerivateKLength; + int SelfCorrelationDLength; + int numOfBitStreams; +} TP; + +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/externs.h b/decoders/session_flags/mesa_sts/src/include/externs.h new file mode 100644 index 0000000..9f6ea9b --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/externs.h @@ -0,0 +1,21 @@ +#ifndef _NIST_EXTERNS_H_ +#define _NIST_EXTERNS_H_ + +#include "defs.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + G L O B A L D A T A S T R U C T U R E S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +//extern BitSequence *epsilon; // BIT STREAM +//extern TP tp; // TEST PARAMETER STRUCTURE +//extern FILE *stats[NUMOFTESTS+1]; // FILE OUTPUT STREAM +//extern FILE *results[NUMOFTESTS+1]; // FILE OUTPUT STREAM +//extern FILE *freqfp; // FILE OUTPUT STREAM +//extern FILE *summary; // FILE OUTPUT STREAM +//extern int testVector[NUMOFTESTS+1]; +// +//extern char generatorDir[NUMOFGENERATORS][20]; +//extern char testNames[NUMOFTESTS+1][32]; + +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/generators.h b/decoders/session_flags/mesa_sts/src/include/generators.h new file mode 100644 index 0000000..183d05e --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/generators.h @@ -0,0 +1,78 @@ +#ifndef _NIST_GENERATORS_H_ +#define _NIST_GENERATORS_H_ + + +/* The circular shifts. */ +#define CS1(x) ((((ULONG)x)<<1)|(((ULONG)x)>>31)) +#define CS5(x) ((((ULONG)x)<<5)|(((ULONG)x)>>27)) +#define CS30(x) ((((ULONG)x)<<30)|(((ULONG)x)>>2)) + +/* K constants */ + +#define K0 0x5a827999L +#define K1 0x6ed9eba1L +#define K2 0x8f1bbcdcL +#define K3 0xca62c1d6L + +#define f1(x,y,z) ( (x & (y ^ z)) ^ z ) + +#define f3(x,y,z) ( (x & ( y ^ z )) ^ (z & y) ) + +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ + +#define expand(x) Wbuff[x%16] = CS1(Wbuff[(x - 3)%16 ] ^ Wbuff[(x - 8)%16 ] ^ Wbuff[(x - 14)%16] ^ Wbuff[x%16]) + +#define sub1Round1(count) { \ + temp = CS5(A) + f1(B, C, D) + E + Wbuff[count] + K0; \ + E = D; \ + D = C; \ + C = CS30( B ); \ + B = A; \ + A = temp; \ + } \ + +#define sub2Round1(count) \ + { \ + expand(count); \ + temp = CS5(A) + f1(B, C, D) + E + Wbuff[count%16] + K0; \ + E = D; \ + D = C; \ + C = CS30( B ); \ + B = A; \ + A = temp; \ + } \ + +#define Round2(count) \ + { \ + expand(count); \ + temp = CS5( A ) + f2( B, C, D ) + E + Wbuff[count%16] + K1; \ + E = D; \ + D = C; \ + C = CS30( B ); \ + B = A; \ + A = temp; \ + } \ + +#define Round3(count) \ + { \ + expand(count); \ + temp = CS5( A ) + f3( B, C, D ) + E + Wbuff[count%16] + K2; \ + E = D; \ + D = C; \ + C = CS30( B ); \ + B = A; \ + A = temp; \ + } + +#define Round4(count) \ + { \ + expand(count); \ + temp = CS5( A ) + f2( B, C, D ) + E + Wbuff[count%16] + K3; \ + E = D; \ + D = C; \ + C = CS30( B ); \ + B = A; \ + A = temp; \ + } + +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/genutils.h b/decoders/session_flags/mesa_sts/src/include/genutils.h new file mode 100644 index 0000000..3d61ed4 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/genutils.h @@ -0,0 +1,47 @@ +#ifndef _NIST_GENUTILS_H_ +#define _NIST_GENUTILS_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" + +typedef struct _MP_struct { + int size; /* in bytes */ + int bitlen; /* in bits, duh */ + BYTE *val; + } MP; + +#define FREE(A) if ( (A) ) { free((A)); (A) = NULL; } +#define ASCII2BIN(ch) ( (((ch) >= '0') && ((ch) <= '9')) ? ((ch) - '0') : (((ch) >= 'A') && ((ch) <= 'F')) ? ((ch) - 'A' + 10) : ((ch) - 'a' + 10) ) + +#ifndef EXPWD +#define EXPWD ((DBLWORD)1<<NUMLEN) +#endif + +#define sniff_bit(ptr,mask) (*(ptr) & mask) + +/* + * Function Declarations + */ +int greater(BYTE *x, BYTE *y, int l); +int less(BYTE *x, BYTE *y, int l); +BYTE bshl(BYTE *x, int l); +void bshr(BYTE *x, int l); +int Mult(BYTE *A, BYTE *B, int LB, BYTE *C, int LC); +void ModSqr(BYTE *A, BYTE *B, int LB, BYTE *M, int LM); +void ModMult(BYTE *A, BYTE *B, int LB, BYTE *C, int LC, BYTE *M, int LM); +void smult(BYTE *A, BYTE b, BYTE *C, int L); +void Square(BYTE *A, BYTE *B, int L); +void ModExp(BYTE *A, BYTE *B, int LB, BYTE *C, int LC, BYTE *M, int LM); +int DivMod(BYTE *x, int lenx, BYTE *n, int lenn, BYTE *quot, BYTE *rem); +void Mod(BYTE *x, int lenx, BYTE *n, int lenn); +void Div(BYTE *x, int lenx, BYTE *n, int lenn); +void sub(BYTE *A, int LA, BYTE *B, int LB); +int negate(BYTE *A, int L); +BYTE add(BYTE *A, int LA, BYTE *B, int LB); +void prettyprintBstr(char *S, BYTE *A, int L); +void byteReverse(unsigned long *buffer, int byteCount); +void ahtopb (char *ascii_hex, BYTE *p_binary, int bin_len); + +#endif /* _GENUTILS_H_ */ diff --git a/decoders/session_flags/mesa_sts/src/include/matrix.h b/decoders/session_flags/mesa_sts/src/include/matrix.h new file mode 100644 index 0000000..1352c6f --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/matrix.h @@ -0,0 +1,18 @@ +#ifndef _NIST_MATRIX_H_ +#define _NIST_MATRIX_H_ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + R A N K A L G O R I T H M F U N C T I O N P R O T O T Y P E S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int computeRank(int M, int Q, BitSequence **matrix); +void perform_elementary_row_operations(int flag, int i, int M, int Q, BitSequence **A); +int find_unit_element_and_swap(int flag, int i, int M, int Q, BitSequence **A); +int swap_rows(int i, int index, int Q, BitSequence **A); +int determine_rank(int m, int M, int Q, BitSequence **A); +BitSequence** create_matrix(int M, int Q); +void display_matrix(int M, int Q, BitSequence **m); +void def_matrix(int M, int Q, BitSequence **m, int k, BitSequence *epsilon); +void delete_matrix(int M, BitSequence **matrix); + +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/stat_fncs.h b/decoders/session_flags/mesa_sts/src/include/stat_fncs.h new file mode 100644 index 0000000..97d02f0 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/stat_fncs.h @@ -0,0 +1,166 @@ +#ifndef _STAT_FNCS_H_ +#define _STAT_FNCS_H_ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + S T A T I S T I C A L T E S T F U N C T I O N P R O T O T Y P E S + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "defs.h" + +/** + * + * @param in + * @param inl + * @param out 外部预先分配缓冲区,缓冲区大小因最少为字节数的8倍 + * @param outbufsize + * @return + */ +int BytesToBitSequence(unsigned char *in, int inl, BitSequence *outbuf, int bufsize); + +/** + * 单比特频数检测 + * @param n + * @return + */ +int Frequency(int n, BitSequence *epsilon); + +/** + * 块内频数检测 + * @param M + * @param n + * @return + */ +int BlockFrequency(int M, int n, BitSequence *epsilon); + +/** + * 累加和检测 + * @param n + * @return + */ +int CumulativeSums(int n, BitSequence *epsilon); + +/** + * 游程总数检测 + * @param n + * @return + */ +int Runs(int n, BitSequence *epsilon); + +/** + * 块内最大“1”游程检测 + * @param n + * @return + */ +int LongestRunOfOnes(int n, BitSequence *epsilon); + +/** + * 矩阵秩检测 + * @param n + * @return + */ +int Rank(int n, BitSequence *epsilon); + +/** + * 离散傅立叶检测 + * @param n + * @return + */ +int DiscreteFourierTransform(int n, BitSequence *epsilon); + +/** + * 非重叠模版匹配测试 + * @param m + * @param n + * @return + */ +int NonOverlappingTemplateMatchings(int m, int n, BitSequence *epsilon); + +/** + * 重叠模版匹配测试 + * @param m + * @param n + * @return + */ +int OverlappingTemplateMatchings(int m, int n, BitSequence *epsilon); + +/** + * 通用统计检测 + * @param n + * @return + */ +int Universal(int n, BitSequence *epsilon); + +/** + * 近似熵检测 + * @param m + * @param n + * @return + */ +int ApproximateEntropy(int m, int n, BitSequence *epsilon); + +/** + * 自由游程测试 + * @param n + * @return + */ +int RandomExcursions(int n, BitSequence *epsilon); + +/** + * 自由变量测试 + * @param n + * @return + */ +int RandomExcursionsVariant(int n, BitSequence *epsilon); + +/** + * 线性复杂度检测 + * @param M + * @param n + * @return + */ +int LinearComplexity(int M, int n, BitSequence *epsilon); + +/** + * 重叠子序列检测 + * @param m + * @param n + * @return + */ +int Serial(int m, int n, BitSequence *epsilon); + +/** + * 二元推导检测 + * @param k + * @param n + * @param epsilon + * @return + */ +int BinaryDerivate(int k, int n, BitSequence *epsilon, int epsilon_l); + +/** + * 自相关测试 + * @param d + * @param n + * @param epsilon + * @return + */ +int SelfCorrelation(int d, int n, BitSequence *epsilon); + +/** + * 扑克检测 + * @param M + * @param n + * @param epsilon + * @return + */ +int PokerDetect(int M, int n, BitSequence *epsilon); + +/** + * 游程分布检测 + * @param n + * @param epsilon + * @return + */ +int RunsDistribution(int n, BitSequence *epsilon); + +#endif
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/include/utilities.h b/decoders/session_flags/mesa_sts/src/include/utilities.h new file mode 100644 index 0000000..8e4fd7d --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/include/utilities.h @@ -0,0 +1,4 @@ +#include "include/config.h" +#include "include/defs.h" + +int convertToBits(BYTE *x, int xBitLength, int bitsNeeded, int *num_0s, int *num_1s, int *bitsRead, BitSequence* epsilon);
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/linearComplexity.c b/decoders/session_flags/mesa_sts/src/linearComplexity.c new file mode 100644 index 0000000..ae831de --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/linearComplexity.c @@ -0,0 +1,135 @@ +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +int +LinearComplexity(int M, int n, BitSequence *epsilon) +{ + int i, ii, j, d, N, L, m, N_, parity, sign, K = 6; + double p_value, T_, mean, nu[7], chi2; + const double pi[7] = { 0.01047, 0.03125, 0.12500, 0.50000, 0.25000, 0.06250, 0.020833 }; + BitSequence *T, *P, *B_, *C; + + N = (int)floor(n/M); + if ( ((B_ = (BitSequence *) calloc(M, sizeof(BitSequence))) == NULL) || + ((C = (BitSequence *) calloc(M, sizeof(BitSequence))) == NULL) || + ((P = (BitSequence *) calloc(M, sizeof(BitSequence))) == NULL) || + ((T = (BitSequence *) calloc(M, sizeof(BitSequence))) == NULL) ) { + printf("Insufficient Memory for Work Space:: Linear Complexity Test\n"); + if ( B_!= NULL ) + free(B_); + if ( C != NULL ) + free(C); + if ( P != NULL ) + free(P); + if ( T != NULL ) + free(T); + return 0; + } + + +// fprintf(stats[TEST_LINEARCOMPLEXITY], "-----------------------------------------------------\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "\tL I N E A R C O M P L E X I T Y\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "-----------------------------------------------------\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "\tM (substring length) = %d\n", M); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "\tN (number of substrings) = %d\n", N); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "-----------------------------------------------------\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], " F R E Q U E N C Y \n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "-----------------------------------------------------\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], " C0 C1 C2 C3 C4 C5 C6 CHI2 P-value\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "-----------------------------------------------------\n"); +// fprintf(stats[TEST_LINEARCOMPLEXITY], "\tNote: %d bits were discarded!\n", n%M); + + for ( i=0; i<K+1; i++ ) + nu[i] = 0.00; + for ( ii=0; ii<N; ii++ ) { + for ( i=0; i<M; i++ ) { + B_[i] = 0; + C[i] = 0; + T[i] = 0; + P[i] = 0; + } + L = 0; + m = -1; + d = 0; + C[0] = 1; + B_[0] = 1; + + /* DETERMINE LINEAR COMPLEXITY */ + N_ = 0; + while ( N_ < M ) { + d = (int)epsilon[ii*M+N_]; + for ( i=1; i<=L; i++ ) + d += C[i] * epsilon[ii*M+N_-i]; + d = d%2; + if ( d == 1 ) { + for ( i=0; i<M; i++ ) { + T[i] = C[i]; + P[i] = 0; + } + for ( j=0; j<M; j++ ) + if ( B_[j] == 1 ) + P[j+N_-m] = 1; + for ( i=0; i<M; i++ ) + C[i] = (C[i] + P[i])%2; + if ( L <= N_/2 ) { + L = N_ + 1 - L; + m = N_; + for ( i=0; i<M; i++ ) + B_[i] = T[i]; + } + } + N_++; + } + if ( (parity = (M+1)%2) == 0 ) + sign = -1; + else + sign = 1; + mean = M/2.0 + (9.0+sign)/36.0 - 1.0/pow(2, M) * (M/3.0 + 2.0/9.0); + if ( (parity = M%2) == 0 ) + sign = 1; + else + sign = -1; + T_ = sign * (L - mean) + 2.0/9.0; + + if ( T_ <= -2.5 ) + nu[0]++; + else if ( T_ <= -1.5 ) + nu[1]++; + else if (T_ <= -0.5 ) + nu[2]++; + else if ( T_ <= 0.5 ) + nu[3]++; + else if ( T_ <= 1.5 ) + nu[4]++; + else if (T_ <= 2.5 ) + nu[5]++; + else + nu[6]++; + } + chi2 = 0.00; +// for ( i=0; i<K+1; i++ ) { +// fprintf(stats[TEST_LINEARCOMPLEXITY], "%4d ", (int) nu[i]); +// } + for ( i=0; i<K+1; i++ ) { + chi2 += pow(nu[i] - N * pi[i], 2) / (N * pi[i]); + } + p_value = cephes_igamc(K/2.0, chi2/2.0); + +// fprintf(stats[TEST_LINEARCOMPLEXITY], "%9.6f%9.6f\n", chi2, p_value); fflush(stats[TEST_LINEARCOMPLEXITY]); +// fprintf(results[TEST_LINEARCOMPLEXITY], "%f\n", p_value); fflush(results[TEST_LINEARCOMPLEXITY]); + + free(B_); + free(P); + free(C); + free(T); + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +} diff --git a/decoders/session_flags/mesa_sts/src/longestRunOfOnes.c b/decoders/session_flags/mesa_sts/src/longestRunOfOnes.c new file mode 100644 index 0000000..0462778 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/longestRunOfOnes.c @@ -0,0 +1,125 @@ +/* got rid of unused 'k' */ + +#include <stdio.h> +#include <math.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + L O N G E S T R U N S T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +LongestRunOfOnes(int n, BitSequence *epsilon) +{ + double pval, chi2, pi[7]; + int run, v_n_obs, N, i, j, K, M, V[7]; + unsigned int nu[7] = { 0, 0, 0, 0, 0, 0, 0 }; + + if ( n < 128 ) { +// fprintf(stats[TEST_LONGEST_RUN], "\t\t\t LONGEST RUNS OF ONES TEST\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t---------------------------------------------\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t n=%d is too short\n", n); + return 0; + } + if ( n < 6272 ) { + K = 3; + M = 8; + V[0] = 1; V[1] = 2; V[2] = 3; V[3] = 4; + pi[0] = 0.21484375; + pi[1] = 0.3671875; + pi[2] = 0.23046875; + pi[3] = 0.1875; + } + else if ( n < 750000 ) { + K = 5; + M = 128; + V[0] = 4; V[1] = 5; V[2] = 6; V[3] = 7; V[4] = 8; V[5] = 9; + pi[0] = 0.1174035788; + pi[1] = 0.242955959; + pi[2] = 0.249363483; + pi[3] = 0.17517706; + pi[4] = 0.102701071; + pi[5] = 0.112398847; + } + else { + K = 6; + M = 10000; + V[0] = 10; V[1] = 11; V[2] = 12; V[3] = 13; V[4] = 14; V[5] = 15; V[6] = 16; + pi[0] = 0.0882; + pi[1] = 0.2092; + pi[2] = 0.2483; + pi[3] = 0.1933; + pi[4] = 0.1208; + pi[5] = 0.0675; + pi[6] = 0.0727; + } + + N = n/M; + for ( i=0; i<N; i++ ) { + v_n_obs = 0; + run = 0; + for ( j=0; j<M; j++ ) { + if ( epsilon[i*M+j] == 1 ) { + run++; + if ( run > v_n_obs ) + v_n_obs = run; + } + else + run = 0; + } + if ( v_n_obs < V[0] ) + nu[0]++; + for ( j=0; j<=K; j++ ) { + if ( v_n_obs == V[j] ) + nu[j]++; + } + if ( v_n_obs > V[K] ) + nu[K]++; + } + + chi2 = 0.0; + for ( i=0; i<=K; i++ ) + chi2 += ((nu[i] - N * pi[i]) * (nu[i] - N * pi[i])) / (N * pi[i]); + + pval = cephes_igamc((double)(K/2.0), chi2 / 2.0); + +// fprintf(stats[TEST_LONGEST_RUN], "\t\t\t LONGEST RUNS OF ONES TEST\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t---------------------------------------------\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\tCOMPUTATIONAL INFORMATION:\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t---------------------------------------------\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t(a) N (# of substrings) = %d\n", N); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t(b) M (Substring Length) = %d\n", M); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t(c) Chi^2 = %f\n", chi2); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t---------------------------------------------\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t F R E Q U E N C Y\n"); +// fprintf(stats[TEST_LONGEST_RUN], "\t\t---------------------------------------------\n"); + +// if ( K == 3 ) { +// fprintf(stats[TEST_LONGEST_RUN], "\t\t <=1 2 3 >=4 P-value Assignment"); +// fprintf(stats[TEST_LONGEST_RUN], "\n\t\t %3d %3d %3d %3d ", nu[0], nu[1], nu[2], nu[3]); +// } +// else if ( K == 5 ) { +// fprintf(stats[TEST_LONGEST_RUN], "\t\t<=4 5 6 7 8 >=9 P-value Assignment"); +// fprintf(stats[TEST_LONGEST_RUN], "\n\t\t %3d %3d %3d %3d %3d %3d ", nu[0], nu[1], nu[2], +// nu[3], nu[4], nu[5]); +// } +// else { +// fprintf(stats[TEST_LONGEST_RUN],"\t\t<=10 11 12 13 14 15 >=16 P-value Assignment"); +// fprintf(stats[TEST_LONGEST_RUN],"\n\t\t %3d %3d %3d %3d %3d %3d %3d ", nu[0], nu[1], nu[2], +// nu[3], nu[4], nu[5], nu[6]); +// } + if ( isNegative(pval) || isGreaterThanOne(pval) ) { +// fprintf(stats[TEST_LONGEST_RUN], "WARNING: P_VALUE IS OUT OF RANGE.\n"); + return 0; + } + +// fprintf(stats[TEST_LONGEST_RUN], "%s\t\tp_value = %f\n\n", pval < ALPHA ? "FAILURE" : "SUCCESS", pval); fflush(stats[TEST_LONGEST_RUN]); +// fprintf(results[TEST_LONGEST_RUN], "%f\n", pval); fflush(results[TEST_LONGEST_RUN]); + if (pval < ALPHA) { + return 0; + } else { + return 1; + } +} diff --git a/decoders/session_flags/mesa_sts/src/matrix.c b/decoders/session_flags/mesa_sts/src/matrix.c new file mode 100644 index 0000000..c456187 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/matrix.c @@ -0,0 +1,170 @@ +#include <stdio.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/matrix.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +R A N K A L G O R I T H M R O U T I N E S +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define MATRIX_FORWARD_ELIMINATION 0 +#define MATRIX_BACKWARD_ELIMINATION 1 + +int +computeRank(int M, int Q, BitSequence **matrix) +{ + int i, rank, m=MIN(M,Q); + + /* FORWARD APPLICATION OF ELEMENTARY ROW OPERATIONS */ + for ( i=0; i<m-1; i++ ) { + if ( matrix[i][i] == 1 ) + perform_elementary_row_operations(MATRIX_FORWARD_ELIMINATION, i, M, Q, matrix); + else { /* matrix[i][i] = 0 */ + if ( find_unit_element_and_swap(MATRIX_FORWARD_ELIMINATION, i, M, Q, matrix) == 1 ) + perform_elementary_row_operations(MATRIX_FORWARD_ELIMINATION, i, M, Q, matrix); + } + } + + /* BACKWARD APPLICATION OF ELEMENTARY ROW OPERATIONS */ + for ( i=m-1; i>0; i-- ) { + if ( matrix[i][i] == 1 ) + perform_elementary_row_operations(MATRIX_BACKWARD_ELIMINATION, i, M, Q, matrix); + else { /* matrix[i][i] = 0 */ + if ( find_unit_element_and_swap(MATRIX_BACKWARD_ELIMINATION, i, M, Q, matrix) == 1 ) + perform_elementary_row_operations(MATRIX_BACKWARD_ELIMINATION, i, M, Q, matrix); + } + } + + rank = determine_rank(m, M, Q, matrix); + + return rank; +} + +void +perform_elementary_row_operations(int flag, int i, int M, int Q, BitSequence **A) +{ + int j, k; + + if ( flag == MATRIX_FORWARD_ELIMINATION ) { + for ( j=i+1; j<M; j++ ) + if ( A[j][i] == 1 ) + for ( k=i; k<Q; k++ ) + A[j][k] = (A[j][k] + A[i][k]) % 2; + } + else { + for ( j=i-1; j>=0; j-- ) + if ( A[j][i] == 1 ) + for ( k=0; k<Q; k++ ) + A[j][k] = (A[j][k] + A[i][k]) % 2; + } +} + +int +find_unit_element_and_swap(int flag, int i, int M, int Q, BitSequence **A) +{ + int index, row_op=0; + + if ( flag == MATRIX_FORWARD_ELIMINATION ) { + index = i+1; + while ( (index < M) && (A[index][i] == 0) ) + index++; + if ( index < M ) + row_op = swap_rows(i, index, Q, A); + } + else { + index = i-1; + while ( (index >= 0) && (A[index][i] == 0) ) + index--; + if ( index >= 0 ) + row_op = swap_rows(i, index, Q, A); + } + + return row_op; +} + +int +swap_rows(int i, int index, int Q, BitSequence **A) +{ + int p; + BitSequence temp; + + for ( p=0; p<Q; p++ ) { + temp = A[i][p]; + A[i][p] = A[index][p]; + A[index][p] = temp; + } + + return 1; +} + +int +determine_rank(int m, int M, int Q, BitSequence **A) +{ + int i, j, rank, allZeroes; + + /* DETERMINE RANK, THAT IS, COUNT THE NUMBER OF NONZERO ROWS */ + + rank = m; + for ( i=0; i<M; i++ ) { + allZeroes = 1; + for ( j=0; j<Q; j++) { + if ( A[i][j] == 1 ) { + allZeroes = 0; + break; + } + } + if ( allZeroes == 1 ) + rank--; + } + + return rank; +} + +BitSequence** +create_matrix(int M, int Q) +{ + int i; + BitSequence **matrix; + + if ( (matrix = (BitSequence **) calloc(M, sizeof(BitSequence *))) == NULL ) { + printf("ERROR IN FUNCTION create_matrix: Insufficient memory available.\n"); + + return NULL; + } + else { + for ( i=0; i<M; i++ ) { + if ( (matrix[i] = calloc(Q, sizeof(BitSequence))) == NULL ) { + printf("ERROR IN FUNCTION create_matrix: Insufficient memory for %dx%d matrix.\n", M, M); + + return NULL; + } + } + return matrix; + } +} + +void +def_matrix(int M, int Q, BitSequence **m, int k, BitSequence *epsilon) +{ + int i,j; + + for ( i=0; i<M; i++ ) + for ( j=0; j<Q; j++ ) + m[i][j] = epsilon[k*(M*Q)+j+i*M]; +} + +void +delete_matrix(int M, BitSequence **matrix) +{ + int i; + + if (matrix != NULL) { + for (i = 0; i < M; i++) { + if (matrix[i] != NULL) { + free(matrix[i]); + matrix[i] = NULL; + } + } + free(matrix); + } +} diff --git a/decoders/session_flags/mesa_sts/src/mesa_sts.c b/decoders/session_flags/mesa_sts/src/mesa_sts.c new file mode 100644 index 0000000..f95ac89 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/mesa_sts.c @@ -0,0 +1,114 @@ +#include <stdlib.h> +#include "include/utilities.h" +#include "include/stat_fncs.h" +#include "mesa_sts.h" + +int mesa_statistical_test_suite(void* data,unsigned int datalen, struct sts_result* result, unsigned int random_judge_switch_flag) +{ + TP tp; + tp.n = datalen; + tp.blockFrequencyBlockLength = 128; + tp.nonOverlappingTemplateBlockLength = 9; + tp.overlappingTemplateBlockLength = 9; + tp.approximateEntropyBlockLength = 10; + tp.serialBlockLength = 16; + tp.linearComplexitySequenceLength = 500; + tp.numOfBitStreams = 1; + tp.PokerDetectMLength = 8; + tp.BinaryDerivateKLength = 3; + tp.SelfCorrelationDLength = 8; + + BitSequence* epsilon = (BitSequence *)calloc(tp.n,sizeof(BitSequence)); + int done, num_0s, num_1s, bitsRead; + num_0s = 0; + num_1s = 0; + bitsRead = 0; + done = 0; + done = convertToBits((BYTE*)data,datalen,tp.n,&num_0s,&num_1s,&bitsRead,epsilon); + if (STS_TEST_FLAG(random_judge_switch_flag, STS_FREQUENCY)) + { + result->frequency = Frequency(tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_BLOCK_FREQUENCY)) + { + result->block_frequency = BlockFrequency(tp.blockFrequencyBlockLength, tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_CUMULATIVE_SUMS)) + { + result->cumulative_sums = CumulativeSums(tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_RUNS)) + { + result->runs = Runs(tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_LONGEST_RUN)) + { + result->longest_run = LongestRunOfOnes(tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_RANK)) + { + result->rank = Rank(tp.n,epsilon); + } + + //result->discrete_fourier_transform = DiscreteFourierTransform(tp.n,epsilon);//cost too much time + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_NON_OVERLAPPING_TEMPLATE_MATCHING)) + { + result->non_overlapping_template_matching = NonOverlappingTemplateMatchings(tp.nonOverlappingTemplateBlockLength, tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_OVERLAPPING_TEMPLATE_MATCHING)) + { + result->overlapping_template_matching = OverlappingTemplateMatchings(tp.overlappingTemplateBlockLength, tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_UNIVERSAL)) + { + result->universal = Universal(tp.n,epsilon); + } + + //result->approximate_entropy = ApproximateEntropy(tp.approximateEntropyBlockLength, tp.n,epsilon);//cost too much time + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_RANDOM_EXCURSIONS)) + { + result->random_excursions = RandomExcursions(tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_RANDOM_EXCURSIONS_VARIANT)) + { + result->random_excursions_variant = RandomExcursionsVariant(tp.n,epsilon); + } + + //result->serial = Serial(tp.serialBlockLength,tp.n,epsilon);//cost too much time + //sresult->linear_complexity = LinearComplexity(tp.linearComplexitySequenceLength, tp.n,epsilon);//cost too much time + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_POKER_DETECT)) + { + result->poker_detect = PokerDetect(tp.PokerDetectMLength,tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_RUNS_DISTRIBUTION)) + { + result->runs_distribution = RunsDistribution(tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_SELF_CORRELATION)) + { + result->self_correlation = SelfCorrelation(tp.SelfCorrelationDLength,tp.n,epsilon); + } + + if (STS_TEST_FLAG(random_judge_switch_flag, STS_BINARY_DERIVATE)) + { + result->binary_derivative = BinaryDerivate(tp.BinaryDerivateKLength,tp.n,epsilon,tp.n);//this function will change the value of epsilon, must be the last one + } + + free(epsilon); + epsilon = NULL; + + return 0; +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/nonOverlappingTemplateMatchings.c b/decoders/session_flags/mesa_sts/src/nonOverlappingTemplateMatchings.c new file mode 100644 index 0000000..1bc47db --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/nonOverlappingTemplateMatchings.c @@ -0,0 +1,281 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + N O N O V E R L A P P I N G T E M P L A T E T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +static unsigned int template9[] = { +0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,1,1, +0,0,0,0,0,0,1,0,1, +0,0,0,0,0,0,1,1,1, +0,0,0,0,0,1,0,0,1, +0,0,0,0,0,1,0,1,1, +0,0,0,0,0,1,1,0,1, +0,0,0,0,0,1,1,1,1, +0,0,0,0,1,0,0,0,1, +0,0,0,0,1,0,0,1,1, +0,0,0,0,1,0,1,0,1, +0,0,0,0,1,0,1,1,1, +0,0,0,0,1,1,0,0,1, +0,0,0,0,1,1,0,1,1, +0,0,0,0,1,1,1,0,1, +0,0,0,0,1,1,1,1,1, +0,0,0,1,0,0,0,1,1, +0,0,0,1,0,0,1,0,1, +0,0,0,1,0,0,1,1,1, +0,0,0,1,0,1,0,0,1, +0,0,0,1,0,1,0,1,1, +0,0,0,1,0,1,1,0,1, +0,0,0,1,0,1,1,1,1, +0,0,0,1,1,0,0,1,1, +0,0,0,1,1,0,1,0,1, +0,0,0,1,1,0,1,1,1, +0,0,0,1,1,1,0,0,1, +0,0,0,1,1,1,0,1,1, +0,0,0,1,1,1,1,0,1, +0,0,0,1,1,1,1,1,1, +0,0,1,0,0,0,0,1,1, +0,0,1,0,0,0,1,0,1, +0,0,1,0,0,0,1,1,1, +0,0,1,0,0,1,0,1,1, +0,0,1,0,0,1,1,0,1, +0,0,1,0,0,1,1,1,1, +0,0,1,0,1,0,0,1,1, +0,0,1,0,1,0,1,0,1, +0,0,1,0,1,0,1,1,1, +0,0,1,0,1,1,0,1,1, +0,0,1,0,1,1,1,0,1, +0,0,1,0,1,1,1,1,1, +0,0,1,1,0,0,1,0,1, +0,0,1,1,0,0,1,1,1, +0,0,1,1,0,1,0,1,1, +0,0,1,1,0,1,1,0,1, +0,0,1,1,0,1,1,1,1, +0,0,1,1,1,0,1,0,1, +0,0,1,1,1,0,1,1,1, +0,0,1,1,1,1,0,1,1, +0,0,1,1,1,1,1,0,1, +0,0,1,1,1,1,1,1,1, +0,1,0,0,0,0,0,1,1, +0,1,0,0,0,0,1,1,1, +0,1,0,0,0,1,0,1,1, +0,1,0,0,0,1,1,1,1, +0,1,0,0,1,0,0,1,1, +0,1,0,0,1,0,1,1,1, +0,1,0,0,1,1,0,1,1, +0,1,0,0,1,1,1,1,1, +0,1,0,1,0,0,0,1,1, +0,1,0,1,0,0,1,1,1, +0,1,0,1,0,1,0,1,1, +0,1,0,1,0,1,1,1,1, +0,1,0,1,1,0,0,1,1, +0,1,0,1,1,0,1,1,1, +0,1,0,1,1,1,0,1,1, +0,1,0,1,1,1,1,1,1, +0,1,1,0,0,0,1,1,1, +0,1,1,0,0,1,1,1,1, +0,1,1,0,1,0,1,1,1, +0,1,1,0,1,1,1,1,1, +0,1,1,1,0,1,1,1,1, +0,1,1,1,1,1,1,1,1, +1,0,0,0,0,0,0,0,0, +1,0,0,0,1,0,0,0,0, +1,0,0,1,0,0,0,0,0, +1,0,0,1,0,1,0,0,0, +1,0,0,1,1,0,0,0,0, +1,0,0,1,1,1,0,0,0, +1,0,1,0,0,0,0,0,0, +1,0,1,0,0,0,1,0,0, +1,0,1,0,0,1,0,0,0, +1,0,1,0,0,1,1,0,0, +1,0,1,0,1,0,0,0,0, +1,0,1,0,1,0,1,0,0, +1,0,1,0,1,1,0,0,0, +1,0,1,0,1,1,1,0,0, +1,0,1,1,0,0,0,0,0, +1,0,1,1,0,0,1,0,0, +1,0,1,1,0,1,0,0,0, +1,0,1,1,0,1,1,0,0, +1,0,1,1,1,0,0,0,0, +1,0,1,1,1,0,1,0,0, +1,0,1,1,1,1,0,0,0, +1,0,1,1,1,1,1,0,0, +1,1,0,0,0,0,0,0,0, +1,1,0,0,0,0,0,1,0, +1,1,0,0,0,0,1,0,0, +1,1,0,0,0,1,0,0,0, +1,1,0,0,0,1,0,1,0, +1,1,0,0,1,0,0,0,0, +1,1,0,0,1,0,0,1,0, +1,1,0,0,1,0,1,0,0, +1,1,0,0,1,1,0,0,0, +1,1,0,0,1,1,0,1,0, +1,1,0,1,0,0,0,0,0, +1,1,0,1,0,0,0,1,0, +1,1,0,1,0,0,1,0,0, +1,1,0,1,0,1,0,0,0, +1,1,0,1,0,1,0,1,0, +1,1,0,1,0,1,1,0,0, +1,1,0,1,1,0,0,0,0, +1,1,0,1,1,0,0,1,0, +1,1,0,1,1,0,1,0,0, +1,1,0,1,1,1,0,0,0, +1,1,0,1,1,1,0,1,0, +1,1,0,1,1,1,1,0,0, +1,1,1,0,0,0,0,0,0, +1,1,1,0,0,0,0,1,0, +1,1,1,0,0,0,1,0,0, +1,1,1,0,0,0,1,1,0, +1,1,1,0,0,1,0,0,0, +1,1,1,0,0,1,0,1,0, +1,1,1,0,0,1,1,0,0, +1,1,1,0,1,0,0,0,0, +1,1,1,0,1,0,0,1,0, +1,1,1,0,1,0,1,0,0, +1,1,1,0,1,0,1,1,0, +1,1,1,0,1,1,0,0,0, +1,1,1,0,1,1,0,1,0, +1,1,1,0,1,1,1,0,0, +1,1,1,1,0,0,0,0,0, +1,1,1,1,0,0,0,1,0, +1,1,1,1,0,0,1,0,0, +1,1,1,1,0,0,1,1,0, +1,1,1,1,0,1,0,0,0, +1,1,1,1,0,1,0,1,0, +1,1,1,1,0,1,1,0,0, +1,1,1,1,0,1,1,1,0, +1,1,1,1,1,0,0,0,0, +1,1,1,1,1,0,0,1,0, +1,1,1,1,1,0,1,0,0, +1,1,1,1,1,0,1,1,0, +1,1,1,1,1,1,0,0,0, +1,1,1,1,1,1,0,1,0, +1,1,1,1,1,1,1,0,0, +1,1,1,1,1,1,1,1,0, +}; +static size_t template_size = sizeof(template9)/sizeof(template9[0]); + +int +NonOverlappingTemplateMatchings(int m, int n, BitSequence *epsilon) +{ + int ret = 0; + int numOfTemplates[100] = {0, 0, 2, 4, 6, 12, 20, 40, 74, 148, 284, 568, 1116, + 2232, 4424, 8848, 17622, 35244, 70340, 140680, 281076, 562152}; + /*---------------------------------------------------------------------------- + NOTE: Should additional templates lengths beyond 21 be desired, they must + first be constructed, saved into files and then the corresponding + number of nonperiodic templates for that file be stored in the m-th + position in the numOfTemplates variable. + ----------------------------------------------------------------------------*/ + unsigned int W_obs, nu[6], *Wj = NULL; + size_t template_idx = 0; + double sum, chi2, p_value, lambda, pi[6], varWj; + int i, j, jj, k, match, SKIP, M, N, K = 5; + BitSequence *sequence = NULL; + + N = 8; + M = n/N; + + if ( (Wj = (unsigned int*)calloc(N, sizeof(unsigned int))) == NULL ) { + return 0; + } + lambda = (M-m+1)/pow(2, m); + varWj = M*(1.0/pow(2.0, m) - (2.0*m-1.0)/pow(2.0, 2.0*m)); + + if ( ((isNegative(lambda)) || (isZero(lambda))) || + ((sequence = (BitSequence *) calloc(m, sizeof(BitSequence))) == NULL) ) { + goto end; + } + else { + if ( numOfTemplates[m] < MAXNUMOFTEMPLATES ) + SKIP = 1; + else + SKIP = (int)(numOfTemplates[m]/MAXNUMOFTEMPLATES); + numOfTemplates[m] = (int)numOfTemplates[m]/SKIP; + + sum = 0.0; + for ( i=0; i<2; i++ ) { /* Compute Probabilities */ + pi[i] = exp(-lambda+i*log(lambda)-cephes_lgam(i+1)); + sum += pi[i]; + } + pi[0] = sum; + for ( i=2; i<=K; i++ ) { /* Compute Probabilities */ + pi[i-1] = exp(-lambda+i*log(lambda)-cephes_lgam(i+1)); + sum += pi[i-1]; + } + pi[K] = 1 - sum; + + for( jj=0; jj<MIN(MAXNUMOFTEMPLATES, numOfTemplates[m]); jj++ ) { + sum = 0; + + for ( k=0; k<m; k++ ) { + if (template_idx < template_size) { + sequence[k] = template9[template_idx]; + template_idx++; + } + else { + sequence[k] = 0; + } +// fprintf(stats[TEST_NONPERIODIC], "%d", sequence[k]); + } +// fprintf(stats[TEST_NONPERIODIC], " "); + for ( k=0; k<=K; k++ ) + nu[k] = 0; + for ( i=0; i<N; i++ ) { + W_obs = 0; + for ( j=0; j<M-m+1; j++ ) { + match = 1; + for ( k=0; k<m; k++ ) { + if ( (int)sequence[k] != (int)epsilon[i*M+j+k] ) { + match = 0; + break; + } + } + if ( match == 1 ) + W_obs++; + } + Wj[i] = W_obs; + } + sum = 0; + chi2 = 0.0; /* Compute Chi Square */ + for ( i=0; i<N; i++ ) { +// if ( m == 10 ) +// fprintf(stats[TEST_NONPERIODIC], "%3d ", Wj[i]); +// else +// fprintf(stats[TEST_NONPERIODIC], "%4d ", Wj[i]); + chi2 += pow(((double)Wj[i] - lambda)/pow(varWj, 0.5), 2); + } + p_value = cephes_igamc(N/2.0, chi2/2.0); + + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { +// fprintf(stats[TEST_NONPERIODIC], "\t\tWARNING: P_VALUE IS OUT OF RANGE.\n"); + goto end; + } + +// fprintf(stats[TEST_NONPERIODIC], "%9.6f %f %s %3d\n", chi2, p_value, p_value < ALPHA ? "FAILURE" : "SUCCESS", jj); + if ( SKIP > 1 ) + template_idx += (SKIP-1)*2*m; +// fprintf(results[TEST_NONPERIODIC], "%f\n", p_value); fflush(results[TEST_NONPERIODIC]); + if (p_value < ALPHA) { + goto end; + } + } + } + + ret = 1; +// fprintf(stats[TEST_NONPERIODIC], "\n"); fflush(stats[TEST_NONPERIODIC]); + + end: + if (Wj != NULL) { + free(Wj); + } + if (sequence != NULL) { + free(sequence); + } + return ret; +} diff --git a/decoders/session_flags/mesa_sts/src/overlappingTemplateMatchings.c b/decoders/session_flags/mesa_sts/src/overlappingTemplateMatchings.c new file mode 100644 index 0000000..70eabdf --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/overlappingTemplateMatchings.c @@ -0,0 +1,97 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + O V E R L A P P I N G T E M P L A T E T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +double Pr(int u, double eta); + +int +OverlappingTemplateMatchings(int m, int n, BitSequence *epsilon) +{ + int ret = 0; + int i, k, match; + double W_obs, eta, sum, chi2, p_value, lambda; + int M, N, j, K = 5; + unsigned int nu[6] = { 0, 0, 0, 0, 0, 0 }; + double pi[6] = { 0.143783, 0.139430, 0.137319, 0.124314, 0.106209, 0.348945 }; + BitSequence *sequence; + + M = 1032; + N = n/M; + + if ( (sequence = (BitSequence *) calloc(m, sizeof(BitSequence))) == NULL ) { + return 0; + } + else { + for (i = 0; i < m; i++) + sequence[i] = 1; + } + + lambda = (double)(M-m+1)/pow(2,m); + eta = lambda/2.0; + sum = 0.0; + for ( i=0; i<K; i++ ) { /* Compute Probabilities */ + pi[i] = Pr(i, eta); + sum += pi[i]; + } + pi[K] = 1 - sum; + + for ( i=0; i<N; i++ ) { + W_obs = 0; + for ( j=0; j<M-m+1; j++ ) { + match = 1; + for ( k=0; k<m; k++ ) { + if ( sequence[k] != epsilon[i*M+j+k] ) + match = 0; + } + if ( match == 1 ) + W_obs++; + } + if ( W_obs <= 4 ) + nu[(int)W_obs]++; + else + nu[K]++; + } + sum = 0; + chi2 = 0.0; /* Compute Chi Square */ + for ( i=0; i<K+1; i++ ) { + chi2 += pow((double)nu[i] - (double)N*pi[i], 2)/((double)N*pi[i]); + sum += nu[i]; + } + p_value = cephes_igamc(K/2.0, chi2/2.0); + + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { + goto end; + } + if (p_value < ALPHA) { + goto end; + } + + ret = 1; + + end: + free(sequence); + return ret; +} + +double +Pr(int u, double eta) +{ + int l; + double sum, p; + + if ( u == 0 ) + p = exp(-eta); + else { + sum = 0.0; + for ( l=1; l<=u; l++ ) + sum += exp(-eta-u*log(2)+l*log(eta)-cephes_lgam(l+1)+cephes_lgam(u)-cephes_lgam(l)-cephes_lgam(u-l+1)); + p = sum; + } + return p; +} diff --git a/decoders/session_flags/mesa_sts/src/pokerDetect.c b/decoders/session_flags/mesa_sts/src/pokerDetect.c new file mode 100644 index 0000000..44d9a3c --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/pokerDetect.c @@ -0,0 +1,79 @@ +#include <stdlib.h> +#include <math.h> +#include "include/stat_fncs.h" +#include "include/cephes.h" + +typedef struct _PokerNi { + unsigned int flag; + unsigned int count; +} PokerNi; + +unsigned char toByte(BitSequence *subEpsilon, int M) +{ + int i = 0; + unsigned char result = 0; + for (i = 0; i < M; ++i) { + result |= (subEpsilon[i] << (M - i - 1)); + } + return result; +} + +int findIndex(PokerNi *tab, int tabSize, unsigned int flag) +{ + int i = 0; + for (i = 0; i < tabSize; ++i) { + if (tab[i].flag == flag) { + return i; + } + } + return -1; +} + +int PokerDetect(int M, int n, BitSequence *epsilon) +{ + int ret = 0; + int i = 0, j = 0, N = n / M, index = 0, c = 0; + int maxElements = (int) pow(2, M); + double p_value = 0.0, sum_ni = 0.0, mp = 0.0, V = 0.0; + unsigned int flag = 0; + PokerNi *tab = NULL; + + if (M > 8) { + return 0; + } + + tab = (PokerNi *)calloc(maxElements, sizeof(PokerNi)); + if (NULL == tab) { + return 0; + } + for (i = 0; i < maxElements; ++i) { + tab[i].flag = (unsigned int) i; + tab[i].count = 0; + } + + for (i = 0, j = 0; j < N; ++j, i += M) { + flag = toByte(epsilon + i, M); + index = findIndex(tab, maxElements, flag); + if (-1 == index) { + goto end; + } + tab[index].count += 1; + } + + for (i = 0; i < maxElements; ++i) { + sum_ni += pow(tab[i].count, 2); + } + mp = (double)maxElements / N; + V = mp * sum_ni - N; + + p_value = cephes_igamc((double)(maxElements - 1) / 2, V / 2); + if (p_value < ALPHA) { + goto end; + } + + ret = 1; + + end: + free(tab); + return ret; +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/randomExcursions.c b/decoders/session_flags/mesa_sts/src/randomExcursions.c new file mode 100644 index 0000000..135396d --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/randomExcursions.c @@ -0,0 +1,116 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + R A N D O M E X C U R S I O N S T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +RandomExcursions(int n, BitSequence *epsilon) +{ + int ret = 0; + int b, i, j, k, J, x; + int cycleStart, cycleStop, *cycle = NULL, *S_k = NULL; + const int stateX[8] = { -4, -3, -2, -1, 1, 2, 3, 4 }; + int counter[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + double p_value, sum, constraint, nu[6][8]; + double pi[5][6] = { {0.0000000000, 0.00000000000, 0.00000000000, 0.00000000000, 0.00000000000, 0.0000000000}, + {0.5000000000, 0.25000000000, 0.12500000000, 0.06250000000, 0.03125000000, 0.0312500000}, + {0.7500000000, 0.06250000000, 0.04687500000, 0.03515625000, 0.02636718750, 0.0791015625}, + {0.8333333333, 0.02777777778, 0.02314814815, 0.01929012346, 0.01607510288, 0.0803755143}, + {0.8750000000, 0.01562500000, 0.01367187500, 0.01196289063, 0.01046752930, 0.0732727051} }; + + if ( ((S_k = (int *)calloc(n, sizeof(int))) == NULL) || + ((cycle = (int *)calloc(MAX(1000, n/100), sizeof(int))) == NULL) ) { + printf("Random Excursions Test: Insufficent Work Space Allocated.\n"); + if ( S_k != NULL ) + free(S_k); + if ( cycle != NULL ) + free(cycle); + return 0; + } + + J = 0; /* DETERMINE CYCLES */ + S_k[0] = 2*(int)epsilon[0] - 1; + for( i=1; i<n; i++ ) { + S_k[i] = S_k[i-1] + 2*epsilon[i] - 1; + if ( S_k[i] == 0 ) { + J++; + if ( J > MAX(1000, n/100) ) { + printf("ERROR IN FUNCTION randomExcursions: EXCEEDING THE MAX NUMBER OF CYCLES EXPECTED\n."); + goto end; + } + cycle[J] = i; + } + } + if ( S_k[n-1] != 0 ) + J++; + cycle[J] = n; + + constraint = MAX(0.005*pow(n, 0.5), 500); + if (J < constraint) { + ret = 1; //TODO + goto end; + } + else { + cycleStart = 0; + cycleStop = cycle[1]; + for ( k=0; k<6; k++ ) + for ( i=0; i<8; i++ ) + nu[k][i] = 0.; + for ( j=1; j<=J; j++ ) { /* FOR EACH CYCLE */ + for ( i=0; i<8; i++ ) + counter[i] = 0; + for ( i=cycleStart; i<cycleStop; i++ ) { + if ( (S_k[i] >= 1 && S_k[i] <= 4) || (S_k[i] >= -4 && S_k[i] <= -1) ) { + if ( S_k[i] < 0 ) + b = 4; + else + b = 3; + counter[S_k[i]+b]++; + } + } + cycleStart = cycle[j]+1; + if ( j < J ) + cycleStop = cycle[j+1]; + + for ( i=0; i<8; i++ ) { + if ( (counter[i] >= 0) && (counter[i] <= 4) ) + nu[counter[i]][i]++; + else if ( counter[i] >= 5 ) + nu[5][i]++; + } + } + + for ( i=0; i<8; i++ ) { + x = stateX[i]; + sum = 0.; + for ( k=0; k<6; k++ ) + sum += pow(nu[k][i] - J*pi[(int)fabs(x)][k], 2) / (J*pi[(int)fabs(x)][k]); + p_value = cephes_igamc(2.5, sum/2.0); + + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { +// fprintf(stats[TEST_RND_EXCURSION], "WARNING: P_VALUE IS OUT OF RANGE.\n"); + goto end; + } + +// fprintf(stats[TEST_RND_EXCURSION], "%s\t\tx = %2d chi^2 = %9.6f p_value = %f\n", +// p_value < ALPHA ? "FAILURE" : "SUCCESS", x, sum, p_value); +// fprintf(results[TEST_RND_EXCURSION], "%f\n", p_value); fflush(results[TEST_RND_EXCURSION]); + if (p_value < ALPHA) { + goto end; + } + } + } +// fprintf(stats[TEST_RND_EXCURSION], "\n"); fflush(stats[TEST_RND_EXCURSION]); + ret = 1; + + end: + free(S_k); + free(cycle); + return ret; +} diff --git a/decoders/session_flags/mesa_sts/src/randomExcursionsVariant.c b/decoders/session_flags/mesa_sts/src/randomExcursionsVariant.c new file mode 100644 index 0000000..447ddf6 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/randomExcursionsVariant.c @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + R A N D O M E X C U R S I O N S V A R I A N T T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +RandomExcursionsVariant(int n, BitSequence *epsilon) +{ + int ret = 0; + int i, p, J, x, constraint, count, *S_k = NULL; + const int stateX[18] = { -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + double p_value; + + if ( (S_k = (int *)calloc(n, sizeof(int))) == NULL ) { + return 0; + } + J = 0; + S_k[0] = 2*(int)epsilon[0] - 1; + for ( i=1; i<n; i++ ) { + S_k[i] = S_k[i-1] + 2*epsilon[i] - 1; + if ( S_k[i] == 0 ) + J++; + } + if ( S_k[n-1] != 0 ) + J++; + + constraint = (int)MAX(0.005*pow(n, 0.5), 500); + if (J < constraint) { + ret = 1; //TODO + goto end; + } + else { + for ( p=0; p<=17; p++ ) { + x = stateX[p]; + count = 0; + for ( i=0; i<n; i++ ) + if ( S_k[i] == x ) + count++; + p_value = erfc(fabs(count-J)/(sqrt(2.0*J*(4.0*fabs(x)-2)))); + + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { + goto end; + } + if (p_value < ALPHA) { + goto end; + } + } + } + + ret = 1; + + end: + free(S_k); + return ret; +} diff --git a/decoders/session_flags/mesa_sts/src/rank.c b/decoders/session_flags/mesa_sts/src/rank.c new file mode 100644 index 0000000..e9898ca --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/rank.c @@ -0,0 +1,76 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" +#include "include/matrix.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + R A N K T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +Rank(int n, BitSequence *epsilon) +{ + int ret = 0; + int N, i, k, r; + double p_value, product, chi_squared, arg1, p_32, p_31, p_30, R, F_32, F_31, F_30; + BitSequence **matrix = create_matrix(32, 32); + + N = n/(32*32); + if ( isZero(N) ) { + p_value = 0.00; + } + else { + r = 32; /* COMPUTE PROBABILITIES */ + product = 1; + for ( i=0; i<=r-1; i++ ) + product *= ((1.e0-pow(2, i-32))*(1.e0-pow(2, i-32)))/(1.e0-pow(2, i-r)); + p_32 = pow(2, r*(32+32-r)-32*32) * product; + + r = 31; + product = 1; + for ( i=0; i<=r-1; i++ ) + product *= ((1.e0-pow(2, i-32))*(1.e0-pow(2, i-32)))/(1.e0-pow(2, i-r)); + p_31 = pow(2, r*(32+32-r)-32*32) * product; + + p_30 = 1 - (p_32+p_31); + + F_32 = 0; + F_31 = 0; + for ( k=0; k<N; k++ ) { /* FOR EACH 32x32 MATRIX */ + def_matrix(32, 32, matrix, k, epsilon); +#if (DISPLAY_MATRICES == 1) + display_matrix(32, 32, matrix); +#endif + R = computeRank(32, 32, matrix); + if ( R == 32 ) + F_32++; /* DETERMINE FREQUENCIES */ + if ( R == 31 ) + F_31++; + } + F_30 = (double)N - (F_32+F_31); + + chi_squared =(pow(F_32 - N*p_32, 2)/(double)(N*p_32) + + pow(F_31 - N*p_31, 2)/(double)(N*p_31) + + pow(F_30 - N*p_30, 2)/(double)(N*p_30)); + + arg1 = -chi_squared/2.e0; + + p_value = exp(arg1); + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { + goto end; + } + } + + if (p_value < ALPHA) { + goto end; + } + + ret = 1; + + end: + delete_matrix(32, matrix); + return ret; +} diff --git a/decoders/session_flags/mesa_sts/src/runs.c b/decoders/session_flags/mesa_sts/src/runs.c new file mode 100644 index 0000000..ddea5a0 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/runs.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + R U N S T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +Runs(int n, BitSequence *epsilon) +{ + int S, k; + double pi, V, erfc_arg, p_value; + + S = 0; + for ( k=0; k<n; k++ ) + if ( epsilon[k] ) + S++; + pi = (double)S / (double)n; + + if ( fabs(pi - 0.5) > (2.0 / sqrt(n)) ) { + p_value = 0.0; + } + else { + + V = 1; + for ( k=1; k<n; k++ ) + if ( epsilon[k] != epsilon[k-1] ) + V++; + + erfc_arg = fabs(V - 2.0 * n * pi * (1-pi)) / (2.0 * pi * (1-pi) * sqrt(2*n)); + p_value = erfc(erfc_arg); + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { + return 0; + } + } + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +} diff --git a/decoders/session_flags/mesa_sts/src/runsDistribution.c b/decoders/session_flags/mesa_sts/src/runsDistribution.c new file mode 100644 index 0000000..4fad006 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/runsDistribution.c @@ -0,0 +1,82 @@ +#include <stdlib.h> +#include <math.h> +#include "include/stat_fncs.h" +#include "include/cephes.h" + +int RunsDistribution(int n, BitSequence *epsilon) +{ + int ret = 0; + int i = 0, j = 0, k = 0; + unsigned char runFlag = 0x00; + double p_value = 0.0, sum_bi = 0.0, sum_gi = 0.0, V = 0.0; + double *bi = NULL, *gi = NULL, *e = NULL; + double bit = 0.0, git = 0.0, et = 0.0; + + bi = (double *)calloc(n, sizeof(double)); + if (NULL == bi) { + goto end; + } + gi = (double *)calloc(n, sizeof(double)); + if (NULL == gi) { + goto end; + } + e = (double *)calloc(n, sizeof(double)); + if (NULL == e) { + goto end; + } + + for (i = 1; i <= n; ++i) { + e[i - 1] = (double)(n - i + 3) / pow(2, i + 2); + if (e[i - 1] >= 5) { + k = i; + } + } + + runFlag = epsilon[0]; + j = 1; + for (i = 1; i < n; ++i) { + if (epsilon[i] != runFlag) { + if (runFlag == 0x00) { + gi[j - 1] += 1; + } else if (runFlag == 0x01) { + bi[j - 1] += 1; + } + runFlag = epsilon[i]; + j = 1; + } else { + ++j; + } + } + + for (i = 0; i < k; ++i) { + bit = bi[i]; + et = e[i]; + sum_bi += pow(bit - et, 2) / et; + } + for (i = 0; i < k; ++i) { + git = gi[i]; + et = e[i]; + sum_gi += pow(git - et, 2) / et; + } + V = sum_bi + sum_gi; + + p_value = cephes_igamc(k - 1, V / 2); + if (p_value < ALPHA) { + goto end; + } + + ret = 1; + + end: + if (NULL != bi) { + free(bi); + } + if (NULL != gi) { + free(gi); + } + if (NULL != e) { + free(e); + } + return ret; +} + diff --git a/decoders/session_flags/mesa_sts/src/selfCorrelation.c b/decoders/session_flags/mesa_sts/src/selfCorrelation.c new file mode 100644 index 0000000..d47a67b --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/selfCorrelation.c @@ -0,0 +1,25 @@ +#include <math.h> +#include "include/stat_fncs.h" + +int SelfCorrelation(int d, int n, BitSequence *epsilon) +{ + int i = 0; + int n_d = n - d; + int Ad = 0; + double V = 0.0, p_value = 0.0, sqrt2 = 1.41421356237309504880; + + for (i = 0; i < n_d - 1; ++i) { + Ad += (epsilon[i] ^ epsilon[i + d]); + } + + V = 2 * ((double)Ad - ((double)n_d / 2)) / sqrt(n_d); + + p_value = erfc(fabs(V) / sqrt2); + + if (p_value < ALPHA) { + return 0; + } else { + return 1; + } +} + diff --git a/decoders/session_flags/mesa_sts/src/serial.c b/decoders/session_flags/mesa_sts/src/serial.c new file mode 100644 index 0000000..3d37272 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/serial.c @@ -0,0 +1,65 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "include/externs.h" +#include "include/cephes.h" + +double psi2(int m, int n, BitSequence *epsilon); + +int +Serial(int m, int n, BitSequence *epsilon) +{ + double p_value1, p_value2, psim0, psim1, psim2, del1, del2; + + psim0 = psi2(m, n, epsilon); + psim1 = psi2(m - 1, n, epsilon); + psim2 = psi2(m - 2, n, epsilon); + del1 = psim0 - psim1; + del2 = psim0 - 2.0*psim1 + psim2; + p_value1 = cephes_igamc(pow(2, m-1)/2, del1/2.0); + p_value2 = cephes_igamc(pow(2, m-2)/2, del2/2.0); + + if (p_value1 < ALPHA || p_value2 < ALPHA) { + return 0; + } else { + return 1; + } +} + +double +psi2(int m, int n, BitSequence *epsilon) +{ + int i, j, k, powLen; + double sum, numOfBlocks; + unsigned int *P; + + if ( (m == 0) || (m == -1) ) + return 0.0; + numOfBlocks = n; + powLen = (int)pow(2, m+1)-1; + if ( (P = (unsigned int*)calloc(powLen,sizeof(unsigned int)))== NULL ) { +// fprintf(stats[TEST_SERIAL], "Serial Test: Insufficient memory available.\n"); +// fflush(stats[TEST_SERIAL]); + return 0.0; + } + for ( i=1; i<powLen-1; i++ ) + P[i] = 0; /* INITIALIZE NODES */ + for ( i=0; i<numOfBlocks; i++ ) { /* COMPUTE FREQUENCY */ + k = 1; + for ( j=0; j<m; j++ ) { + if ( epsilon[(i+j)%n] == 0 ) + k *= 2; + else if ( epsilon[(i+j)%n] == 1 ) + k = 2*k+1; + } + P[k-1]++; + } + sum = 0.0; + for ( i=(int)pow(2, m)-1; i<(int)pow(2, m+1)-1; i++ ) + sum += pow(P[i], 2); + sum = (sum * pow(2, m)/(double)n) - (double)n; + free(P); + + return sum; +} diff --git a/decoders/session_flags/mesa_sts/src/universal.c b/decoders/session_flags/mesa_sts/src/universal.c new file mode 100644 index 0000000..393ea1b --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/universal.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include "include/externs.h" +#include "include/cephes.h" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + U N I V E R S A L T E S T + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +Universal(int n, BitSequence *epsilon) +{ + int ret = 0; + int i, j, p, L, Q, K; + double arg, sqrt2, sigma, phi, sum, p_value, c; + long *T, decRep; + const double expected_value[17] = { 0, 0, 0, 0, 0, 0, 5.2177052, 6.1962507, 7.1836656, + 8.1764248, 9.1723243, 10.170032, 11.168765, + 12.168070, 13.167693, 14.167488, 15.167379 }; + const double variance[17] = { 0, 0, 0, 0, 0, 0, 2.954, 3.125, 3.238, 3.311, 3.356, 3.384, + 3.401, 3.410, 3.416, 3.419, 3.421 }; + + /* * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * THE FOLLOWING REDEFINES L, SHOULD THE CONDITION: n >= 1010*2^L*L * + * NOT BE MET, FOR THE BLOCK LENGTH L. * + * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + L = 5; + if ( n >= 387840 ) L = 6; + if ( n >= 904960 ) L = 7; + if ( n >= 2068480 ) L = 8; + if ( n >= 4654080 ) L = 9; + if ( n >= 10342400 ) L = 10; + if ( n >= 22753280 ) L = 11; + if ( n >= 49643520 ) L = 12; + if ( n >= 107560960 ) L = 13; + if ( n >= 231669760 ) L = 14; + if ( n >= 496435200 ) L = 15; + if ( n >= 1059061760 ) L = 16; + + Q = 10*(int)pow(2, L); + K = (int) (floor(n/L) - (double)Q); /* BLOCKS TO TEST */ + + p = (int)pow(2, L); + if ( (L < 6) || (L > 16) || ((double)Q < 10*pow(2, L)) || + ((T = (long *)calloc(p, sizeof(long))) == NULL) ) { + return 0; + } + + /* COMPUTE THE EXPECTED: Formula 16, in Marsaglia's Paper */ + c = 0.7 - 0.8/(double)L + (4 + 32/(double)L)*pow(K, -3/(double)L)/15; + sigma = c * sqrt(variance[L]/(double)K); + sqrt2 = sqrt(2); + sum = 0.0; + for ( i=0; i<p; i++ ) + T[i] = 0; + for ( i=1; i<=Q; i++ ) { /* INITIALIZE TABLE */ + decRep = 0; + for ( j=0; j<L; j++ ) + decRep += epsilon[(i-1)*L+j] * (long)pow(2, L-1-j); + T[decRep] = i; + } + for ( i=Q+1; i<=Q+K; i++ ) { /* PROCESS BLOCKS */ + decRep = 0; + for ( j=0; j<L; j++ ) + decRep += epsilon[(i-1)*L+j] * (long)pow(2, L-1-j); + sum += log(i - T[decRep])/log(2); + T[decRep] = i; + } + phi = (double)(sum/(double)K); + + arg = fabs(phi-expected_value[L])/(sqrt2 * sigma); + p_value = erfc(arg); + if ( isNegative(p_value) || isGreaterThanOne(p_value) ) { + goto end; + } + + if (p_value < ALPHA) { + goto end; + } + + ret = 1; + + end: + free(T); + return ret; +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/src/utilities.c b/decoders/session_flags/mesa_sts/src/utilities.c new file mode 100644 index 0000000..d3c4973 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/utilities.c @@ -0,0 +1,45 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +U T I L I T I E S +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#include "include/utilities.h" + +int +convertToBits(BYTE *x, int xBitLength, int bitsNeeded, int *num_0s, int *num_1s, int *bitsRead, BitSequence* epsilon) +{ + int i, j, count, bit; + BYTE mask; + int zeros, ones; + + count = 0; + zeros = ones = 0; + for ( i=0; i<(xBitLength+7)/8; i++ ) { + mask = 0x80; + for ( j=0; j<8; j++ ) { + if ( *(x+i) & mask ) { + bit = 1; + (*num_1s)++; + ones++; + } + else { + bit = 0; + (*num_0s)++; + zeros++; + } + mask >>= 1; + epsilon[*bitsRead] = bit; + (*bitsRead)++; + if ( *bitsRead == bitsNeeded ) + return 1; + if ( ++count == xBitLength ) + return 0; + } + } + + return 0; +} + diff --git a/decoders/session_flags/mesa_sts/src/version.map b/decoders/session_flags/mesa_sts/src/version.map new file mode 100644 index 0000000..ea17166 --- /dev/null +++ b/decoders/session_flags/mesa_sts/src/version.map @@ -0,0 +1,6 @@ +{ + global: + statistical_test_suite; + GIT_VERSION*; + local: *; +};
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/test/CMakeLists.txt b/decoders/session_flags/mesa_sts/test/CMakeLists.txt new file mode 100644 index 0000000..f4e7678 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required (VERSION 3.5)
+
+add_executable(gtest_mesa gtest_mesa_sts.cpp)
+target_link_libraries(gtest_mesa gtest pcap pthread libmesa_sts)
+
+file(COPY pcap DESTINATION ./)
diff --git a/decoders/session_flags/mesa_sts/test/gtest_mesa_sts.cpp b/decoders/session_flags/mesa_sts/test/gtest_mesa_sts.cpp new file mode 100644 index 0000000..2d9658f --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/gtest_mesa_sts.cpp @@ -0,0 +1,256 @@ +#include <netinet/ip6.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <pcap/pcap.h> + +#include "gtest/gtest.h" + +#include "mesa_sts.h" + +#define MAX_PKT_CNT 1 + +static int read_pcap_and_judge_randomness(const char* pcap_file, struct sts_result* result) +{ + pcap_t *handle; + struct pcap_pkthdr *header; // pcap报文头部结构 + const u_char *packet; // 报文数据指针 + char errbuf[PCAP_ERRBUF_SIZE]; + char content[2048] = {0}; + int content_len = 0; + int payload_len; + char *payload; + int pkt_cnt = 0; + + handle = pcap_open_offline(pcap_file, errbuf); + while (pcap_next_ex(handle, &header, &packet) > 0) { + unsigned short eth_type = ntohs(*(unsigned short *)(packet + 12)); + if (eth_type == ETH_P_IP) { + int l4_proto = *(unsigned char *)(packet + sizeof(struct ethhdr) + 9); + if (l4_proto == IPPROTO_TCP) { + int tcp_header_len = (*(unsigned char *)(packet + sizeof(struct ethhdr) + sizeof(struct iphdr) + 12) & 0xf0) >> 2; + payload_len = header->caplen - sizeof(struct ethhdr) - sizeof(struct iphdr) - tcp_header_len; + payload = (char *)packet + sizeof(struct ethhdr) + sizeof(struct iphdr) + tcp_header_len; + } else if (l4_proto == IPPROTO_UDP) { + payload_len = header->caplen - sizeof(struct ethhdr) - sizeof(struct iphdr) - sizeof(struct udphdr); + payload = (char *)packet + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr); + } else { + continue; + } + + } else if (eth_type == ETH_P_IPV6) { + int l4_proto = *(unsigned char *)(packet + sizeof(struct ethhdr) + 6); + if (l4_proto == IPPROTO_TCP) { + int tcp_header_len = (*(unsigned char *)(packet + sizeof(struct ethhdr) + sizeof(struct ip6_hdr) + 12) & 0xf0) >> 2; + payload_len = header->caplen - sizeof(struct ethhdr) - sizeof(struct ip6_hdr) - tcp_header_len; + payload = (char *)packet + sizeof(struct ethhdr) + sizeof(struct ip6_hdr) + tcp_header_len; + } else if (l4_proto == IPPROTO_UDP) { + payload_len = header->caplen - sizeof(struct ethhdr) - sizeof(struct ip6_hdr) - sizeof(struct udphdr); + payload = (char *)packet + sizeof(struct ethhdr) + sizeof(struct ip6_hdr) + sizeof(struct udphdr); + } else { + continue; + } + } + + if (payload_len < 100) { + continue; + } + + memcpy(content + content_len, payload, payload_len); + content_len += payload_len; + pkt_cnt++; + if (pkt_cnt == MAX_PKT_CNT) { + break; + } + } + + mesa_statistical_test_suite(content, content_len, result, 0xffffffff); + + pcap_close(handle); + + return 0; +} + +TEST(random_looking, telegram_mtproto_ipv4_key1) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/telegram_mtproto_ipv4_key_1.pcap", &result); + + EXPECT_EQ(result.frequency, 1); + EXPECT_EQ(result.block_frequency, 1); + EXPECT_EQ(result.cumulative_sums, 1); + EXPECT_EQ(result.runs, 1); + EXPECT_EQ(result.longest_run, 1); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 1); + EXPECT_EQ(result.runs_distribution, 1); + EXPECT_EQ(result.self_correlation, 1); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(random_looking, telegram_mtproto_ipv4_key2) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/telegram_mtproto_ipv4_key_2_dd.pcap", &result); + + EXPECT_EQ(result.frequency, 1); + EXPECT_EQ(result.block_frequency, 1); + EXPECT_EQ(result.cumulative_sums, 1); + EXPECT_EQ(result.runs, 1); + EXPECT_EQ(result.longest_run, 1); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 1); + EXPECT_EQ(result.runs_distribution, 1); + EXPECT_EQ(result.self_correlation, 1); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(random_looking, telegram_mtproto_ipv4_key3) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/telegram_mtproto_ipv4_key_3_ee.pcap", &result); + + EXPECT_EQ(result.frequency, 1); + EXPECT_EQ(result.block_frequency, 0); + EXPECT_EQ(result.cumulative_sums, 1); + EXPECT_EQ(result.runs, 0); + EXPECT_EQ(result.longest_run, 1); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 0); + EXPECT_EQ(result.runs_distribution, 1); + EXPECT_EQ(result.self_correlation, 1); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(random_looking, telegram_mtproto_ipv6_key1) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/telegram_mtproto_ipv6_key_1.pcap", &result); + + EXPECT_EQ(result.frequency, 1); + EXPECT_EQ(result.block_frequency, 1); + EXPECT_EQ(result.cumulative_sums, 1); + EXPECT_EQ(result.runs, 1); + EXPECT_EQ(result.longest_run, 1); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 1); + EXPECT_EQ(result.runs_distribution, 1); + EXPECT_EQ(result.self_correlation, 1); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(random_looking, telegram_mtproto_ipv6_key2) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/telegram_mtproto_ipv6_key_2_dd.pcap", &result); + + EXPECT_EQ(result.frequency, 1); + EXPECT_EQ(result.block_frequency, 1); + EXPECT_EQ(result.cumulative_sums, 1); + EXPECT_EQ(result.runs, 1); + EXPECT_EQ(result.longest_run, 1); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 1); + EXPECT_EQ(result.runs_distribution, 1); + EXPECT_EQ(result.self_correlation, 1); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(random_looking, telegram_mtproto_ipv6_key3) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/telegram_mtproto_ipv6_key_3_ee.pcap", &result); + + EXPECT_EQ(result.frequency, 1); + EXPECT_EQ(result.block_frequency, 0); + EXPECT_EQ(result.cumulative_sums, 1); + EXPECT_EQ(result.runs, 1); + EXPECT_EQ(result.longest_run, 1); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 0); + EXPECT_EQ(result.runs_distribution, 1); + EXPECT_EQ(result.self_correlation, 1); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(non_random_looking, wechat_voice_call) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/202202161604_win_wifi_30M_pure_wechat_wechat3.5.0.46_voice-call_120s_2_multinat.pcap", &result); + + EXPECT_EQ(result.frequency, 0); + EXPECT_EQ(result.block_frequency, 1); + EXPECT_EQ(result.cumulative_sums, 0); + EXPECT_EQ(result.runs, 0); + EXPECT_EQ(result.longest_run, 0); + EXPECT_EQ(result.rank, 0); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 1); + EXPECT_EQ(result.runs_distribution, 0); + EXPECT_EQ(result.self_correlation, 0); + EXPECT_EQ(result.binary_derivative, 1); +} + +TEST(non_random_looking, http) +{ + struct sts_result result; + read_pcap_and_judge_randomness("pcap/xingongsuo_kouling_http_C2S.pcap", &result); + + EXPECT_EQ(result.frequency, 0); + EXPECT_EQ(result.block_frequency, 0); + EXPECT_EQ(result.cumulative_sums, 0); + EXPECT_EQ(result.runs, 1); + EXPECT_EQ(result.longest_run, 0); + EXPECT_EQ(result.rank, 1); + EXPECT_EQ(result.non_overlapping_template_matching, 0); + EXPECT_EQ(result.overlapping_template_matching, 1); + EXPECT_EQ(result.universal, 0); + EXPECT_EQ(result.random_excursions, 1); + EXPECT_EQ(result.random_excursions_variant, 1); + EXPECT_EQ(result.poker_detect, 0); + EXPECT_EQ(result.runs_distribution, 0); + EXPECT_EQ(result.self_correlation, 0); + EXPECT_EQ(result.binary_derivative, 1); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + //testing::GTEST_FLAG(filter) = "random_looking.telegram_mtproto_ipv6_key1"; + return RUN_ALL_TESTS(); +}
\ No newline at end of file diff --git a/decoders/session_flags/mesa_sts/test/pcap/202202161604_win_wifi_30M_pure_wechat_wechat3.5.0.46_voice-call_120s_2_multinat.pcap b/decoders/session_flags/mesa_sts/test/pcap/202202161604_win_wifi_30M_pure_wechat_wechat3.5.0.46_voice-call_120s_2_multinat.pcap Binary files differnew file mode 100644 index 0000000..63787b7 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/202202161604_win_wifi_30M_pure_wechat_wechat3.5.0.46_voice-call_120s_2_multinat.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_1.pcap b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_1.pcap Binary files differnew file mode 100644 index 0000000..7b966dd --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_1.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_2_dd.pcap b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_2_dd.pcap Binary files differnew file mode 100644 index 0000000..59eb480 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_2_dd.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_3_ee.pcap b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_3_ee.pcap Binary files differnew file mode 100644 index 0000000..8c70a1b --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv4_key_3_ee.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_1.pcap b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_1.pcap Binary files differnew file mode 100644 index 0000000..e0b3144 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_1.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_2_dd.pcap b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_2_dd.pcap Binary files differnew file mode 100644 index 0000000..0659281 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_2_dd.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_3_ee.pcap b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_3_ee.pcap Binary files differnew file mode 100644 index 0000000..03a3678 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/telegram_mtproto_ipv6_key_3_ee.pcap diff --git a/decoders/session_flags/mesa_sts/test/pcap/xingongsuo_kouling_http_C2S.pcap b/decoders/session_flags/mesa_sts/test/pcap/xingongsuo_kouling_http_C2S.pcap Binary files differnew file mode 100644 index 0000000..cd05da7 --- /dev/null +++ b/decoders/session_flags/mesa_sts/test/pcap/xingongsuo_kouling_http_C2S.pcap diff --git a/decoders/session_flags/onlinemean.c b/decoders/session_flags/onlinemean.c new file mode 100644 index 0000000..aeb7427 --- /dev/null +++ b/decoders/session_flags/onlinemean.c @@ -0,0 +1,37 @@ +#include <math.h> +#include "onlinemean.h" + +void OnlineMean_Init(OnlineMean_t *oMean) { + OnlineMean_Reset(oMean); +} + +void OnlineMean_Update(OnlineMean_t *oMean, float newValue) { + oMean->count++; + if (oMean->count > 1) { + float delta = newValue - oMean->mean; + oMean->mean += delta / oMean->count; + oMean->varsum += delta * (newValue - oMean->mean); + } else { + oMean->mean = newValue; + } +} + +float OnlineMean_GetMean(OnlineMean_t *oMean) { + return oMean->mean; +} + +float OnlineMean_GetStd(OnlineMean_t *oMean) { + if (oMean->count == 0) + return 0; +#if UNBIASED_ESTIMATOR + return sqrt(oMean->varsum / (oMean->count - 1)); +#else + return sqrt(oMean->varsum / oMean->count); +#endif /* UNBIASED_ESTIMATOR */ +} + +void OnlineMean_Reset(OnlineMean_t *oMean) { + oMean->count = 0; + oMean->mean = 0.f; + oMean->varsum = 0.f; +} diff --git a/decoders/session_flags/onlinemean.h b/decoders/session_flags/onlinemean.h new file mode 100644 index 0000000..6cb5c95 --- /dev/null +++ b/decoders/session_flags/onlinemean.h @@ -0,0 +1,30 @@ +#ifndef ONLINEMEAN_H_ +#define ONLINEMEAN_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Set to 1 to return unbiased (sample) variance + * rather than a population variance */ +#define UNBIASED_ESTIMATOR 0 + +#include <stdint.h> + +typedef struct OnlineMean { + float mean; + float varsum; // variance sum + uint32_t count; +} OnlineMean_t; + +void OnlineMean_Init(OnlineMean_t *oMean); +void OnlineMean_Update(OnlineMean_t *oMean, float newValue); +float OnlineMean_GetMean(OnlineMean_t *oMean); +float OnlineMean_GetStd(OnlineMean_t *oMean); +void OnlineMean_Reset(OnlineMean_t *oMean); + +#ifdef __cplusplus +} +#endif + +#endif /* ONLINEMEAN_H_ */ diff --git a/decoders/session_flags/session_flags.cpp b/decoders/session_flags/session_flags.cpp new file mode 100644 index 0000000..6f7443f --- /dev/null +++ b/decoders/session_flags/session_flags.cpp @@ -0,0 +1,824 @@ +#include <stdio.h> +#include <unistd.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <math.h> +#include <cJSON.h> +#include <pthread.h> + +#include "onlinemean.h" +#include "session_flags_internal.h" +#include "fet.h" +#include "stellar/stellar.h" +#include "mesa_sts.h" +#include "stellar/session.h" +#include "stellar/log.h" + +#define SESSION_BUKLY_THRESHORD 0.95 +#define SESSION_DOWNLOAD_THRESHORD 0.95 +#define SESSION_CBR_STREAMING_THRESHORD 0.15 +#define SESSION_STREAMING_THRESHORD 0.86 +#define SESSION_PSEUDO_UNIDIRECTIONA_THRESHORD 0.95 +#define SESSION_INTERACTIVE_THRESHORD 0.7 + +#define SESSION_BIDIRECTIONAL_THRESHORD_MIN 0.7 +#define SESSION_BIDIRECTIONAL_THRESHORD_MAX 1.43 +#define SESSION_EWMA_FACTOR 0.9 + + +#define SESSION_RANDOM_LOOKING_PAYLOAD_LEN_MIN 100 + +#define SESSION_ITER_INTERVAL_MS 1000 +#define SESSION_EWMA_ITER_CNT_MIN 5 + +#define LARGE_PKT_SIZE_MIN 600 +#define LARGE_PKT_SIZE_MAX 1400 + +#define SESSION_FLAGS_IDENTIFY_STR_LEN 256 + +extern struct session_flags_init_conf g_sf_conf; + +extern uint32_t sts_random_switch; + +thread_local OnlineMean_t g_large_pkt_omean = { + .mean = 0, + .varsum = 0, + .count = 0 +};//record the mean and std of packet size, to calculate large packet size +thread_local uint64_t g_large_pkt_size_update_ms = 0; +thread_local uint32_t g_large_pkt_size = 0; +#define LARGE_PKT_SIZE_UPDATE_COUNT_MIN 10000 +#define LARGE_PKT_SIZE_UPDATE_INTERVAL_MS 10000 + +static void session_flags_calculate_local(struct session_flags_stat *stat, enum session_direction session_dir) +{ + if (session_dir == SESSION_DIRECTION_INBOUND) + { + stat->result.flags |= SESSION_FLAGS_LOCAL_SERVER; + stat->result.identify[session_flags_local_server_mask] = 1; + } + else + { + stat->result.flags |= SESSION_FLAGS_LOCAL_CLIENT; + stat->result.identify[session_flags_local_client_mask] = 1; + } + + return; +} + +void session_flags_stat_init(struct session_flags_stat *stat, enum session_direction session_dir) +{ + session_flags_calculate_local(stat, session_dir); + + OnlineMean_Init(&stat->iter.c2s.omean); + OnlineMean_Init(&stat->iter.s2c.omean); + + stat->main_dir = MAIN_DIR_UNKONWN; + + return; +}; + +static void session_flags_EWMA_iter(float *ori_value, float iter_value) +{ + float temp = *ori_value; + + if (temp == 0) + { + temp = iter_value; + } + else + { + temp = SESSION_EWMA_FACTOR * temp + (1 - SESSION_EWMA_FACTOR) * iter_value; + } + + *ori_value = temp; +} + +static void session_flags_calculate_pseudo_unidirection(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL) + return ; + + float c2s_ratio, s2c_ratio; + float pseudo_unidirectional; + uint64_t delta_payload_pkts = stat->c2s.delta_payload_pkts + stat->s2c.delta_payload_pkts; + + if (delta_payload_pkts == 0) + { + return; + } + + c2s_ratio = stat->c2s.delta_payload_pkts * 1.f / delta_payload_pkts; + s2c_ratio = stat->s2c.delta_payload_pkts * 1.f / delta_payload_pkts; + + session_flags_EWMA_iter(&stat->iter.c2s.pseudo_unidirectional, c2s_ratio); + session_flags_EWMA_iter(&stat->iter.s2c.pseudo_unidirectional, s2c_ratio); + + if (stat->iter.iter_cnt < SESSION_EWMA_ITER_CNT_MIN || stat->main_dir == MAIN_DIR_UNKONWN) + { + return; + } + + if (stat->main_dir == FLOW_TYPE_C2S) + { + pseudo_unidirectional = stat->iter.c2s.pseudo_unidirectional; + } + else + { + pseudo_unidirectional = stat->iter.s2c.pseudo_unidirectional; + } + + if (pseudo_unidirectional > SESSION_PSEUDO_UNIDIRECTIONA_THRESHORD) + { + stat->result.flags |= SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL; + stat->result.identify[session_flags_pseudo_unidirectional_mask] = all_pkts; + } +} + +static void session_flags_calculate_unidirection(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_UNIDIRECTIONAL || stat->s2c.pkts == 0 || stat->c2s.pkts == 0) + return ; + + if (stat->c2s.payload_pkts == 0 || stat->s2c.payload_pkts == 0) + { + stat->result.flags |= SESSION_FLAGS_UNIDIRECTIONAL; + stat->result.identify[session_flags_unidirectional_mask] = all_pkts; + } +} + +static void session_flags_calculate_streaming(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_STREAMING) + return; + + float c2s_ratio, s2c_ratio; + float streaming; + uint64_t delta_bytes = stat->c2s.delta_bytes + stat->s2c.delta_bytes; + + if (delta_bytes == 0) + { + return; + } + + c2s_ratio = stat->c2s.delta_bytes * 1.f / delta_bytes; + s2c_ratio = stat->s2c.delta_bytes * 1.f / delta_bytes; + + session_flags_EWMA_iter(&stat->iter.c2s.streaming, c2s_ratio); + session_flags_EWMA_iter(&stat->iter.s2c.streaming, s2c_ratio); + + if (stat->iter.iter_cnt < SESSION_EWMA_ITER_CNT_MIN || stat->main_dir == MAIN_DIR_UNKONWN) + { + return; + } + + if (stat->main_dir == FLOW_TYPE_C2S) + { + streaming = stat->iter.c2s.streaming; + } + else + { + streaming = stat->iter.s2c.streaming; + } + + if (streaming > SESSION_STREAMING_THRESHORD) + { + stat->result.flags |= SESSION_FLAGS_STREAMING; + stat->result.identify[session_flags_streaming_mask] = all_pkts; + } +} + +static void session_flags_calculate_download(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_DOWNLOAD) + return ; + + float c2s_ratio, s2c_ratio; + float download; + uint64_t delta_payload_pkts = stat->c2s.delta_payload_pkts + stat->s2c.delta_payload_pkts; + + if (delta_payload_pkts == 0) + { + return; + } + + c2s_ratio = stat->c2s.delta_large_pkts * 1.f / delta_payload_pkts; + s2c_ratio = stat->s2c.delta_large_pkts * 1.f / delta_payload_pkts; + + session_flags_EWMA_iter(&stat->iter.c2s.download, c2s_ratio); + session_flags_EWMA_iter(&stat->iter.s2c.download, s2c_ratio); + + if (stat->iter.iter_cnt < SESSION_EWMA_ITER_CNT_MIN || stat->main_dir == MAIN_DIR_UNKONWN) + { + return; + } + + if (stat->main_dir == FLOW_TYPE_C2S) + { + download = stat->iter.c2s.download; + } + else + { + download = stat->iter.s2c.download; + } + + if (download > SESSION_DOWNLOAD_THRESHORD) + { + stat->result.flags |= SESSION_FLAGS_DOWNLOAD; + stat->result.identify[session_flags_download_mask] = all_pkts; + } +} + +static void session_flags_calculate_bulky(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_BULKY) + return ; + + float bulky; + + if (stat->c2s.delta_pkts != 0) + { + float c2s_ratio; + c2s_ratio = stat->c2s.delta_large_pkts * 1.f / stat->c2s.delta_pkts; + session_flags_EWMA_iter(&stat->iter.c2s.bulky, c2s_ratio); + } + + if (stat->s2c.delta_pkts != 0) + { + float s2c_ratio; + s2c_ratio = stat->s2c.delta_large_pkts * 1.f / stat->s2c.delta_pkts; + session_flags_EWMA_iter(&stat->iter.s2c.bulky, s2c_ratio); + } + + if (stat->iter.iter_cnt < SESSION_EWMA_ITER_CNT_MIN || stat->main_dir == MAIN_DIR_UNKONWN) + { + return; + } + + if (stat->main_dir == FLOW_TYPE_C2S) + { + bulky = stat->iter.c2s.bulky; + } + else + { + bulky = stat->iter.s2c.bulky; + } + + if (bulky > SESSION_BUKLY_THRESHORD) + { + stat->result.flags |= SESSION_FLAGS_BULKY; + stat->result.identify[session_flags_bulky_mask] = all_pkts; + } +} + +static void flow_stat_update(struct session *session, struct flow_stat *flow, uint64_t bytes) +{ + flow->bytes += bytes; + flow->pkts++; + + flow->delta_pkts++; + flow->delta_bytes += bytes; + + const struct packet *pkt = session_get0_current_packet(session); + size_t payload_len = packet_get_payload_len(pkt); + + if (payload_len > 0) + { + flow->payload_pkts++; + flow->delta_payload_pkts++; + } + + if (bytes > g_large_pkt_size) + { + flow->large_pkts++; + flow->delta_large_pkts++; + } + + return; +} + +static void session_flags_calculate_main_dir(struct session_flags_stat *stat) +{ + if (stat->main_dir != MAIN_DIR_UNKONWN) + { + return; + } + + if (stat->c2s.bytes > stat->s2c.bytes) + { + stat->main_dir = FLOW_TYPE_C2S; + } + else + { + stat->main_dir = FLOW_TYPE_S2C; + } +} + +float session_flags_calculate_CV(OnlineMean_t * omean) +{ + float CV = -1.f; + float mean = OnlineMean_GetMean(omean); + if (mean!= 0) + { + CV = OnlineMean_GetStd(omean) / mean; + } + // printf("CV:%lf\n", CV); + return CV; +} + +static void session_flags_calculate_CBR(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_CBR) + return; + + float CBR; + + OnlineMean_Update(&stat->iter.c2s.omean, stat->c2s.rate); + OnlineMean_Update(&stat->iter.s2c.omean, stat->s2c.rate); + + stat->iter.c2s.CBR = session_flags_calculate_CV(&stat->iter.c2s.omean); + stat->iter.s2c.CBR = session_flags_calculate_CV(&stat->iter.s2c.omean); + + if (stat->main_dir == MAIN_DIR_UNKONWN) + { + return; + } + + if (stat->main_dir == FLOW_TYPE_C2S) + { + CBR = stat->iter.c2s.CBR; + } + else + { + CBR = stat->iter.s2c.CBR; + } + + if (CBR < SESSION_CBR_STREAMING_THRESHORD && CBR > 0.0) + { + stat->result.flags |= SESSION_FLAGS_CBR; + stat->result.identify[session_flags_cbr_mask] = all_pkts; + } +} + +static void session_flags_calculate_interactive(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_INTERACTIVE || stat->c2s.pkts == 0 || stat->s2c.pkts == 0) + return; + + if (stat->stream_live_time_ms > g_sf_conf.interactive_starttime_ms && stat->interactive_pulse_num > g_sf_conf.interactive_pulse_num) + { + stat->result.flags |= SESSION_FLAGS_INTERACTIVE; + stat->result.identify[session_flags_interactive_mask] = all_pkts; + } +} + +static void session_flags_calculate_interactive_pulse(struct session_flags_stat *stat, uint64_t cur_ms, uint64_t all_pkts) +{ + uint64_t delta_ms = 0; + if (cur_ms > stat->last_pkt_ts_ms) + { + delta_ms = cur_ms - stat->last_pkt_ts_ms; + } + + if (delta_ms > g_sf_conf.interactive_latency_ms) + { + stat->interactive_pulse_num++; + session_flags_calculate_interactive(stat, all_pkts); + } +} + +static void session_flags_calculate_bound(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat == NULL || stat->c2s.pkts == 0 || stat->s2c.pkts == 0) + { + return; + } + + if (!(stat->result.flags & SESSION_FLAGS_INBOUND) && !(stat->result.flags & SESSION_FLAGS_OUTBOUND)) + { + if (stat->result.flags & SESSION_FLAGS_LOCAL_CLIENT) + { + if (stat->main_dir == FLOW_TYPE_C2S) + { + stat->result.flags |= SESSION_FLAGS_OUTBOUND; + stat->result.identify[session_flags_outbound_mask] = all_pkts; + } + else + { + stat->result.flags |= SESSION_FLAGS_INBOUND; + stat->result.identify[session_flags_inbound_mask] = all_pkts; + } + } + else + { + if (stat->main_dir == FLOW_TYPE_C2S) + { + stat->result.flags |= SESSION_FLAGS_INBOUND; + stat->result.identify[session_flags_inbound_mask] = all_pkts; + } + else + { + stat->result.flags |= SESSION_FLAGS_OUTBOUND; + stat->result.identify[session_flags_outbound_mask] = all_pkts; + } + } + } +} + +static void session_flags_calculate_dir(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->c2s.pkts != 0 && !(stat->result.flags & SESSION_FLAGS_C2S)) + { + stat->result.flags |= SESSION_FLAGS_C2S; + stat->result.identify[session_flags_c2s_mask] = all_pkts; + } + if (stat->s2c.pkts != 0 && !(stat->result.flags & SESSION_FLAGS_S2C)) + { + stat->result.flags |= SESSION_FLAGS_S2C; + stat->result.identify[session_flags_s2c_mask] = all_pkts; + } +} + +static void session_flags_calculate_bidirectional(struct session_flags_stat *stat, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_BIDIRECTIONAL) + { + return; + } + + float rate_ratio = stat->c2s.rate / stat->s2c.rate; + if (stat->iter.bidirectional == 0) + { + stat->iter.bidirectional = rate_ratio; + } + else + {//EWMA + stat->iter.bidirectional = SESSION_EWMA_FACTOR * stat->iter.bidirectional + (1 - SESSION_EWMA_FACTOR) * rate_ratio; + } + + if (stat->iter.iter_cnt >= SESSION_EWMA_ITER_CNT_MIN) + { + if (stat->iter.bidirectional > SESSION_BIDIRECTIONAL_THRESHORD_MIN && stat->iter.bidirectional < SESSION_BIDIRECTIONAL_THRESHORD_MAX) + { + stat->result.flags |= SESSION_FLAGS_BIDIRECTIONAL; + stat->result.identify[session_flags_bidirectional_mask] = all_pkts; + } + } + + return; +} + +static void session_flags_calculate_randomness_by_fet(struct session_flags_stat *stat, size_t payload_len, const char *payload, uint64_t all_pkts) +{ + if (stat->random_looking_stat.has_judged_fet) + { + return; + } + + stat->random_looking_stat.has_judged_fet = 1; + + if (g_sf_conf.fet_enabled) + { + struct fet_detail detail; + int is_fet = is_data_fet((unsigned char *)payload, payload_len, &detail); + + stat->result.is_tls = detail.is_tls; + + if (is_fet) + {//if payload is fet data, then it is definitely random looking + stat->result.flags |= SESSION_FLAGS_RANDOM_LOOKING; + stat->result.identify[session_flags_random_looking_mask] = all_pkts; + } + } + + return; +} + +static void session_flags_calculate_randomness_by_sts(struct session_flags_plugin_info *sf_plugin_info, struct session *session, struct session_flags_stat *stat, size_t payload_len, const char *payload, uint64_t all_pkts) +{ + if (stat->random_looking_stat.has_judged_sts || sts_random_switch == 0) + { + return; + } + + if (payload_len < SESSION_RANDOM_LOOKING_PAYLOAD_LEN_MIN) + { + return; + } + + stat->random_looking_stat.has_judged_sts = 1; + + struct sts_result result; + uint32_t random_flags_count = 0; + memset(&result, 0, sizeof(result)); + + mesa_statistical_test_suite((void*)payload, payload_len, &result, sts_random_switch); + + if (result.frequency) + { + stat->result.random_looking_flags |= SESSION_FLAGS_FREQUENCY; + random_flags_count++; + } + if (result.block_frequency) + { + stat->result.random_looking_flags |= SESSION_FLAGS_BLOCK_FREQUENCY; + random_flags_count++; + } + if (result.cumulative_sums) + { + stat->result.random_looking_flags |= SESSION_FLAGS_CUMULATIVE_SUMS; + random_flags_count++; + } + if (result.runs) + { + stat->result.random_looking_flags |= SESSION_FLAGS_RUNS; + random_flags_count++; + } + if (result.longest_run) + { + stat->result.random_looking_flags |= SESSION_FLAGS_LONGEST_RUN; + random_flags_count++; + } + if (result.rank) + { + stat->result.random_looking_flags |= SESSION_FLAGS_RANK; + random_flags_count++; + } + if (result.non_overlapping_template_matching) + { + stat->result.random_looking_flags |= SESSION_FLAGS_NON_OVERLAPPING_TEMPLATE_MATCHING; + random_flags_count++; + } + if (result.overlapping_template_matching) + { + stat->result.random_looking_flags |= SESSION_FLAGS_OVERLAPPING_TEMPLATE_MATCHING; + random_flags_count++; + } + if (result.universal) + { + stat->result.random_looking_flags |= SESSION_FLAGS_UNIVERSAL; + random_flags_count++; + } + if (result.random_excursions) + { + stat->result.random_looking_flags |= SESSION_FLAGS_RANDOM_EXCURSIONS; + random_flags_count++; + } + if (result.random_excursions_variant) + { + stat->result.random_looking_flags |= SESSION_FLAGS_RANDOM_EXCURSIONS_VARIANT; + random_flags_count++; + } + if (result.poker_detect) + { + stat->result.random_looking_flags |= SESSION_FLAGS_POKER_DETECT; + random_flags_count++; + } + if (result.runs_distribution) + { + stat->result.random_looking_flags |= SESSION_FLAGS_RUNS_DISTRIBUTION; + random_flags_count++; + } + if (result.self_correlation) + { + stat->result.random_looking_flags |= SESSION_FLAGS_SELF_CORRELATION; + random_flags_count++; + } + if (result.binary_derivative) + { + stat->result.random_looking_flags |= SESSION_FLAGS_BINARY_DERIVATIVE; + random_flags_count++; + } + + if (random_flags_count > (g_sf_conf.random_judge_flags_cnt / 2)) + { + stat->result.flags |= SESSION_FLAGS_RANDOM_LOOKING; + stat->result.identify[session_flags_random_looking_mask] = all_pkts; + } + + STELLAR_LOG_DEBUG(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "[%s] calculate random looking flags, flags:0x%x, pkts_num:%d", session_get0_readable_addr(session), stat->result.random_looking_flags, all_pkts); +} + +static void session_flags_calculate_random_looking(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_stat *stat, struct session *session, int topic_id, uint64_t all_pkts) +{ + if (stat->result.flags & SESSION_FLAGS_RANDOM_LOOKING) + { + return; + } + + int udp_topic_id = sf_plugin_info->udp_topic_id; + + const struct packet *pkt = session_get0_current_packet(session); + size_t payload_len = packet_get_payload_len(pkt); + const char *payload = packet_get_payload(pkt); + + if ((topic_id == udp_topic_id) && g_sf_conf.random_looking_udp_ignore_pkts < 0)// disable random looking udp when random_looking_udp_ignore_pkts<0 + { + return; + } + + if (payload_len == 0 || payload == NULL) + { + return; + } + + stat->random_looking_stat.payload_pkt_num++; + if ((topic_id == udp_topic_id) && stat->random_looking_stat.payload_pkt_num <= g_sf_conf.random_looking_udp_ignore_pkts) + { + return; + } + + session_flags_calculate_randomness_by_fet(stat, payload_len, payload, all_pkts); + if (stat->result.flags & SESSION_FLAGS_RANDOM_LOOKING) + { + return; + } + + session_flags_calculate_randomness_by_sts(sf_plugin_info, session, stat, payload_len, payload, all_pkts); + + return; +} + +static void session_flags_reset_delta(struct session_flags_stat *stat) +{ + stat->c2s.delta_bytes = 0; + stat->c2s.delta_pkts = 0; + stat->c2s.delta_large_pkts = 0; + stat->c2s.delta_payload_pkts = 0; + + stat->s2c.delta_bytes = 0; + stat->s2c.delta_pkts = 0; + stat->s2c.delta_large_pkts = 0; + stat->s2c.delta_payload_pkts = 0; + + return; +} + +static void session_flags_calculate_rate(struct session_flags_stat *stat, uint64_t delta_ms) +{ + stat->c2s.rate = stat->c2s.delta_bytes * 1.f / delta_ms; + stat->s2c.rate = stat->s2c.delta_bytes * 1.f / delta_ms; + + return; +} + +static void session_flags_update_large_pkt_size(struct session_flags_plugin_info *sf_plugin_info, uint32_t pkt_len, uint64_t ms) +{ + if (pkt_len > 1500) + { + return; + } + + OnlineMean_Update(&g_large_pkt_omean, pkt_len); + + if (g_large_pkt_size_update_ms == 0) + { + g_large_pkt_size_update_ms = ms; + g_large_pkt_size = g_sf_conf.large_ptks_init_size; + return; + } + + if (ms - g_large_pkt_size_update_ms >= LARGE_PKT_SIZE_UPDATE_INTERVAL_MS && g_large_pkt_omean.count >= LARGE_PKT_SIZE_UPDATE_COUNT_MIN) + { + g_large_pkt_size_update_ms = ms; + g_large_pkt_size = (uint32_t)(0.84f * OnlineMean_GetStd(&g_large_pkt_omean) + OnlineMean_GetMean(&g_large_pkt_omean));//计算公式 0.84 = (g_large_pkt_size - mean) / std, 0.84为正态分布表中80%的概率对应的z值 + + if (g_large_pkt_size < LARGE_PKT_SIZE_MIN) + { + g_large_pkt_size = LARGE_PKT_SIZE_MIN; + } + else if (g_large_pkt_size > LARGE_PKT_SIZE_MAX) + { + g_large_pkt_size = LARGE_PKT_SIZE_MAX; + } + + STELLAR_LOG_DEBUG(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "session_flags thread %ld update large_pkt_size %d", pthread_self(), g_large_pkt_size); + } + + return; +} + +struct session_flags_result *session_flags(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_ctx *ctx, struct session *session, int topic_id, uint32_t bytes, enum flow_type flow_type, uint64_t ms) +{ + struct session_flags_stat *stat = &ctx->stat; + + if (stat == NULL || bytes == 0) + { + return NULL; + } + + session_flags_update_large_pkt_size(sf_plugin_info, bytes, ms); + + uint64_t delta_ms = 0; + + if(stat->session_start_time_ms == 0) + { + stat->session_start_time_ms = ms; + } + stat->stream_live_time_ms = ms - stat->session_start_time_ms; + + if (stat->last_iter_ts_ms == 0) + { + stat->last_iter_ts_ms = ms; + } + + if (flow_type == FLOW_TYPE_C2S) + { + flow_stat_update(session, &stat->c2s, bytes); + } + else + { + flow_stat_update(session, &stat->s2c, bytes); + } + + uint64_t all_pkts = stat->c2s.pkts + stat->s2c.pkts; + session_flags_calculate_dir(stat, all_pkts); + session_flags_calculate_random_looking(sf_plugin_info, stat, session, topic_id, all_pkts); + + const struct packet *pkt = session_get0_current_packet(session); + size_t payload_len = packet_get_payload_len(pkt); + if (g_sf_conf.tunneling_enabled && payload_len > 0 && (topic_id == sf_plugin_info->tcp_topic_id))// detect tunneling on tcp only + { + tunneling_scan_sequence(sf_plugin_info, session, ctx, payload_len, flow_type, all_pkts); + } + + if (stat->stream_live_time_ms >= START_JUDGE_TIME_MS) + { + if (all_pkts > g_sf_conf.main_dir_front_n_pkts) + { + session_flags_calculate_main_dir(stat); + } + } + + if (stat->c2s.pkts == 0 || stat->s2c.pkts == 0) + { + goto END; + } + + if (stat->main_dir != MAIN_DIR_UNKONWN) + { + session_flags_calculate_bound(stat, all_pkts); + session_flags_calculate_unidirection(stat, all_pkts); + } + + delta_ms = ms - stat->last_iter_ts_ms; + if (delta_ms >= SESSION_ITER_INTERVAL_MS) + { + session_flags_calculate_rate(stat, delta_ms); + + session_flags_calculate_bidirectional(stat, all_pkts); + session_flags_calculate_CBR(stat, all_pkts); + session_flags_calculate_download(stat, all_pkts); + session_flags_calculate_bulky(stat, all_pkts); + session_flags_calculate_pseudo_unidirection(stat, all_pkts); + session_flags_calculate_streaming(stat, all_pkts); + stat->iter.iter_cnt++; + stat->last_iter_ts_ms = ms; + + session_flags_reset_delta(stat); + } + + session_flags_calculate_interactive_pulse(stat, ms, all_pkts); + +END: + stat->last_pkt_ts_ms = ms; + return &stat->result; +} + +struct session_flags_result *session_flags_get_flags(struct session_flags_stat *stat) +{ + if (stat == NULL) + return NULL; + + return &stat->result; +} + +struct session_flags_message *session_flags_generate_firewall_message(uint64_t flags, const uint32_t identify[session_flags_all_mask]) +{ + int flag_num = 0; + uint32_t temp_identify[session_flags_all_mask] = {0}; + struct session_flags_message *flags_msg = (struct session_flags_message *)calloc(1, sizeof(struct session_flags_message)); + + flags_msg->magic= MESSAGE_MAGIC; + flags_msg->flags = flags; + + for (int i = 0; i < session_flags_all_mask; i++) + { + if (flags & (SESSION_FLAGS_START << i)) + { + temp_identify[flag_num] = identify[i]; + flag_num++; + } + } + + flags_msg->packet_sequence_array = (uint32_t *)calloc(flag_num, sizeof(uint32_t)); + for (int i = 0; i < flag_num; i++) + { + flags_msg->packet_sequence_array[i] = temp_identify[i]; + } + flags_msg->array_num = flag_num; + + return flags_msg; +} diff --git a/decoders/session_flags/session_flags_internal.h b/decoders/session_flags/session_flags_internal.h new file mode 100644 index 0000000..eea0b20 --- /dev/null +++ b/decoders/session_flags/session_flags_internal.h @@ -0,0 +1,153 @@ +#pragma once +#include <stdint.h> +#include "onlinemean.h" +#include "tunneling.h" + +#include "hs/hs_runtime.h" +#include "stellar/session.h" +#include "stellar/session_flags.h" +#include "toml/toml.h" + +#define SESSION_FLAGS_LOG_MODULE "SESSION_FLAGS" + +enum random_looking_flags +{ + session_flags_frequency_mask = 0, + session_flags_block_frequency_mask, + session_flags_cumulative_sums_mask, + session_flags_runs_mask, + session_flags_longest_run_mask, + session_flags_rank_mask, + session_flags_non_overlapping_template_matching_mask, + session_flags_overlapping_template_matching_mask, + session_flags_universal_mask, + session_flags_random_excursions_mask, + session_flags_random_excursions_variant_mask, + session_flags_poker_detect_mask, + session_flags_runs_distribution_mask, + session_flags_self_correlation_mask, + session_flags_binary_derivative_mask, +}; +#define SESSION_FLAGS_FREQUENCY (0x0000000000000001) +#define SESSION_FLAGS_BLOCK_FREQUENCY (SESSION_FLAGS_FREQUENCY << session_flags_block_frequency_mask) +#define SESSION_FLAGS_CUMULATIVE_SUMS (SESSION_FLAGS_FREQUENCY << session_flags_cumulative_sums_mask) +#define SESSION_FLAGS_RUNS (SESSION_FLAGS_FREQUENCY << session_flags_runs_mask) +#define SESSION_FLAGS_LONGEST_RUN (SESSION_FLAGS_FREQUENCY << session_flags_longest_run_mask) +#define SESSION_FLAGS_RANK (SESSION_FLAGS_FREQUENCY << session_flags_rank_mask) +#define SESSION_FLAGS_NON_OVERLAPPING_TEMPLATE_MATCHING (SESSION_FLAGS_FREQUENCY << session_flags_non_overlapping_template_matching_mask) +#define SESSION_FLAGS_OVERLAPPING_TEMPLATE_MATCHING (SESSION_FLAGS_FREQUENCY << session_flags_overlapping_template_matching_mask) +#define SESSION_FLAGS_UNIVERSAL (SESSION_FLAGS_FREQUENCY << session_flags_universal_mask) +#define SESSION_FLAGS_RANDOM_EXCURSIONS (SESSION_FLAGS_FREQUENCY << session_flags_random_excursions_mask) +#define SESSION_FLAGS_RANDOM_EXCURSIONS_VARIANT (SESSION_FLAGS_FREQUENCY << session_flags_random_excursions_variant_mask) +#define SESSION_FLAGS_POKER_DETECT (SESSION_FLAGS_FREQUENCY << session_flags_poker_detect_mask) +#define SESSION_FLAGS_RUNS_DISTRIBUTION (SESSION_FLAGS_FREQUENCY << session_flags_runs_distribution_mask) +#define SESSION_FLAGS_SELF_CORRELATION (SESSION_FLAGS_FREQUENCY << session_flags_self_correlation_mask) +#define SESSION_FLAGS_BINARY_DERIVATIVE (SESSION_FLAGS_FREQUENCY << session_flags_binary_derivative_mask) + +#define MAIN_DIR_UNKONWN -1 + +#define START_JUDGE_TIME_MS 5000 + +struct session_flags_result { + uint64_t flags; + uint64_t random_looking_flags; + uint32_t identify[session_flags_all_mask]; + bool is_tls; +}; + +struct session_flags_init_conf{ + uint32_t interactive_starttime_ms; + uint32_t interactive_pulse_num; + uint32_t main_dir_front_n_pkts; + uint64_t interactive_latency_ms; + uint32_t large_ptks_init_size; + uint32_t random_judge_flags_cnt; + uint32_t session_max_process_time_ms; + uint32_t fet_enabled; + uint32_t tunneling_enabled; + int32_t random_looking_udp_ignore_pkts; + uint32_t tunneling_tls_ignore_pkts; + uint32_t tunneling_max_scan_pkts; + char tunneling_pcre_list[2048]; + char random_looking_judge_list[2048]; +}; + +struct session_flags_plugin_info{ + int plugin_id; + int sess_ctx_exdata_idx; + struct stellar *st; + struct logger *log_handle; + int session_flags_topic_id; + int tcp_topic_id; + int udp_topic_id; + hs_database_t *tunneling_hs_db; +}; + +struct session_flags_iter_values +{ + float bulky; + float CBR; + float download; + float interactive; + float pseudo_unidirectional; + float streaming; + OnlineMean_t omean; +}; + +struct session_flags_iter +{ + uint32_t iter_cnt; + float bidirectional; + struct session_flags_iter_values c2s; + struct session_flags_iter_values s2c; +}; + +struct flow_stat +{ + uint64_t bytes; + uint64_t pkts; + uint64_t payload_pkts; + uint64_t large_pkts; + + uint32_t delta_pkts; + uint32_t delta_large_pkts; + uint32_t delta_payload_pkts; + uint32_t delta_bytes; + + float rate; +}; + +struct random_looking_stat_info +{ + uint8_t has_judged_sts; + uint8_t has_judged_fet; + uint8_t payload_pkt_num; +}; + +struct session_flags_stat +{ + struct flow_stat c2s, s2c; + uint64_t last_pkt_ts_ms; + uint64_t interactive_pulse_num; + uint64_t session_start_time_ms; + uint64_t stream_live_time_ms; + uint64_t last_iter_ts_ms; + int main_dir; + struct random_looking_stat_info random_looking_stat; + struct tunneling_stat_info tunneling_stat; + struct session_flags_iter iter; + struct session_flags_result result; +}; + +struct session_flags_ctx +{ + struct session_flags_stat stat; + hs_stream_t *tunneling_hs_stream; + uint64_t history_flags; +}; + +void session_flags_stat_init(struct session_flags_stat *stat, enum session_direction session_dir); +struct session_flags_result *session_flags(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_ctx *ctx, struct session *session, int etopic_id, uint32_t bytes, enum flow_type flow_type, uint64_t ms); +struct session_flags_result *session_flags_get_flags(struct session_flags_stat *session_flags); +struct session_flags_message *session_flags_generate_firewall_message(uint64_t flags, const uint32_t identify[session_flags_all_mask]); +float session_flags_calculate_CV(OnlineMean_t * omean);
\ No newline at end of file diff --git a/decoders/session_flags/session_flags_plugin.cpp b/decoders/session_flags/session_flags_plugin.cpp new file mode 100644 index 0000000..db9522c --- /dev/null +++ b/decoders/session_flags/session_flags_plugin.cpp @@ -0,0 +1,404 @@ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include "mesa_sts.h" +#include "cJSON.h" +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" +#include "stellar/log.h" + +#include "session_flags_internal.h" + +#define _MAX_STR_LEN 64 + +#define UNUSED(x) (void)(x) + +const char *CFG_FILE_PATH="./etc/session_flags/session_flags.toml"; + +uint32_t sts_random_switch = 0; + +struct session_flags_init_conf g_sf_conf; + +static const char* random_looking_judge_table[] = { + "frequency", + "block_frequency", + "cumulative_sums", + "runs", + "longest_run", + "rank", + "non_overlapping_template_matching", + "overlapping_template_matching", + "universal", + "random_excursions", + "random_excursions_variant", + "poker_detect", + "runs_distribution", + "self_correlation", + "binary_derivative" +}; + +static void session_flags_topic_free_cb(void *msg, void *msg_free_arg) +{ + UNUSED(msg_free_arg); + struct session_flags_message *flags = (struct session_flags_message *)msg; + + if (flags) + { + if (flags->packet_sequence_array) + { + free(flags->packet_sequence_array); + } + free(flags); + } + + return; +} + +static void session_flags_exdata_free_cb(int idx, void *ex_ptr, void *arg) +{ + UNUSED(idx); + UNUSED(arg); + + if (ex_ptr == NULL) + { + return; + } + struct session_flags_ctx *ctx = (struct session_flags_ctx *)ex_ptr; + tunneling_hs_stream_free(ctx); + + free(ex_ptr); +} + +void session_flags_entry(struct session *session, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) +{ + UNUSED(per_session_ctx); + if (msg == NULL) + { + return; + } + + const struct packet *pkt = (const struct packet *)msg; + struct session_flags_plugin_info *sf_plugin_info = (struct session_flags_plugin_info *)plugin_env; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)session_exdata_get(session, sf_plugin_info->sess_ctx_exdata_idx); + + if (ctx == NULL) + { + ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + session_exdata_set(session, sf_plugin_info->sess_ctx_exdata_idx, ctx); + + session_flags_stat_init(&ctx->stat, session_get_direction(session)); + if (g_sf_conf.tunneling_enabled) + { + tunneling_hs_stream_init(sf_plugin_info, ctx); + } + } + + struct session_flags_stat *stat = &ctx->stat; + session_flags_result *flags_result = NULL; + size_t pktlen = 0; + + pktlen = packet_get_raw_len(pkt); + + uint64_t curr_time_ms = 0; + const struct timeval *tv; + + tv = packet_get_timeval(pkt); + if (tv != NULL) + { + curr_time_ms = tv->tv_sec * 1000 + tv->tv_usec / 1000; + } + + flags_result = session_flags(sf_plugin_info, ctx, session, topic_id, pktlen, session_get_flow_type(session), curr_time_ms); + + if ((stat->stream_live_time_ms > g_sf_conf.session_max_process_time_ms)) + { + stellar_session_plugin_dettach_current_session(session); + } + + uint32_t pkts_num = stat->c2s.pkts + stat->s2c.pkts; + + if (flags_result != NULL) + { + if (flags_result->flags != ctx->history_flags) + { + struct session_flags_message *flags_msg = session_flags_generate_firewall_message(flags_result->flags, flags_result->identify); + if (session_mq_publish_message(session, sf_plugin_info->session_flags_topic_id, flags_msg) < 0) + { + session_flags_topic_free_cb(flags_msg, NULL); + + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "[%s] publish session flags message failed, flags:0x%x, pkts_num:%d", session_get0_readable_addr(session), flags_result->flags, pkts_num); + return; + } + + ctx->history_flags = flags_result->flags; + + STELLAR_LOG_DEBUG(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, + "[%s] flags:0x%x, pkts_num:%d\n \ + c2s_iter: bulky: %f, CBR: %f, download: %f, interactive: %f, pseudo_unidirectional: %f, streaming: %f, CBR_CV: %f\n \ + s2c_iter: bulky: %f, CBR: %f, download: %f, interactive: %f, pseudo_unidirectional: %f, streaming: %f, CBR_CV: %f\n \ + iter_cnt: %d, bidirectional: %f\n", session_get0_readable_addr(session), ctx->history_flags, pkts_num, + stat->iter.c2s.bulky, stat->iter.c2s.CBR, stat->iter.c2s.download, stat->iter.c2s.interactive, stat->iter.c2s.pseudo_unidirectional, stat->iter.c2s.streaming, session_flags_calculate_CV(&stat->iter.c2s.omean), + stat->iter.s2c.bulky, stat->iter.s2c.CBR, stat->iter.s2c.download, stat->iter.s2c.interactive, stat->iter.s2c.pseudo_unidirectional, stat->iter.s2c.streaming, session_flags_calculate_CV(&stat->iter.s2c.omean), + stat->iter.iter_cnt, stat->iter.bidirectional); + } + } + + return; +} + +static void session_flags_load_config(struct session_flags_plugin_info *sf_plugin_info, const char *cfg_file, struct session_flags_init_conf *g_sf_conf) +{ + char errbuf[256] = {0}; + + FILE *fp = fopen(cfg_file, "r"); + if (NULL == fp) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "Can't open config file:%s", cfg_file); + return; + } + + toml_table_t *toml_root = toml_parse_file(fp, errbuf, sizeof(errbuf)); + fclose(fp); + + toml_table_t *cfg_tbl = toml_table_in(toml_root, "SESSION_FLAGS"); + if (NULL == cfg_tbl) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "config file:%s has no key: [SESSION_FLAGS]", cfg_file); + toml_free(toml_root); + return; + } + + toml_datum_t toml_val = toml_int_in(cfg_tbl, "INTERACTIVE_STARTTIME_MS"); + if (toml_val.ok) + { + g_sf_conf->interactive_starttime_ms = toml_val.u.i; + } + else + { + g_sf_conf->interactive_starttime_ms = 15000; + } + + toml_val = toml_int_in(cfg_tbl, "INTERACTIVE_PULSE_NUM"); + if (toml_val.ok) + { + g_sf_conf->interactive_pulse_num = toml_val.u.i; + } + else + { + g_sf_conf->interactive_pulse_num = 4; + } + + toml_val = toml_int_in(cfg_tbl, "INTERACTIVE_LATENCY_MS"); + if (toml_val.ok) + { + g_sf_conf->interactive_latency_ms = toml_val.u.i; + } + else + { + g_sf_conf->interactive_latency_ms = 1000; + } + + toml_val = toml_int_in(cfg_tbl, "MAIN_DIR_FRONT_N_PKTS"); + if (toml_val.ok) + { + g_sf_conf->main_dir_front_n_pkts = toml_val.u.i; + } + else + { + g_sf_conf->main_dir_front_n_pkts = 100; + } + + toml_val = toml_int_in(cfg_tbl, "LARGE_PKTS_INIT_SIZE"); + if (toml_val.ok) + { + g_sf_conf->large_ptks_init_size = toml_val.u.i; + } + else + { + g_sf_conf->large_ptks_init_size = 1000; + } + + toml_val = toml_int_in(cfg_tbl, "SESSION_MAX_PROCESS_TIME_MS"); + if (toml_val.ok) + { + g_sf_conf->session_max_process_time_ms = toml_val.u.i; + } + else + { + g_sf_conf->session_max_process_time_ms = 30000; + } + + toml_val = toml_int_in(cfg_tbl, "FET_ENABLED"); + if (toml_val.ok) + { + g_sf_conf->fet_enabled = toml_val.u.b; + } + else + { + g_sf_conf->fet_enabled = 1; + } + + toml_val = toml_int_in(cfg_tbl, "RANDOM_LOOKING_UDP_IGNORE_PKTS"); + if (toml_val.ok) + { + g_sf_conf->random_looking_udp_ignore_pkts = toml_val.u.i; + } + else + { + g_sf_conf->random_looking_udp_ignore_pkts = 3; + } + + toml_val = toml_int_in(cfg_tbl, "TUNNELING_TLS_IGNORE_PKTS"); + if (toml_val.ok) + { + g_sf_conf->tunneling_tls_ignore_pkts = toml_val.u.i; + } + else + { + g_sf_conf->tunneling_tls_ignore_pkts = 4; + } + + toml_val = toml_int_in(cfg_tbl, "TUNNELING_MAX_SCAN_PKTS"); + if (toml_val.ok) + { + g_sf_conf->tunneling_max_scan_pkts = toml_val.u.i; + } + else + { + g_sf_conf->tunneling_max_scan_pkts = 15; + } + + toml_val = toml_string_in(cfg_tbl, "TUNNELING_PCRE_LIST"); + if (toml_val.ok) + { + strncpy(g_sf_conf->tunneling_pcre_list, toml_val.u.s, sizeof(g_sf_conf->tunneling_pcre_list) - 1); + } + else + { + strncpy(g_sf_conf->tunneling_pcre_list, "{\"tunneling_pcre_list\":[]}", sizeof(g_sf_conf->tunneling_pcre_list) - 1); + } + + toml_val = toml_string_in(cfg_tbl, "RANDOM_LOOKING_JUDGE_LIST"); + if (toml_val.ok) + { + strncpy(g_sf_conf->random_looking_judge_list, toml_val.u.s, sizeof(g_sf_conf->random_looking_judge_list) - 1); + } + else + { + strncpy(g_sf_conf->random_looking_judge_list, "{\"random_looking_judge_list\":[]}", sizeof(g_sf_conf->random_looking_judge_list) - 1); + } +} + +extern "C" void *session_flags_plugin_init(struct stellar *st) +{ + char random_looking_list_str[2048] = {0}; + struct session_flags_plugin_info *sf_plugin_info = (struct session_flags_plugin_info *)calloc(1, sizeof(struct session_flags_plugin_info)); + cJSON *json = NULL, *item = NULL; + int array_num; + + sf_plugin_info->st = st; + sf_plugin_info->sess_ctx_exdata_idx = stellar_exdata_new_index(st, "SESSION_FLAGS_SESS_CTX", session_flags_exdata_free_cb, NULL); + + sf_plugin_info->log_handle = stellar_get_logger(st); + if(sf_plugin_info->log_handle==NULL) + { + printf("stellar_get_logger object failed ...\n"); + goto ERROR; + } + + memset(&g_sf_conf, 0, sizeof(g_sf_conf)); + session_flags_load_config(sf_plugin_info, CFG_FILE_PATH, &g_sf_conf); + tunneling_hyperscan_engine_init(sf_plugin_info, &g_sf_conf); + + json = cJSON_Parse(g_sf_conf.random_looking_judge_list); + if (json == NULL) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "cJSON_Parse failed, random_looking_list_str:%s", random_looking_list_str); + goto ERROR; + } + item = cJSON_GetObjectItem(json, "random_looking_judge_list"); + if (item == NULL) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "cJSON_GetObjectItem failed, random_looking_list_str:%s", random_looking_list_str); + goto ERROR; + } + array_num = cJSON_GetArraySize(item); + if (array_num > STS_RANDOM_JUDGE_NUM || array_num < 0) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "array size error, array_num:%d", array_num); + goto ERROR; + } + for (int i = 0; i < array_num; i++) + { + for (int j = 0; j < STS_RANDOM_JUDGE_NUM; j++) + { + if (strcmp(cJSON_GetArrayItem(item, i)->valuestring, random_looking_judge_table[j]) == 0) + { + STS_SET_FLAG(sts_random_switch, j); + g_sf_conf.random_judge_flags_cnt++; + break; + } + } + } + cJSON_Delete(json); + + sf_plugin_info->plugin_id = stellar_session_plugin_register(st, NULL, NULL, sf_plugin_info); + if (sf_plugin_info->plugin_id < 0) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "stellar_session_plugin_register failed"); + goto ERROR; + + } + + sf_plugin_info->session_flags_topic_id = stellar_mq_create_topic(st, SESSION_FLAGS_MESSAGE_TOPIC, session_flags_topic_free_cb, NULL); + if (sf_plugin_info->session_flags_topic_id < 0) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "stellar_session_mq_create_topic failed"); + goto ERROR; + } + + sf_plugin_info->tcp_topic_id = stellar_mq_get_topic_id(st, TOPIC_TCP_INPUT); + sf_plugin_info->udp_topic_id = stellar_mq_get_topic_id(st, TOPIC_UDP_INPUT); + if (sf_plugin_info->tcp_topic_id < 0 || sf_plugin_info->udp_topic_id < 0) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "stellar_session_mq_get_topic_id failed"); + goto ERROR; + } + + stellar_session_mq_subscribe(st, sf_plugin_info->tcp_topic_id, session_flags_entry, sf_plugin_info->plugin_id); + stellar_session_mq_subscribe(st, sf_plugin_info->udp_topic_id, session_flags_entry, sf_plugin_info->plugin_id); + + return sf_plugin_info; + +ERROR: + if (sf_plugin_info != NULL) + { + free(sf_plugin_info); + } + + if (json != NULL) + { + cJSON_Delete(json); + } + + perror("session_flags init failed"); + exit(-1); +} + +extern "C" void session_flags_plugin_exit(void *plugin_ctx) +{ + if (plugin_ctx == NULL) + { + return; + } + + struct session_flags_plugin_info *sf_plugin_info = (struct session_flags_plugin_info *)plugin_ctx; + + tunneling_hyperscan_engine_exit(sf_plugin_info->tunneling_hs_db); + + free(plugin_ctx); + + return; +}
\ No newline at end of file diff --git a/decoders/session_flags/tunneling.cpp b/decoders/session_flags/tunneling.cpp new file mode 100644 index 0000000..987ffc5 --- /dev/null +++ b/decoders/session_flags/tunneling.cpp @@ -0,0 +1,217 @@ +#include <cctype> +#include <stdlib.h> +#include <stdio.h> +#include "cJSON.h" +#include "session_flags_internal.h" +#include "tunneling.h" +#include "stellar/log.h" + +#define UNUSED(x) (void)(x) + +thread_local hs_scratch_t *hs_scratch = NULL; +extern struct session_flags_init_conf g_sf_conf; + +static char tunneling_length_to_character(enum flow_type flow_type, size_t len) +{ + char ret; + + switch(len) + { + case 1 ... 200: + ret = 'A'; + break; + case 201 ... 600: + ret = 'B'; + break; + case 601 ... 1000: + ret = 'C'; + break; + case 1001 ... 1460: + ret = 'D'; + break; + default: + ret = 'Z'; + break; + } + + if (flow_type == FLOW_TYPE_C2S) + { + return ret; + } + else + { + return tolower(ret); + } +} + +static int tunneling_match_event_handler(unsigned int id, unsigned long long from, unsigned long long to, unsigned int flags, void *context) { + UNUSED(id); + UNUSED(from); + UNUSED(to); + UNUSED(flags); + + struct session_flags_ctx *ctx = (struct session_flags_ctx *)context; + ctx->stat.result.flags |= SESSION_FLAGS_TUNNELING; + return 0; +} + +int tunneling_scan_sequence(struct session_flags_plugin_info *sf_plugin_info, struct session *session, struct session_flags_ctx *ctx, size_t payload_len, enum flow_type flow_type, uint64_t pkts_cnt) +{ + if (ctx->stat.result.flags & SESSION_FLAGS_TUNNELING) + { + return 0; + } + + ctx->stat.tunneling_stat.payload_pkt_num++; + if (ctx->stat.result.is_tls && ctx->stat.tunneling_stat.payload_pkt_num <= g_sf_conf.tunneling_tls_ignore_pkts) + { + return 0; + } + + if((ctx->stat.result.is_tls==0) && (ctx->stat.tunneling_stat.payload_pkt_num > g_sf_conf.tunneling_max_scan_pkts)) + { + return 0; + } + + if((ctx->stat.result.is_tls) && (ctx->stat.tunneling_stat.payload_pkt_num > g_sf_conf.tunneling_max_scan_pkts+g_sf_conf.tunneling_tls_ignore_pkts)) + { + return 0; + } + + if (hs_scratch == NULL) + { + hs_error_t err = hs_alloc_scratch(sf_plugin_info->tunneling_hs_db, &hs_scratch); + if (err != HS_SUCCESS) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "hs_alloc_scratch failed, err:%d", err); + return -1; + } + } + + char tunneling_seq_char = tunneling_length_to_character(flow_type, payload_len); + STELLAR_LOG_DEBUG(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "session: %s, is tls:%s, total_num: %d, payload_pkt_num: %d, tunneling_seq_char:%c, payload_len:%d", + session_get0_readable_addr(session), ctx->stat.result.is_tls == true ? "yes":"no", pkts_cnt, ctx->stat.tunneling_stat.payload_pkt_num, tunneling_seq_char, payload_len); + + hs_error_t err = hs_scan_stream(ctx->tunneling_hs_stream, &tunneling_seq_char, 1, 0, hs_scratch, tunneling_match_event_handler, ctx); + if (err != HS_SUCCESS) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "hs_scan_stream failed, err:%d", err); + return -1; + } + if (ctx->stat.result.flags & SESSION_FLAGS_TUNNELING) + { + ctx->stat.result.identify[session_flags_tunneling_mask] = pkts_cnt; + } + + return 0; +} + +void tunneling_hs_stream_init(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_ctx *ctx) +{ + hs_error_t err = hs_open_stream(sf_plugin_info->tunneling_hs_db, 0, &ctx->tunneling_hs_stream); + if (err != HS_SUCCESS) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "hs_open_stream failed, err:%d", err); + return; + } +} + +void tunneling_hs_stream_free(struct session_flags_ctx *ctx) +{ + if (ctx->tunneling_hs_stream == NULL) + { + return; + } + + hs_close_stream(ctx->tunneling_hs_stream, hs_scratch, NULL, NULL); +} + +int tunneling_hyperscan_engine_init(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_init_conf *g_sf_conf) +{ + cJSON *json = NULL, *item = NULL; + int array_num; + char **pcre = NULL; + hs_compile_error_t *compile_err; + hs_error_t err; + unsigned int *flags = NULL; + unsigned int *ids = NULL; + int ret = 0; + + g_sf_conf->tunneling_enabled = 0; + + json = cJSON_Parse(g_sf_conf->tunneling_pcre_list); + if (json == NULL) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "cJSON_Parse failed, tunneling_pcre_list:%s", g_sf_conf->tunneling_pcre_list); + goto END; + } + item = cJSON_GetObjectItem(json, "tunneling_pcre_list"); + if (item == NULL) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "cJSON_GetObjectItem failed, tunneling_pcre_list:%s", g_sf_conf->tunneling_pcre_list); + goto END; + } + array_num = cJSON_GetArraySize(item); + if (array_num < 0) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "array size error, array_num:%d", array_num); + goto END; + } + + if (array_num == 0) + { + goto END; + } + + g_sf_conf->tunneling_enabled = 1; + pcre = (char **)calloc(array_num, sizeof(char *)); + for (int i = 0; i < array_num; i++) + { + pcre[i] = cJSON_GetArrayItem(item, i)->valuestring; + } + + flags = (unsigned int *)calloc(array_num, sizeof(unsigned int)); + ids = (unsigned int *)calloc(array_num, sizeof(unsigned int)); + for (int i = 0; i < array_num; i++) + { + flags[i] = HS_FLAG_DOTALL; + ids[i] = i; + } + + err = hs_compile_multi(pcre, flags, ids, array_num, HS_MODE_STREAM, NULL, &sf_plugin_info->tunneling_hs_db, &compile_err); + if (err != HS_SUCCESS) + { + STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "hs_compile_multi failed, err:%d, pattern id: %d, err_msg: %s, pattern: %s", err, compile_err->expression, compile_err->message, pcre[compile_err->expression]); + cJSON_Delete(json); + free(pcre); + ret = -1; + goto END; + } + +END: + if (json != NULL) + { + cJSON_Delete(json); + } + if (pcre != NULL) + { + free(pcre); + } + if (flags != NULL) + { + free(flags); + } + if (ids != NULL) + { + free(ids); + } + return ret; +} + +void tunneling_hyperscan_engine_exit(hs_database_t *tunneling_hs_db) +{ + if (tunneling_hs_db != NULL) + { + hs_free_database(tunneling_hs_db); + } +} diff --git a/decoders/session_flags/tunneling.h b/decoders/session_flags/tunneling.h new file mode 100644 index 0000000..50fc3fe --- /dev/null +++ b/decoders/session_flags/tunneling.h @@ -0,0 +1,18 @@ +#pragma once + +#include <cstdint> +#include <stdlib.h> +#include <hs/hs_common.h> +#include <hs/hs.h> +#include "stellar/session.h" + +struct tunneling_stat_info +{ + uint8_t payload_pkt_num; +}; + +int tunneling_scan_sequence(struct session_flags_plugin_info *sf_plugin_info, struct session *session, struct session_flags_ctx *ctx, size_t payload_len, flow_type flow_type, uint64_t pkts_cnt); +void tunneling_hs_stream_init(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_ctx *ctx); +void tunneling_hs_stream_free(struct session_flags_ctx *ctx); +int tunneling_hyperscan_engine_init(struct session_flags_plugin_info *sf_plugin_info, struct session_flags_init_conf *g_sf_conf); +void tunneling_hyperscan_engine_exit(hs_database_t *tunneling_hs_db);
\ No newline at end of file diff --git a/decoders/socks/CMakeLists.txt b/decoders/socks/CMakeLists.txt new file mode 100644 index 0000000..dabede1 --- /dev/null +++ b/decoders/socks/CMakeLists.txt @@ -0,0 +1,13 @@ +add_definitions(-fPIC) + +set(SOCKS_SRC socks_decoder.cpp) + +add_library(socks STATIC ${SOCKS_SRC}) +add_library(socks_dyn SHARED ${SOCKS_SRC}) +set_target_properties(socks PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/version.map") +target_include_directories(socks PUBLIC ${CMAKE_SOURCE_DIR}/deps/) +target_link_libraries(socks toml) +set_target_properties(socks PROPERTIES PREFIX "") + +set_target_properties(socks_dyn PROPERTIES PREFIX "") +target_link_libraries(socks_dyn toml)
\ No newline at end of file diff --git a/decoders/socks/socks_decoder.cpp b/decoders/socks/socks_decoder.cpp new file mode 100644 index 0000000..233c077 --- /dev/null +++ b/decoders/socks/socks_decoder.cpp @@ -0,0 +1,527 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +extern "C" { +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" +} + +#include "socks_decoder_internal.h" +#include "stellar/log.h" + +#define UNUSED(x) (void)(x) + + +static void socks_decoder_session_exdata_free(int idx, void *ex_ptr, void *arg) +{ + UNUSED(idx); + UNUSED(arg); + + if (ex_ptr == NULL) + { + return; + } + + free(ex_ptr); + + return; +} + +//packet format refer to https://zh.wikipedia.org/wiki/SOCKS +static int socks_rough_rec(const char *payload, size_t payload_len) +{ + //for socks4 + if (payload_len < SOCKS5_REQUEST_METHOD_MIN_LEN) + { + return -1; + } + + if (payload[0] == SOCKS_FIELD_VER_4 && payload[payload_len-1] == 0) + { + if (payload_len >= 9) + { + return 0; + } + } + + if (payload[0] == SOCKS_FIELD_VER_5) + { + if (2 + (unsigned int)payload[1] == payload_len) + { + + return 0; + } + } + return -1; +} + +static int socks5_method_request(const char *payload, size_t payload_len) +{ + if (payload_len < SOCKS5_REQUEST_METHOD_MIN_LEN) + { + return -1; + } + + if (payload[0] != SOCKS_FIELD_VER_5) + { + return -1; + } + + if ((size_t)(2 + payload[1]) != payload_len) + { + return -1; + } + + return 0; +} + +static int socks4_request(struct socks_tunnel_stream *stream, const char *payload, size_t payload_len) +{ + if (payload_len < 9) + return -1; + if (payload[0] != SOCKS_FIELD_VER_4 || payload[payload_len-1] != 0) + return -1; + + struct socks_addr *addr = &(stream->info.dst_addr); + + memcpy(&(addr->port), payload + 2, 2); + memcpy(&(addr->ipv4), payload + 4, 4); + + if (addr->ipv4 & 0x00FFFFFF) + { + addr->type = SOCKS_ADDR_IPV4; + return 0; + } + else if (addr->ipv4 & 0xFF000000)//socks4a hostname + { + size_t pos = 8; + while (pos < payload_len - 2 && payload[pos] != 0) + { + pos++; + } + + if (payload[pos] == 0) + { + if (payload_len - 1 - pos < 2) + return -1; + + addr->fqdn.iov_len = payload_len - 1 - pos - 1; + addr->fqdn.iov_base = (unsigned char *)calloc(1, addr->fqdn.iov_len + 1); + + memcpy(addr->fqdn.iov_base, payload+pos+1, addr->fqdn.iov_len); + + addr->type = SOCKS_ADDR_FQDN; + + return 0; + } + else + { + return -1; + } + } + + return -1; +} + +static int socks5_request(struct socks_tunnel_stream *stream, const char *payload, size_t payload_len) +{ + unsigned int port_offset = 0; + struct socks_addr *addr = &(stream->info.dst_addr); + + if (payload_len < SOCKS5_REQUEST_MIN_LEN) + { + return -1; + } + + if (payload[0] != SOCKS_FIELD_VER_5) + { + return -1; + } + + if (payload[1] != SOCKS_CMD_CONNECT && payload[1] != SOCKS_CMD_BIND) + { + return -1; + } + + if (payload[2] != SOCKS5_RSV_DEFAULT) + { + return -1; + } + + switch (payload[3]) + { + case SOCKS_ATYPE_IP4: + { + if (payload_len != 10) + { + return -1; + } + + addr->type = SOCKS_ADDR_IPV4; + memcpy(&(addr->ipv4), payload+4, 4); + + port_offset = 8; + + break; + } + //should be processed + case SOCKS_ATYPE_IP6: + { + if(payload_len != 22) + { + return -1; + } + addr->type = SOCKS_ADDR_IPV6; + memcpy(addr->ipv6, payload+4, 16); + port_offset = 20; + + break; + } + case SOCKS_ATYPE_FQDN: + { + if (payload[4] < 0 || payload_len != (size_t)(7 + payload[4])) + { + return -1; + } + addr->type = SOCKS_ADDR_FQDN; + addr->fqdn.iov_len = payload[4]; + addr->fqdn.iov_base = (char *)calloc(1, addr->fqdn.iov_len + 1); + memcpy(addr->fqdn.iov_base, payload+5, payload[4]); + + port_offset = 5 + payload[4]; + } + break; + default: + break; + } + + memcpy(&(addr->port), payload+port_offset, 2); + + return 0; +} + +static int socks5_pass_request(struct socks_tunnel_stream *stream, const char *payload, size_t payload_len) +{ + unsigned char *ubuf = (unsigned char*)payload; + unsigned char *cur; + struct socks_info *info = &stream->info; + + if (ubuf[0]!=1) + { + return -1; + } + if (payload_len < 2 || payload_len < (size_t)(3+ubuf[1]) || payload_len != (size_t)(3+ubuf[1]+ubuf[2+ubuf[1]])) + { + return -1; + } + + info->user_name.iov_len = ubuf[1]; + info->user_name.iov_base = (char *)calloc(1, info->user_name.iov_len + 1); + memcpy(info->user_name.iov_base, ubuf+2, info->user_name.iov_len); + + info->password.iov_len = ubuf[2+ubuf[1]]; + info->password.iov_base = (char *)calloc(1, info->password.iov_len + 1); + cur = ubuf + 2 + info->user_name.iov_len + 1; + memcpy(info->password.iov_base, cur, info->password.iov_len); + + return 0; +} + +static void c2s_handler(struct socks_tunnel_stream *stream, const char *payload, size_t payload_len) +{ + switch (stream->client_state) + { + case SS_BEGIN: + if (socks5_method_request(payload, payload_len) == 0) + { + stream->client_state = SS_SUB; + stream->info.version = SOCKS_VERSION_5; + } + else if (socks4_request(stream, payload, payload_len) == 0) + { + stream->client_state = SS_END; + stream->info.version = SOCKS_VERSION_4; + } + else + { + stream->client_state = SS_FAILED; + } + break; + case SS_SUB: + if (socks5_request(stream, payload, payload_len) == 0) + { + stream->client_state = SS_END; + } + else if (socks5_pass_request(stream, payload, payload_len) != 0) + { + stream->client_state = SS_FAILED; + } + break; + default: + break; + } +} + +static int socks5_method_replay(const char *payload, size_t payload_len) +{ + if (payload_len != 2) + { + return -1; + } + if (payload[0] != SOCKS_FIELD_VER_5) + { + return -1; + } + if (payload[1] != 0 && payload[1]!=2) + { + return -1; + } + + ////printf("socks5 method replay!\n"); + return 0; +} + +static int socks4_replay(const char *payload, size_t payload_len) +{ + if (payload_len != 8) + return -1; + if (payload[0] != 0 || payload[1] < 90 || payload[1] > 93) + return -1; + + return 0; +} + +static int socks5_replay(const char *payload, size_t payload_len) +{ + if (payload_len < 6) + { + return -1; + } + if (payload[0] != SOCKS_FIELD_VER_5) + { + return -1; + } + if (payload[1] != 0) + { + return -1; + } + if (payload[2] != 0) + { + return -1; + } + + switch(payload[3]) + { + case SOCKS_ATYPE_IP4: + if (payload_len < 10) + { + return -1; + } + break; + case SOCKS_ATYPE_IP6: + if (payload_len != 22) + { + return -1; + } + break; + case SOCKS_ATYPE_FQDN: + if (payload[4] < 0 || payload_len < (size_t)(7 + payload[4])) + { + return -1; + } + break; + default: + return -1; + } + + return 0; +} + +static int socks5_pass_reply(const char *payload, size_t payload_len) +{ + if (payload_len != 2) + return -1; + if (payload[0] != 1 || payload[1] != 0) + return -1; + return 0; +} + +static void s2c_handler(struct socks_tunnel_stream *stream, const char *payload, size_t payload_len) +{ + switch (stream->server_state) + { + case SS_BEGIN: + if (stream->info.version == SOCKS_VERSION_5 && socks5_method_replay(payload, payload_len) == 0) + { + stream->server_state = SS_SUB; + } + else if (stream->info.version == SOCKS_VERSION_4 && socks4_replay(payload, payload_len) == 0) + { + stream->server_state = SS_END; + } + else + { + stream->server_state = SS_FAILED; + //printf("socks error, s2c beign\n"); + } + break; + case SS_SUB: + if (socks5_replay(payload, payload_len) == 0) + { + stream->server_state = SS_END; + } + else if (socks5_pass_reply(payload, payload_len) != 0) + { + stream->server_state = SS_FAILED; + + //printf("socks error, s2c sub\n"); + } + break; + default: + //error! + break; + } +} + +int socks_process(struct socks_decoder_info *socks_decoder_info, struct session *sess, struct socks_tunnel_stream *stream, const char *payload, size_t payload_len) +{ + if (payload_len == 0) + { + return 0; + } + + switch(stream->state) + { + case STATE_INIT: + if (socks_rough_rec(payload, payload_len) < 0) + { + stream->state = STATE_FAILED; + return -1; + } + stream->state = STATE_OPENING; + [[fallthrough]];//continue execute STATE_OPENING + case STATE_OPENING: + switch (session_get_flow_type(sess)) + { + case FLOW_TYPE_C2S: + c2s_handler(stream, payload, payload_len); + break; + case FLOW_TYPE_S2C: + s2c_handler(stream, payload, payload_len); + break; + default: + break; + } + + if (stream->client_state == SS_END && stream->server_state == SS_END) + { + if (session_mq_publish_message(sess, socks_decoder_info->socks_decoder_topic_id, &stream->info) < 0) + { + STELLAR_LOG_FATAL(socks_decoder_info->log_handle, SOCKS_LOG_MOUDLE, "session_mq_publish_message OPENING failed"); + } + stellar_session_plugin_dettach_current_session(sess); + } + else if (stream->client_state == SS_FAILED || stream->server_state == SS_FAILED) + { + //not a socks proxy + stream->state = STATE_FAILED; + return -1; + } + break; + default: + return -1; + } + + return 0; +} + +void socks_decoder_on_message(struct session *sess, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) +{ + UNUSED(per_session_ctx); + UNUSED(topic_id); + UNUSED(msg); + + struct socks_decoder_info *socks_decoder_info = (struct socks_decoder_info *)plugin_env; + struct socks_tunnel_stream *socks_tunel_stream = (struct socks_tunnel_stream *)session_exdata_get(sess, socks_decoder_info->sess_exdata_idx); + const char *payload = NULL; + size_t payload_len = 0; + const struct packet *pkt = NULL; + + if (socks_tunel_stream == NULL) + { + socks_tunel_stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream)); + session_exdata_set(sess, socks_decoder_info->sess_exdata_idx, socks_tunel_stream); + } + + pkt = session_get0_current_packet(sess); + payload = packet_get_payload(pkt); + payload_len = packet_get_payload_len(pkt); + + if (socks_process(socks_decoder_info, sess, socks_tunel_stream, payload, payload_len) < 0) + { + stellar_session_plugin_dettach_current_session(sess); + } +} + +extern "C" void *socks_decoder_init(struct stellar *st) +{ + struct socks_decoder_info *socks_decoder_info = (struct socks_decoder_info *)calloc(1, sizeof(struct socks_decoder_info)); + + socks_decoder_info->sess_exdata_idx= stellar_exdata_new_index(st, "SOCKS_DECODER_SESS_CTX", socks_decoder_session_exdata_free, NULL); + + socks_decoder_info->st = st; + socks_decoder_info->log_handle = stellar_get_logger(st); + + socks_decoder_info->plugin_id = stellar_session_plugin_register(st, NULL, NULL, socks_decoder_info); + if (socks_decoder_info->plugin_id < 0) + { + STELLAR_LOG_FATAL(socks_decoder_info->log_handle, SOCKS_LOG_MOUDLE, "stellar_session_plugin_register failed"); + goto ERROR; + + } + + socks_decoder_info->socks_decoder_topic_id = stellar_mq_create_topic(st, SOCKS_MESSAGE_TOPIC, NULL, NULL); + if (socks_decoder_info->socks_decoder_topic_id < 0) + { + STELLAR_LOG_FATAL(socks_decoder_info->log_handle, SOCKS_LOG_MOUDLE, "stellar_session_mq_create_topic failed"); + goto ERROR; + } + + socks_decoder_info->tcp_topic_id = stellar_mq_get_topic_id(st, TOPIC_TCP_STREAM); + if (socks_decoder_info->tcp_topic_id < 0) + { + STELLAR_LOG_FATAL(socks_decoder_info->log_handle, SOCKS_LOG_MOUDLE, "stellar_session_mq_get_topic_id failed"); + goto ERROR; + } + + if (stellar_session_mq_subscribe(st, socks_decoder_info->tcp_topic_id, socks_decoder_on_message, socks_decoder_info->plugin_id) < 0) + { + STELLAR_LOG_FATAL(socks_decoder_info->log_handle, SOCKS_LOG_MOUDLE, "stellar_session_mq_subscribe tcp_topic_id failed"); + goto ERROR; + } + + return socks_decoder_info; + +ERROR: + if (socks_decoder_info != NULL) + { + free(socks_decoder_info); + } + perror("socks_decoder init failed"); + exit(-1); +} + +extern "C" void socks_decoder_exit(void *plugin_env) +{ + struct socks_decoder_info *socks_decoder_info = (struct socks_decoder_info *)plugin_env; + + if (socks_decoder_info != NULL) + { + free(socks_decoder_info); + } + + return; +}
\ No newline at end of file diff --git a/decoders/socks/socks_decoder_internal.h b/decoders/socks/socks_decoder_internal.h new file mode 100644 index 0000000..8749c62 --- /dev/null +++ b/decoders/socks/socks_decoder_internal.h @@ -0,0 +1,56 @@ +#include "stellar/socks_decoder.h" + +#define SOCKS_FIELD_VER_4 4 +#define SOCKS_FIELD_VER_5 5 + +#define SOCKS5_REQUEST_METHOD_MIN_LEN 3 +#define SOCKS5_REQUEST_MIN_LEN 6 +#define SOCKS_VERSION_TYPE_SOCKS4 4 +#define SOCKS_VERSION_TYPE_SOCKS5 5 + +#define SOCKS_CMD_CONNECT 0x01 +#define SOCKS_CMD_BIND 0x02 +#define SOCKS_CMD_UDP 0x03 + +#define SOCKS5_RSV_DEFAULT 0 +#define SOCKS_ATYPE_IP4 1 +#define SOCKS_ATYPE_IP6 4 +#define SOCKS_ATYPE_FQDN 3 + +#define SOCKS5_AUTH_NONE 0x00 +#define SOCKS5_AUTH_PASS 0x02 + +#define SOCKS_LOG_MOUDLE "SOCKS_DECODER" + +struct socks_decoder_info +{ + int plugin_id; + int sess_exdata_idx; + struct stellar *st; + struct logger *log_handle; + int socks_decoder_topic_id; + int tcp_topic_id; +}; + +enum socks_establish_state +{ + SS_BEGIN = 0, + SS_SUB, + SS_END, + SS_FAILED +}; + +enum socks_internal_state +{ + STATE_INIT, + STATE_OPENING, + STATE_FAILED +}; + +struct socks_tunnel_stream +{ + enum socks_internal_state state; + enum socks_establish_state client_state; + enum socks_establish_state server_state; + struct socks_info info; +};
\ No newline at end of file diff --git a/decoders/stratum/CMakeLists.txt b/decoders/stratum/CMakeLists.txt new file mode 100644 index 0000000..757555e --- /dev/null +++ b/decoders/stratum/CMakeLists.txt @@ -0,0 +1,14 @@ +add_definitions(-fPIC) +include_directories(${CMAKE_SOURCE_DIR}/deps) +include_directories(${CMAKE_BINARY_DIR}/vendors/cjson/src/cjson/include) + +set(STRATUM_SRC stratum_decoder.cpp) + +add_library(stratum STATIC ${STRATUM_SRC}) +add_library(stratum_dyn SHARED ${STRATUM_SRC}) +set_target_properties(stratum PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/version.map") + +set_target_properties(stratum PROPERTIES PREFIX "") + +target_link_libraries(stratum_dyn) +set_target_properties(stratum_dyn PROPERTIES PREFIX "")
\ No newline at end of file diff --git a/decoders/stratum/stratum_decoder.cpp b/decoders/stratum/stratum_decoder.cpp new file mode 100644 index 0000000..3267817 --- /dev/null +++ b/decoders/stratum/stratum_decoder.cpp @@ -0,0 +1,311 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "cJSON.h" +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" +#include "stellar/stratum_decoder.h" +#include "stellar/log.h" + +#define unused(x) ((void)(x)) + +#define STRATUM_LOG_MOUDLE "STRATUM_DECODER" + +//字段内容宏 +#define METHOD_STR "method" +#define WORKER_STR "worker" +#define PARAMS_STR "params" +#define AGENT_STR "agent" + +enum stratum_field_type +{ + CRYPTOCURRENCY_FLAG = 1, + MINING_POOL_FLAG, + MINING_PROGRAM_FLAG, + MINING_SUBSCRIBE_FLAG, +}; + +struct stratum_decoder_info +{ + int plugin_id; + struct stellar *st; + struct logger *log_handle; + int tcp_topic_id; + int stratum_decoder_topic_id; +}; + +void free_stratum_filed(struct stratum_field *stratum_field) +{ + if(stratum_field!=NULL){ + if(stratum_field->mining_program.iov_base != NULL){ + free(stratum_field->mining_program.iov_base); + stratum_field->mining_program.iov_len = 0; + } + if(stratum_field->mining_pools.iov_base != NULL){ + free(stratum_field->mining_pools.iov_base); + stratum_field->mining_pools.iov_len = 0; + } + if(stratum_field->mining_subscribe.iov_base != NULL){ + free(stratum_field->mining_subscribe.iov_base); + stratum_field->mining_subscribe.iov_len = 0; + } + free(stratum_field); + } + return; +} + +void stratum_decoder_session_msg_free_cb(void *msg, void *msg_free_arg) +{ + unused(msg_free_arg); + + struct stratum_field *stratum_field = (struct stratum_field *)msg; + + free_stratum_filed(stratum_field); + + return; +} + +int stratum_field_assign(char *content, struct stratum_field* stratum_field,int field_range) +{ + switch (field_range) + { + case MINING_POOL_FLAG: + stratum_field->mining_pools.iov_len=strlen(content); + stratum_field->mining_pools.iov_base=(char*)malloc(stratum_field->mining_pools.iov_len+1); + memcpy(stratum_field->mining_pools.iov_base, content, stratum_field->mining_pools.iov_len); + ((char*)stratum_field->mining_pools.iov_base)[stratum_field->mining_pools.iov_len]='\0'; + break; + case MINING_PROGRAM_FLAG: + stratum_field->mining_program.iov_len=strlen(content); + stratum_field->mining_program.iov_base=(char*)malloc(stratum_field->mining_program.iov_len+1); + memcpy(stratum_field->mining_program.iov_base, content, stratum_field->mining_program.iov_len); + ((char*)stratum_field->mining_program.iov_base)[stratum_field->mining_program.iov_len]='\0'; + break; + case MINING_SUBSCRIBE_FLAG: + stratum_field->mining_subscribe.iov_len=strlen(content); + stratum_field->mining_subscribe.iov_base=(char*)malloc(stratum_field->mining_subscribe.iov_len+1); + memcpy(stratum_field->mining_subscribe.iov_base, content,stratum_field->mining_subscribe.iov_len); + ((char*)stratum_field->mining_subscribe.iov_base)[stratum_field->mining_subscribe.iov_len]='\0'; + break; + default: + return -1; + } + + return 0; +} + +struct stratum_field *stratum_json_decode(struct stratum_decoder_info *stratum_decoder_info, char *raw_json_str) +{ + + if(raw_json_str==NULL){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode error!:raw_json_str is null! "); + return NULL; + } + + cJSON *root = cJSON_Parse(raw_json_str); + if (root == NULL){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode error!:root_json is null,error: %s ",cJSON_GetErrorPtr()); + return NULL; + } + + cJSON *method_item = cJSON_GetObjectItem(root, METHOD_STR); + if(method_item==NULL){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode error!:not_found '%s' in raw_json_str ", METHOD_STR); + cJSON_Delete(root); + return NULL; + } + + struct stratum_field *stratum_field = (struct stratum_field *)calloc(1, sizeof(struct stratum_field)); + int field_range = 0; + if(cJSON_IsString(method_item)){ + int assign_ret = 0; + STELLAR_LOG_DEBUG(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode,find '%s':%s\n", METHOD_STR, method_item->valuestring); + + if((strncasecmp("mining.subscribe", method_item->valuestring,strlen("mining.subscribe")) == 0) + ||(strncasecmp("login", method_item->valuestring,strlen("login")) == 0)){ + field_range = MINING_SUBSCRIBE_FLAG; + assign_ret = stratum_field_assign(raw_json_str, stratum_field, field_range); + + cJSON *paras_item = cJSON_GetObjectItem(root, PARAMS_STR); + if(paras_item == NULL){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!not_found '%s' in raw_json_str ", PARAMS_STR); + goto err_ret; + } + + if(cJSON_IsArray(paras_item)){ + int asize = cJSON_GetArraySize(paras_item); + stratum_field->type = OTHER; + cJSON *array_item = cJSON_GetArrayItem(paras_item, 0); + if(cJSON_IsString(array_item)){ + field_range = MINING_PROGRAM_FLAG; + assign_ret = stratum_field_assign(array_item->valuestring, stratum_field, field_range); + } + if(asize>2){ + array_item = cJSON_GetArrayItem(paras_item, 2); + if(cJSON_IsString(array_item)){ + field_range = MINING_POOL_FLAG; + assign_ret = stratum_field_assign(array_item->valuestring, stratum_field, field_range); + } + } + }else if(cJSON_IsObject(paras_item) || cJSON_IsRaw(paras_item)){ + cJSON *agent_item = cJSON_GetObjectItem(paras_item, AGENT_STR); + if(agent_item == NULL){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!not_found '%s' in raw_json_str ", AGENT_STR); + goto err_ret; + } + if(cJSON_IsString(agent_item)){ + field_range = MINING_PROGRAM_FLAG; + stratum_field->type = OTHER; + assign_ret = stratum_field_assign(agent_item->valuestring, stratum_field, field_range); + } + }else{ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!found '%s',json_value_type:%d\n ", PARAMS_STR, paras_item->type); + goto err_ret; + } + }else if(strncasecmp("eth_submitLogin", method_item->valuestring, strlen("eth_submitLogin")) == 0){ + field_range = MINING_SUBSCRIBE_FLAG; + assign_ret = stratum_field_assign(raw_json_str, stratum_field, field_range); + + cJSON *worker_item = cJSON_GetObjectItem(root, WORKER_STR); + if(worker_item == NULL){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!not_found '%s' in raw_json_str ", WORKER_STR); + goto err_ret; + } + if(cJSON_IsString(worker_item)){ + field_range = MINING_PROGRAM_FLAG; + stratum_field->type = ETH; + assign_ret = stratum_field_assign(worker_item->valuestring, stratum_field, field_range); + }else{ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!found '%s',json_value_type:%d\n ", WORKER_STR, worker_item->type); + goto err_ret; + } + }else{ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!found '%s',json_value_type:%d\n ", METHOD_STR, method_item->type); + goto err_ret; + } + + if(assign_ret<0){ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "field_assign_error:raw_json_str:%s\n ", raw_json_str); + goto err_ret; + } + cJSON_Delete(root); + return stratum_field; + }else{ + STELLAR_LOG_INFO(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "json_decode:error!found '%s',json_value_type:%d\n ", METHOD_STR, method_item->type); + goto err_ret; + } + +err_ret: + cJSON_Delete(root); + free_stratum_filed(stratum_field); + return NULL; +} + +struct stratum_field *stratum_data_process(struct stratum_decoder_info *stratum_decoder_info, const char *tcpdata, size_t datalen) +{ + if(tcpdata == NULL || datalen == 0) + { + return NULL; + } + + char *tcp_json=(char*)malloc(datalen+1); + memcpy(tcp_json, tcpdata, datalen); + tcp_json[datalen]='\0'; + + struct stratum_field *stratum_field=stratum_json_decode(stratum_decoder_info, tcp_json); + if(stratum_field==NULL) + { + STELLAR_LOG_DEBUG(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "payload_decode failed!stratum_field is null"); + } + + free(tcp_json); + tcp_json=NULL; + + return stratum_field; + +} + +void stratum_decoder_tcp_on_msg_cb(struct session *sess, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) +{ + unused(topic_id); + unused(per_session_ctx); + unused(msg); + + struct stratum_decoder_info *stratum_decoder_info = (struct stratum_decoder_info *)plugin_env; + + const struct packet *pkt = session_get0_current_packet(sess); + const char *payload = packet_get_payload(pkt); + size_t payload_len = packet_get_payload_len(pkt); + + struct stratum_field *stratum_field = stratum_data_process(stratum_decoder_info, payload, payload_len); + if (stratum_field != NULL) + { + if (session_mq_publish_message(sess, stratum_decoder_info->stratum_decoder_topic_id, stratum_field) < 0) + { + STELLAR_LOG_FATAL(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "stratum_decoder_tcp_on_msg_cb:session_mq_publish_message failed"); + free_stratum_filed(stratum_field); + } + stellar_session_plugin_dettach_current_session(sess); + } + + return; +} + +extern "C" void *stratum_decoder_init(struct stellar *st) +{ + struct stratum_decoder_info *stratum_decoder_info = (struct stratum_decoder_info *)malloc(sizeof(struct stratum_decoder_info)); + + stratum_decoder_info->st = st; + stratum_decoder_info->log_handle = stellar_get_logger(st); + + stratum_decoder_info->plugin_id = stellar_session_plugin_register(st, NULL, NULL, stratum_decoder_info); + if (stratum_decoder_info->plugin_id < 0) + { + STELLAR_LOG_FATAL(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "stellar_session_plugin_register failed"); + goto ERROR; + } + + stratum_decoder_info->stratum_decoder_topic_id = stellar_mq_create_topic(st, STRATUM_MESSAGE_TOPIC, stratum_decoder_session_msg_free_cb, NULL); + if (stratum_decoder_info->stratum_decoder_topic_id < 0) + { + STELLAR_LOG_FATAL(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "stellar_session_mq_create_topic failed"); + goto ERROR; + } + + stratum_decoder_info->tcp_topic_id = stellar_mq_get_topic_id(st, TOPIC_TCP_STREAM); + if (stratum_decoder_info->tcp_topic_id < 0) + { + STELLAR_LOG_FATAL(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "stellar_session_mq_get_topic_id failed"); + goto ERROR; + } + + if (stellar_session_mq_subscribe(st, stratum_decoder_info->tcp_topic_id, stratum_decoder_tcp_on_msg_cb, stratum_decoder_info->plugin_id) < 0) + { + STELLAR_LOG_FATAL(stratum_decoder_info->log_handle, STRATUM_LOG_MOUDLE, "stellar_session_mq_subscribe failed"); + goto ERROR; + } + + return stratum_decoder_info; + +ERROR: + if (stratum_decoder_info) + { + free(stratum_decoder_info); + } + return NULL; +} + +extern "C" void stratum_decoder_exit(void *plugin_env) +{ + struct stratum_decoder_info *stratum_decoder_info = (struct stratum_decoder_info *)plugin_env; + + if (stratum_decoder_info != NULL) + { + free(stratum_decoder_info); + } + + return; +}
\ No newline at end of file diff --git a/include/stellar/session_flags.h b/include/stellar/session_flags.h new file mode 100644 index 0000000..2aeace8 --- /dev/null +++ b/include/stellar/session_flags.h @@ -0,0 +1,55 @@ +#pragma once + +#include <stddef.h> +#include <stdint.h> + +#define MESSAGE_MAGIC 0x12345678 + +#define SESSION_FLAGS_MESSAGE_TOPIC "TOPIC_SESSION_FLAGS" + +enum +{ + session_flags_bulky_mask = 1, + session_flags_cbr_mask, + session_flags_local_client_mask, + session_flags_local_server_mask, + session_flags_download_mask, + session_flags_interactive_mask, + session_flags_inbound_mask, + session_flags_outbound_mask, + session_flags_pseudo_unidirectional_mask, + session_flags_streaming_mask, + session_flags_unidirectional_mask, + session_flags_random_looking_mask, + session_flags_c2s_mask, + session_flags_s2c_mask, + session_flags_bidirectional_mask, + session_flags_tunneling_mask, + session_flags_all_mask +}; + +#define SESSION_FLAGS_START (0x0000000000000001) +#define SESSION_FLAGS_BULKY (SESSION_FLAGS_START << session_flags_bulky_mask) +#define SESSION_FLAGS_CBR (SESSION_FLAGS_START << session_flags_cbr_mask) +#define SESSION_FLAGS_LOCAL_CLIENT (SESSION_FLAGS_START << session_flags_local_client_mask) +#define SESSION_FLAGS_LOCAL_SERVER (SESSION_FLAGS_START << session_flags_local_server_mask) +#define SESSION_FLAGS_DOWNLOAD (SESSION_FLAGS_START << session_flags_download_mask) +#define SESSION_FLAGS_INTERACTIVE (SESSION_FLAGS_START << session_flags_interactive_mask) +#define SESSION_FLAGS_INBOUND (SESSION_FLAGS_START << session_flags_inbound_mask) +#define SESSION_FLAGS_OUTBOUND (SESSION_FLAGS_START << session_flags_outbound_mask) +#define SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL (SESSION_FLAGS_START << session_flags_pseudo_unidirectional_mask) +#define SESSION_FLAGS_STREAMING (SESSION_FLAGS_START << session_flags_streaming_mask) +#define SESSION_FLAGS_UNIDIRECTIONAL (SESSION_FLAGS_START << session_flags_unidirectional_mask) +#define SESSION_FLAGS_RANDOM_LOOKING (SESSION_FLAGS_START << session_flags_random_looking_mask) +#define SESSION_FLAGS_C2S (SESSION_FLAGS_START << session_flags_c2s_mask) +#define SESSION_FLAGS_S2C (SESSION_FLAGS_START << session_flags_s2c_mask) +#define SESSION_FLAGS_BIDIRECTIONAL (SESSION_FLAGS_START << session_flags_bidirectional_mask) +#define SESSION_FLAGS_TUNNELING (SESSION_FLAGS_START << session_flags_tunneling_mask) + +struct session_flags_message +{ + int magic; + uint64_t flags; + uint32_t array_num; + uint32_t *packet_sequence_array; +};
\ No newline at end of file diff --git a/include/stellar/socks_decoder.h b/include/stellar/socks_decoder.h new file mode 100644 index 0000000..c3034b8 --- /dev/null +++ b/include/stellar/socks_decoder.h @@ -0,0 +1,44 @@ +#include <sys/uio.h> + +#include <netinet/in.h> +#ifndef IPV6_ADDR_LEN +#define IPV6_ADDR_LEN (sizeof(struct in6_addr)) +#endif + + +#define SOCKS_MESSAGE_TOPIC "TOPIC_SOCKS" + + +enum socks_addr_type +{ + SOCKS_ADDR_IPV4, + SOCKS_ADDR_IPV6, + SOCKS_ADDR_FQDN +}; + +struct socks_addr +{ + enum socks_addr_type type; + union + { + uint32_t ipv4; /* network order */ + uint8_t ipv6[IPV6_ADDR_LEN] ; + struct iovec fqdn; + }; + uint16_t port; /* network order */ +}; + +enum socks_version +{ + SOCKS_VERSION_4, + SOCKS_VERSION_5 +}; + +struct socks_info +{ + enum socks_version version; + struct socks_addr dst_addr; + struct iovec user_name; + struct iovec password; +};//message data +
\ No newline at end of file diff --git a/include/stellar/stratum_decoder.h b/include/stellar/stratum_decoder.h new file mode 100644 index 0000000..a6eed42 --- /dev/null +++ b/include/stellar/stratum_decoder.h @@ -0,0 +1,18 @@ +#include <sys/uio.h> + +#define STRATUM_MESSAGE_TOPIC "TOPIC_STRATUM" + +enum cryptocurrency_type +{ + ETH=1, + OTHER=2 +}; + +struct stratum_field +{ + enum cryptocurrency_type type; + struct iovec mining_pools; + struct iovec mining_program; + struct iovec mining_subscribe; + +};//message data
\ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7f8f9f0..89f667b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,3 +3,6 @@ add_subdirectory(packet_tool) add_subdirectory(debug_plugin) add_subdirectory(lpi_plugin) add_subdirectory(decoders/http) +add_subdirectory(decoders/socks) +add_subdirectory(decoders/stratum) +add_subdirectory(decoders/session_flags)
\ No newline at end of file diff --git a/test/decoders/session_flags/CMakeLists.txt b/test/decoders/session_flags/CMakeLists.txt new file mode 100644 index 0000000..4bf55ba --- /dev/null +++ b/test/decoders/session_flags/CMakeLists.txt @@ -0,0 +1,56 @@ +set(DECODER_NAME session_flags) + +add_library(${DECODER_NAME}_test SHARED session_flags_test_plugin.cpp) +add_dependencies(${DECODER_NAME}_test ${DECODER_NAME}) +set_target_properties(${DECODER_NAME}_test PROPERTIES PREFIX "") + +set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/testing) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/src) +include_directories(${CMAKE_BINARY_DIR}/vendors/cjson/src/cjson/include) +include_directories(${PROJECT_SOURCE_DIR}/decoders/session_flags) +include_directories(${PROJECT_SOURCE_DIR}/include/stellar) + +add_executable(gtest_session_flags_pcap session_flags_pcap_test.cpp + dummy.c + ${PROJECT_SOURCE_DIR}/decoders/session_flags/fet.cpp + ${PROJECT_SOURCE_DIR}/decoders/session_flags/onlinemean.c + ${PROJECT_SOURCE_DIR}/decoders/session_flags/session_flags_plugin.cpp + ${PROJECT_SOURCE_DIR}/decoders/session_flags/session_flags.cpp + ${PROJECT_SOURCE_DIR}/decoders/session_flags/tunneling.cpp) +target_link_libraries(gtest_session_flags_pcap gtest pcap hyperscan_static hyperscan_runtime_static logger cjson-static libmesa_sts) + +add_executable(gtest_session_flags_static session_flags_static_test.cpp + dummy.c + ${PROJECT_SOURCE_DIR}/decoders/session_flags/fet.cpp + ${PROJECT_SOURCE_DIR}/decoders/session_flags/onlinemean.c + ${PROJECT_SOURCE_DIR}/decoders/session_flags/session_flags_plugin.cpp + ${PROJECT_SOURCE_DIR}/decoders/session_flags/session_flags.cpp + ${PROJECT_SOURCE_DIR}/decoders/session_flags/tunneling.cpp) +target_link_libraries(gtest_session_flags_static gtest pcap hyperscan_static hyperscan_runtime_static logger cjson-static libmesa_sts) + +add_executable(session_flags_test_main plugin_test_main.cpp) +set_target_properties(session_flags_test_main + PROPERTIES + LINK_OPTIONS + "-rdynamic" + ) +set_target_properties(session_flags_test_main + PROPERTIES + LINK_FLAGS + "-rdynamic" + ) +set(LINK_FLAGS "-rdynamic") + +target_link_libraries(session_flags_test_main PUBLIC gtest cjson-static stellar_lib -Wl,--whole-archive packet_parser -Wl,--no-whole-archive) + +add_subdirectory(test_based_on_stellar) + +#copy pcap file folder to build directory +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pcap DESTINATION ${CMAKE_BINARY_DIR}/test/decoders/session_flags) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_based_on_stellar/env/session_flags.toml DESTINATION ${CMAKE_BINARY_DIR}/test/decoders/session_flags/etc/session_flags/) + +include(GoogleTest) +gtest_discover_tests(gtest_session_flags_pcap) +gtest_discover_tests(gtest_session_flags_static) diff --git a/test/decoders/session_flags/dummy.c b/test/decoders/session_flags/dummy.c new file mode 100644 index 0000000..9227261 --- /dev/null +++ b/test/decoders/session_flags/dummy.c @@ -0,0 +1,167 @@ +#include <stdlib.h> +#include <string.h> + +#include "dummy.h" + +#define UNUSED(x) (void)(x) + +struct session g_sess; + +void session_set_current_payload(struct session *sess, char *payload, int payload_len) +{ + UNUSED(sess); + g_sess.payload_len = payload_len; + g_sess.payload = payload; +} + +int session_exdata_set(struct session *sess, int idx, void *ex_ptr) +{ + UNUSED(sess); + UNUSED(idx); + UNUSED(ex_ptr); + + return 0; +} + +struct logger *stellar_get_logger(struct stellar *st) +{ + UNUSED(st); + + return (struct logger *)1; +} + +void *session_exdata_get(struct session *sess, int idx) +{ + UNUSED(sess); + UNUSED(idx); + + return NULL; +} + +const struct packet *session_get0_current_packet(const struct session *sess) +{ + UNUSED(sess); + + return NULL; +} + +uint16_t packet_get_payload_len(const struct packet *pkt) +{ + UNUSED(pkt); + + return g_sess.payload_len; +} + +const char *packet_get_payload(const struct packet *pkt) +{ + UNUSED(pkt); + + return g_sess.payload; +} + +enum session_direction session_get_direction(const struct session *sess) +{ + UNUSED(sess); + + return SESSION_DIRECTION_OUTBOUND; +} + +enum flow_type session_get_flow_type(const struct session *sess) +{ + UNUSED(sess); + + return FLOW_TYPE_C2S; +} + +const char *session_get0_readable_addr(const struct session *sess) +{ + UNUSED(sess); + + return NULL; +} + +uint16_t packet_get_raw_len(const struct packet *pkt) +{ + UNUSED(pkt); + + return 0; +} + +const struct timeval *packet_get_timeval(const struct packet *pkt) +{ + UNUSED(pkt); + + return NULL; +} + +void stellar_session_plugin_dettach_current_session(struct session *sess) +{ + UNUSED(sess); +} + +int session_mq_publish_message(struct session *sess, int topic_id, void *msg) +{ + UNUSED(sess); + UNUSED(topic_id); + UNUSED(msg); + + return 0; +} + +int stellar_exdata_new_index(struct stellar *st, const char *name, stellar_exdata_free *free_func,void *arg) +{ + UNUSED(st); + UNUSED(name); + UNUSED(free_func); + UNUSED(arg); + + return 0; +} + +int stellar_mq_create_topic(struct stellar *st, const char *topic_name, stellar_msg_free_cb_func *msg_free_cb, void *msg_free_arg) +{ + UNUSED(st); + UNUSED(topic_name); + UNUSED(msg_free_cb); + UNUSED(msg_free_arg); + + return 0; +} + +int stellar_mq_get_topic_id(struct stellar *st, const char *topic_name) +{ + UNUSED(st); + + if (strcmp(topic_name, TOPIC_TCP_INPUT) == 0) + { + return DUMMY_TCP_TOPIC_ID; + } + else if (strcmp(topic_name, TOPIC_UDP_INPUT) == 0) + { + return DUMMY_UDP_TOPIC_ID; + } + else + { + return -1; + } +} + +int stellar_session_mq_subscribe(struct stellar *st, int topic_id, on_session_msg_cb_func *plugin_on_msg_cb, int plugin_id) +{ + UNUSED(st); + UNUSED(topic_id); + UNUSED(plugin_on_msg_cb); + UNUSED(plugin_id); + + return 0; +} + +int stellar_session_plugin_register(struct stellar *st, session_ctx_new_func session_ctx_new, session_ctx_free_func session_ctx_free, void *plugin_env) +{ + UNUSED(st); + UNUSED(session_ctx_new); + UNUSED(session_ctx_free); + UNUSED(plugin_env); + + return 0; +}
\ No newline at end of file diff --git a/test/decoders/session_flags/dummy.h b/test/decoders/session_flags/dummy.h new file mode 100644 index 0000000..aec8383 --- /dev/null +++ b/test/decoders/session_flags/dummy.h @@ -0,0 +1,18 @@ +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" + +#define DUMMY_TCP_TOPIC_ID 1 +#define DUMMY_UDP_TOPIC_ID 2 + +struct session //stub just for test +{ + int payload_len; + char *payload; +}; + +void session_set_current_payload(struct session *sess, char *payload, int payload_len); + +void *session_flags_plugin_init(struct stellar *st); +void session_flags_plugin_exit(void *arg);
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/1-dtls.192.168.44.32.pcap b/test/decoders/session_flags/pcap/1-dtls.192.168.44.32.pcap Binary files differnew file mode 100644 index 0000000..4fa6ce4 --- /dev/null +++ b/test/decoders/session_flags/pcap/1-dtls.192.168.44.32.pcap diff --git a/test/decoders/session_flags/pcap/192.168.56.19.56554.json b/test/decoders/session_flags/pcap/192.168.56.19.56554.json new file mode 100644 index 0000000..78d1fd1 --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.56.19.56554.json @@ -0,0 +1,20 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":4}", + "common_flags_2": 2123980808, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":4,\"frequency\":6,\"runs\":6,\"longest_run\":6,\"overlapping_template_matching\":6,\"random_excursions\":6,\"random_excursions_variant\":6,\"poker_detect\":6,\"runs_distribution\":6,\"self_correlation\":6,\"binary_derivative\":6}", + "common_flags_3": 2123980936, + "common_flags_str_3": "[Client is Local,Inbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":21,\"C2S\":1,\"S2C\":4,\"frequency\":6,\"runs\":6,\"longest_run\":6,\"overlapping_template_matching\":6,\"random_excursions\":6,\"random_excursions_variant\":6,\"poker_detect\":6,\"runs_distribution\":6,\"self_correlation\":6,\"binary_derivative\":6}", + "common_flags_4": 2123981960, + "common_flags_str_4": "[Client is Local,Inbound,Streaming]", + "common_flags_identify_info_4": "{\"Client is Local\":1,\"Inbound\":21,\"Streaming\":100,\"C2S\":1,\"S2C\":4,\"frequency\":6,\"runs\":6,\"longest_run\":6,\"overlapping_template_matching\":6,\"random_excursions\":6,\"random_excursions_variant\":6,\"poker_detect\":6,\"runs_distribution\":6,\"self_correlation\":6,\"binary_derivative\":6}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/192.168.56.19.56555-47.93.59.84.443_869284834001082715.pcapng b/test/decoders/session_flags/pcap/192.168.56.19.56555-47.93.59.84.443_869284834001082715.pcapng Binary files differnew file mode 100644 index 0000000..b675a02 --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.56.19.56555-47.93.59.84.443_869284834001082715.pcapng diff --git a/test/decoders/session_flags/pcap/192.168.56.31.58530.json b/test/decoders/session_flags/pcap/192.168.56.31.58530.json new file mode 100644 index 0000000..67acb45 --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.56.31.58530.json @@ -0,0 +1,17 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2}", + "common_flags_2": 1185898504, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"frequency\":4,\"block_frequency\":4,\"cumulative_sums\":4,\"runs\":4,\"rank\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"binary_derivative\":4}", + "common_flags_3": 1185898632, + "common_flags_str_3": "[Client is Local,Inbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":34,\"C2S\":1,\"S2C\":2,\"frequency\":4,\"block_frequency\":4,\"cumulative_sums\":4,\"runs\":4,\"rank\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"binary_derivative\":4}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/192.168.56.31.58530.pcapng b/test/decoders/session_flags/pcap/192.168.56.31.58530.pcapng Binary files differnew file mode 100644 index 0000000..6abe0ed --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.56.31.58530.pcapng diff --git a/test/decoders/session_flags/pcap/192.168.64.61.62275.asymmetric.pcapng b/test/decoders/session_flags/pcap/192.168.64.61.62275.asymmetric.pcapng Binary files differnew file mode 100644 index 0000000..afff17d --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.64.61.62275.asymmetric.pcapng diff --git a/test/decoders/session_flags/pcap/192.168.64.61.62275.json b/test/decoders/session_flags/pcap/192.168.64.61.62275.json new file mode 100644 index 0000000..ea68bf3 --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.64.61.62275.json @@ -0,0 +1,14 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 1453269000, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"frequency\":3,\"block_frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"runs_distribution\":3,\"binary_derivative\":3}", + "common_flags_2": 1453269001, + "common_flags_str_2": "[Asymmetric,Client is Local]", + "common_flags_identify_info_2": "{\"Asymmetric\":10,\"Client is Local\":1,\"C2S\":1,\"frequency\":3,\"block_frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"runs_distribution\":3,\"binary_derivative\":3}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/192.168.64.67.53813.json b/test/decoders/session_flags/pcap/192.168.64.67.53813.json new file mode 100644 index 0000000..6893c7f --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.64.67.53813.json @@ -0,0 +1,14 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 2126340104, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_2": 2126340232, + "common_flags_str_2": "[Client is Local,Inbound]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"Inbound\":18,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/192.168.64.67.53813.pcapng b/test/decoders/session_flags/pcap/192.168.64.67.53813.pcapng Binary files differnew file mode 100644 index 0000000..ffb6287 --- /dev/null +++ b/test/decoders/session_flags/pcap/192.168.64.67.53813.pcapng diff --git a/test/decoders/session_flags/pcap/1_result.json b/test/decoders/session_flags/pcap/1_result.json new file mode 100644 index 0000000..57df72d --- /dev/null +++ b/test/decoders/session_flags/pcap/1_result.json @@ -0,0 +1,11 @@ +[ + { + "common_flags_0": 8208, + "common_flags_str_0": "[Server is Local,C2S]", + "common_flags_identify_info_0": "1,1,", + "common_flags_1": 24592, + "common_flags_str_1": "[Server is Local,C2S,S2C]", + "common_flags_identify_info_1": "1,1,2,", + "name": "session_flags_test" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/bilibili-dtls.pcap b/test/decoders/session_flags/pcap/bilibili-dtls.pcap Binary files differnew file mode 100644 index 0000000..9316c01 --- /dev/null +++ b/test/decoders/session_flags/pcap/bilibili-dtls.pcap diff --git a/test/decoders/session_flags/pcap/bilibili.json b/test/decoders/session_flags/pcap/bilibili.json new file mode 100644 index 0000000..640957c --- /dev/null +++ b/test/decoders/session_flags/pcap/bilibili.json @@ -0,0 +1,23 @@ +[ + { + "common_flags_0": 16392, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"S2C\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":2,\"S2C\":1}", + "common_flags_2": 1585602568, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":2,\"S2C\":1,\"block_frequency\":5,\"overlapping_template_matching\":5,\"random_excursions\":5,\"random_excursions_variant\":5,\"poker_detect\":5,\"runs_distribution\":5,\"binary_derivative\":5}", + "common_flags_3": 1585602696, + "common_flags_str_3": "[Client is Local,Inbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":25,\"C2S\":2,\"S2C\":1,\"block_frequency\":5,\"overlapping_template_matching\":5,\"random_excursions\":5,\"random_excursions_variant\":5,\"poker_detect\":5,\"runs_distribution\":5,\"binary_derivative\":5}", + "common_flags_4": 1585603720, + "common_flags_str_4": "[Client is Local,Inbound,Streaming]", + "common_flags_identify_info_4": "{\"Client is Local\":1,\"Inbound\":25,\"Streaming\":186,\"C2S\":2,\"S2C\":1,\"block_frequency\":5,\"overlapping_template_matching\":5,\"random_excursions\":5,\"random_excursions_variant\":5,\"poker_detect\":5,\"runs_distribution\":5,\"binary_derivative\":5}", + "common_flags_5": 1585636488, + "common_flags_str_5": "[Client is Local,Inbound,Streaming,Bidirectional]", + "common_flags_identify_info_5": "{\"Client is Local\":1,\"Inbound\":25,\"Streaming\":186,\"C2S\":2,\"S2C\":1,\"Bidirectional\":8551,\"block_frequency\":5,\"overlapping_template_matching\":5,\"random_excursions\":5,\"random_excursions_variant\":5,\"poker_detect\":5,\"runs_distribution\":5,\"binary_derivative\":5}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/dns_asymmetric.json b/test/decoders/session_flags/pcap/dns_asymmetric.json new file mode 100644 index 0000000..3b3510b --- /dev/null +++ b/test/decoders/session_flags/pcap/dns_asymmetric.json @@ -0,0 +1,14 @@ +[ + { + "common_flags_0": 8208, + "common_flags_str_0": "[Server is Local]", + "common_flags_identify_info_0": "{\"Server is Local\":1,\"C2S\":1}", + "common_flags_1": 8209, + "common_flags_str_1": "[Asymmetric,Server is Local]", + "common_flags_identify_info_1": "{\"Asymmetric\":10,\"Server is Local\":1,\"C2S\":1}", + "common_flags_2": 24593, + "common_flags_str_2": "[Asymmetric,Server is Local]", + "common_flags_identify_info_2": "{\"Asymmetric\":10,\"Server is Local\":1,\"C2S\":1,\"S2C\":12}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/dns_asymmetric.pcap b/test/decoders/session_flags/pcap/dns_asymmetric.pcap Binary files differnew file mode 100644 index 0000000..116934f --- /dev/null +++ b/test/decoders/session_flags/pcap/dns_asymmetric.pcap diff --git a/test/decoders/session_flags/pcap/douyin.json b/test/decoders/session_flags/pcap/douyin.json new file mode 100644 index 0000000..739d1db --- /dev/null +++ b/test/decoders/session_flags/pcap/douyin.json @@ -0,0 +1,20 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2}", + "common_flags_2": 2124242952, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"frequency\":4,\"cumulative_sums\":4,\"runs\":4,\"longest_run\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"poker_detect\":4,\"runs_distribution\":4,\"self_correlation\":4,\"binary_derivative\":4}", + "common_flags_3": 2124244104, + "common_flags_str_3": "[Client is Local,Inbound,Streaming]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":6036,\"Streaming\":6036,\"C2S\":1,\"S2C\":2,\"frequency\":4,\"cumulative_sums\":4,\"runs\":4,\"longest_run\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"poker_detect\":4,\"runs_distribution\":4,\"self_correlation\":4,\"binary_derivative\":4}", + "common_flags_4": 2124244650, + "common_flags_str_4": "[Bulky,Client is Local,Download,Inbound,Pseudo Unidirectional,Streaming]", + "common_flags_identify_info_4": "{\"Bulky\":6042,\"Client is Local\":1,\"Download\":6042,\"Inbound\":6036,\"Pseudo Unidirectional\":6042,\"Streaming\":6036,\"C2S\":1,\"S2C\":2,\"frequency\":4,\"cumulative_sums\":4,\"runs\":4,\"longest_run\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"poker_detect\":4,\"runs_distribution\":4,\"self_correlation\":4,\"binary_derivative\":4}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/douyin.pcap b/test/decoders/session_flags/pcap/douyin.pcap Binary files differnew file mode 100644 index 0000000..89e08d3 --- /dev/null +++ b/test/decoders/session_flags/pcap/douyin.pcap diff --git a/test/decoders/session_flags/pcap/ftp-data.pcap b/test/decoders/session_flags/pcap/ftp-data.pcap Binary files differnew file mode 100644 index 0000000..9517dde --- /dev/null +++ b/test/decoders/session_flags/pcap/ftp-data.pcap diff --git a/test/decoders/session_flags/pcap/https_download.json b/test/decoders/session_flags/pcap/https_download.json new file mode 100644 index 0000000..b0f735d --- /dev/null +++ b/test/decoders/session_flags/pcap/https_download.json @@ -0,0 +1,26 @@ +[{ + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local,C2S]", + "common_flags_identify_info_0": "1,1,", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local,C2S,S2C]", + "common_flags_identify_info_1": "1,1,2,", + "common_flags_2": 28680, + "common_flags_str_2": "[Client is Local,Random Looking,C2S,S2C]", + "common_flags_identify_info_2": "1,4,1,2,", + "common_flags_3": 28808, + "common_flags_str_3": "[Client is Local,Inbound,Random Looking,C2S,S2C]", + "common_flags_identify_info_3": "1,1188,4,1,2,", + "common_flags_4": 29832, + "common_flags_str_4": "[Client is Local,Inbound,Streaming,Random Looking,C2S,S2C]", + "common_flags_identify_info_4": "1,1188,1662,4,1,2,", + "common_flags_5": 30344, + "common_flags_str_5": "[Client is Local,Inbound,Pseudo Unidirectional,Streaming,Random Looking,C2S,S2C]", + "common_flags_identify_info_5": "1,1188,3546,1662,4,1,2,", + "common_flags_6": 30346, + "common_flags_str_6": "[Bulky,Client is Local,Inbound,Pseudo Unidirectional,Streaming,Random Looking,C2S,S2C]", + "common_flags_identify_info_6": "4095,1,1188,3546,1662,4,1,2,", + "common_flags_7": 30378, + "common_flags_str_7": "[Bulky,Client is Local,Download,Inbound,Pseudo Unidirectional,Streaming,Random Looking,C2S,S2C]", + "common_flags_identify_info_7": "4095,1,4201,1188,3546,1662,4,1,2," +}]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/https_download.pcap b/test/decoders/session_flags/pcap/https_download.pcap Binary files differnew file mode 100644 index 0000000..f2f5835 --- /dev/null +++ b/test/decoders/session_flags/pcap/https_download.pcap diff --git a/test/decoders/session_flags/pcap/mix-quic-ssl-quic-mail.pcap b/test/decoders/session_flags/pcap/mix-quic-ssl-quic-mail.pcap Binary files differnew file mode 100644 index 0000000..05f2d03 --- /dev/null +++ b/test/decoders/session_flags/pcap/mix-quic-ssl-quic-mail.pcap diff --git a/test/decoders/session_flags/pcap/mix.json b/test/decoders/session_flags/pcap/mix.json new file mode 100644 index 0000000..e3144b6 --- /dev/null +++ b/test/decoders/session_flags/pcap/mix.json @@ -0,0 +1,65 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2}", + "common_flags_2": 109076488, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4}", + "common_flags_3": 109078186, + "common_flags_str_3": "[Bulky,Client is Local,Download,Inbound,Pseudo Unidirectional,Streaming]", + "common_flags_identify_info_3": "{\"Bulky\":2250,\"Client is Local\":1,\"Download\":2250,\"Inbound\":2250,\"Pseudo Unidirectional\":2250,\"Streaming\":2250,\"C2S\":1,\"S2C\":2,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4}", + "name": "base_0" + }, + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 1451237384, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"overlapping_template_matching\":10,\"random_excursions\":10,\"random_excursions_variant\":10,\"runs_distribution\":10,\"binary_derivative\":10}", + "common_flags_2": 1451237385, + "common_flags_str_2": "[Asymmetric,Client is Local]", + "common_flags_identify_info_2": "{\"Asymmetric\":4168,\"Client is Local\":1,\"C2S\":1,\"overlapping_template_matching\":10,\"random_excursions\":10,\"random_excursions_variant\":10,\"runs_distribution\":10,\"binary_derivative\":10}", + "name": "base_1" + }, + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 2126323720, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_2": 2126340104, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":6,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_3": 2126340232, + "common_flags_str_3": "[Client is Local,Inbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":29,\"C2S\":1,\"S2C\":6,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "name": "base_2" + }, + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 1186291720, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"binary_derivative\":2}", + "common_flags_2": 1186291848, + "common_flags_str_2": "[Client is Local,Inbound]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"Inbound\":21,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"binary_derivative\":2}", + "common_flags_3": 1186292872, + "common_flags_str_3": "[Client is Local,Inbound,Streaming]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":21,\"Streaming\":100,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"binary_derivative\":2}", + "common_flags_4": 1186292874, + "common_flags_str_4": "[Bulky,Client is Local,Inbound,Streaming]", + "common_flags_identify_info_4": "{\"Bulky\":430,\"Client is Local\":1,\"Inbound\":21,\"Streaming\":100,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"binary_derivative\":2}", + "common_flags_5": 1186292878, + "common_flags_str_5": "[Bulky,CBR Streaming,Client is Local,Inbound,Streaming]", + "common_flags_identify_info_5": "{\"Bulky\":430,\"CBR Streaming\":6984,\"Client is Local\":1,\"Inbound\":21,\"Streaming\":100,\"C2S\":1,\"S2C\":2,\"frequency\":2,\"cumulative_sums\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"binary_derivative\":2}", + "name": "base_3" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/quic_asymmetric.json b/test/decoders/session_flags/pcap/quic_asymmetric.json new file mode 100644 index 0000000..68e3e37 --- /dev/null +++ b/test/decoders/session_flags/pcap/quic_asymmetric.json @@ -0,0 +1,17 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 2126323720, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_2": 2126340104, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":14,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_3": 2126340232, + "common_flags_str_3": "[Client is Local,Inbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":84,\"C2S\":1,\"S2C\":14,\"frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/quic_asymmetric.pcapng b/test/decoders/session_flags/pcap/quic_asymmetric.pcapng Binary files differnew file mode 100644 index 0000000..5596a03 --- /dev/null +++ b/test/decoders/session_flags/pcap/quic_asymmetric.pcapng diff --git a/test/decoders/session_flags/pcap/quic_asymmetric_1.json b/test/decoders/session_flags/pcap/quic_asymmetric_1.json new file mode 100644 index 0000000..dab7c23 --- /dev/null +++ b/test/decoders/session_flags/pcap/quic_asymmetric_1.json @@ -0,0 +1,14 @@ +[ + { + "common_flags_0": 16392, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"S2C\":1}", + "common_flags_1": 1452294152, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"S2C\":1,\"longest_run\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"runs_distribution\":2,\"binary_derivative\":2}", + "common_flags_2": 1452294153, + "common_flags_str_2": "[Asymmetric,Client is Local]", + "common_flags_identify_info_2": "{\"Asymmetric\":37,\"Client is Local\":1,\"S2C\":1,\"longest_run\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"runs_distribution\":2,\"binary_derivative\":2}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/quic_asymmetric_1.pcap b/test/decoders/session_flags/pcap/quic_asymmetric_1.pcap Binary files differnew file mode 100644 index 0000000..bb55d52 --- /dev/null +++ b/test/decoders/session_flags/pcap/quic_asymmetric_1.pcap diff --git a/test/decoders/session_flags/pcap/quic_online_streaming.json b/test/decoders/session_flags/pcap/quic_online_streaming.json new file mode 100644 index 0000000..443d331 --- /dev/null +++ b/test/decoders/session_flags/pcap/quic_online_streaming.json @@ -0,0 +1,26 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 2124226568, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"poker_detect\":3,\"runs_distribution\":3,\"self_correlation\":3,\"binary_derivative\":3}", + "common_flags_2": 2124242952, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":4,\"frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"poker_detect\":3,\"runs_distribution\":3,\"self_correlation\":3,\"binary_derivative\":3}", + "common_flags_3": 2124244104, + "common_flags_str_3": "[Client is Local,Inbound,Streaming]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Inbound\":291,\"Streaming\":291,\"C2S\":1,\"S2C\":4,\"frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"poker_detect\":3,\"runs_distribution\":3,\"self_correlation\":3,\"binary_derivative\":3}", + "common_flags_4": 2124244106, + "common_flags_str_4": "[Bulky,Client is Local,Inbound,Streaming]", + "common_flags_identify_info_4": "{\"Bulky\":630,\"Client is Local\":1,\"Inbound\":291,\"Streaming\":291,\"C2S\":1,\"S2C\":4,\"frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"poker_detect\":3,\"runs_distribution\":3,\"self_correlation\":3,\"binary_derivative\":3}", + "common_flags_5": 2124276874, + "common_flags_str_5": "[Bulky,Client is Local,Inbound,Streaming,Bidirectional]", + "common_flags_identify_info_5": "{\"Bulky\":630,\"Client is Local\":1,\"Inbound\":291,\"Streaming\":291,\"C2S\":1,\"S2C\":4,\"Bidirectional\":7315,\"frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"poker_detect\":3,\"runs_distribution\":3,\"self_correlation\":3,\"binary_derivative\":3}", + "common_flags_6": 2124276938, + "common_flags_str_6": "[Bulky,Client is Local,Interactive,Inbound,Streaming,Bidirectional]", + "common_flags_identify_info_6": "{\"Bulky\":630,\"Client is Local\":1,\"Interactive\":25786,\"Inbound\":291,\"Streaming\":291,\"C2S\":1,\"S2C\":4,\"Bidirectional\":7315,\"frequency\":3,\"cumulative_sums\":3,\"runs\":3,\"longest_run\":3,\"overlapping_template_matching\":3,\"random_excursions\":3,\"random_excursions_variant\":3,\"poker_detect\":3,\"runs_distribution\":3,\"self_correlation\":3,\"binary_derivative\":3}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/quic_online_streaming.pcap b/test/decoders/session_flags/pcap/quic_online_streaming.pcap Binary files differnew file mode 100644 index 0000000..9db5c49 --- /dev/null +++ b/test/decoders/session_flags/pcap/quic_online_streaming.pcap diff --git a/test/decoders/session_flags/pcap/ssh-interactive.json b/test/decoders/session_flags/pcap/ssh-interactive.json new file mode 100644 index 0000000..e6a3e40 --- /dev/null +++ b/test/decoders/session_flags/pcap/ssh-interactive.json @@ -0,0 +1,29 @@ +[ + { + "common_flags_0": 8208, + "common_flags_str_0": "[Server is Local]", + "common_flags_identify_info_0": "{\"Server is Local\":1,\"C2S\":1}", + "common_flags_1": 24592, + "common_flags_str_1": "[Server is Local]", + "common_flags_identify_info_1": "{\"Server is Local\":1,\"C2S\":1,\"S2C\":2}", + "common_flags_2": 111173648, + "common_flags_str_2": "[Server is Local]", + "common_flags_identify_info_2": "{\"Server is Local\":1,\"C2S\":1,\"S2C\":2,\"rank\":7,\"overlapping_template_matching\":7,\"random_excursions\":7,\"random_excursions_variant\":7}", + "common_flags_3": 111173904, + "common_flags_str_3": "[Server is Local,Outbound]", + "common_flags_identify_info_3": "{\"Server is Local\":1,\"Outbound\":40,\"C2S\":1,\"S2C\":2,\"rank\":7,\"overlapping_template_matching\":7,\"random_excursions\":7,\"random_excursions_variant\":7}", + "common_flags_4": 111173968, + "common_flags_str_4": "[Server is Local,Interactive,Outbound]", + "common_flags_identify_info_4": "{\"Server is Local\":1,\"Interactive\":52,\"Outbound\":40,\"C2S\":1,\"S2C\":2,\"rank\":7,\"overlapping_template_matching\":7,\"random_excursions\":7,\"random_excursions_variant\":7}", + "name": "base_0" + }, + { + "common_flags_0": 16400, + "common_flags_str_0": "[Server is Local]", + "common_flags_identify_info_0": "{\"Server is Local\":1,\"S2C\":1}", + "common_flags_1": 16401, + "common_flags_str_1": "[Asymmetric,Server is Local]", + "common_flags_identify_info_1": "{\"Asymmetric\":2,\"Server is Local\":1,\"S2C\":1}", + "name": "base_1" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/ssh-interactive.pcap b/test/decoders/session_flags/pcap/ssh-interactive.pcap Binary files differnew file mode 100644 index 0000000..6efe2ab --- /dev/null +++ b/test/decoders/session_flags/pcap/ssh-interactive.pcap diff --git a/test/decoders/session_flags/pcap/telegram_mtproto_ipv4_key_1.pcap b/test/decoders/session_flags/pcap/telegram_mtproto_ipv4_key_1.pcap Binary files differnew file mode 100644 index 0000000..7b966dd --- /dev/null +++ b/test/decoders/session_flags/pcap/telegram_mtproto_ipv4_key_1.pcap diff --git a/test/decoders/session_flags/pcap/telegram_mtproto_ipv6_key_1.pcap b/test/decoders/session_flags/pcap/telegram_mtproto_ipv6_key_1.pcap Binary files differnew file mode 100644 index 0000000..e0b3144 --- /dev/null +++ b/test/decoders/session_flags/pcap/telegram_mtproto_ipv6_key_1.pcap diff --git a/test/decoders/session_flags/pcap/tencent_meeting_video.json b/test/decoders/session_flags/pcap/tencent_meeting_video.json new file mode 100644 index 0000000..bb29da4 --- /dev/null +++ b/test/decoders/session_flags/pcap/tencent_meeting_video.json @@ -0,0 +1,23 @@ +[ + { + "common_flags_0": 16392, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"S2C\":1}", + "common_flags_1": 2126462984, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"S2C\":1,\"frequency\":2,\"block_frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_2": 2126471176, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":5,\"S2C\":1,\"frequency\":2,\"block_frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_3": 2126471432, + "common_flags_str_3": "[Client is Local,Outbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Outbound\":414,\"C2S\":5,\"S2C\":1,\"frequency\":2,\"block_frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_4": 2126504200, + "common_flags_str_4": "[Client is Local,Outbound,Bidirectional]", + "common_flags_identify_info_4": "{\"Client is Local\":1,\"Outbound\":414,\"C2S\":5,\"S2C\":1,\"Bidirectional\":2448,\"frequency\":2,\"block_frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_5": 2126504204, + "common_flags_str_5": "[CBR Streaming,Client is Local,Outbound,Bidirectional]", + "common_flags_identify_info_5": "{\"CBR Streaming\":4095,\"Client is Local\":1,\"Outbound\":414,\"C2S\":5,\"S2C\":1,\"Bidirectional\":2448,\"frequency\":2,\"block_frequency\":2,\"cumulative_sums\":2,\"runs\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/tencent_meeting_video.pcapng b/test/decoders/session_flags/pcap/tencent_meeting_video.pcapng Binary files differnew file mode 100644 index 0000000..6013cfb --- /dev/null +++ b/test/decoders/session_flags/pcap/tencent_meeting_video.pcapng diff --git a/test/decoders/session_flags/pcap/tencent_meeting_voice.json b/test/decoders/session_flags/pcap/tencent_meeting_voice.json new file mode 100644 index 0000000..a81e3c5 --- /dev/null +++ b/test/decoders/session_flags/pcap/tencent_meeting_voice.json @@ -0,0 +1,20 @@ +[ + { + "common_flags_0": 16392, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"S2C\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":2,\"S2C\":1}", + "common_flags_2": 2123980808, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":2,\"S2C\":1,\"frequency\":4,\"runs\":4,\"longest_run\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"poker_detect\":4,\"runs_distribution\":4,\"self_correlation\":4,\"binary_derivative\":4}", + "common_flags_3": 2123981064, + "common_flags_str_3": "[Client is Local,Outbound]", + "common_flags_identify_info_3": "{\"Client is Local\":1,\"Outbound\":21,\"C2S\":2,\"S2C\":1,\"frequency\":4,\"runs\":4,\"longest_run\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"poker_detect\":4,\"runs_distribution\":4,\"self_correlation\":4,\"binary_derivative\":4}", + "common_flags_4": 2124013832, + "common_flags_str_4": "[Client is Local,Outbound,Bidirectional]", + "common_flags_identify_info_4": "{\"Client is Local\":1,\"Outbound\":21,\"C2S\":2,\"S2C\":1,\"Bidirectional\":606,\"frequency\":4,\"runs\":4,\"longest_run\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"poker_detect\":4,\"runs_distribution\":4,\"self_correlation\":4,\"binary_derivative\":4}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/tencent_meeting_voice.pcapng b/test/decoders/session_flags/pcap/tencent_meeting_voice.pcapng Binary files differnew file mode 100644 index 0000000..2935fe5 --- /dev/null +++ b/test/decoders/session_flags/pcap/tencent_meeting_voice.pcapng diff --git a/test/decoders/session_flags/pcap/tls1.2.pcapng b/test/decoders/session_flags/pcap/tls1.2.pcapng Binary files differnew file mode 100644 index 0000000..ad1a1e0 --- /dev/null +++ b/test/decoders/session_flags/pcap/tls1.2.pcapng diff --git a/test/decoders/session_flags/pcap/tls1.2_no_reuse.pcap b/test/decoders/session_flags/pcap/tls1.2_no_reuse.pcap Binary files differnew file mode 100644 index 0000000..e911f2b --- /dev/null +++ b/test/decoders/session_flags/pcap/tls1.2_no_reuse.pcap diff --git a/test/decoders/session_flags/pcap/tls_over_tls_1.2_no_reuse.pcap b/test/decoders/session_flags/pcap/tls_over_tls_1.2_no_reuse.pcap Binary files differnew file mode 100644 index 0000000..9deb86f --- /dev/null +++ b/test/decoders/session_flags/pcap/tls_over_tls_1.2_no_reuse.pcap diff --git a/test/decoders/session_flags/pcap/unidirectional.json b/test/decoders/session_flags/pcap/unidirectional.json new file mode 100644 index 0000000..a681f54 --- /dev/null +++ b/test/decoders/session_flags/pcap/unidirectional.json @@ -0,0 +1,14 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 24584, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2}", + "common_flags_2": 1185898504, + "common_flags_str_2": "[Client is Local]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"frequency\":4,\"block_frequency\":4,\"cumulative_sums\":4,\"runs\":4,\"rank\":4,\"overlapping_template_matching\":4,\"random_excursions\":4,\"random_excursions_variant\":4,\"binary_derivative\":4}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/unidirectional.pcap b/test/decoders/session_flags/pcap/unidirectional.pcap Binary files differnew file mode 100644 index 0000000..9e7b65a --- /dev/null +++ b/test/decoders/session_flags/pcap/unidirectional.pcap diff --git a/test/decoders/session_flags/pcap/wechat_voice_call.json b/test/decoders/session_flags/pcap/wechat_voice_call.json new file mode 100644 index 0000000..a2077d6 --- /dev/null +++ b/test/decoders/session_flags/pcap/wechat_voice_call.json @@ -0,0 +1,20 @@ +[ + { + "common_flags_0": 8208, + "common_flags_str_0": "[Server is Local]", + "common_flags_identify_info_0": "{\"Server is Local\":1,\"C2S\":1}", + "common_flags_1": 2123390992, + "common_flags_str_1": "[Server is Local]", + "common_flags_identify_info_1": "{\"Server is Local\":1,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_2": 2123391120, + "common_flags_str_2": "[Server is Local,Inbound]", + "common_flags_identify_info_2": "{\"Server is Local\":1,\"Inbound\":83,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_3": 2123391124, + "common_flags_str_3": "[CBR Streaming,Server is Local,Inbound]", + "common_flags_identify_info_3": "{\"CBR Streaming\":3634,\"Server is Local\":1,\"Inbound\":83,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_4": 2123423892, + "common_flags_str_4": "[CBR Streaming,Server is Local,Inbound,Bidirectional]", + "common_flags_identify_info_4": "{\"CBR Streaming\":3634,\"Server is Local\":1,\"Inbound\":83,\"C2S\":1,\"S2C\":2,\"Bidirectional\":3808,\"longest_run\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"poker_detect\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/pcap/wechat_voice_call.pcap b/test/decoders/session_flags/pcap/wechat_voice_call.pcap Binary files differnew file mode 100644 index 0000000..4690892 --- /dev/null +++ b/test/decoders/session_flags/pcap/wechat_voice_call.pcap diff --git a/test/decoders/session_flags/pcap/youtube-quic.pcap b/test/decoders/session_flags/pcap/youtube-quic.pcap Binary files differnew file mode 100644 index 0000000..b6ae0cd --- /dev/null +++ b/test/decoders/session_flags/pcap/youtube-quic.pcap diff --git a/test/decoders/session_flags/pcap/youtube.json b/test/decoders/session_flags/pcap/youtube.json new file mode 100644 index 0000000..6c055db --- /dev/null +++ b/test/decoders/session_flags/pcap/youtube.json @@ -0,0 +1,20 @@ +[ + { + "common_flags_0": 8200, + "common_flags_str_0": "[Client is Local]", + "common_flags_identify_info_0": "{\"Client is Local\":1,\"C2S\":1}", + "common_flags_1": 1991270408, + "common_flags_str_1": "[Client is Local]", + "common_flags_identify_info_1": "{\"Client is Local\":1,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_2": 1991271560, + "common_flags_str_2": "[Client is Local,Inbound,Streaming]", + "common_flags_identify_info_2": "{\"Client is Local\":1,\"Inbound\":633,\"Streaming\":633,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_3": 1991271562, + "common_flags_str_3": "[Bulky,Client is Local,Inbound,Streaming]", + "common_flags_identify_info_3": "{\"Bulky\":635,\"Client is Local\":1,\"Inbound\":633,\"Streaming\":633,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "common_flags_4": 1991271566, + "common_flags_str_4": "[Bulky,CBR Streaming,Client is Local,Inbound,Streaming]", + "common_flags_identify_info_4": "{\"Bulky\":635,\"CBR Streaming\":7070,\"Client is Local\":1,\"Inbound\":633,\"Streaming\":633,\"C2S\":1,\"S2C\":2,\"longest_run\":2,\"rank\":2,\"overlapping_template_matching\":2,\"random_excursions\":2,\"random_excursions_variant\":2,\"runs_distribution\":2,\"self_correlation\":2,\"binary_derivative\":2}", + "name": "base_0" + } +]
\ No newline at end of file diff --git a/test/decoders/session_flags/plugin_test_main.cpp b/test/decoders/session_flags/plugin_test_main.cpp new file mode 100644 index 0000000..8f3d996 --- /dev/null +++ b/test/decoders/session_flags/plugin_test_main.cpp @@ -0,0 +1,135 @@ +#include "cJSON.h" +#include <gtest/gtest.h> +#include <unistd.h> +#include <stdio.h> +#include <assert.h> + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "stellar/stellar.h" +#ifdef __cplusplus +} +#endif + +// #define IGNORE_PRINTF +#ifdef IGNORE_PRINTF +#define printf(fmt, ...) (0) +#endif +static cJSON *g_test_result_root = NULL; +static cJSON *g_load_result_root = NULL; +static const char *result_json_path = NULL; + +extern "C" int commit_test_result_json(cJSON *node, const char *name) +{ + (void)name; + if (g_test_result_root) + { + // cJSON_AddItemToObject(g_test_result_root, name, node); + // cJSON_AddStringToObject(node, "name", name); + cJSON_AddItemToArray(g_test_result_root, node); + return 0; + } + return -1; +} + +static cJSON *load_result_from_jsonfile(const char *json_path) +{ + if (json_path == NULL) + return NULL; + + long file_len = 0; + char *file_content = NULL; + FILE *fp = NULL; + + fp = fopen(json_path, "r+"); + if (NULL == fp) + { + return NULL; + } + fseek(fp, 0, SEEK_END); + file_len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (file_len == 0) + { + fclose(fp); + return NULL; + } + file_content = (char *)malloc(file_len + 1); + fread(file_content, file_len, 1, fp); + file_content[file_len] = '\0'; + cJSON *load = cJSON_Parse(file_content); + free(file_content); + fclose(fp); + + return load; +} + +TEST(PROTOCOL, compare_result_json) +{ + EXPECT_EQ(cJSON_GetArraySize(g_test_result_root), cJSON_GetArraySize(g_load_result_root)); + int ret = cJSON_Compare(g_test_result_root, g_load_result_root, 0); + EXPECT_EQ(1, ret); + + if (ret != 1) + { + char *load_json_str = cJSON_Print(g_load_result_root); + printf("LOAD Raw:\n%s\n", load_json_str); + free(load_json_str); + char *result_json_str = cJSON_Print(g_test_result_root); + printf("TEST Raw:\n%s\n", result_json_str); + free(result_json_str); + + cJSON *t_load = g_load_result_root->child, *t_test = g_test_result_root->child; + while (t_load != NULL) + { + ret = cJSON_Compare(t_load, t_test, 0); + if (ret != 1) + { + load_json_str = cJSON_Print(t_load); + printf("LOAD Diff:\n%s\n", load_json_str); + free(load_json_str); + result_json_str = cJSON_Print(t_test); + printf("TEST Diff:\n%s\n", result_json_str); + free(result_json_str); + goto fail; + } + t_load = t_load->next; + t_test = t_test->next; + } + } + cJSON_Delete(g_load_result_root); + cJSON_Delete(g_test_result_root); + return; +fail: + cJSON_Delete(g_load_result_root); + cJSON_Delete(g_test_result_root); + return; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + if (argc < 2) + { + printf("Usage: %s <result_json_path>\n", argv[0]); + result_json_path = NULL; + } + else + { + result_json_path = argv[1]; + g_test_result_root = cJSON_CreateArray(); + g_load_result_root = load_result_from_jsonfile(result_json_path); + assert(g_load_result_root != NULL && g_test_result_root != NULL); + } + ::testing::InitGoogleTest(&argc, argv); + struct stellar *st = stellar_new("./conf/stellar.toml", "./plugin/spec.toml", "./conf/log.toml"); + stellar_run(st); + if (result_json_path != NULL) + { + ret = RUN_ALL_TESTS(); + } + stellar_free(st); + return ret; +} diff --git a/test/decoders/session_flags/session_flags_pcap_test.cpp b/test/decoders/session_flags/session_flags_pcap_test.cpp new file mode 100644 index 0000000..14af115 --- /dev/null +++ b/test/decoders/session_flags/session_flags_pcap_test.cpp @@ -0,0 +1,630 @@ +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <stdio.h> +#include <stdlib.h> +#include <stellar/session.h> +#include <time.h> +#include <pcap/pcap.h> +#include <pcap/sll.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "session_flags_internal.h" +#include "gtest/gtest.h" +extern "C" { +#include "dummy.h" +} + +#define MAC_FRAME_HEADER_LEN 14 +#define IP_HEADER_LEN 20 +#define TCP_HEADER_LEN 20 +#define UDP_HEADER_LEN 8 +#define LINUX_COOKED_CAPTURE 20 + +struct pcap_loop_arg +{ + pcap_t *pcap_handle; + struct session_flags_ctx *ctx; +}; + +struct session_flags_plugin_info *sf_plugin_info = NULL; + +extern int MESA_dir_link_to_human(int link_route_dir); +extern char *session_flags_generate_firewall_message(uint64_t flags, uint32_t identify[session_flags_all_mask]); + +static inline size_t ts2ms(const timeval *ts) +{ + return ts->tv_sec * 1000 + ts->tv_usec / 1000; +} + +static void pcap_handle_cb(pcap_loop_arg *userarg, const struct pcap_pkthdr *pkthdr, const u_char *packet) +{ + struct pcap_loop_arg *arg = (struct pcap_loop_arg *)userarg; + struct session sess; + int payload_len = 0; + char *payload = NULL; + unsigned short sport, dport; + unsigned short eth_proto_type; + unsigned char *ip_header; + int topic_id = 0; + + memset(&sess, 0, sizeof(sess)); + + int data_link_type = pcap_datalink(arg->pcap_handle); + switch (data_link_type) { + case DLT_EN10MB: + eth_proto_type = ntohs(*(unsigned short *)(packet + 12)); + ip_header = (unsigned char *)(packet + sizeof(struct ethhdr)); + break; + case 276://DLT_LINUX_SLL2 + eth_proto_type = ntohs(*(unsigned short *)packet); + ip_header = (unsigned char *)(packet + LINUX_COOKED_CAPTURE); + break; + default: + return; + } + + if (eth_proto_type == ETH_P_IP) { + int l4_proto = *(unsigned char *)(ip_header + 9); + if (l4_proto == IPPROTO_TCP) { + topic_id = DUMMY_TCP_TOPIC_ID; + int ip_total_len = ntohs(*(unsigned short *)(ip_header + 2)); + int ip_header_len = (*(unsigned char *)ip_header & 0x0f) * 4; + int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(iphdr) + 12) & 0xf0) >> 4); + payload_len = ip_total_len - ip_header_len - tcp_header_len; + payload = (char *)ip_header + ip_header_len + tcp_header_len; + } else if (l4_proto == IPPROTO_UDP) { + topic_id = DUMMY_UDP_TOPIC_ID; + payload_len = pkthdr->caplen - (ip_header - packet) - sizeof(iphdr) - sizeof(struct udphdr); + payload = (char *)ip_header + sizeof(iphdr) + sizeof(struct udphdr); + } else { + return; + } + + sport = ntohs(*(unsigned short *)(ip_header + sizeof(iphdr) + 0)); + dport = ntohs(*(unsigned short *)(ip_header + sizeof(iphdr) + 2)); + + } else if (eth_proto_type == ETH_P_IPV6) { + int l4_proto = *(unsigned char *)(ip_header + 6); + if (l4_proto == IPPROTO_TCP) { + topic_id = DUMMY_TCP_TOPIC_ID; + int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(struct ip6_hdr) + 12) & 0xf0) >> 4); + payload_len = pkthdr->caplen - (ip_header - packet) - sizeof(struct ip6_hdr) - tcp_header_len; + payload = (char *)ip_header + sizeof(struct ip6_hdr) + tcp_header_len; + } else if (l4_proto == IPPROTO_UDP) { + topic_id = DUMMY_UDP_TOPIC_ID; + payload_len = pkthdr->caplen - (ip_header - packet) - sizeof(struct ip6_hdr) - sizeof(struct udphdr); + payload = (char *)ip_header + sizeof(struct ip6_hdr) + sizeof(struct udphdr); + } else { + return; + } + + sport = ntohs(*(unsigned short *)(ip_header + sizeof(struct ip6_hdr) + 0)); + dport = ntohs(*(unsigned short *)(ip_header + sizeof(struct ip6_hdr) + 2)); + } else { + return; + } + + session_set_current_payload(&sess, payload, payload_len); + + if (sport > dport) + { + session_flags(sf_plugin_info, arg->ctx, &sess, topic_id, pkthdr->caplen, FLOW_TYPE_C2S, ts2ms(&pkthdr->ts)); + } + else + { + session_flags(sf_plugin_info, arg->ctx, &sess, topic_id, pkthdr->caplen, FLOW_TYPE_S2C, ts2ms(&pkthdr->ts)); + } + +} + +TEST(session_flags, bulky_and_download) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_BULKY, SESSION_FLAGS_BULKY); + EXPECT_EQ(flags_info->identify[session_flags_bulky_mask], 2333); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_DOWNLOAD, SESSION_FLAGS_DOWNLOAD); + EXPECT_EQ(flags_info->identify[session_flags_download_mask], 2333); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, CBR) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/youtube-quic.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + EXPECT_EQ(flags_info->identify[session_flags_cbr_mask], 3351); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, not_CBR_ftp) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, not_CBR_dtls) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/bilibili-dtls.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, server_is_local) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + // session_flags_ip(sf, inet_addr("192.168.1.1"), inet_addr("127.0.0.1"), inet_addr("192.168.1.1")); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_INBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_LOCAL_SERVER, SESSION_FLAGS_LOCAL_SERVER); + EXPECT_EQ(flags_info->identify[session_flags_local_server_mask], 1); + + EXPECT_NE(flags_info->flags & SESSION_FLAGS_LOCAL_CLIENT, SESSION_FLAGS_LOCAL_CLIENT); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, client_is_local) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_LOCAL_SERVER, SESSION_FLAGS_LOCAL_SERVER); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_LOCAL_CLIENT, SESSION_FLAGS_LOCAL_CLIENT); + EXPECT_EQ(flags_info->identify[session_flags_local_client_mask], 1); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, inbound) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_LOCAL_CLIENT, SESSION_FLAGS_LOCAL_CLIENT); + EXPECT_EQ(flags_info->identify[session_flags_local_client_mask], 1); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_INBOUND, SESSION_FLAGS_INBOUND); + EXPECT_EQ(flags_info->identify[session_flags_inbound_mask], 1834); + + EXPECT_NE(flags_info->flags & SESSION_FLAGS_OUTBOUND, SESSION_FLAGS_OUTBOUND); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_LOCAL_SERVER, SESSION_FLAGS_LOCAL_SERVER); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, outbound) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_INBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_LOCAL_SERVER, SESSION_FLAGS_LOCAL_SERVER); + EXPECT_EQ(flags_info->identify[session_flags_local_server_mask], 1); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_OUTBOUND, SESSION_FLAGS_OUTBOUND); + EXPECT_EQ(flags_info->identify[session_flags_outbound_mask], 1834); + + EXPECT_NE(flags_info->flags & SESSION_FLAGS_LOCAL_CLIENT, SESSION_FLAGS_LOCAL_CLIENT); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_INBOUND, SESSION_FLAGS_INBOUND); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, not_streaming) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/1-dtls.192.168.44.32.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_STREAMING, SESSION_FLAGS_STREAMING); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL, SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_UNIDIRECTIONAL, SESSION_FLAGS_UNIDIRECTIONAL); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, streaming_pseudo_unidirectional_unidirectional) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ftp-data.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_STREAMING, SESSION_FLAGS_STREAMING); + EXPECT_EQ(flags_info->identify[session_flags_streaming_mask], 2333); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL, SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL); + EXPECT_EQ(flags_info->identify[session_flags_pseudo_unidirectional_mask], 2333); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_UNIDIRECTIONAL, SESSION_FLAGS_UNIDIRECTIONAL); + EXPECT_EQ(flags_info->identify[session_flags_unidirectional_mask], 1834); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, interactive) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/ssh-interactive.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_INTERACTIVE, SESSION_FLAGS_INTERACTIVE); + EXPECT_EQ(flags_info->identify[session_flags_interactive_mask], 52); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, not_interactive) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/youtube-quic.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_INTERACTIVE, SESSION_FLAGS_INTERACTIVE); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, random_looking_flags_telegram_mtproto_ipv4_key_1) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/telegram_mtproto_ipv4_key_1.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_RANDOM_LOOKING, SESSION_FLAGS_RANDOM_LOOKING); +#if 0 + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_FREQUENCY, SESSION_FLAGS_FREQUENCY); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_BLOCK_FREQUENCY, SESSION_FLAGS_BLOCK_FREQUENCY); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_CUMULATIVE_SUMS, SESSION_FLAGS_CUMULATIVE_SUMS); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RUNS, SESSION_FLAGS_RUNS); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_LONGEST_RUN, SESSION_FLAGS_LONGEST_RUN); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RANK, 0); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_NON_OVERLAPPING_TEMPLATE_MATCHING, 0); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_OVERLAPPING_TEMPLATE_MATCHING, SESSION_FLAGS_OVERLAPPING_TEMPLATE_MATCHING); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_UNIVERSAL, 0); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RANDOM_EXCURSIONS, SESSION_FLAGS_RANDOM_EXCURSIONS); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RANDOM_EXCURSIONS_VARIANT, SESSION_FLAGS_RANDOM_EXCURSIONS_VARIANT); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_POKER_DETECT, SESSION_FLAGS_POKER_DETECT); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RUNS_DISTRIBUTION, SESSION_FLAGS_RUNS_DISTRIBUTION); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_SELF_CORRELATION, SESSION_FLAGS_SELF_CORRELATION); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_BINARY_DERIVATIVE, SESSION_FLAGS_BINARY_DERIVATIVE); +#endif + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, random_looking_flags_telegram_mtproto_ipv6_key_1) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t * handle = pcap_open_offline("pcap/telegram_mtproto_ipv6_key_1.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_RANDOM_LOOKING, SESSION_FLAGS_RANDOM_LOOKING); + +#if 0 + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_FREQUENCY, SESSION_FLAGS_FREQUENCY); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_BLOCK_FREQUENCY, SESSION_FLAGS_BLOCK_FREQUENCY); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_CUMULATIVE_SUMS, SESSION_FLAGS_CUMULATIVE_SUMS); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RUNS, SESSION_FLAGS_RUNS); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_LONGEST_RUN, SESSION_FLAGS_LONGEST_RUN); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RANK, 0); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_NON_OVERLAPPING_TEMPLATE_MATCHING, 0); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_OVERLAPPING_TEMPLATE_MATCHING, SESSION_FLAGS_OVERLAPPING_TEMPLATE_MATCHING); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_UNIVERSAL, 0); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RANDOM_EXCURSIONS, SESSION_FLAGS_RANDOM_EXCURSIONS); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RANDOM_EXCURSIONS_VARIANT, SESSION_FLAGS_RANDOM_EXCURSIONS_VARIANT); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_POKER_DETECT, SESSION_FLAGS_POKER_DETECT); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_RUNS_DISTRIBUTION, SESSION_FLAGS_RUNS_DISTRIBUTION); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_SELF_CORRELATION, SESSION_FLAGS_SELF_CORRELATION); + EXPECT_EQ(flags_info->random_looking_flags & SESSION_FLAGS_BINARY_DERIVATIVE, SESSION_FLAGS_BINARY_DERIVATIVE); +#endif + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, bidirectional) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t *handle = pcap_open_offline("pcap/wechat_voice_call.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_INBOUND); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_BIDIRECTIONAL, SESSION_FLAGS_BIDIRECTIONAL); + + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, tunneling_tls_fet) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t *handle = pcap_open_offline("pcap/tls1.2_no_reuse.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + tunneling_hs_stream_init(sf_plugin_info, ctx); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_TUNNELING, SESSION_FLAGS_TUNNELING); + + tunneling_hs_stream_free(ctx); + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, tunneling_tls_over_tls) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t *handle = pcap_open_offline("pcap/tls_over_tls_1.2_no_reuse.pcap", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + tunneling_hs_stream_init(sf_plugin_info, ctx); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_TUNNELING, SESSION_FLAGS_TUNNELING); + + tunneling_hs_stream_free(ctx); + pcap_close(handle); + free(ctx); +} + +TEST(session_flags, tunneling_tls) +{ + char error[100]; + struct pcap_loop_arg arg; + struct session_flags_ctx *ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx)); + pcap_t *handle = pcap_open_offline("pcap/tls1.2.pcapng", error); + ASSERT_NE(handle, nullptr); + + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + tunneling_hs_stream_init(sf_plugin_info, ctx); + + memset(&arg, 0, sizeof(arg)); + arg.ctx = ctx; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + + EXPECT_NE(flags_info->flags & SESSION_FLAGS_TUNNELING, SESSION_FLAGS_TUNNELING); + + tunneling_hs_stream_free(ctx); + pcap_close(handle); + free(ctx); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + + sf_plugin_info = (struct session_flags_plugin_info *)session_flags_plugin_init(NULL); + sf_plugin_info->log_handle = NULL; + + int result = RUN_ALL_TESTS(); + + session_flags_plugin_exit(sf_plugin_info); + + return result; +}
\ No newline at end of file diff --git a/test/decoders/session_flags/session_flags_static_test.cpp b/test/decoders/session_flags/session_flags_static_test.cpp new file mode 100644 index 0000000..d415807 --- /dev/null +++ b/test/decoders/session_flags/session_flags_static_test.cpp @@ -0,0 +1,494 @@ +#include <cstring> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <stellar/session.h> +#include "session_flags_internal.h" +#include "gtest/gtest.h" + +extern "C" { +#include "dummy.h" +} + +struct session_flags_plugin_info *sf_plugin_info = NULL; + +TEST(session_flags_static, bulky) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + int cur_time_ms = 1; + for (int i = 0; i < 100; i++) + { + for (int j = 0; j < 96; j++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 1001, FLOW_TYPE_C2S, cur_time_ms); + cur_time_ms++; + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + for (int j = 0; j < 4; j++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 100, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_BULKY, SESSION_FLAGS_BULKY); + EXPECT_EQ(flags_info->identify[session_flags_bulky_mask], 6001); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Bulky\":196,\"Client is Local\":1,\"Outbound\":196,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, download_gt_95) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + int cur_time_ms = 1; + for (int i = 0; i < 100; i++) + { + for (int j = 0; j < 96; j++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 1001, FLOW_TYPE_C2S, cur_time_ms); + cur_time_ms++; + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + for (int j = 0; j < 4; j++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 100, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + } + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_DOWNLOAD, SESSION_FLAGS_DOWNLOAD); + EXPECT_EQ(flags_info->identify[session_flags_download_mask], 6001); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Bulky\":195,\"Client is Local\":1,\"Outbound\":195,\"Streaming\":195,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, download_lt_95) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + int cur_time_ms = 1; + for (int i = 0; i < 100; i++) + { + for (int j = 0; j < 94; j++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 1001, FLOW_TYPE_C2S, cur_time_ms); + cur_time_ms++; + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + for (int j = 0; j < 6; j++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 100, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + } + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_DOWNLOAD, SESSION_FLAGS_DOWNLOAD); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Bulky\":195,\"Client is Local\":1,\"Outbound\":195,\"Streaming\":195,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, CBR_lt_1s) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + int std_bytes = 1000; + int cur_time_ms = 1; + for (int i = 0; i < 100; i++) + { + long delta = random() % 200; + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, std_bytes + delta, FLOW_TYPE_C2S, cur_time_ms++); + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms++); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Bulky\":200,\"Client is Local\":1,\"Download\":200,\"Outbound\":200,\"Pseudo Unidirectional\":200,\"Streaming\":200,\"Unidirectional\":200,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, CBR) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + for (uint64_t cur_time_ms = 1; cur_time_ms < 11000; cur_time_ms += 10) + { + long delta = random() % 200; + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 1000 + delta, FLOW_TYPE_C2S, cur_time_ms); + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + EXPECT_EQ(flags_info->identify[session_flags_cbr_mask], 1001); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Bulky\":201,\"CBR Streaming\":2021,\"Client is Local\":1,\"Download\":201,\"Outbound\":201,\"Pseudo Unidirectional\":201,\"Streaming\":201,\"Unidirectional\":201,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, not_CBR) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + for (uint64_t cur_time_ms = 1, i = 0; cur_time_ms < 10000; cur_time_ms += 500) + { + int delta = (i++ % 10) * 100; + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 100 + delta, FLOW_TYPE_C2S, cur_time_ms); + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ( "{\"Client is Local\":1,\"Outbound\":21,\"Pseudo Unidirectional\":21,\"Unidirectional\":21,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, interactive) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + uint64_t cur_time_ms = 1; + while(cur_time_ms < 60000) + { + long delta = random() % 100; + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 1000 + delta, FLOW_TYPE_C2S, cur_time_ms++); + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms++); + } + while(cur_time_ms < 200000) + { + cur_time_ms += 10000; + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 80, FLOW_TYPE_C2S, cur_time_ms); + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 66, FLOW_TYPE_S2C, cur_time_ms); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_INTERACTIVE, SESSION_FLAGS_INTERACTIVE); + EXPECT_EQ(flags_info->identify[session_flags_interactive_mask], 60009); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ( "{\"Bulky\":1001,\"CBR Streaming\":10021,\"Client is Local\":1,\"Download\":1001,\"Interactive\":60009,\"Outbound\":1001,\"Pseudo Unidirectional\":1001,\"Streaming\":1001,\"Unidirectional\":1001,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, streaming_gt_90) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + session_set_current_payload(&sess, NULL, 100); + for (uint64_t cur_time_ms = 1; cur_time_ms < 10000; cur_time_ms++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 861, FLOW_TYPE_C2S, cur_time_ms); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 139, FLOW_TYPE_S2C, cur_time_ms); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_STREAMING, SESSION_FLAGS_STREAMING); + EXPECT_EQ(flags_info->identify[session_flags_streaming_mask], 12001); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Client is Local\":1,\"Outbound\":668,\"Streaming\":669,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, streaming_lt_90) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + session_set_current_payload(&sess, NULL, 100); + for (uint64_t cur_time_ms = 1; cur_time_ms < 10000; cur_time_ms++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 859, FLOW_TYPE_C2S, cur_time_ms); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 141, FLOW_TYPE_S2C, cur_time_ms); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_STREAMING, 0); + EXPECT_EQ(flags_info->identify[session_flags_streaming_mask], 0); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Client is Local\":1,\"Outbound\":668,\"Streaming\":669,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, presu_unidirectional_gt_95) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + uint64_t cur_time_ms = 1; + session_set_current_payload(&sess, NULL, 100); + for (int i = 0; i < 100; i++) + { + for (int j = 0; j < 96; j++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 100 + random() % 1000, FLOW_TYPE_C2S, cur_time_ms); + cur_time_ms++; + } + for (int j = 0; j < 4; j++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 100 + random() % 1000, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL, SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL); + EXPECT_EQ(flags_info->identify[session_flags_pseudo_unidirectional_mask], 6001); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ( "{\"Client is Local\":1,\"Outbound\":1002,\"Pseudo Unidirectional\":1002,\"Streaming\":1002,\"C2S\":1,\"S2C\":99}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, presu_unidirectional_lt_95) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + uint64_t cur_time_ms = 1; + session_set_current_payload(&sess, NULL, 100); + for (int i = 0; i < 100; i++) + { + for (int j = 0; j < 94; j++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 100 + random() % 1000, FLOW_TYPE_C2S, cur_time_ms); + cur_time_ms++; + } + for (int j = 0; j < 6; j++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 100 + random() % 1000, FLOW_TYPE_S2C, cur_time_ms); + cur_time_ms++; + } + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL, 0); + EXPECT_EQ(flags_info->identify[session_flags_pseudo_unidirectional_mask], 0); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ( "{\"Client is Local\":1,\"Outbound\":1002,\"Pseudo Unidirectional\":1002,\"Streaming\":1002,\"C2S\":1,\"S2C\":99}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, Unidirectional) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + for (uint64_t cur_time_ms = 1; cur_time_ms < 10000; cur_time_ms++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 100 + random() % 1000, FLOW_TYPE_C2S, cur_time_ms); + + session_set_current_payload(&sess, NULL, 0); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 80, FLOW_TYPE_S2C, cur_time_ms); + } + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_UNIDIRECTIONAL, SESSION_FLAGS_UNIDIRECTIONAL); + EXPECT_EQ(flags_info->identify[session_flags_unidirectional_mask], 10001); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL, SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL); + EXPECT_EQ(flags_info->identify[session_flags_pseudo_unidirectional_mask], 12001); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ("{\"Client is Local\":1,\"Outbound\":668,\"Pseudo Unidirectional\":669,\"Unidirectional\":669,\"C2S\":1,\"S2C\":2}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, not_unidirectional) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + srandom(time(NULL)); + uint64_t cur_time_ms = 1; + session_set_current_payload(&sess, NULL, 100); + for (int i = 1; i < 10000; i++) + { + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 100 + random() % 1000, FLOW_TYPE_C2S, cur_time_ms++); + } + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 80, FLOW_TYPE_S2C, cur_time_ms++); + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_UNIDIRECTIONAL, SESSION_FLAGS_UNIDIRECTIONAL); + + struct session_flags_message *msg = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ( "{\"Client is Local\":1, \"Outbound\":10000, \"C2S\":1,\"S2C\":10000}", identify_str); + EXPECT_EQ(msg->packet_sequence_array[0], 1); + EXPECT_EQ(msg->packet_sequence_array[1], 10000); + EXPECT_EQ(msg->packet_sequence_array[2], 1); + EXPECT_EQ(msg->packet_sequence_array[3], 10000); + free(msg->packet_sequence_array); + free(msg); + free(ctx); +} + +TEST(session_flags_static, dns) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + uint64_t cur_time_ms = 1000; + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 72, FLOW_TYPE_C2S, cur_time_ms); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 72, FLOW_TYPE_C2S, cur_time_ms); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 72, FLOW_TYPE_C2S, cur_time_ms+10000); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 72, FLOW_TYPE_C2S, cur_time_ms+10000); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 146, FLOW_TYPE_S2C, cur_time_ms+15000); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_UDP_TOPIC_ID, 72, FLOW_TYPE_C2S, cur_time_ms+15000); + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_NE(flags_info->flags & SESSION_FLAGS_CBR, SESSION_FLAGS_CBR); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_LOCAL_CLIENT, SESSION_FLAGS_LOCAL_CLIENT); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_C2S, SESSION_FLAGS_C2S); + EXPECT_EQ(flags_info->identify[session_flags_c2s_mask], 1); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_S2C, SESSION_FLAGS_S2C); + EXPECT_EQ(flags_info->identify[session_flags_s2c_mask], 5); + + //char *identify_str = session_flags_generate_firewall_message(flags_info->flags, flags_info->identify); + //EXPECT_STREQ( "{\"Client is Local\":1,\"Outbound\":6,\"C2S\":1,\"S2C\":5}", identify_str); + //free(identify_str); + free(ctx); +} + +TEST(session_flags_static, bidirectional) +{ + struct session_flags_ctx *ctx = (struct session_flags_ctx*)calloc(1, sizeof(struct session_flags_ctx)); + struct session sess; + + memset(&sess, 0, sizeof(sess)); + session_flags_stat_init(&ctx->stat, SESSION_DIRECTION_OUTBOUND); + + int cur_time_ms = 1; + session_set_current_payload(&sess, NULL, 100); + for (int i = 0; i < 5000; i++) + { + session_set_current_payload(&sess, NULL, 100); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 100, FLOW_TYPE_C2S, cur_time_ms++); + + session_set_current_payload(&sess, NULL, 99); + session_flags(sf_plugin_info, ctx, &sess, DUMMY_TCP_TOPIC_ID, 99, FLOW_TYPE_S2C, cur_time_ms++); + } + + struct session_flags_result *flags_info = session_flags_get_flags(&ctx->stat); + EXPECT_EQ(flags_info->flags & SESSION_FLAGS_BIDIRECTIONAL, SESSION_FLAGS_BIDIRECTIONAL); + EXPECT_EQ(flags_info->identify[session_flags_bidirectional_mask], 6001); + free(ctx); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + //testing::GTEST_FLAG(filter) = ""; + sf_plugin_info = (struct session_flags_plugin_info *)session_flags_plugin_init(NULL); + sf_plugin_info->log_handle = NULL; + int result = RUN_ALL_TESTS(); + session_flags_plugin_exit(sf_plugin_info); + + return result; +}
\ No newline at end of file diff --git a/test/decoders/session_flags/session_flags_test_plugin.cpp b/test/decoders/session_flags/session_flags_test_plugin.cpp new file mode 100644 index 0000000..27d2377 --- /dev/null +++ b/test/decoders/session_flags/session_flags_test_plugin.cpp @@ -0,0 +1,210 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "cJSON.h" + +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" + +#include "stellar/session_flags.h" + +#ifdef __cplusplus +extern "C" +{ +int commit_test_result_json(cJSON *node, const char *name); +} +#endif + +#define unused(x) ((void)(x)) + +int g_test_session_flags_plugin_id; +int g_session_flags_topic_id; + +int g_receive_msg_count = 0; + +static void session_flags_2_str(uint64_t flags, char *str, int str_len) +{ + if (str == NULL || str_len == 0) + return; + + int offset = 0; + str[0] = '['; + offset += 1; + + if (flags & SESSION_FLAGS_BULKY && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Bulky,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_CBR && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "CBR Streaming,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_LOCAL_CLIENT && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Client is Local,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_LOCAL_SERVER && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Server is Local,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_DOWNLOAD && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Download,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_INTERACTIVE && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Interactive,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_INBOUND && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Inbound,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_OUTBOUND && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Outbound,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Pseudo Unidirectional,"); + offset = strlen(str); + } + + + if (flags & SESSION_FLAGS_STREAMING && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Streaming,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_UNIDIRECTIONAL && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Unidirectional,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_RANDOM_LOOKING && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Random Looking,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_C2S && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "C2S,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_S2C && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "S2C,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_BIDIRECTIONAL && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Bidirectional,"); + offset = strlen(str); + } + + if (flags & SESSION_FLAGS_TUNNELING && str_len > offset) + { + snprintf(&str[offset], str_len-offset, "Tunneling,"); + offset = strlen(str); + } + + + str[offset-1] = ']'; +} + +static void append_json(cJSON *root, struct session_flags_message *sf_message) +{ + char key[128] = {0}; + snprintf(key, 128, "common_flags_%d", g_receive_msg_count); + cJSON_AddNumberToObject(root, (const char *)key, sf_message->flags); + + char str[1024] = {0}; + session_flags_2_str(sf_message->flags, str, 1024); + snprintf(key, 128, "common_flags_str_%d", g_receive_msg_count); + cJSON_AddStringToObject(root, (const char *)key, str); + + char identify_str[1024] = {0}; + int offset = 0; + for (unsigned int i = 0; i < sf_message->array_num; i++) + { + offset += snprintf(identify_str + offset, 1024-offset, "%u,", sf_message->packet_sequence_array[i]); + } + snprintf(key, 128, "common_flags_identify_info_%d", g_receive_msg_count); + cJSON_AddStringToObject(root, (const char *)key, identify_str); + + g_receive_msg_count++; +} + +void test_session_flags_entry(struct session *session, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) +{ + unused(plugin_env); + unused(session); + unused(topic_id); + + if (msg == NULL) + { + return; + } + + struct session_flags_message *sf_message = (struct session_flags_message *)msg; + cJSON *json_root = (cJSON *)per_session_ctx; + + append_json(json_root, sf_message); + +} + +void *ctx_new(struct session *session, void *plugin_env) +{ + unused(plugin_env); + unused(session); + + cJSON *root = cJSON_CreateObject(); + return (void *)root; +} + +void ctx_free(struct session *sess, void *session_ctx, void *plugin_env) +{ + unused(sess); + unused(plugin_env); + + commit_test_result_json((cJSON *)session_ctx, "session_flags_test"); +} + +extern "C" void *SESSION_FLAGS_TEST_PLUG_INIT(struct stellar *st) +{ + g_test_session_flags_plugin_id = stellar_session_plugin_register(st, ctx_new, ctx_free, NULL); + g_session_flags_topic_id = stellar_mq_get_topic_id(st, SESSION_FLAGS_MESSAGE_TOPIC); + + stellar_session_mq_subscribe(st, g_session_flags_topic_id, test_session_flags_entry, g_test_session_flags_plugin_id); + + return NULL; +} + +extern "C" void SESSION_FLAGS_TEST_PLUG_DESTROY(void *ctx) +{ + unused(ctx); + return; +}
\ No newline at end of file diff --git a/test/decoders/session_flags/test_based_on_stellar/CMakeLists.txt b/test/decoders/session_flags/test_based_on_stellar/CMakeLists.txt new file mode 100644 index 0000000..9f4f5ba --- /dev/null +++ b/test/decoders/session_flags/test_based_on_stellar/CMakeLists.txt @@ -0,0 +1,37 @@ +set(DECODER_NAME session_flags) + +set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/test/decoders/session_flags) +set(SAPP_DEVEL_DIR ${TEST_RUN_DIR}/lib) +set(TEST_MAIN session_flags_test_main) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/test) +include_directories(/usr/local/include/cjson) +include_directories(/opt/tsg/framework/include/stellar) +include_directories(/opt/MESA/include/MESA) +include_directories(/opt/tsg/stellar/include/) + +#various ways to add -rdynamic for centos7, centos8, and different cmake version +add_definitions(-rdynamic) +link_directories(${SAPP_DEVEL_DIR}) + +# assemble test env +add_test(NAME SESSION_FLAGS_MKDIR_METRIC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/metrics; mkdir -p ${TEST_RUN_DIR}/plugin; mkdir -p ${TEST_RUN_DIR}/log; mkdir -p ${TEST_RUN_DIR}/pcap") +add_test(NAME SESSION_FLAGS_COPY_SPEC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plugin/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/spec.toml ${TEST_RUN_DIR}/plugin/spec.toml") +add_test(NAME SESSION_FLAGS_COPY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/stellar.toml ${TEST_RUN_DIR}/conf/stellar.toml") +add_test(NAME SESSION_FLAGS_COPY_LOG_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/log.toml ${TEST_RUN_DIR}/conf/log.toml") + +# update plugin to be tested +add_test(NAME SESSION_FLAGS_CP_DECODER_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/decoders/session_flags/session_flags_dyn.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}.so") +add_test(NAME SESSION_FLAGS_CP_DECODER_GTEST_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/decoders/session_flags/${DECODER_NAME}_test.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}_test.so") + +set_tests_properties(SESSION_FLAGS_MKDIR_METRIC SESSION_FLAGS_COPY_SPEC + SESSION_FLAGS_COPY_CONF SESSION_FLAGS_COPY_LOG_CONF + SESSION_FLAGS_CP_DECODER_SO SESSION_FLAGS_CP_DECODER_GTEST_SO + PROPERTIES FIXTURES_SETUP TestFixture) + +set(TEST_PCAP_DIR ${PROJECT_SOURCE_DIR}/test/decoders/session_flags/pcap) + +# run tests +add_test(NAME SESSION_FLAGS_PLUGIN_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/https_download.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_PCAP_DIR}/https_download.json" WORKING_DIRECTORY ${TEST_RUN_DIR}) + diff --git a/test/decoders/session_flags/test_based_on_stellar/env/log.toml b/test/decoders/session_flags/test_based_on_stellar/env/log.toml new file mode 100644 index 0000000..a51abd8 --- /dev/null +++ b/test/decoders/session_flags/test_based_on_stellar/env/log.toml @@ -0,0 +1,4 @@ +[log] +output = "stderr" # stderr, file +file = "log/stellar.log" +level = "ERROR" # TRACE, DEBUG, INFO, WARN, ERROR, FATAL diff --git a/test/decoders/session_flags/test_based_on_stellar/env/session_flags.toml b/test/decoders/session_flags/test_based_on_stellar/env/session_flags.toml new file mode 100644 index 0000000..af62a2b --- /dev/null +++ b/test/decoders/session_flags/test_based_on_stellar/env/session_flags.toml @@ -0,0 +1,9 @@ +[SESSION_FLAGS] +FET_ENABLED=1 +INTERACTIVE_STARTTIME_MS = 10000 +INTERACTIVE_PULSE_NUM = 4 +INTERACTIVE_LATENCY_MS = 5000 +MAIN_DIR_FRONT_N_PKTS = 100 +LARGE_PKTS_INIT_SIZE = 1000 +RANDOM_LOOKING_JUDGE_LIST="{\"random_looking_judge_list\":[ \"frequency\", \"block_frequency\", \"cumulative_sums\", \"runs\", \"longest_run\", \"rank\", \"non_overlapping_template_matching\", \"overlapping_template_matching\", \"universal\", \"random_excursions\", \"random_excursions_variant\", \"poker_detect\", \"runs_distribution\", \"self_correlation\", \"binary_derivative\" ]}" +TUNNELING_PCRE_LIST="{\"tunneling_pcre_list\":[\"(B|C)(d){3,5}(a|b|c|d)(A|B)b(A|B|C|D)\", \"(B|C)(d){3,5}(a|b|c|d)Aa(A|B|C|D)\", \"(B|C)(d){2}(b|c)(A|B)b(A|B|C|D)\", \"(B|C)(d){2}(b|c)Aa(A|B|C|D)\"]}" diff --git a/test/decoders/session_flags/test_based_on_stellar/env/spec.toml b/test/decoders/session_flags/test_based_on_stellar/env/spec.toml new file mode 100644 index 0000000..ead4371 --- /dev/null +++ b/test/decoders/session_flags/test_based_on_stellar/env/spec.toml @@ -0,0 +1,9 @@ +[[plugin]] +path = "./plugin/session_flags.so" +init = "session_flags_plugin_init" +exit = "session_flags_plugin_exit" + +[[plugin]] +path = "./plugin/session_flags_test.so" +init = "SESSION_FLAGS_TEST_PLUG_INIT" +exit = "SESSION_FLAGS_TEST_PLUG_DESTROY" diff --git a/test/decoders/session_flags/test_based_on_stellar/env/stellar.toml b/test/decoders/session_flags/test_based_on_stellar/env/stellar.toml new file mode 100644 index 0000000..308c884 --- /dev/null +++ b/test/decoders/session_flags/test_based_on_stellar/env/stellar.toml @@ -0,0 +1,64 @@ +[instance] + id = 1 # range: [0, 4095] (20 bit) + +[packet_io] + mode = "pcapfile" # pcapfile, pcaplist, marsio + app_symbol = "stellar" + dev_symbol = "nf_0_fw" + pcap_path = "./pcap/test.pcap" + nr_worker_thread = 1 # range: [1, 256] + cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12] + idle_yield_interval_ms = 90 # range: [0, 60000] (ms) + +[ip_reassembly] + enable = 1 + bucket_entries = 32 # range: [1, 4294967295] (must be power of 2) + bucket_num = 1024 # range: [1, 4294967295] + + ip_frag_timeout_ms = 1000 # range: [1, 60000] (ms) + ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms) + ip_frag_expire_polling_limit = 1024 # range: [1, 1024] + +[session_manager] + tcp_session_max = 500 + udp_session_max = 500 + + evict_old_on_tcp_table_limit = 1 # range: [0, 1] + evict_old_on_udp_table_limit = 1 # range: [0, 1] + + expire_period_ms = 0 # range: [0, 60000] (ms) + expire_batch_max = 1024 # range: [1, 1024] + + [session_manager.tcp_timeout_ms] + init = 500 # range: [1, 60000] (ms) + handshake = 500 # range: [1, 60000] (ms) + data = 500 # range: [1, 15999999000] (ms) + half_closed = 500 # range: [1, 604800000] (ms) + time_wait = 500 # range: [1, 600000] (ms) + discard_default = 1000 # range: [1, 15999999000] (ms) + unverified_rst = 500 # range: [1, 600000] (ms) + + [session_manager.udp_timeout_ms] + data = 500 # range: [1, 15999999000] (ms) + discard_default = 500 # range: [1, 15999999000] (ms) + + [session_manager.duplicated_packet_bloom_filter] + enable = 0 + capacity = 1000000 # range: [1, 4294967295] + time_window_ms = 10000 # range: [1, 60000] (ms) + error_rate = 0.00001 # range: [0.0, 1.0] + + [session_manager.evicted_session_bloom_filter] + enable = 0 # range: [0, 1] + capacity = 1000000 # range: [1, 4294967295] + time_window_ms = 10000 # range: [1, 60000] (ms) + error_rate = 0.00001 # range: [0.0, 1.0] + + [session_manager.tcp_reassembly] + enable = 1 # range: [0, 1] + timeout_ms = 100 # range: [1, 60000] (ms) + buffered_segments_max = 256 # range: [2, 4096] per flow + +[stat] + merge_interval_ms = 500 # range: [0, 60000] (ms) + output_interval_ms = 1000 # range: [0, 60000] (ms) diff --git a/test/decoders/socks/CMakeLists.txt b/test/decoders/socks/CMakeLists.txt new file mode 100644 index 0000000..f40930a --- /dev/null +++ b/test/decoders/socks/CMakeLists.txt @@ -0,0 +1,38 @@ +set(DECODER_NAME socks) + +add_library(${DECODER_NAME}_test SHARED socks_decoder_test_plugin.cpp) +add_dependencies(${DECODER_NAME}_test ${DECODER_NAME}) +set_target_properties(${DECODER_NAME}_test PROPERTIES PREFIX "") + +set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/testing) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/src) +include_directories(${CMAKE_BINARY_DIR}/vendors/cjson/src/cjson/include) +include_directories(${PROJECT_SOURCE_DIR}/decoders/socks) +include_directories(${PROJECT_SOURCE_DIR}/include/stellar) + +add_executable(gtest_pcap_socks socks_decoder_pcap_gtest.cpp dummy.c ${PROJECT_SOURCE_DIR}/decoders/socks/socks_decoder.cpp) +target_link_libraries(gtest_pcap_socks gtest logger pcap) + +add_executable(socks_test_main plugin_test_main.cpp) +set_target_properties(socks_test_main + PROPERTIES + LINK_OPTIONS + "-rdynamic" + ) +set_target_properties(socks_test_main + PROPERTIES + LINK_FLAGS + "-rdynamic" + ) +set(LINK_FLAGS "-rdynamic") +target_link_libraries(socks_test_main gtest cjson-static stellar_lib) + +add_subdirectory(test_based_on_stellar) + +#copy pcap file folder to build directory +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pcap DESTINATION ${CMAKE_BINARY_DIR}/test/decoders/socks) + +include(GoogleTest) +gtest_discover_tests(gtest_pcap_socks) diff --git a/test/decoders/socks/dummy.c b/test/decoders/socks/dummy.c new file mode 100644 index 0000000..bd15d44 --- /dev/null +++ b/test/decoders/socks/dummy.c @@ -0,0 +1,151 @@ +#include "dummy.h" + +#define UNUSED(x) (void)(x) + +int direction; + +void session_set_current_state(struct session *sess, enum session_state sess_state) +{ + sess->sess_state = sess_state; + + return; +} +enum session_state session_get_current_state(const struct session *sess) +{ + return sess->sess_state; +} + +void dummy_set_direction(int dir) +{ + direction = dir; +} + +struct logger *stellar_get_logger(struct stellar *st) +{ + UNUSED(st); + + return NULL; +} + +enum flow_type session_get_flow_type(const struct session *sess) +{ + UNUSED(sess); + + return direction; +} + +const struct packet *session_get0_current_packet(const struct session *sess) +{ + UNUSED(sess); + + return NULL; +} + +const char *packet_get_payload(const struct packet *pkt) +{ + UNUSED(pkt); + + return NULL; +} + +uint16_t packet_get_payload_len(const struct packet *pkt) +{ + UNUSED(pkt); + + return 0; +} + +int session_mq_ignore_message(struct session *sess, int topic_id, int plugin_id) +{ + UNUSED(sess); + UNUSED(topic_id); + UNUSED(plugin_id); + + return 0; +} + +int session_exdata_set(struct session *sess, int idx, void *ex_ptr) +{ + UNUSED(sess); + UNUSED(idx); + UNUSED(ex_ptr); + + return 0; +} + +void *session_exdata_get(struct session *sess, int idx) +{ + UNUSED(sess); + UNUSED(idx); + + return NULL; +} + +void stellar_session_plugin_dettach_current_session(struct session *sess) +{ + UNUSED(sess); +} + +int session_mq_publish_message(struct session *sess, int topic_id, void *msg) +{ + UNUSED(sess); + UNUSED(topic_id); + UNUSED(msg); + + return 0; +} + +const char *session_get0_readable_addr(const struct session *sess) +{ + UNUSED(sess); + + return NULL; +} + +int stellar_exdata_new_index(struct stellar *st, const char *name, stellar_exdata_free *free_func,void *arg) +{ + UNUSED(st); + UNUSED(name); + UNUSED(free_func); + UNUSED(arg); + + return 0; +} + +int stellar_mq_create_topic(struct stellar *st, const char *topic_name, stellar_msg_free_cb_func *msg_free_cb, void *msg_free_arg) +{ + UNUSED(st); + UNUSED(topic_name); + UNUSED(msg_free_cb); + UNUSED(msg_free_arg); + + return 0; +} + +int stellar_mq_get_topic_id(struct stellar *st, const char *topic_name) +{ + UNUSED(st); + UNUSED(topic_name); + + return 0; +} + +int stellar_session_mq_subscribe(struct stellar *st, int topic_id, on_session_msg_cb_func *plugin_on_msg_cb, int plugin_id) +{ + UNUSED(st); + UNUSED(topic_id); + UNUSED(plugin_on_msg_cb); + UNUSED(plugin_id); + + return 0; +} + +int stellar_session_plugin_register(struct stellar *st, session_ctx_new_func session_ctx_new, session_ctx_free_func session_ctx_free, void *plugin_env) +{ + UNUSED(st); + UNUSED(session_ctx_new); + UNUSED(session_ctx_free); + UNUSED(plugin_env); + + return 0; +}
\ No newline at end of file diff --git a/test/decoders/socks/dummy.h b/test/decoders/socks/dummy.h new file mode 100644 index 0000000..48f801e --- /dev/null +++ b/test/decoders/socks/dummy.h @@ -0,0 +1,14 @@ +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" + +struct session //stub just for test +{ + enum session_state sess_state; + int payload_len; + char *payload; +}; + +void session_set_current_state(struct session *sess, enum session_state sess_state); +void dummy_set_direction(int dir);
\ No newline at end of file diff --git a/test/decoders/socks/pcap/result.json b/test/decoders/socks/pcap/result.json new file mode 100644 index 0000000..084d449 --- /dev/null +++ b/test/decoders/socks/pcap/result.json @@ -0,0 +1,7 @@ +[{ + "socks_info": { + "version": "SOCKS4", + "dst_addr": "127.0.0.1", + "dst_port": 8888 + } +}]
\ No newline at end of file diff --git a/test/decoders/socks/pcap/socks4.pcap b/test/decoders/socks/pcap/socks4.pcap Binary files differnew file mode 100644 index 0000000..9091236 --- /dev/null +++ b/test/decoders/socks/pcap/socks4.pcap diff --git a/test/decoders/socks/pcap/socks4_nest_socks4a.pcap b/test/decoders/socks/pcap/socks4_nest_socks4a.pcap Binary files differnew file mode 100644 index 0000000..b5bcc9f --- /dev/null +++ b/test/decoders/socks/pcap/socks4_nest_socks4a.pcap diff --git a/test/decoders/socks/pcap/socks4a_domain.pcap b/test/decoders/socks/pcap/socks4a_domain.pcap Binary files differnew file mode 100644 index 0000000..14fbf10 --- /dev/null +++ b/test/decoders/socks/pcap/socks4a_domain.pcap diff --git a/test/decoders/socks/pcap/socks5_auth_failed.pcap b/test/decoders/socks/pcap/socks5_auth_failed.pcap Binary files differnew file mode 100644 index 0000000..1c75c66 --- /dev/null +++ b/test/decoders/socks/pcap/socks5_auth_failed.pcap diff --git a/test/decoders/socks/pcap/socks5_auth_success.pcap b/test/decoders/socks/pcap/socks5_auth_success.pcap Binary files differnew file mode 100644 index 0000000..4c4b9fd --- /dev/null +++ b/test/decoders/socks/pcap/socks5_auth_success.pcap diff --git a/test/decoders/socks/pcap/socks5_no_auth.pcap b/test/decoders/socks/pcap/socks5_no_auth.pcap Binary files differnew file mode 100644 index 0000000..a00100f --- /dev/null +++ b/test/decoders/socks/pcap/socks5_no_auth.pcap diff --git a/test/decoders/socks/plugin_test_main.cpp b/test/decoders/socks/plugin_test_main.cpp new file mode 100644 index 0000000..8f3d996 --- /dev/null +++ b/test/decoders/socks/plugin_test_main.cpp @@ -0,0 +1,135 @@ +#include "cJSON.h" +#include <gtest/gtest.h> +#include <unistd.h> +#include <stdio.h> +#include <assert.h> + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "stellar/stellar.h" +#ifdef __cplusplus +} +#endif + +// #define IGNORE_PRINTF +#ifdef IGNORE_PRINTF +#define printf(fmt, ...) (0) +#endif +static cJSON *g_test_result_root = NULL; +static cJSON *g_load_result_root = NULL; +static const char *result_json_path = NULL; + +extern "C" int commit_test_result_json(cJSON *node, const char *name) +{ + (void)name; + if (g_test_result_root) + { + // cJSON_AddItemToObject(g_test_result_root, name, node); + // cJSON_AddStringToObject(node, "name", name); + cJSON_AddItemToArray(g_test_result_root, node); + return 0; + } + return -1; +} + +static cJSON *load_result_from_jsonfile(const char *json_path) +{ + if (json_path == NULL) + return NULL; + + long file_len = 0; + char *file_content = NULL; + FILE *fp = NULL; + + fp = fopen(json_path, "r+"); + if (NULL == fp) + { + return NULL; + } + fseek(fp, 0, SEEK_END); + file_len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (file_len == 0) + { + fclose(fp); + return NULL; + } + file_content = (char *)malloc(file_len + 1); + fread(file_content, file_len, 1, fp); + file_content[file_len] = '\0'; + cJSON *load = cJSON_Parse(file_content); + free(file_content); + fclose(fp); + + return load; +} + +TEST(PROTOCOL, compare_result_json) +{ + EXPECT_EQ(cJSON_GetArraySize(g_test_result_root), cJSON_GetArraySize(g_load_result_root)); + int ret = cJSON_Compare(g_test_result_root, g_load_result_root, 0); + EXPECT_EQ(1, ret); + + if (ret != 1) + { + char *load_json_str = cJSON_Print(g_load_result_root); + printf("LOAD Raw:\n%s\n", load_json_str); + free(load_json_str); + char *result_json_str = cJSON_Print(g_test_result_root); + printf("TEST Raw:\n%s\n", result_json_str); + free(result_json_str); + + cJSON *t_load = g_load_result_root->child, *t_test = g_test_result_root->child; + while (t_load != NULL) + { + ret = cJSON_Compare(t_load, t_test, 0); + if (ret != 1) + { + load_json_str = cJSON_Print(t_load); + printf("LOAD Diff:\n%s\n", load_json_str); + free(load_json_str); + result_json_str = cJSON_Print(t_test); + printf("TEST Diff:\n%s\n", result_json_str); + free(result_json_str); + goto fail; + } + t_load = t_load->next; + t_test = t_test->next; + } + } + cJSON_Delete(g_load_result_root); + cJSON_Delete(g_test_result_root); + return; +fail: + cJSON_Delete(g_load_result_root); + cJSON_Delete(g_test_result_root); + return; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + if (argc < 2) + { + printf("Usage: %s <result_json_path>\n", argv[0]); + result_json_path = NULL; + } + else + { + result_json_path = argv[1]; + g_test_result_root = cJSON_CreateArray(); + g_load_result_root = load_result_from_jsonfile(result_json_path); + assert(g_load_result_root != NULL && g_test_result_root != NULL); + } + ::testing::InitGoogleTest(&argc, argv); + struct stellar *st = stellar_new("./conf/stellar.toml", "./plugin/spec.toml", "./conf/log.toml"); + stellar_run(st); + if (result_json_path != NULL) + { + ret = RUN_ALL_TESTS(); + } + stellar_free(st); + return ret; +} diff --git a/test/decoders/socks/socks_decoder_pcap_gtest.cpp b/test/decoders/socks/socks_decoder_pcap_gtest.cpp new file mode 100644 index 0000000..b1cde22 --- /dev/null +++ b/test/decoders/socks/socks_decoder_pcap_gtest.cpp @@ -0,0 +1,246 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> +#include <netinet/tcp.h> +#include <netinet/ether.h> +#include <pcap/sll.h> +#include <pcap/pcap.h> +#include "gtest/gtest.h" + +#include "socks_decoder_internal.h" +extern "C" { +#include "stellar/session.h" +#include "dummy.h" +} + +#define LINUX_COOKED_CAPTURE 20 + +extern int socks_process(struct socks_decoder_info *socks_decoder_info, struct session *sess, struct socks_tunnel_stream *stream, const char *payload, size_t payload_len); +struct pcap_loop_arg +{ + pcap_t *pcap_handle; + struct socks_tunnel_stream *stream; +}; + +struct socks_decoder_info *socks_decoder_info = NULL; + +static void pcap_handle_cb(pcap_loop_arg *userarg, const struct pcap_pkthdr *pkthdr, const u_char *packet) +{ + struct pcap_loop_arg *arg = (struct pcap_loop_arg *)userarg; + struct session sess; + int payload_len = 0; + char *payload = NULL; + unsigned short sport, dport; + unsigned short eth_proto_type; + unsigned char *ip_header; + + memset(&sess, 0, sizeof(sess)); + + int data_link_type = pcap_datalink(arg->pcap_handle); + switch (data_link_type) { + case DLT_EN10MB: + eth_proto_type = ntohs(*(unsigned short *)(packet + 12)); + ip_header = (unsigned char *)(packet + sizeof(struct ethhdr)); + break; + case 276://DLT_LINUX_SLL2 + eth_proto_type = ntohs(*(unsigned short *)packet); + ip_header = (unsigned char *)(packet + LINUX_COOKED_CAPTURE); + break; + default: + return; + } + + if (eth_proto_type == ETH_P_IP) { + int l4_proto = *(unsigned char *)(ip_header + 9); + if (l4_proto == IPPROTO_TCP) { + int ip_total_len = ntohs(*(unsigned short *)(ip_header + 2)); + int ip_header_len = (*(unsigned char *)ip_header & 0x0f) * 4; + int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(iphdr) + 12) & 0xf0) >> 4); + payload_len = ip_total_len - ip_header_len - tcp_header_len; + payload = (char *)ip_header + ip_header_len + tcp_header_len; + } else { + return; + } + + sport = ntohs(*(unsigned short *)(ip_header + sizeof(iphdr) + 0)); + dport = ntohs(*(unsigned short *)(ip_header + sizeof(iphdr) + 2)); + + } else if (eth_proto_type == ETH_P_IPV6) { + int l4_proto = *(unsigned char *)(ip_header + 6); + if (l4_proto == IPPROTO_TCP) { + int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(struct ip6_hdr) + 12) & 0xf0) >> 4); + payload_len = pkthdr->caplen - (ip_header - packet) - sizeof(struct ip6_hdr) - tcp_header_len; + payload = (char *)ip_header + sizeof(struct ip6_hdr) + tcp_header_len; + } else { + return; + } + + sport = ntohs(*(unsigned short *)(ip_header + sizeof(struct ip6_hdr) + 0)); + dport = ntohs(*(unsigned short *)(ip_header + sizeof(struct ip6_hdr) + 2)); + } else { + return; + } + + session_set_current_state(&sess, SESSION_STATE_ACTIVE); + + if (sport > dport) + { + dummy_set_direction(FLOW_TYPE_C2S); + } else { + dummy_set_direction(FLOW_TYPE_S2C); + } + socks_process(socks_decoder_info, &sess, arg->stream, payload, payload_len); + +} + +TEST(socks_decoder, socks4) +{ + char error[100]; + struct pcap_loop_arg arg; + struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream)); + pcap_t * handle = pcap_open_offline("pcap/socks4.pcap", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.stream = stream; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + EXPECT_EQ(stream->info.version, SOCKS_VERSION_4); + EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_IPV4); + EXPECT_EQ(stream->info.dst_addr.ipv4, inet_addr("93.184.216.119")); + EXPECT_EQ(stream->info.dst_addr.port, htons(80)); + EXPECT_EQ(stream->info.user_name.iov_len, 0); + EXPECT_EQ(stream->info.password.iov_len, 0); + EXPECT_EQ(stream->client_state, SS_END); + EXPECT_EQ(stream->server_state, SS_END); + + pcap_close(handle); + free(stream); +} + +TEST(socks_decoder, socks4a_domain) +{ + char error[100]; + struct pcap_loop_arg arg; + struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream)); + pcap_t * handle = pcap_open_offline("pcap/socks4a_domain.pcap", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.stream = stream; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + EXPECT_EQ(stream->info.version, SOCKS_VERSION_4); + EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_FQDN); + EXPECT_EQ(stream->info.dst_addr.fqdn.iov_len, strlen("www.example.com")); + EXPECT_STREQ("www.example.com", (char *)stream->info.dst_addr.fqdn.iov_base); + EXPECT_EQ(stream->info.dst_addr.port, htons(80)); + EXPECT_EQ(stream->info.user_name.iov_len, 0); + EXPECT_EQ(stream->info.password.iov_len, 0); + EXPECT_EQ(stream->client_state, SS_END); + EXPECT_EQ(stream->server_state, SS_END); + + pcap_close(handle); + free(stream->info.dst_addr.fqdn.iov_base); + free(stream); +} + +TEST(socks_decoder, socks5_no_auth) +{ + char error[100]; + struct pcap_loop_arg arg; + struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream)); + pcap_t * handle = pcap_open_offline("pcap/socks5_no_auth.pcap", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.stream = stream; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + EXPECT_EQ(stream->info.version, SOCKS_VERSION_5); + EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_IPV4); + EXPECT_EQ(stream->info.dst_addr.ipv4, inet_addr("93.184.216.119")); + EXPECT_EQ(stream->info.dst_addr.port, htons(80)); + EXPECT_EQ(stream->info.user_name.iov_len, 0); + EXPECT_EQ(stream->info.password.iov_len, 0); + EXPECT_EQ(stream->client_state, SS_END); + EXPECT_EQ(stream->server_state, SS_END); + + pcap_close(handle); + free(stream); +} + +TEST(socks_decoder, socks5_auth_success) +{ + char error[100]; + struct pcap_loop_arg arg; + struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream)); + pcap_t * handle = pcap_open_offline("pcap/socks5_auth_success.pcap", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.stream = stream; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + EXPECT_EQ(stream->info.version, SOCKS_VERSION_5); + EXPECT_EQ(stream->info.dst_addr.type, SOCKS_ADDR_IPV4); + EXPECT_EQ(stream->info.dst_addr.ipv4, inet_addr("93.184.216.119")); + EXPECT_EQ(stream->info.dst_addr.port, htons(80)); + EXPECT_EQ(stream->info.user_name.iov_len, strlen("testuser")); + EXPECT_STREQ("testuser", (char *)stream->info.user_name.iov_base); + EXPECT_EQ(stream->info.password.iov_len, strlen("testuser")); + EXPECT_STREQ("testuser", (char *)stream->info.password.iov_base); + EXPECT_EQ(stream->client_state, SS_END); + EXPECT_EQ(stream->server_state, SS_END); + + pcap_close(handle); + free(stream->info.user_name.iov_base); + free(stream->info.password.iov_base); + free(stream); +} + +TEST(socks_decoder, socks5_auth_fail) +{ + char error[100]; + struct pcap_loop_arg arg; + struct socks_tunnel_stream *stream = (struct socks_tunnel_stream *)calloc(1, sizeof(struct socks_tunnel_stream)); + pcap_t * handle = pcap_open_offline("pcap/socks5_auth_failed.pcap", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.stream = stream; + arg.pcap_handle = handle; + + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + EXPECT_EQ(stream->client_state, SS_SUB); + EXPECT_EQ(stream->server_state, SS_FAILED); + + pcap_close(handle); + free(stream->info.user_name.iov_base); + free(stream->info.password.iov_base); + free(stream); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + + socks_decoder_info = (struct socks_decoder_info *)calloc(1, sizeof(struct socks_decoder_info)); + + int result = RUN_ALL_TESTS(); + + free(socks_decoder_info); + + return result; +}
\ No newline at end of file diff --git a/test/decoders/socks/socks_decoder_test_plugin.cpp b/test/decoders/socks/socks_decoder_test_plugin.cpp new file mode 100644 index 0000000..7edcf8d --- /dev/null +++ b/test/decoders/socks/socks_decoder_test_plugin.cpp @@ -0,0 +1,88 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> + +extern "C" { +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" +} + +#include "cJSON.h" +#include "socks_decoder.h" + +extern "C" int commit_test_result_json(cJSON *node, const char *name); +#define unused(x) ((void)(x)) + + +int g_test_socks_decoder_plugin_id = 0; +int g_socks_message_topic_id = 0; + +void *ctx_new(struct session *session, void *plugin_env) +{ + unused(plugin_env); + unused(session); + + cJSON *root = cJSON_CreateObject(); + return (void *)root; +} + +void ctx_free(struct session *sess, void *session_ctx, void *plugin_env) +{ + unused(sess); + unused(plugin_env); + + commit_test_result_json((cJSON *)session_ctx, "socks_decoder_test"); +} + +static void append_json(cJSON *root, struct socks_info *info) +{ + cJSON *json_stream = cJSON_CreateObject(); + + cJSON_AddStringToObject(json_stream, "version", info->version == SOCKS_VERSION_4 ? "SOCKS4" : "SOCKS5"); + + char ip_str[INET6_ADDRSTRLEN] = {0}; + if (info->dst_addr.type == SOCKS_ADDR_IPV4) { + inet_ntop(AF_INET, &info->dst_addr.ipv4, ip_str, INET_ADDRSTRLEN); + } else if (info->dst_addr.type == SOCKS_ADDR_IPV6) { + inet_ntop(AF_INET6, info->dst_addr.ipv6, ip_str, INET6_ADDRSTRLEN); + } else { + memcpy(ip_str, info->dst_addr.fqdn.iov_base, info->dst_addr.fqdn.iov_len); + } + cJSON_AddStringToObject(json_stream, "dst_addr", ip_str); + cJSON_AddNumberToObject(json_stream, "dst_port", ntohs(info->dst_addr.port)); + cJSON_AddStringToObject(json_stream, "user_name", (char *)info->user_name.iov_base); + cJSON_AddStringToObject(json_stream, "password", (char *)info->password.iov_base); + + cJSON_AddItemToObject(root, "socks_info", json_stream); +} + +void test_socks_decoder_on_message(struct session *session, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) +{ + unused(plugin_env); + unused(session); + unused(topic_id); + + struct socks_info *info = (struct socks_info *)msg; + cJSON *json_root = (cJSON *)per_session_ctx; + + append_json(json_root, info); +} + +extern "C" void *SOCKS_DECODER_TEST_PLUG_INIT(struct stellar *st) +{ + g_test_socks_decoder_plugin_id = stellar_session_plugin_register(st, ctx_new, ctx_free, NULL); + g_socks_message_topic_id = stellar_mq_get_topic_id(st, SOCKS_MESSAGE_TOPIC); + + stellar_session_mq_subscribe(st, g_socks_message_topic_id, test_socks_decoder_on_message, g_test_socks_decoder_plugin_id); + + + return NULL; +} + +extern "C" void SOCKS_DECODER_TEST_PLUG_DESTROY(void *plugin_env) +{ + unused(plugin_env); +}
\ No newline at end of file diff --git a/test/decoders/socks/test_based_on_stellar/CMakeLists.txt b/test/decoders/socks/test_based_on_stellar/CMakeLists.txt new file mode 100644 index 0000000..2a3bc25 --- /dev/null +++ b/test/decoders/socks/test_based_on_stellar/CMakeLists.txt @@ -0,0 +1,37 @@ +set(DECODER_NAME socks) + +set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/test/decoders/socks) +set(SAPP_DEVEL_DIR ${TEST_RUN_DIR}/lib) +set(TEST_MAIN socks_test_main) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/test) +include_directories(/usr/local/include/cjson) +include_directories(/opt/tsg/framework/include/stellar) +include_directories(/opt/MESA/include/MESA) +include_directories(/opt/tsg/stellar/include/) + +#various ways to add -rdynamic for centos7, centos8, and different cmake version +add_definitions(-rdynamic) +link_directories(${SAPP_DEVEL_DIR}) + +# assemble test env +add_test(NAME SOCKS_MKDIR_METRIC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/metrics; mkdir -p ${TEST_RUN_DIR}/plugin; mkdir -p ${TEST_RUN_DIR}/log; mkdir -p ${TEST_RUN_DIR}/pcap") +add_test(NAME SOCKS_COPY_SPEC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plugin/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/spec.toml ${TEST_RUN_DIR}/plugin/spec.toml") +add_test(NAME SOCKS_COPY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/stellar.toml ${TEST_RUN_DIR}/conf/stellar.toml") +add_test(NAME SOCKS_COPY_LOG_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/log.toml ${TEST_RUN_DIR}/conf/log.toml") + +# update plugin to be tested +add_test(NAME SOCKS_CP_DECODER_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/decoders/socks/socks_dyn.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}.so") +add_test(NAME SOCKS_CP_DECODER_GTEST_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/decoders/socks/${DECODER_NAME}_test.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}_test.so") + +set_tests_properties(SOCKS_MKDIR_METRIC SOCKS_COPY_SPEC + SOCKS_COPY_CONF SOCKS_COPY_LOG_CONF + SOCKS_CP_DECODER_SO SOCKS_CP_DECODER_GTEST_SO + PROPERTIES FIXTURES_SETUP TestFixture) + +set(TEST_PCAP_DIR ${PROJECT_SOURCE_DIR}/test/decoders/socks/pcap) + +# run tests +add_test(NAME SOCKS_DECODER_PLUGIN_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/socks4_nest_socks4a.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_PCAP_DIR}/result.json" WORKING_DIRECTORY ${TEST_RUN_DIR}) + diff --git a/test/decoders/socks/test_based_on_stellar/env/log.toml b/test/decoders/socks/test_based_on_stellar/env/log.toml new file mode 100644 index 0000000..a51abd8 --- /dev/null +++ b/test/decoders/socks/test_based_on_stellar/env/log.toml @@ -0,0 +1,4 @@ +[log] +output = "stderr" # stderr, file +file = "log/stellar.log" +level = "ERROR" # TRACE, DEBUG, INFO, WARN, ERROR, FATAL diff --git a/test/decoders/socks/test_based_on_stellar/env/spec.toml b/test/decoders/socks/test_based_on_stellar/env/spec.toml new file mode 100644 index 0000000..71e58b4 --- /dev/null +++ b/test/decoders/socks/test_based_on_stellar/env/spec.toml @@ -0,0 +1,9 @@ +[[plugin]] +path = "./plugin/socks.so" +init = "socks_decoder_init" +exit = "socks_decoder_exit" + +[[plugin]] +path = "./plugin/socks_test.so" +init = "SOCKS_DECODER_TEST_PLUG_INIT" +exit = "SOCKS_DECODER_TEST_PLUG_DESTROY" diff --git a/test/decoders/socks/test_based_on_stellar/env/stellar.toml b/test/decoders/socks/test_based_on_stellar/env/stellar.toml new file mode 100644 index 0000000..308c884 --- /dev/null +++ b/test/decoders/socks/test_based_on_stellar/env/stellar.toml @@ -0,0 +1,64 @@ +[instance] + id = 1 # range: [0, 4095] (20 bit) + +[packet_io] + mode = "pcapfile" # pcapfile, pcaplist, marsio + app_symbol = "stellar" + dev_symbol = "nf_0_fw" + pcap_path = "./pcap/test.pcap" + nr_worker_thread = 1 # range: [1, 256] + cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12] + idle_yield_interval_ms = 90 # range: [0, 60000] (ms) + +[ip_reassembly] + enable = 1 + bucket_entries = 32 # range: [1, 4294967295] (must be power of 2) + bucket_num = 1024 # range: [1, 4294967295] + + ip_frag_timeout_ms = 1000 # range: [1, 60000] (ms) + ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms) + ip_frag_expire_polling_limit = 1024 # range: [1, 1024] + +[session_manager] + tcp_session_max = 500 + udp_session_max = 500 + + evict_old_on_tcp_table_limit = 1 # range: [0, 1] + evict_old_on_udp_table_limit = 1 # range: [0, 1] + + expire_period_ms = 0 # range: [0, 60000] (ms) + expire_batch_max = 1024 # range: [1, 1024] + + [session_manager.tcp_timeout_ms] + init = 500 # range: [1, 60000] (ms) + handshake = 500 # range: [1, 60000] (ms) + data = 500 # range: [1, 15999999000] (ms) + half_closed = 500 # range: [1, 604800000] (ms) + time_wait = 500 # range: [1, 600000] (ms) + discard_default = 1000 # range: [1, 15999999000] (ms) + unverified_rst = 500 # range: [1, 600000] (ms) + + [session_manager.udp_timeout_ms] + data = 500 # range: [1, 15999999000] (ms) + discard_default = 500 # range: [1, 15999999000] (ms) + + [session_manager.duplicated_packet_bloom_filter] + enable = 0 + capacity = 1000000 # range: [1, 4294967295] + time_window_ms = 10000 # range: [1, 60000] (ms) + error_rate = 0.00001 # range: [0.0, 1.0] + + [session_manager.evicted_session_bloom_filter] + enable = 0 # range: [0, 1] + capacity = 1000000 # range: [1, 4294967295] + time_window_ms = 10000 # range: [1, 60000] (ms) + error_rate = 0.00001 # range: [0.0, 1.0] + + [session_manager.tcp_reassembly] + enable = 1 # range: [0, 1] + timeout_ms = 100 # range: [1, 60000] (ms) + buffered_segments_max = 256 # range: [2, 4096] per flow + +[stat] + merge_interval_ms = 500 # range: [0, 60000] (ms) + output_interval_ms = 1000 # range: [0, 60000] (ms) diff --git a/test/decoders/stratum/CMakeLists.txt b/test/decoders/stratum/CMakeLists.txt new file mode 100644 index 0000000..683efee --- /dev/null +++ b/test/decoders/stratum/CMakeLists.txt @@ -0,0 +1,41 @@ +set(DECODER_NAME stratum) + +add_library(${DECODER_NAME}_test SHARED stratum_test_plugin.cpp) +add_dependencies(${DECODER_NAME}_test ${DECODER_NAME}) +set_target_properties(${DECODER_NAME}_test PROPERTIES PREFIX "") + +set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/testing) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/src) +include_directories(${CMAKE_SOURCE_DIR}/deps/toml) +include_directories(${CMAKE_BINARY_DIR}/vendors/cjson/src/cjson/include) +include_directories(${PROJECT_SOURCE_DIR}/decoders/stratum) +include_directories(${PROJECT_SOURCE_DIR}/include/stellar) + +add_executable(gtest_pcap_stratum stratum_decoder_pcap_gtest.cpp dummy.c ${PROJECT_SOURCE_DIR}/decoders/stratum/stratum_decoder.cpp) +target_link_libraries(gtest_pcap_stratum gtest pcap cjson-static logger) + +add_executable(stratum_test_main plugin_test_main.cpp) +set_target_properties(stratum_test_main + PROPERTIES + LINK_OPTIONS + "-rdynamic" + ) +set_target_properties(stratum_test_main + PROPERTIES + LINK_FLAGS + "-rdynamic" + ) +set(LINK_FLAGS "-rdynamic") +#target_link_options(stratum_test_main PRIVATE -Wl,--whole-archive logger -Wl,--no-whole-archive) +set(CMAKE_VERBOSE_MAKEFILE ON) +target_link_libraries(stratum_test_main gtest cjson-static logger stellar_lib) + +add_subdirectory(test_based_on_stellar) + +#copy pcap file folder to build directory +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pcap DESTINATION ${CMAKE_BINARY_DIR}/test/decoders/stratum) + +include(GoogleTest) +gtest_discover_tests(gtest_pcap_stratum) diff --git a/test/decoders/stratum/dummy.c b/test/decoders/stratum/dummy.c new file mode 100644 index 0000000..0290c59 --- /dev/null +++ b/test/decoders/stratum/dummy.c @@ -0,0 +1,86 @@ +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" + +#define UNUSED(x) (void)(x) + +void stellar_session_plugin_dettach_current_session(struct session *sess) +{ + UNUSED(sess); +} + +const struct packet *session_get0_current_packet(const struct session *sess) +{ + UNUSED(sess); + + return NULL; +} + +const char *packet_get_payload(const struct packet *pkt) +{ + UNUSED(pkt); + + return NULL; +} + +uint16_t packet_get_payload_len(const struct packet *pkt) +{ + UNUSED(pkt); + + return 0; +} + +struct logger *stellar_get_logger(struct stellar *st) +{ + UNUSED(st); + + return NULL; +} + +int session_mq_publish_message(struct session *sess, int topic_id, void *msg) +{ + UNUSED(sess); + UNUSED(topic_id); + UNUSED(msg); + + return 0; +} + +int stellar_mq_create_topic(struct stellar *st, const char *topic_name, stellar_msg_free_cb_func *msg_free_cb, void *msg_free_arg) +{ + UNUSED(st); + UNUSED(topic_name); + UNUSED(msg_free_cb); + UNUSED(msg_free_arg); + + return 0; +} + +int stellar_mq_get_topic_id(struct stellar *st, const char *topic_name) +{ + UNUSED(st); + UNUSED(topic_name); + + return 0; +} + +int stellar_session_mq_subscribe(struct stellar *st, int topic_id, on_session_msg_cb_func *plugin_on_msg_cb, int plugin_id) +{ + UNUSED(st); + UNUSED(topic_id); + UNUSED(plugin_on_msg_cb); + UNUSED(plugin_id); + + return 0; +} + +int stellar_session_plugin_register(struct stellar *st, session_ctx_new_func session_ctx_new, session_ctx_free_func session_ctx_free, void *plugin_env) +{ + UNUSED(st); + UNUSED(session_ctx_new); + UNUSED(session_ctx_free); + UNUSED(plugin_env); + + return 0; +}
\ No newline at end of file diff --git a/test/decoders/stratum/pcap/01-bch_f2pool_cpuminer_1.pcapng b/test/decoders/stratum/pcap/01-bch_f2pool_cpuminer_1.pcapng Binary files differnew file mode 100644 index 0000000..725aed7 --- /dev/null +++ b/test/decoders/stratum/pcap/01-bch_f2pool_cpuminer_1.pcapng diff --git a/test/decoders/stratum/pcap/02-eth-antpool.pcapng b/test/decoders/stratum/pcap/02-eth-antpool.pcapng Binary files differnew file mode 100644 index 0000000..5902981 --- /dev/null +++ b/test/decoders/stratum/pcap/02-eth-antpool.pcapng diff --git a/test/decoders/stratum/pcap/03-xmr_f2pool_nanominer_1.pcapng b/test/decoders/stratum/pcap/03-xmr_f2pool_nanominer_1.pcapng Binary files differnew file mode 100644 index 0000000..dfb0516 --- /dev/null +++ b/test/decoders/stratum/pcap/03-xmr_f2pool_nanominer_1.pcapng diff --git a/test/decoders/stratum/pcap/04-zec-antpool.pcapng b/test/decoders/stratum/pcap/04-zec-antpool.pcapng Binary files differnew file mode 100644 index 0000000..d46ab7f --- /dev/null +++ b/test/decoders/stratum/pcap/04-zec-antpool.pcapng diff --git a/test/decoders/stratum/pcap/stratum_result.json b/test/decoders/stratum/pcap/stratum_result.json new file mode 100644 index 0000000..37747ed --- /dev/null +++ b/test/decoders/stratum/pcap/stratum_result.json @@ -0,0 +1,11 @@ +[ + { + "stratum": + { + "Tuple4": "192.168.50.243:58748-120.26.148.222:1228-6-0", + "type": "OTHER", + "mining_program": "cpuminer/2.5.1", + "mining_subscribe": "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": [\"cpuminer/2.5.1\"]}\n" + } + } +]
\ No newline at end of file diff --git a/test/decoders/stratum/plugin_test_main.cpp b/test/decoders/stratum/plugin_test_main.cpp new file mode 100644 index 0000000..8f3d996 --- /dev/null +++ b/test/decoders/stratum/plugin_test_main.cpp @@ -0,0 +1,135 @@ +#include "cJSON.h" +#include <gtest/gtest.h> +#include <unistd.h> +#include <stdio.h> +#include <assert.h> + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "stellar/stellar.h" +#ifdef __cplusplus +} +#endif + +// #define IGNORE_PRINTF +#ifdef IGNORE_PRINTF +#define printf(fmt, ...) (0) +#endif +static cJSON *g_test_result_root = NULL; +static cJSON *g_load_result_root = NULL; +static const char *result_json_path = NULL; + +extern "C" int commit_test_result_json(cJSON *node, const char *name) +{ + (void)name; + if (g_test_result_root) + { + // cJSON_AddItemToObject(g_test_result_root, name, node); + // cJSON_AddStringToObject(node, "name", name); + cJSON_AddItemToArray(g_test_result_root, node); + return 0; + } + return -1; +} + +static cJSON *load_result_from_jsonfile(const char *json_path) +{ + if (json_path == NULL) + return NULL; + + long file_len = 0; + char *file_content = NULL; + FILE *fp = NULL; + + fp = fopen(json_path, "r+"); + if (NULL == fp) + { + return NULL; + } + fseek(fp, 0, SEEK_END); + file_len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (file_len == 0) + { + fclose(fp); + return NULL; + } + file_content = (char *)malloc(file_len + 1); + fread(file_content, file_len, 1, fp); + file_content[file_len] = '\0'; + cJSON *load = cJSON_Parse(file_content); + free(file_content); + fclose(fp); + + return load; +} + +TEST(PROTOCOL, compare_result_json) +{ + EXPECT_EQ(cJSON_GetArraySize(g_test_result_root), cJSON_GetArraySize(g_load_result_root)); + int ret = cJSON_Compare(g_test_result_root, g_load_result_root, 0); + EXPECT_EQ(1, ret); + + if (ret != 1) + { + char *load_json_str = cJSON_Print(g_load_result_root); + printf("LOAD Raw:\n%s\n", load_json_str); + free(load_json_str); + char *result_json_str = cJSON_Print(g_test_result_root); + printf("TEST Raw:\n%s\n", result_json_str); + free(result_json_str); + + cJSON *t_load = g_load_result_root->child, *t_test = g_test_result_root->child; + while (t_load != NULL) + { + ret = cJSON_Compare(t_load, t_test, 0); + if (ret != 1) + { + load_json_str = cJSON_Print(t_load); + printf("LOAD Diff:\n%s\n", load_json_str); + free(load_json_str); + result_json_str = cJSON_Print(t_test); + printf("TEST Diff:\n%s\n", result_json_str); + free(result_json_str); + goto fail; + } + t_load = t_load->next; + t_test = t_test->next; + } + } + cJSON_Delete(g_load_result_root); + cJSON_Delete(g_test_result_root); + return; +fail: + cJSON_Delete(g_load_result_root); + cJSON_Delete(g_test_result_root); + return; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + if (argc < 2) + { + printf("Usage: %s <result_json_path>\n", argv[0]); + result_json_path = NULL; + } + else + { + result_json_path = argv[1]; + g_test_result_root = cJSON_CreateArray(); + g_load_result_root = load_result_from_jsonfile(result_json_path); + assert(g_load_result_root != NULL && g_test_result_root != NULL); + } + ::testing::InitGoogleTest(&argc, argv); + struct stellar *st = stellar_new("./conf/stellar.toml", "./plugin/spec.toml", "./conf/log.toml"); + stellar_run(st); + if (result_json_path != NULL) + { + ret = RUN_ALL_TESTS(); + } + stellar_free(st); + return ret; +} diff --git a/test/decoders/stratum/stratum_decoder_pcap_gtest.cpp b/test/decoders/stratum/stratum_decoder_pcap_gtest.cpp new file mode 100644 index 0000000..a5c5b72 --- /dev/null +++ b/test/decoders/stratum/stratum_decoder_pcap_gtest.cpp @@ -0,0 +1,179 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> +#include <netinet/tcp.h> +#include <netinet/ether.h> +#include <pcap/sll.h> +#include <pcap/pcap.h> +#include "gtest/gtest.h" + +#include "stellar/stratum_decoder.h" + +#include <stellar/session.h> + + +#define LINUX_COOKED_CAPTURE 20 + +struct pcap_loop_arg +{ + pcap_t *pcap_handle; + void *ctx; +}; + +extern struct stratum_field *stratum_data_process(struct stratum_decoder_info *stratum_decoder_info, const char *tcpdata, size_t datalen); +extern void free_stratum_filed(struct stratum_field *stratum_field); +extern "C" void *stratum_decoder_init(struct stellar *st); + +struct stratum_decoder_info *stratum_decoder_info = NULL; + +static void pcap_handle_cb(pcap_loop_arg *userarg, const struct pcap_pkthdr *pkthdr, const u_char *packet) +{ + struct pcap_loop_arg *arg = (struct pcap_loop_arg *)userarg; + int payload_len = 0; + char *payload = NULL; + unsigned short eth_proto_type; + unsigned char *ip_header; + + int data_link_type = pcap_datalink(arg->pcap_handle); + switch (data_link_type) { + case DLT_EN10MB: + eth_proto_type = ntohs(*(unsigned short *)(packet + 12)); + ip_header = (unsigned char *)(packet + sizeof(struct ethhdr)); + break; + case 276://DLT_LINUX_SLL2 + eth_proto_type = ntohs(*(unsigned short *)packet); + ip_header = (unsigned char *)(packet + LINUX_COOKED_CAPTURE); + break; + default: + return; + } + + if (eth_proto_type == ETH_P_IP) { + int l4_proto = *(unsigned char *)(ip_header + 9); + if (l4_proto == IPPROTO_TCP) { + int ip_total_len = ntohs(*(unsigned short *)(ip_header + 2)); + int ip_header_len = (*(unsigned char *)ip_header & 0x0f) * 4; + int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(iphdr) + 12) & 0xf0) >> 4); + payload_len = ip_total_len - ip_header_len - tcp_header_len; + payload = (char *)ip_header + ip_header_len + tcp_header_len; + } else { + return; + } + + } else if (eth_proto_type == ETH_P_IPV6) { + int l4_proto = *(unsigned char *)(ip_header + 6); + if (l4_proto == IPPROTO_TCP) { + int tcp_header_len = 4 * ((*(unsigned char *)(ip_header + sizeof(struct ip6_hdr) + 12) & 0xf0) >> 4); + payload_len = pkthdr->caplen - (ip_header - packet) - sizeof(struct ip6_hdr) - tcp_header_len; + payload = (char *)ip_header + sizeof(struct ip6_hdr) + tcp_header_len; + } else { + return; + } + } else { + return; + } + + struct stratum_field *stratum = stratum_data_process(stratum_decoder_info, payload, payload_len); + if (stratum != NULL) + { + arg->ctx = stratum; + pcap_breakloop(arg->pcap_handle); + } +} + +TEST(stratum_decoder, parse01) +{ + char error[100]; + struct pcap_loop_arg arg; + pcap_t *handle = pcap_open_offline("pcap/01-bch_f2pool_cpuminer_1.pcapng", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.pcap_handle = handle; + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct stratum_field *stratum = (struct stratum_field *)arg.ctx; + EXPECT_EQ(stratum->type, OTHER); + EXPECT_STREQ((const char *)stratum->mining_program.iov_base, "cpuminer/2.5.1"); + EXPECT_EQ(stratum->mining_pools.iov_len, 0); + EXPECT_STREQ((const char *)stratum->mining_subscribe.iov_base, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": [\"cpuminer/2.5.1\"]}\n"); + + pcap_close(handle); + free_stratum_filed(stratum); +} + +TEST(stratum_decoder, parse02) +{ + char error[100]; + struct pcap_loop_arg arg; + pcap_t *handle = pcap_open_offline("pcap/02-eth-antpool.pcapng", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.pcap_handle = handle; + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct stratum_field *stratum = (struct stratum_field *)arg.ctx; + EXPECT_EQ(stratum->type, ETH); + EXPECT_STREQ((const char *)stratum->mining_program.iov_base, "lolMinerWorker"); + EXPECT_EQ(stratum->mining_pools.iov_len, 0); + EXPECT_STREQ((const char *)stratum->mining_subscribe.iov_base, "{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_submitLogin\",\"worker\":\"lolMinerWorker\",\"params\":[\"0xa0279Ad2aA6BDb440f041Aa0947178431d9Bd253.lolMinerWorker\", \"x\"]} \n"); + + pcap_close(handle); + free_stratum_filed(stratum); +} + +TEST(stratum_decoder, parse03) +{ + char error[100]; + struct pcap_loop_arg arg; + pcap_t *handle = pcap_open_offline("pcap/03-xmr_f2pool_nanominer_1.pcapng", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.pcap_handle = handle; + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct stratum_field *stratum = (struct stratum_field *)arg.ctx; + EXPECT_EQ(stratum->type, OTHER); + EXPECT_STREQ((const char *)stratum->mining_program.iov_base, "nanominer/3.3.5-cuda11"); + EXPECT_EQ(stratum->mining_pools.iov_len, 0); + EXPECT_STREQ((const char *)stratum->mining_subscribe.iov_base, "{\"id\": 1, \"method\": \"login\", \"params\": { \"login\":\"yhzzhk.001.001\",\"pass\" : \"x\", \"agent\" : \"nanominer/3.3.5-cuda11\"}}\n"); + + pcap_close(handle); + free_stratum_filed(stratum); +} + +TEST(stratum_decoder, parse04) +{ + char error[100]; + struct pcap_loop_arg arg; + pcap_t *handle = pcap_open_offline("pcap/04-zec-antpool.pcapng", error); + ASSERT_NE(handle, nullptr); + + memset(&arg, 0, sizeof(arg)); + arg.pcap_handle = handle; + pcap_loop(handle, -1, (pcap_handler)pcap_handle_cb, (u_char *)&arg); + + struct stratum_field *stratum = (struct stratum_field *)arg.ctx; + EXPECT_EQ(stratum->type, OTHER); + EXPECT_STREQ((const char *)stratum->mining_program.iov_base, "nheqminer/0.5c"); + EXPECT_STREQ((const char*)stratum->mining_pools.iov_base, "stratum-zec.antpool.com"); + EXPECT_STREQ((const char *)stratum->mining_subscribe.iov_base, "{\"id\":1,\"method\":\"mining.subscribe\",\"params\":[\"nheqminer/0.5c\", null,\"stratum-zec.antpool.com\",\"8899\"]}\n"); + + pcap_close(handle); + free_stratum_filed(stratum); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + + stratum_decoder_info = (struct stratum_decoder_info*)stratum_decoder_init(NULL); + + int result = RUN_ALL_TESTS(); + + return result; +}
\ No newline at end of file diff --git a/test/decoders/stratum/stratum_test_plugin.cpp b/test/decoders/stratum/stratum_test_plugin.cpp new file mode 100644 index 0000000..3ec563b --- /dev/null +++ b/test/decoders/stratum/stratum_test_plugin.cpp @@ -0,0 +1,72 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "cJSON.h" +#include "stellar/stellar.h" +#include "stellar/session.h" +#include "stellar/stellar_mq.h" +#include "stellar/stellar_exdata.h" + +#include "stratum_decoder.h" + +#define unused(x) ((void)(x)) +extern "C" int commit_test_result_json(cJSON *node, const char *name); + +int g_test_stratum_decoder_plugin_id = 0; +int g_stratum_message_topic_id = 0; + +void *ctx_new(struct session *session, void *plugin_env) +{ + unused(plugin_env); + unused(session); + + cJSON *root = cJSON_CreateObject(); + return (void *)root; +} + +void ctx_free(struct session *sess, void *session_ctx, void *plugin_env) +{ + unused(sess); + unused(plugin_env); + + commit_test_result_json((cJSON *)session_ctx, "socks_decoder_test"); +} + +void test_stratum_decoder_on_message(struct session *session, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) +{ + unused(plugin_env); + unused(topic_id); + + struct stratum_field *stratum = (struct stratum_field *)msg; + cJSON *root = (cJSON *)per_session_ctx; + + cJSON *stratum_json = cJSON_CreateObject(); + cJSON_AddItemToObject(root, "stratum", stratum_json); + + cJSON_AddStringToObject(stratum_json, "Tuple4", session_get0_readable_addr(session)); + cJSON_AddStringToObject(stratum_json, "type", stratum->type == ETH ? "ETH" : "OTHER"); + cJSON_AddStringToObject(stratum_json, "mining_pools", (char *)stratum->mining_pools.iov_base); + cJSON_AddStringToObject(stratum_json, "mining_program", (char *)stratum->mining_program.iov_base); + cJSON_AddStringToObject(stratum_json, "mining_subscribe", (char *)stratum->mining_subscribe.iov_base); + +} + +extern "C" void *STRATUM_DECODER_TEST_PLUG_INIT(struct stellar *st) +{ + g_test_stratum_decoder_plugin_id = stellar_session_plugin_register(st, ctx_new, ctx_free, NULL); + g_stratum_message_topic_id = stellar_mq_get_topic_id(st, STRATUM_MESSAGE_TOPIC); + + if (stellar_session_mq_subscribe(st, g_stratum_message_topic_id, test_stratum_decoder_on_message, g_test_stratum_decoder_plugin_id) < 0) + { + printf("subscribe topic %s failed\n", STRATUM_MESSAGE_TOPIC); + return NULL; + } + + return NULL; +} + +extern "C" void STRATUM_DECODER_TEST_PLUG_DESTROY(void * plugin_env) +{ + unused(plugin_env); +}
\ No newline at end of file diff --git a/test/decoders/stratum/test_based_on_stellar/CMakeLists.txt b/test/decoders/stratum/test_based_on_stellar/CMakeLists.txt new file mode 100644 index 0000000..1de14e5 --- /dev/null +++ b/test/decoders/stratum/test_based_on_stellar/CMakeLists.txt @@ -0,0 +1,37 @@ +set(DECODER_NAME stratum) + +set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/test/decoders/stratum) +set(SAPP_DEVEL_DIR ${TEST_RUN_DIR}/lib) +set(TEST_MAIN stratum_test_main) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/test) +include_directories(/usr/local/include/cjson) +include_directories(/opt/tsg/framework/include/stellar) +include_directories(/opt/MESA/include/MESA) +include_directories(/opt/tsg/stellar/include/) + +#various ways to add -rdynamic for centos7, centos8, and different cmake version +add_definitions(-rdynamic) +link_directories(${SAPP_DEVEL_DIR}) + +# assemble test env +add_test(NAME STRATUM_MKDIR_METRIC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/metrics; mkdir -p ${TEST_RUN_DIR}/plugin; mkdir -p ${TEST_RUN_DIR}/log; mkdir -p ${TEST_RUN_DIR}/pcap") +add_test(NAME STRATUM_COPY_SPEC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plugin/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/spec.toml ${TEST_RUN_DIR}/plugin/spec.toml") +add_test(NAME STRATUM_COPY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/stellar.toml ${TEST_RUN_DIR}/conf/stellar.toml") +add_test(NAME STRATUM_COPY_LOG_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/log.toml ${TEST_RUN_DIR}/conf/log.toml") + +# update plugin to be tested +add_test(NAME STRATUM_CP_DECODER_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/decoders/stratum/stratum_dyn.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}.so") +add_test(NAME STRATUM_CP_DECODER_GTEST_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/decoders/stratum/${DECODER_NAME}_test.so ${TEST_RUN_DIR}/plugin/${DECODER_NAME}_test.so") + +set_tests_properties(STRATUM_MKDIR_METRIC STRATUM_COPY_SPEC + STRATUM_COPY_CONF STRATUM_COPY_LOG_CONF + STRATUM_CP_DECODER_SO STRATUM_CP_DECODER_GTEST_SO + PROPERTIES FIXTURES_SETUP TestFixture) + +set(TEST_PCAP_DIR ${PROJECT_SOURCE_DIR}/test/decoders/stratum/pcap) + +# run tests +add_test(NAME STRATUM_DECODER_PLUGIN_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/01-bch_f2pool_cpuminer_1.pcapng ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_PCAP_DIR}/stratum_result.json" WORKING_DIRECTORY ${TEST_RUN_DIR}) + diff --git a/test/decoders/stratum/test_based_on_stellar/env/log.toml b/test/decoders/stratum/test_based_on_stellar/env/log.toml new file mode 100644 index 0000000..b5213d9 --- /dev/null +++ b/test/decoders/stratum/test_based_on_stellar/env/log.toml @@ -0,0 +1,4 @@ +[log] +output = "stderr" # stderr, file +file = "log/stellar.log" +level = "INFO" # TRACE, DEBUG, INFO, WARN, ERROR, FATAL diff --git a/test/decoders/stratum/test_based_on_stellar/env/spec.toml b/test/decoders/stratum/test_based_on_stellar/env/spec.toml new file mode 100644 index 0000000..6eafab8 --- /dev/null +++ b/test/decoders/stratum/test_based_on_stellar/env/spec.toml @@ -0,0 +1,9 @@ +[[plugin]] +path = "./plugin/stratum.so" +init = "stratum_decoder_init" +exit = "stratum_decoder_exit" + +[[plugin]] +path = "./plugin/stratum_test.so" +init = "STRATUM_DECODER_TEST_PLUG_INIT" +exit = "STRATUM_DECODER_TEST_PLUG_DESTROY" diff --git a/test/decoders/stratum/test_based_on_stellar/env/stellar.toml b/test/decoders/stratum/test_based_on_stellar/env/stellar.toml new file mode 100644 index 0000000..308c884 --- /dev/null +++ b/test/decoders/stratum/test_based_on_stellar/env/stellar.toml @@ -0,0 +1,64 @@ +[instance] + id = 1 # range: [0, 4095] (20 bit) + +[packet_io] + mode = "pcapfile" # pcapfile, pcaplist, marsio + app_symbol = "stellar" + dev_symbol = "nf_0_fw" + pcap_path = "./pcap/test.pcap" + nr_worker_thread = 1 # range: [1, 256] + cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12] + idle_yield_interval_ms = 90 # range: [0, 60000] (ms) + +[ip_reassembly] + enable = 1 + bucket_entries = 32 # range: [1, 4294967295] (must be power of 2) + bucket_num = 1024 # range: [1, 4294967295] + + ip_frag_timeout_ms = 1000 # range: [1, 60000] (ms) + ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms) + ip_frag_expire_polling_limit = 1024 # range: [1, 1024] + +[session_manager] + tcp_session_max = 500 + udp_session_max = 500 + + evict_old_on_tcp_table_limit = 1 # range: [0, 1] + evict_old_on_udp_table_limit = 1 # range: [0, 1] + + expire_period_ms = 0 # range: [0, 60000] (ms) + expire_batch_max = 1024 # range: [1, 1024] + + [session_manager.tcp_timeout_ms] + init = 500 # range: [1, 60000] (ms) + handshake = 500 # range: [1, 60000] (ms) + data = 500 # range: [1, 15999999000] (ms) + half_closed = 500 # range: [1, 604800000] (ms) + time_wait = 500 # range: [1, 600000] (ms) + discard_default = 1000 # range: [1, 15999999000] (ms) + unverified_rst = 500 # range: [1, 600000] (ms) + + [session_manager.udp_timeout_ms] + data = 500 # range: [1, 15999999000] (ms) + discard_default = 500 # range: [1, 15999999000] (ms) + + [session_manager.duplicated_packet_bloom_filter] + enable = 0 + capacity = 1000000 # range: [1, 4294967295] + time_window_ms = 10000 # range: [1, 60000] (ms) + error_rate = 0.00001 # range: [0.0, 1.0] + + [session_manager.evicted_session_bloom_filter] + enable = 0 # range: [0, 1] + capacity = 1000000 # range: [1, 4294967295] + time_window_ms = 10000 # range: [1, 60000] (ms) + error_rate = 0.00001 # range: [0.0, 1.0] + + [session_manager.tcp_reassembly] + enable = 1 # range: [0, 1] + timeout_ms = 100 # range: [1, 60000] (ms) + buffered_segments_max = 256 # range: [2, 4096] per flow + +[stat] + merge_interval_ms = 500 # range: [0, 60000] (ms) + output_interval_ms = 1000 # range: [0, 60000] (ms) diff --git a/vendors/CMakeLists.txt b/vendors/CMakeLists.txt index 5ed2c1b..07d5711 100644 --- a/vendors/CMakeLists.txt +++ b/vendors/CMakeLists.txt @@ -97,4 +97,41 @@ add_library(libevent-static STATIC IMPORTED GLOBAL) add_dependencies(libevent-static libevent) set_property(TARGET libevent-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libevent.a) set_property(TARGET libevent-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) -set_property(TARGET libevent-static PROPERTY INTERFACE_LINK_LIBRARIES pthread)
\ No newline at end of file +set_property(TARGET libevent-static PROPERTY INTERFACE_LINK_LIBRARIES pthread) + +set(VENDOR_BUILD ${CMAKE_BINARY_DIR}/vendor/vbuild) +# colm-0.14.7 +ExternalProject_Add(colm PREFIX colm + URL ${CMAKE_CURRENT_SOURCE_DIR}/colm-0.14.7.tar.gz + CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix=${VENDOR_BUILD} + BUILD_COMMAND make + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1) + +# ragel-7.0.4 +ExternalProject_Add(ragel PREFIX ragel + URL ${CMAKE_CURRENT_SOURCE_DIR}/ragel-7.0.4.tar.gz + CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix=${VENDOR_BUILD} --disable-manual --with-colm=${VENDOR_BUILD} + DEPENDS colm + BUILD_COMMAND make + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1) + +# HyperScan 5.4.2 +ExternalProject_Add(hyperscan PREFIX hyperscan + URL ${CMAKE_CURRENT_SOURCE_DIR}/hyperscan-5.4.2.tar.gz + DEPENDS ragel + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${VENDOR_BUILD} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_C_FLAGS="-fPIC" -DCMAKE_CXX_FLAGS="-fPIC") + +ExternalProject_Get_Property(hyperscan INSTALL_DIR) +file(MAKE_DIRECTORY ${VENDOR_BUILD}/include) + +add_library(hyperscan_static STATIC IMPORTED GLOBAL) +add_dependencies(hyperscan_static hyperscan) +set_property(TARGET hyperscan_static PROPERTY IMPORTED_LOCATION ${VENDOR_BUILD}/lib64/libhs.a) +set_property(TARGET hyperscan_static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${VENDOR_BUILD}/include) + +add_library(hyperscan_runtime_static STATIC IMPORTED GLOBAL) +add_dependencies(hyperscan_runtime_static hyperscan) +set_property(TARGET hyperscan_runtime_static PROPERTY IMPORTED_LOCATION ${VENDOR_BUILD}/lib64/libhs_runtime.a) +set_property(TARGET hyperscan_runtime_static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${VENDOR_BUILD}/include)
\ No newline at end of file diff --git a/vendors/colm-0.14.7.tar.gz b/vendors/colm-0.14.7.tar.gz Binary files differnew file mode 100644 index 0000000..a73e692 --- /dev/null +++ b/vendors/colm-0.14.7.tar.gz diff --git a/vendors/hyperscan-5.4.2.tar.gz b/vendors/hyperscan-5.4.2.tar.gz Binary files differnew file mode 100644 index 0000000..fa49221 --- /dev/null +++ b/vendors/hyperscan-5.4.2.tar.gz diff --git a/vendors/ragel-7.0.4.tar.gz b/vendors/ragel-7.0.4.tar.gz Binary files differnew file mode 100644 index 0000000..d37daf6 --- /dev/null +++ b/vendors/ragel-7.0.4.tar.gz |
