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; }