diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9fb46038da43608d5818ccd96f04bb9ca906ba99..e1575eb7b42e921fc854b2bb76857854ce9737fb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,7 @@ set(DAP_CHAIN_NET_SRCS
         dap_chain_node_cli_cmd_tx.c
         dap_chain_node_client.c
         dap_chain_node_remote.c
+        dap_chain_node_ping.c
         )
 
 set(DAP_CHAIN_NET_HEADERS
@@ -21,6 +22,7 @@ set(DAP_CHAIN_NET_HEADERS
         dap_chain_node_cli_cmd_tx.h
         dap_chain_node_client.h
         dap_chain_node_remote.h
+        dap_chain_node_ping.h
     )
 
 #if (ANDROID)
diff --git a/dap_chain_net.c b/dap_chain_net.c
index 062b948090013417f0d2e30917081044be684bc3..ad42a7190b4e3b4ae4523ca8a80b36b2d05f370a 100755
--- a/dap_chain_net.c
+++ b/dap_chain_net.c
@@ -1606,6 +1606,75 @@ dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net)
     return  PVT(l_net)->node_info? &PVT(l_net)->node_info->hdr.cell_id: 0;
 }
 
+/**
+ * Get remote node list
+ */
+dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net)
+{
+    dap_list_t *l_node_list = NULL;
+    /*
+     dap_chain_net_pvt_t *l_net_pvt = PVT(l_net);
+     // get nodes from seed_nodes
+     for(uint16_t i = 0; i < l_net_pvt->seed_aliases_count; i++) {
+     dap_chain_node_addr_t *l_node_address = dap_chain_node_alias_find(l_net, l_net_pvt->seed_aliases[i]);
+     l_node_list = dap_list_append(l_node_list, l_node_address);
+     }*/
+
+    // get nodes list from global_db
+    dap_global_db_obj_t *l_objs = NULL;
+    size_t l_nodes_count = 0;
+    // read all node
+    l_objs = dap_chain_global_db_gr_load(l_net->pub.gdb_nodes, &l_nodes_count);
+    if(!l_nodes_count || !l_objs)
+        return l_node_list;
+    for(size_t i = 0; i < l_nodes_count; i++) {
+        dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *) l_objs[i].value;
+        dap_chain_node_addr_t *l_address = DAP_NEW(dap_chain_node_addr_t);
+        l_address->uint64 = l_node_info->hdr.address.uint64;
+        l_node_list = dap_list_append(l_node_list, l_address);
+    }
+    dap_chain_global_db_objs_delete(l_objs, l_nodes_count);
+    return l_node_list;
+
+        // get remote node list
+        /*dap_chain_node_info_t *l_node_info = dap_chain_node_info_read(l_net, l_node_address);
+        if(!l_node_info)
+            continue;
+        // start connect
+        //debug inet_pton( AF_INET, "192.168.100.93", &l_node_info->hdr.ext_addr_v4);
+        dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect(l_node_info);
+        //dap_chain_node_client_t *l_node_client = dap_chain_client_connect(l_node_info, l_stage_target, l_active_channels);
+        if(!l_node_client) {
+            DAP_DELETE(l_node_info);
+            continue;
+        }
+        // wait connected
+        int timeout_ms = 5000; //5 sec = 5000 ms
+        int res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
+        if(res) {
+            // clean client struct
+            dap_chain_node_client_close(l_node_client);
+            DAP_DELETE(l_node_info);
+            continue;
+        }
+        res = dap_chain_node_client_send_nodelist_req(l_node_client);
+        if(res) {
+            // clean client struct
+            dap_chain_node_client_close(l_node_client);
+            DAP_DELETE(l_node_info);
+            continue;
+        }
+        res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_NODELIST_GOT, timeout_ms);
+        if(res) {
+            // clean client struct
+            dap_chain_node_client_close(l_node_client);
+            DAP_DELETE(l_node_info);
+            continue;
+        }
+        DAP_DELETE(l_node_info);
+        */
+}
+
 /**
  * @brief dap_chain_net_proc_datapool
  * @param a_net
diff --git a/dap_chain_net.h b/dap_chain_net.h
index a987aeea659b000ee402e5989712ef66472146a2..239a08cd1f7911ae2b6952728add0d612ce15fda 100644
--- a/dap_chain_net.h
+++ b/dap_chain_net.h
@@ -107,6 +107,8 @@ dap_chain_node_addr_t * dap_chain_net_get_cur_addr( dap_chain_net_t * l_net);
 uint64_t dap_chain_net_get_cur_addr_int(dap_chain_net_t * l_net);
 dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net);
 
+dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net);
+
 void dap_chain_net_links_connect(dap_chain_net_t * a_net);
 
 typedef enum dap_chain_net_tx_search_type {
diff --git a/dap_chain_node_cli.c b/dap_chain_node_cli.c
index de684df089f5f71285ea6fc12ced3ebf1e930b4e..1aaf97dbe823a9d93af5dd8e6b9d3078dd4808a0 100755
--- a/dap_chain_node_cli.c
+++ b/dap_chain_node_cli.c
@@ -34,16 +34,16 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <arpa/inet.h>
-#include <unistd.h> // for close
+//#include <unistd.h> // for close
 #include <fcntl.h>
 //#include <sys/poll.h>
 //#include <sys/select.h>
 #include <netinet/in.h>
 #include <sys/un.h>
-#define closesocket close
-typedef int SOCKET;
-#define SOCKET_ERROR    -1  // for win32 =  (-1)
-#define INVALID_SOCKET  -1  // for win32 =  (SOCKET)(~0)
+//#define closesocket close
+//typedef int SOCKET;
+//#define SOCKET_ERROR    -1  // for win32 =  (-1)
+//#define INVALID_SOCKET  -1  // for win32 =  (SOCKET)(~0)
 // for Windows
 #else
 #include <winsock2.h>
@@ -787,7 +787,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                     "node del  -net <net name> -addr <node address> | -alias <node alias>\n\n"
                     "node link {add|del}  -net <net name> {-addr <node address> | -alias <node alias>} -link <node address>\n\n"
                     "node alias -addr <node address> -alias <node alias>\n\n"
-                    "node connect {<node address> | -alias <node alias>}\n\n"
+                    "node connect {<node address> | -alias <node alias> | auto}\n\n"
                     "node handshake {<node address> | -alias <node alias>}\n"
                     "node dump -net <net name> [ -addr <node address> | -alias <node alias>] [-full]\n\n"
                                         );
diff --git a/dap_chain_node_cli.h b/dap_chain_node_cli.h
index b79e115a96f3fcf2c21412cbd1e830bcb52af84f..ea9393d8677a57f40f9c47584e76bcd6857603ee 100644
--- a/dap_chain_node_cli.h
+++ b/dap_chain_node_cli.h
@@ -29,6 +29,14 @@
 #include "dap_config.h"
 #include "uthash.h"
 
+#ifndef _WIN32
+#include <unistd.h> // for close
+#define closesocket close
+typedef int SOCKET;
+#define SOCKET_ERROR    -1  // for win32 =  (-1)
+#define INVALID_SOCKET  -1  // for win32 =  (SOCKET)(~0)
+#endif
+
 
 typedef int cmdfunc_t(int argc, char ** argv, char **str_reply);
 
@@ -40,6 +48,10 @@ typedef struct dap_chain_node_cmd_item{
     UT_hash_handle hh;
 } dap_chain_node_cmd_item_t;
 
+
+// Read from socket
+long s_recv(SOCKET sock, unsigned char *buf, size_t bufsize, int timeout);
+
 /**
  *  Look up NAME as the name of a command, and return a pointer to that
  *  command.  Return a NULL pointer if NAME isn't a command name.
diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c
index 59df5b3a73ee2d8fee860f93940bc4b5bd1bdff9..2e859dea541072365f7d00a36f768ea87c87272a 100644
--- a/dap_chain_node_cli_cmd.c
+++ b/dap_chain_node_cli_cmd.c
@@ -42,6 +42,8 @@
 #include <mswsock.h>
 #include <ws2tcpip.h>
 #include <io.h>
+#include <wepoll.h>
+#include <signal.h>
 #include <pthread.h>
 #else
 #include <sys/types.h>
@@ -68,6 +70,7 @@
 #include "dap_chain_node_remote.h"
 #include "dap_chain_node_cli_cmd.h"
 #include "dap_chain_node_cli_cmd_tx.h"
+#include "dap_chain_node_ping.h"
 #include "dap_chain_net_srv.h"
 #include "dap_chain_net_vpn_client.h"
 #include "dap_chain_cell.h"
@@ -749,150 +752,6 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
     return  -555;
 }
 
-/*
- int com_global_db_prev(int a_argc, char ** a_argv, char **a_str_reply)
- {
- enum {
- CMD_NONE, CMD_NAME_NODE, CMD_NAME_CELL, CMD_ADD, CMD_DEL, CMD_LINK    };
- //printf("com_global_db\n");
- int arg_index = 1;
- int cmd_name =  CMD_NONE;
- // find 'node' as first parameter only
- arg_index = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "node", NULL);
- if(arg_index)
- cmd_name =  CMD_NAME_NODE;
- // find 'cells' as first parameter only
- if(!arg_index) {
- arg_index = 1;
- arg_index = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "cells", NULL);
- if(arg_index)
- cmd_name =  CMD_NAME_CELL;
- }
- if(!arg_index || a_argc < 3) {
- dap_chain_node_cli_set_reply_text(a_str_reply, "parameters are not valid");
- return -1;
- }
- dap_chain_t * l_chain = NULL;
- dap_chain_net_t * l_net = NULL;
-
- if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, a_argc, a_argv, a_str_reply, &l_chain, &l_net) < 0)
- return -11;
-
- int arg_index_n = ++arg_index;
- // find command (add, delete, etc) as second parameter only
- int cmd_num = CMD_NONE;
- switch(cmd_name){
- case CMD_NAME_NODE:
- if((arg_index_n = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "add", NULL))
- != 0) {
- cmd_num = CMD_ADD;
- }
- else if((arg_index_n = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "del",
- NULL))
- != 0) {
- cmd_num = CMD_DEL;
- }
- else if((arg_index_n = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "link",
- NULL))
- != 0) {
- cmd_num = CMD_LINK;
- }
- break;
-
- case CMD_NAME_CELL:
- if((arg_index_n = dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "add", NULL))
- != 0) {
- cmd_num = CMD_ADD;
- }
- }
-
- if(cmd_num == CMD_NONE) {
- dap_chain_node_cli_set_reply_text(a_str_reply, "command %s not recognized", a_argv[1]);
- return -1;
- }
- //arg_index = arg_index_n; // no need, they are already equal must be
- assert(arg_index == arg_index_n);
- arg_index++;
- const char *l_addr_str = NULL, *alias_str = NULL, *l_cell_str = NULL, *l_chain_str = NULL, *l_link_str = NULL;
- const char *a_ipv4_str = NULL, *a_ipv6_str = NULL;
- // find addr, alias
-
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-addr", &l_addr_str);
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-alias", &alias_str);
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-cell", &l_cell_str);
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_str);
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-ipv4", &a_ipv4_str);
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-ipv6", &a_ipv6_str);
- dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-link", &l_link_str);
-
- // struct to write to the global db
- dap_chain_node_addr_t l_link = { 0 };
- dap_chain_node_info_t *l_node_info;
- size_t l_node_info_size = sizeof(l_node_info->hdr) + sizeof(l_link);
- l_node_info = DAP_NEW_Z_SIZE(dap_chain_node_info_t, l_node_info_size);
-
- if(l_addr_str) {
- dap_digit_from_string(l_addr_str, l_node_info->hdr.address.raw, sizeof(l_node_info->hdr.address.raw));
- }
- if(l_cell_str) {
- dap_digit_from_string(l_cell_str, l_node_info->hdr.cell_id.raw, sizeof(l_node_info->hdr.cell_id.raw)); //DAP_CHAIN_CELL_ID_SIZE);
- }
- if(l_link_str) {
- dap_digit_from_string(l_link_str, l_link.raw, sizeof(l_link.raw));
- }
-
- switch (cmd_num)
- {
- // add new node to global_db
- case CMD_ADD:
- if(cmd_name == CMD_NAME_NODE) {
- if(!arg_index || a_argc < 8) {
- dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameters");
- return -1;
- }
- // handler of command 'global_db node add'
- return node_info_add_with_reply(l_net, l_node_info, alias_str, l_cell_str, a_ipv4_str, a_ipv6_str,
- a_str_reply);
- }
- else if(cmd_name == CMD_NAME_CELL) {
- if(!arg_index || a_argc < 7) {
- dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameters");
- return -1;
- }
- dap_chain_cell_t *l_cell = dap_chain_cell_create();
- l_cell->chain = l_chain;
- l_cell->id.uint64 = l_node_info->hdr.cell_id.uint64;
- l_cell->file_storage_path = "234";
- dap_chain_cell_file_update(l_cell);
- DAP_DELETE(l_cell);
-
- }
- break;
-
- case CMD_DEL:
- // handler of command 'global_db node del'
- return node_info_del_with_reply(l_net,l_node_info, alias_str, a_str_reply);
- case CMD_LINK:
- if(dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "add", NULL))
- // handler of command 'global_db node link add -addr <node address> -link <node address>'
- return link_add_or_del_with_reply(l_net, l_node_info, "add", alias_str, &l_link, a_str_reply);
- else if(dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "del", NULL))
- // handler of command 'global_db node link del -addr <node address> -link <node address>'
- return link_add_or_del_with_reply(l_net, l_node_info, "del", alias_str, &l_link, a_str_reply);
- else {
- dap_chain_node_cli_set_reply_text(a_str_reply, "command not recognize, supported format:\n"
- "global_db node link <add|del] [-addr <node address>  | -alias <node alias>] -link <node address>");
- DAP_DELETE(l_node_info);
- return -1;
- }
-
- default:
- dap_chain_node_cli_set_reply_text(a_str_reply, "command %s not recognized", a_argv[1]);
- return -1;
- }
- }
- */
-
 /**
  * Node command
  */
@@ -1055,8 +914,87 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply)
             }
         }
         if(!l_node_addr.uint64) {
-            dap_chain_node_cli_set_reply_text(a_str_reply, "addr not found");
-            return -1;
+            // check whether auto mode
+            int l_is_auto = dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "auto", NULL);
+            if(!l_is_auto) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "addr not found");
+                return -1;
+            }
+            // if auto mode, then looking for the node address
+
+            // list of dap_chain_node_addr_t struct
+            dap_list_t *l_node_list = dap_chain_net_get_node_list(l_net);
+            // add cur node links to list
+            dap_chain_node_info_t *l_cur_node_info = NULL;
+            {
+                // get cur node address
+                dap_chain_node_addr_t l_cur_node_addr = { 0 };
+                l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net);
+                // get cur node info
+                l_cur_node_info = node_info_read_and_reply(l_net, &l_cur_node_addr, NULL);
+                // add links to nodes list only from the same cell
+                if(l_cur_node_info) {
+                    for(unsigned int i = 0; i < l_cur_node_info->hdr.links_number; i++) {
+                        //if(l_node_info && l_node_info->hdr.cell_id == l_cur_node_info->hdr.cell_id){
+                        l_node_list = dap_list_append(l_node_list, l_cur_node_info->links + i);
+                        //}
+                    }
+
+                }
+            }
+
+            // select the nearest node from the list
+            unsigned int l_nodes_count = dap_list_length(l_node_list);
+            unsigned int l_thread_id = 0;
+            pthread_t *l_threads = DAP_NEW_Z_SIZE(pthread_t, sizeof(pthread_t) * l_nodes_count);
+            uint64_t *l_nodes_addr = DAP_NEW_Z_SIZE(uint64_t, sizeof(uint64_t) * l_nodes_count);
+            dap_list_t *l_node_list0 = l_node_list;
+            // send ping to all nodes
+            while(l_node_list) {
+                dap_chain_node_addr_t *l_node_addr = l_node_list->data;
+                dap_chain_node_info_t *l_node_info = node_info_read_and_reply(l_net, l_node_addr, NULL);
+
+                // start sending ping
+                start_node_ping(&l_threads[l_thread_id], l_node_info->hdr.ext_addr_v4, l_node_info->hdr.ext_port, 1);
+
+                l_nodes_addr[l_thread_id] = l_node_info->hdr.address.uint64;
+                l_thread_id++;
+                DAP_DELETE(l_node_info);
+                l_node_list = dap_list_next(l_node_list);
+            }
+            // wait for reply from nodes
+            int best_node_pos = -1;
+            int best_node_reply = INT32_MAX;
+            // timeout for all threads
+            int l_timeout_full_ms = 3000;// wait max 3 second
+            for(l_thread_id = 0; l_thread_id < l_nodes_count; l_thread_id++) {
+                if(l_timeout_full_ms<100)
+                    l_timeout_full_ms = 100;// make small timeout anyway, may be
+                struct timespec l_time_start;
+                clock_gettime(CLOCK_MONOTONIC, &l_time_start);
+                int res = wait_node_ping(l_threads[l_thread_id], l_timeout_full_ms);
+                if(res > 0 && res < best_node_reply) {
+                    best_node_pos = l_thread_id;
+                    best_node_reply = res;
+                }
+                struct timespec l_time_stop;
+                clock_gettime(CLOCK_MONOTONIC, &l_time_stop);
+                l_timeout_full_ms -= timespec_diff(&l_time_start, &l_time_stop, NULL);
+                //printf(" thread %x ping=%d\n", l_threads[l_thread_id], res);
+            }
+            if(best_node_pos > 0) {
+                l_node_addr.uint64 = l_nodes_addr[best_node_pos];
+            }
+
+            DAP_DELETE(l_nodes_addr);
+            DAP_DELETE(l_threads);
+            dap_list_free_full(l_node_list0, free);
+            DAP_DELETE(l_cur_node_info);
+
+            if(!l_node_addr.uint64) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "no node is available");
+                return -1;
+            }
         }
 
         dap_chain_node_info_t *l_remote_node_info = node_info_read_and_reply(l_net, &l_node_addr, a_str_reply);
@@ -1476,7 +1414,9 @@ int com_ping(int argc, char** argv, char **str_reply)
         n = 1;
     const char *addr = argv[argc_host];
     iputils_set_verbose();
-    int res = (addr) ? ping_util(addr, n) : -EADDRNOTAVAIL;
+    ping_handle_t *l_ping_handle = ping_handle_create();
+    int res = (addr) ? ping_util(l_ping_handle, addr, n) : -EADDRNOTAVAIL;
+    DAP_DELETE(l_ping_handle);
     if(res >= 0) {
         if(str_reply)
             dap_chain_node_cli_set_reply_text(str_reply, "ping %s time=%.1lf ms", addr, res * 1. / 1000);
diff --git a/dap_chain_node_client.c b/dap_chain_node_client.c
index 53b815308df211f71ead06d539eaa028b157001f..bce0989d71e738eb7d3953a1b5d1953ee0a3a0e3 100644
--- a/dap_chain_node_client.c
+++ b/dap_chain_node_client.c
@@ -644,3 +644,26 @@ int dap_chain_node_client_set_callbacks(dap_client_t *a_client, uint8_t a_ch_id)
     }
     return l_ret;
 }
+
+/*static void nodelist_response_callback(dap_client_t *a_client, void *data, size_t data_len)
+{
+}
+
+static void nodelist_response_error_callback(dap_client_t *a_client, int a_err)
+{
+}*/
+
+/**
+ * Send nodelist request to server
+ */
+int dap_chain_node_client_send_nodelist_req(dap_chain_node_client_t *a_client)
+{
+    if(!a_client || !a_client->client || a_client->state < NODE_CLIENT_STATE_CONNECTED)
+        return -1;
+    //dap_client_pvt_t * l_client_pvt = DAP_CLIENT_PVT(a_client->client);
+
+    //TODO send request to get nodelist
+    //dap_client_request_enc(a_client->client, DAP_UPLINK_PATH_NODE_LIST, "", "", "", 0,
+    //        nodelist_response_callback, nodelist_response_error_callback);
+    return 1;
+}
diff --git a/dap_chain_node_client.h b/dap_chain_node_client.h
index ad959a3e88f5d1d4d8ee1818c28d8d788dba15aa..21678c23bf4ffb5d4b7a08f1dd004e5adda35dfc 100644
--- a/dap_chain_node_client.h
+++ b/dap_chain_node_client.h
@@ -43,7 +43,7 @@ typedef enum dap_chain_node_client_state {
     //NODE_CLIENT_STATE_SENDED,
     NODE_CLIENT_STATE_SYNC_GDB = 101,
     NODE_CLIENT_STATE_SYNC_CHAINS = 102,
-    NODE_CLIENT_STATE_SYNCED = 103
+    NODE_CLIENT_STATE_SYNCED = 103,
 } dap_chain_node_client_state_t;
 
 typedef struct dap_chain_node_client dap_chain_node_client_t;
