diff --git a/.gitignore b/.gitignore index 0fde286..1b86e7e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,268 @@ -CVS -*.pyc -*.beam +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* *~ -.cvsignore -*.zip +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/ diff --git a/c/.gitignore b/c/.gitignore index 5579800..942b144 100644 --- a/c/.gitignore +++ b/c/.gitignore @@ -16,3 +16,212 @@ save_to_pcap unmap wide_recorder version.c + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt \ No newline at end of file diff --git a/c/Corelatus-GTH-example-code.sdf b/c/Corelatus-GTH-example-code.sdf new file mode 100644 index 0000000..f5c92ff Binary files /dev/null and b/c/Corelatus-GTH-example-code.sdf differ diff --git a/c/Corelatus-GTH-example-code.v12.suo b/c/Corelatus-GTH-example-code.v12.suo new file mode 100644 index 0000000..93f06e8 Binary files /dev/null and b/c/Corelatus-GTH-example-code.v12.suo differ diff --git a/c/NMakefile b/c/NMakefile index 23f7ef5..bd8610c 100755 --- a/c/NMakefile +++ b/c/NMakefile @@ -19,7 +19,8 @@ header_files=gth_client_xml_parse.h gth_apilib.h common_c_files=gth_client_xml_parse.c gth_apilib.c version.c LIBS_WIN32=ws2_32.lib -CFLAGS=/DWIN32 /nologo /DEBUG /Zi /MDd +#CFLAGS=/DWIN32 /nologo /DEBUG /Zi /MDd +CFLAGS=/DWIN32 /nologo /RELEASE /MD CC=cl RM=del diff --git a/c/connect_timeslots.obj b/c/connect_timeslots.obj new file mode 100644 index 0000000..0b216e2 Binary files /dev/null and b/c/connect_timeslots.obj differ diff --git a/c/disable.obj b/c/disable.obj new file mode 100644 index 0000000..29ca6ef Binary files /dev/null and b/c/disable.obj differ diff --git a/c/duplex_lapd.obj b/c/duplex_lapd.obj new file mode 100644 index 0000000..264b271 Binary files /dev/null and b/c/duplex_lapd.obj differ diff --git a/c/enable.obj b/c/enable.obj new file mode 100644 index 0000000..1cec1e8 Binary files /dev/null and b/c/enable.obj differ diff --git a/c/gth_apilib.c b/c/gth_apilib.c index e3333eb..e4de63d 100644 --- a/c/gth_apilib.c +++ b/c/gth_apilib.c @@ -188,7 +188,7 @@ void *checked_malloc(size_t size) void gth_event_handler(void *data, GTH_resp *resp) { GTH_resp *child; - GTH_api *api = data; + GTH_api *api = (GTH_api*)data; assert(api); assert(resp); @@ -284,16 +284,16 @@ int gth_connect(GTH_api *api, const char *address, const int verbose) // Helper for simple commands. static int single_arg_ok_response(GTH_api *api, - const char *template, + const char *tmpl, const char *arg) { char buffer[MAX_COMMAND]; assert(api); - assert(template); + assert(tmpl); assert(arg); - snprintf(buffer, MAX_COMMAND, template, arg); + snprintf(buffer, MAX_COMMAND, tmpl, arg); api_write(api, buffer); if (check_api_response(api, GTH_RESP_OK, 0)) { @@ -641,17 +641,17 @@ int gth_new_lapd_layer(GTH_api *api, { char command[MAX_COMMAND]; int result; - const char* template; + const char* tmpl; assert(ts > 0 && ts < 32); assert(!strcmp("network", side) || !strcmp("user", side)); - template = "" + tmpl = "" "" "" ""; - result = snprintf(command, MAX_COMMAND, template, side, sapi, + result = snprintf(command, MAX_COMMAND, tmpl, side, sapi, tei, ip, port, tag, span, ts, span, ts); assert(result < MAX_COMMAND); api_write(api, command); @@ -671,15 +671,15 @@ int gth_new_lapd_monitor(GTH_api *api, { char command[MAX_COMMAND]; int result; - const char* template; + const char* tmpl; assert(ts > 0 && ts < 32); - template = "" + tmpl = "" "" ""; - result = snprintf(command, MAX_COMMAND, template, ip, port, tag, span, ts); + result = snprintf(command, MAX_COMMAND, tmpl, ip, port, tag, span, ts); assert(result < MAX_COMMAND); api_write(api, command); result = recv_job_id(api, job_id); @@ -736,18 +736,18 @@ int gth_new_mtp2_monitor_opt(GTH_api *api, char sources[MAX_COMMAND]; char attributes[MAX_COMMAND]; int result; - const char* template; + const char* tmpl; assert(n_timeslots < 32 && n_timeslots > 0); result = kv_to_attributes(attributes, MAX_COMMAND, options, n_options); - template = "" + tmpl = "" "%s"; format_sources(span, timeslots, n_timeslots, sources); - result = snprintf(command, MAX_COMMAND, template, + result = snprintf(command, MAX_COMMAND, tmpl, attributes, ip, port, tag, sources); assert(result < MAX_COMMAND); api_write(api, command); @@ -767,17 +767,17 @@ int gth_new_player(GTH_api *api, int data_socket; char command[MAX_COMMAND]; int result; - const char* template; + const char* tmpl; assert(api); assert(span); assert(job_id); assert(timeslot > 0 && timeslot < 32); - template = "" + tmpl = "" ""; - result = snprintf(command, MAX_COMMAND, template, + result = snprintf(command, MAX_COMMAND, tmpl, api->my_ip, listen_port, span, timeslot); assert(result < MAX_COMMAND); api_write(api, command); @@ -800,18 +800,18 @@ int gth_new_recorder(GTH_api *api, int data_socket; char command[MAX_COMMAND]; int result; - const char* template; + const char* tmpl; assert(api); assert(span); assert(timeslot > 0 && timeslot < 32); assert(job_id); - template = "" + tmpl = "" "" ""; - result = snprintf(command, MAX_COMMAND, template, + result = snprintf(command, MAX_COMMAND, tmpl, span, timeslot, api->my_ip, listen_port); assert(result < MAX_COMMAND); api_write(api, command); @@ -830,14 +830,14 @@ int gth_new_tone_detector(GTH_api *api, char *job_id, GTH_tone_handler* handler) { - const char *template; + const char *tmpl; int result; char command[MAX_COMMAND]; - template = "" + tmpl = "" ""; - result = snprintf(command, MAX_COMMAND, template, span, timeslot); + result = snprintf(command, MAX_COMMAND, tmpl, span, timeslot); assert(result < MAX_COMMAND); api_write(api, command); result = recv_job_id(api, job_id); @@ -873,17 +873,17 @@ int gth_new_wide_recorder(GTH_api *api, int data_socket = gth_make_udp_socket(&portno); char command[MAX_COMMAND]; int result; - const char* template; + const char* tmpl; assert(api); assert(span); assert(job_id); - template = "" + tmpl = "" "" ""; - result = snprintf(command, MAX_COMMAND, template, + result = snprintf(command, MAX_COMMAND, tmpl, span, api->my_ip, portno); assert(result < MAX_COMMAND); api_write(api, command); @@ -1381,7 +1381,7 @@ static int query_single_resource(GTH_api *api, if (is_text_following_resource_query(name)) { int result; - char *text_buffer = checked_malloc(MAX_LOGFILE); + char *text_buffer = (char*)checked_malloc(MAX_LOGFILE); result = next_api_response(api, text_buffer, MAX_LOGFILE); if (result != 0) @@ -1392,13 +1392,13 @@ static int query_single_resource(GTH_api *api, } (*n_attributes)++; - *attributes = checked_malloc(sizeof(GTH_attribute) * *n_attributes); + *attributes = (GTH_attribute*)checked_malloc(sizeof(GTH_attribute) * *n_attributes); (*attributes)[*n_attributes - 1].key = "log_body"; (*attributes)[*n_attributes - 1].value = text_buffer; } else { - *attributes = checked_malloc(sizeof(GTH_attribute) * *n_attributes); + *attributes = (GTH_attribute*)checked_malloc(sizeof(GTH_attribute) * *n_attributes); } for (x = 0; x < resource->n_children; x++) { @@ -1446,7 +1446,7 @@ static int query_inventory(GTH_api *api, if (resp->type == GTH_RESP_STATE) { - *attributes = checked_malloc(sizeof(GTH_attribute) * resp->n_children); + *attributes =(GTH_attribute*) checked_malloc(sizeof(GTH_attribute) * resp->n_children); *n_attributes = resp->n_children; for (x = 0; x < resp->n_children; x++) { diff --git a/c/gth_apilib.obj b/c/gth_apilib.obj new file mode 100644 index 0000000..83353c3 Binary files /dev/null and b/c/gth_apilib.obj differ diff --git a/c/gth_client_xml_parse.c b/c/gth_client_xml_parse.c index 17cc299..2085cab 100644 --- a/c/gth_client_xml_parse.c +++ b/c/gth_client_xml_parse.c @@ -72,7 +72,7 @@ copy_to_new_add_null(const char *src, int len) { char *result; - result = checked_malloc(len + 1); + result = (char*)checked_malloc(len + 1); memcpy(result, src, len); result[len] = 0; @@ -84,7 +84,7 @@ copy_to_new_add_null(const char *src, int len) // Return: the number of characters that were in the string. static int scan_string(const char* string, GTH_token *token, const char end) { - char* endptr; + const char* endptr; int len; endptr = strchr(string, end); @@ -124,7 +124,7 @@ int gth_scan(const char *string, GTH_token **ret_tokens) size_t len; int max_token = 5; int tokens_used = 0; - GTH_token *start = checked_malloc(max_token * sizeof(GTH_token)); + GTH_token *start = (GTH_token*)checked_malloc(max_token * sizeof(GTH_token)); GTH_token *current = start; //---- @@ -132,7 +132,7 @@ int gth_scan(const char *string, GTH_token **ret_tokens) tokens_used = (current - start); if ( tokens_used == max_token) { max_token = max_token * 2; - start = checked_realloc(start, max_token * sizeof(GTH_token)); + start = (GTH_token*)checked_realloc(start, max_token * sizeof(GTH_token)); current = start + tokens_used; } @@ -164,7 +164,7 @@ int gth_scan(const char *string, GTH_token **ret_tokens) tokens_used = (current - start); if ( tokens_used == max_token) { max_token = max_token * 2; - start = checked_realloc(start, max_token * sizeof(GTH_token)); + start = (GTH_token*)checked_realloc(start, max_token * sizeof(GTH_token)); current = start + tokens_used; } @@ -300,7 +300,7 @@ static GTH_resp *resp_add_child(GTH_resp *resp, GTH_resp_type type) if (resp->n_children >= resp->allocated_children) { resp->allocated_children = resp->allocated_children * 2 + 3; - resp->children = checked_realloc(resp->children, + resp->children =(GTH_resp_struct*) checked_realloc(resp->children, resp->allocated_children * sizeof(GTH_resp)); } @@ -319,7 +319,7 @@ static void resp_add_attribute(GTH_resp *resp, char *key, char *value) if (resp->allocated_attributes <= resp->n_attributes) { resp->allocated_attributes = 2*resp->allocated_attributes + 2; - resp->attributes = checked_realloc(resp->attributes, + resp->attributes =(GTH_attribute*) checked_realloc(resp->attributes, resp->allocated_attributes * sizeof(GTH_attribute)); } @@ -334,7 +334,7 @@ static void resp_add_attribute(GTH_resp *resp, char *key, char *value) static GTH_token *parse(GTH_token *token, GTH_resp *resp); static GTH_token *attributes(GTH_token *token, GTH_resp *resp); static GTH_token *parse_inside_tag(GTH_token *token, char **text); -static enum Token_type name_to_token_type(const char* name); +static GTH_resp_type name_to_token_type(const char* name); void gth_free_resp(GTH_resp *resp); static int can_lookahead(const GTH_token *token, int n); @@ -348,7 +348,7 @@ GTH_resp *gth_parse(const char *string) { GTH_token *tokens; GTH_token *end; - GTH_resp *resp = checked_malloc(sizeof(GTH_resp)); + GTH_resp *resp = (GTH_resp*)checked_malloc(sizeof(GTH_resp)); GTH_resp *old; new_resp(resp, GTH_RESP_ERROR); @@ -381,7 +381,7 @@ static GTH_token *parse(GTH_token *token, GTH_resp *list_of_trees) GTH_token *name; GTH_token *slash; GTH_token *close; - char *tag_name; + const char *tag_name; GTH_resp *tree = 0; if (!can_lookahead(token, 2)) { @@ -484,7 +484,7 @@ static GTH_token *attributes(GTH_token *token, GTH_resp *resp) { } -static enum Token_type name_to_token_type(const char* name) +static GTH_resp_type name_to_token_type(const char* name) { if (!strcmp(name, "alarm")) return GTH_RESP_ALARM; if (!strcmp(name, "alert")) return GTH_RESP_ALERT; @@ -519,7 +519,7 @@ static enum Token_type name_to_token_type(const char* name) fprintf(stderr, "don't know what this is: %s\n", name); assert(!"unknown tag"); - return 0; // never reached + return (GTH_resp_type)0; // never reached } // Are there at least N tokens left to look at. diff --git a/c/gth_client_xml_parse.obj b/c/gth_client_xml_parse.obj new file mode 100644 index 0000000..d41acd4 Binary files /dev/null and b/c/gth_client_xml_parse.obj differ diff --git a/c/install_release.obj b/c/install_release.obj new file mode 100644 index 0000000..e5cd804 Binary files /dev/null and b/c/install_release.obj differ diff --git a/c/install_start_script.obj b/c/install_start_script.obj new file mode 100644 index 0000000..7a9ab26 Binary files /dev/null and b/c/install_start_script.obj differ diff --git a/c/map.obj b/c/map.obj new file mode 100644 index 0000000..143e358 Binary files /dev/null and b/c/map.obj differ diff --git a/c/monitor_dtmf.obj b/c/monitor_dtmf.obj new file mode 100644 index 0000000..53d0c7c Binary files /dev/null and b/c/monitor_dtmf.obj differ diff --git a/c/playback_file.obj b/c/playback_file.obj new file mode 100644 index 0000000..048ea1e Binary files /dev/null and b/c/playback_file.obj differ diff --git a/c/query_set.obj b/c/query_set.obj new file mode 100644 index 0000000..04294ee Binary files /dev/null and b/c/query_set.obj differ diff --git a/c/record.obj b/c/record.obj new file mode 100644 index 0000000..04a3c9e Binary files /dev/null and b/c/record.obj differ diff --git a/c/save_to_pcap.c b/c/save_to_pcap.c index f785c7c..a051950 100644 --- a/c/save_to_pcap.c +++ b/c/save_to_pcap.c @@ -51,6 +51,7 @@ #include #include #include +#include #ifdef WIN32 #include @@ -72,21 +73,21 @@ typedef unsigned short u16; // PCap classic file format structures. #pragma pack(1) typedef struct { - u32 magic; - u16 major_version; - u16 minor_version; - u32 GMT_to_localtime; - u32 sigfigs; - u32 snaplen; - u32 network; + u32 magic; + u16 major_version; + u16 minor_version; + u32 GMT_to_localtime; + u32 sigfigs; + u32 snaplen; + u32 network; } PACK_SUFFIX PCap_classic_global_header; #pragma pack(1) typedef struct { - u32 ts_sec; - u32 ts_us; - u32 incl_len; - u32 orig_len; + u32 ts_sec; + u32 ts_us; + u32 incl_len; + u32 orig_len; } PACK_SUFFIX PCap_classic_packet_header; //-------------------------------------------------- @@ -94,38 +95,38 @@ typedef struct { #pragma pack(1) typedef struct { - u16 code; - u16 length; + u16 code; + u16 length; } PACK_SUFFIX PCap_NG_option; #pragma pack(1) typedef struct { - u32 type; - u32 block_total_length; - u32 byte_order_magic; - u16 major_version; - u16 minor_version; - unsigned long long section_length; + u32 type; + u32 block_total_length; + u32 byte_order_magic; + u16 major_version; + u16 minor_version; + unsigned long long section_length; } PACK_SUFFIX PCap_NG_shb; typedef struct { - u32 type; - u32 block_total_length; - u16 link_type; - u16 reserved; - u32 snaplen; + u32 type; + u32 block_total_length; + u16 link_type; + u16 reserved; + u32 snaplen; } PACK_SUFFIX PCap_NG_idb; #pragma pack(1) typedef struct { - u32 type; - u32 block_total_length; - u32 interface_id; - u32 timestamp_hi; - u32 timestamp_lo; - u32 captured_len; - u32 packet_len; + u32 type; + u32 block_total_length; + u32 interface_id; + u32 timestamp_hi; + u32 timestamp_lo; + u32 captured_len; + u32 packet_len; } PACK_SUFFIX PCap_NG_epb; // GTH socket structure. An SS7 MTP-2 signal unit can't be more than @@ -144,11 +145,11 @@ typedef struct { #define MAX_MTP2_CHANNELS 72 typedef struct { - u16 tag; - u16 flags; - u16 timestamp_hi; - u32 timestamp_lo; - char payload[MAX_SIGNAL_UNIT]; + u16 tag; + u16 flags; + u16 timestamp_hi; + u32 timestamp_lo; + char payload[MAX_SIGNAL_UNIT]; } GTH_mtp2; enum PCap_format { PCAP_CLASSIC, PCAP_NG }; @@ -157,62 +158,68 @@ enum PCap_format { PCAP_CLASSIC, PCAP_NG }; #define LINK_TYPE_MTP2 140 typedef struct { - char *span; - int timeslots[MAX_TIMESLOTS]; - int n_timeslots; + char *span; + int timeslots[MAX_TIMESLOTS]; + int n_timeslots; } Channel_t; //---------------------------------------------------------------------- void usage() { - fprintf(stderr, - "save_to_pcap git_head: %s build_hostname: %s\n\n" - - "save_to_pcap [...] " - "\n\nSave decoded MTP-2 signal units to a file in libpcap format, " - "\nsuitable for examining with wireshark, tshark or other network" - "\nanalyser software.\n" - "\n: [-c] [-f fisu=no] [-m] [-n ] [-v]" - "\n-c: save in the classic Pcap format (default is the newer Pcap-NG)" - "\n-f fisu=no: remove all MTP-2 FISUs" - "\n-f esnf=yes: use MTP-2 extended sequence numbers" - "\n-m: tells the GTH that you are using a -20dB monitor point" - "\n-n : rotate the output file after packets" - "\n-n : rotate the output file after seconds" - "\n-v: print API commands and responses (verbose)" - "\n" - "\n is the GTH's IP address or hostname" - "\n is a list of spans and timeslots:" - "\n [...] [...]" - "\n e.g. 1A 2A 1 2 3 monitors timeslots 1, 2 and 3 on span 1A and 2A." - "\n e.g. 1A 1 2A 2 3A 3 4 monitors timeslot 1 on 1A, 2 on 2A and 3 and 4 on 3A." - "\n can also be a range of timeslots for Nx64kbit/s signalling):" - "\n -[,-]" - "\n e.g. 1A 1-31 monitors one 1980kbit/s channel on timeslots 1-31" - "\n e.g. 1A 1-15,17-31 monitors one 1920kbit/s channel" - "\n e.g. 1A 1-4 1B 1-4 monitors two 256kbit/s channels" - "\n is the name of a span, e.g. '1A'" - "\n is a timeslot number, from 1 to 31" - "\n can be -, which means standard output.\n\n", - git_head, build_hostname); - - fprintf(stderr, - "Examples (on hardware with electrical E1/T1 ports):\n" - "./save_to_pcap 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" - "./save_to_pcap 172.16.1.10 1A 2A 3A 4A 1 2 3 4 isup_capture.pcapng\n" - "./save_to_pcap 172.16.1.10 1A 2A 16 1B 5 6 7 8 capture.pcapng\n" - "./save_to_pcap -m 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" - "./save_to_pcap -m -n packets:1000 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" - "./save_to_pcap -m -n duration:60 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" - "./save_to_pcap -c 172.16.1.10 1A 2A 16 - | tshark -V -i - \n" - "./save_to_pcap -c 172.16.1.10 1A 2A 16 - | wireshark -k -i - \n" - "./save_to_pcap -c 172.16.1.10 1A 2A 16 \\\\.\\pipe\\isup_capture.1\n"); - - fprintf(stderr, - "\nExamples (on SDH/SONET hardware, usually optical):\n" - "./save_to_pcap 172.16.1.10 pcm55 16 isup_capture.pcapng\n\n"); - - exit(-1); + fprintf(stderr, + "save_to_pcap git_head: %s build_hostname: %s\n\n" + + "save_to_pcap [...] " + "\n\nSave decoded MTP-2 signal units to a file in libpcap format, " + "\nsuitable for examining with wireshark, tshark or other network" + "\nanalyser software.\n" + "\n: [-c] [-f fisu=no] [-m] [-n ] [-v]" + "\n-c: save in the classic Pcap format (default is the newer Pcap-NG)" + "\n-f fisu=no: remove all MTP-2 FISUs" + "\n-f esnf=yes: use MTP-2 extended sequence numbers" + "\n-m: tells the GTH that you are using a -20dB monitor point" + "\n-n : rotate the output file after packets" + "\n-n : rotate the output file after seconds" + "\n-s Stop the process instead of rotating the files" + "\n-v: print API commands and responses (verbose)" + "\n-o: Output format" + "\n\tdefault: it uses in output file name base_name with counter number (default option)" + "\n\tutc=no: add local time after counter number (standard output like tshark)" + "\n\tutc=yes: add utc time after counter number (standard output like tshark)" + "\n" + "\n is the GTH's IP address or hostname" + "\n is a list of spans and timeslots:" + "\n [...] [...]" + "\n e.g. 1A 2A 1 2 3 monitors timeslots 1, 2 and 3 on span 1A and 2A." + "\n e.g. 1A 1 2A 2 3A 3 4 monitors timeslot 1 on 1A, 2 on 2A and 3 and 4 on 3A." + "\n can also be a range of timeslots for Nx64kbit/s signalling):" + "\n -[,-]" + "\n e.g. 1A 1-31 monitors one 1980kbit/s channel on timeslots 1-31" + "\n e.g. 1A 1-15,17-31 monitors one 1920kbit/s channel" + "\n e.g. 1A 1-4 1B 1-4 monitors two 256kbit/s channels" + "\n is the name of a span, e.g. '1A'" + "\n is a timeslot number, from 1 to 31" + "\n can be -, which means standard output.\n\n", + git_head, build_hostname); + + fprintf(stderr, + "Examples (on hardware with electrical E1/T1 ports):\n" + "./save_to_pcap 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" + "./save_to_pcap 172.16.1.10 1A 2A 3A 4A 1 2 3 4 isup_capture.pcapng\n" + "./save_to_pcap 172.16.1.10 1A 2A 16 1B 5 6 7 8 capture.pcapng\n" + "./save_to_pcap -m 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" + "./save_to_pcap -m -n packets:1000 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" + "./save_to_pcap -m -n duration:60 172.16.1.10 1A 2A 16 isup_capture.pcapng\n" + "./save_to_pcap -c 172.16.1.10 1A 2A 16 - | tshark -V -i - \n" + "./save_to_pcap -c 172.16.1.10 1A 2A 16 - | wireshark -k -i - \n" + "./save_to_pcap -c 172.16.1.10 1A 2A 16 \\\\.\\pipe\\isup_capture.1\n" + "./save_to_pcap -o utc=yes 172.16.1.10 1A 2A 16 isup_capture.pcapng\n"); + + fprintf(stderr, + "\nExamples (on SDH/SONET hardware, usually optical):\n" + "./save_to_pcap 172.16.1.10 pcm55 16 isup_capture.pcapng\n\n"); + + exit(-1); } //---------------------------------------------------------------------- @@ -225,24 +232,24 @@ usage() { #define fwrite write_to_handle_or_file static int write_to_handle_or_file(void *buffer, - int length, - int items, - HANDLE_OR_FILEPTR file) +int length, +int items, +HANDLE_OR_FILEPTR file) { - int result; - DWORD written; - - result = WriteFile(file, buffer, length * items, &written, 0); - if (written != length || !result ) { - return 0; - } - return 1; + int result; + DWORD written; + + result = WriteFile(file, buffer, length * items, &written, 0); + if (written != length || !result) { + return 0; + } + return 1; } static HANDLE_OR_FILEPTR stdout_handle_or_file() { - return GetStdHandle(STD_OUTPUT_HANDLE); + return GetStdHandle(STD_OUTPUT_HANDLE); } #define fclose CloseHandle @@ -251,7 +258,7 @@ stdout_handle_or_file() static HANDLE_OR_FILEPTR stdout_handle_or_file() { - return stdout; + return stdout; } #endif @@ -260,31 +267,31 @@ static HANDLE_OR_FILEPTR open_windows_pipe(const char *filename) { #ifdef WIN32 - HANDLE pipe; - int result; - - pipe = CreateNamedPipe(filename, - PIPE_ACCESS_OUTBOUND, // write-only - PIPE_TYPE_MESSAGE | PIPE_WAIT, // blocking writes - 1, // only allow one pipe - 70000, // write buffer. GTH max is 64k - 10000, // read buffer. We don't read - 0, // default timeout - 0); // no security attributes - - if (pipe == INVALID_HANDLE_VALUE) { - die("Unable to create a named pipe. Giving up."); - } - - result = ConnectNamedPipe(pipe, 0); - if (!result) { - die("Unabled to connect the named pipe. Giving up."); - } - - return pipe; + HANDLE pipe; + int result; + + pipe = CreateNamedPipe(filename, + PIPE_ACCESS_OUTBOUND, // write-only + PIPE_TYPE_MESSAGE | PIPE_WAIT, // blocking writes + 1, // only allow one pipe + 70000, // write buffer. GTH max is 64k + 10000, // read buffer. We don't read + 0, // default timeout + 0); // no security attributes + + if (pipe == INVALID_HANDLE_VALUE) { + die("Unable to create a named pipe. Giving up."); + } + + result = ConnectNamedPipe(pipe, 0); + if (!result) { + die("Unabled to connect the named pipe. Giving up."); + } + + return pipe; #else - die("Cannot open a windows named pipe on a non-windows OS. Giving up."); - return 0; + die("Cannot open a windows named pipe on a non-windows OS. Giving up."); + return 0; #endif } @@ -292,35 +299,35 @@ static void flush_file(HANDLE_OR_FILEPTR hf) { #ifdef WIN32 - FlushFileBuffers(hf); + FlushFileBuffers(hf); #else - fflush(hf); + fflush(hf); #endif } static void open_file_for_writing(HANDLE_OR_FILEPTR *hf, const char *filename) { - int result = 0; + int result = 0; #ifdef WIN32 - *hf = CreateFile(filename, - GENERIC_WRITE, - 0, - 0, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - 0); - - if (*hf == INVALID_HANDLE_VALUE) { - *hf = 0; - } + *hf = CreateFile(filename, + GENERIC_WRITE, + 0, + 0, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + 0); + + if (*hf == INVALID_HANDLE_VALUE) { + *hf = 0; + } #else - result = fopen_s(hf, filename, "wb"); + result = fopen_s(hf, filename, "wb"); #endif - if (*hf == 0 || result != 0) { - fprintf(stderr, "unable to open %s for writing. Aborting.\n", filename); - exit(-1); - } + if (*hf == 0 || result != 0) { + fprintf(stderr, "unable to open %s for writing. Aborting.\n", filename); + exit(-1); + } } //---------------------------------------------------------------------- @@ -328,74 +335,74 @@ open_file_for_writing(HANDLE_OR_FILEPTR *hf, const char *filename) // Optical E1/T1: just enable; no special options required. static void enable_optical_l1(GTH_api *api, - const char* span, - const int monitoring) +const char* span, +const int monitoring) { - int result; + int result; - if (monitoring) - fprintf(stderr, "Warning: ignoring -m switch on optical hardware.\n"); + if (monitoring) + fprintf(stderr, "Warning: ignoring -m switch on optical hardware.\n"); - result = gth_enable(api, span, 0, 0); + result = gth_enable(api, span, 0, 0); - if (result != 0) - die("Setting up L1 failed. (-v switch gives more information)"); + if (result != 0) + die("Setting up L1 failed. (-v switch gives more information)"); } // Electrical E1: disable TX pins and possibly enable -20dB monitoring static void enable_electrical_l1(GTH_api *api, - const char* span, - const int monitoring) +const char* span, +const int monitoring) { - int result; - char span_name[20]; + int result; + char span_name[20]; - int n_attributes = (monitoring)?3:2; - GTH_attribute attributes[] = { {"status", "enabled"}, - {"tx_enabled", "false"}, - {"monitoring", "true"} - }; + int n_attributes = (monitoring) ? 3 : 2; + GTH_attribute attributes[] = { { "status", "enabled" }, + { "tx_enabled", "false" }, + { "monitoring", "true" } + }; - assert(sizeof(span_name) > (strlen(span) + strlen("pcm"))); - strncpy_s(span_name, sizeof span_name, "pcm", sizeof span_name - 1); - strncat(span_name, span, sizeof span_name); + assert(sizeof(span_name) > (strlen(span) + strlen("pcm"))); + strncpy_s(span_name, sizeof span_name, "pcm", sizeof span_name - 1); + strncat(span_name, span, sizeof span_name); - // Use here: isn't supported until gth2_system_37a. - result = gth_set(api, span_name, attributes, n_attributes); + // Use here: isn't supported until gth2_system_37a. + result = gth_set(api, span_name, attributes, n_attributes); - if (result != 0) - die("Setting up L1 failed. (-v switch gives more information)"); + if (result != 0) + die("Setting up L1 failed. (-v switch gives more information)"); } // Start L1 for all channels. // This can cause an L1 to be started multiple times. That's OK. static void enable_l1(GTH_api *api, - const Channel_t channels[], - const int n_channels, - const int monitoring) +const Channel_t channels[], +const int n_channels, +const int monitoring) { - char architecture[10]; - int i; - int result; - - result = gth_query_resource_attribute(api, "board", "architecture", - architecture, 10); - if (result != 0) - die("Unable to query hardware architecture. Giving up."); - - architecture[3] = 0; - if (strcmp(architecture, "gth") == 0) { - for (i = 0; i < n_channels; i++) { - enable_electrical_l1(api, channels[i].span, monitoring); - } - } - else { - for (i = 0; i < n_channels; i++) { - enable_optical_l1(api, channels[i].span, monitoring); - } - } + char architecture[10]; + int i; + int result; + + result = gth_query_resource_attribute(api, "board", "architecture", + architecture, 10); + if (result != 0) + die("Unable to query hardware architecture. Giving up."); + + architecture[3] = 0; + if (strcmp(architecture, "gth") == 0) { + for (i = 0; i < n_channels; i++) { + enable_electrical_l1(api, channels[i].span, monitoring); + } + } + else { + for (i = 0; i < n_channels; i++) { + enable_optical_l1(api, channels[i].span, monitoring); + } + } } #define MAX_MTP2_ATTRS 2 @@ -403,88 +410,94 @@ enable_l1(GTH_api *api, // Start up MTP-2 monitoring on the given span and timeslot static void monitor_mtp2(GTH_api *api, - const Channel_t *channel, - int tag, - int drop_fisus, - int esnf, - int listen_port, - int listen_socket - ) +const Channel_t *channel, +int tag, +int drop_fisus, +int esnf, +int listen_port, +int listen_socket +) { - int result; - char job_id[MAX_JOB_ID]; - GTH_attribute attrs[MAX_MTP2_ATTRS]; - int n_attrs = 0; - - if (drop_fisus) { - attrs[n_attrs].key = "fisu"; - attrs[n_attrs].value = "no"; - n_attrs++; - } - - if (esnf) { - attrs[n_attrs].key = "esnf"; - attrs[n_attrs].value = "yes"; - n_attrs++; - } - - result = gth_new_mtp2_monitor_opt(api, tag, - channel->span, - channel->timeslots, - channel->n_timeslots, - job_id, api->my_ip, listen_port, - attrs, n_attrs); - if (result != 0) - die("Setting up MTP2 monitoring failed. (-v gives more information)"); - - return; + int result; + char job_id[MAX_JOB_ID]; + GTH_attribute attrs[MAX_MTP2_ATTRS]; + int n_attrs = 0; + + if (drop_fisus) { + attrs[n_attrs].key = "fisu"; + attrs[n_attrs].value = "no"; + n_attrs++; + } + + if (esnf) { + attrs[n_attrs].key = "esnf"; + attrs[n_attrs].value = "yes"; + n_attrs++; + } + + result = gth_new_mtp2_monitor_opt(api, tag, + channel->span, + channel->timeslots, + channel->n_timeslots, + job_id, api->my_ip, listen_port, + attrs, n_attrs); + if (result != 0) + die("Setting up MTP2 monitoring failed. (-v gives more information)"); + + return; } // Read exactly the requested number of bytes from the given descriptor void read_exact(int fd, char* buf, size_t count) { - size_t this_time; + size_t this_time; - while (count > 0) { - this_time = recv(fd, buf, count, 0); - if (this_time <= 0) - die("MTP-2 data socket from GTH unexpectedly closed\n"); + while (count > 0) { + this_time = recv(fd, buf, count, 0); + if (this_time <= 0) + die("MTP-2 data socket from GTH unexpectedly closed\n"); - count -= this_time; - buf += this_time; - } + count -= this_time; + buf += this_time; + } } void inline checked_fwrite(void *b, int n, HANDLE_OR_FILEPTR f) { - int result = fwrite(b, n, 1, f); + int result = fwrite(b, n, 1, f); - if (result != 1) { - die("fwrite failed. (Is the output file writeable?)"); - } + if (result != 1) { + die("fwrite failed. (Is the output file writeable?)"); + } } static void write_pcap_classic_header(HANDLE_OR_FILEPTR file) { - PCap_classic_global_header header; - - // The pcap file is native-endian, i.e. wireshark uses the magic value - // to figure out if it was created on a little-endian or big-endian machine. - header.magic = 0xa1b2c3d4; - header.major_version = 2; - header.minor_version = 4; - header.GMT_to_localtime = 0; - header.sigfigs = 0; - header.snaplen = 65535; - header.network = LINK_TYPE_MTP2; - - checked_fwrite((void*)&header, sizeof header, file); - - return; + PCap_classic_global_header header; + + // The pcap file is native-endian, i.e. wireshark uses the magic value + // to figure out if it was created on a little-endian or big-endian machine. + /* + TIMESTAMP PRECISION NOTICE: + using 0xa1b2c3d4, the application informs readers that the timestamp precision is set to MICROseconds. + using 0xa1b2c34d, the application informs readers that the timestamp precision is set to NANOseconds. + if the magic number is changed, the code should be checked for other "TIMESTAMP PRECISION NOTICE"s to ensure their sanity. + */ + header.magic = 0xa1b2c3d4; + header.major_version = 2; + header.minor_version = 4; + header.GMT_to_localtime = 0; + header.sigfigs = 0; + header.snaplen = 65535; + header.network = LINK_TYPE_MTP2; + + checked_fwrite((void*)&header, sizeof header, file); + + return; } // Must be a multiple of 4 because of padding rules in PCap-ng @@ -494,55 +507,55 @@ char hw_description[MAX_HW_DESCRIPTION]; void read_hw_description(GTH_api *api, const char *hostname) { - int result; - char architecture[10]; - - result = gth_query_resource_attribute(api, "board", "architecture", - architecture, 10); - if (result != 0) - die("Unable to query hardware architecture. Giving up."); - - result = snprintf(hw_description, MAX_HW_DESCRIPTION, - "save_to_pcap (Corelatus %s %s)", - architecture, hostname); - if (result >= MAX_HW_DESCRIPTION) - die("Hardware description is too long"); + int result; + char architecture[10]; + + result = gth_query_resource_attribute(api, "board", "architecture", + architecture, 10); + if (result != 0) + die("Unable to query hardware architecture. Giving up."); + + result = snprintf(hw_description, MAX_HW_DESCRIPTION, + "save_to_pcap (Corelatus %s %s)", + architecture, hostname); + if (result >= MAX_HW_DESCRIPTION) + die("Hardware description is too long"); } static int inline round_up_32_bit(int x) { - return (x + 3) & (~3); + return (x + 3) & (~3); } static void write_pcap_ng_shb(HANDLE_OR_FILEPTR file) { - PCap_NG_shb shb; - u32 btl; - PCap_NG_option userappl = {4, 0}; // 4 = user application name - PCap_NG_option end_of_options = {0, 0}; - userappl.length = strlen(hw_description); - - btl = sizeof(PCap_NG_shb) - + sizeof(userappl) + round_up_32_bit(userappl.length) - + sizeof(end_of_options) - + sizeof(shb.block_total_length); - - shb.type = 0x0A0D0D0A; - shb.block_total_length = btl; - shb.byte_order_magic = 0x1A2B3C4D; - shb.major_version = 1; - shb.minor_version = 0; - shb.section_length = 0xffffffffFFFFFFFFULL; // "unknown" - - checked_fwrite((void*)&shb, sizeof shb, file); - checked_fwrite((void*)&userappl, sizeof userappl, file); - checked_fwrite((void*)hw_description, round_up_32_bit(userappl.length), file); - checked_fwrite((void*)&end_of_options, sizeof end_of_options, file); - checked_fwrite((void*)&btl, sizeof(btl), file); - - return; + PCap_NG_shb shb; + u32 btl; + PCap_NG_option userappl = { 4, 0 }; // 4 = user application name + PCap_NG_option end_of_options = { 0, 0 }; + userappl.length = strlen(hw_description); + + btl = sizeof(PCap_NG_shb) + + sizeof(userappl) + round_up_32_bit(userappl.length) + + sizeof(end_of_options) + + sizeof(shb.block_total_length); + + shb.type = 0x0A0D0D0A; + shb.block_total_length = btl; + shb.byte_order_magic = 0x1A2B3C4D; + shb.major_version = 1; + shb.minor_version = 0; + shb.section_length = 0xffffffffFFFFFFFFULL; // "unknown" + + checked_fwrite((void*)&shb, sizeof shb, file); + checked_fwrite((void*)&userappl, sizeof userappl, file); + checked_fwrite((void*)hw_description, round_up_32_bit(userappl.length), file); + checked_fwrite((void*)&end_of_options, sizeof end_of_options, file); + checked_fwrite((void*)&btl, sizeof(btl), file); + + return; } // Must be a multiple of 4 because of padding rules in PCap-ng @@ -553,161 +566,165 @@ write_pcap_ng_shb(HANDLE_OR_FILEPTR file) static void write_pcap_idbs(HANDLE_OR_FILEPTR file, Channel_t *c, int n) { - int x; - PCap_NG_option end_of_options = {0, 0}; - - for (x = 0; x < n; x++) { - PCap_NG_idb idb; - PCap_NG_option if_name; - char idb_if_name[MAX_IF_NAME]; - PCap_NG_option if_tsresol; - char tsresol[4] = {3, 0, 0, 0}; // 10^-3 resolution, three padding bytes - - u32 block_total_length; - - if_name.code = 2; // if_name - if_name.length = snprintf(idb_if_name, MAX_IF_NAME, "%s:%d", - c[x].span, c[x].timeslots[0]); - if (if_name.length < 0 || if_name.length >= MAX_IF_NAME) - die("interface name is too long"); - - block_total_length = sizeof(idb) - + sizeof(PCap_NG_option) + round_up_32_bit(if_name.length) - + sizeof(PCap_NG_option) + sizeof(tsresol) - + sizeof(PCap_NG_option) - + sizeof(block_total_length); - - idb.type = 1; - idb.block_total_length = block_total_length; - idb.link_type = LINK_TYPE_MTP2; - idb.reserved = 0; - idb.snaplen = 279; - - if_tsresol.code = 9; // tsresol - if_tsresol.length = 1; - - checked_fwrite((void*)&idb, sizeof(idb), file); - - checked_fwrite((void*)&if_name, sizeof (if_name), file); - checked_fwrite((void*)&idb_if_name, round_up_32_bit(if_name.length), file); - - checked_fwrite((void*)&if_tsresol, sizeof(if_tsresol), file); - checked_fwrite((void*)&tsresol, sizeof(tsresol), file); - - checked_fwrite((void*)&end_of_options, sizeof(end_of_options), file); - - checked_fwrite((void*)&block_total_length, sizeof block_total_length, file); - } + int x; + PCap_NG_option end_of_options = { 0, 0 }; + + for (x = 0; x < n; x++) { + PCap_NG_idb idb; + PCap_NG_option if_name; + char idb_if_name[MAX_IF_NAME]; + PCap_NG_option if_tsresol; + /* + TIMESTAMP PRECISION NOTICE: + Precision is set to MILLIseconds (10^-3 seconds) + */ + char tsresol[4] = { 3, 0, 0, 0 }; // 10^-3 resolution, three padding bytes + + u32 block_total_length; + + if_name.code = 2; // if_name + if_name.length = snprintf(idb_if_name, MAX_IF_NAME, "%s:%d", + c[x].span, c[x].timeslots[0]); + if (if_name.length < 0 || if_name.length >= MAX_IF_NAME) + die("interface name is too long"); + + block_total_length = sizeof(idb) + + sizeof(PCap_NG_option) + round_up_32_bit(if_name.length) + + sizeof(PCap_NG_option) + sizeof(tsresol) + + sizeof(PCap_NG_option) + + sizeof(block_total_length); + + idb.type = 1; + idb.block_total_length = block_total_length; + idb.link_type = LINK_TYPE_MTP2; + idb.reserved = 0; + idb.snaplen = 279; + + if_tsresol.code = 9; // tsresol + if_tsresol.length = 1; + + checked_fwrite((void*)&idb, sizeof(idb), file); + + checked_fwrite((void*)&if_name, sizeof(if_name), file); + checked_fwrite((void*)&idb_if_name, round_up_32_bit(if_name.length), file); + + checked_fwrite((void*)&if_tsresol, sizeof(if_tsresol), file); + checked_fwrite((void*)&tsresol, sizeof(tsresol), file); + + checked_fwrite((void*)&end_of_options, sizeof(end_of_options), file); + + checked_fwrite((void*)&block_total_length, sizeof block_total_length, file); + } } static void write_pcap_global_header(HANDLE_OR_FILEPTR file, - enum PCap_format format, - Channel_t *channels, - int n_channels) +enum PCap_format format, + Channel_t *channels, + int n_channels) { - switch (format) { - case PCAP_CLASSIC: - write_pcap_classic_header(file); - break; - - case PCAP_NG: - write_pcap_ng_shb(file); - write_pcap_idbs(file, channels, n_channels); - break; - - default: die("internal error writing global pcap header"); - } + switch (format) { + case PCAP_CLASSIC: + write_pcap_classic_header(file); + break; + + case PCAP_NG: + write_pcap_ng_shb(file); + write_pcap_idbs(file, channels, n_channels); + break; + + default: die("internal error writing global pcap header"); + } } static void write_classic_packet_header(HANDLE_OR_FILEPTR file, - u32 timestamp_hi, - u32 timestamp_lo, - int length) + u32 timestamp_hi, + u32 timestamp_lo, + int length) { - PCap_classic_packet_header pcap_header; - unsigned long long ts_sec; - unsigned long long ts_us; - int result; + PCap_classic_packet_header pcap_header; + unsigned long long ts_sec; + unsigned long long ts_us; + int result; - assert(sizeof ts_sec == 8); + assert(sizeof ts_sec == 8); - ts_us = timestamp_hi; - ts_us <<= 32; - ts_us += timestamp_lo; + ts_us = timestamp_hi; + ts_us <<= 32; + ts_us += timestamp_lo; - ts_sec = ts_us / 1000; - ts_us = (ts_us % 1000) * 1000; + ts_sec = ts_us / 1000; + ts_us = (ts_us % 1000) * 1000; - pcap_header.ts_sec = (u32)ts_sec; - pcap_header.ts_us = (u32)ts_us; - pcap_header.incl_len = length; - pcap_header.orig_len = length; + pcap_header.ts_sec = (u32)ts_sec; + pcap_header.ts_us = (u32)ts_us; + pcap_header.incl_len = length; + pcap_header.orig_len = length; - result = fwrite(&pcap_header, sizeof pcap_header, 1, file); - if (result != 1) { - die("Unable to write packet to the given file. (Is it writeable?)"); - } + result = fwrite(&pcap_header, sizeof pcap_header, 1, file); + if (result != 1) { + die("Unable to write packet to the given file. (Is it writeable?)"); + } } static u32 write_ng_packet_header(HANDLE_OR_FILEPTR file, - u32 timestamp_hi, - u32 timestamp_lo, - u16 tag, - int length) +u32 timestamp_hi, +u32 timestamp_lo, +u16 tag, +int length) { - PCap_NG_epb epb; + PCap_NG_epb epb; - epb.type = 6; - epb.block_total_length = sizeof(epb) - + round_up_32_bit(length) - + sizeof(epb.block_total_length); - epb.interface_id = tag; - epb.timestamp_hi = timestamp_hi; - epb.timestamp_lo = timestamp_lo; - epb.captured_len = length; - epb.packet_len = length; + epb.type = 6; + epb.block_total_length = sizeof(epb) + + round_up_32_bit(length) + + sizeof(epb.block_total_length); + epb.interface_id = tag; + epb.timestamp_hi = timestamp_hi; + epb.timestamp_lo = timestamp_lo; + epb.captured_len = length; + epb.packet_len = length; - checked_fwrite(&epb, sizeof epb, file); + checked_fwrite(&epb, sizeof epb, file); - return epb.block_total_length; + return epb.block_total_length; } static inline void write_packet(HANDLE_OR_FILEPTR file, - u32 timestamp_hi, - u32 timestamp_lo, - u16 tag, - void *payload, - int length, - int format) +u32 timestamp_hi, +u32 timestamp_lo, +u16 tag, +void *payload, +int length, +int format) { - u32 total_length; - - switch (format) { - case PCAP_CLASSIC: - write_classic_packet_header(file, timestamp_hi, timestamp_lo, length); - checked_fwrite(payload, length, file); - break; - - case PCAP_NG: - total_length = write_ng_packet_header(file, timestamp_hi, - timestamp_lo, tag, length); - checked_fwrite(payload, round_up_32_bit(length), file); - checked_fwrite(&total_length, sizeof total_length, file); - break; - - default: - die("internal error"); - } + u32 total_length; + + switch (format) { + case PCAP_CLASSIC: + write_classic_packet_header(file, timestamp_hi, timestamp_lo, length); + checked_fwrite(payload, length, file); + break; + + case PCAP_NG: + total_length = write_ng_packet_header(file, timestamp_hi, + timestamp_lo, tag, length); + checked_fwrite(payload, round_up_32_bit(length), file); + checked_fwrite(&total_length, sizeof total_length, file); + break; + + default: + die("internal error"); + } } static int is_filename_a_pipe(const char *name) { - const char pipe_prefix[] = "\\\\.\\pipe\\"; - return (strncmp(pipe_prefix, name, strlen(pipe_prefix)) == 0); + const char pipe_prefix[] = "\\\\.\\pipe\\"; + return (strncmp(pipe_prefix, name, strlen(pipe_prefix)) == 0); } // windows.h has a max() function. On *nix, sys/param.h has a MAX macro @@ -715,7 +732,7 @@ is_filename_a_pipe(const char *name) static int max_arg(int a, int b) { - return (a > b)?a:b; + return (a > b) ? a : b; } @@ -725,40 +742,40 @@ max_arg(int a, int b) static int wait_for_packet(GTH_api *api, int data_socket) { - fd_set fds; - int result; - int nfds = max_arg(api->fd, data_socket) + 1; + fd_set fds; + int result; + int nfds = max_arg(api->fd, data_socket) + 1; - FD_ZERO(&fds); + FD_ZERO(&fds); - for (;;) - { - struct timeval tv = {1, 0}; - FD_SET(api->fd, &fds); - FD_SET(data_socket, &fds); - - result = select(nfds, &fds, 0, 0, &tv); - - if (result < 0) - { - die("internal error---select() returned error"); - } - - if (result == 0) - { - return 0; - } - - if (FD_ISSET(api->fd, &fds)) - { - gth_nop(api); - } - - if (FD_ISSET(data_socket, &fds)) + for (;;) { - return 1; + struct timeval tv = { 1, 0 }; + FD_SET(api->fd, &fds); + FD_SET(data_socket, &fds); + + result = select(nfds, &fds, 0, 0, &tv); + + if (result < 0) + { + die("internal error---select() returned error"); + } + + if (result == 0) + { + return 0; + } + + if (FD_ISSET(api->fd, &fds)) + { + gth_nop(api); + } + + if (FD_ISSET(data_socket, &fds)) + { + return 1; + } } - } } // Timers are totally different on Windows and the Unixes. We just @@ -769,23 +786,37 @@ static HANDLE timer; static void set_timer(int seconds) { - LARGE_INTEGER liDueTime; - int result; + LARGE_INTEGER liDueTime; + int result; + + liDueTime.QuadPart = seconds; + // Timer is in 100ns units. Negative means relative timeout. + liDueTime.QuadPart *= -10000000LL; + + result = SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, 0); + if (!result) die("SetWaitableTimer failed"); +} + +static void +set_timer_milli(int milliSeconds) +{ + LARGE_INTEGER liDueTime; + int result; - liDueTime.QuadPart = seconds; - // Timer is in 100ns units. Negative means relative timeout. - liDueTime.QuadPart *= -10000000LL; + liDueTime.QuadPart = milliSeconds; + // Timer is in 100ns units. Negative means relative timeout. + liDueTime.QuadPart *= -10000LL; - result = SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, 0); - if (!result) die("SetWaitableTimer failed"); + result = SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, 0); + if (!result) die("SetWaitableTimer failed"); } static void init_timer(int seconds) { - timer = CreateWaitableTimer(NULL, TRUE, "file_rotation_timer"); - if (timer == NULL) die("CreateWaitableTimer failed"); - set_timer(seconds); + timer = CreateWaitableTimer(NULL, TRUE, NULL); + if (timer == NULL) die("CreateWaitableTimer failed"); + set_timer(seconds); } // Return: 0 if the timer has expired @@ -793,12 +824,12 @@ static int read_and_restart_timer(int seconds) { - if (WaitForSingleObject(timer, 0) == WAIT_OBJECT_0) - { - set_timer(seconds); - return 0; - } - return 1; + if (WaitForSingleObject(timer, 0) == WAIT_OBJECT_0) + { + set_timer(seconds); + return 0; + } + return 1; } @@ -808,164 +839,291 @@ static timer_t timer; static void set_timer(int seconds) { - int result; - struct itimerspec new_timer = { {0, 0}, {seconds, 0} }; + int result; + struct itimerspec new_timer = { { 0, 0 }, { seconds, 0 } }; - result = timer_settime(timer, 0, &new_timer, 0); - if (result != 0) die("timer_settime failed"); + result = timer_settime(timer, 0, &new_timer, 0); + if (result != 0) die("timer_settime failed"); } static void init_timer(int seconds) { - int result; - struct sigevent se; + int result; + struct sigevent se; - se.sigev_notify = SIGEV_NONE; + se.sigev_notify = SIGEV_NONE; - result = timer_create(CLOCK_REALTIME, &se, &timer); - if (result != 0) die("unable to create a timer"); + result = timer_create(CLOCK_REALTIME, &se, &timer); + if (result != 0) die("unable to create a timer"); - set_timer(seconds); + set_timer(seconds); } // Return: 0 if the timer has expired static int read_and_restart_timer(int seconds) { - int result; - struct itimerspec current; + int result; + struct itimerspec current; - result = timer_gettime(timer, ¤t); - if (result != 0) die("timer_gettime() failed"); + result = timer_gettime(timer, ¤t); + if (result != 0) die("timer_gettime() failed"); - if (current.it_value.tv_sec == 0 && current.it_value.tv_nsec == 0) - { - set_timer(seconds); - return 0; - } + if (current.it_value.tv_sec == 0 && current.it_value.tv_nsec == 0) + { + set_timer(seconds); + return 0; + } - return 1; + return 1; } #endif static inline int is_time_to_rotate(int su_count, int n_sus_per_file, int duration) { - if (duration > 0 && read_and_restart_timer(duration) == 0) - { - return 1; - } - return (n_sus_per_file > 0 && (su_count >= n_sus_per_file)); + if (duration > 0 && read_and_restart_timer(duration) == 0) + { + return 1; + } + return (n_sus_per_file > 0 && (su_count >= n_sus_per_file)); } #define MAX_FILENAME 100 + +static unsigned long long convert_timestamp_micro( + u32 ts_hi, + u32 ts_lo, + const enum PCap_format format) +{ + unsigned long long ts; + + assert(sizeof ts == 8); + + ts = ts_hi; + ts <<= 32; + ts += ts_lo; + + //if (format != PCAP_CLASSIC) + //TIMESTAMP PRECISION NOTICE: + //convert milliseconds into microseconds + ts *=1000; + + return ts; +} + +static unsigned long long convert_epoch_micro(time_t time) +{ + return time*1000000;//microseconds precision +} + +//3651096057 + // Loop forever, converting the incoming GTH data to libpcap format static void convert_to_pcap(GTH_api *api, - int data_socket, - const char *base_name, - const int n_sus_per_file, - const int duration_per_file, - Channel_t channels[], - int n_channels, - const enum PCap_format format) +int data_socket, +const char *base_name, +const int n_sus_per_file, +const int duration_per_file, +const int stop_after_interval, +const int output_filename_format, +Channel_t channels[], +int n_channels, +const enum PCap_format format) { - u16 length; - GTH_mtp2 signal_unit; - int su_count; - int file_number = 1; - HANDLE_OR_FILEPTR file; - int write_to_stdout = 0; - int write_to_pipe; - - write_to_stdout = (strcmp(base_name, "-") == 0); - write_to_pipe = is_filename_a_pipe(base_name); - - init_timer(duration_per_file); - - while (1) { - char filename[MAX_FILENAME]; - - if (!write_to_stdout && !write_to_pipe) - { - snprintf(filename, MAX_FILENAME, "%s.%d", - base_name, file_number); - open_file_for_writing(&file, filename); - fprintf(stderr, "saving to file %s\n", filename); - } - else if (write_to_stdout) - { - file = stdout_handle_or_file(); - fprintf(stderr, "saving capture to stdout\n"); - } - else - { - fprintf(stderr, "saving capture to a windows named pipe\n"); - file = open_windows_pipe(base_name); - } - - write_pcap_global_header(file, format, channels, n_channels); - - file_number++; - su_count = 0; - - do - { - if (wait_for_packet(api, data_socket) != 0) - { - read_exact(data_socket, (void*)&length, sizeof length); - length = ntohs(length); - assert(length <= sizeof signal_unit); - read_exact(data_socket, (void*)&signal_unit, length); - - length -= (signal_unit.payload - (char*)&(signal_unit.tag)); - write_packet(file, - ntohs(signal_unit.timestamp_hi), - ntohl(signal_unit.timestamp_lo), - ntohs(signal_unit.tag), - signal_unit.payload, - length, - format); - flush_file(file); - su_count++; - } - } - while ( !is_time_to_rotate(su_count, n_sus_per_file, duration_per_file) - || write_to_pipe - || write_to_stdout ); - - fclose(file); - } + u16 length; + GTH_mtp2 signal_unit; + int su_count; + int file_number = 1; + HANDLE_OR_FILEPTR file; + int write_to_stdout = 0; + int write_to_pipe; + + write_to_stdout = (strcmp(base_name, "-") == 0); + write_to_pipe = is_filename_a_pipe(base_name); + + init_timer(duration_per_file); + + int always_true = 1; + time_t rawtime; + struct tm * timeinfo = NULL; + + unsigned long long interval_threshold=0; + + u32 curr_sec = 0; + u32 curr_usec = 0; + unsigned long long curr_ts; + + while (always_true) { + char filename[MAX_FILENAME]; + + if (!write_to_stdout && !write_to_pipe) + { + if (output_filename_format > 0) + { + if(timeinfo==NULL) //setting interval time + time(&rawtime); + else + rawtime+=duration_per_file; //hard setting next interval (duration_per_file is in seconds) + + if (output_filename_format == 1) + timeinfo = localtime(&rawtime); // local time + else + timeinfo = gmtime(&rawtime); // utc time + + interval_threshold=convert_epoch_micro(rawtime+duration_per_file); + + fprintf(stderr, "interval started at %04d/%02d/%02d %02d:%02d:%02d\n", + timeinfo->tm_year + 1900, + timeinfo->tm_mon + 1, + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec); + + fprintf(stderr, "threshold epoch: %llu\n", interval_threshold); + } + + if (!stop_after_interval) + { + if (output_filename_format > 0) + { + snprintf(filename, MAX_FILENAME, "%s_%05d_%04d%02d%02d%02d%02d%02d", + base_name, file_number, + timeinfo->tm_year + 1900, + timeinfo->tm_mon + 1, + timeinfo->tm_mday, + timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + } + else + { + snprintf(filename, MAX_FILENAME, "%s_%05d", + base_name, file_number); + } + } + else + { + if (output_filename_format > 0) + { + snprintf(filename, MAX_FILENAME, "%s_%04d%02d%02d%02d%02d%02d", + base_name, + timeinfo->tm_year + 1900, + timeinfo->tm_mon + 1, + timeinfo->tm_mday, + timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + } + else + { + snprintf(filename, MAX_FILENAME, "%s", + base_name); + } + } + open_file_for_writing(&file, filename); + fprintf(stderr, "saving to file %s\n", filename); + } + else if (write_to_stdout) + { + file = stdout_handle_or_file(); + fprintf(stderr, "saving capture to stdout\n"); + } + else + { + fprintf(stderr, "saving capture to a windows named pipe\n"); + file = open_windows_pipe(base_name); + } + + write_pcap_global_header(file, format, channels, n_channels); + + file_number++; + su_count = 0; + + int rotation_time_reached = 0; + do + { + if (wait_for_packet(api, data_socket) != 0) + { + read_exact(data_socket, (void*)&length, sizeof length); + length = ntohs(length); + assert(length <= sizeof signal_unit); + read_exact(data_socket, (void*)&signal_unit, length); + + curr_sec = ntohs(signal_unit.timestamp_hi); + curr_usec = ntohl(signal_unit.timestamp_lo); + + length -= (signal_unit.payload - (char*)&(signal_unit.tag)); + write_packet(file, + curr_sec, + curr_usec, + ntohs(signal_unit.tag), + signal_unit.payload, + length, + format); + flush_file(file); + su_count++; + + if (!write_to_pipe && !write_to_stdout) + { + if (duration_per_file) + { + curr_ts = convert_timestamp_micro(curr_sec, curr_usec, format); + + if (curr_ts >= interval_threshold) + { + fprintf(stderr, "interval threshold triggered.\n"); + set_timer(duration_per_file); + break; + } + } + } + } + } while ( + !(rotation_time_reached = is_time_to_rotate(su_count, n_sus_per_file, duration_per_file)) + || write_to_pipe + || write_to_stdout + ); + + fclose(file); + + if (!write_to_pipe && !write_to_stdout) + { + if (rotation_time_reached && stop_after_interval) + { + fprintf(stderr, "stopped capturing when rotation time reached\n"); + always_true = 0; + } + } + } } static int is_span_name(char *arg) { - if (strstr(arg, "pcm")) return 1; // Optical hardware uses e.g. 'pcm55' - if (strstr(arg, "A")) return 1; - if (strstr(arg, "B")) return 1; - if (strstr(arg, "C")) return 1; - if (strstr(arg, "D")) return 1; - return 0; + if (strstr(arg, "pcm")) return 1; // Optical hardware uses e.g. 'pcm55' + if (strstr(arg, "A")) return 1; + if (strstr(arg, "B")) return 1; + if (strstr(arg, "C")) return 1; + if (strstr(arg, "D")) return 1; + return 0; } static void print_channels(Channel_t *channels, int n) { - int x; - int y; - - for (x = 0; x < n; x++) { - fprintf(stderr, "monitoring %s:", channels->span); - for (y = 0; y < channels->n_timeslots-1; y++) { - fprintf(stderr, "%d,", channels->timeslots[y]); - } - fprintf(stderr, "%d ", channels->timeslots[y]); - fprintf(stderr, "interface_id=%d\n", x); - channels++; - } + int x; + int y; + + for (x = 0; x < n; x++) { + fprintf(stderr, "monitoring %s:", channels->span); + for (y = 0; y < channels->n_timeslots - 1; y++) { + fprintf(stderr, "%d,", channels->timeslots[y]); + } + fprintf(stderr, "%d ", channels->timeslots[y]); + fprintf(stderr, "interface_id=%d\n", x); + channels++; + } } // Examples of arguments "16", "1-3", "1-3,5-9,10", "1,2,3" @@ -976,79 +1134,78 @@ print_channels(Channel_t *channels, int n) static void argument_to_ts_array(const char* s, int timeslots[], int *n_timeslots) { - char ranges[MAX_TIMESLOTS][MAX_RANGE]; // Longest-possible - int range = 0; - char *pos; - int i; - - *n_timeslots = 0; - - while ( (pos = strchr(s, ',')) ) - { - strncpy_s(ranges[range++], MAX_RANGE, s, pos-s); - s = pos + 1; - if (range > MAX_TIMESLOTS) - die("Too many timeslots specified. Abort."); - } - strncpy_s(ranges[range++], MAX_RANGE, s, strlen(s)); - - for (i = 0; i < range; i++) - { - int lo; - int hi; - int result; - - result = sscanf(ranges[i], "%d-%d", &lo, &hi); - - if (result == 0) - { - fprintf(stderr, "Got %s", ranges[i]); - die(" when expecting a timeslot. Abort."); - } + char ranges[MAX_TIMESLOTS][MAX_RANGE]; // Longest-possible + int range = 0; + char *pos; + int i; - if (result == 1) - hi = lo; + *n_timeslots = 0; - if (lo > hi) + while ((pos = strchr(s, ','))) { - fprintf(stderr, "timeslot range %s in unexpected format.", ranges[i]); - die("Abort."); + strncpy_s(ranges[range++], MAX_RANGE, s, pos - s); + s = pos + 1; + if (range > MAX_TIMESLOTS) + die("Too many timeslots specified. Abort."); } + strncpy_s(ranges[range++], MAX_RANGE, s, strlen(s)); - if (lo < 1 || hi > 31) - die("Timeslot outside expected range 1..31. Abort."); - - do + for (i = 0; i < range; i++) { - timeslots[(*n_timeslots)++] = lo++; + int lo; + int hi; + int result; + + result = sscanf(ranges[i], "%d-%d", &lo, &hi); + + if (result == 0) + { + fprintf(stderr, "Got %s", ranges[i]); + die(" when expecting a timeslot. Abort."); + } + + if (result == 1) + hi = lo; + + if (lo > hi) + { + fprintf(stderr, "timeslot range %s in unexpected format.", ranges[i]); + die("Abort."); + } + + if (lo < 1 || hi > 31) + die("Timeslot outside expected range 1..31. Abort."); + + do + { + timeslots[(*n_timeslots)++] = lo++; + } while (lo <= hi); } - while (lo <= hi); - } } static void check_for_overlapping_channels(Channel_t *channels, int n_channels) { - int i; - int j; - int k; - int l; - - for (i = 0; i < n_channels; i++) - for (j = i+1; j < n_channels; j++) - { - if (channels[i].span == channels[j].span) - { - for (k = 0; k < channels[i].n_timeslots; k++) - for (l = 0; l < channels[j].n_timeslots; l++) - if (channels[i].timeslots[k] == channels[j].timeslots[l]) - { - fprintf(stderr, "Input %s:%d was specified twice. ", - channels[i].span, channels[i].timeslots[k]); - die("Abort."); - } - } - } + int i; + int j; + int k; + int l; + + for (i = 0; i < n_channels; i++) + for (j = i + 1; j < n_channels; j++) + { + if (channels[i].span == channels[j].span) + { + for (k = 0; k < channels[i].n_timeslots; k++) + for (l = 0; l < channels[j].n_timeslots; l++) + if (channels[i].timeslots[k] == channels[j].timeslots[l]) + { + fprintf(stderr, "Input %s:%d was specified twice. ", + channels[i].span, channels[i].timeslots[k]); + die("Abort."); + } + } + } } @@ -1057,61 +1214,61 @@ check_for_overlapping_channels(Channel_t *channels, int n_channels) // Return the number of arguments consumed static int arguments_to_channels(int argc, - char **argv, - Channel_t *channels, - int *n_channels) +char **argv, +Channel_t *channels, +int *n_channels) { - char *spans[MAX_SPANS]; - int n_spans = 0; + char *spans[MAX_SPANS]; + int n_spans = 0; - int timeslots[MAX_TIMESLOTS]; - int n_timeslots; + int timeslots[MAX_TIMESLOTS]; + int n_timeslots; - int current_arg = 0; + int current_arg = 0; - int i; + int i; - if (!is_span_name(argv[current_arg])) - die("Must specify at least one E1/T1 interface, e.g. '1A'. Abort."); + if (!is_span_name(argv[current_arg])) + die("Must specify at least one E1/T1 interface, e.g. '1A'. Abort."); - while (current_arg < argc - 1) - { - if (is_span_name(argv[current_arg])) + while (current_arg < argc - 1) { - if (n_timeslots > 0) // We are starting a new span group - { - n_spans = 0; - n_timeslots = 0; - } - spans[n_spans++] = argv[current_arg]; - if (n_spans > MAX_SPANS) - die("Too many interfaces given"); + if (is_span_name(argv[current_arg])) + { + if (n_timeslots > 0) // We are starting a new span group + { + n_spans = 0; + n_timeslots = 0; + } + spans[n_spans++] = argv[current_arg]; + if (n_spans > MAX_SPANS) + die("Too many interfaces given"); + } + else // We're now processing either timeslots or timeslot ranges + { + if (n_spans == 0) + die("Expected E1/T1 interface before further arguments. Abort."); + + argument_to_ts_array(argv[current_arg], timeslots, &n_timeslots); + + for (i = 0; i < n_spans; i++) + { + if (*n_channels >= MAX_MTP2_CHANNELS) + die("Attempted to start too many signalling channels. Abort."); + + channels[*n_channels].span = spans[i]; + channels[*n_channels].n_timeslots = n_timeslots; + memcpy(channels[*n_channels].timeslots, timeslots, + sizeof timeslots); + (*n_channels)++; + } + } + current_arg++; } - else // We're now processing either timeslots or timeslot ranges - { - if (n_spans == 0) - die("Expected E1/T1 interface before further arguments. Abort."); - - argument_to_ts_array(argv[current_arg], timeslots, &n_timeslots); - - for (i = 0; i < n_spans; i++) - { - if (*n_channels >= MAX_MTP2_CHANNELS) - die("Attempted to start too many signalling channels. Abort."); - - channels[*n_channels].span = spans[i]; - channels[*n_channels].n_timeslots = n_timeslots; - memcpy(channels[*n_channels].timeslots, timeslots, - sizeof timeslots); - (*n_channels)++; - } - } - current_arg++; - } - check_for_overlapping_channels(channels, *n_channels); + check_for_overlapping_channels(channels, *n_channels); - return current_arg; + return current_arg; } // Two possible rotation syntaxes. @@ -1125,152 +1282,176 @@ arguments_to_channels(int argc, void static parse_rotation(char *arg, int *n_sus_per_file, int *duration_per_file) { - int n; - - if (sscanf(arg, "packets:%d", &n) == 1 - || sscanf(arg, "%d", &n) == 1) - { - *n_sus_per_file = n; - return; - } - - if (sscanf(arg, "duration:%d", &n) == 1) - { - *duration_per_file = n; - return; - } - - usage(); -} - + int n; -void static -process_arguments(char **argv, - int argc, - int *monitoring, - int *verbose, - int *n_sus_per_file, - int *duration_per_file, - int *drop_fisus, - int *esnf, - char **hostname, - Channel_t channels[], - int *n_channels, - char **base_filename, - enum PCap_format *format) -{ - int current_arg; + if (sscanf(arg, "packets:%d", &n) == 1 + || sscanf(arg, "%d", &n) == 1) + { + *n_sus_per_file = n; + return; + } - while (argc > 1 && argv[1][0] == '-') { - switch (argv[1][1]) { - case 'c': *format = PCAP_CLASSIC; break; + if (sscanf(arg, "duration:%d", &n) == 1) + { + *duration_per_file = n; + return; + } - case 'f': - if (argc < 3) { - usage(); - } - if (!strcmp("fisu=no", argv[2])) { - *drop_fisus = 1; - } else if (!strcmp("esnf=yes", argv[2])) { - *esnf = 1; - } - argc--; - argv++; - break; - - case 'm': *monitoring = 1; break; - - case 'n': - if (argc < 3) { usage(); - } - parse_rotation(argv[2], n_sus_per_file, duration_per_file); - argc--; - argv++; - break; +} - case 'v': *verbose = 1; break; - default: usage(); - } - argc--; - argv++; - } +void static +process_arguments(char **argv, +int argc, +int *monitoring, +int *verbose, +int *n_sus_per_file, +int *duration_per_file, +int *stop_after_interval, +int *output_filename_format, +int *drop_fisus, +int *esnf, +char **hostname, +Channel_t channels[], +int *n_channels, +char **base_filename, +enum PCap_format *format) +{ + int current_arg; + + while (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + case 'c': *format = PCAP_CLASSIC; break; + + case 'f': + if (argc < 3) { + usage(); + } + if (!strcmp("fisu=no", argv[2])) { + *drop_fisus = 1; + } + else if (!strcmp("esnf=yes", argv[2])) { + *esnf = 1; + } + argc--; + argv++; + break; + + case 'm': *monitoring = 1; break; + + case 'n': + if (argc < 3) { + usage(); + } + parse_rotation(argv[2], n_sus_per_file, duration_per_file); + argc--; + argv++; + break; + + case 's': *stop_after_interval = 1; break; + + case 'o': + if (argc < 3) { + usage(); + } + if (!strcmp("utc=yes", argv[2])) { + *output_filename_format = 2; + } + else if (!strcmp("utc=no", argv[2])) { + *output_filename_format = 1; + } + else if (!strcmp("default", argv[2])) { + *output_filename_format = 0; + } + argc--; + argv++; + break; + + case 'v': *verbose = 1; break; + + default: usage(); + } + argc--; + argv++; + } - if (argc < 4) { - usage(); - } + if (argc < 4) { + usage(); + } - *hostname = argv[1]; + *hostname = argv[1]; - argv += 2; - argc -= 2; + argv += 2; + argc -= 2; - current_arg = arguments_to_channels(argc, argv, channels, n_channels); - if (!n_channels){ - die("No timeslots given (or, perhaps, no output filename given)."); - } + current_arg = arguments_to_channels(argc, argv, channels, n_channels); + if (!n_channels){ + die("No timeslots given (or, perhaps, no output filename given)."); + } - print_channels(channels, *n_channels); + print_channels(channels, *n_channels); - *base_filename = argv[current_arg]; + *base_filename = argv[current_arg]; } // Entry point int main(int argc, char **argv) { - GTH_api api; - int data_socket = -1; - int result; - int monitoring = 0; - int verbose = 0; - Channel_t channels[MAX_MTP2_CHANNELS]; - int i; - int n_channels = 0; - int n_sus_per_file = 0; - int duration_per_file = 0; - int drop_fisus = 0; - int esnf = 0; - int listen_port = 0; - int listen_socket = -1; - enum PCap_format format = PCAP_NG; - char *hostname; - char *base_filename; - - // Check a couple of assumptions about type size. - assert(sizeof(u32) == 4); - assert(sizeof(u16) == 2); - - win32_specific_startup(); - - process_arguments(argv, argc, - &monitoring, &verbose, &n_sus_per_file, &duration_per_file, - &drop_fisus, &esnf, &hostname, channels, &n_channels, - &base_filename, &format); - result = gth_connect(&api, hostname, verbose); - if (result != 0) { - die("Unable to connect to the GTH. Giving up."); - } - - read_hw_description(&api, hostname); - enable_l1(&api, channels, n_channels, monitoring); - - listen_socket = gth_make_listen_socket(&listen_port); - for (i = 0; i < n_channels; i++){ - monitor_mtp2(&api, channels + i, - i, drop_fisus, esnf, listen_port, listen_socket); - if (i == 0) { - data_socket = gth_wait_for_accept(listen_socket); - } - } - - fprintf(stderr, "capturing packets, press ^C to abort\n"); - convert_to_pcap(&api, data_socket, base_filename, - n_sus_per_file, duration_per_file, - channels, n_channels, format); - - return 0; // not reached + GTH_api api; + int data_socket = -1; + int result; + int monitoring = 0; + int verbose = 0; + Channel_t channels[MAX_MTP2_CHANNELS]; + int i; + int n_channels = 0; + int n_sus_per_file = 0; + int duration_per_file = 0; + int stop_after_interval = 0; + int output_filename_format = 0; + int drop_fisus = 0; + int esnf = 0; + int listen_port = 0; + int listen_socket = -1; + enum PCap_format format = PCAP_NG; + char *hostname; + char *base_filename; + + // Check a couple of assumptions about type size. + assert(sizeof(u32) == 4); + assert(sizeof(u16) == 2); + + win32_specific_startup(); + + process_arguments(argv, argc, + &monitoring, &verbose, &n_sus_per_file, &duration_per_file, &stop_after_interval, &output_filename_format, + &drop_fisus, &esnf, &hostname, channels, &n_channels, + &base_filename, &format); + result = gth_connect(&api, hostname, verbose); + if (result != 0) { + die("Unable to connect to the GTH. Giving up."); + } + + read_hw_description(&api, hostname); + enable_l1(&api, channels, n_channels, monitoring); + + listen_socket = gth_make_listen_socket(&listen_port); + for (i = 0; i < n_channels; i++){ + monitor_mtp2(&api, channels + i, + i, drop_fisus, esnf, listen_port, listen_socket); + if (i == 0) { + data_socket = gth_wait_for_accept(listen_socket); + } + } + + fprintf(stderr, "capturing packets, press ^C to abort\n"); + convert_to_pcap(&api, data_socket, base_filename, + n_sus_per_file, duration_per_file, stop_after_interval, output_filename_format, + channels, n_channels, format); + + return 0; // not reached } -// eof +// eof \ No newline at end of file diff --git a/c/save_to_pcap.obj b/c/save_to_pcap.obj new file mode 100644 index 0000000..eab3088 Binary files /dev/null and b/c/save_to_pcap.obj differ diff --git a/c/unmap.obj b/c/unmap.obj new file mode 100644 index 0000000..9bd85ad Binary files /dev/null and b/c/unmap.obj differ diff --git a/c/version.obj b/c/version.obj new file mode 100644 index 0000000..93c2a47 Binary files /dev/null and b/c/version.obj differ diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Channel.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Channel.cs new file mode 100644 index 0000000..4569955 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Channel.cs @@ -0,0 +1,8 @@ +namespace Corelatus.GTH.Utilities +{ + public class Channel + { + public string Span { get; set; } + public int[] Timeslots { get; set; } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Config.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Config.cs new file mode 100644 index 0000000..8a5cfd1 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Config.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Corelatus.GTH.Utilities +{ + public class Config + { + public string Address { get; set; } + public bool Fisu { get; set; } + public bool Esnf { get; set; } + public bool Monitoring { get; set; } + public bool Verbose { get; set; } + public IEnumerable Channels { get; set; } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Corelatus.GTH.Utilities.csproj b/dotnet/Corelatus/Corelatus.GTH.Utilities/Corelatus.GTH.Utilities.csproj new file mode 100644 index 0000000..3bb7843 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Corelatus.GTH.Utilities.csproj @@ -0,0 +1,68 @@ + + + + + Debug + AnyCPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3} + Library + Properties + Corelatus.GTH.Utilities + Corelatus.GTH.Utilities + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + x64 + true + + + + + + + + + + + + + + + + + + + + + + + + {6836d52d-2f3e-4568-bb02-9f2d8296cf89} + Corelatus.GTH + + + + + \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/EndianReader.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/EndianReader.cs new file mode 100644 index 0000000..59c6e6f --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/EndianReader.cs @@ -0,0 +1,48 @@ +using System; + +namespace Corelatus.GTH.Utilities +{ + public static class EndianReader + { + public unsafe static UInt16 ReadUInt16Big(byte[] data, int offset) + { + UInt16 value; + byte* ptr = (byte*)&value; + + *(ptr) = data[offset + 1]; + *(ptr + 1) = data[offset]; + + return value; + } + + public unsafe static UInt32 ReadUInt32Big(byte[] data, int offset) + { + UInt32 value; + byte* ptr = (byte*)&value; + + *ptr = data[offset + 3]; + *(ptr + 1) = data[offset + 2]; + *(ptr + 2) = data[offset + 1]; + *(ptr + 3) = data[offset]; + + return value; + } + + public unsafe static UInt64 ReadUInt64Big(byte[] data, int offset) + { + UInt64 value; + byte* ptr = (byte*)&value; + + *ptr = data[offset + 7]; + *(ptr + 1) = data[offset + 6]; + *(ptr + 2) = data[offset + 5]; + *(ptr + 3) = data[offset + 4]; + *(ptr + 4) = data[offset + 3]; + *(ptr + 5) = data[offset + 2]; + *(ptr + 6) = data[offset + 1]; + *(ptr + 7) = data[offset]; + + return value; + } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Extensions.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Extensions.cs new file mode 100644 index 0000000..561eaa1 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Extensions.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; + +namespace Corelatus.GTH.Utilities +{ + public static class Extensions + { + public static bool EnableElectricalL1(this Device device,string span, bool monitoring) + { + var atts = new List + { + new DeviceAttribute("status", "enabled"), + new DeviceAttribute("tx_enabled", "false"), + }; + if (monitoring) + atts.Add(new DeviceAttribute("monitoring", "true")); + + span = "pcm" + span; + + return device.Set(span, atts); + } + + public static bool EnableOpticalL1(this Device device,string span) + { + return device.Enable(span, null); + } + + public static bool EnableL1(this Device device,IEnumerable channels, bool monitoring) + { + var value = device.QueryResourceAttribute("board", "architecture"); + var succeed = true; + if (value.StartsWith("gth")) + { + foreach (var c in channels) + succeed &= EnableElectricalL1(device, c.Span, monitoring); + } + else + { + foreach (var c in channels) + succeed &= EnableOpticalL1(device, c.Span); + } + return succeed; + } + + public static bool MonitorMtp2(this Device device, Mtp2Config config, ref string jobId) + { + var atts = new List(); + + if (config.DropFisus) + atts.Add(new DeviceAttribute("fisu", "no")); + + if (config.Esnf) + atts.Add(new DeviceAttribute("esnf", "yes")); + + var res = device.NewMtp2Monitor(config.Tag, config.Channel.Span, config.Channel.Timeslots, config.Listener, + atts, ref jobId); + + return res; + } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Config.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Config.cs new file mode 100644 index 0000000..6e2b09e --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Config.cs @@ -0,0 +1,11 @@ +namespace Corelatus.GTH.Utilities +{ + public class Mtp2Config + { + public Channel Channel { get; set; } + public Listener Listener { get; set; } + public bool DropFisus { get; set; } + public bool Esnf { get; set; } + public int Tag { get; set; } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2FailedArgs.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2FailedArgs.cs new file mode 100644 index 0000000..f0318a2 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2FailedArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace Corelatus.GTH.Utilities +{ + public class Mtp2FailedArgs:EventArgs + { + public Exception Exception { get;private set; } + + internal Mtp2FailedArgs(Exception exception) + { + Exception = exception; + } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Packet.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Packet.cs new file mode 100644 index 0000000..6ab1b48 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Packet.cs @@ -0,0 +1,57 @@ +using System; +using System.Linq; + +namespace Corelatus.GTH.Utilities +{ + public class Mtp2Packet : EventArgs + { + private readonly byte[] _header; + private readonly byte[] _payload; + + private readonly Lazy _tag; + private readonly Lazy _flags; + + public ushort Tag + { + get { return _tag.Value; } + } + + public ushort Flags + { + get { return _flags.Value; } + } + + public byte[] Payload + { + get { return _payload; } + } + + public uint Seconds { get; private set; } + public uint Microseconds { get; private set; } + + public Mtp2Packet(byte[] header, byte[] payload) + { + _header = header; + _payload = payload; + + _tag = new Lazy(() => EndianReader.ReadUInt16Big(_header, 0)); + _flags = new Lazy(() => EndianReader.ReadUInt16Big(_header, 2)); + + + var tsHigh = EndianReader.ReadUInt16Big(_header, 4); + var tsLow =EndianReader.ReadUInt32Big(_header, 6); + + ulong ts = tsHigh; + ts <<= 32; + ts += tsLow; + + Seconds = (uint)(ts / 1000); + Microseconds = (uint)((ts % 1000) * 1000); + } + + public Mtp2Packet(byte[] data) + : this(data.Take(10).ToArray(), data.Skip(10).ToArray()) + { + } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Receiver.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Receiver.cs new file mode 100644 index 0000000..d3df9e0 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Mtp2Receiver.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Corelatus.GTH.Utilities +{ + public class Mtp2Receiver:IDisposable + { + public event EventHandler PacketReceived; + public event EventHandler Failed; + + private readonly Config _config; + private Device _device; + private Listener _listener; + private DataConnection _dataConn; + private bool _started; + private readonly ManualResetEventSlim _waitHandle = new ManualResetEventSlim(); + + private readonly List _jobIds = new List(); + + public IEnumerable GetJobIds() + { + return _jobIds.ToArray(); + } + + public Mtp2Receiver(Config config) + { + _config = config; + } + + public void Start() + { + Connect(); + EnableL1(); + OpenListener(); + MonitorMtp2(); + EstablishData(); + + _started = true; + Task.Factory.StartNew(Fetch, TaskCreationOptions.LongRunning); + } + + private void OnPacketReceived(Mtp2Packet packet) + { + if (_started && PacketReceived != null) + PacketReceived(this, packet); + } + + private void OnFailed(Exception exception) + { + if (Failed != null) + Failed(this, new Mtp2FailedArgs(exception)); + } + + private void Fetch() + { + var reader = _dataConn.GetReader(); + var lenBuffer = new byte[2]; + + while (_started) + { + try + { + if (_device.WaitForPacket(_dataConn)) + { + reader.ReadExact(lenBuffer, 0, lenBuffer.Length); + var len=EndianReader.ReadUInt16Big(lenBuffer, 0); + var header = new byte[10]; + reader.ReadExact(header, 0, header.Length); + var payload = new byte[len - header.Length]; + reader.ReadExact(payload, 0, payload.Length); + + var mtp2 = new Mtp2Packet(header, payload); + OnPacketReceived(mtp2); + } + } + catch (Exception e) + { + OnFailed(e); + } + } + + _waitHandle.Set(); + } + + private void CleanResources() + { + foreach (var j in _jobIds) + _device.Delete(j); + + _dataConn.Dispose(); + _listener.Dispose(); + _device.Dispose(); + } + + private void EstablishData() + { + _dataConn = _device.WaitForAccept(_listener) as DataConnection; + if (_dataConn == null) + throw new CorelatusException(string.Format("failed to open data connection for device '{0}'.", _config.Address)); + } + + private void MonitorMtp2() + { + var tag = 0; + foreach (var c in _config.Channels) + { + var mtp2Config = new Mtp2Config + { + Channel = c, + DropFisus = !_config.Fisu, + Esnf = _config.Esnf, + Listener = _listener, + Tag = tag + }; + tag++; + + string jobId=null; + if (!_device.MonitorMtp2(mtp2Config, ref jobId)) + throw new CorelatusException(string.Format("failed to channel {0} for device '{1}'.", tag - 1, + _config.Address)); + _jobIds.Add(jobId); + } + } + + private void Connect() + { + _device = Device.Connect(_config.Address,_config.Verbose); + if (_device == null) + throw new CorelatusException(string.Format("failed to open device '{0}'.", _config.Address)); + } + + private void OpenListener() + { + _listener = _device.Listen() as Listener; + if (_listener == null) + throw new CorelatusException(string.Format("failed to open listener for device '{0}'.", _config.Address)); + } + + private void EnableL1() + { + if (!_device.EnableL1(_config.Channels, _config.Monitoring)) + throw new CorelatusException(string.Format("failed to enable L1 for device '{0}'.", _config.Address)); + } + + public void Dispose() + { + PacketReceived = null; + _started = false; + _waitHandle.Wait(10000); + CleanResources(); + } + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH.Utilities/Properties/AssemblyInfo.cs b/dotnet/Corelatus/Corelatus.GTH.Utilities/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8700549 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH.Utilities/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Corelatus.GTH.Utilities")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Corelatus.GTH.Utilities")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("08eea402-5d24-4ebc-98a7-fe94c4fc4fb9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/dotnet/Corelatus/Corelatus.GTH/AssemblyInfo.cpp b/dotnet/Corelatus/Corelatus.GTH/AssemblyInfo.cpp new file mode 100644 index 0000000..8a8dd06 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/AssemblyInfo.cpp @@ -0,0 +1,38 @@ +#include "stdafx.h" + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly:AssemblyTitleAttribute(L"CorelatusGTH")]; +[assembly:AssemblyDescriptionAttribute(L"")]; +[assembly:AssemblyConfigurationAttribute(L"")]; +[assembly:AssemblyCompanyAttribute(L"")]; +[assembly:AssemblyProductAttribute(L"CorelatusGTH")]; +[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2016")]; +[assembly:AssemblyTrademarkAttribute(L"")]; +[assembly:AssemblyCultureAttribute(L"")]; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the value or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly:AssemblyVersionAttribute("1.0.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.cpp b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.cpp new file mode 100644 index 0000000..d6b4392 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.cpp @@ -0,0 +1,612 @@ +// This is the main DLL file. + +#include "Corelatus.GTH.h" +#include "DeviceReader.h" +#include "DeviceWriter.h" +#include "Socket.h" +#include "IConnection.h" +#include "Listener.h" +#include "DataConnection.h" + +#define MAX_BUFFER 4096 + +using namespace Corelatus::GTH; + + +Device^ Device::Connect(String^ addr){ + return Connect(addr, false); +} + +Device^ Device::Connect(String^ addr, bool verbose){ + + if (!init){ + win32_specific_startup(); + init = true; + } + + Device^ dev = gcnew Device(); + dev->ptr_addr = Marshal::StringToHGlobalAnsi(addr); + dev->api = new GTH_api(); + + int res = gth_connect(dev->api, (char*)dev->ptr_addr.ToPointer(), verbose); + + if (res != 0) + throw gcnew CorelatusException("Failed to connect to device."); + + dev->connected = true; + return dev; +} + +bool Device::WaitForReboot(String^ addr){ + IntPtr ptr_addr; + int res = -1; + try{ + ptr_addr = Marshal::StringToHGlobalAnsi(addr); + res = gth_wait_for_reboot((const char*)ptr_addr.ToPointer()); + } + finally{ + if (ptr_addr != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_addr); + } + return res == 0; +} + +void Device::SwitchTo(String^ addr, String^ system,bool verbose){ + IntPtr ptr_addr; + IntPtr ptr_system; + + try{ + ptr_addr = Marshal::StringToHGlobalAnsi(addr); + ptr_system = Marshal::StringToHGlobalAnsi(system); + + gth_switch_to((const char*)ptr_addr.ToPointer(), (const char*)ptr_system.ToPointer(),verbose); + } + finally{ + if (ptr_addr != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_addr); + if (ptr_system != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_system); + } +} + +String^ Device::QueryResourceAttribute(String^ name, String^ key){ + + IntPtr ptr_name; + IntPtr ptr_key; + char buffer[MAX_BUFFER]; + + try{ + ptr_name = Marshal::StringToHGlobalAnsi(name); + ptr_key = Marshal::StringToHGlobalAnsi(key); + + int res = gth_query_resource_attribute(api, (const char*)ptr_name.ToPointer(), (const char*)ptr_key.ToPointer(), buffer, MAX_BUFFER); + if (res != 0) + throw gcnew CorelatusException(String::Format("Failed to read attribute {0}.{1}", name, key)); + + return gcnew String(buffer); + } + finally{ + if (ptr_name != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_name); + if (ptr_key != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_key); + } +} + +bool Device::WaitForMessageEnded(String^ jobId){ + + IntPtr ptr_jobId; + int res = -1; + try{ + ptr_jobId=Marshal::StringToHGlobalAnsi(jobId); + res=gth_wait_for_message_ended(api, (const char*)ptr_jobId.ToPointer()); + } + finally{ + if (ptr_jobId != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_jobId); + } + return res == 0; +} + +bool Device::Delete(String^ jobId){ + + IntPtr ptr_jobId; + int res = -1; + try{ + ptr_jobId = Marshal::StringToHGlobalAnsi(jobId); + res=gth_delete(api, (const char*)ptr_jobId.ToPointer()); + } + finally{ + if (ptr_jobId != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_jobId); + } + return res == 0; +} + +bool Device::Disable(String^ resource){ + + IntPtr ptr_resource; + int res = -1; + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + res=gth_disable(api, (const char*)ptr_resource.ToPointer()); + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return res == 0; +} + +bool Device::Enable(String^ resource, IEnumerable ^attributes){ + IntPtr ptr_resource; + int res = -1; + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + + GTH_attribute* native_atts = 0; + + int count = attributes == nullptr ? 0 : Enumerable::Count(attributes); + if (count > 0){ + native_atts = new GTH_attribute[count]; + + int i = 0; + for each (DeviceAttribute^ att in attributes) + { + native_atts[i] = att->ToNative(); + i++; + } + } + res = gth_enable(api, (const char*)ptr_resource.ToPointer(), native_atts, count); + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return res == 0; +} + +bool Device::Install(String^ name, String^ type, array ^data){ + IntPtr ptr_name; + IntPtr ptr_type; + IntPtr ptr_data; + int res = -1; + + try{ + ptr_name = Marshal::StringToHGlobalAnsi(name); + ptr_type = Marshal::StringToHGlobalAnsi(type); + ptr_data = Marshal::AllocHGlobal(data->Length); + Marshal::Copy(data, 0, ptr_data, data->Length); + + res = gth_install(api, (const char*)ptr_name.ToPointer(), (const char*)ptr_type.ToPointer(), (const char*)ptr_data.ToPointer(), data->Length); + } + finally{ + if (ptr_name != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_name); + if (ptr_type != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_type); + if (ptr_data != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_data); + } + return res == 0; +} + +bool Device::Map(String^ resource, String^% name){ + IntPtr ptr_resource; + char buff_name[MAX_BUFFER]; + + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + int res = gth_map(api, (const char*)ptr_resource.ToPointer(), buff_name, MAX_BUFFER); + + if (res != 0){ + name = nullptr; + return false; + } + + name = gcnew String(buff_name); + return true; + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return false; +} + +bool Device::Unmap(String^ resource){ + IntPtr ptr_resource; + int res = -1; + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + res = gth_unmap(api, (const char*)ptr_resource.ToPointer()); + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return res == 0; +} + +bool Device::NewConnection(String^ srcSpan, int srcTs, String^dstSpan, int dstTs, String^% jobId){ + IntPtr ptr_srcSpan; + IntPtr ptr_dstSpan; + char buff_jobId[MAX_BUFFER]; + + try{ + ptr_srcSpan = Marshal::StringToHGlobalAnsi(srcSpan); + ptr_dstSpan = Marshal::StringToHGlobalAnsi(dstSpan); + + int res = gth_new_connection(api, (const char*)ptr_srcSpan.ToPointer(), srcTs, (const char*)ptr_dstSpan.ToPointer(), dstTs, buff_jobId); + if (res != 0){ + jobId == nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_srcSpan != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_srcSpan); + if (ptr_dstSpan != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_dstSpan); + } + return false; +} + +void Device::Nop(){ + gth_nop(api); +} + +bool Device::Set(String^ resource, IEnumerable ^attributes){ + IntPtr ptr_resource; + int res = -1; + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + int count = Enumerable::Count(attributes); + GTH_attribute* native_atts = new GTH_attribute[count]; + + int i = 0; + for each (DeviceAttribute^ att in attributes) + { + native_atts[i] = att->ToNative(); + i++; + } + + res = gth_set(api, (const char*)ptr_resource.ToPointer(), native_atts, count); + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return res == 0; +} + +bool Device::Set(String^ resource, DeviceAttribute ^attribute){ + IntPtr ptr_resource; + int res = -1; + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + GTH_attribute native_att = attribute->ToNative(); + + res = gth_set_single(api, (const char*)ptr_resource.ToPointer(), native_att.key,native_att.value); + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return res == 0; +} + +bool Device::Reset(String^ resource){ + IntPtr ptr_resource; + int res = -1; + try{ + ptr_resource = Marshal::StringToHGlobalAnsi(resource); + res = gth_reset(api, (const char*)ptr_resource.ToPointer()); + } + finally{ + if (ptr_resource != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_resource); + } + return res == 0; +} + +String^ Device::MyIpAddress(){ + return gcnew String(gth_my_ip_address(api)); +} + +GTH_api* Device::NativeApi(){ + return api; +} + +IConnection^ Device::Listen(){ + int port; + int socket=gth_make_listen_socket(&port); + + return gcnew Listener(socket, port, this); +} + +IConnection^ Device::ListenUdp(){ + int port; + int socket = gth_make_udp_socket(&port); + + return gcnew Listener(socket, port, this); +} + +IConnection^ Device::WaitForAccept(IConnection^ listener){ + + int socket = gth_wait_for_accept(listener->NativeHandle()); + return gcnew DataConnection(socket); +} + +bool Device::NewCasR2MfcDetector(int tag, String^ span, int timeslot, IConnection^ connection, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + Listener^ listener = (Listener^)connection; + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_cas_r2_mfc_detector(api, tag, (const char*)ptr_span.ToPointer(), timeslot, buff_jobId, api->my_ip, listener->Port); + + if (res != 0){ + jobId = nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return false; +} + +bool Device::NewCasR2LineSigMonitor(int tag, String^ span, int timeslot, IConnection^ connection, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + Listener^ listener = (Listener^)connection; + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_cas_r2_mfc_detector(api, tag, (const char*)ptr_span.ToPointer(), timeslot, buff_jobId, api->my_ip, listener->Port); + + if (res != 0){ + jobId = nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return false; +} + +bool Device::NewLapdLayer(int tag, String^ span, int timeslot, String^ side, int sapi, int tei, IConnection^ connection, String^% jobId){ + IntPtr ptr_span; + IntPtr ptr_side; + char buff_jobId[MAX_BUFFER]; + try{ + Listener^ listener = (Listener^)connection; + + ptr_span = Marshal::StringToHGlobalAnsi(span); + ptr_side = Marshal::StringToHGlobalAnsi(side); + + int res = gth_new_lapd_layer(api, tag, (const char*)ptr_span.ToPointer(), timeslot, (const char*)ptr_side.ToPointer(),sapi,tei, buff_jobId, api->my_ip, listener->Port); + + if (res != 0){ + jobId = nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + if (ptr_side != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_side); + } + return false; +} + +bool Device::NewLapdMonitor(int tag, String^ span, int timeslot, IConnection^ connection, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + Listener^ listener = (Listener^)connection; + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_lapd_monitor(api, tag, (const char*)ptr_span.ToPointer(), timeslot, buff_jobId, api->my_ip, listener->Port); + + if (res != 0){ + jobId = nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return false; +} + +bool Device::NewMtp2Monitor(int tag, String^ span, array^ timeslot, IConnection^ connection, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + Listener^ listener = (Listener^)connection; + + ptr_span = Marshal::StringToHGlobalAnsi(span); + pin_ptr ptr_timeslot = ×lot[0]; + + int res = gth_new_mtp2_monitor(api, tag, (const char*)ptr_span.ToPointer(), ptr_timeslot, timeslot->Length, buff_jobId, api->my_ip, listener->Port); + + if (res != 0){ + jobId = nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return false; +} + +bool Device::NewMtp2Monitor(int tag, String^ span, array^ timeslot, IConnection^ connection, IEnumerable ^attributes, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + Listener^ listener = (Listener^)connection; + + ptr_span = Marshal::StringToHGlobalAnsi(span); + pin_ptr ptr_timeslot = ×lot[0]; + + int count = Enumerable::Count(attributes); + GTH_attribute* native_atts = new GTH_attribute[count]; + + int i = 0; + for each (DeviceAttribute^ att in attributes) + { + native_atts[i] = att->ToNative(); + i++; + } + + int res = gth_new_mtp2_monitor_opt(api, tag, (const char*)ptr_span.ToPointer(), ptr_timeslot, timeslot->Length, buff_jobId, api->my_ip, listener->Port, native_atts, count); + + if (res != 0){ + jobId = nullptr; + return false; + } + + jobId = gcnew String(buff_jobId); + return true; + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return false; +} + +DeviceWriter^ Device::NewPlayer(String^ span, int timeslot, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_player(api,(const char*)ptr_span.ToPointer(), timeslot,buff_jobId); + + if (res < 0){ + jobId = nullptr; + return nullptr; + } + + jobId = gcnew String(buff_jobId); + return gcnew DeviceWriter(res,0); + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return nullptr; +} + +DeviceReader^ Device::NewRecorder(String^ span, int timeslot, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_recorder(api, (const char*)ptr_span.ToPointer(), timeslot, buff_jobId); + + if (res < 0){ + jobId = nullptr; + return nullptr; + } + + jobId = gcnew String(buff_jobId); + return gcnew DeviceReader(res,0); + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return nullptr; +} + +DeviceReader^ Device::NewRecorder(String^ span, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_wide_recorder(api, (const char*)ptr_span.ToPointer(), buff_jobId); + + if (res < 0){ + jobId = nullptr; + return nullptr; + } + + jobId = gcnew String(buff_jobId); + return gcnew DeviceReader(res, 0); + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return nullptr; +} + +DeviceReader^ Device::NewToneDetector(String^ span, int timeslot,ToneHandler^ handle, String^% jobId){ + IntPtr ptr_span; + char buff_jobId[MAX_BUFFER]; + try{ + + ptr_span = Marshal::StringToHGlobalAnsi(span); + int res = gth_new_tone_detector(api, (const char*)ptr_span.ToPointer(), timeslot, buff_jobId, (GTH_tone_handler*) handle->native_ptr().ToPointer()); + + if (res < 0){ + jobId = nullptr; + return nullptr; + } + + jobId = gcnew String(buff_jobId); + return gcnew DeviceReader(res, 0); + } + finally{ + if (ptr_span != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_span); + } + return nullptr; +} + +Device::~Device(){ + try{ + if (!connected) + return; + + int res = gth_bye(api); + if (res != 0) + throw gcnew CorelatusException("Failed to close the device."); + } + finally{ + if (ptr_addr != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_addr); + } +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.h b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.h new file mode 100644 index 0000000..1de8590 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.h @@ -0,0 +1,69 @@ +// Corelatus.GTH.h + +#pragma once + +#include "GTH.h" +#include "CorelatusException.h" +#include "DeviceAttribute.h" +#include "IConnection.h" +#include "ToneHandler.h" + +using namespace System; +using namespace System::Collections::Generic; +using namespace System::Runtime::InteropServices; +using namespace System::Linq; + +namespace Corelatus { + namespace GTH{ + + public ref class Device:IDisposable + { + private: + IntPtr ptr_addr; + GTH_api* api; + bool connected; + static bool init; + public: + static Device^ Connect(String^ addr); + static Device^ Connect(String^ addr, bool verbose); + static bool WaitForReboot(String^ addr); + static void SwitchTo(String^ addr, String^ mode, bool verbose); + + String^ QueryResourceAttribute(String^ name, String^ key); + bool WaitForMessageEnded(String^ jobId); + bool Delete(String^ jobId); + bool Disable(String^ resource); + bool Enable(String^ resource, IEnumerable ^attributes); + bool Install(String^ name, String^ type, array ^data); + bool Map(String^ resource,[Out] String^% name); + bool Unmap(String^ resource); + + void Nop(); + bool Set(String^ resource, IEnumerable ^attributes); + bool Set(String^ resource, DeviceAttribute ^attribute); + bool Reset(String^ resource); + String^ MyIpAddress(); + IConnection^ Listen(); + IConnection^ ListenUdp(); + IConnection^ WaitForAccept(IConnection^ listener); + + bool NewConnection(String^ srcSpan, int srcTs, String^ dstSpan, int dstTs, String^% jobId); + bool NewCasR2MfcDetector(int tag, String^ span, int timeslot, IConnection^ listener, String^% jobId); + bool NewCasR2LineSigMonitor(int tag, String^ span, int timeslot, IConnection^ listener, String^% jobId); + bool NewLapdLayer(int tag, String^ span, int timeslot, String^ side,int sapi, int tei, IConnection^ listener, String^% jobId); + bool NewLapdMonitor(int tag, String^ span, int timeslot, IConnection^ listener, String^% jobId); + bool NewMtp2Monitor(int tag, String^ span, array^ timeslot, IConnection^ listener, String^% jobId); + bool NewMtp2Monitor(int tag, String^ span, array^ timeslot, IConnection^ listener,IEnumerable ^attributes, String^% jobId); + + DeviceWriter^ NewPlayer(String^ span, int timeslot, String^% jobId); + DeviceReader^ NewRecorder(String^ span, int timeslot, String^% jobId); + DeviceReader^ NewRecorder(String^ span, String^% jobId); + DeviceReader^ NewToneDetector(String^ span, int timeslot, ToneHandler^ handle, String^% jobId); + + + ~Device(); + internal: + GTH_api* NativeApi(); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.vcxproj b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.vcxproj new file mode 100644 index 0000000..9ef18cf --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.vcxproj @@ -0,0 +1,194 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {6836D52D-2F3E-4568-BB02-9F2D8296CF89} + v4.5 + ManagedCProj + CorelatusGTH + + + + DynamicLibrary + true + v120 + true + Unicode + + + DynamicLibrary + true + v120 + true + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + NotUsing + CompileAsCpp + + + true + ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + NotUsing + CompileAsCpp + + + true + ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + NotUsing + CompileAsCpp + + + true + ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + NotUsing + CompileAsCpp + + + true + ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.vcxproj.filters b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.vcxproj.filters new file mode 100644 index 0000000..5243034 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Corelatus.GTH.vcxproj.filters @@ -0,0 +1,133 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/CorelatusException.cpp b/dotnet/Corelatus/Corelatus.GTH/CorelatusException.cpp new file mode 100644 index 0000000..067a695 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/CorelatusException.cpp @@ -0,0 +1,8 @@ +#include "stdafx.h" +#include "CorelatusException.h" + +using namespace Corelatus; + +CorelatusException::CorelatusException(String^ message) :Exception(message) +{ +} diff --git a/dotnet/Corelatus/Corelatus.GTH/CorelatusException.h b/dotnet/Corelatus/Corelatus.GTH/CorelatusException.h new file mode 100644 index 0000000..4356e30 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/CorelatusException.h @@ -0,0 +1,11 @@ +#pragma once + +using namespace System; + +namespace Corelatus{ + public ref class CorelatusException :Exception + { + public: + CorelatusException(String^ message); + }; +} diff --git a/dotnet/Corelatus/Corelatus.GTH/DataConnection.cpp b/dotnet/Corelatus/Corelatus.GTH/DataConnection.cpp new file mode 100644 index 0000000..2620603 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DataConnection.cpp @@ -0,0 +1,33 @@ + +#include "Socket.h" +#include "DataConnection.h" + +using namespace Corelatus::GTH; + +DataConnection::DataConnection(int descriptor){ + this->descriptor = descriptor; +} + +DataConnection::~DataConnection(){ + close(descriptor); +} + +int DataConnection::NativeHandle(){ + return descriptor; +} + +DeviceReader^ DataConnection::GetReader(int flags){ + return gcnew DeviceReader(descriptor, flags); +} + +DeviceReader^ DataConnection::GetReader(){ + return GetReader(0); +} + +DeviceWriter^ DataConnection::GetWriter(int flags){ + return gcnew DeviceWriter(descriptor, flags); +} + +DeviceWriter^ DataConnection::GetWriter(){ + return GetWriter(0); +} diff --git a/dotnet/Corelatus/Corelatus.GTH/DataConnection.h b/dotnet/Corelatus/Corelatus.GTH/DataConnection.h new file mode 100644 index 0000000..8b47c49 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DataConnection.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Corelatus.GTH.h" +#include "DeviceReader.h" +#include "DeviceWriter.h" +#include "IConnection.h" + +namespace Corelatus{ + namespace GTH{ + public ref class DataConnection :IConnection, IDisposable + { + private: + int descriptor; + public: + virtual DeviceReader^ GetReader(); + virtual DeviceWriter^ GetWriter(); + virtual DeviceReader^ GetReader(int flags); + virtual DeviceWriter^ GetWriter(int flags); + virtual int NativeHandle(); + + internal: + DataConnection(int descriptor); + ~DataConnection(); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/DeviceAttribute.cpp b/dotnet/Corelatus/Corelatus.GTH/DeviceAttribute.cpp new file mode 100644 index 0000000..f8207aa --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DeviceAttribute.cpp @@ -0,0 +1,30 @@ +#include "stdafx.h" +#include "DeviceAttribute.h" + +using namespace Corelatus::GTH; +using namespace System::Runtime::InteropServices; + +DeviceAttribute::DeviceAttribute(String^ key,String^ value) +{ + this->key = key; + this->value = value; + + this->ptr_key = Marshal::StringToHGlobalAnsi(key); + this->ptr_value = Marshal::StringToHGlobalAnsi(value); +} + +DeviceAttribute::~DeviceAttribute(){ + if (ptr_key != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_key); + + if (ptr_value != IntPtr::Zero) + Marshal::FreeHGlobal(ptr_value); +} + +GTH_attribute DeviceAttribute::ToNative(){ + + GTH_attribute att; + att.key = (char*)ptr_key.ToPointer(); + att.value = (char*)ptr_value.ToPointer(); + return att; +} diff --git a/dotnet/Corelatus/Corelatus.GTH/DeviceAttribute.h b/dotnet/Corelatus/Corelatus.GTH/DeviceAttribute.h new file mode 100644 index 0000000..80c427f --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DeviceAttribute.h @@ -0,0 +1,32 @@ +#pragma once + +#include "GTH.h" +using namespace System; + +namespace Corelatus{ + namespace GTH{ + public ref class DeviceAttribute :IDisposable + { + private: + String^ key; + String^ value; + IntPtr ptr_key; + IntPtr ptr_value; + public: + property String^ Key{ + String^ get(){ + return key; + } + } + property String^ Value{ + String^ get(){ + return value; + } + } + DeviceAttribute(String^ key, String^ value); + ~DeviceAttribute(); + internal: + GTH_attribute ToNative(); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/DeviceReader.cpp b/dotnet/Corelatus/Corelatus.GTH/DeviceReader.cpp new file mode 100644 index 0000000..f40f7e6 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DeviceReader.cpp @@ -0,0 +1,39 @@ +#include "DeviceReader.h" + +#include "GTH.h" +#include "Socket.h" +#include "CorelatusException.h" + +using namespace Corelatus::GTH; + +DeviceReader::DeviceReader(int descriptor, int flags) +{ + this->descriptor = descriptor; + this->flags = flags; +} + +DeviceReader::~DeviceReader(){ + close(descriptor); +} + +int DeviceReader::Read(array ^buffer, int offset, int length){ + + pin_ptr ptr_buff = &buffer[offset]; + int res = rcv(descriptor, (char*)ptr_buff, length, flags); + return res; +} + +void DeviceReader::ReadExact(array ^buffer, int offset, int length){ + + pin_ptr ptr_buff = &buffer[offset]; + size_t this_time; + + while (length > 0) { + this_time = rcv(descriptor, (char*)ptr_buff, length, flags); + if (this_time <= 0) + throw gcnew CorelatusException("failed to read from device."); + + length -= this_time; + ptr_buff+=this_time; + } +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/DeviceReader.h b/dotnet/Corelatus/Corelatus.GTH/DeviceReader.h new file mode 100644 index 0000000..c8b12fa --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DeviceReader.h @@ -0,0 +1,20 @@ +#pragma once +using namespace System; + +namespace Corelatus{ + namespace GTH { + public ref class DeviceReader:IDisposable + { + private: + int descriptor; + int flags; + public: + int Read(array ^buffer, int offset, int length); + void ReadExact(array ^buffer, int offset, int length); + ~DeviceReader(); + internal: + DeviceReader(int descriptor, int flags); + }; +} +} + diff --git a/dotnet/Corelatus/Corelatus.GTH/DeviceWriter.cpp b/dotnet/Corelatus/Corelatus.GTH/DeviceWriter.cpp new file mode 100644 index 0000000..542eb38 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DeviceWriter.cpp @@ -0,0 +1,22 @@ +#include "DeviceWriter.h" + +#include "Socket.h" + +using namespace Corelatus::GTH; + +DeviceWriter::DeviceWriter(int descriptor, int flags) +{ + this->descriptor = descriptor; + this->flags = flags; +} + +DeviceWriter::~DeviceWriter(){ + close(descriptor); +} + +int DeviceWriter::Write(array ^buffer, int offset, int length){ + + pin_ptr ptr_buff = &buffer[offset]; + int res = snd(descriptor, (const char*)ptr_buff, length, flags); + return res; +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/DeviceWriter.h b/dotnet/Corelatus/Corelatus.GTH/DeviceWriter.h new file mode 100644 index 0000000..76170ae --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/DeviceWriter.h @@ -0,0 +1,19 @@ +#pragma once +using namespace System; + +namespace Corelatus{ + namespace GTH { + public ref class DeviceWriter :IDisposable + { + private: + int descriptor; + int flags; + public: + int Write(array ^buffer, int offset, int length); + ~DeviceWriter(); + internal: + DeviceWriter(int descriptor, int flags); + }; + } +} + diff --git a/dotnet/Corelatus/Corelatus.GTH/GTH.h b/dotnet/Corelatus/Corelatus.GTH/GTH.h new file mode 100644 index 0000000..8165be5 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/GTH.h @@ -0,0 +1,5 @@ +#pragma once + +#include "..\..\..\c\gth_apilib.h" +#include "..\..\..\c\gth_win32_compat.h" +#include "..\..\..\c\gth_client_xml_parse.h" \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/IConnection.h b/dotnet/Corelatus/Corelatus.GTH/IConnection.h new file mode 100644 index 0000000..1d146ec --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/IConnection.h @@ -0,0 +1,18 @@ +#pragma once + +#include "DeviceReader.h" +#include "DeviceWriter.h" + +namespace Corelatus{ + namespace GTH{ + public interface class IConnection + { + public: + DeviceReader^ GetReader(); + DeviceWriter^ GetWriter(); + DeviceReader^ GetReader(int flags); + DeviceWriter^ GetWriter(int flags); + int NativeHandle(); + }; + } +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Listener.cpp b/dotnet/Corelatus/Corelatus.GTH/Listener.cpp new file mode 100644 index 0000000..bc6fa81 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Listener.cpp @@ -0,0 +1,34 @@ + +#include "Socket.h" +#include "Listener.h" + +using namespace Corelatus::GTH; + +Listener::Listener(int descriptor, int port, Device^ owner){ + this->descriptor = descriptor; + this->port = port; + this->device = owner; +} +Listener::~Listener(){ + close(descriptor); +} + +int Listener::NativeHandle(){ + return descriptor; +} + +DeviceReader^ Listener::GetReader(int flags){ + return gcnew DeviceReader(descriptor, flags); +} + +DeviceReader^ Listener::GetReader(){ + return GetReader(0); +} + +DeviceWriter^ Listener::GetWriter(int flags){ + return gcnew DeviceWriter(descriptor, flags); +} + +DeviceWriter^ Listener::GetWriter(){ + return GetWriter(0); +} diff --git a/dotnet/Corelatus/Corelatus.GTH/Listener.h b/dotnet/Corelatus/Corelatus.GTH/Listener.h new file mode 100644 index 0000000..9ce7fa3 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Listener.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Corelatus.GTH.h" +#include "DeviceReader.h" +#include "DeviceWriter.h" +#include "IConnection.h" + +namespace Corelatus{ + namespace GTH{ + public ref class Listener :IConnection, IDisposable + { + private: + int descriptor; + int port; + Device^ device; + public: + virtual DeviceReader^ GetReader(); + virtual DeviceWriter^ GetWriter(); + virtual DeviceReader^ GetReader(int flags); + virtual DeviceWriter^ GetWriter(int flags); + virtual int NativeHandle(); + + property Device^ Owner{ + Device^ get(){ + return device; + } + } + + property int Port{ + int get(){ + return port; + } + } + internal: + Listener(int descriptor, int port, Device^ owner); + ~Listener(); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/NativeUtilities.cpp b/dotnet/Corelatus/Corelatus.GTH/NativeUtilities.cpp new file mode 100644 index 0000000..a217a8d --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/NativeUtilities.cpp @@ -0,0 +1,14 @@ +#include "stdafx.h" +#include "NativeUtilities.h" +#include "Socket.h" +#include "CorelatusException.h" + +using namespace Corelatus::GTH; + +bool NativeUtilities::WaitForPacket(Device^ device, IConnection^ connection){ + int res = wait_for_packet(device->NativeApi(), connection->NativeHandle()); + if (res == -1) + throw gcnew CorelatusException("waiting on packet failed, connection closed abruptly."); + + return res > 0; +} diff --git a/dotnet/Corelatus/Corelatus.GTH/NativeUtilities.h b/dotnet/Corelatus/Corelatus.GTH/NativeUtilities.h new file mode 100644 index 0000000..709fe41 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/NativeUtilities.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Corelatus.GTH.h" +#include "IConnection.h" + +using namespace System::Runtime::CompilerServices; + +namespace Corelatus{ + namespace GTH{ + [ExtensionAttribute] + public ref class NativeUtilities abstract sealed + { + public: + [ExtensionAttribute] + static bool WaitForPacket(Device^ device, IConnection^ connection); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/ReadMe.txt b/dotnet/Corelatus/Corelatus.GTH/ReadMe.txt new file mode 100644 index 0000000..e7879eb --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/ReadMe.txt @@ -0,0 +1,5 @@ +======================================================================== + Corelatus.GTH CLI Wrapper +======================================================================== + +A C++/CLI wrapper based on official C version. \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Socket.c b/dotnet/Corelatus/Corelatus.GTH/Socket.c new file mode 100644 index 0000000..956bd32 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Socket.c @@ -0,0 +1,66 @@ +#include "Socket.h" + +#include +#include "GTH.h" + +#include + +static int max_arg(int a, int b); + +int close(int handle){ + return closesocket(handle); +} + +int snd(int handle, const char* data, int len, int flags){ + return send(handle, data, len, flags); +} + +int rcv(int handle, char* data, int len, int flags){ + return recv(handle, data, len, flags); +} + +static int +max_arg(int a, int b) +{ + return (a > b) ? a : b; +} + +int wait_for_packet(void* ptr_api, int data_socket) +{ + GTH_api* api = (GTH_api*)ptr_api; + + fd_set fds; + int result; + int nfds = max_arg(api->fd, data_socket) + 1; + + FD_ZERO(&fds); + + for (;;) + { + struct timeval tv = { 1, 0 }; + FD_SET(api->fd, &fds); + FD_SET(data_socket, &fds); + + result = select(nfds, &fds, 0, 0, &tv); + + if (result < 0) + { + return -1; //failed + } + + if (result == 0) + { + return 0; + } + + if (FD_ISSET(api->fd, &fds)) + { + gth_nop(api); + } + + if (FD_ISSET(data_socket, &fds)) + { + return 1; + } + } +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Socket.h b/dotnet/Corelatus/Corelatus.GTH/Socket.h new file mode 100644 index 0000000..b334f7a --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Socket.h @@ -0,0 +1,6 @@ +#pragma once + +int close(int handle); +int snd(int handle, const char* data, int len, int flags); +int rcv(int handle, char* data, int len, int flags); +int wait_for_packet(void *api, int data_socket); \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/Stdafx.cpp b/dotnet/Corelatus/Corelatus.GTH/Stdafx.cpp new file mode 100644 index 0000000..5f94d28 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Stdafx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// Corelatus.GTH.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/dotnet/Corelatus/Corelatus.GTH/Stdafx.h b/dotnet/Corelatus/Corelatus.GTH/Stdafx.h new file mode 100644 index 0000000..3cc4c24 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/Stdafx.h @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + + diff --git a/dotnet/Corelatus/Corelatus.GTH/ToneArgs.cpp b/dotnet/Corelatus/Corelatus.GTH/ToneArgs.cpp new file mode 100644 index 0000000..0193430 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/ToneArgs.cpp @@ -0,0 +1,9 @@ +#include "stdafx.h" +#include "ToneArgs.h" + +using namespace Corelatus::GTH; + +ToneArgs::ToneArgs(String^ name) +{ + this->name = name; +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/ToneArgs.h b/dotnet/Corelatus/Corelatus.GTH/ToneArgs.h new file mode 100644 index 0000000..e15eede --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/ToneArgs.h @@ -0,0 +1,20 @@ +#pragma once + +using namespace System; + +namespace Corelatus{ + namespace GTH{ + public ref class ToneArgs :EventArgs + { + private: + String^ name; + public: + property String^ Name{ + String^ get(){ + return name; + } + } + ToneArgs(String^ name); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/ToneHandler.cpp b/dotnet/Corelatus/Corelatus.GTH/ToneHandler.cpp new file mode 100644 index 0000000..9e1896f --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/ToneHandler.cpp @@ -0,0 +1,23 @@ +#include "stdafx.h" +#include "ToneHandler.h" + +using namespace System::Runtime::InteropServices; +using namespace System::Reflection; +using namespace Corelatus::GTH; + +void ToneHandler::native_handle(const char *name, const int length) +{ + ToneArgs^ args = gcnew ToneArgs(gcnew String(name)); + ToneDetected(this, args); +} + +ToneHandler::ToneHandler(){ + + Type^ type = this->GetType(); + MethodInfo^ mi = type->GetMethod("native_handle", BindingFlags::NonPublic | BindingFlags::Instance); + del = Delegate::CreateDelegate(type, mi); +} + +IntPtr ToneHandler::native_ptr(){ + return Marshal::GetFunctionPointerForDelegate(del); +} \ No newline at end of file diff --git a/dotnet/Corelatus/Corelatus.GTH/ToneHandler.h b/dotnet/Corelatus/Corelatus.GTH/ToneHandler.h new file mode 100644 index 0000000..f1c1012 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/ToneHandler.h @@ -0,0 +1,22 @@ +#pragma once + +#include "ToneArgs.h" + +using namespace System; + +namespace Corelatus{ + namespace GTH{ + public ref class ToneHandler + { + private: + Delegate^ del; + public: + event EventHandler^ ToneDetected; + ToneHandler(); + + internal: + void native_handle(const char *name, const int length); + IntPtr native_ptr(); + }; + } +} diff --git a/dotnet/Corelatus/Corelatus.GTH/app.ico b/dotnet/Corelatus/Corelatus.GTH/app.ico new file mode 100644 index 0000000..d06d92b Binary files /dev/null and b/dotnet/Corelatus/Corelatus.GTH/app.ico differ diff --git a/dotnet/Corelatus/Corelatus.GTH/app.rc b/dotnet/Corelatus/Corelatus.GTH/app.rc new file mode 100644 index 0000000..eab4306 Binary files /dev/null and b/dotnet/Corelatus/Corelatus.GTH/app.rc differ diff --git a/dotnet/Corelatus/Corelatus.GTH/resource.h b/dotnet/Corelatus/Corelatus.GTH/resource.h new file mode 100644 index 0000000..d5ac7c4 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.GTH/resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc diff --git a/dotnet/Corelatus/Corelatus.sln b/dotnet/Corelatus/Corelatus.sln new file mode 100644 index 0000000..c9433d0 --- /dev/null +++ b/dotnet/Corelatus/Corelatus.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Corelatus.GTH", "Corelatus.GTH\Corelatus.GTH.vcxproj", "{6836D52D-2F3E-4568-BB02-9F2D8296CF89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaveToPcap", "SaveToPcap\SaveToPcap.csproj", "{10900870-540B-45DD-8420-D33C78AE03A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Corelatus.GTH.Utilities", "Corelatus.GTH.Utilities\Corelatus.GTH.Utilities.csproj", "{C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|Win32.ActiveCfg = Debug|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|Win32.Build.0 = Debug|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|x64.ActiveCfg = Debug|x64 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Debug|x64.Build.0 = Debug|x64 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|Any CPU.ActiveCfg = Release|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|Win32.ActiveCfg = Release|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|Win32.Build.0 = Release|Win32 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|x64.ActiveCfg = Release|x64 + {6836D52D-2F3E-4568-BB02-9F2D8296CF89}.Release|x64.Build.0 = Release|x64 + {10900870-540B-45DD-8420-D33C78AE03A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Debug|Win32.ActiveCfg = Debug|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Debug|x64.ActiveCfg = Debug|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Release|Any CPU.Build.0 = Release|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Release|Win32.ActiveCfg = Release|Any CPU + {10900870-540B-45DD-8420-D33C78AE03A5}.Release|x64.ActiveCfg = Release|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Debug|x64.ActiveCfg = Debug|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Release|Any CPU.Build.0 = Release|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Release|Win32.ActiveCfg = Release|Any CPU + {C50ECF56-6C6A-4CE7-AE01-D59936D4E7F3}.Release|x64.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dotnet/Corelatus/SaveToPcap/App.config b/dotnet/Corelatus/SaveToPcap/App.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/dotnet/Corelatus/SaveToPcap/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dotnet/Corelatus/SaveToPcap/Cmd.cs b/dotnet/Corelatus/SaveToPcap/Cmd.cs new file mode 100644 index 0000000..3b63207 --- /dev/null +++ b/dotnet/Corelatus/SaveToPcap/Cmd.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using CLAP; +using Corelatus.GTH.Utilities; +using PcapngUtils.Common; +using PcapngUtils.Pcap; + +namespace SaveToPcap +{ + class Cmd + { + private PcapWriter _writer; + + [Verb(IsDefault=true)] + public void Test( + [Required]string ip, + [DefaultValue(false)]bool fisu, + [DefaultValue(false)] bool esnf, + [DefaultValue(true)][Aliases("m")]bool monitor, + [DefaultValue(false)][Aliases("v")]bool verbose, + [Required][Aliases("s")]string spans, + [Required][Aliases("o")]string output) + { + Console.WriteLine("Output file is '{0}'",output); + var header = SectionHeader.CreateEmptyHeader(); + header.LinkType=LinkTypes.Mtp2; + _writer = new PcapWriter(output, header); + + var channels = DefineChannels(spans); + + Console.WriteLine("Openning Mtp2 receiver..."); + var receiver = new Mtp2Receiver(new Config + { + Address = ip, + Esnf = esnf, + Fisu = fisu, + Monitoring = monitor, + Verbose=verbose, + Channels = channels + }); + + receiver.Failed += (s, e) => Console.WriteLine(e); + receiver.PacketReceived+=PacketReceived; + using (receiver) + { + receiver.Start(); + Console.WriteLine("Mtp2 montoring started."); + Console.WriteLine("Press any key to exit."); + Console.ReadKey(true); + } + _writer.Dispose(); + } + + private static List DefineChannels(string spans) + { + Console.WriteLine("Defining channels..."); + var channels = new List(); + var parsedSpans = spans.Split(','); + + foreach (var span in parsedSpans) + { + var parts = span.Trim().Split(' '); + var ch = parts[0]; + var tsArr = parts.Skip(1).Select(t => int.Parse(t)).ToArray(); + + for (var j = 0; j < tsArr.Length; j++) + { + Console.WriteLine("Channel '{0}:{1}' defined.", ch, tsArr[j]); + var c = new Channel + { + Span = ch, + Timeslots = new[] {tsArr[j]} + }; + channels.Add(c); + } + } + return channels; + } + + private void PacketReceived(object sender, Mtp2Packet e) + { + _writer.WriteUnsafe(e.Seconds, e.Microseconds, e.Payload); + } + } +} diff --git a/dotnet/Corelatus/SaveToPcap/Program.cs b/dotnet/Corelatus/SaveToPcap/Program.cs new file mode 100644 index 0000000..8154f03 --- /dev/null +++ b/dotnet/Corelatus/SaveToPcap/Program.cs @@ -0,0 +1,12 @@ +using CLAP; + +namespace SaveToPcap +{ + class Program + { + private static void Main(string[] args) + { + Parser.RunConsole(args, new Cmd()); + } + } +} diff --git a/dotnet/Corelatus/SaveToPcap/Properties/AssemblyInfo.cs b/dotnet/Corelatus/SaveToPcap/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b69bb9f --- /dev/null +++ b/dotnet/Corelatus/SaveToPcap/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SaveToPcap")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SaveToPcap")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("923c3dd7-5578-450f-883e-59d8e47e3f59")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/dotnet/Corelatus/SaveToPcap/SaveToPcap.csproj b/dotnet/Corelatus/SaveToPcap/SaveToPcap.csproj new file mode 100644 index 0000000..86502dc --- /dev/null +++ b/dotnet/Corelatus/SaveToPcap/SaveToPcap.csproj @@ -0,0 +1,77 @@ + + + + + Debug + AnyCPU + {10900870-540B-45DD-8420-D33C78AE03A5} + Exe + Properties + SaveToPcap + SaveToPcap + v4.5 + 512 + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + true + + + x64 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + true + + + + ..\packages\CLAP.4.6\lib\net35\CLAP.dll + True + + + ..\..\..\..\Gears\Gears\Gemik.Gears\3rdParty\PcapngUtils\PcapngUtils.dll + + + + + + + + + + + + + + + + + + + + + {c50ecf56-6c6a-4ce7-ae01-d59936d4e7f3} + Corelatus.GTH.Utilities + + + + + \ No newline at end of file diff --git a/dotnet/Corelatus/SaveToPcap/packages.config b/dotnet/Corelatus/SaveToPcap/packages.config new file mode 100644 index 0000000..723ecf4 --- /dev/null +++ b/dotnet/Corelatus/SaveToPcap/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file