diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0143561c0980d9e42f1557b9cef488a5e8bfd8b9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,67 @@
+/coverage/
+/bin/
+
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2b52474da669ac755b7e01bef6ce937e66c11693
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,42 @@
+image: golang:1.16-buster
+
+cache:
+  paths:
+    - /apt-cache
+    - /go/src/github.com
+    - /go/src/golang.org
+    - /go/src/google.golang.org
+    - /go/src/gopkg.in
+
+stages:
+  - test
+
+before_script:
+
+unit_tests:
+  stage: test
+  script:
+    - make test
+  only:
+    - merge_requests 
+
+race_detector:
+  stage: test
+  script:
+    - make test-race
+  only:
+    - merge_requests
+
+code_coverage:
+  stage: test
+  script:
+    - make coverage
+  only:
+    - merge_requests
+
+lint_code:
+  stage: test
+  script:
+    - make lint
+  only:
+    - merge_requests 
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..73f69e0958611ac6e00bde95641f6699030ad235
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/aws.xml b/.idea/aws.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec328d0bbf68db9e7322932181cc811412e3ca87
--- /dev/null
+++ b/.idea/aws.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="accountSettings">
+    <option name="activeProfile" value="profile:default" />
+    <option name="activeRegion" value="eu-west-1" />
+    <option name="recentlyUsedProfiles">
+      <list>
+        <option value="profile:default" />
+      </list>
+    </option>
+    <option name="recentlyUsedRegions">
+      <list>
+        <option value="eu-west-1" />
+      </list>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea639c3e6909c3231f0285933b4f83a0e2e69c6d
--- /dev/null
+++ b/.idea/dbnavigator.xml
@@ -0,0 +1,463 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DBNavigator.Project.DataEditorManager">
+    <record-view-column-sorting-type value="BY_INDEX" />
+    <value-preview-text-wrapping value="true" />
+    <value-preview-pinned value="false" />
+  </component>
+  <component name="DBNavigator.Project.DataExportManager">
+    <export-instructions>
+      <create-header value="true" />
+      <friendly-headers value="false" />
+      <quote-values-containing-separator value="true" />
+      <quote-all-values value="false" />
+      <value-separator value="" />
+      <file-name value="" />
+      <file-location value="" />
+      <scope value="GLOBAL" />
+      <destination value="FILE" />
+      <format value="EXCEL" />
+      <charset value="UTF-8" />
+    </export-instructions>
+  </component>
+  <component name="DBNavigator.Project.DatabaseBrowserManager">
+    <autoscroll-to-editor value="false" />
+    <autoscroll-from-editor value="true" />
+    <show-object-properties value="true" />
+    <loaded-nodes />
+  </component>
+  <component name="DBNavigator.Project.DatabaseFileManager">
+    <open-files />
+  </component>
+  <component name="DBNavigator.Project.EditorStateManager">
+    <last-used-providers />
+  </component>
+  <component name="DBNavigator.Project.ExecutionManager">
+    <retain-sticky-names value="false" />
+  </component>
+  <component name="DBNavigator.Project.MethodExecutionManager">
+    <method-browser />
+    <execution-history>
+      <group-entries value="true" />
+      <execution-inputs />
+    </execution-history>
+    <argument-values-cache />
+  </component>
+  <component name="DBNavigator.Project.ObjectDependencyManager">
+    <last-used-dependency-type value="INCOMING" />
+  </component>
+  <component name="DBNavigator.Project.ObjectQuickFilterManager">
+    <last-used-operator value="EQUAL" />
+    <filters />
+  </component>
+  <component name="DBNavigator.Project.ScriptExecutionManager" clear-outputs="true">
+    <recently-used-interfaces />
+  </component>
+  <component name="DBNavigator.Project.Settings">
+    <connections />
+    <browser-settings>
+      <general>
+        <display-mode value="TABBED" />
+        <navigation-history-size value="100" />
+        <show-object-details value="false" />
+      </general>
+      <filters>
+        <object-type-filter>
+          <object-type name="SCHEMA" enabled="true" />
+          <object-type name="USER" enabled="true" />
+          <object-type name="ROLE" enabled="true" />
+          <object-type name="PRIVILEGE" enabled="true" />
+          <object-type name="CHARSET" enabled="true" />
+          <object-type name="TABLE" enabled="true" />
+          <object-type name="VIEW" enabled="true" />
+          <object-type name="MATERIALIZED_VIEW" enabled="true" />
+          <object-type name="NESTED_TABLE" enabled="true" />
+          <object-type name="COLUMN" enabled="true" />
+          <object-type name="INDEX" enabled="true" />
+          <object-type name="CONSTRAINT" enabled="true" />
+          <object-type name="DATASET_TRIGGER" enabled="true" />
+          <object-type name="DATABASE_TRIGGER" enabled="true" />
+          <object-type name="SYNONYM" enabled="true" />
+          <object-type name="SEQUENCE" enabled="true" />
+          <object-type name="PROCEDURE" enabled="true" />
+          <object-type name="FUNCTION" enabled="true" />
+          <object-type name="PACKAGE" enabled="true" />
+          <object-type name="TYPE" enabled="true" />
+          <object-type name="TYPE_ATTRIBUTE" enabled="true" />
+          <object-type name="ARGUMENT" enabled="true" />
+          <object-type name="DIMENSION" enabled="true" />
+          <object-type name="CLUSTER" enabled="true" />
+          <object-type name="DBLINK" enabled="true" />
+        </object-type-filter>
+      </filters>
+      <sorting>
+        <object-type name="COLUMN" sorting-type="NAME" />
+        <object-type name="FUNCTION" sorting-type="NAME" />
+        <object-type name="PROCEDURE" sorting-type="NAME" />
+        <object-type name="ARGUMENT" sorting-type="POSITION" />
+      </sorting>
+      <default-editors>
+        <object-type name="VIEW" editor-type="SELECTION" />
+        <object-type name="PACKAGE" editor-type="SELECTION" />
+        <object-type name="TYPE" editor-type="SELECTION" />
+      </default-editors>
+    </browser-settings>
+    <navigation-settings>
+      <lookup-filters>
+        <lookup-objects>
+          <object-type name="SCHEMA" enabled="true" />
+          <object-type name="USER" enabled="false" />
+          <object-type name="ROLE" enabled="false" />
+          <object-type name="PRIVILEGE" enabled="false" />
+          <object-type name="CHARSET" enabled="false" />
+          <object-type name="TABLE" enabled="true" />
+          <object-type name="VIEW" enabled="true" />
+          <object-type name="MATERIALIZED VIEW" enabled="true" />
+          <object-type name="INDEX" enabled="true" />
+          <object-type name="CONSTRAINT" enabled="true" />
+          <object-type name="DATASET TRIGGER" enabled="true" />
+          <object-type name="DATABASE TRIGGER" enabled="true" />
+          <object-type name="SYNONYM" enabled="false" />
+          <object-type name="SEQUENCE" enabled="true" />
+          <object-type name="PROCEDURE" enabled="true" />
+          <object-type name="FUNCTION" enabled="true" />
+          <object-type name="PACKAGE" enabled="true" />
+          <object-type name="TYPE" enabled="true" />
+          <object-type name="DIMENSION" enabled="false" />
+          <object-type name="CLUSTER" enabled="false" />
+          <object-type name="DBLINK" enabled="true" />
+        </lookup-objects>
+        <force-database-load value="false" />
+        <prompt-connection-selection value="true" />
+        <prompt-schema-selection value="true" />
+      </lookup-filters>
+    </navigation-settings>
+    <dataset-grid-settings>
+      <general>
+        <enable-zooming value="true" />
+        <enable-column-tooltip value="true" />
+      </general>
+      <sorting>
+        <nulls-first value="true" />
+        <max-sorting-columns value="4" />
+      </sorting>
+      <tracking-columns>
+        <columnNames value="" />
+        <visible value="true" />
+        <editable value="false" />
+      </tracking-columns>
+    </dataset-grid-settings>
+    <dataset-editor-settings>
+      <text-editor-popup>
+        <active value="false" />
+        <active-if-empty value="false" />
+        <data-length-threshold value="100" />
+        <popup-delay value="1000" />
+      </text-editor-popup>
+      <values-actions-popup>
+        <show-popup-button value="true" />
+        <element-count-threshold value="1000" />
+        <data-length-threshold value="250" />
+      </values-actions-popup>
+      <general>
+        <fetch-block-size value="100" />
+        <fetch-timeout value="30" />
+        <trim-whitespaces value="true" />
+        <convert-empty-strings-to-null value="true" />
+        <select-content-on-cell-edit value="true" />
+        <large-value-preview-active value="true" />
+      </general>
+      <filters>
+        <prompt-filter-dialog value="true" />
+        <default-filter-type value="BASIC" />
+      </filters>
+      <qualified-text-editor text-length-threshold="300">
+        <content-types>
+          <content-type name="Text" enabled="true" />
+          <content-type name="Properties" enabled="true" />
+          <content-type name="XML" enabled="true" />
+          <content-type name="DTD" enabled="true" />
+          <content-type name="HTML" enabled="true" />
+          <content-type name="XHTML" enabled="true" />
+          <content-type name="CSS" enabled="true" />
+          <content-type name="Java" enabled="true" />
+          <content-type name="SQL" enabled="true" />
+          <content-type name="PL/SQL" enabled="true" />
+          <content-type name="JavaScript" enabled="true" />
+          <content-type name="JSON" enabled="true" />
+          <content-type name="JSON5" enabled="true" />
+          <content-type name="PHP" enabled="true" />
+          <content-type name="JSP" enabled="true" />
+          <content-type name="JSPx" enabled="true" />
+          <content-type name="FTL" enabled="true" />
+          <content-type name="VTL" enabled="true" />
+          <content-type name="YAML" enabled="true" />
+          <content-type name="Manifest" enabled="true" />
+        </content-types>
+      </qualified-text-editor>
+      <record-navigation>
+        <navigation-target value="VIEWER" />
+      </record-navigation>
+    </dataset-editor-settings>
+    <code-editor-settings>
+      <general>
+        <show-object-navigation-gutter value="false" />
+        <show-spec-declaration-navigation-gutter value="true" />
+        <enable-spellchecking value="true" />
+        <enable-reference-spellchecking value="false" />
+      </general>
+      <confirmations>
+        <save-changes value="false" />
+        <revert-changes value="true" />
+      </confirmations>
+    </code-editor-settings>
+    <code-completion-settings>
+      <filters>
+        <basic-filter>
+          <filter-element type="RESERVED_WORD" id="keyword" selected="true" />
+          <filter-element type="RESERVED_WORD" id="function" selected="true" />
+          <filter-element type="RESERVED_WORD" id="parameter" selected="true" />
+          <filter-element type="RESERVED_WORD" id="datatype" selected="true" />
+          <filter-element type="RESERVED_WORD" id="exception" selected="true" />
+          <filter-element type="OBJECT" id="schema" selected="true" />
+          <filter-element type="OBJECT" id="role" selected="true" />
+          <filter-element type="OBJECT" id="user" selected="true" />
+          <filter-element type="OBJECT" id="privilege" selected="true" />
+          <user-schema>
+            <filter-element type="OBJECT" id="table" selected="true" />
+            <filter-element type="OBJECT" id="view" selected="true" />
+            <filter-element type="OBJECT" id="materialized view" selected="true" />
+            <filter-element type="OBJECT" id="index" selected="true" />
+            <filter-element type="OBJECT" id="constraint" selected="true" />
+            <filter-element type="OBJECT" id="trigger" selected="true" />
+            <filter-element type="OBJECT" id="synonym" selected="false" />
+            <filter-element type="OBJECT" id="sequence" selected="true" />
+            <filter-element type="OBJECT" id="procedure" selected="true" />
+            <filter-element type="OBJECT" id="function" selected="true" />
+            <filter-element type="OBJECT" id="package" selected="true" />
+            <filter-element type="OBJECT" id="type" selected="true" />
+            <filter-element type="OBJECT" id="dimension" selected="true" />
+            <filter-element type="OBJECT" id="cluster" selected="true" />
+            <filter-element type="OBJECT" id="dblink" selected="true" />
+          </user-schema>
+          <public-schema>
+            <filter-element type="OBJECT" id="table" selected="false" />
+            <filter-element type="OBJECT" id="view" selected="false" />
+            <filter-element type="OBJECT" id="materialized view" selected="false" />
+            <filter-element type="OBJECT" id="index" selected="false" />
+            <filter-element type="OBJECT" id="constraint" selected="false" />
+            <filter-element type="OBJECT" id="trigger" selected="false" />
+            <filter-element type="OBJECT" id="synonym" selected="false" />
+            <filter-element type="OBJECT" id="sequence" selected="false" />
+            <filter-element type="OBJECT" id="procedure" selected="false" />
+            <filter-element type="OBJECT" id="function" selected="false" />
+            <filter-element type="OBJECT" id="package" selected="false" />
+            <filter-element type="OBJECT" id="type" selected="false" />
+            <filter-element type="OBJECT" id="dimension" selected="false" />
+            <filter-element type="OBJECT" id="cluster" selected="false" />
+            <filter-element type="OBJECT" id="dblink" selected="false" />
+          </public-schema>
+          <any-schema>
+            <filter-element type="OBJECT" id="table" selected="true" />
+            <filter-element type="OBJECT" id="view" selected="true" />
+            <filter-element type="OBJECT" id="materialized view" selected="true" />
+            <filter-element type="OBJECT" id="index" selected="true" />
+            <filter-element type="OBJECT" id="constraint" selected="true" />
+            <filter-element type="OBJECT" id="trigger" selected="true" />
+            <filter-element type="OBJECT" id="synonym" selected="true" />
+            <filter-element type="OBJECT" id="sequence" selected="true" />
+            <filter-element type="OBJECT" id="procedure" selected="true" />
+            <filter-element type="OBJECT" id="function" selected="true" />
+            <filter-element type="OBJECT" id="package" selected="true" />
+            <filter-element type="OBJECT" id="type" selected="true" />
+            <filter-element type="OBJECT" id="dimension" selected="true" />
+            <filter-element type="OBJECT" id="cluster" selected="true" />
+            <filter-element type="OBJECT" id="dblink" selected="true" />
+          </any-schema>
+        </basic-filter>
+        <extended-filter>
+          <filter-element type="RESERVED_WORD" id="keyword" selected="true" />
+          <filter-element type="RESERVED_WORD" id="function" selected="true" />
+          <filter-element type="RESERVED_WORD" id="parameter" selected="true" />
+          <filter-element type="RESERVED_WORD" id="datatype" selected="true" />
+          <filter-element type="RESERVED_WORD" id="exception" selected="true" />
+          <filter-element type="OBJECT" id="schema" selected="true" />
+          <filter-element type="OBJECT" id="user" selected="true" />
+          <filter-element type="OBJECT" id="role" selected="true" />
+          <filter-element type="OBJECT" id="privilege" selected="true" />
+          <user-schema>
+            <filter-element type="OBJECT" id="table" selected="true" />
+            <filter-element type="OBJECT" id="view" selected="true" />
+            <filter-element type="OBJECT" id="materialized view" selected="true" />
+            <filter-element type="OBJECT" id="index" selected="true" />
+            <filter-element type="OBJECT" id="constraint" selected="true" />
+            <filter-element type="OBJECT" id="trigger" selected="true" />
+            <filter-element type="OBJECT" id="synonym" selected="true" />
+            <filter-element type="OBJECT" id="sequence" selected="true" />
+            <filter-element type="OBJECT" id="procedure" selected="true" />
+            <filter-element type="OBJECT" id="function" selected="true" />
+            <filter-element type="OBJECT" id="package" selected="true" />
+            <filter-element type="OBJECT" id="type" selected="true" />
+            <filter-element type="OBJECT" id="dimension" selected="true" />
+            <filter-element type="OBJECT" id="cluster" selected="true" />
+            <filter-element type="OBJECT" id="dblink" selected="true" />
+          </user-schema>
+          <public-schema>
+            <filter-element type="OBJECT" id="table" selected="true" />
+            <filter-element type="OBJECT" id="view" selected="true" />
+            <filter-element type="OBJECT" id="materialized view" selected="true" />
+            <filter-element type="OBJECT" id="index" selected="true" />
+            <filter-element type="OBJECT" id="constraint" selected="true" />
+            <filter-element type="OBJECT" id="trigger" selected="true" />
+            <filter-element type="OBJECT" id="synonym" selected="true" />
+            <filter-element type="OBJECT" id="sequence" selected="true" />
+            <filter-element type="OBJECT" id="procedure" selected="true" />
+            <filter-element type="OBJECT" id="function" selected="true" />
+            <filter-element type="OBJECT" id="package" selected="true" />
+            <filter-element type="OBJECT" id="type" selected="true" />
+            <filter-element type="OBJECT" id="dimension" selected="true" />
+            <filter-element type="OBJECT" id="cluster" selected="true" />
+            <filter-element type="OBJECT" id="dblink" selected="true" />
+          </public-schema>
+          <any-schema>
+            <filter-element type="OBJECT" id="table" selected="true" />
+            <filter-element type="OBJECT" id="view" selected="true" />
+            <filter-element type="OBJECT" id="materialized view" selected="true" />
+            <filter-element type="OBJECT" id="index" selected="true" />
+            <filter-element type="OBJECT" id="constraint" selected="true" />
+            <filter-element type="OBJECT" id="trigger" selected="true" />
+            <filter-element type="OBJECT" id="synonym" selected="true" />
+            <filter-element type="OBJECT" id="sequence" selected="true" />
+            <filter-element type="OBJECT" id="procedure" selected="true" />
+            <filter-element type="OBJECT" id="function" selected="true" />
+            <filter-element type="OBJECT" id="package" selected="true" />
+            <filter-element type="OBJECT" id="type" selected="true" />
+            <filter-element type="OBJECT" id="dimension" selected="true" />
+            <filter-element type="OBJECT" id="cluster" selected="true" />
+            <filter-element type="OBJECT" id="dblink" selected="true" />
+          </any-schema>
+        </extended-filter>
+      </filters>
+      <sorting enabled="true">
+        <sorting-element type="RESERVED_WORD" id="keyword" />
+        <sorting-element type="RESERVED_WORD" id="datatype" />
+        <sorting-element type="OBJECT" id="column" />
+        <sorting-element type="OBJECT" id="table" />
+        <sorting-element type="OBJECT" id="view" />
+        <sorting-element type="OBJECT" id="materialized view" />
+        <sorting-element type="OBJECT" id="index" />
+        <sorting-element type="OBJECT" id="constraint" />
+        <sorting-element type="OBJECT" id="trigger" />
+        <sorting-element type="OBJECT" id="synonym" />
+        <sorting-element type="OBJECT" id="sequence" />
+        <sorting-element type="OBJECT" id="procedure" />
+        <sorting-element type="OBJECT" id="function" />
+        <sorting-element type="OBJECT" id="package" />
+        <sorting-element type="OBJECT" id="type" />
+        <sorting-element type="OBJECT" id="dimension" />
+        <sorting-element type="OBJECT" id="cluster" />
+        <sorting-element type="OBJECT" id="dblink" />
+        <sorting-element type="OBJECT" id="schema" />
+        <sorting-element type="OBJECT" id="role" />
+        <sorting-element type="OBJECT" id="user" />
+        <sorting-element type="RESERVED_WORD" id="function" />
+        <sorting-element type="RESERVED_WORD" id="parameter" />
+      </sorting>
+      <format>
+        <enforce-code-style-case value="true" />
+      </format>
+    </code-completion-settings>
+    <execution-engine-settings>
+      <statement-execution>
+        <fetch-block-size value="100" />
+        <execution-timeout value="20" />
+        <debug-execution-timeout value="600" />
+        <focus-result value="false" />
+        <prompt-execution value="false" />
+      </statement-execution>
+      <script-execution>
+        <command-line-interfaces />
+        <execution-timeout value="300" />
+      </script-execution>
+      <method-execution>
+        <execution-timeout value="30" />
+        <debug-execution-timeout value="600" />
+        <parameter-history-size value="10" />
+      </method-execution>
+    </execution-engine-settings>
+    <operation-settings>
+      <transactions>
+        <uncommitted-changes>
+          <on-project-close value="ASK" />
+          <on-disconnect value="ASK" />
+          <on-autocommit-toggle value="ASK" />
+        </uncommitted-changes>
+        <multiple-uncommitted-changes>
+          <on-commit value="ASK" />
+          <on-rollback value="ASK" />
+        </multiple-uncommitted-changes>
+      </transactions>
+      <session-browser>
+        <disconnect-session value="ASK" />
+        <kill-session value="ASK" />
+        <reload-on-filter-change value="false" />
+      </session-browser>
+      <compiler>
+        <compile-type value="KEEP" />
+        <compile-dependencies value="ASK" />
+        <always-show-controls value="false" />
+      </compiler>
+      <debugger>
+        <debugger-type value="ASK" />
+        <use-generic-runners value="true" />
+      </debugger>
+    </operation-settings>
+    <ddl-file-settings>
+      <extensions>
+        <mapping file-type-id="VIEW" extensions="vw" />
+        <mapping file-type-id="TRIGGER" extensions="trg" />
+        <mapping file-type-id="PROCEDURE" extensions="prc" />
+        <mapping file-type-id="FUNCTION" extensions="fnc" />
+        <mapping file-type-id="PACKAGE" extensions="pkg" />
+        <mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
+        <mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
+        <mapping file-type-id="TYPE" extensions="tpe" />
+        <mapping file-type-id="TYPE_SPEC" extensions="tps" />
+        <mapping file-type-id="TYPE_BODY" extensions="tpb" />
+      </extensions>
+      <general>
+        <lookup-ddl-files value="true" />
+        <create-ddl-files value="false" />
+        <synchronize-ddl-files value="true" />
+        <use-qualified-names value="false" />
+        <make-scripts-rerunnable value="true" />
+      </general>
+    </ddl-file-settings>
+    <general-settings>
+      <regional-settings>
+        <date-format value="MEDIUM" />
+        <number-format value="UNGROUPED" />
+        <locale value="SYSTEM_DEFAULT" />
+        <use-custom-formats value="false" />
+      </regional-settings>
+      <environment>
+        <environment-types>
+          <environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
+          <environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
+          <environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
+          <environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
+        </environment-types>
+        <visibility-settings>
+          <connection-tabs value="true" />
+          <dialog-headers value="true" />
+          <object-editor-tabs value="true" />
+          <script-editor-tabs value="false" />
+          <execution-result-tabs value="true" />
+        </visibility-settings>
+      </environment>
+    </general-settings>
+  </component>
+  <component name="DBNavigator.Project.StatementExecutionManager">
+    <execution-variables />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/markdown-navigator-enh.xml b/.idea/markdown-navigator-enh.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a8fcc84db3668cadd75348be61bda65a8fc5ea21
--- /dev/null
+++ b/.idea/markdown-navigator-enh.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MarkdownEnhProjectSettings">
+    <AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" />
+    <HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imagePathType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
+    <LinkMapSettings>
+      <textMaps />
+    </LinkMapSettings>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2fc0864e7bc79d88eaf4d3f18785833dfe9d367
--- /dev/null
+++ b/.idea/markdown-navigator.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MarkdownProjectSettings">
+    <PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="LINE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="true" showSelectionInPreview="true" lastLayoutSetsDefault="false">
+      <PanelProvider>
+        <provider providerId="com.vladsch.md.nav.editor.swing.html.panel" providerName="Default - Swing" />
+      </PanelProvider>
+    </PreviewSettings>
+    <ParserSettings gitHubSyntaxChange="false" correctedInvalidSettings="false" emojiShortcuts="1" emojiImages="0">
+      <PegdownExtensions>
+        <option name="ATXHEADERSPACE" value="true" />
+        <option name="FENCED_CODE_BLOCKS" value="true" />
+        <option name="INTELLIJ_DUMMY_IDENTIFIER" value="true" />
+        <option name="RELAXEDHRULES" value="true" />
+        <option name="STRIKETHROUGH" value="true" />
+        <option name="TABLES" value="true" />
+        <option name="TASKLISTITEMS" value="true" />
+      </PegdownExtensions>
+      <ParserOptions>
+        <option name="COMMONMARK_LISTS" value="true" />
+        <option name="EMOJI_SHORTCUTS" value="true" />
+        <option name="GFM_TABLE_RENDERING" value="true" />
+        <option name="PRODUCTION_SPEC_PARSER" value="true" />
+        <option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
+      </ParserOptions>
+    </ParserSettings>
+    <HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="false" addAnchorLinks="false" anchorLinksWrapText="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" defaultUrlTitle="false" migratedPlantUml="true" migratedAnchorLinks="true" plantUmlConversion="0">
+      <GeneratorProvider>
+        <provider providerId="com.vladsch.md.nav.editor.text.html.generator" providerName="Unmodified HTML Generator" />
+      </GeneratorProvider>
+      <headerTop />
+      <headerBottom />
+      <bodyTop />
+      <bodyBottom />
+      <fencedCodeConversions>
+        <option name="c4plantuml" value="NONE" />
+        <option name="ditaa" value="NONE" />
+        <option name="erd" value="NONE" />
+        <option name="graphviz" value="NONE" />
+        <option name="latex" value="KATEX" />
+        <option name="math" value="KATEX" />
+        <option name="mermaid" value="NONE" />
+        <option name="nomnoml" value="NONE" />
+        <option name="plantuml" value="NONE" />
+        <option name="puml" value="NONE" />
+        <option name="svgbob" value="NONE" />
+        <option name="umlet" value="NONE" />
+        <option name="vega" value="NONE" />
+        <option name="vegalite" value="NONE" />
+        <option name="wavedrom" value="NONE" />
+      </fencedCodeConversions>
+    </HtmlSettings>
+    <CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
+      <StylesheetProvider>
+        <provider providerId="com.vladsch.md.nav.editor.text.html.css" providerName="No Stylesheet" />
+      </StylesheetProvider>
+      <ScriptProviders />
+      <cssText />
+      <cssUriHistory />
+    </CssSettings>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..639900d13c6182e452e33a3bd638e70a0146c785
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f0ad2f76bc8b29cb0a6001f9372e71a889a790f3
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/traceroute.iml" filepath="$PROJECT_DIR$/traceroute.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e74cfa6fcae11a1fbe280a77e044309d8867c806
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,81 @@
+
+#PACKAGES		?= $(shell basename `go list`)
+#FILES		?= $(shell find . -type f -name '*.go' -not -path "./vendor/*")
+
+#VERSION		?= $(shell git describe --tags --always --dirty --match=v* 2> /dev/null || cat $(PWD)/.version 2> /dev/null || echo v0)
+##PACKAGE		?= $(shell go list)
+##PACKAGES	?= $(shell go list ./...)
+
+PROJECT_NAME := "traceroute"
+PKG := "gitlab.schukai.com/oss/libraries/go/network/traceroute"
+PKG_LIST := $(shell go list ${PKG}/... )
+GO_FILES := $(shell find . -name '*.go')
+#GO_FILES := $(shell find . -name '*.go' | grep -v _test.go)
+
+GOCMD=go
+GOBUILD=$(GOCMD) build 
+GOCLEAN=$(GOCMD) clean 
+GOTEST=$(GOCMD) test 
+GOVET=$(GOCMD) vet  
+GOGET=$(GOCMD) get 
+GOFMT=$(GOCMD) fmt 
+GODOC=$(GOCMD) fmt 
+GOLINT=golint 
+
+default: help
+
+help:   ## show this help
+	@echo 'usage: make [target] ...'
+	@echo ''
+	@echo 'targets:'
+	@egrep '^(.+)\:\ .*##\ (.+)' ${MAKEFILE_LIST} | sed 's/:.*##/#/' | column -t -c 2 -s '#'
+
+clean:  ## go clean
+	$(GOCLEAN)
+
+clean-all:  ## remove all generated artifacts and clean all build artifacts
+	$(GOCLEAN) -i ./...
+
+lint:   ## run go lint on the source files
+	$(GOLINT) -set_exit_status .
+
+vet:    ## run go vet on the source files
+	$(GOVET) ./...
+
+doc:    ## generate godocs and start a local documentation webserver on port 8085
+	godoc -http=:8085 -index
+
+test:   ## test package
+	$(GOTEST) -v $(PKG_LIST)
+
+test-race: ## run race-tests
+	$(GOTEST) -race $(PKG_LIST)
+
+benchmark: ## run benchmark tests
+	$(GOTEST) -bench .
+
+coverage: coverage/cover.html ## Run test coverage and generate html report
+
+coverage/cover.html: $(GO_FILES) 
+	mkdir -p coverage
+	$(GOCMD) list -f '{{if gt (len .TestGoFiles) 0}}"go test -covermode count -coverprofile {{.Name}}.coverprofile -coverpkg ./... {{.ImportPath}}"{{end}}' ./... | xargs -I {} bash -c {}
+	echo "mode: count" > coverage/cover.out
+	grep -h -v "^mode:" *.coverprofile >> "coverage/cover.out"
+	rm *.coverprofile
+	$(GOCMD) tool cover -html=coverage/cover.out -o=coverage/cover.html
+
+test-all: test test-race benchmark coverage
+
+
+fmt:    ## format the go source files
+	$(GOFMT) .
+
+all:    ## clean, format and unit test
+	make clean-all
+	make fmt
+	make test-all
+
+build-cmd:
+	mkdir -p bin
+	$(GOCMD) build -o bin/traceroute cmd/main.go
+	sudo setcap cap_net_raw+ep bin/traceroute 
diff --git a/README.md b/README.md
index 22447bc549c2d6e06e0434f953397cb452c49320..f4658127d5f420f0965cd4362ade1a2c7ddf20f9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,113 @@
-# traceroute
+# Traceroute
+
+This library allows to record a traceroute.
+
+## Requirements
+
+To execute the traceroute, a privileged port must be opened. this
+requires special permissions. One possibility is .
+
+A prerequisite for reading incoming traffic is being able to either to
+be root or set the executable capability `CAP_NET_RAW`.
+
+Reminder: You can set the `CAP_NET_RAW` capability on an executable like
+this:
+
+```bash
+sudo setcap cap_net_raw+ep /path/to/executable
+```
+
+Look at manpage for [setcap](https://linux.die.net/man/8/setcap)
+
+You can also change the restrictions on unprivileged ports. 
+
+```bash
+sudo /sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0
+```
+
+for the purpose of debugging, pkttyagent can also be taken.
+
+```bash
+
+# PID is the processid
+pkttyagent --process  PID-OF-IDE
+
+## für netbeans
+pkttyagent --process  $(ps -xa | grep "netbeans" )
+
+## für intellij
+pkttyagent --process  $(ps -xa | grep "IntelliJ-IDEA-Ultimate/jbr/bin/java" )
+```
+
+## Installation
+
+The recommended way to install this package is
+
+```bash
+go get gitlab.schukai.com/oss/libraries/go/network/traceroute
+```
+
+## Usage
+
+First, a session must be created `traceroute.NewSession(host)`. Then the
+traceroute can be executed `session.TraceRoute()`.  
+
+Either waits for the result and continues working with it, or   
+Specifies a callback that is called directly after a hop.
+
+
+```go
+package main
+
+import (
+	"flag"
+	"fmt"
+	"gitlab.schukai.com/oss/libraries/go/network/traceroute"
+)
+
+const (
+	flagValue = ""
+	flagUsage = "hostname or ip address"
+)
+
+func main() {
+
+	var host string
+
+	flag.StringVar(&host, "h", flagValue, flagUsage+" (shorthand)")
+	flag.StringVar(&host, "host", flagValue, flagUsage)
+	flag.Parse()
+
+	if host == "" {
+		fmt.Println("missing host")
+		flag.Usage()
+		return
+	}
+
+	session, err := traceroute.NewSession(host)
+	if err != nil {
+		flag.Usage()
+		return
+	}
+
+	session.CallBack = func(result traceroute.Result) {
+		if result.Err!=nil {
+			fmt.Printf("%v\t%s\t\t\t\t%v\t\t(%s)\n", result.Hop, result.Station, result.Latency, result.Err.Error())
+			return
+		}
+		
+		fmt.Printf("%v\t%s\t\t\t%v\n", result.Hop, result.Station, result.Latency)
+	}
+
+	_, err=session.TraceRoute()
+	if err!=nil {
+		fmt.Println(err.Error())
+	}
+
+}
+```
+
+
+
+
 
diff --git a/bin/traceroute b/bin/traceroute
new file mode 100755
index 0000000000000000000000000000000000000000..d1dab4a834876711bf6d28747b0700893b2a9bad
Binary files /dev/null and b/bin/traceroute differ
diff --git a/cmd/main.go b/cmd/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..f623e6cbf2a1c02ebbc7b0070934c90b4066aca4
--- /dev/null
+++ b/cmd/main.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"gitlab.schukai.com/oss/libraries/go/network/traceroute"
+)
+
+const (
+	flagValue = ""
+	flagUsage = "hostname or ip address"
+)
+
+func main() {
+
+	var host string
+
+	flag.StringVar(&host, "h", flagValue, flagUsage+" (shorthand)")
+	flag.StringVar(&host, "host", flagValue, flagUsage)
+	flag.Parse()
+
+	if host == "" {
+		fmt.Println("missing host")
+		flag.Usage()
+		return
+	}
+
+	session, err := traceroute.NewSession(host)
+	if err != nil {
+		flag.Usage()
+		return
+	}
+
+	session.CallBack = func(result traceroute.Result) {
+		if result.Err!=nil {
+			fmt.Printf("%v\t%s\t\t\t\t%v\t\t(%s)\n", result.Hop, result.Station, result.Latency, result.Err.Error())
+			return
+		}
+		
+		fmt.Printf("%v\t%s\t\t\t%v\n", result.Hop, result.Station, result.Latency)
+	}
+
+	_, err=session.TraceRoute()
+	if err!=nil {
+		fmt.Println(err.Error())
+	}
+
+}
diff --git a/dns.go b/dns.go
new file mode 100644
index 0000000000000000000000000000000000000000..52869ba48ad0234a4359b8858e4654f681870488
--- /dev/null
+++ b/dns.go
@@ -0,0 +1,46 @@
+package traceroute
+
+import (
+	"errors"
+	"net"
+)
+
+func resolveDNS(hostname string) (*address, error) {
+
+	ips, err := net.LookupIP(hostname)
+	if err != nil {
+		return nil, err
+	}
+
+	var ipV4 net.IP
+	for _, ip := range ips {
+		if len(ip) == net.IPv6len {
+			return &address{ip: ip, version: addressV6}, nil
+		} else if len(ip) == net.IPv4len {
+			ipV4 = ip
+		}
+	}
+
+	if ipV4 != nil {
+		return &address{ip: ipV4, version: addressV4}, nil
+	}
+
+	return nil, errors.New("could not find a valid record for " + hostname)
+
+}
+
+// DNS resolution utility function (IPv6/IPv4)
+func resolve(hostname string) (*address, error) {
+	ip := net.ParseIP(hostname)
+
+	if ip.To4() != nil {
+		return &address{ip: ip, version: addressV4}, nil
+	}
+
+	if ip.To16() != nil {
+		return &address{ip: ip, version: addressV6}, nil
+	}
+
+	return resolveDNS(hostname)
+
+}
diff --git a/dns_test.go b/dns_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..9d35bb648e2e95f4bb8f6cd7c58c93c24a71ee04
--- /dev/null
+++ b/dns_test.go
@@ -0,0 +1,65 @@
+package traceroute
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestResolve(t *testing.T) {
+
+	testCases := []struct {
+		name           string
+		should         string
+		shouldHasError bool
+		shouldVersion  int
+	}{
+		{"schukai.com", "80.147.206.177", false, addressV4},
+		{"unsupported", "", true, addressV4},
+		{"::ffff:192.0.2.1", "192.0.2.1", false, addressV4}, // ipv6 masked ipv4
+		{"127.0.0.1", "127.0.0.1", false, addressV4},
+		{"2001:4860:4860::8888", "2001:4860:4860::8888", false, addressV6},
+		{"example.com", "2606:2800:220:1:248:1893:25c8:1946", false, addressV6},
+	}
+	for _, tc := range testCases {
+
+		t.Run(fmt.Sprintf("%s should fail %t", tc.name, tc.shouldHasError), func(t *testing.T) {
+			address, err := resolve(tc.name)
+			if err != nil {
+				if tc.shouldHasError == true {
+					return
+				}
+				t.Errorf("dns query error: %s", err.Error())
+			}
+
+			if address.String() != tc.should {
+				t.Errorf("query %s should %s and not %s", tc.name, tc.should, address.String())
+			}
+
+			if tc.shouldVersion == addressV6 {
+				if address.isV6() != true || address.isV4() != false {
+					t.Errorf("query %s should version V6", tc.name)
+				}
+			} else {
+				if address.isV6() == true || address.isV4() == false {
+					t.Errorf("query %s should version V4", tc.name)
+				}
+			}
+
+
+		})
+
+	}
+
+}
+
+func benchmarkResolve(address string, b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		resolve(address)
+	}
+}
+
+func BenchmarkResolve1(b *testing.B) { benchmarkResolve("www.google.com", b) }
+func BenchmarkResolve2(b *testing.B) { benchmarkResolve("www.schukai.com", b) }
+func BenchmarkResolve3(b *testing.B) { benchmarkResolve("2001:4860:4860::8888", b) }
+func BenchmarkResolve4(b *testing.B) { benchmarkResolve("unsupported", b) }
+func BenchmarkResolve5(b *testing.B) { benchmarkResolve("127.0.0.1", b) }
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000000000000000000000000000000000000..94ecf4885b42f56d210ccd17cf0384b4c5ba1760
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,9 @@
+module gitlab.schukai.com/oss/libraries/go/network/traceroute
+
+go 1.16
+
+require (
+	github.com/creasty/defaults v1.5.1
+	github.com/jackpal/gateway v1.0.7
+	golang.org/x/net v0.0.0-20210510120150-4163338589ed
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000000000000000000000000000000000000..ea2dc19104755a5ea5f53b1198ba334d96e71c1c
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,12 @@
+github.com/creasty/defaults v1.5.1 h1:j8WexcS3d/t4ZmllX4GEkl4wIB/trOr035ajcLHCISM=
+github.com/creasty/defaults v1.5.1/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY=
+github.com/jackpal/gateway v1.0.7 h1:7tIFeCGmpyrMx9qvT0EgYUi7cxVW48a0mMvnIL17bPM=
+github.com/jackpal/gateway v1.0.7/go.mod h1:aRcO0UFKt+MgIZmRmvOmnejdDT4Y1DNiNOsSd1AcIbA=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/ip.go b/ip.go
new file mode 100644
index 0000000000000000000000000000000000000000..1adf99da6f5e76dd8e354c4208edf128b96a7389
--- /dev/null
+++ b/ip.go
@@ -0,0 +1,69 @@
+package traceroute
+
+import "net"
+
+const (
+	unknown   = 0
+	addressV4 = 4
+	addressV6 = 6
+)
+
+func isV4(ip net.IP) bool {
+	i := ip.To4()
+	if i != nil {
+		return true
+	}
+	return false
+}
+
+type address struct {
+	ip      net.IP
+	version int
+}
+
+func (a address) isV4() bool {
+	return a.version == addressV4
+}
+func (a address) isV6() bool {
+	return a.version == addressV6
+}
+
+func (a address) isUnknow() bool {
+	return a.version == unknown
+}
+
+func (a address) String() string {
+	return a.ip.String()
+}
+
+func  (a address) Network() string {
+	r:= net.IPAddr{
+		IP:   a.ip,
+		Zone: "",
+	}
+	return r.Network()
+}
+
+func newAddress(ip net.IP) address {
+
+	if ip == nil {
+		return address{
+			ip:      nil,
+			version: unknown,
+		}
+
+	}
+
+	if isV4(ip) {
+		return address{
+			ip:      ip,
+			version: addressV4,
+		}
+	}
+
+	return address{
+		ip:      ip,
+		version: addressV6,
+	}
+
+}
diff --git a/ip_test.go b/ip_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a51694762e4d387e8a23e03d26db195486998753
--- /dev/null
+++ b/ip_test.go
@@ -0,0 +1,38 @@
+package traceroute
+
+import (
+	"fmt"
+	"net"
+	"testing"
+)
+
+func TestNewAddress(t *testing.T) {
+
+	testCases := []struct {
+		name           string
+		mode int
+	}{
+		{"127.0.0.1",addressV4},
+		{"unsupported", unknown},
+		{"::ffff:192.0.2.1", addressV4}, 
+		{"2001:4860:4860::8888", addressV6},
+		{"2606:2800:220:1:248:1893:25c8:1946", addressV6},
+	}
+	for _, tc := range testCases {
+
+		t.Run(fmt.Sprintf("%s should fail %d", tc.name, tc.mode), func(t *testing.T) {
+			a:= newAddress(net.ParseIP(tc.name))
+
+			if a.isV4()&&tc.mode!=addressV4 {
+				t.Errorf("an error has occurred")
+			} else if a.isV6()&&tc.mode!=addressV6 {
+				t.Errorf("an error has occurred")
+			} else if a.isUnknow() &&tc.mode!=unknown{
+				t.Errorf("an error has occurred")
+			}
+
+		})
+
+	}
+
+}
diff --git a/outbound.go b/outbound.go
new file mode 100644
index 0000000000000000000000000000000000000000..764b71c659832eba52d87370bccbf0b02769eb13
--- /dev/null
+++ b/outbound.go
@@ -0,0 +1,97 @@
+package traceroute
+
+import (
+	"errors"
+	"github.com/jackpal/gateway"
+	"net"
+)
+
+func getOutboundIP(mode int) (*address, error) {
+	ip, err := gateway.DiscoverInterface()
+	if err != nil {
+		return nil, err
+	}
+
+	a := newAddress(ip)
+
+	switch mode {
+	case addressV4:
+		if isV4(ip) {
+			return &a, nil
+		}
+	case addressV6:
+		if !isV4(ip) {
+			return &a, nil
+		}
+	case unknown:
+	default:
+		return nil, errors.New("the mode parameter must be either 4 or 6")
+	}
+
+	interfaces, err := net.Interfaces()
+
+	if err != nil {
+		return nil, err
+	}
+
+	for _, i := range interfaces {
+		addrs, err := i.Addrs()
+
+		if err != nil {
+			continue
+		}
+
+		var ipv6, ipv4 net.IP
+		var found bool
+
+		for _, a := range addrs {
+			if a.Network() != "ip+net" {
+				continue
+			}
+
+			b, _, err := net.ParseCIDR(a.String())
+			if err != nil {
+				continue
+			}
+
+			if !b.IsGlobalUnicast() {
+				continue
+			}
+
+			if isV4(b) {
+				ipv4 = b
+			} else {
+				ipv6 = b
+			}
+
+			if b.String() == ip.String() {
+				found = true
+			}
+
+		}
+
+		if !found {
+			continue
+		}
+
+		if mode <= addressV4 {
+			if ipv4 == nil {
+				return nil, errors.New("no suitable interface was found")
+			}
+
+			a:= newAddress(ipv4)
+			return &a, nil
+		}
+
+		if ipv6 == nil {
+			return nil, errors.New("no suitable interface was found")
+		}
+
+		a:= newAddress(ipv6)
+		return &a, nil
+
+	}
+
+	return nil, errors.New("no suitable interface was found")
+
+}
diff --git a/outbound_test.go b/outbound_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..64587a8508e1b4d99845b009f4933b45df0bdd0e
--- /dev/null
+++ b/outbound_test.go
@@ -0,0 +1,38 @@
+package traceroute
+
+import (
+	"testing"
+)
+
+func TestGetOutboundIPV6(t *testing.T) {
+	ip, err := getOutboundIP(addressV6)
+
+	if err != nil {
+		t.Errorf("this call should not return an error " + err.Error())
+	}
+	
+	if !ip.isV6() {
+		t.Errorf("this call should not return an error " + err.Error())
+	}
+	
+	
+}
+
+func TestGetOutboundIPV4(t *testing.T) {
+	ip, err := getOutboundIP(addressV4)
+
+	if err != nil {
+		t.Errorf("this call should not return an error " + err.Error())
+	}
+
+	if !ip.isV4() {
+		t.Errorf("this call should not return an error " + err.Error())
+	}
+	
+}
+
+func BenchmarkGetOutboundIP(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		getOutboundIP(addressV6)
+	}
+}
diff --git a/session.go b/session.go
new file mode 100644
index 0000000000000000000000000000000000000000..b4a51f04226375e02c227dfc0358466541335406
--- /dev/null
+++ b/session.go
@@ -0,0 +1,59 @@
+package traceroute
+
+import (
+	"github.com/creasty/defaults"
+	"golang.org/x/net/icmp"
+	"golang.org/x/net/ipv4"
+	"time"
+)
+
+// Session is Transaction Struct
+type Session struct {
+	Destination *address
+	Source      *address
+	
+	CallBack func(result Result)
+
+	Timeout time.Duration `default:"2"` // in seconds
+	MaxHops int   `default:"30"`
+
+	nextHop  int
+	isFinale bool
+
+	ipV4Sock   *ipv4.PacketConn
+	icmpEcho   icmp.Message
+	readBuffer []byte
+}
+
+// NewSession creates a new Session 
+func NewSession(destination string) (*Session, error) {
+
+	s := Session{}
+
+	if err := defaults.Set(&s); err != nil {
+		return nil, err
+	}
+
+	dest, err := resolve(destination)
+	if err != nil {
+		return nil, err
+	}
+	s.Destination = dest
+
+	var mode int
+	if dest.isV6() {
+		mode = addressV6
+	} else {
+		mode = addressV4
+	}
+
+	
+	s.Timeout = s.Timeout*time.Second
+	//* time.Second
+
+	src, err := getOutboundIP(mode)
+	s.Source = src
+
+	return &s, nil
+
+}
diff --git a/session_test.go b/session_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..e9c8b7a739f491a02f37aad2235478201e37b505
--- /dev/null
+++ b/session_test.go
@@ -0,0 +1,48 @@
+package traceroute
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestNewSession(t *testing.T) {
+
+	testCases := []struct {
+		destination        string
+		shouldSessionError bool
+	}{
+		{
+			"www.schukai.com",
+			false,
+		},
+	}
+
+	for _, tc := range testCases {
+
+		t.Run(fmt.Sprintf(""), func(t *testing.T) {
+
+			session, err := NewSession(tc.destination)
+			if err != nil {
+				if tc.shouldSessionError {
+					return
+				}
+				t.Errorf("%s shout not error %s", tc.destination, err.Error())
+				return
+			}
+
+			if session.Timeout==0 {
+				t.Errorf("timeout should be greater than 0")
+			}
+
+			_, err = session.TraceRoute()
+			if err!=nil {
+				t.Errorf("%s shout not error %s", tc.destination, err.Error())
+				return
+			}
+		
+
+		})
+
+	}
+
+}
diff --git a/traceroute.coverprofile b/traceroute.coverprofile
new file mode 100644
index 0000000000000000000000000000000000000000..2f575eff08efa23cfe98a890e39ee4c7a39814b7
--- /dev/null
+++ b/traceroute.coverprofile
@@ -0,0 +1,106 @@
+mode: count
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:26.39,36.16 4 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:41.2,41.45 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:46.2,55.68 4 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:60.2,60.78 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:65.2,67.20 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:71.2,71.16 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:76.2,78.16 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:83.2,86.50 3 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:91.2,91.47 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:96.2,98.10 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:36.16,39.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:41.45,44.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:55.68,58.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:60.78,63.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:67.20,69.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:71.16,74.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:78.16,81.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:86.50,89.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:91.47,94.3 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:101.52,105.16 2 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:109.2,114.118 4 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:118.2,126.33 4 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:133.2,133.22 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:105.16,107.3 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:114.118,116.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:126.33,128.17 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:128.17,129.9 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:142.50,144.26 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:159.2,159.74 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:144.26,146.17 2 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:149.3,149.22 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:146.17,148.4 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:8.52,11.16 2 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:15.2,16.25 2 4
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:24.2,24.17 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:28.2,28.73 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:11.16,13.3 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:16.25,17.29 1 4
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:17.29,19.4 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:19.9,19.36 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:19.36,21.4 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:24.17,26.3 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:33.49,36.21 2 8
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:40.2,40.22 1 6
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:44.2,44.29 1 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:36.21,38.3 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:40.22,42.3 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:11.27,13.14 2 15
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:16.2,16.14 1 4
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:13.14,15.3 1 11
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:24.30,26.2 1 13
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:27.30,29.2 1 13
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:31.34,33.2 1 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:35.34,37.2 1 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:39.36,45.2 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:47.36,49.15 1 10
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:57.2,57.14 1 9
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:64.2,67.3 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:49.15,55.3 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:57.14,62.3 1 6
+gitlab.schukai.com/oss/libraries/go/network/traceroute/main.go:3.14,5.2 0 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:9.48,11.16 2 4
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:15.2,17.14 2 4
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:31.2,33.16 2 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:37.2,37.31 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:95.2,95.59 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:11.16,13.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:18.17,19.15 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:22.17,23.16 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:26.15,26.15 0 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:27.10,28.69 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:19.15,21.4 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:23.16,25.4 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:33.16,35.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:37.31,40.17 2 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:44.3,47.27 3 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:73.3,73.13 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:77.3,77.24 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:86.3,86.18 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:90.3,91.17 2 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:40.17,41.12 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:47.27,48.31 1 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:52.4,53.18 2 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:57.4,57.28 1 5
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:61.4,61.15 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:67.4,67.33 1 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:48.31,49.13 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:53.18,54.13 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:57.28,58.13 1 3
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:61.15,63.5 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:63.10,65.5 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:67.33,69.5 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:73.13,74.12 1 1
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:77.24,78.19 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:82.4,83.18 2 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:78.19,80.5 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:86.18,88.4 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:27.55,31.41 2 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:35.2,36.16 2 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:39.2,42.17 3 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:49.2,55.16 4 2
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:31.41,33.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:36.16,38.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:42.17,44.3 1 0
+gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:44.8,46.3 1 2
diff --git a/traceroute.go b/traceroute.go
new file mode 100644
index 0000000000000000000000000000000000000000..c867c04e83f4f748cf0b85cb0c1182085e174c32
--- /dev/null
+++ b/traceroute.go
@@ -0,0 +1,166 @@
+package traceroute
+
+import (
+	"errors"
+	"fmt"
+	"golang.org/x/net/icmp"
+	"golang.org/x/net/ipv4"
+	"math/rand"
+	"net"
+
+	"time"
+)
+
+type Result struct {
+	Hop     int
+	Station string
+	Latency time.Duration
+	Err     error
+}
+
+// Results is a collection of hops
+type Results struct {
+	Hops []Result
+}
+
+func (s *Session) doHop(i int) Result {
+	s.icmpEcho.Body.(*icmp.Echo).Seq = i
+
+	r := Result{
+		Hop:     i,
+		Station: "*",
+	}
+
+	writeBuffer, err := s.icmpEcho.Marshal(nil)
+
+	if err != nil {
+		r.Err = err
+		return r
+	}
+
+	if err := s.ipV4Sock.SetTTL(i); err != nil {
+		r.Err = fmt.Errorf("socket: %w", err)
+		return r
+	}
+
+	timeNow := time.Now()
+
+	dst := s.Destination
+
+	a := net.IPAddr{
+		IP:   dst.ip,
+		Zone: "",
+	}
+
+	if _, err := s.ipV4Sock.WriteTo(writeBuffer, nil, &a); err != nil {
+		r.Err = err
+		return r
+	}
+
+	if err := s.ipV4Sock.SetReadDeadline(time.Now().Add(s.Timeout)); err != nil {
+		r.Err = err
+		return r
+	}
+
+	readBytes, _, hopNode, err := s.ipV4Sock.ReadFrom(s.readBuffer)
+
+	if hopNode != nil {
+		r.Station = hopNode.String()
+	}
+
+	if err != nil {
+		r.Err = err
+		return r
+	}
+
+	icmpAnswer, err := icmp.ParseMessage(1, s.readBuffer[:readBytes])
+
+	if err != nil {
+		r.Err = err
+		return r
+	}
+
+	latency := time.Since(timeNow)
+	r.Latency = latency
+
+	if icmpAnswer.Type == ipv4.ICMPTypeTimeExceeded {
+		s.nextHop++
+		return r
+	}
+
+	if icmpAnswer.Type == ipv4.ICMPTypeEchoReply {
+		s.isFinale = true
+		return r
+	}
+
+	r.Err = fmt.Errorf("unknown icmp answer: %d", icmpAnswer.Type.Protocol())
+
+	return r
+}
+
+func (s *Session) TraceRouteV4() (*Results, error) {
+
+	sock, err := net.ListenPacket("ip4:icmp", s.Source.ip.String())
+
+	if err != nil {
+		return nil, err
+	}
+
+	defer sock.Close()
+
+	s.ipV4Sock = ipv4.NewPacketConn(sock)
+	defer s.ipV4Sock.Close()
+
+	if err := s.ipV4Sock.SetControlMessage(ipv4.FlagTTL|ipv4.FlagDst|ipv4.FlagInterface|ipv4.FlagSrc, true); err != nil {
+		return nil, err
+	}
+
+	s.icmpEcho = icmp.Message{
+		Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ID: rand.Int(), Data: []byte("")},
+	}
+
+	s.readBuffer = make([]byte, 1500)
+
+	results := Results{}
+
+	for i := 1; i < s.MaxHops; i++ {
+		r:=s.doHop(i)
+		results.Hops = append(results.Hops, r)
+		if s.CallBack!=nil {
+			s.CallBack(r)
+		}
+
+		if s.isFinale {
+			break
+		}
+	}
+
+	return &results, nil
+}
+
+// currently not implemented
+//func (s *Session) traceRouteV6() error {
+//	return nil
+//}
+
+// TraceRoute measures the steps to the target host 
+func (s *Session) TraceRoute() (*Results, error) {
+
+	if s.Destination.isV4() {
+		results, err := s.TraceRouteV4()
+		if err != nil {
+			return nil, err
+		}
+		return results, nil
+	}
+
+	// currently not implemented
+	//if s.Destination.isV6() {
+	//	if err := s.traceRouteV6(); err != nil {
+	//		return nil, err
+	//	}
+	//}
+
+	return nil, errors.New("could not traceroute " + s.Destination.String())
+
+}
diff --git a/traceroute.iml b/traceroute.iml
new file mode 100644
index 0000000000000000000000000000000000000000..eacc75a3ca037d63f5c1eafd27c21c99c66161a5
--- /dev/null
+++ b/traceroute.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/traceroute_test.go b/traceroute_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..13931d419ac9253e3c91e0a99ce0f67526f79834
--- /dev/null
+++ b/traceroute_test.go
@@ -0,0 +1,46 @@
+package traceroute
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestTraceroute(t *testing.T) {
+
+	testCases := []struct {
+		destination        string
+		shouldSessionError bool
+	}{
+		{
+			"www.schukai.com",
+			false,
+		},
+	}
+
+	for _, tc := range testCases {
+
+		t.Run(fmt.Sprintf(""), func(t *testing.T) {
+
+			session, err := NewSession(tc.destination)
+			if err != nil {
+				t.Errorf("%s shout not error %s", tc.destination, err.Error())
+			}
+
+			_,err = session.TraceRoute()
+			if err != nil {
+				t.Errorf("%s shout not error %s", tc.destination, err.Error())
+			}
+
+		})
+
+	}
+
+}
+
+func benchmarkTraceroute(address string, b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		resolve(address)
+	}
+}
+
+func BenchmarkTraceroute1(b *testing.B) { benchmarkTraceroute("www.google.com", b) }