@@ -112,3 +112,6 @@ int dap_chain_node_client_wait(dap_chain_node_client_t *a_client, int a_waited_s
 
 int dap_chain_node_client_set_callbacks(dap_client_t *a_client, uint8_t a_ch_id);
 
+int dap_chain_node_client_send_nodelist_req(dap_chain_node_client_t *a_client);
+
+
diff --git a/dap_chain_node_ping.c b/dap_chain_node_ping.c
new file mode 100644
index 0000000000000000000000000000000000000000..cd7d84492b218edd144b85c73bfcee133d08bd54
--- /dev/null
+++ b/dap_chain_node_ping.c
@@ -0,0 +1,171 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+//#include <sys/socket.h>
+#include <time.h>
+#include <errno.h>
+
+#include "dap_common.h"
+#include "dap_client.h"
+#include "dap_strfuncs.h"
+#include "dap_chain_node_ping.h"
+
+/*
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <stddef.h>
+ #include <stdint.h>
+ #include <string.h>
+ #include <stdbool.h>
+ #include <assert.h>
+ #include <ctype.h>
+ #include <dirent.h>
+ */
+
+#ifdef WIN32
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#include <winsock2.h>
+#include <windows.h>
+#include <mswsock.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <wepoll.h>
+#else
+#include <signal.h>
+#endif
+
+#include <pthread.h>
+
+#include "dap_common.h"
+//#include "dap_client.h"
+#include "dap_strfuncs.h"
+#include "dap_chain_node_cli.h"
+#include "dap_chain_node_ping.h"
+
+#define LOG_TAG "chain_node_ping"
+
+static void* node_ping_proc(void *a_arg)
+{
+    struct in_addr l_addr = { 0 };
+    int l_port = 0;
+    int l_count;
+    if(!a_arg)
+        return NULL;
+    memcpy(&l_count, a_arg, sizeof(int));
+    memcpy(&l_port, (a_arg + sizeof(int)), sizeof(int));
+    memcpy(&l_addr, (a_arg + 2 * sizeof(int)), sizeof(struct in_addr));
+    DAP_DELETE(a_arg);
+
+    char *host4 = DAP_NEW_SIZE(char, INET_ADDRSTRLEN);
+    struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = l_addr };
+    const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, INET_ADDRSTRLEN);
+    if(!str_ip4)
+        return NULL;
+    //printf(" %s %d ping start\n", str_ip4, l_count);
+    /*
+     // send ping
+     ping_handle_t *l_ping_handle = ping_handle_create();
+     //iputils_set_verbose();
+     int res = ping_util(l_ping_handle, str_ip4, l_count);
+     DAP_DELETE(l_ping_handle);
+     printf(" %s %d ping=%d us\n",str_ip4,l_count,res );
+     DAP_DELETE(host4);
+     */
+
+    // instead of ping to connect with server and send/recv header
+    long res = -1;
+    {
+        struct timespec l_time_start, l_time_stop;
+        struct sockaddr_in l_remote_addr = { 0 };
+        //memset(&l_remote_addr, 0, sizeof(l_remote_addr));
+        l_remote_addr.sin_family = AF_INET;
+        l_remote_addr.sin_port = htons(l_port);
+        l_remote_addr.sin_addr = l_addr;
+
+        SOCKET l_socket = socket( PF_INET, SOCK_STREAM, 0);
+        if(l_socket == INVALID_SOCKET) {
+            log_it(L_ERROR, "Can't create socket");
+            return (void*) -1;
+        }
+        clock_gettime(CLOCK_MONOTONIC, &l_time_start);
+
+        if(connect(l_socket, (struct sockaddr *) &l_remote_addr, sizeof(struct sockaddr_in)) != SOCKET_ERROR) {
+            size_t l_buf_size = 1024;
+            uint8_t l_buf[l_buf_size];
+
+            const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4,
+                    INET_ADDRSTRLEN);
+            char *l_str_to_send = dap_strdup_printf("GET /%s/ping_sub_url HTTP/1.1\r\nHost: %s\r\n\r\n",
+            DAP_UPLINK_PATH_ENC_INIT, str_ip4);
+            // send data to bad suburl
+            int l_send_count = send(l_socket, l_str_to_send, dap_strlen(l_str_to_send), 0);
+            long l_recv_count = 0;
+            // recv data with error message
+            if(l_send_count > 30)
+                l_recv_count = s_recv(l_socket, l_buf, l_buf_size, 1000);
+            // connect/send/recv was successful
+            if(l_recv_count > 20) {
+                clock_gettime(CLOCK_MONOTONIC, &l_time_stop);
+                res = timespec_diff(&l_time_start, &l_time_stop, NULL);
+            }
+            DAP_DELETE(l_str_to_send);
+        }
+        else{
+            ;//log_it(L_INFO, "Can't connect to node for ping");
+        }
+        closesocket(l_socket);
+    }
+    return (void*) res;
+}
+
+// start sending ping
+int start_node_ping(pthread_t *a_thread, struct in_addr a_addr, int a_port, int a_count)
+{
+    uint8_t *l_data = DAP_NEW_Z_SIZE(uint8_t, sizeof(struct in_addr) + 2 * sizeof(int));
+    memcpy(l_data, &a_count, sizeof(int));
+    memcpy(l_data + sizeof(int), &a_port, sizeof(int));
+    memcpy(l_data + 2 * sizeof(int), &a_addr, sizeof(struct in_addr));
+    pthread_create(a_thread, NULL, node_ping_proc, l_data);
+    return 0;
+}
+
+// wait for ending ping within timeout_ms milliseconds
+int wait_node_ping(pthread_t l_thread, int timeout_ms)
+{
+    int l_ping_time = 0;
+    struct timespec l_wait_time;
+    clock_gettime(CLOCK_REALTIME, &l_wait_time);
+
+    timeout_ms *= 1000;
+    l_wait_time.tv_sec += timeout_ms / DAP_USEC_PER_SEC;
+    l_wait_time.tv_nsec += 1000 * (timeout_ms % DAP_USEC_PER_SEC);
+
+    int res = pthread_timedjoin_np(l_thread, (void **) &l_ping_time, &l_wait_time);
+    if(res == ETIMEDOUT) {
+        pthread_kill(l_thread, 3); // SIGQUIT SIGABRT
+    }
+    else if(!res)
+        return l_ping_time;
+    return -1;
+}
diff --git a/dap_chain_node_ping.h b/dap_chain_node_ping.h
new file mode 100644
index 0000000000000000000000000000000000000000..8289031c8fab5b8ebfef3aa799ec38f48dc8b659
--- /dev/null
+++ b/dap_chain_node_ping.h
@@ -0,0 +1,30 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <netinet/in.h>
+#include <pthread.h>
+
+// start sending ping
+int start_node_ping(pthread_t *a_thread, struct in_addr a_addr, int a_port, int a_count);
+
+// wait for ending ping within timeout_ms milliseconds
+int wait_node_ping(pthread_t l_thread, int timeout_ms);
diff --git a/iputils/iputils.h b/iputils/iputils.h
index d7613e1092d3febc9fc8b48a39c1af0033943cdf..4ec59b51a4d869ec05460bb48dbe54b43fd7c604 100644
--- a/iputils/iputils.h
+++ b/iputils/iputils.h
@@ -7,11 +7,111 @@
 
 #include <stdint.h>
 #include <stdlib.h>
+#include <netinet/ip.h>
+#include <setjmp.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#define MAXPACKET 128000    /* max packet size */
+
+#define MAX_DUP_CHK 0x10000
+
+#ifdef USE_BITMAP64
+typedef uint64_t  bitmap_t;
+# define BITMAP_SHIFT 6
+#else
+typedef uint32_t  bitmap_t;
+# define BITMAP_SHIFT 5
+#endif
+
+struct rcvd_table {
+  bitmap_t bitmap[MAX_DUP_CHK / (sizeof(bitmap_t) * 8)];
+};
+
+typedef struct ping_handle{
+    int ts_type;
+    int nroute;
+    uint32_t route[10];
+
+    struct sockaddr_in whereto; /* who to ping */
+    int optlen;
+    int settos; /* Set TOS, Precendence or other QOS options */
+
+    int broadcast_pings;
+
+    struct sockaddr_in source;
+    char *device;
+    int pmtudisc;
+    struct {
+
+        int options;
+
+        int mark;
+        int sndbuf;
+        int ttl;
+        int rtt;
+        int rtt_addend;
+        uint16_t acked;
+
+        unsigned char outpack[MAXPACKET];
+        struct rcvd_table rcvd_tbl;
+
+        // counters
+        long npackets; // max packets to transmit
+        long nreceived; // # of packets we got back
+        long nrepeats; // number of duplicates
+        long ntransmitted; // sequence # for outbound packets = #sent
+        long nchecksum; // replies with bad checksum
+        long nerrors; // icmp errors
+        int interval; // interval between packets (msec)
+        int preload;
+        int deadline; // time to die
+        int lingertime;
+        struct timeval start_time, cur_time;
+        //volatile int exiting;
+        //volatile int status_snapshot;
+        int confirm;
+        volatile int in_pr_addr; // pr_addr() is executing
+        jmp_buf pr_addr_jmp;
+
+        /* Stupid workarounds for bugs/missing functionality in older linuces.
+         * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
+         * i.e. for linux-2.2 */
+        int confirm_flag;
+
+        // timing
+        int timing; // flag to do timing
+        long tmin; // minimum round trip time
+        long tmax; // maximum round trip time
+        /* Message for rpm maintainers: have _shame_. If you want
+         * to fix something send the patch to me for sanity checking.
+         * "sparcfix" patch is a complete non-sense, apparenly the person
+         * prepared it was stoned.
+         */
+        long long tsum; // sum of all times, for doing average
+        long long tsum2;
+        int pipesize;
+
+        int datalen;
+
+        char *hostname;
+        int uid;
+        uid_t euid;
+        int ident; // process id to identify our packets
+
+        int screen_width;
+
+        #ifdef HAVE_LIBCAP
+        cap_value_t cap_raw;
+        cap_value_t cap_admin;
+        #endif
+    } ping_common;
+}ping_handle_t;
+
+ping_handle_t* ping_handle_create(void);
+
 /**
  * Send ping for ipv4
  *
@@ -19,7 +119,7 @@ extern "C" {
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util(const char *addr, int count);
+int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count);
 
 /**
  * Send ping for ipv6
@@ -28,7 +128,7 @@ int ping_util(const char *addr, int count);
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util6(const char *addr, int count);
+int ping_util6(ping_handle_t *a_ping_handle, const char *addr, int count);
 
 
 /**
diff --git a/iputils/ping.c b/iputils/ping.c
index f9f65beada8ac7afb58535a9357037d5e0648521..e634a606e8bde2c67697719a6d1295cbc4960a1d 100644
--- a/iputils/ping.c
+++ b/iputils/ping.c
@@ -52,12 +52,12 @@
 #include "ping.h"
 
 #include <assert.h>
-#include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
 #include <ifaddrs.h>
 #include <math.h>
 #include "dap_common.h"
 #include "dap_strfuncs.h"
+#include "iputils.h"
 
 #ifndef ICMP_FILTER
 #define ICMP_FILTER	1
@@ -78,28 +78,58 @@ ping_func_set_st ping4_func_set = {
 #define	NROUTES		9		/* number of record route slots */
 #define TOS_MAX		255		/* 8-bit TOS field */
 
+/*
 static int ts_type;
 static int nroute = 0;
 static uint32_t route[10];
 
-static struct sockaddr_in whereto; /* who to ping */
+static struct sockaddr_in whereto; // who to ping
 static int optlen = 0;
-static int settos = 0; /* Set TOS, Precendence or other QOS options */
+static int settos = 0; // Set TOS, Precendence or other QOS options
 
 static int broadcast_pings = 0;
 
-static void pr_options(unsigned char * cp, int hlen);
-static void pr_iph(struct iphdr *ip);
+static struct sockaddr_in source = { .sin_family = AF_INET };
+char *device;
+int pmtudisc = -1;
+*/
+
+static void pr_options(ping_handle_t *a_ping_handle, unsigned char * cp, int hlen);
+static void pr_iph(ping_handle_t *a_ping_handle, struct iphdr *ip);
 static unsigned short in_cksum(const unsigned short *addr, int len, unsigned short salt);
-static void pr_icmph(uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp);
+static void pr_icmph(ping_handle_t *a_ping_handle, uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp);
 static int parsetos(char *str);
 static int parseflow(char *str);
 
-static struct sockaddr_in source = { .sin_family = AF_INET };
-char *device;
-int pmtudisc = -1;
+ping_handle_t* ping_handle_create(void)
+{
+    ping_handle_t *lping = DAP_NEW_Z(ping_handle_t);
+    lping->source.sin_family = AF_INET;
+    lping->pmtudisc = -1;
+
+    lping->ping_common.interval = 1000; // interval between packets (msec)
+    lping->ping_common.preload = 1;
+    lping->ping_common.lingertime = MAXWAIT * 1000;
 
-static void create_socket(socket_st *sock, int family, int socktype, int protocol, int requisite)
+
+    lping->ping_common.confirm_flag = MSG_CONFIRM;
+
+    lping->ping_common.tmin = LONG_MAX; // minimum round trip time
+    lping->ping_common.pipesize = -1;
+
+    lping->ping_common.datalen = DEFDATALEN;
+
+    lping->ping_common.screen_width = INT_MAX;
+
+#ifdef HAVE_LIBCAP
+    lping->ping_common.cap_raw = CAP_NET_RAW;
+    lping->ping_common.cap_admin = CAP_NET_ADMIN;
+#endif
+
+    return lping;
+}
+
+static void create_socket(ping_handle_t *a_ping_handle, socket_st *sock, int family, int socktype, int protocol, int requisite)
 {
     int do_fallback = 0;
 
@@ -168,7 +198,7 @@ static void create_socket(socket_st *sock, int family, int socktype, int protoco
         /* Report error related to disabled IPv6 only when IPv6 also failed or in
          * verbose mode. Report other errors always.
          */
-        if((errno == EAFNOSUPPORT && socktype == AF_INET6) || (options & F_VERBOSE) || requisite)
+        if((errno == EAFNOSUPPORT && socktype == AF_INET6) || (a_ping_handle->ping_common.options & F_VERBOSE) || requisite)
             error(0, errno, "socket");
         if(requisite)
             exit(2);
@@ -218,7 +248,7 @@ static double ping_strtod(const char *str, const char *err_msg)
     return 0.0;
 }
 
-static int ping_main(int argc, char **argv)
+static int ping_main(ping_handle_t *a_ping_handle, int argc, char **argv)
 {
     struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_protocol = IPPROTO_UDP, .ai_socktype = SOCK_DGRAM, .ai_flags =
     getaddrinfo_flags };
@@ -229,7 +259,7 @@ static int ping_main(int argc, char **argv)
     socket_st sock6 = { .fd = -1 };
     char *target;
 
-    limit_capabilities();
+    limit_capabilities(a_ping_handle);
 
 #ifdef USE_IDN
     setlocale(LC_ALL, "");
@@ -253,23 +283,23 @@ static int ping_main(int argc, char **argv)
             hints.ai_family = AF_INET;
             break;
         case 'b':
-            broadcast_pings = 1;
+            a_ping_handle->broadcast_pings = 1;
             break;
         case 'R':
-            if(options & F_TIMESTAMP)
+            if(a_ping_handle->ping_common.options & F_TIMESTAMP)
                 error(2, 0, "only one of -T or -R may be used");
-            options |= F_RROUTE;
+            a_ping_handle->ping_common.options |= F_RROUTE;
             break;
         case 'T':
-            if(options & F_RROUTE)
+            if(a_ping_handle->ping_common.options & F_RROUTE)
                 error(2, 0, "only one of -T or -R may be used");
-            options |= F_TIMESTAMP;
+            a_ping_handle->ping_common.options |= F_TIMESTAMP;
             if(strcmp(optarg, "tsonly") == 0)
-                ts_type = IPOPT_TS_TSONLY;
+                a_ping_handle->ts_type = IPOPT_TS_TSONLY;
             else if(strcmp(optarg, "tsandaddr") == 0)
-                ts_type = IPOPT_TS_TSANDADDR;
+                a_ping_handle->ts_type = IPOPT_TS_TSANDADDR;
             else if(strcmp(optarg, "tsprespec") == 0)
-                ts_type = IPOPT_TS_PRESPEC;
+                a_ping_handle->ts_type = IPOPT_TS_PRESPEC;
             else
                 error(2, 0, "invalid timestamp type: %s", optarg);
             break;
@@ -281,7 +311,7 @@ static int ping_main(int argc, char **argv)
             break;
         case 'F':
             flowlabel = parseflow(optarg);
-            options |= F_FLOWINFO;
+            a_ping_handle->ping_common.options |= F_FLOWINFO;
             break;
         case 'N':
             if(niquery_option_handler(optarg) < 0)
@@ -290,24 +320,24 @@ static int ping_main(int argc, char **argv)
             break;
             /* Common options */
         case 'a':
-            options |= F_AUDIBLE;
+            a_ping_handle->ping_common.options |= F_AUDIBLE;
             break;
         case 'A':
-            options |= F_ADAPTIVE;
+            a_ping_handle->ping_common.options |= F_ADAPTIVE;
             break;
         case 'B':
-            options |= F_STRICTSOURCE;
+            a_ping_handle->ping_common.options |= F_STRICTSOURCE;
             break;
         case 'c':
-            npackets = atoi(optarg);
-            if(npackets <= 0)
-                error(2, 0, "bad number of packets to transmit: %ld", npackets);
+            a_ping_handle->ping_common.npackets = atoi(optarg);
+            if(a_ping_handle->ping_common.npackets <= 0)
+                error(2, 0, "bad number of packets to transmit: %ld", a_ping_handle->ping_common.npackets);
             break;
         case 'd':
-            options |= F_SO_DEBUG;
+            a_ping_handle->ping_common.options |= F_SO_DEBUG;
             break;
         case 'D':
-            options |= F_PTIMEOFDAY;
+            a_ping_handle->ping_common.options |= F_PTIMEOFDAY;
             break;
         case 'i':
             {
@@ -316,8 +346,8 @@ static int ping_main(int argc, char **argv)
             optval = ping_strtod(optarg, "bad timing interval");
             if(isgreater(optval, (double)(INT_MAX / 1000)))
                 error(2, 0, "bad timing interval: %s", optarg);
-            interval = (int) (optval * 1000);
-            options |= F_INTERVAL;
+            a_ping_handle->ping_common.interval = (int) (optval * 1000);
+            a_ping_handle->ping_common.options |= F_INTERVAL;
         }
             break;
         case 'I':
@@ -331,107 +361,107 @@ static int ping_main(int argc, char **argv)
                 p = strchr(addr, SCOPE_DELIMITER);
                 if(p) {
                     *p = '\0';
-                    device = optarg + (p - addr) + 1;
+                    a_ping_handle->device = optarg + (p - addr) + 1;
                 }
 
                 if(inet_pton(AF_INET6, addr, (char*) &source6.sin6_addr) <= 0)
                     error(2, 0, "invalid source address: %s", optarg);
 
-                options |= F_STRICTSOURCE;
+                a_ping_handle->ping_common.options |= F_STRICTSOURCE;
 
                 free(addr);
-            } else if(inet_pton(AF_INET, optarg, &source.sin_addr) > 0) {
-                options |= F_STRICTSOURCE;
+            } else if(inet_pton(AF_INET, optarg, &a_ping_handle->source.sin_addr) > 0) {
+                a_ping_handle->ping_common.options |= F_STRICTSOURCE;
             } else {
-                device = optarg;
+                a_ping_handle->device = optarg;
             }
             break;
         case 'l':
-            preload = atoi(optarg);
-            if(preload <= 0)
+            a_ping_handle->ping_common.preload = atoi(optarg);
+            if(a_ping_handle->ping_common.preload <= 0)
                 error(2, 0, "bad preload value: %s, should be 1..%d", optarg, MAX_DUP_CHK);
-            if(preload > MAX_DUP_CHK)
-                preload = MAX_DUP_CHK;
-            if(uid && preload > 3)
-                error(2, 0, "cannot set preload to value greater than 3: %d", preload);
+            if(a_ping_handle->ping_common.preload > MAX_DUP_CHK)
+                a_ping_handle->ping_common.preload = MAX_DUP_CHK;
+            if(a_ping_handle->ping_common.uid && a_ping_handle->ping_common.preload > 3)
+                error(2, 0, "cannot set preload to value greater than 3: %d", a_ping_handle->ping_common.preload);
             break;
         case 'L':
-            options |= F_NOLOOP;
+            a_ping_handle->ping_common.options |= F_NOLOOP;
             break;
         case 'm':
             {
             char *endp;
-            mark = (int) strtoul(optarg, &endp, 10);
-            if(mark < 0 || *endp != '\0')
+            a_ping_handle->ping_common.mark = (int) strtoul(optarg, &endp, 10);
+            if(a_ping_handle->ping_common.mark < 0 || *endp != '\0')
                 error(2, 0, "mark cannot be negative: %s", optarg);
-            options |= F_MARK;
+            a_ping_handle->ping_common.options |= F_MARK;
             break;
         }
         case 'M':
             if(strcmp(optarg, "do") == 0)
-                pmtudisc = IP_PMTUDISC_DO;
+                a_ping_handle->pmtudisc = IP_PMTUDISC_DO;
             else if(strcmp(optarg, "dont") == 0)
-                pmtudisc = IP_PMTUDISC_DONT;
+                a_ping_handle->pmtudisc = IP_PMTUDISC_DONT;
             else if(strcmp(optarg, "want") == 0)
-                pmtudisc = IP_PMTUDISC_WANT;
+                a_ping_handle->pmtudisc = IP_PMTUDISC_WANT;
             else
                 error(2, 0, "invalid -M argument: %s", optarg);
             break;
         case 'n':
-            options |= F_NUMERIC;
+            a_ping_handle->ping_common.options |= F_NUMERIC;
             break;
         case 'O':
-            options |= F_OUTSTANDING;
+            a_ping_handle->ping_common.options |= F_OUTSTANDING;
             break;
         case 'f':
             /* avoid `getaddrinfo()` during flood */
-            options |= F_FLOOD | F_NUMERIC;
+            a_ping_handle->ping_common.options |= F_FLOOD | F_NUMERIC;
             setbuf(stdout, (char *) NULL);
             break;
         case 'p':
-            options |= F_PINGFILLED;
-            fill(optarg, outpack, sizeof(outpack));
+            a_ping_handle->ping_common.options |= F_PINGFILLED;
+            fill(a_ping_handle, optarg, a_ping_handle->ping_common.outpack, sizeof(a_ping_handle->ping_common.outpack));
             break;
         case 'q':
-            options |= F_QUIET;
+            a_ping_handle->ping_common.options |= F_QUIET;
             break;
         case 'Q':
-            settos = parsetos(optarg); /* IPv4 */
-            tclass = settos; /* IPv6 */
+            a_ping_handle->settos = parsetos(optarg); /* IPv4 */
+            tclass = a_ping_handle->settos; /* IPv6 */
             break;
         case 'r':
-            options |= F_SO_DONTROUTE;
+            a_ping_handle->ping_common.options |= F_SO_DONTROUTE;
             break;
         case 's':
-            datalen = atoi(optarg);
-            if(datalen < 0)
-                error(2, 0, "illegal packet size: %d", datalen);
-            if(datalen > MAXPACKET - 8)
-                error(2, 0, "packet size too large: %d", datalen);
+            a_ping_handle->ping_common.datalen = atoi(optarg);
+            if(a_ping_handle->ping_common.datalen < 0)
+                error(2, 0, "illegal packet size: %d", a_ping_handle->ping_common.datalen);
+            if(a_ping_handle->ping_common.datalen > MAXPACKET - 8)
+                error(2, 0, "packet size too large: %d", a_ping_handle->ping_common.datalen);
             break;
         case 'S':
-            sndbuf = atoi(optarg);
-            if(sndbuf <= 0)
+            a_ping_handle->ping_common.sndbuf = atoi(optarg);
+            if(a_ping_handle->ping_common.sndbuf <= 0)
                 error(2, 0, "bad sndbuf value: %s", optarg);
             break;
         case 't':
-            options |= F_TTL;
-            ttl = atoi(optarg);
-            if(ttl < 0 || ttl > 255)
+            a_ping_handle->ping_common.options |= F_TTL;
+            a_ping_handle->ping_common.ttl = atoi(optarg);
+            if(a_ping_handle->ping_common.ttl < 0 || a_ping_handle->ping_common.ttl > 255)
                 error(2, 0, "ttl out of range: %s", optarg);
             break;
         case 'U':
-            options |= F_LATENCY;
+            a_ping_handle->ping_common.options |= F_LATENCY;
             break;
         case 'v':
-            options |= F_VERBOSE;
+            a_ping_handle->ping_common.options |= F_VERBOSE;
             break;
         case 'V':
             printf(IPUTILS_VERSION("ping"));
             exit(0);
         case 'w':
-            deadline = atoi(optarg);
-            if(deadline < 0)
+            a_ping_handle->ping_common.deadline = atoi(optarg);
+            if(a_ping_handle->ping_common.deadline < 0)
                 error(2, 0, "bad wait time: %s", optarg);
             break;
         case 'W':
@@ -442,7 +472,7 @@ static int ping_main(int argc, char **argv)
             if(isless(optval, 0.001) || isgreater(optval, (double)(INT_MAX / 1000)))
                 error(2, 0, "bad linger time: %s", optarg);
             /* lingertime will be converted to usec later */
-            lingertime = (int) (optval * 1000);
+            a_ping_handle->ping_common.lingertime = (int) (optval * 1000);
         }
             break;
         default:
@@ -464,18 +494,18 @@ static int ping_main(int argc, char **argv)
     target = argv[argc - 1];
 
     /* Create sockets */
-    enable_capability_raw();
+    enable_capability_raw(a_ping_handle);
     if(hints.ai_family != AF_INET6)
-        create_socket(&sock4, AF_INET, hints.ai_socktype, IPPROTO_ICMP, hints.ai_family == AF_INET);
+        create_socket(a_ping_handle, &sock4, AF_INET, hints.ai_socktype, IPPROTO_ICMP, hints.ai_family == AF_INET);
     if(hints.ai_family != AF_INET) {
-        create_socket(&sock6, AF_INET6, hints.ai_socktype, IPPROTO_ICMPV6, sock4.fd == -1);
+        create_socket(a_ping_handle, &sock6, AF_INET6, hints.ai_socktype, IPPROTO_ICMPV6, sock4.fd == -1);
         /* This may not be needed if both protocol versions always had the same value, but
          * since I don't know that, it's better to be safe than sorry. */
-        pmtudisc = pmtudisc == IP_PMTUDISC_DO ? IPV6_PMTUDISC_DO :
-                   pmtudisc == IP_PMTUDISC_DONT ? IPV6_PMTUDISC_DONT :
-                   pmtudisc == IP_PMTUDISC_WANT ? IPV6_PMTUDISC_WANT : pmtudisc;
+        a_ping_handle->pmtudisc = a_ping_handle->pmtudisc == IP_PMTUDISC_DO ? IPV6_PMTUDISC_DO :
+                                  a_ping_handle->pmtudisc == IP_PMTUDISC_DONT ? IPV6_PMTUDISC_DONT :
+                                  a_ping_handle->pmtudisc == IP_PMTUDISC_WANT ? IPV6_PMTUDISC_WANT : a_ping_handle->pmtudisc;
     }
-    disable_capability_raw();
+    disable_capability_raw(a_ping_handle);
 
     /* Limit address family on single-protocol systems */
     if(hints.ai_family == AF_UNSPEC) {
@@ -486,8 +516,8 @@ static int ping_main(int argc, char **argv)
     }
 
     /* Set socket options */
-    if(settos)
-        set_socket_option(&sock4, IPPROTO_IP, IP_TOS, &settos, sizeof settos);
+    if(a_ping_handle->settos)
+        set_socket_option(&sock4, IPPROTO_IP, IP_TOS, &a_ping_handle->settos, sizeof (a_ping_handle->settos));
     if(tclass)
         set_socket_option(&sock6, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof tclass);
 
@@ -501,10 +531,10 @@ static int ping_main(int argc, char **argv)
     for(ai = result; ai; ai = ai->ai_next) {
         switch (ai->ai_family) {
         case AF_INET:
-            status = ping4_run(argc, argv, ai, &sock4);
+            status = ping4_run(a_ping_handle, argc, argv, ai, &sock4);
             break;
         case AF_INET6:
-            status = ping6_run(argc, argv, ai, &sock6);
+            status = ping6_run(a_ping_handle, argc, argv, ai, &sock6);
             break;
         default:
         {
@@ -530,7 +560,7 @@ static int ping_main(int argc, char **argv)
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util_common(int type, const char *addr, int count)
+int ping_util_common(ping_handle_t *a_ping_handle, int type, const char *addr, int count)
 {
 
     /*
@@ -541,7 +571,7 @@ int ping_util_common(int type, const char *addr, int count)
      Need change range for other users:
      # sysctl net.ipv4.ping_group_range="1 65000"
      */
-    tsum = ntransmitted = nreceived = exiting = 0;
+    a_ping_handle->ping_common.tsum = a_ping_handle->ping_common.ntransmitted = a_ping_handle->ping_common.nreceived = exiting = 0;
     int argc = 3;
     const char *argv[argc];
     if(type != 4)
@@ -550,10 +580,10 @@ int ping_util_common(int type, const char *addr, int count)
         argv[0] = "ping4";
     argv[1] = dap_strdup_printf("-c%d", count);
     argv[2] = addr;
-    int status = ping_main(argc, (char**) argv);
+    int status = ping_main(a_ping_handle, argc, (char**) argv);
     DAP_DELETE((char*) argv[1]);
-    if(ntransmitted >= 1 && nreceived >= 1)
-        return tsum;
+    if(a_ping_handle->ping_common.ntransmitted >= 1 && a_ping_handle->ping_common.nreceived >= 1)
+        return a_ping_handle->ping_common.tsum;
     return status;
 }
 
@@ -564,9 +594,9 @@ int ping_util_common(int type, const char *addr, int count)
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util(const char *addr, int count)
+int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count)
 {
-    return ping_util_common(4, addr, count);
+    return ping_util_common(a_ping_handle, 4, addr, count);
 }
 
 /**
@@ -576,12 +606,12 @@ int ping_util(const char *addr, int count)
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util6(const char *addr, int count)
+int ping_util6(ping_handle_t *a_ping_handle, const char *addr, int count)
 {
-    return ping_util_common(6, addr, count);
+    return ping_util_common(a_ping_handle, 6, addr, count);
 }
 
-int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock)
+int ping4_run(ping_handle_t *a_ping_handle, int argc, char **argv, struct addrinfo *ai, socket_st *sock)
 {
     static const struct addrinfo hints = { .ai_family = AF_INET, .ai_protocol = IPPROTO_UDP, .ai_flags =
     getaddrinfo_flags };
@@ -593,28 +623,28 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock)
     uint32_t *tmp_rspace;
 
     if(argc > 1) {
-        if(options & F_RROUTE)
+        if(a_ping_handle->ping_common.options & F_RROUTE)
             usage();
-        else if(options & F_TIMESTAMP) {
-            if(ts_type != IPOPT_TS_PRESPEC)
+        else if(a_ping_handle->ping_common.options & F_TIMESTAMP) {
+            if(a_ping_handle->ts_type != IPOPT_TS_PRESPEC)
                 usage();
             if(argc > 5)
                 usage();
         } else {
             if(argc > 10)
                 usage();
-            options |= F_SOURCEROUTE;
+            a_ping_handle->ping_common.options |= F_SOURCEROUTE;
         }
     }
     while(argc > 0) {
         target = *argv;
 
-        memset((char *) &whereto, 0, sizeof(whereto));
-        whereto.sin_family = AF_INET;
-        if(inet_aton(target, &whereto.sin_addr) == 1) {
-            hostname = target;
+        memset((char *) &a_ping_handle->whereto, 0, sizeof(a_ping_handle->whereto));
+        a_ping_handle->whereto.sin_family = AF_INET;
+        if(inet_aton(target, &a_ping_handle->whereto.sin_addr) == 1) {
+            a_ping_handle->ping_common.hostname = target;
             if(argc == 1)
-                options |= F_NUMERIC;
+                a_ping_handle->ping_common.options |= F_NUMERIC;
         } else {
             struct addrinfo *result = NULL;
             int status;
@@ -626,88 +656,88 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock)
                 ai = result;
             }
 
-            memcpy(&whereto, ai->ai_addr, sizeof whereto);
+            memcpy(&a_ping_handle->whereto, ai->ai_addr, sizeof (a_ping_handle->whereto));
             memset(hnamebuf, 0, sizeof hnamebuf);
             if(ai->ai_canonname)
                 strncpy(hnamebuf, ai->ai_canonname, sizeof hnamebuf - 1);
-            hostname = hnamebuf;
+            a_ping_handle->ping_common.hostname = hnamebuf;
 
             if(result)
                 freeaddrinfo(result);
         }
         if(argc > 1)
-            route[nroute++] = whereto.sin_addr.s_addr;
+            a_ping_handle->route[a_ping_handle->nroute++] = a_ping_handle->whereto.sin_addr.s_addr;
         argc--;
         argv++;
     }
 
-    if(source.sin_addr.s_addr == 0) {
+    if(a_ping_handle->source.sin_addr.s_addr == 0) {
         socklen_t alen;
-        struct sockaddr_in dst = whereto;
+        struct sockaddr_in dst = a_ping_handle->whereto;
         int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
 
         if(probe_fd < 0)
             error(2, errno, "socket");
-        if(device) {
+        if(a_ping_handle->device) {
             struct ifreq ifr;
             int i;
             int fds[2] = { probe_fd, sock->fd };
 
             memset(&ifr, 0, sizeof(ifr));
-            strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
+            strncpy(ifr.ifr_name, a_ping_handle->device, IFNAMSIZ - 1);
 
             for(i = 0; i < 2; i++) {
                 int fd = fds[i];
                 int rc;
                 int errno_save;
 
-                enable_capability_raw();
-                rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1);
+                enable_capability_raw(a_ping_handle);
+                rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, a_ping_handle->device, strlen(a_ping_handle->device) + 1);
                 errno_save = errno;
-                disable_capability_raw();
+                disable_capability_raw(a_ping_handle);
 
                 if(rc == -1) {
                     if(IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
                         struct ip_mreqn imr;
                         if(ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
-                            error(2, 0, "unknown iface: %s", device);
+                            error(2, 0, "unknown iface: %s", a_ping_handle->device);
                         memset(&imr, 0, sizeof(imr));
                         imr.imr_ifindex = ifr.ifr_ifindex;
                         if(setsockopt(fd, SOL_IP, IP_MULTICAST_IF, &imr, sizeof(imr)) == -1)
                             error(2, errno, "IP_MULTICAST_IF");
                     } else
-                        error(2, errno_save, "SO_BINDTODEVICE %s", device);
+                        error(2, errno_save, "SO_BINDTODEVICE %s", a_ping_handle->device);
                 }
             }
         }
 
-        if(settos &&
-                setsockopt(probe_fd, IPPROTO_IP, IP_TOS, (char *) &settos, sizeof(int)) < 0)
+        if(a_ping_handle->settos &&
+                setsockopt(probe_fd, IPPROTO_IP, IP_TOS, (char *) &a_ping_handle->settos, sizeof(int)) < 0)
             error(0, errno, "warning: QOS sockopts");
 
         dst.sin_port = htons(1025);
-        if(nroute)
-            dst.sin_addr.s_addr = route[0];
+        if(a_ping_handle->nroute)
+            dst.sin_addr.s_addr = a_ping_handle->route[0];
         if(connect(probe_fd, (struct sockaddr*) &dst, sizeof(dst)) == -1) {
             if(errno == EACCES) {
-                if(broadcast_pings == 0)
+                if(a_ping_handle->broadcast_pings == 0)
                     error(2, 0,
                             "Do you want to ping broadcast? Then -b. If not, check your local firewall rules");
                 fprintf(stderr, "WARNING: pinging broadcast address\n");
                 if(setsockopt(probe_fd, SOL_SOCKET, SO_BROADCAST,
-                        &broadcast_pings, sizeof(broadcast_pings)) < 0)
+                        &a_ping_handle->broadcast_pings, sizeof(a_ping_handle->broadcast_pings)) < 0)
                     error(2, errno, "cannot set broadcasting");
                 if(connect(probe_fd, (struct sockaddr*) &dst, sizeof(dst)) == -1)
                     error(2, errno, "connect");
             } else
                 error(2, errno, "connect");
         }
-        alen = sizeof(source);
-        if(getsockname(probe_fd, (struct sockaddr*) &source, &alen) == -1)
+        alen = sizeof(a_ping_handle->source);
+        if(getsockname(probe_fd, (struct sockaddr*) &a_ping_handle->source, &alen) == -1)
             error(2, errno, "getsockname");
-        source.sin_port = 0;
+        a_ping_handle->source.sin_port = 0;
 
-        if(device) {
+        if(a_ping_handle->device) {
             struct ifaddrs *ifa0, *ifa;
             int ret;
 
@@ -718,56 +748,56 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock)
                 if(!ifa->ifa_name || !ifa->ifa_addr ||
                         ifa->ifa_addr->sa_family != AF_INET)
                     continue;
-                if(!strcmp(ifa->ifa_name, device) &&
+                if(!strcmp(ifa->ifa_name, a_ping_handle->device) &&
                         !memcmp(&((struct sockaddr_in *) ifa->ifa_addr)->sin_addr,
-                                &source.sin_addr, sizeof(source.sin_addr)))
+                                &a_ping_handle->source.sin_addr, sizeof(a_ping_handle->source.sin_addr)))
                     break;
             }
             if(ifa && !memcmp(&((struct sockaddr_in *) ifa->ifa_addr)->sin_addr,
-                    &dst.sin_addr, sizeof(source.sin_addr))) {
-                enable_capability_raw();
+                    &dst.sin_addr, sizeof(a_ping_handle->source.sin_addr))) {
+                enable_capability_raw(a_ping_handle);
                 setsockopt(sock->fd, SOL_SOCKET, SO_BINDTODEVICE, "", 0);
-                disable_capability_raw();
+                disable_capability_raw(a_ping_handle);
             }
             freeifaddrs(ifa0);
             if(!ifa)
-                error(0, 0, "Warning: source address might be selected on device other than: %s", device);
+                error(0, 0, "Warning: source address might be selected on device other than: %s", a_ping_handle->device);
         }
         close(probe_fd);
     }
     while(0)
         ;
 
-    if(whereto.sin_addr.s_addr == 0)
-        whereto.sin_addr.s_addr = source.sin_addr.s_addr;
+    if(a_ping_handle->whereto.sin_addr.s_addr == 0)
+        a_ping_handle->whereto.sin_addr.s_addr = a_ping_handle->source.sin_addr.s_addr;
 
-    if(device) {
+    if(a_ping_handle->device) {
         struct ifreq ifr;
 
         memset(&ifr, 0, sizeof(ifr));
-        strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
+        strncpy(ifr.ifr_name, a_ping_handle->device, IFNAMSIZ - 1);
         if(ioctl(sock->fd, SIOCGIFINDEX, &ifr) < 0)
-            error(2, 0, "unknown iface: %s", device);
+            error(2, 0, "unknown iface: %s", a_ping_handle->device);
     }
 
-    if(broadcast_pings || IN_MULTICAST(ntohl(whereto.sin_addr.s_addr))) {
-        if(uid) {
-            if(interval < 1000)
-                error(2, 0, "broadcast ping with too short interval: %d", interval);
-            if(pmtudisc >= 0 && pmtudisc != IP_PMTUDISC_DO)
+    if(a_ping_handle->broadcast_pings || IN_MULTICAST(ntohl(a_ping_handle->whereto.sin_addr.s_addr))) {
+        if(a_ping_handle->ping_common.uid) {
+            if(a_ping_handle->ping_common.interval < 1000)
+                error(2, 0, "broadcast ping with too short interval: %d", a_ping_handle->ping_common.interval);
+            if(a_ping_handle->pmtudisc >= 0 && a_ping_handle->pmtudisc != IP_PMTUDISC_DO)
                 error(2, 0, "broadcast ping does not fragment");
         }
-        if(pmtudisc < 0)
-            pmtudisc = IP_PMTUDISC_DO;
+        if(a_ping_handle->pmtudisc < 0)
+            a_ping_handle->pmtudisc = IP_PMTUDISC_DO;
     }
 
-    if(pmtudisc >= 0) {
-        if(setsockopt(sock->fd, SOL_IP, IP_MTU_DISCOVER, &pmtudisc, sizeof pmtudisc) == -1)
+    if(a_ping_handle->pmtudisc >= 0) {
+        if(setsockopt(sock->fd, SOL_IP, IP_MTU_DISCOVER, &a_ping_handle->pmtudisc, sizeof (a_ping_handle->pmtudisc)) == -1)
             error(2, errno, "IP_MTU_DISCOVER");
     }
 
-    if((options & F_STRICTSOURCE) &&
-            bind(sock->fd, (struct sockaddr *) &source, sizeof source) == -1)
+    if((a_ping_handle->ping_common.options & F_STRICTSOURCE) &&
+            bind(sock->fd, (struct sockaddr *) &a_ping_handle->source, sizeof (a_ping_handle->source)) == -1)
         error(2, errno, "bind");
 
     if(sock->socktype == SOCK_RAW) {
@@ -794,28 +824,28 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock)
     }
 
     /* record route option */
-    if(options & F_RROUTE) {
+    if(a_ping_handle->ping_common.options & F_RROUTE) {
         memset(rspace, 0, sizeof(rspace));
         rspace[0] = IPOPT_NOP;
         rspace[1 + IPOPT_OPTVAL] = IPOPT_RR;
         rspace[1 + IPOPT_OLEN] = sizeof(rspace) - 1;
         rspace[1 + IPOPT_OFFSET] = IPOPT_MINOFF;
-        optlen = 40;
+        a_ping_handle->optlen = 40;
         if(setsockopt(sock->fd, IPPROTO_IP, IP_OPTIONS, rspace, sizeof rspace) < 0)
             error(2, errno, "record route");
     }
-    if(options & F_TIMESTAMP) {
+    if(a_ping_handle->ping_common.options & F_TIMESTAMP) {
         memset(rspace, 0, sizeof(rspace));
         rspace[0] = IPOPT_TIMESTAMP;
-        rspace[1] = (ts_type == IPOPT_TS_TSONLY ? 40 : 36);
+        rspace[1] = (a_ping_handle->ts_type == IPOPT_TS_TSONLY ? 40 : 36);
         rspace[2] = 5;
-        rspace[3] = ts_type;
-        if(ts_type == IPOPT_TS_PRESPEC) {
+        rspace[3] = a_ping_handle->ts_type;
+        if(a_ping_handle->ts_type == IPOPT_TS_PRESPEC) {
             int i;
-            rspace[1] = 4 + nroute * 8;
-            for(i = 0; i < nroute; i++) {
+            rspace[1] = 4 + a_ping_handle->nroute * 8;
+            for(i = 0; i < a_ping_handle->nroute; i++) {
                 tmp_rspace = (uint32_t*) &rspace[4 + i * 8];
-                *tmp_rspace = route[i];
+                *tmp_rspace = a_ping_handle->route[i];
             }
         }
         if(setsockopt(sock->fd, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) {
@@ -823,74 +853,74 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock)
             if(setsockopt(sock->fd, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0)
                 error(2, errno, "ts option");
         }
-        optlen = 40;
+        a_ping_handle->optlen = 40;
     }
-    if(options & F_SOURCEROUTE) {
+    if(a_ping_handle->ping_common.options & F_SOURCEROUTE) {
         int i;
         memset(rspace, 0, sizeof(rspace));
         rspace[0] = IPOPT_NOOP;
-        rspace[1 + IPOPT_OPTVAL] = (options & F_SO_DONTROUTE) ? IPOPT_SSRR
+        rspace[1 + IPOPT_OPTVAL] = (a_ping_handle->ping_common.options & F_SO_DONTROUTE) ? IPOPT_SSRR
                                                                 :
                                                                 IPOPT_LSRR;
-        rspace[1 + IPOPT_OLEN] = 3 + nroute * 4;
+        rspace[1 + IPOPT_OLEN] = 3 + a_ping_handle->nroute * 4;
         rspace[1 + IPOPT_OFFSET] = IPOPT_MINOFF;
-        for(i = 0; i < nroute; i++) {
+        for(i = 0; i < a_ping_handle->nroute; i++) {
             tmp_rspace = (uint32_t*) &rspace[4 + i * 4];
-            *tmp_rspace = route[i];
+            *tmp_rspace = a_ping_handle->route[i];
         }
 
-        if(setsockopt(sock->fd, IPPROTO_IP, IP_OPTIONS, rspace, 4 + nroute * 4) < 0)
+        if(setsockopt(sock->fd, IPPROTO_IP, IP_OPTIONS, rspace, 4 + a_ping_handle->nroute * 4) < 0)
             error(2, errno, "record route");
-        optlen = 40;
+        a_ping_handle->optlen = 40;
     }
 
     /* Estimate memory eaten by single packet. It is rough estimate.
      * Actually, for small datalen's it depends on kernel side a lot. */
-    hold = datalen + 8;
-    hold += ((hold + 511) / 512) * (optlen + 20 + 16 + 64 + 160);
-    sock_setbufs(sock, hold);
+    hold = a_ping_handle->ping_common.datalen + 8;
+    hold += ((hold + 511) / 512) * (a_ping_handle->optlen + 20 + 16 + 64 + 160);
+    sock_setbufs(a_ping_handle, sock, hold);
 
-    if(broadcast_pings) {
-        if(setsockopt(sock->fd, SOL_SOCKET, SO_BROADCAST, &broadcast_pings, sizeof broadcast_pings) < 0)
+    if(a_ping_handle->broadcast_pings) {
+        if(setsockopt(sock->fd, SOL_SOCKET, SO_BROADCAST, &a_ping_handle->broadcast_pings, sizeof (a_ping_handle->broadcast_pings)) < 0)
             error(2, errno, "cannot set broadcasting");
     }
 
-    if(options & F_NOLOOP) {
+    if(a_ping_handle->ping_common.options & F_NOLOOP) {
         int loop = 0;
         if(setsockopt(sock->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof loop) == -1)
             error(2, errno, "cannot disable multicast loopback");
     }
-    if(options & F_TTL) {
-        int ittl = ttl;
-        if(setsockopt(sock->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof ttl) == -1)
+    if(a_ping_handle->ping_common.options & F_TTL) {
+        int ittl = a_ping_handle->ping_common.ttl;
+        if(setsockopt(sock->fd, IPPROTO_IP, IP_MULTICAST_TTL, &a_ping_handle->ping_common.ttl, sizeof (a_ping_handle->ping_common.ttl)) == -1)
             error(2, errno, "cannot set multicast time-to-live");
         if(setsockopt(sock->fd, IPPROTO_IP, IP_TTL, &ittl, sizeof ittl) == -1)
             error(2, errno, "cannot set unicast time-to-live");
     }
 
-    if(datalen > 0xFFFF - 8 - optlen - 20)
+    if(a_ping_handle->ping_common.datalen > 0xFFFF - 8 - a_ping_handle->optlen - 20)
         error(2, 0, "packet size %d is too large. Maximum is %d",
-                datalen, 0xFFFF - 8 - 20 - optlen);
+                a_ping_handle->ping_common.datalen, 0xFFFF - 8 - 20 - a_ping_handle->optlen);
 
-    if(datalen >= (int) sizeof(struct timeval)) /* can we time transfer */
-        timing = 1;
-    packlen = datalen + MAXIPLEN + MAXICMPLEN;
+    if(a_ping_handle->ping_common.datalen >= (int) sizeof(struct timeval)) /* can we time transfer */
+        a_ping_handle->ping_common.timing = 1;
+    packlen = a_ping_handle->ping_common.datalen + MAXIPLEN + MAXICMPLEN;
     if(!(packet = (unsigned char *) malloc((unsigned int) packlen)))
         error(2, errno, "memory allocation failed");
 
 //printf("PING %s (%s) ", hostname, inet_ntoa(whereto.sin_addr));
-    if(device || (options & F_STRICTSOURCE))
-        printf("from %s %s: ", inet_ntoa(source.sin_addr), device ? device : "");
+    if(a_ping_handle->device || (a_ping_handle->ping_common.options & F_STRICTSOURCE))
+        printf("from %s %s: ", inet_ntoa(a_ping_handle->source.sin_addr), a_ping_handle->device ? a_ping_handle->device : "");
 //printf("%d(%d) bytes of data.\n", datalen, datalen + 8 + optlen + 20);
 
-    setup(sock);
-    log_printf("main_loop start %s (%s)\n", hostname, inet_ntoa(whereto.sin_addr));
-    main_loop(&ping4_func_set, sock, packet, packlen);
+    setup(a_ping_handle, sock);
+    log_printf("main_loop start %s (%s)\n", a_ping_handle->ping_common.hostname, inet_ntoa(a_ping_handle->whereto.sin_addr));
+    main_loop(a_ping_handle, &ping4_func_set, sock, packet, packlen);
     log_printf("main_loop end\n");
     return 0;
 }
 
-int ping4_receive_error_msg(socket_st *sock)
+int ping4_receive_error_msg(ping_handle_t *a_ping_handle, socket_st *sock)
 {
     ssize_t res;
     char cbuf[512];
@@ -931,39 +961,39 @@ int ping4_receive_error_msg(socket_st *sock)
 
     if(e->ee_origin == SO_EE_ORIGIN_LOCAL) {
         local_errors++;
-        if(options & F_QUIET)
+        if(a_ping_handle->ping_common.options & F_QUIET)
             goto out;
-        if(options & F_FLOOD)
+        if(a_ping_handle->ping_common.options & F_FLOOD)
             write_stdout("E", 1);
         else if(e->ee_errno != EMSGSIZE)
             error(0, 0, "local error: %s", strerror(e->ee_errno));
         else
             error(0, 0, "local error: message too long, mtu=%u", e->ee_info);
-        nerrors++;
+        a_ping_handle->ping_common.nerrors++;
     } else if(e->ee_origin == SO_EE_ORIGIN_ICMP) {
         struct sockaddr_in *sin = (struct sockaddr_in*) (e + 1);
 
         if(res < (ssize_t) sizeof(icmph) ||
-                target.sin_addr.s_addr != whereto.sin_addr.s_addr ||
+                target.sin_addr.s_addr != a_ping_handle->whereto.sin_addr.s_addr ||
                 icmph.type != ICMP_ECHO ||
-                !is_ours(sock, icmph.un.echo.id)) {
+                !is_ours(a_ping_handle, sock, icmph.un.echo.id)) {
             /* Not our error, not an error at all. Clear. */
             saved_errno = 0;
             goto out;
         }
 
-        acknowledge(ntohs(icmph.un.echo.sequence));
+        acknowledge(a_ping_handle, ntohs(icmph.un.echo.sequence));
 
         net_errors++;
-        nerrors++;
-        if(options & F_QUIET)
+        a_ping_handle->ping_common.nerrors++;
+        if(a_ping_handle->ping_common.options & F_QUIET)
             goto out;
-        if(options & F_FLOOD) {
+        if(a_ping_handle->ping_common.options & F_FLOOD) {
             write_stdout("\bE", 2);
         } else {
-            print_timestamp();
-            printf("From %s icmp_seq=%u ", pr_addr(sin, sizeof *sin), ntohs(icmph.un.echo.sequence));
-            pr_icmph(e->ee_type, e->ee_code, e->ee_info, NULL);
+            print_timestamp(a_ping_handle);
+            printf("From %s icmp_seq=%u ", pr_addr(a_ping_handle, sin, sizeof *sin), ntohs(icmph.un.echo.sequence));
+            pr_icmph(a_ping_handle, e->ee_type, e->ee_code, e->ee_info, NULL);
             fflush(stdout);
         }
     }
@@ -981,7 +1011,7 @@ int ping4_receive_error_msg(socket_st *sock)
  * of the data portion are used to hold a UNIX "timeval" struct in VAX
  * byte-order, to compute the round-trip time.
  */
-int ping4_send_probe(socket_st *sock, void *packet, unsigned packet_size __attribute__((__unused__)))
+int ping4_send_probe(ping_handle_t *a_ping_handle, socket_st *sock, void *packet, unsigned packet_size __attribute__((__unused__)))
 {
     struct icmphdr *icp;
     int cc;
@@ -991,13 +1021,13 @@ int ping4_send_probe(socket_st *sock, void *packet, unsigned packet_size __attri
     icp->type = ICMP_ECHO;
     icp->code = 0;
     icp->checksum = 0;
-    icp->un.echo.sequence = htons(ntransmitted + 1);
-    icp->un.echo.id = ident; /* ID */
+    icp->un.echo.sequence = htons(a_ping_handle->ping_common.ntransmitted + 1);
+    icp->un.echo.id = a_ping_handle->ping_common.ident; /* ID */
 
-    rcvd_clear(ntransmitted + 1);
+    rcvd_clear(a_ping_handle, a_ping_handle->ping_common.ntransmitted + 1);
 
-    if(timing) {
-        if(options & F_LATENCY) {
+    if(a_ping_handle->ping_common.timing) {
+        if(a_ping_handle->ping_common.options & F_LATENCY) {
             struct timeval tmp_tv;
             gettimeofday(&tmp_tv, NULL);
             memcpy(icp + 1, &tmp_tv, sizeof(tmp_tv));
@@ -1006,20 +1036,20 @@ int ping4_send_probe(socket_st *sock, void *packet, unsigned packet_size __attri
         }
     }
 
-    cc = datalen + 8; /* skips ICMP portion */
+    cc = a_ping_handle->ping_common.datalen + 8; /* skips ICMP portion */
 
     /* compute ICMP checksum here */
     icp->checksum = in_cksum((unsigned short *) icp, cc, 0);
 
-    if(timing && !(options & F_LATENCY)) {
+    if(a_ping_handle->ping_common.timing && !(a_ping_handle->ping_common.options & F_LATENCY)) {
         struct timeval tmp_tv;
         gettimeofday(&tmp_tv, NULL);
         memcpy(icp + 1, &tmp_tv, sizeof(tmp_tv));
         icp->checksum = in_cksum((unsigned short *) &tmp_tv, sizeof(tmp_tv), ~icp->checksum);
     }
 
-    i = sendto(sock->fd, icp, cc, 0, (struct sockaddr*) &whereto, sizeof(whereto));
-
+    i = sendto(sock->fd, icp, cc, 0, (struct sockaddr*) &a_ping_handle->whereto, sizeof(a_ping_handle->whereto));
+    //log_printf("**sendto(fd=%d,icp=0x%x,cc=%d)=%d\n",sock->fd,&icp,cc,i);
     return (cc == i ? 0 : i);
 }
 
@@ -1038,7 +1068,7 @@ void pr_echo_reply(uint8_t *_icp, int len __attribute__((__unused__)))
 }
 
 int
-ping4_parse_reply(struct socket_st *sock, struct msghdr *msg, int cc, void *addr, struct timeval *tv)
+ping4_parse_reply(ping_handle_t *a_ping_handle, struct socket_st *sock, struct msghdr *msg, int cc, void *addr, struct timeval *tv)
 {
     struct sockaddr_in *from = addr;
     uint8_t *buf = msg->msg_iov->iov_base;
@@ -1056,9 +1086,9 @@ ping4_parse_reply(struct socket_st *sock, struct msghdr *msg, int cc, void *addr
     if(sock->socktype == SOCK_RAW) {
         hlen = ip->ihl * 4;
         if(cc < hlen + 8 || ip->ihl < 5) {
-            if(options & F_VERBOSE)
+            if(a_ping_handle->ping_common.options & F_VERBOSE)
                 error(0, 0, "packet too short (%d bytes) from %s", cc,
-                        pr_addr(from, sizeof *from));
+                        pr_addr(a_ping_handle, from, sizeof *from));
             return 1;
         }
         reply_ttl = ip->ttl;
@@ -1091,13 +1121,13 @@ ping4_parse_reply(struct socket_st *sock, struct msghdr *msg, int cc, void *addr
 
     if(icp->type == ICMP_ECHOREPLY) {
         //log_printf("in ping4_parse_reply00\n");
-        if(!is_ours(sock, icp->un.echo.id))
+        if(!is_ours(a_ping_handle, sock, icp->un.echo.id))
             return 1; /* 'Twas not our ECHO */
-        if(!contains_pattern_in_payload((uint8_t*) (icp + 1)))
+        if(!contains_pattern_in_payload(a_ping_handle, (uint8_t*) (icp + 1)))
             return 1; /* 'Twas really not our ECHO */
-        if(gather_statistics((uint8_t*) icp, sizeof(*icp), cc,
+        if(gather_statistics(a_ping_handle, (uint8_t*) icp, sizeof(*icp), cc,
                 ntohs(icp->un.echo.sequence),
-                reply_ttl, 0, tv, pr_addr(from, sizeof *from),
+                reply_ttl, 0, tv, pr_addr(a_ping_handle, from, sizeof *from),
                 pr_echo_reply)) {
             fflush(stdout);
             return 0;
@@ -1122,60 +1152,60 @@ ping4_parse_reply(struct socket_st *sock, struct msghdr *msg, int cc, void *addr
                     cc < 8 + iph->ihl * 4 + 8)
                 return 1;
             if(icp1->type != ICMP_ECHO ||
-                    iph->daddr != whereto.sin_addr.s_addr ||
-                    !is_ours(sock, icp1->un.echo.id))
+                    iph->daddr != a_ping_handle->whereto.sin_addr.s_addr ||
+                    !is_ours(a_ping_handle, sock, icp1->un.echo.id))
                 return 1;
             error_pkt = (icp->type != ICMP_REDIRECT &&
                     icp->type != ICMP_SOURCE_QUENCH);
             if(error_pkt) {
-                acknowledge(ntohs(icp1->un.echo.sequence));
+                acknowledge(a_ping_handle, ntohs(icp1->un.echo.sequence));
                 return 0;
             }
-            if(options & (F_QUIET | F_FLOOD))
+            if(a_ping_handle->ping_common.options & (F_QUIET | F_FLOOD))
                 return 1;
-            print_timestamp();
+            print_timestamp(a_ping_handle);
             log_printf("From %s: icmp_seq=%u ",
-                    pr_addr(from, sizeof *from),
+                    pr_addr(a_ping_handle, from, sizeof *from),
                     ntohs(icp1->un.echo.sequence));
             if(csfailed)
                 log_printf("(BAD CHECKSUM)");
-            pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
+            pr_icmph(a_ping_handle, icp->type, icp->code, ntohl(icp->un.gateway), icp);
             return 1;
         }
         default:
             /* MUST NOT */
             break;
         }
-        if((options & F_FLOOD) && !(options & (F_VERBOSE | F_QUIET))) {
+        if((a_ping_handle->ping_common.options & F_FLOOD) && !(a_ping_handle->ping_common.options & (F_VERBOSE | F_QUIET))) {
             if(!csfailed)
                 write_stdout("!E", 2);
             else
                 write_stdout("!EC", 3);
             return 0;
         }
-        if(!(options & F_VERBOSE) || uid)
+        if(!(a_ping_handle->ping_common.options & F_VERBOSE) || a_ping_handle->ping_common.uid)
             return 0;
-        if(options & F_PTIMEOFDAY) {
+        if(a_ping_handle->ping_common.options & F_PTIMEOFDAY) {
             struct timeval recv_time;
             gettimeofday(&recv_time, NULL);
             log_printf("%lu.%06lu ", (unsigned long) recv_time.tv_sec, (unsigned long) recv_time.tv_usec);
         }
-        printf("From %s: ", pr_addr(from, sizeof *from));
+        printf("From %s: ", pr_addr(a_ping_handle, from, sizeof *from));
         if(csfailed) {
             log_printf("(BAD CHECKSUM)\n");
             return 0;
         }
-        pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
+        pr_icmph(a_ping_handle, icp->type, icp->code, ntohl(icp->un.gateway), icp);
         return 0;
     }
 
-    if(options & F_AUDIBLE) {
+    if(a_ping_handle->ping_common.options & F_AUDIBLE) {
         log_printf("\a"); //putchar('\a');
-        if(options & F_FLOOD)
+        if(a_ping_handle->ping_common.options & F_FLOOD)
             fflush(stdout);
     }
-    if(!(options & F_FLOOD)) {
-        pr_options(opts, olen + sizeof(struct iphdr));
+    if(!(a_ping_handle->ping_common.options & F_FLOOD)) {
+        pr_options(a_ping_handle, opts, olen + sizeof(struct iphdr));
 
         log_printf("\n"); //putchar('\n');
         fflush(stdout);
@@ -1227,7 +1257,7 @@ in_cksum(const unsigned short *addr, int len, unsigned short csum)
  * pr_icmph --
  *	Print a descriptive string about an ICMP header.
  */
-void pr_icmph(uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp)
+void pr_icmph(ping_handle_t *a_ping_handle, uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp)
 {
     switch (type) {
     case ICMP_ECHOREPLY:
@@ -1288,13 +1318,13 @@ void pr_icmph(uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp)
             printf("Dest Unreachable, Bad Code: %d\n", code);
             break;
         }
-        if(icp && (options & F_VERBOSE))
-            pr_iph((struct iphdr*) (icp + 1));
+        if(icp && (a_ping_handle->ping_common.options & F_VERBOSE))
+            pr_iph(a_ping_handle, (struct iphdr*) (icp + 1));
         break;
     case ICMP_SOURCE_QUENCH:
         printf("Source Quench\n");
-        if(icp && (options & F_VERBOSE))
-            pr_iph((struct iphdr*) (icp + 1));
+        if(icp && (a_ping_handle->ping_common.options & F_VERBOSE))
+            pr_iph(a_ping_handle, (struct iphdr*) (icp + 1));
         break;
     case ICMP_REDIRECT:
         switch (code) {
@@ -1317,10 +1347,10 @@ void pr_icmph(uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp)
         {
             struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = { icp ? icp->un.gateway : info } };
 
-            printf("(New nexthop: %s)\n", pr_addr(&sin, sizeof sin));
+            printf("(New nexthop: %s)\n", pr_addr(a_ping_handle, &sin, sizeof sin));
         }
-        if(icp && (options & F_VERBOSE))
-            pr_iph((struct iphdr*) (icp + 1));
+        if(icp && (a_ping_handle->ping_common.options & F_VERBOSE))
+            pr_iph(a_ping_handle, (struct iphdr*) (icp + 1));
         break;
     case ICMP_ECHO:
         printf("Echo Request\n");
@@ -1338,13 +1368,13 @@ void pr_icmph(uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp)
             printf("Time exceeded, Bad Code: %d\n", code);
             break;
         }
-        if(icp && (options & F_VERBOSE))
-            pr_iph((struct iphdr*) (icp + 1));
+        if(icp && (a_ping_handle->ping_common.options & F_VERBOSE))
+            pr_iph(a_ping_handle, (struct iphdr*) (icp + 1));
         break;
     case ICMP_PARAMETERPROB:
         printf("Parameter problem: pointer = %u\n", icp ? (ntohl(icp->un.gateway) >> 24) : info);
-        if(icp && (options & F_VERBOSE))
-            pr_iph((struct iphdr*) (icp + 1));
+        if(icp && (a_ping_handle->ping_common.options & F_VERBOSE))
+            pr_iph(a_ping_handle, (struct iphdr*) (icp + 1));
         break;
     case ICMP_TIMESTAMP:
         printf("Timestamp\n");
@@ -1377,7 +1407,7 @@ void pr_icmph(uint8_t type, uint8_t code, uint32_t info, struct icmphdr *icp)
     }
 }
 
-void pr_options(unsigned char * cp, int hlen)
+void pr_options(ping_handle_t *a_ping_handle, unsigned char * cp, int hlen)
 {
     int i, j;
     int olen, totlen;
@@ -1418,7 +1448,7 @@ void pr_options(unsigned char * cp, int hlen)
                     else {
                         struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = { address } };
 
-                        printf("\t%s", pr_addr(&sin, sizeof sin));
+                        printf("\t%s", pr_addr(a_ping_handle, &sin, sizeof sin));
                     }
                     j -= 4;
                     putchar('\n');
@@ -1437,7 +1467,7 @@ void pr_options(unsigned char * cp, int hlen)
                 break;
             if(i == old_rrlen
                     && !memcmp(cp, old_rr, i)
-                    && !(options & F_FLOOD)) {
+                    && !(a_ping_handle->ping_common.options & F_FLOOD)) {
                 printf("\t(same route)");
                 break;
             }
@@ -1454,7 +1484,7 @@ void pr_options(unsigned char * cp, int hlen)
                 else {
                     struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = { address } };
 
-                    printf("\t%s", pr_addr(&sin, sizeof sin));
+                    printf("\t%s", pr_addr(a_ping_handle, &sin, sizeof sin));
                 }
                 i -= 4;
                 putchar('\n');
@@ -1488,7 +1518,7 @@ void pr_options(unsigned char * cp, int hlen)
                     else {
                         struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = { address } };
 
-                        printf("\t%s", pr_addr(&sin, sizeof sin));
+                        printf("\t%s", pr_addr(a_ping_handle, &sin, sizeof sin));
                     }
                     i -= 4;
                     if(i <= 0)
@@ -1534,7 +1564,7 @@ void pr_options(unsigned char * cp, int hlen)
  * pr_iph --
  *	Print an IP header with options.
  */
-void pr_iph(struct iphdr *ip)
+void pr_iph(ping_handle_t *a_ping_handle, struct iphdr *ip)
 {
     int hlen;
     unsigned char *cp;
@@ -1551,7 +1581,7 @@ void pr_iph(struct iphdr *ip)
     printf(" %s ", inet_ntoa(*(struct in_addr *) &ip->saddr));
     printf(" %s ", inet_ntoa(*(struct in_addr *) &ip->daddr));
     printf("\n");
-    pr_options(cp, hlen);
+    pr_options(a_ping_handle, cp, hlen);
 }
 
 /*
@@ -1560,7 +1590,7 @@ void pr_iph(struct iphdr *ip)
  * Return an ascii host address optionally with a hostname.
  */
 char *
-pr_addr(void *sa, socklen_t salen)
+pr_addr(ping_handle_t *a_ping_handle, void *sa, socklen_t salen)
 {
     static char buffer[4096] = "";
     static struct sockaddr_storage last_sa = { 0, { 0 }, 0 };
@@ -1573,10 +1603,10 @@ pr_addr(void *sa, socklen_t salen)
 
     memcpy(&last_sa, sa, (last_salen = salen));
 
-    in_pr_addr = !setjmp(pr_addr_jmp);
+    a_ping_handle->ping_common.in_pr_addr = !setjmp(a_ping_handle->ping_common.pr_addr_jmp);
 
     getnameinfo(sa, salen, address, sizeof address, NULL, 0, getnameinfo_flags | NI_NUMERICHOST);
-    if(!exiting && !(options & F_NUMERIC))
+    if(!exiting && !(a_ping_handle->ping_common.options & F_NUMERIC))
         getnameinfo(sa, salen, name, sizeof name, NULL, 0, getnameinfo_flags);
 
     if(*name)
@@ -1584,7 +1614,7 @@ pr_addr(void *sa, socklen_t salen)
     else
         snprintf(buffer, sizeof buffer, "%s", address);
 
-    in_pr_addr = 0;
+    a_ping_handle->ping_common.in_pr_addr = 0;
 
     return (buffer);
 }
@@ -1634,7 +1664,7 @@ int parseflow(char *str)
     return (val);
 }
 
-void ping4_install_filter(socket_st *sock)
+void ping4_install_filter(ping_handle_t *a_ping_handle, socket_st *sock)
 {
     static int once;
     static struct sock_filter insns[] = {
@@ -1657,7 +1687,7 @@ void ping4_install_filter(socket_st *sock)
     once = 1;
 
     /* Patch bpflet for current identifier. */
-    insns[2] = (struct sock_filter )BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(ident), 0, 1);
+    insns[2] = (struct sock_filter )BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(a_ping_handle->ping_common.ident), 0, 1);
 
     if(setsockopt(sock->fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
         error(0, errno, "WARNING: failed to install socket filter");
diff --git a/iputils/ping.h b/iputils/ping.h
index ddc445f9322fb63c089f50272e27b637adf55aa1..651455289f18f42a956cd9cfc8cf61d4f059ecfa 100644
--- a/iputils/ping.h
+++ b/iputils/ping.h
@@ -93,7 +93,7 @@
 #define SCHINT(a) (((a) <= MININTERVAL) ? MININTERVAL : (a))
 
 /* various options */
-extern int options;
+//extern int options;
 #define F_FLOOD   0x001
 #define F_INTERVAL  0x002
 #define F_NUMERIC 0x004
@@ -122,49 +122,44 @@ extern int options;
  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
  * number of received sequence numbers we can keep track of.
  */
-#define MAX_DUP_CHK 0x10000
+
 
 #if defined(__WORDSIZE) && __WORDSIZE == 64
 # define USE_BITMAP64
 #endif
 
-#ifdef USE_BITMAP64
-typedef uint64_t  bitmap_t;
-# define BITMAP_SHIFT 6
-#else
-typedef uint32_t  bitmap_t;
-# define BITMAP_SHIFT 5
-#endif
+
 
 #if ((MAX_DUP_CHK >> (BITMAP_SHIFT + 3)) << (BITMAP_SHIFT + 3)) != MAX_DUP_CHK
 # error Please MAX_DUP_CHK and/or BITMAP_SHIFT
 #endif
 
-struct rcvd_table {
-  bitmap_t bitmap[MAX_DUP_CHK / (sizeof(bitmap_t) * 8)];
-};
 
-extern struct rcvd_table rcvd_tbl;
 
-#define A(bit)  (rcvd_tbl.bitmap[(bit) >> BITMAP_SHIFT])  /* identify word in array */
+//extern struct rcvd_table rcvd_tbl;
+
+//#define A(a_ping_handle, bit)  (a_ping_handle->ping_common.rcvd_tbl.bitmap[(bit) >> BITMAP_SHIFT])  /* identify word in array */
 #define B(bit)  (((bitmap_t)1) << ((bit) & ((1 << BITMAP_SHIFT) - 1)))  /* identify bit in word */
 
-static inline void rcvd_set(uint16_t seq)
+static inline void rcvd_set(ping_handle_t *a_ping_handle, uint16_t seq)
 {
   unsigned bit = seq % MAX_DUP_CHK;
-  A(bit) |= B(bit);
+  a_ping_handle->ping_common.rcvd_tbl.bitmap[(bit) >> BITMAP_SHIFT] |= B(bit);
+  //A(a_ping_handle, bit) |= B(bit);
 }
 
-static inline void rcvd_clear(uint16_t seq)
+static inline void rcvd_clear(ping_handle_t *a_ping_handle, uint16_t seq)
 {
   unsigned bit = seq % MAX_DUP_CHK;
-  A(bit) &= ~B(bit);
+  a_ping_handle->ping_common.rcvd_tbl.bitmap[(bit) >> BITMAP_SHIFT] &= ~B(bit);
+  //A(a_ping_handle, bit) &= ~B(bit);
 }
 
-static inline bitmap_t rcvd_test(uint16_t seq)
+static inline bitmap_t rcvd_test(ping_handle_t *a_ping_handle, uint16_t seq)
 {
   unsigned bit = seq % MAX_DUP_CHK;
-  return A(bit) & B(bit);
+  return (a_ping_handle->ping_common.rcvd_tbl.bitmap[(bit) >> BITMAP_SHIFT] & B(bit));
+  //return A(a_ping_handle, bit) & B(bit);
 }
 
 #ifndef HAVE_ERROR_H
@@ -185,34 +180,37 @@ static void error(int status, int errnum, const char *format, ...)
 }
 #endif
 
+/*
 extern int datalen;
 extern char *hostname;
 extern int uid;
-extern int ident;     /* process id to identify our packets */
+extern int ident;     // process id to identify our packets
 
 extern int sndbuf;
 extern int ttl;
 
-extern long npackets;     /* max packets to transmit */
-extern long nreceived;      /* # of packets we got back */
-extern long nrepeats;     /* number of duplicates */
-extern long ntransmitted;   /* sequence # for outbound packets = #sent */
-extern long nchecksum;      /* replies with bad checksum */
-extern long nerrors;      /* icmp errors */
-extern int interval;      /* interval between packets (msec) */
+extern long npackets;     // max packets to transmit
+extern long nreceived;      // # of packets we got back
+extern long nrepeats;     // number of duplicates
+extern long ntransmitted;   // sequence # for outbound packets = #sent
+extern long nchecksum;      // replies with bad checksum
+extern long nerrors;      // icmp errors
+extern int interval;      // interval between packets (msec)
 extern int preload;
-extern int deadline;      /* time to die */
+extern int deadline;      // time to die
 extern int lingertime;
 extern struct timeval start_time, cur_time;
-extern volatile int exiting;
-extern volatile int status_snapshot;
 extern int confirm;
 extern int confirm_flag;
 extern char *device;
 extern int pmtudisc;
 
-extern volatile int in_pr_addr;   /* pr_addr() is executing */
+extern volatile int in_pr_addr;   // pr_addr() is executing
 extern jmp_buf pr_addr_jmp;
+*/
+
+extern volatile int exiting;
+extern volatile int status_snapshot;
 
 #ifndef MSG_CONFIRM
 #define MSG_CONFIRM 0
@@ -220,14 +218,16 @@ extern jmp_buf pr_addr_jmp;
 
 
 /* timing */
-extern int timing;      /* flag to do timing */
-extern long tmin;     /* minimum round trip time */
-extern long tmax;     /* maximum round trip time */
-extern long long tsum;      /* sum of all times, for doing average */
+/*
+extern int timing;      // flag to do timing
+extern long tmin;     // minimum round trip time
+extern long tmax;     // maximum round trip time
+extern long long tsum;      // sum of all times, for doing average
 extern long long tsum2;
 extern int rtt;
 extern uint16_t acked;
 extern int pipesize;
+*/
 
 /*
  * Write to stdout
@@ -266,47 +266,48 @@ static inline void set_signal(int signo, void (*handler)(int))
   sigaction(signo, &sa, NULL);
 }
 
-extern int __schedule_exit(int next);
+extern int __schedule_exit(ping_handle_t *a_ping_handle, int next);
 
-static inline int schedule_exit(int next)
+static inline int schedule_exit(ping_handle_t  *a_ping_handle, int next)
 {
-  if (npackets && ntransmitted >= npackets && !deadline)
-    next = __schedule_exit(next);
+  if (a_ping_handle->ping_common.npackets && a_ping_handle->ping_common.ntransmitted >= a_ping_handle->ping_common.npackets
+          && !a_ping_handle->ping_common.deadline)
+    next = __schedule_exit(a_ping_handle, next);
   return next;
 }
 
-static inline int in_flight(void)
+static inline int in_flight(ping_handle_t *a_ping_handle)
 {
-  uint16_t diff = (uint16_t)ntransmitted - acked;
-  return (diff<=0x7FFF) ? diff : ntransmitted-nreceived-nerrors;
+  uint16_t diff = (uint16_t)a_ping_handle->ping_common.ntransmitted - a_ping_handle->ping_common.acked;
+  return (diff<=0x7FFF) ? diff : a_ping_handle->ping_common.ntransmitted-a_ping_handle->ping_common.nreceived-a_ping_handle->ping_common.nerrors;
 }
 
-static inline void acknowledge(uint16_t seq)
+static inline void acknowledge(ping_handle_t *a_ping_handle, uint16_t seq)
 {
-  uint16_t diff = (uint16_t)ntransmitted - seq;
+  uint16_t diff = (uint16_t)a_ping_handle->ping_common.ntransmitted - seq;
   if (diff <= 0x7FFF) {
-    if ((int)diff+1 > pipesize)
-      pipesize = (int)diff+1;
-    if ((int16_t)(seq - acked) > 0 ||
-        (uint16_t)ntransmitted - acked > 0x7FFF)
-      acked = seq;
+    if ((int)diff+1 > a_ping_handle->ping_common.pipesize)
+        a_ping_handle->ping_common.pipesize = (int)diff+1;
+    if ((int16_t)(seq - a_ping_handle->ping_common.acked) > 0 ||
+        (uint16_t)a_ping_handle->ping_common.ntransmitted - a_ping_handle->ping_common.acked > 0x7FFF)
+        a_ping_handle->ping_common.acked = seq;
   }
 }
 
-static inline void advance_ntransmitted(void)
+static inline void advance_ntransmitted(ping_handle_t  *a_ping_handle)
 {
-  ntransmitted++;
+    a_ping_handle->ping_common.ntransmitted++;
   /* Invalidate acked, if 16 bit seq overflows. */
-  if ((uint16_t)ntransmitted - acked > 0x7FFF)
-    acked = (uint16_t)ntransmitted + 1;
+  if ((uint16_t)a_ping_handle->ping_common.ntransmitted - a_ping_handle->ping_common.acked > 0x7FFF)
+      a_ping_handle->ping_common.acked = (uint16_t)a_ping_handle->ping_common.ntransmitted + 1;
 }
 
 extern void usage(void) __attribute__((noreturn));
-extern void limit_capabilities(void);
-static int enable_capability_raw(void);
-static int disable_capability_raw(void);
-static int enable_capability_admin(void);
-static int disable_capability_admin(void);
+extern void limit_capabilities(ping_handle_t *a_ping_handle);
+static int enable_capability_raw(ping_handle_t *a_ping_handle);
+static int disable_capability_raw(ping_handle_t *a_ping_handle);
+static int enable_capability_admin(ping_handle_t *a_ping_handle);
+static int disable_capability_admin(ping_handle_t *a_ping_handle);
 #ifdef HAVE_LIBCAP
 extern int modify_capability(cap_value_t, cap_flag_value_t);
 static inline int enable_capability_raw(void)   { return modify_capability(CAP_NET_RAW,   CAP_SET);   }
@@ -314,11 +315,11 @@ static inline int disable_capability_raw(void)    { return modify_capability(CAP
 static inline int enable_capability_admin(void)   { return modify_capability(CAP_NET_ADMIN, CAP_SET);   }
 static inline int disable_capability_admin(void)  { return modify_capability(CAP_NET_ADMIN, CAP_CLEAR); }
 #else
-extern int modify_capability(int);
-static inline int enable_capability_raw(void)   { return modify_capability(1); }
-static inline int disable_capability_raw(void)    { return modify_capability(0); }
-static inline int enable_capability_admin(void)   { return modify_capability(1); }
-static inline int disable_capability_admin(void)  { return modify_capability(0); }
+extern int modify_capability(ping_handle_t *a_ping_handle, int);
+static inline int enable_capability_raw(ping_handle_t *a_ping_handle)     { return modify_capability(a_ping_handle, 1); }
+static inline int disable_capability_raw(ping_handle_t *a_ping_handle)    { return modify_capability(a_ping_handle, 0); }
+static inline int enable_capability_admin(ping_handle_t *a_ping_handle)   { return modify_capability(a_ping_handle, 1); }
+static inline int disable_capability_admin(ping_handle_t *a_ping_handle)  { return modify_capability(a_ping_handle, 0); }
 #endif
 extern void drop_capabilities(void);
 
@@ -327,53 +328,52 @@ typedef struct socket_st {
   int socktype;
 } socket_st;
 
-char *pr_addr(void *sa, socklen_t salen);
+char *pr_addr(ping_handle_t *a_ping_handle, void *sa, socklen_t salen);
 
-int is_ours(socket_st *sock, uint16_t id);
+int is_ours(ping_handle_t *a_ping_handle, socket_st *sock, uint16_t id);
 
-int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock);
-int ping4_send_probe(socket_st *, void *packet, unsigned packet_size);
-int ping4_receive_error_msg(socket_st *);
-int ping4_parse_reply(socket_st *, struct msghdr *msg, int len, void *addr, struct timeval *);
-void ping4_install_filter(socket_st *);
+int ping4_run(ping_handle_t *a_ping_handle, int argc, char **argv, struct addrinfo *ai, socket_st *sock);
+int ping4_send_probe(ping_handle_t *a_ping_handle, socket_st *, void *packet, unsigned packet_size);
+int ping4_receive_error_msg(ping_handle_t *a_ping_handle, socket_st *sock);
+int ping4_parse_reply(ping_handle_t *a_ping_handle, socket_st *, struct msghdr *msg, int len, void *addr, struct timeval *);
+void ping4_install_filter( ping_handle_t *a_ping_handle, socket_st *);
 
 typedef struct ping_func_set_st {
-  int (*send_probe)(socket_st *, void *packet, unsigned packet_size);
-  int (*receive_error_msg)(socket_st *sock);
-  int (*parse_reply)(socket_st *, struct msghdr *msg, int len, void *addr, struct timeval *);
-  void (*install_filter)(socket_st *);
+  int (*send_probe)(ping_handle_t *a_ping_handle, socket_st *, void *packet, unsigned packet_size);
+  int (*receive_error_msg)(ping_handle_t *a_ping_handle, socket_st *sock);
+  int (*parse_reply)(ping_handle_t *a_ping_handle, socket_st *, struct msghdr *msg, int len, void *addr, struct timeval *);
+  void (*install_filter)(ping_handle_t *a_ping_handle, socket_st *);
 } ping_func_set_st;
 
-#define MAXPACKET 128000    /* max packet size */
 extern ping_func_set_st ping4_func_set;
 
-extern int pinger(ping_func_set_st *fset, socket_st *sock);
-extern void sock_setbufs(socket_st*, int alloc);
-extern void setup(socket_st *);
-extern int contains_pattern_in_payload(uint8_t *ptr);
-extern void main_loop(ping_func_set_st *fset, socket_st*, uint8_t *buf, int buflen);// __attribute__((noreturn));
-extern void finish(void);// __attribute__((noreturn));
-extern void status(void);
+extern int pinger(ping_handle_t *a_ping_handle, ping_func_set_st *fset, socket_st *sock);
+extern void sock_setbufs(ping_handle_t *a_ping_handle, socket_st*, int alloc);
+extern void setup(ping_handle_t *a_ping_handle, socket_st *);
+extern int contains_pattern_in_payload(ping_handle_t *a_ping_handle, uint8_t *ptr);
+extern void main_loop(ping_handle_t *a_ping_handle, ping_func_set_st *fset, socket_st*, uint8_t *buf, int buflen);// __attribute__((noreturn));
+extern void finish(ping_handle_t *a_ping_handle);// __attribute__((noreturn));
+extern void status(ping_handle_t *a_ping_handle);
 extern void common_options(int ch);
-extern int gather_statistics(uint8_t *ptr, int icmplen,
+extern int gather_statistics(ping_handle_t *a_ping_handle, uint8_t *ptr, int icmplen,
            int cc, uint16_t seq, int hops,
            int csfailed, struct timeval *tv, char *from,
            void (*pr_reply)(uint8_t *ptr, int cc));
-extern void print_timestamp(void);
-void fill(char *patp, unsigned char *packet, unsigned packet_size);
+extern void print_timestamp(ping_handle_t *a_ping_handle);
+void fill(ping_handle_t *a_ping_handle, char *patp, unsigned char *packet, unsigned packet_size);
 
-extern int mark;
-extern unsigned char outpack[MAXPACKET];
+//extern int mark;
+//extern unsigned char outpack[MAXPACKET];
 
 /* IPv6 */
 
-int ping6_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock);
+int ping6_run(ping_handle_t *a_ping_handle, int argc, char **argv, struct addrinfo *ai, socket_st *sock);
 void ping6_usage(unsigned from_ping);
 
-int ping6_send_probe(socket_st *sockets, void *packet, unsigned packet_size);
-int ping6_receive_error_msg(socket_st *sockets);
-int ping6_parse_reply(socket_st *, struct msghdr *msg, int len, void *addr, struct timeval *);
-void ping6_install_filter(socket_st *sockets);
+int ping6_send_probe(ping_handle_t *a_ping_handle, socket_st *sockets, void *packet, unsigned packet_size);
+int ping6_receive_error_msg(ping_handle_t *a_ping_handle, socket_st *sock);
+int ping6_parse_reply(ping_handle_t *a_ping_handle, socket_st *, struct msghdr *msg, int len, void *addr, struct timeval *);
+void ping6_install_filter(ping_handle_t *a_ping_handle, socket_st *sockets);
 
 extern ping_func_set_st ping6_func_set;
 
diff --git a/iputils/ping6_common.c b/iputils/ping6_common.c
index ee2690cb541dfe12fd3beaca4856690af97f93e5..3bb143fadd3c39f6bc58b146e380892f50e365aa 100644
--- a/iputils/ping6_common.c
+++ b/iputils/ping6_common.c
@@ -90,7 +90,7 @@ static size_t cmsglen = 0;
 static int pr_icmph(uint8_t type, uint8_t code, uint32_t info);
 
 struct sockaddr_in6 source6 = { .sin6_family = AF_INET6 };
-extern char *device;
+//extern char *device;
 
 #if defined(USE_GCRYPT) || defined(USE_OPENSSL) || defined(USE_NETTLE)
 #include "iputils_md5dig.h"
@@ -562,7 +562,7 @@ int niquery_option_handler(const char *opt_arg)
     return ret;
 }
 
-int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock)
+int ping6_run(ping_handle_t *a_ping_handle, int argc, char **argv, struct addrinfo *ai, struct socket_st *sock)
 {
     static const struct addrinfo hints = { .ai_family = AF_INET6, .ai_flags = getaddrinfo_flags };
     struct addrinfo *result = NULL;
@@ -608,7 +608,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
         freeaddrinfo(result);
 
     if(memchr(target, ':', strlen(target)))
-        options |= F_NUMERIC;
+        a_ping_handle->ping_common.options |= F_NUMERIC;
 
     if(IN6_IS_ADDR_UNSPECIFIED(&firsthop.sin6_addr)) {
         memcpy(&firsthop.sin6_addr, &whereto.sin6_addr, 16);
@@ -620,7 +620,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
             scope_id = firsthop.sin6_scope_id;
     }
 
-    hostname = target;
+    a_ping_handle->ping_common.hostname = target;
 
     if(IN6_IS_ADDR_UNSPECIFIED(&source6.sin6_addr)) {
         socklen_t alen;
@@ -628,8 +628,8 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
 
         if(probe_fd < 0)
             error(2, errno, "socket");
-        if(device) {
-            unsigned int iface = if_name2index(device);
+        if(a_ping_handle->device) {
+            unsigned int iface = if_name2index(a_ping_handle->device);
 #ifdef IPV6_RECVPKTINFO
             struct in6_pktinfo ipi;
 
@@ -640,7 +640,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
             if(IN6_IS_ADDR_LINKLOCAL(&firsthop.sin6_addr) ||
                     IN6_IS_ADDR_MC_LINKLOCAL(&firsthop.sin6_addr))
                 firsthop.sin6_scope_id = iface;
-            enable_capability_raw();
+            enable_capability_raw(a_ping_handle);
 #ifdef IPV6_RECVPKTINFO
             if(
             setsockopt(probe_fd, IPPROTO_IPV6, IPV6_PKTINFO, &ipi, sizeof ipi) == -1 ||
@@ -650,11 +650,11 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
             }
 #endif
             if(
-            setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1 ||
-                    setsockopt(sock->fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1) {
-                error(2, errno, "setsockopt(SO_BINDTODEVICE) %s", device);
+            setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, a_ping_handle->device, strlen(a_ping_handle->device) + 1) == -1 ||
+                    setsockopt(sock->fd, SOL_SOCKET, SO_BINDTODEVICE, a_ping_handle->device, strlen(a_ping_handle->device) + 1) == -1) {
+                error(2, errno, "setsockopt(SO_BINDTODEVICE) %s", a_ping_handle->device);
             }
-            disable_capability_raw();
+            disable_capability_raw(a_ping_handle);
         }
 
         if(!IN6_IS_ADDR_LINKLOCAL(&firsthop.sin6_addr) &&
@@ -670,7 +670,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
         source6.sin6_port = 0;
         close(probe_fd);
 
-        if(device) {
+        if(a_ping_handle->device) {
             struct ifaddrs *ifa0, *ifa;
 
             if(getifaddrs(&ifa0))
@@ -680,22 +680,22 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
                 if(!ifa->ifa_name || !ifa->ifa_addr ||
                         ifa->ifa_addr->sa_family != AF_INET6)
                     continue;
-                if(!strcmp(ifa->ifa_name, device) &&
+                if(!strcmp(ifa->ifa_name, a_ping_handle->device) &&
                         IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 * )ifa->ifa_addr)->sin6_addr,
                                 &source6.sin6_addr))
                     break;
             }
             if(!ifa)
-                error(0, 0, "Warning: source address might be selected on device other than: %s", device);
+                error(0, 0, "Warning: source address might be selected on device other than: %s", a_ping_handle->device);
 
             freeifaddrs(ifa0);
         }
     }
-    else if(device && (IN6_IS_ADDR_LINKLOCAL(&source6.sin6_addr) ||
+    else if(a_ping_handle->device && (IN6_IS_ADDR_LINKLOCAL(&source6.sin6_addr) ||
             IN6_IS_ADDR_MC_LINKLOCAL(&source6.sin6_addr)))
-        source6.sin6_scope_id = if_name2index(device);
+        source6.sin6_scope_id = if_name2index(a_ping_handle->device);
 
-    if(device) {
+    if(a_ping_handle->device) {
         struct cmsghdr *cmsg;
         struct in6_pktinfo *ipi;
 
@@ -707,34 +707,34 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
 
         ipi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
         memset(ipi, 0, sizeof(*ipi));
-        ipi->ipi6_ifindex = if_name2index(device);
+        ipi->ipi6_ifindex = if_name2index(a_ping_handle->device);
     }
 
     if((whereto.sin6_addr.s6_addr16[0] & htons(0xff00)) == htons(0xff00)) {
-        if(uid) {
-            if(interval < 1000)
-                error(2, 0, "multicast ping with too short interval: %d", interval);
-            if(pmtudisc >= 0 && pmtudisc != IPV6_PMTUDISC_DO)
+        if(a_ping_handle->ping_common.uid) {
+            if(a_ping_handle->ping_common.interval < 1000)
+                error(2, 0, "multicast ping with too short interval: %d", a_ping_handle->ping_common.interval);
+            if(a_ping_handle->pmtudisc >= 0 && a_ping_handle->pmtudisc != IPV6_PMTUDISC_DO)
                 error(2, 0, "multicast ping does not fragment");
         }
-        if(pmtudisc < 0)
-            pmtudisc = IPV6_PMTUDISC_DO;
+        if(a_ping_handle->pmtudisc < 0)
+            a_ping_handle->pmtudisc = IPV6_PMTUDISC_DO;
     }
 
-    if(pmtudisc >= 0) {
-        if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &pmtudisc, sizeof pmtudisc) == -1)
+    if(a_ping_handle->pmtudisc >= 0) {
+        if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &a_ping_handle->pmtudisc, sizeof (a_ping_handle->pmtudisc)) == -1)
             error(2, errno, "IPV6_MTU_DISCOVER");
     }
 
-    if((options & F_STRICTSOURCE) &&
+    if((a_ping_handle->ping_common.options & F_STRICTSOURCE) &&
             bind(sock->fd, (struct sockaddr *) &source6, sizeof source6) == -1)
         error(2, errno, "bind icmp socket");
 
-    if((ssize_t) datalen >= (ssize_t) sizeof(struct timeval) && (ni_query < 0)) {
+    if((ssize_t) a_ping_handle->ping_common.datalen >= (ssize_t) sizeof(struct timeval) && (ni_query < 0)) {
         /* can we time transfer */
-        timing = 1;
+        a_ping_handle->ping_common.timing = 1;
     }
-    packlen = datalen + 8 + 4096 + 40 + 8; /* 4096 for rthdr */
+    packlen = a_ping_handle->ping_common.datalen + 8 + 4096 + 40 + 8; /* 4096 for rthdr */
     if(!(packet = (unsigned char *) malloc((unsigned int) packlen)))
         error(2, errno, "memory allocation failed");
 
@@ -742,9 +742,9 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
 
     /* Estimate memory eaten by single packet. It is rough estimate.
      * Actually, for small datalen's it depends on kernel side a lot. */
-    hold = datalen + 8;
+    hold = a_ping_handle->ping_common.datalen + 8;
     hold += ((hold + 511) / 512) * (40 + 16 + 64 + 160);
-    sock_setbufs(sock, hold);
+    sock_setbufs(a_ping_handle,sock, hold);
 
 #ifdef __linux__
     if(sock->socktype == SOCK_RAW) {
@@ -784,15 +784,15 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
             error(2, errno, "setsockopt(ICMP6_FILTER)");
     }
 
-    if(options & F_NOLOOP) {
+    if(a_ping_handle->ping_common.options & F_NOLOOP) {
         int loop = 0;
         if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof loop) == -1)
             error(2, errno, "can't disable multicast loopback");
     }
-    if(options & F_TTL) {
-        if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof ttl) == -1)
+    if(a_ping_handle->ping_common.options & F_TTL) {
+        if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &a_ping_handle->ping_common.ttl, sizeof (a_ping_handle->ping_common.ttl)) == -1)
             error(2, errno, "can't set multicast hop limit");
-        if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof ttl) == -1)
+        if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &a_ping_handle->ping_common.ttl, sizeof (a_ping_handle->ping_common.ttl)) == -1)
             error(2, errno, "can't set unicast hop limit");
     }
 
@@ -807,7 +807,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
                     )
         error(2, errno, "can't receive hop limit");
 
-    if(options & F_TCLASS) {
+    if(a_ping_handle->ping_common.options & F_TCLASS) {
 #ifdef IPV6_TCLASS
         if(setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof tclass) == -1)
             error(2, errno, "setsockopt(IPV6_TCLASS)");
@@ -816,7 +816,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
 #endif
     }
 
-    if(options & F_FLOWINFO) {
+    if(a_ping_handle->ping_common.options & F_FLOWINFO) {
 #ifdef IPV6_FLOWLABEL_MGR
         char freq_buf[CMSG_ALIGN(sizeof(struct in6_flowlabel_req)) + cmsglen];
         struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
@@ -843,27 +843,27 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock
 #endif
     }
 
-    printf("PING %s(%s) ", hostname, pr_addr(&whereto, sizeof whereto));
+    printf("PING %s(%s) ", a_ping_handle->ping_common.hostname, pr_addr(a_ping_handle, &whereto, sizeof whereto));
     if(flowlabel)
         printf(", flow 0x%05x, ", (unsigned) ntohl(flowlabel));
-    if(device || (options & F_STRICTSOURCE)) {
-        int saved_options = options;
+    if(a_ping_handle->device || (a_ping_handle->ping_common.options & F_STRICTSOURCE)) {
+        int saved_options = a_ping_handle->ping_common.options;
 
-        options |= F_NUMERIC;
-        printf("from %s %s: ", pr_addr(&source6, sizeof source6), device ? device : "");
-        options = saved_options;
+        a_ping_handle->ping_common.options |= F_NUMERIC;
+        printf("from %s %s: ", pr_addr(a_ping_handle, &source6, sizeof source6), a_ping_handle->device ? a_ping_handle->device : "");
+        a_ping_handle->ping_common.options = saved_options;
     }
-    printf("%d data bytes\n", datalen);
+    printf("%d data bytes\n", a_ping_handle->ping_common.datalen);
 
-    setup(sock);
+    setup(a_ping_handle, sock);
 
     drop_capabilities();
 
-    main_loop(&ping6_func_set, sock, packet, packlen);
+    main_loop(a_ping_handle, &ping6_func_set, sock, packet, packlen);
     return 0;
 }
 
-int ping6_receive_error_msg(socket_st *sock)
+int ping6_receive_error_msg(ping_handle_t *a_ping_handle, socket_st *sock)
 {
     ssize_t res;
     char cbuf[512];
@@ -903,36 +903,36 @@ int ping6_receive_error_msg(socket_st *sock)
 
     if(e->ee_origin == SO_EE_ORIGIN_LOCAL) {
         local_errors++;
-        if(options & F_QUIET)
+        if(a_ping_handle->ping_common.options & F_QUIET)
             goto out;
-        if(options & F_FLOOD)
+        if(a_ping_handle->ping_common.options & F_FLOOD)
             write_stdout("E", 1);
         else if(e->ee_errno != EMSGSIZE)
             error(0, e->ee_errno, "local error");
         else
             error(0, 0, "local error: message too long, mtu: %u", e->ee_info);
-        nerrors++;
+        a_ping_handle->ping_common.nerrors++;
     } else if(e->ee_origin == SO_EE_ORIGIN_ICMP6) {
         struct sockaddr_in6 *sin6 = (struct sockaddr_in6*) (e + 1);
 
         if((size_t) res < sizeof(icmph) ||
                 memcmp(&target.sin6_addr, &whereto.sin6_addr, 16) ||
                 icmph.icmp6_type != ICMP6_ECHO_REQUEST ||
-                !is_ours(sock, icmph.icmp6_id)) {
+                !is_ours(a_ping_handle, sock, icmph.icmp6_id)) {
             /* Not our error, not an error at all. Clear. */
             saved_errno = 0;
             goto out;
         }
 
         net_errors++;
-        nerrors++;
-        if(options & F_QUIET)
+        a_ping_handle->ping_common.nerrors++;
+        if(a_ping_handle->ping_common.options & F_QUIET)
             goto out;
-        if(options & F_FLOOD) {
+        if(a_ping_handle->ping_common.options & F_FLOOD) {
             write_stdout("\bE", 2);
         } else {
-            print_timestamp();
-            printf("From %s icmp_seq=%u ", pr_addr(sin6, sizeof *sin6), ntohs(icmph.icmp6_seq));
+            print_timestamp(a_ping_handle);
+            printf("From %s icmp_seq=%u ", pr_addr(a_ping_handle, sin6, sizeof *sin6), ntohs(icmph.icmp6_seq));
             pr_icmph(e->ee_type, e->ee_code, e->ee_info);
             putchar('\n');
             fflush(stdout);
@@ -952,7 +952,7 @@ int ping6_receive_error_msg(socket_st *sock)
  * of the data portion are used to hold a UNIX "timeval" struct in VAX
  * byte-order, to compute the round-trip time.
  */
-int build_echo(uint8_t *_icmph, unsigned packet_size __attribute__((__unused__)))
+static int build_echo(ping_handle_t *a_ping_handle, uint8_t *_icmph, unsigned packet_size __attribute__((__unused__)))
 {
     struct icmp6_hdr *icmph;
     int cc;
@@ -961,19 +961,19 @@ int build_echo(uint8_t *_icmph, unsigned packet_size __attribute__((__unused__))
     icmph->icmp6_type = ICMP6_ECHO_REQUEST;
     icmph->icmp6_code = 0;
     icmph->icmp6_cksum = 0;
-    icmph->icmp6_seq= htons(ntransmitted+1);
-    icmph->icmp6_id= ident;
+    icmph->icmp6_seq= htons(a_ping_handle->ping_common.ntransmitted+1);
+    icmph->icmp6_id= a_ping_handle->ping_common.ident;
 
-    if(timing)
+    if(a_ping_handle->ping_common.timing)
         gettimeofday((struct timeval *) &_icmph[8],
                 (struct timezone *) NULL);
 
-    cc = datalen + 8; /* skips ICMP portion */
+    cc = a_ping_handle->ping_common.datalen + 8; /* skips ICMP portion */
 
     return cc;
 }
 
-int build_niquery(uint8_t *_nih, unsigned packet_size __attribute__((__unused__)))
+static int build_niquery(ping_handle_t *a_ping_handle, uint8_t *_nih, unsigned packet_size __attribute__((__unused__)))
 {
     struct ni_hdr *nih;
     int cc;
@@ -983,9 +983,9 @@ int build_niquery(uint8_t *_nih, unsigned packet_size __attribute__((__unused__)
 
     nih->ni_type = ICMPV6_NI_QUERY;
     cc = sizeof(*nih);
-    datalen = 0;
+    a_ping_handle->ping_common.datalen = 0;
 
-    niquery_fill_nonce(ntransmitted + 1, nih->ni_nonce);
+    niquery_fill_nonce(a_ping_handle->ping_common.ntransmitted + 1, nih->ni_nonce);
     nih->ni_code = ni_subject_type;
     nih->ni_qtype= htons(ni_query);
     nih->ni_flags= ni_flag;
@@ -995,19 +995,19 @@ int build_niquery(uint8_t *_nih, unsigned packet_size __attribute__((__unused__)
     return cc;
 }
 
-int ping6_send_probe(socket_st *sock, void *packet, unsigned packet_size)
+int ping6_send_probe(ping_handle_t *a_ping_handle, socket_st *sock, void *packet, unsigned packet_size)
 {
     int len, cc;
 
-    rcvd_clear(ntransmitted + 1);
+    rcvd_clear(a_ping_handle, a_ping_handle->ping_common.ntransmitted + 1);
 
     if(niquery_is_enabled())
-        len = build_niquery(packet, packet_size);
+        len = build_niquery(a_ping_handle, packet, packet_size);
     else
-        len = build_echo(packet, packet_size);
+        len = build_echo(a_ping_handle, packet, packet_size);
 
     if(cmsglen == 0) {
-        cc = sendto(sock->fd, (char *) packet, len, confirm,
+        cc = sendto(sock->fd, (char *) packet, len, a_ping_handle->ping_common.confirm,
                 (struct sockaddr *) &whereto,
                 sizeof(struct sockaddr_in6));
     } else {
@@ -1025,9 +1025,9 @@ int ping6_send_probe(socket_st *sock, void *packet, unsigned packet_size)
         mhdr.msg_control = cmsgbuf;
         mhdr.msg_controllen = cmsglen;
 
-        cc = sendmsg(sock->fd, &mhdr, confirm);
+        cc = sendmsg(sock->fd, &mhdr, a_ping_handle->ping_common.confirm);
     }
-    confirm = 0;
+    a_ping_handle->ping_common.confirm = 0;
 
     return (cc == len ? 0 : cc);
 }
@@ -1184,7 +1184,7 @@ void pr_niquery_reply(uint8_t *_nih, int len)
  * program to be run without having intermingled output (or statistics!).
  */
 int
-ping6_parse_reply(socket_st *sock, struct msghdr *msg, int cc, void *addr, struct timeval *tv)
+ping6_parse_reply(ping_handle_t *a_ping_handle, socket_st *sock, struct msghdr *msg, int cc, void *addr, struct timeval *tv)
 {
     struct sockaddr_in6 *from = addr;
     uint8_t *buf = msg->msg_iov->iov_base;
@@ -1210,19 +1210,19 @@ ping6_parse_reply(socket_st *sock, struct msghdr *msg, int cc, void *addr, struc
 
     icmph = (struct icmp6_hdr *) buf;
     if(cc < 8) {
-        if(options & F_VERBOSE)
+        if(a_ping_handle->ping_common.options & F_VERBOSE)
             error(0, 0, "packet too short: %d bytes", cc);
         return 1;
     }
 
     if(icmph->icmp6_type == ICMP6_ECHO_REPLY) {
-        if(!is_ours(sock, icmph->icmp6_id))
+        if(!is_ours(a_ping_handle, sock, icmph->icmp6_id))
         return 1;
-        if (!contains_pattern_in_payload((uint8_t*)(icmph+1)))
+        if (!contains_pattern_in_payload(a_ping_handle, (uint8_t*)(icmph+1)))
         return 1; /* 'Twas really not our ECHO */
-        if (gather_statistics((uint8_t*)icmph, sizeof(*icmph), cc,
+        if (gather_statistics(a_ping_handle, (uint8_t*)icmph, sizeof(*icmph), cc,
                 ntohs(icmph->icmp6_seq),
-                hops, 0, tv, pr_addr(from, sizeof *from),
+                hops, 0, tv, pr_addr(a_ping_handle, from, sizeof *from),
                 pr_echo_reply)) {
             fflush(stdout);
             return 0;
@@ -1232,9 +1232,9 @@ ping6_parse_reply(socket_st *sock, struct msghdr *msg, int cc, void *addr, struc
         int seq = niquery_check_nonce(nih->ni_nonce);
         if (seq < 0)
         return 1;
-        if (gather_statistics((uint8_t*)icmph, sizeof(*icmph), cc,
+        if (gather_statistics(a_ping_handle, (uint8_t*)icmph, sizeof(*icmph), cc,
                 seq,
-                hops, 0, tv, pr_addr(from, sizeof *from),
+                hops, 0, tv, pr_addr(a_ping_handle, from, sizeof *from),
                 pr_niquery_reply))
         return 0;
     } else {
@@ -1263,32 +1263,32 @@ ping6_parse_reply(socket_st *sock, struct msghdr *msg, int cc, void *addr, struc
         }
         if (nexthdr == IPPROTO_ICMPV6) {
             if (icmph1->icmp6_type != ICMP6_ECHO_REQUEST ||
-            !is_ours(sock, icmph1->icmp6_id))
+            !is_ours(a_ping_handle, sock, icmph1->icmp6_id))
             return 1;
-            acknowledge(ntohs(icmph1->icmp6_seq));
-            nerrors++;
-            if (options & F_FLOOD) {
+            acknowledge(a_ping_handle, ntohs(icmph1->icmp6_seq));
+            a_ping_handle->ping_common.nerrors++;
+            if (a_ping_handle->ping_common.options & F_FLOOD) {
                 write_stdout("\bE", 2);
                 return 0;
             }
-            print_timestamp();
-            printf("From %s: icmp_seq=%u ", pr_addr(from, sizeof *from), ntohs(icmph1->icmp6_seq));
+            print_timestamp(a_ping_handle);
+            printf("From %s: icmp_seq=%u ", pr_addr(a_ping_handle, from, sizeof *from), ntohs(icmph1->icmp6_seq));
         } else {
             /* We've got something other than an ECHOREPLY */
-            if (!(options & F_VERBOSE) || uid)
+            if (!(a_ping_handle->ping_common.options & F_VERBOSE) || a_ping_handle->ping_common.uid)
             return 1;
-            print_timestamp();
-            printf("From %s: ", pr_addr(from, sizeof *from));
+            print_timestamp(a_ping_handle);
+            printf("From %s: ", pr_addr(a_ping_handle, from, sizeof *from));
         }
         pr_icmph(icmph->icmp6_type, icmph->icmp6_code, ntohl(icmph->icmp6_mtu));
     }
 
-    if(options & F_AUDIBLE) {
+    if(a_ping_handle->ping_common.options & F_AUDIBLE) {
         putchar('\a');
-        if(options & F_FLOOD)
+        if(a_ping_handle->ping_common.options & F_FLOOD)
             fflush(stdout);
     }
-    if(!(options & F_FLOOD)) {
+    if(!(a_ping_handle->ping_common.options & F_FLOOD)) {
         putchar('\n');
         fflush(stdout);
     }
@@ -1369,7 +1369,7 @@ int pr_icmph(uint8_t type, uint8_t code, uint32_t info)
     return 0;
 }
 
-void ping6_install_filter(socket_st *sock)
+void ping6_install_filter(ping_handle_t *a_ping_handle, socket_st *sock)
 {
     static int once;
     static struct sock_filter insns[] = {
@@ -1391,7 +1391,7 @@ void ping6_install_filter(socket_st *sock)
     once = 1;
 
     /* Patch bpflet for current identifier. */
-    insns[1] = (struct sock_filter )BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(ident), 0, 1);
+    insns[1] = (struct sock_filter )BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(a_ping_handle->ping_common.ident), 0, 1);
 
     if(setsockopt(sock->fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
         error(0, errno, "WARNING: failed to install socket filter");
diff --git a/iputils/ping_common.c b/iputils/ping_common.c
index 4f84eb4434ecc733cfb05b2ec5688e84d29b1f95..566fdc755ee685ccff49f24f34d3450fb8590779 100644
--- a/iputils/ping_common.c
+++ b/iputils/ping_common.c
@@ -36,6 +36,7 @@
 #define HZ sysconf(_SC_CLK_TCK)
 #endif
 
+/*
 int options;
 
 int mark;
@@ -48,39 +49,45 @@ uint16_t acked;
 unsigned char outpack[MAXPACKET];
 struct rcvd_table rcvd_tbl;
 
-/* counters */
-long npackets; /* max packets to transmit */
-long nreceived; /* # of packets we got back */
-long nrepeats; /* number of duplicates */
-long ntransmitted; /* sequence # for outbound packets = #sent */
-long nchecksum; /* replies with bad checksum */
-long nerrors; /* icmp errors */
-int interval = 1000; /* interval between packets (msec) */
+// counters
+long npackets; // max packets to transmit
+long nreceived; // # of packets we got back
+long nrepeats; // number of duplicates
+long ntransmitted; // sequence # for outbound packets = #sent
+long nchecksum; // replies with bad checksum
+long nerrors; // icmp errors
+int interval = 1000; // interval between packets (msec)
 int preload = 1;
-int deadline = 0; /* time to die */
+int deadline = 0; // time to die
 int lingertime = MAXWAIT * 1000;
 struct timeval start_time, cur_time;
-volatile int exiting;
-volatile int status_snapshot;
 int confirm = 0;
-volatile int in_pr_addr = 0; /* pr_addr() is executing */
+volatile int in_pr_addr = 0; // pr_addr() is executing
 jmp_buf pr_addr_jmp;
+*/
+
+volatile int exiting;
+volatile int status_snapshot;
 
 /* Stupid workarounds for bugs/missing functionality in older linuces.
  * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
  * i.e. for linux-2.2 */
+/*
+
 int confirm_flag = MSG_CONFIRM;
 
-/* timing */
-int timing; /* flag to do timing */
-long tmin = LONG_MAX; /* minimum round trip time */
-long tmax; /* maximum round trip time */
+// timing
+int timing; // flag to do timing
+long tmin = LONG_MAX; // minimum round trip time
+long tmax; // maximum round trip time
+*/
 /* Message for rpm maintainers: have _shame_. If you want
  * to fix something send the patch to me for sanity checking.
  * "sparcfix" patch is a complete non-sense, apparenly the person
  * prepared it was stoned.
  */
-long long tsum; /* sum of all times, for doing average */
+/*
+long long tsum; // sum of all times, for doing average
 long long tsum2;
 int pipesize = -1;
 
@@ -89,16 +96,18 @@ int datalen = DEFDATALEN;
 char *hostname;
 int uid;
 uid_t euid;
-int ident; /* process id to identify our packets */
+int ident; // process id to identify our packets
 
 static int screen_width = INT_MAX;
 
-#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
-
 #ifdef HAVE_LIBCAP
 static cap_value_t cap_raw = CAP_NET_RAW;
 static cap_value_t cap_admin = CAP_NET_ADMIN;
 #endif
+*/
+
+#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
+
 
 void usage(void)
 {
@@ -149,7 +158,7 @@ void usage(void)
     exit(2);
 }
 
-void limit_capabilities(void)
+void limit_capabilities(ping_handle_t *a_ping_handle)
 {
 #ifdef HAVE_LIBCAP
     cap_t cap_cur_p;
@@ -181,10 +190,10 @@ void limit_capabilities(void)
     cap_free(cap_p);
     cap_free(cap_cur_p);
 #endif
-    uid = getuid();
-    euid = geteuid();
+    a_ping_handle->ping_common.uid = getuid();
+    a_ping_handle->ping_common.euid = geteuid();
 #ifndef HAVE_LIBCAP
-    if(seteuid(uid))
+    if(seteuid(a_ping_handle->ping_common.uid))
         error(-1, errno, "setuid");
 #endif
 }
@@ -225,9 +234,9 @@ int modify_capability(cap_value_t cap, cap_flag_value_t on)
     return rc;
 }
 #else
-int modify_capability(int on)
+int modify_capability(ping_handle_t *a_ping_handle, int on)
 {
-    if(seteuid(on ? euid : getuid())) {
+    if(seteuid(on ? a_ping_handle->ping_common.euid : getuid())) {
         error(0, errno, "seteuid");
         return -1;
     }
@@ -252,7 +261,7 @@ void drop_capabilities(void)
 /* Fills all the outpack, excluding ICMP header, but _including_
  * timestamp area with supplied pattern.
  */
-void fill(char *patp, unsigned char *packet, unsigned packet_size)
+void fill(ping_handle_t *a_ping_handle, char *patp, unsigned char *packet, unsigned packet_size)
 {
     int ii, jj;
     unsigned int pat[16];
@@ -279,7 +288,7 @@ void fill(char *patp, unsigned char *packet, unsigned packet_size)
             for(jj = 0; jj < ii; ++jj)
                 bp[jj + kk] = pat[jj];
     }
-    if(!(options & F_QUIET)) {
+    if(!(a_ping_handle->ping_common.options & F_QUIET)) {
         printf("PATTERN: 0x");
         for(jj = 0; jj < ii; ++jj)
             printf("%02x", bp[jj] & 0xFF);
@@ -293,17 +302,17 @@ void fill(char *patp, unsigned char *packet, unsigned packet_size)
 
 static void sigexit(int signo __attribute__((__unused__)))
 {
-    exiting = 1;
-    if(in_pr_addr)
-        longjmp(pr_addr_jmp, 0);
+    //exiting = 1;
+    //if(in_pr_addr)
+    //    longjmp(pr_addr_jmp, 0);
 }
 
 static void sigstatus(int signo __attribute__((__unused__)))
 {
-    status_snapshot = 1;
+    //status_snapshot = 1;
 }
 
-int __schedule_exit(int next)
+int __schedule_exit(ping_handle_t *a_ping_handle, int next)
 {
     static unsigned long waittime;
     struct itimerval it;
@@ -311,12 +320,12 @@ int __schedule_exit(int next)
     if(waittime)
         return next;
 
-    if(nreceived) {
-        waittime = 2 * tmax;
-        if(waittime < (unsigned long) (1000 * interval))
-            waittime = 1000 * interval;
+    if(a_ping_handle->ping_common.nreceived) {
+        waittime = 2 * a_ping_handle->ping_common.tmax;
+        if(waittime < (unsigned long) (1000 * a_ping_handle->ping_common.interval))
+            waittime = 1000 * a_ping_handle->ping_common.interval;
     } else
-        waittime = lingertime * 1000;
+        waittime = a_ping_handle->ping_common.lingertime * 1000;
 
     if(next < 0 || (unsigned long) next < waittime / 1000)
         next = waittime / 1000;
@@ -329,21 +338,21 @@ int __schedule_exit(int next)
     return next;
 }
 
-static inline void update_interval(void)
+static inline void update_interval(ping_handle_t *a_ping_handle)
 {
-    int est = rtt ? rtt / 8 : interval * 1000;
+    int est = a_ping_handle->ping_common.rtt ? a_ping_handle->ping_common.rtt / 8 : a_ping_handle->ping_common.interval * 1000;
 
-    interval = (est + rtt_addend + 500) / 1000;
-    if(uid && interval < MINUSERINTERVAL)
-        interval = MINUSERINTERVAL;
+    a_ping_handle->ping_common.interval = (est + a_ping_handle->ping_common.rtt_addend + 500) / 1000;
+    if(a_ping_handle->ping_common.uid && a_ping_handle->ping_common.interval < MINUSERINTERVAL)
+        a_ping_handle->ping_common.interval = MINUSERINTERVAL;
 }
 
 /*
  * Print timestamp
  */
-void print_timestamp(void)
+void print_timestamp(ping_handle_t *a_ping_handle)
 {
-    if(options & F_PTIMEOFDAY) {
+    if(a_ping_handle->ping_common.options & F_PTIMEOFDAY) {
         struct timeval tv;
         gettimeofday(&tv, NULL);
         printf("[%lu.%06lu] ",
@@ -359,65 +368,65 @@ void print_timestamp(void)
  * of the data portion are used to hold a UNIX "timeval" struct in VAX
  * byte-order, to compute the round-trip time.
  */
-int pinger(ping_func_set_st *fset, socket_st *sock)
+int pinger(ping_handle_t *a_ping_handle, ping_func_set_st *fset, socket_st *sock)
 {
     static int oom_count;
     static int tokens;
     int i;
 
     /* Have we already sent enough? If we have, return an arbitrary positive value. */
-    if(exiting || (npackets && ntransmitted >= npackets && !deadline))
+    if(exiting || (a_ping_handle->ping_common.npackets && a_ping_handle->ping_common.ntransmitted >= a_ping_handle->ping_common.npackets && !a_ping_handle->ping_common.deadline))
         return 1000;
 
     /* Check that packets < rate*time + preload */
-    if(cur_time.tv_sec == 0) {
-        gettimeofday(&cur_time, NULL);
-        tokens = interval * (preload - 1);
+    if(a_ping_handle->ping_common.cur_time.tv_sec == 0) {
+        gettimeofday(&a_ping_handle->ping_common.cur_time, NULL);
+        tokens = a_ping_handle->ping_common.interval * (a_ping_handle->ping_common.preload - 1);
     } else {
         long ntokens;
         struct timeval tv;
 
         gettimeofday(&tv, NULL);
-        ntokens = (tv.tv_sec - cur_time.tv_sec) * 1000 +
-                (tv.tv_usec - cur_time.tv_usec) / 1000;
-        if(!interval) {
+        ntokens = (tv.tv_sec - a_ping_handle->ping_common.cur_time.tv_sec) * 1000 +
+                (tv.tv_usec - a_ping_handle->ping_common.cur_time.tv_usec) / 1000;
+        if(!a_ping_handle->ping_common.interval) {
             /* Case of unlimited flood is special;
              * if we see no reply, they are limited to 100pps */
-            if(ntokens < MININTERVAL && in_flight() >= preload)
+            if(ntokens < MININTERVAL && in_flight(a_ping_handle) >= a_ping_handle->ping_common.preload)
                 return MININTERVAL - ntokens;
         }
         ntokens += tokens;
-        if(ntokens > interval * preload)
-            ntokens = interval * preload;
-        if(ntokens < interval)
-            return interval - ntokens;
+        if(ntokens > a_ping_handle->ping_common.interval * a_ping_handle->ping_common.preload)
+            ntokens = a_ping_handle->ping_common.interval * a_ping_handle->ping_common.preload;
+        if(ntokens < a_ping_handle->ping_common.interval)
+            return a_ping_handle->ping_common.interval - ntokens;
 
-        cur_time = tv;
-        tokens = ntokens - interval;
+        a_ping_handle->ping_common.cur_time = tv;
+        tokens = ntokens - a_ping_handle->ping_common.interval;
     }
 
-    if(options & F_OUTSTANDING) {
-        if(ntransmitted > 0 && !rcvd_test(ntransmitted)) {
-            print_timestamp();
-            printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK));
+    if(a_ping_handle->ping_common.options & F_OUTSTANDING) {
+        if(a_ping_handle->ping_common.ntransmitted > 0 && !rcvd_test(a_ping_handle, a_ping_handle->ping_common.ntransmitted)) {
+            print_timestamp(a_ping_handle);
+            printf("no answer yet for icmp_seq=%lu\n", (a_ping_handle->ping_common.ntransmitted % MAX_DUP_CHK));
             fflush(stdout);
         }
     }
 
     resend:
-    i = fset->send_probe(sock, outpack, sizeof(outpack));
+    i = fset->send_probe(a_ping_handle, sock, a_ping_handle->ping_common.outpack, sizeof(a_ping_handle->ping_common.outpack));
 
     if(i == 0) {
         oom_count = 0;
-        advance_ntransmitted();
-        if(!(options & F_QUIET) && (options & F_FLOOD)) {
+        advance_ntransmitted(a_ping_handle);
+        if(!(a_ping_handle->ping_common.options & F_QUIET) && (a_ping_handle->ping_common.options & F_FLOOD)) {
             /* Very silly, but without this output with
              * high preload or pipe size is very confusing. */
-            if((preload < screen_width && pipesize < screen_width) ||
-                    in_flight() < screen_width)
+            if((a_ping_handle->ping_common.preload < a_ping_handle->ping_common.screen_width && a_ping_handle->ping_common.pipesize < a_ping_handle->ping_common.screen_width) ||
+                    in_flight(a_ping_handle) < a_ping_handle->ping_common.screen_width)
                 write_stdout(".", 1);
         }
-        return interval - tokens;
+        return a_ping_handle->ping_common.interval - tokens;
     }
 
     /* And handle various errors... */
@@ -430,14 +439,14 @@ int pinger(ping_func_set_st *fset, socket_st *sock)
         /* Device queue overflow or OOM. Packet is not sent. */
         tokens = 0;
         /* Slowdown. This works only in adaptive mode (option -A) */
-        rtt_addend += (rtt < 8 * 50000 ? rtt / 8 : 50000);
-        if(options & F_ADAPTIVE)
-            update_interval();
-        nores_interval = SCHINT(interval / 2);
+        a_ping_handle->ping_common.rtt_addend += (a_ping_handle->ping_common.rtt < 8 * 50000 ? a_ping_handle->ping_common.rtt / 8 : 50000);
+        if(a_ping_handle->ping_common.options & F_ADAPTIVE)
+            update_interval(a_ping_handle);
+        nores_interval = SCHINT(a_ping_handle->ping_common.interval / 2);
         if(nores_interval > 500)
             nores_interval = 500;
         oom_count++;
-        if(oom_count * nores_interval < lingertime)
+        if(oom_count * nores_interval < a_ping_handle->ping_common.lingertime)
             return nores_interval;
         i = 0;
         /* Fall to hard error. It is to avoid complete deadlock
@@ -446,10 +455,10 @@ int pinger(ping_func_set_st *fset, socket_st *sock)
          * exit some day. :-) */
     } else if(errno == EAGAIN) {
         /* Socket buffer is full. */
-        tokens += interval;
+        tokens += a_ping_handle->ping_common.interval;
         return MININTERVAL;
     } else {
-        if((i = fset->receive_error_msg(sock)) > 0) {
+        if((i = fset->receive_error_msg(a_ping_handle, sock)) > 0) {
             /* An ICMP error arrived. In this case, we've received
              * an error from sendto(), but we've also received an
              * ICMP message, which means the packet did in fact
@@ -460,8 +469,8 @@ int pinger(ping_func_set_st *fset, socket_st *sock)
             goto hard_local_error;
         }
         /* Compatibility with old linuces. */
-        if(i == 0 && confirm_flag && errno == EINVAL) {
-            confirm_flag = 0;
+        if(i == 0 && a_ping_handle->ping_common.confirm_flag && errno == EINVAL) {
+            a_ping_handle->ping_common.confirm_flag = 0;
             errno = 0;
         }
         if(!errno)
@@ -470,30 +479,30 @@ int pinger(ping_func_set_st *fset, socket_st *sock)
 
     hard_local_error:
     /* Hard local error. Pretend we sent packet. */
-    advance_ntransmitted();
+    advance_ntransmitted(a_ping_handle);
 
-    if(i == 0 && !(options & F_QUIET)) {
-        if(options & F_FLOOD)
+    if(i == 0 && !(a_ping_handle->ping_common.options & F_QUIET)) {
+        if(a_ping_handle->ping_common.options & F_FLOOD)
             write_stdout("E", 1);
         else
             perror("ping: sendmsg");
     }
     tokens = 0;
-    return SCHINT(interval);
+    return SCHINT(a_ping_handle->ping_common.interval);
 }
 
 /* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
 
-void sock_setbufs(socket_st *sock, int alloc)
+void sock_setbufs(ping_handle_t *a_ping_handle, socket_st *sock, int alloc)
 {
     int rcvbuf, hold;
     socklen_t tmplen = sizeof(hold);
 
-    if(!sndbuf)
-        sndbuf = alloc;
-    setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF, (char *) &sndbuf, sizeof(sndbuf));
+    if(!a_ping_handle->ping_common.sndbuf)
+        a_ping_handle->ping_common.sndbuf = alloc;
+    setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF, (char *) &a_ping_handle->ping_common.sndbuf, sizeof(a_ping_handle->ping_common.sndbuf));
 
-    rcvbuf = hold = alloc * preload;
+    rcvbuf = hold = alloc * a_ping_handle->ping_common.preload;
     if(hold < 65536)
         hold = 65536;
     setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, (char *) &hold, sizeof(hold));
@@ -505,49 +514,49 @@ void sock_setbufs(socket_st *sock, int alloc)
 
 /* Protocol independent setup and parameter checks. */
 
-void setup(socket_st *sock)
+void setup(ping_handle_t *a_ping_handle, socket_st *sock)
 {
     int hold;
     struct timeval tv;
     sigset_t sset;
 
-    if((options & F_FLOOD) && !(options & F_INTERVAL))
-        interval = 0;
+    if((a_ping_handle->ping_common.options & F_FLOOD) && !(a_ping_handle->ping_common.options & F_INTERVAL))
+        a_ping_handle->ping_common.interval = 0;
 
-    if(uid && interval < MINUSERINTERVAL)
+    if(a_ping_handle->ping_common.uid && a_ping_handle->ping_common.interval < MINUSERINTERVAL)
         error(2, 0, "cannot flood; minimal interval allowed for user is %dms", MINUSERINTERVAL);
 
-    if(interval >= INT_MAX / preload)
-        error(2, 0, "illegal preload and/or interval: %d", interval);
+    if(a_ping_handle->ping_common.interval >= INT_MAX / a_ping_handle->ping_common.preload)
+        error(2, 0, "illegal preload and/or interval: %d", a_ping_handle->ping_common.interval);
 
     hold = 1;
-    if(options & F_SO_DEBUG)
+    if(a_ping_handle->ping_common.options & F_SO_DEBUG)
         setsockopt(sock->fd, SOL_SOCKET, SO_DEBUG, (char *) &hold, sizeof(hold));
-    if(options & F_SO_DONTROUTE)
+    if(a_ping_handle->ping_common.options & F_SO_DONTROUTE)
         setsockopt(sock->fd, SOL_SOCKET, SO_DONTROUTE, (char *) &hold, sizeof(hold));
 
 #ifdef SO_TIMESTAMP
-    if(!(options & F_LATENCY)) {
+    if(!(a_ping_handle->ping_common.options & F_LATENCY)) {
         int on = 1;
         if(setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
             error(0, 0, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP");
     }
 #endif
 #ifdef SO_MARK
-    if(options & F_MARK) {
+    if(a_ping_handle->ping_common.options & F_MARK) {
         int ret;
         int errno_save;
 
-        enable_capability_admin();
-        ret = setsockopt(sock->fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
+        enable_capability_admin(a_ping_handle);
+        ret = setsockopt(sock->fd, SOL_SOCKET, SO_MARK, &a_ping_handle->ping_common.mark, sizeof(a_ping_handle->ping_common.mark));
         errno_save = errno;
-        disable_capability_admin();
+        disable_capability_admin(a_ping_handle);
 
         if(ret == -1) {
             /* we probably dont wanna exit since old kernels
              * dont support mark ..
              */
-            error(0, errno_save, "Warning: Failed to set mark: %d", mark);
+            error(0, errno_save, "Warning: Failed to set mark: %d", a_ping_handle->ping_common.mark);
         }
     }
 #endif
@@ -558,32 +567,32 @@ void setup(socket_st *sock)
      */
     tv.tv_sec = 1;
     tv.tv_usec = 0;
-    if(interval < 1000) {
+    if(a_ping_handle->ping_common.interval < 1000) {
         tv.tv_sec = 0;
-        tv.tv_usec = 1000 * SCHINT(interval);
+        tv.tv_usec = 1000 * SCHINT(a_ping_handle->ping_common.interval);
     }
     setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (char*) &tv, sizeof(tv));
 
     /* Set RCVTIMEO to "interval". Note, it is just an optimization
      * allowing to avoid redundant poll(). */
-    tv.tv_sec = SCHINT(interval) / 1000;
-    tv.tv_usec = 1000 * (SCHINT(interval) % 1000);
+    tv.tv_sec = SCHINT(a_ping_handle->ping_common.interval) / 1000;
+    tv.tv_usec = 1000 * (SCHINT(a_ping_handle->ping_common.interval) % 1000);
     if(setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (char*) &tv, sizeof(tv)))
-        options |= F_FLOOD_POLL;
+        a_ping_handle->ping_common.options |= F_FLOOD_POLL;
 
-    if(!(options & F_PINGFILLED)) {
+    if(!(a_ping_handle->ping_common.options & F_PINGFILLED)) {
         int i;
-        unsigned char *p = outpack + 8;
+        unsigned char *p = a_ping_handle->ping_common.outpack + 8;
 
         /* Do not forget about case of small datalen,
          * fill timestamp area too!
          */
-        for(i = 0; i < datalen; ++i)
+        for(i = 0; i < a_ping_handle->ping_common.datalen; ++i)
             *p++ = i;
     }
 
     if(sock->socktype == SOCK_RAW)
-        ident = htons(getpid() & 0xFFFF);
+        a_ping_handle->ping_common.ident = htons(getpid() & 0xFFFF);
 
     set_signal(SIGINT, sigexit);
     set_signal(SIGALRM, sigexit);
@@ -592,14 +601,14 @@ void setup(socket_st *sock)
     sigemptyset(&sset);
     sigprocmask(SIG_SETMASK, &sset, NULL);
 
-    gettimeofday(&start_time, NULL);
+    gettimeofday(&a_ping_handle->ping_common.start_time, NULL);
 
-    if(deadline) {
+    if(a_ping_handle->ping_common.deadline) {
         struct itimerval it;
 
         it.it_interval.tv_sec = 0;
         it.it_interval.tv_usec = 0;
-        it.it_value.tv_sec = deadline;
+        it.it_value.tv_sec = a_ping_handle->ping_common.deadline;
         it.it_value.tv_usec = 0;
         setitimer(ITIMER_REAL, &it, NULL);
     }
@@ -609,7 +618,7 @@ void setup(socket_st *sock)
 
         if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
             if(w.ws_col > 0)
-                screen_width = w.ws_col;
+                a_ping_handle->ping_common.screen_width = w.ws_col;
         }
     }
 }
@@ -617,22 +626,22 @@ void setup(socket_st *sock)
 /*
  * Return 0 if pattern in payload point to be ptr did not match the pattern that was sent  
  */
-int contains_pattern_in_payload(uint8_t *ptr)
+int contains_pattern_in_payload(ping_handle_t *a_ping_handle, uint8_t *ptr)
 {
     int i;
     uint8_t *cp, *dp;
 
     /* check the data */
     cp = ((u_char*) ptr) + sizeof(struct timeval);
-    dp = &outpack[8 + sizeof(struct timeval)];
-    for(i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
+    dp = &a_ping_handle->ping_common.outpack[8 + sizeof(struct timeval)];
+    for(i = sizeof(struct timeval); i < a_ping_handle->ping_common.datalen; ++i, ++cp, ++dp) {
         if(*cp != *dp)
             return 0;
     }
     return 1;
 }
 
-void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int packlen)
+void main_loop(ping_handle_t *a_ping_handle, ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int packlen)
 {
     char addrbuf[128];
     char ans_data[4096];
@@ -650,18 +659,18 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
         /* Check exit conditions. */
         if(exiting)
             break;
-        if(npackets && nreceived + nerrors >= npackets)
+        if(a_ping_handle->ping_common.npackets && a_ping_handle->ping_common.nreceived + a_ping_handle->ping_common.nerrors >= a_ping_handle->ping_common.npackets)
             break;
-        if(deadline && nerrors)
+        if(a_ping_handle->ping_common.deadline && a_ping_handle->ping_common.nerrors)
             break;
         /* Check for and do special actions. */
         if(status_snapshot)
-            status();
+            status(a_ping_handle);
 
         /* Send probes scheduled to this time. */
         do {
-            next = pinger(fset, sock);
-            next = schedule_exit(next);
+            next = pinger(a_ping_handle, fset, sock);
+            next = schedule_exit(a_ping_handle, next);
         } while(next <= 0);
 
         /* "next" is time to send next probe, if positive.
@@ -676,8 +685,8 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
          *    timed waiting (SO_RCVTIMEO). */
         polling = 0;
         recv_error = 0;
-        if((options & (F_ADAPTIVE | F_FLOOD_POLL)) || next < SCHINT(interval)) {
-            int recv_expected = in_flight();
+        if((a_ping_handle->ping_common.options & (F_ADAPTIVE | F_FLOOD_POLL)) || next < SCHINT(a_ping_handle->ping_common.interval)) {
+            int recv_expected = in_flight(a_ping_handle);
 
             /* If we are here, recvmsg() is unable to wait for
              * required timeout. */
@@ -698,7 +707,7 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
             }
 
             if(!polling &&
-                    ((options & (F_ADAPTIVE | F_FLOOD_POLL)) || interval)) {
+                    ((a_ping_handle->ping_common.options & (F_ADAPTIVE | F_FLOOD_POLL)) || a_ping_handle->ping_common.interval)) {
                 struct pollfd pset;
                 pset.fd = sock->fd;
                 pset.events = POLLIN;
@@ -727,6 +736,7 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
             msg.msg_controllen = sizeof(ans_data);
 
             cc = recvmsg(sock->fd, &msg, polling);
+            //log_printf("**recvmsg(fd=%d,msg=0x%x,polling=%d)=%d\n",sock->fd,&msg,polling,cc);
             polling = MSG_DONTWAIT;
 
             if(cc < 0) {
@@ -738,7 +748,7 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
                 errno == EINTR)
                     break;
                 recv_error = 0;
-                if(!fset->receive_error_msg(sock)) {
+                if(!fset->receive_error_msg(a_ping_handle, sock)) {
                     if(errno) {
                         error(0, errno, "recvmsg");
                         break;
@@ -758,21 +768,21 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
                 }
 #endif
 
-                if((options & F_LATENCY) || recv_timep == NULL) {
-                    if((options & F_LATENCY) ||
+                if((a_ping_handle->ping_common.options & F_LATENCY) || recv_timep == NULL) {
+                    if((a_ping_handle->ping_common.options & F_LATENCY) ||
                             ioctl(sock->fd, SIOCGSTAMP, &recv_time))
                         gettimeofday(&recv_time, NULL);
                     recv_timep = &recv_time;
                 }
-                not_ours = fset->parse_reply(sock, &msg, cc, addrbuf, recv_timep);
+                not_ours = fset->parse_reply(a_ping_handle, sock, &msg, cc, addrbuf, recv_timep);
             }
 
             /* See? ... someone runs another ping on this host. */
             if(not_ours && sock->socktype == SOCK_RAW)
-                fset->install_filter(sock);
+                fset->install_filter(a_ping_handle, sock);
 
             /* If nothing is in flight, "break" returns us to pinger. */
-            if(in_flight() == 0)
+            if(in_flight(a_ping_handle) == 0)
                 break;
 
             /* Otherwise, try to recvmsg() again. recvmsg()
@@ -782,10 +792,10 @@ void main_loop(ping_func_set_st *fset, socket_st *sock, uint8_t *packet, int pac
         }
     }
     // here present exit() from app
-    finish();
+    finish(a_ping_handle);
 }
 
-int gather_statistics(uint8_t *icmph, int icmplen,
+int gather_statistics(ping_handle_t *a_ping_handle, uint8_t *icmph, int icmplen,
         int cc, uint16_t seq, int hops,
         int csfailed, struct timeval *tv, char *from,
         void (*pr_reply)(uint8_t *icmph, int cc))
@@ -794,11 +804,11 @@ int gather_statistics(uint8_t *icmph, int icmplen,
     long triptime = 0;
     uint8_t *ptr = icmph + icmplen;
 
-    ++nreceived;
+    ++a_ping_handle->ping_common.nreceived;
     if(!csfailed)
-        acknowledge(seq);
+        acknowledge(a_ping_handle, seq);
 
-    if(timing && cc >= (int) (8 + sizeof(struct timeval))) {
+    if(a_ping_handle->ping_common.timing && cc >= (int) (8 + sizeof(struct timeval))) {
         struct timeval tmp_tv;
         memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
 
@@ -808,45 +818,45 @@ int gather_statistics(uint8_t *icmph, int icmplen,
         if(triptime < 0) {
             error(0, 0, "Warning: time of day goes back (%ldus), taking countermeasures", triptime);
             triptime = 0;
-            if(!(options & F_LATENCY)) {
+            if(!(a_ping_handle->ping_common.options & F_LATENCY)) {
                 gettimeofday(tv, NULL);
-                options |= F_LATENCY;
+                a_ping_handle->ping_common.options |= F_LATENCY;
                 goto restamp;
             }
         }
         if(!csfailed) {
-            tsum += triptime;
-            tsum2 += (long long) triptime * (long long) triptime;
-            if(triptime < tmin)
-                tmin = triptime;
-            if(triptime > tmax)
-                tmax = triptime;
-            if(!rtt)
-                rtt = triptime * 8;
+            a_ping_handle->ping_common.tsum += triptime;
+            a_ping_handle->ping_common.tsum2 += (long long) triptime * (long long) triptime;
+            if(triptime < a_ping_handle->ping_common.tmin)
+                a_ping_handle->ping_common.tmin = triptime;
+            if(triptime > a_ping_handle->ping_common.tmax)
+                a_ping_handle->ping_common.tmax = triptime;
+            if(!a_ping_handle->ping_common.rtt)
+                a_ping_handle->ping_common.rtt = triptime * 8;
             else
-                rtt += triptime - rtt / 8;
-            if(options & F_ADAPTIVE)
-                update_interval();
+                a_ping_handle->ping_common.rtt += triptime - a_ping_handle->ping_common.rtt / 8;
+            if(a_ping_handle->ping_common.options & F_ADAPTIVE)
+                update_interval(a_ping_handle);
         }
     }
 
     if(csfailed) {
-        ++nchecksum;
-        --nreceived;
-    } else if(rcvd_test(seq)) {
-        ++nrepeats;
-        --nreceived;
+        ++a_ping_handle->ping_common.nchecksum;
+        --a_ping_handle->ping_common.nreceived;
+    } else if(rcvd_test(a_ping_handle, seq)) {
+        ++a_ping_handle->ping_common.nrepeats;
+        --a_ping_handle->ping_common.nreceived;
         dupflag = 1;
     } else {
-        rcvd_set(seq);
+        rcvd_set(a_ping_handle, seq);
         dupflag = 0;
     }
-    confirm = confirm_flag;
+    a_ping_handle->ping_common.confirm = a_ping_handle->ping_common.confirm_flag;
 
-    if(options & F_QUIET)
+    if(a_ping_handle->ping_common.options & F_QUIET)
         return 1;
 
-    if(options & F_FLOOD) {
+    if(a_ping_handle->ping_common.options & F_FLOOD) {
         if(!csfailed)
             write_stdout("\b \b", 3);
         else
@@ -855,7 +865,7 @@ int gather_statistics(uint8_t *icmph, int icmplen,
         int i;
         uint8_t *cp, *dp;
 
-        print_timestamp();
+        print_timestamp(a_ping_handle);
         log_printf("%d bytes from %s:", cc, from);
 
         if(pr_reply)
@@ -864,11 +874,11 @@ int gather_statistics(uint8_t *icmph, int icmplen,
         if(hops >= 0)
             log_printf(" ttl=%d", hops);
 
-        if(cc < datalen + 8) {
+        if(cc < a_ping_handle->ping_common.datalen + 8) {
             log_printf(" (truncated)\n");
             return 1;
         }
-        if(timing) {
+        if(a_ping_handle->ping_common.timing) {
             if(triptime >= 100000)
                 log_printf(" time=%ld ms", (triptime + 500) / 1000);
             else if(triptime >= 10000)
@@ -880,7 +890,7 @@ int gather_statistics(uint8_t *icmph, int icmplen,
             else
                 log_printf(" time=%ld.%03ld ms", triptime / 1000,
                         triptime % 1000);
-            log_printf(" tsum=%d ", tsum);
+            log_printf(" tsum=%d ", a_ping_handle->ping_common.tsum);
         }
         if(dupflag)
             log_printf(" (DUP!)");
@@ -889,13 +899,13 @@ int gather_statistics(uint8_t *icmph, int icmplen,
 
         /* check the data */
         cp = ((unsigned char*) ptr) + sizeof(struct timeval);
-        dp = &outpack[8 + sizeof(struct timeval)];
-        for(i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
+        dp = &a_ping_handle->ping_common.outpack[8 + sizeof(struct timeval)];
+        for(i = sizeof(struct timeval); i < a_ping_handle->ping_common.datalen; ++i, ++cp, ++dp) {
             if(*cp != *dp) {
                 log_printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
                         i, *dp, *cp);
                 cp = (unsigned char*) ptr + sizeof(struct timeval);
-                for(i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
+                for(i = sizeof(struct timeval); i < a_ping_handle->ping_common.datalen; ++i, ++cp) {
                     if((i % 32) == sizeof(struct timeval))
                         log_printf("\n#%d\t", i);
                     log_printf("%x ", *cp);
@@ -927,14 +937,14 @@ static long llsqrt(long long a)
  * finish --
  *	Print out statistics, and give up.
  */
-void finish(void)
+void finish(ping_handle_t *a_ping_handle)
 {
-    struct timeval tv = cur_time;
+    struct timeval tv = a_ping_handle->ping_common.cur_time;
 #ifdef PING_DBG
     char *comma = "";
 #endif
 
-    tvsub(&tv, &start_time);
+    tvsub(&tv, &a_ping_handle->ping_common.start_time);
 #ifdef PING_DBG
     putchar('\n');
     fflush(stdout);
@@ -959,10 +969,10 @@ void finish(void)
     putchar('\n');
 #endif
 
-    if(nreceived && timing) {
+    if(a_ping_handle->ping_common.nreceived && a_ping_handle->ping_common.timing) {
 
-        tsum /= nreceived + nrepeats;
-        tsum2 /= nreceived + nrepeats;
+        a_ping_handle->ping_common.tsum /= a_ping_handle->ping_common.nreceived + a_ping_handle->ping_common.nrepeats;
+        a_ping_handle->ping_common.tsum2 /= a_ping_handle->ping_common.nreceived + a_ping_handle->ping_common.nrepeats;
 #ifdef PING_DBG
         long tmdev;
         tmdev = llsqrt(tsum2 - tsum * tsum);
@@ -980,7 +990,7 @@ void finish(void)
         printf("%spipe %d", comma, pipesize);
         comma = ", ";
     }
-    if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) {
+    if (nreceived && (!interval || (a_ping_handle->ping_common.options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) {
         int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
         printf("%sipg/ewma %d.%03d/%d.%03d ms",
                 comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
@@ -990,31 +1000,31 @@ void finish(void)
 #endif
 }
 
-void status(void)
+void status(ping_handle_t *a_ping_handle)
 {
     int loss = 0;
     long tavg = 0;
 
     status_snapshot = 0;
 
-    if(ntransmitted)
-        loss = (((long long) (ntransmitted - nreceived)) * 100) / ntransmitted;
+    if(a_ping_handle->ping_common.ntransmitted)
+        loss = (((long long) (a_ping_handle->ping_common.ntransmitted - a_ping_handle->ping_common.nreceived)) * 100) / a_ping_handle->ping_common.ntransmitted;
 
-    fprintf(stderr, "\r%ld/%ld packets, %d%% loss", nreceived, ntransmitted, loss);
+    fprintf(stderr, "\r%ld/%ld packets, %d%% loss", a_ping_handle->ping_common.nreceived, a_ping_handle->ping_common.ntransmitted, loss);
 
-    if(nreceived && timing) {
-        tavg = tsum / (nreceived + nrepeats);
+    if(a_ping_handle->ping_common.nreceived && a_ping_handle->ping_common.timing) {
+        tavg = a_ping_handle->ping_common.tsum / (a_ping_handle->ping_common.nreceived + a_ping_handle->ping_common.nrepeats);
 
         fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
-                (long) tmin / 1000, (long) tmin % 1000,
+                (long) a_ping_handle->ping_common.tmin / 1000, (long) a_ping_handle->ping_common.tmin % 1000,
                 tavg / 1000, tavg % 1000,
-                rtt / 8000, (rtt / 8) % 1000,
-                (long) tmax / 1000, (long) tmax % 1000
+                a_ping_handle->ping_common.rtt / 8000, (a_ping_handle->ping_common.rtt / 8) % 1000,
+                (long) a_ping_handle->ping_common.tmax / 1000, (long) a_ping_handle->ping_common.tmax % 1000
                         );
     }
     fprintf(stderr, "\n");
 }
 
-inline int is_ours(socket_st *sock, uint16_t id) {
-    return sock->socktype == SOCK_DGRAM || id == ident;
+inline int is_ours(ping_handle_t *a_ping_handle, socket_st *sock, uint16_t id) {
+    return sock->socktype == SOCK_DGRAM || id == a_ping_handle->ping_common.ident;
 }