Newer
Older
/*
* Authors:
* Dmitriy A. Gearasimov <naeper@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 <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <glib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "iputils/iputils.h"
//#include "dap_common.h"
#include "dap_chain_node.h"
#include "dap_chain_global_db.h"
#include "dap_chain_node_cli_cmd.h"
// Max and min macros
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
#define LOG_TAG "chain_node_cli_cmd"
/**
* find option value
*
* return index of string in argv, or 0 if not found
*/
static int find_option_val(const char** argv, int arg_start, int arg_end, const char *opt_name, const char **opt_value)
{
int arg_index = arg_start;
int arg_character, on_or_off, next_arg, i;
char *arg_string;
while(arg_index < arg_end)
{
arg_string = (char *) argv[arg_index];
// find opt_name
if(arg_string && opt_name && !strcmp(arg_string, opt_name)) {
// find opt_value
if(opt_value) {
arg_string = (char *) argv[++arg_index];
if(arg_string) {
*opt_value = arg_string;
return arg_index;
}
}
else
// need only opt_name
return arg_index;
}
arg_index++;
}
return 0;
}
/**
* Convert string to digit
*/
static void digit_from_string(const char *num_str, uint8_t *raw, size_t raw_len)
{
if(!num_str)
return;
uint64_t val;
if(!strncasecmp(num_str, "0x", 2)) {
val = strtoull(num_str + 2, NULL, 16);
}
else {
val = strtoull(num_str, NULL, 10);
}
// for LITTLE_ENDIAN (Intel), do nothing, otherwise swap bytes
val = le64toh(val);
memset(raw, 0, raw_len);
memcpy(raw, &val, min(raw_len, sizeof(uint64_t)));
}
/**
* Add alias in base
*/
static bool add_alias(const char *alias, dap_chain_node_addr_t *addr)
{
const char *a_key = alias;
char a_value[2 * sizeof(dap_chain_node_addr_t) + 1];
if(bin2hex(a_value, (const unsigned char *) addr, sizeof(dap_chain_node_addr_t)) == -1)
return false;
a_value[2 * sizeof(dap_chain_node_addr_t)] = '\0';
bool res = dap_chain_global_db_gr_set(a_key, a_value, GROUP_ALIAS);
return res;
}
/**
* Delete alias from base
*/
{
const char *a_key = alias;
bool res = dap_chain_global_db_gr_del(a_key, GROUP_ALIAS);
return res;
}
/**
* Find in base addr by alias
*
* return addr, NULL if not found
*/
static dap_chain_node_addr_t* get_name_by_alias(const char *alias)
{
dap_chain_node_addr_t *addr = NULL;
if(!alias)
return NULL;
const char *a_key = alias;
char *addr_str = dap_chain_global_db_gr_get(a_key, GROUP_ALIAS);
if(addr_str && strlen(addr_str) == sizeof(dap_chain_node_addr_t) * 2) {
addr = DAP_NEW_Z(dap_chain_node_addr_t);
if(hex2bin((char*) addr, (const unsigned char *) addr_str, sizeof(dap_chain_node_addr_t) * 2) == -1) {
DAP_DELETE(addr);
addr = NULL;
}
}
DAP_DELETE(addr_str);
return addr;
}
* return list of addr, NULL if not found
static GList* get_aliases_by_name(dap_chain_node_addr_t *addr)
size_t data_size = 0;
// read all aliases
dap_global_db_obj_t **objs = dap_chain_global_db_gr_load(&data_size, GROUP_ALIAS);
if(!objs || !data_size)
return NULL;
for(int i = 0; i < data_size; i++) {
dap_chain_node_addr_t addr_i;
dap_global_db_obj_t *obj = objs[i];
if(!obj)
break;
char *addr_str = obj->value;
if(addr_str && strlen(addr_str) == sizeof(dap_chain_node_addr_t) * 2) {
//addr_i = DAP_NEW_Z(dap_chain_node_addr_t);
if(hex2bin((char*) &addr_i, (const unsigned char *) addr_str, sizeof(dap_chain_node_addr_t) * 2) == -1) {
continue;
}
if(addr->uint64 == addr_i.uint64) {
list_aliases = g_list_prepend(list_aliases, strdup(obj->key));
}
dap_chain_global_db_objs_delete(objs);
return list_aliases;
}
static dap_chain_node_addr_t* com_global_db_get_addr(dap_chain_node_info_t *node_info,
dap_chain_node_addr_t *addr, const char *alias_str)
{
dap_chain_node_addr_t *address = NULL;
address = get_name_by_alias(alias_str);
}
}
return address;
}
static char* com_global_db_get_key_for_addr(dap_chain_node_addr_t *address)
{
char *a_key = dap_chain_global_db_hash((const uint8_t*) address, sizeof(dap_chain_node_addr_t));
return a_key;
}
/**
* Write text to reply string
*/
static void set_reply_text(char **str_reply, const char *str, ...)
{
if(str_reply) {
va_list args;
va_start(args, str);
*str_reply = g_strdup_vprintf(str, args); //*str_reply = g_strdup(str);
va_end(args);
}
}
/**
* Handler of command 'global_db node add'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_add(dap_chain_node_info_t *node_info, const char *alias_str,
const char *shard_str, const char *ipv4_str, const char *ipv6_str, char **str_reply)
{
if(!node_info->hdr.address.uint64) {
set_reply_text(str_reply, "not found -addr parameter");
set_reply_text(str_reply, "not found -shard parameter");
return -1;
}
if(!ipv4_str && !ipv6_str) {
set_reply_text(str_reply, "not found -ipv4 or -ipv6 parameter");
return -1;
}
else {
if(ipv4_str)
inet_pton(AF_INET, ipv4_str, &(node_info->hdr.ext_addr_v4));
if(ipv6_str)
inet_pton(AF_INET6, ipv6_str, &(node_info->hdr.ext_addr_v6));
}
// check match addr to shard or no
/*dap_chain_node_addr_t *addr = dap_chain_node_gen_addr(&node_info->hdr.shard_id);
if(!dap_chain_node_check_addr(&node_info->hdr.address, &node_info->hdr.shard_id)) {
if(str_reply)
*str_reply = g_strdup("shard does not match addr");
return -1;
}*/
if(alias_str) {
// add alias
if(!add_alias(alias_str, &node_info->hdr.address)) {
log_it(L_WARNING, "can't save alias %s", alias_str);
set_reply_text(str_reply, "alias '%s' can't be mapped to addr=0x%lld",
alias_str, node_info->hdr.address.uint64);
return -1;
}
}
// write to base
char *a_key = dap_chain_global_db_hash((const uint8_t*) &(node_info->hdr.address),
sizeof(dap_chain_node_addr_t));
char *a_value = dap_chain_node_info_serialize(node_info, NULL);
bool res = dap_chain_global_db_gr_set(a_key, a_value, GROUP_NODE);
if(res)
set_reply_text(str_reply, "node added");
else
set_reply_text(str_reply, "node not added");
DAP_DELETE(a_key);
DAP_DELETE(a_value);
if(res)
return 0;
return -1;
}
/**
* Handler of command 'global_db node add'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_del(dap_chain_node_info_t *node_info, const char *alias_str, char **str_reply)
if(!node_info->hdr.address.uint64 && !alias_str) {
set_reply_text(str_reply, "addr not found");
return -1;
// find addr by alias or addr_str
dap_chain_node_addr_t *address = com_global_db_get_addr(node_info, &node_info->hdr.address, alias_str);
if(!address) {
set_reply_text(str_reply, "alias not found");
return -1;
char *a_key = com_global_db_get_key_for_addr(address);
if(a_key)
{
// delete node
bool res = dap_chain_global_db_gr_del(a_key, GROUP_NODE);
if(res) {
// delete all aliases for node address
{
GList *list_aliases = get_aliases_by_name(address);
GList *list = list_aliases;
while(list)
{
const char *alias = (const char *) list->data;
g_list_free_full(list_aliases, free);
// set text response
set_reply_text(str_reply, "node deleted");
else
set_reply_text(str_reply, "node not deleted");
set_reply_text(str_reply, "addr to delete can't be defined");
DAP_DELETE(address);
return -1;
}
/**
* Handler of command 'global_db node link'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, const char *alias_str,
dap_chain_node_addr_t *link, char **str_reply)
if(!node_info->hdr.address.uint64 && !alias_str) {
set_reply_text(str_reply, "addr not found");
return -1;
}
if(!link->uint64) {
set_reply_text(str_reply, "link not found");
return -1;
}
// TODO check the presence of link in the node base
if(0) {
set_reply_text(str_reply, "node 0x%llx not found in base", link->uint64);
return -1;
// find addr by alias or addr_str
dap_chain_node_addr_t *address = com_global_db_get_addr(node_info, &node_info->hdr.address, alias_str);
if(!address) {
set_reply_text(str_reply, "alias not found");
return -1;
}
char *a_key = com_global_db_get_key_for_addr(address);
if(!a_key)
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
set_reply_text(str_reply, "addr to link can't be defined");
DAP_DELETE(address);
return -1;
}
bool res_successful = false;
// read node
char *str = dap_chain_global_db_gr_get(a_key, GROUP_NODE);
if(!str) {
set_reply_text(str_reply, "node is not found in base");
DAP_DELETE(address);
DAP_DELETE(a_key);
return -1;
}
dap_chain_node_info_t *node_info_read = dap_chain_node_info_deserialize(str, strlen(str));
if(!node_info_read) {
set_reply_text(str_reply, "node have bad format in base");
DAP_DELETE(str);
DAP_DELETE(a_key);
DAP_DELETE(address);
return -1;
}
int cmd_int = 0;
if(!strcmp(cmd, "add"))
cmd_int = 1;
else if(!strcmp(cmd, "del"))
cmd_int = 2;
// find link in node_info_read
int index_link = -1;
for(int i = 0; i < node_info_read->hdr.links_number; i++) {
if(node_info_read->links[i].uint64 == link->uint64) {
// link already present
index_link = i;
break;
// add link
if(cmd_int == 1) {
if(index_link == -1) {
memcpy(&(node_info_read->links[node_info_read->hdr.links_number]), link, sizeof(dap_chain_node_addr_t));
node_info_read->hdr.links_number++;
res_successful = true;
}
}
// delete link
else if(cmd_int == 2) {
// move link list to one item prev
if(index_link >= 0) {
for(int j = index_link; j < node_info_read->hdr.links_number - 1; j++) {
memcpy(&(node_info_read->links[j]), &(node_info_read->links[j + 1]), sizeof(dap_chain_node_addr_t));
}
node_info_read->hdr.links_number--;
res_successful = true;
}
}
// save edited node_info
if(res_successful) {
char *a_value = dap_chain_node_info_serialize(node_info_read, NULL);
bool res = dap_chain_global_db_gr_set(a_key, a_value, GROUP_NODE);
if(res) {
res_successful = true;
if(cmd_int == 1)
set_reply_text(str_reply, "link added");
if(cmd_int == 2)
set_reply_text(str_reply, "link deleted");
else {
res_successful = false;
}
DAP_DELETE(a_value);
else {
if(cmd_int == 1) {
if(index_link >= 0)
set_reply_text(str_reply, "link not added because it is already present");
else
set_reply_text(str_reply, "link not added");
}
if(cmd_int == 2) {
if(index_link == -1)
set_reply_text(str_reply, "link not deleted because not found");
else
set_reply_text(str_reply, "link not deleted");
}
}
DAP_DELETE(str);
DAP_DELETE(a_key);
DAP_DELETE(node_info_read);
if(res_successful)
return 0;
return -1;
}
/**
* Handler of command 'global_db node dump'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_dump(dap_chain_node_info_t *node_info, const char *alias_str, char **str_reply)
if(!node_info->hdr.address.uint64 && !alias_str) {
set_reply_text(str_reply, "addr not found");
// find addr by alias or addr_str
dap_chain_node_addr_t *address = com_global_db_get_addr(node_info, &node_info->hdr.address, alias_str);
set_reply_text(str_reply, "alias not found");
return -1;
}
a_key = com_global_db_get_key_for_addr(address);
if(a_key)
{
dap_chain_node_info_t *node_info_read = NULL;
// read node
char *str = dap_chain_global_db_gr_get(a_key, GROUP_NODE);
if(str) {
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
node_info_read = dap_chain_node_info_deserialize(str, strlen(str));
if(!node_info_read) {
set_reply_text(str_reply, "node have bad format in base");
}
else {
;
//get_host(struct in_addr addr, char *host, size_t hostlen)
int hostlen = 128;
char host4[hostlen];
char host6[hostlen];
//const struct sockaddr *sa
//sockaddr_in
struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = node_info_read->hdr.ext_addr_v4 };
const char* res4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, hostlen);
struct sockaddr_in6 sa6 = { .sin6_family = AF_INET6, .sin6_addr = node_info_read->hdr.ext_addr_v6 };
const char* res6 = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa6)->sin6_addr), host6, hostlen);
//int res = getnameinfo(&sa4, sizeof sa4, host4, hostlen, 0, 0, 0);
// get aliases in form of string
GString *aliases_string = g_string_new(NULL);
GList *list_aliases = get_aliases_by_name(address);
if(list_aliases)
{
GList *list = list_aliases;
while(list)
{
const char *alias = (const char *) list->data;
g_string_append_printf(aliases_string, "\nalias %s", alias);
list = g_list_next(list);
}
g_list_free_full(list_aliases, (GDestroyNotify) free);
}
else
g_string_append(aliases_string, "\nno aliases");
// get links in form of string
GString *links_string = g_string_new(NULL);
for(int i = 0; i < node_info_read->hdr.links_number; i++) {
dap_chain_node_addr_t link_addr = node_info_read->links[i];
g_string_append_printf(links_string, "\nlink%02d address : 0x%llx", i, link_addr.uint64);
}
// set full reply with node param
set_reply_text(str_reply, "node address 0x%llx\nshard 0x%llx%s\nipv4 %s\nipv6 %s\nnumber of links %d%s",
node_info_read->hdr.address, node_info_read->hdr.shard_id, aliases_string->str,
host4, host6,
node_info_read->hdr.links_number, links_string->str);
g_string_free(aliases_string, TRUE);
g_string_free(links_string, TRUE);
else
set_reply_text(str_reply, "node is not found in base");
DAP_DELETE(str);
DAP_DELETE(a_key);
DAP_DELETE(address);
if(node_info_read)
{
DAP_DELETE(node_info_read);
set_reply_text(str_reply, "addr to dump can't be defined");
DAP_DELETE(address);
return -1;
}
/**
* global_db command
*
* return 0 OK, -1 Err
*/
int com_global_db(int argc, const char ** argv, char **str_reply)
{
enum {
CMD_NONE, CMD_ADD, CMD_DEL, CMD_LINK, CMD_DUMP
};
printf("com_global_db\n");
int arg_index = 1;
// find 'node' as first parameter only
arg_index = find_option_val(argv, arg_index, min(argc, arg_index + 1), "node", NULL);
if(str_reply)
*str_reply = g_strdup("parameters are not valid");
return -1;
}
int arg_index_n = ++arg_index;
// find command (add, delete, etc) as second parameter only
if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "add", NULL)) != 0) {
else if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "del", NULL)) != 0) {
else if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "link", NULL)) != 0) {
else if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "dump", NULL)) != 0) {
cmd_num = CMD_DUMP;
}
if(cmd_num == CMD_NONE) {
if(str_reply)
*str_reply = g_strdup_printf("command %s not recognized", 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 *addr_str = NULL, *alias_str = NULL, *shard_str = NULL, *link_str = NULL;
const char *ipv4_str = NULL, *ipv6_str = NULL;
// find addr, alias
find_option_val(argv, arg_index, argc, "-addr", &addr_str);
find_option_val(argv, arg_index, argc, "-alias", &alias_str);
find_option_val(argv, arg_index, argc, "-shard", &shard_str);
find_option_val(argv, arg_index, argc, "-ipv4", &ipv4_str);
find_option_val(argv, arg_index, argc, "-ipv6", &ipv6_str);
find_option_val(argv, arg_index, argc, "-link", &link_str);
// struct to write to the global db
memset(&node_info, 0, sizeof(dap_chain_node_info_t));
memset(&link, 0, sizeof(dap_chain_node_addr_t));
if(addr_str) {
digit_from_string(addr_str, node_info.hdr.address.raw, sizeof(node_info.hdr.address.raw));
}
if(shard_str) {
digit_from_string(shard_str, node_info.hdr.shard_id.raw, sizeof(node_info.hdr.shard_id.raw)); //DAP_CHAIN_SHARD_ID_SIZE);
}
if(link_str) {
digit_from_string(link_str, link.raw, sizeof(link.raw));
}
case CMD_ADD:
if(!arg_index || argc < 8) {
if(str_reply)
*str_reply = g_strdup("parameters are not valid");
return -1;
}
// handler of command 'global_db node add'
return com_global_db_add(&node_info, alias_str, shard_str, ipv4_str, ipv6_str, str_reply);
return com_global_db_del(&node_info, alias_str, str_reply);
if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "add", NULL))
// handler of command 'global_db node link add -addr <node address> -link <node address>'
return com_global_db_link(&node_info, "add", alias_str, &link, str_reply);
else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "del", NULL))
// handler of command 'global_db node link del -addr <node address> -link <node address>'
return com_global_db_link(&node_info, "del", alias_str, &link, str_reply);
else {
set_reply_text(str_reply, "command not recognize, supported format:\n"
"global_db node link [add|del] [-addr <node address> | -alias <node alias>] -link <node address>");
return -1;
}
break;
case CMD_DUMP:
// handler of command 'global_db node dump'
return com_global_db_dump(&node_info, alias_str, str_reply);
break;
default:
if(str_reply)
*str_reply = g_strdup_printf("command %s not recognized", argv[1]);
return -1;
//inet_ntop(AF_INET, &(dap_addr.uint64), str, INET_ADDRSTRLEN);
//uint64
return -1;
}
/**
* Node command
*/
int com_node(int argc, const char ** argv, char **str_reply)
{
enum {
CMD_NONE, CMD_ALIAS, CMD_HANDSHAKE
};
int arg_index = 1;
int cmd_num = CMD_NONE;
const char *cmd_str = NULL;
// find add parameter ('alias' or 'handshake')
if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "handshake", NULL)) {
cmd_num = CMD_HANDSHAKE;
}
else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "alias", NULL)) {
cmd_num = CMD_ALIAS;
}
arg_index++;
if(cmd_num == CMD_NONE) {
if(str_reply)
*str_reply = g_strdup_printf("command %s not recognized", argv[1]);
return -1;
}
dap_chain_node_addr_t address;
const char *addr_str = NULL, *alias_str = NULL;
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
find_option_val(argv, arg_index, argc, "-addr", &addr_str);
find_option_val(argv, arg_index, argc, "-alias", &alias_str);
digit_from_string(addr_str, address.raw, sizeof(address.raw));
switch (cmd_num)
{
// add alias
case CMD_ALIAS:
if(alias_str) {
if(addr_str) {
// add alias
if(!add_alias(alias_str, &address))
log_it(L_WARNING, "can't save alias %s", alias_str);
else {
if(str_reply)
*str_reply = g_strdup("alias mapped successfully");
}
}
else {
if(str_reply)
*str_reply = g_strdup("alias can't be mapped because -addr is not found");
return -1;
}
}
else {
if(str_reply)
*str_reply = g_strdup("alias can't be mapped because -alias is not found");
return -1;
}
break;
// make handshake
case CMD_HANDSHAKE:
// get address from alias if addr not defined
if(alias_str && !address.uint64) {
dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
if(address_tmp) {
memcpy(&address, address_tmp, sizeof(address_tmp));
DAP_DELETE(address_tmp);
}
else {
set_reply_text(str_reply, "no address found by alias");
return -1;
}
}
if(!address.uint64) {
set_reply_text(str_reply, "addr not found");
return -1;
}
// TODO start handshake
if(str_reply)
*str_reply = g_strdup("handshake in progress...");
break;
}
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
return 0;
}
/**
* Traceroute command
*
* return 0 OK, -1 Err
*/
int com_traceroute(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int hops = 0, time_usec = 0;
if(argc > 1)
addr = argv[1];
iputils_set_verbose();
int res = (addr) ? traceroute_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
if(res >= 0) {
if(str_reply)
*str_reply = g_strdup_printf("traceroute %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EADDRNOTAVAIL:
*str_reply = g_strdup_printf("traceroute %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case 2:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "Unknown traceroute module");
break;
case 3:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "first hop out of range");
break;
case 4:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "max hops cannot be more than 255");
break;
case 5:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "no more than 10 probes per hop");
break;
case 6:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "bad wait specifications");
break;
case 7:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "too big packetlen ");
break;
case 8:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr,
"IP version mismatch in addresses specified");
break;
case 9:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "bad sendtime");
break;
case 10:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "init_ip_options");
break;
case 11:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "calloc");
break;
case 12:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "parse cmdline");
break;
case 13:
*str_reply = g_strdup_printf("traceroute %s error: %s", addr, "trace method's init failed");
break;
default:
*str_reply = g_strdup_printf("traceroute %s error(%d) %s", addr, res, "trace not found");
}
}
}
return res;
}
/**
* Tracepath command
*
* return 0 OK, -1 Err
*/
int com_tracepath(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int hops = 0, time_usec = 0;
if(argc > 1)
addr = argv[1];
iputils_set_verbose();
int res = (addr) ? tracepath_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
if(res >= 0) {
if(str_reply)
*str_reply = g_strdup_printf("tracepath %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EADDRNOTAVAIL:
*str_reply = g_strdup_printf("tracepath %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case ESOCKTNOSUPPORT:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't create socket");
break;
case 2:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_MTU_DISCOVER");
break;
case 3:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_RECVERR");
break;
case 4:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_HOPLIMIT");
break;
case 5:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_MTU_DISCOVER");
break;
case 6:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_RECVERR");
break;
case 7:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_RECVTTL");
break;
case 8:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "malloc");
break;
case 9:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_UNICAST_HOPS");
break;
case 10:
*str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_TTL");
break;
default:
*str_reply = g_strdup_printf("tracepath %s error(%d) %s", addr, res, "trace not found");
}
}
}
return res;
}
/**
* Ping command
*
* return 0 OK, -1 Err
*/
int com_ping(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int n = 4;
if(argc > 1)
addr = argv[1];
const char *n_str = NULL;
if(find_option_val(argv, 2, argc, "-n", &n_str))
n = (n_str) ? atoi(n_str) : 4;
else if(find_option_val(argv, 2, argc, "-c", &n_str))
n = (n_str) ? atoi(n_str) : 4;
if(n <= 1)
n = 1;
iputils_set_verbose();
int res = (addr) ? ping_util(addr, n) : -EADDRNOTAVAIL;
if(res >= 0) {
if(str_reply)
*str_reply = g_strdup_printf("ping %s time=%.1lf ms", addr, res * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EDESTADDRREQ:
*str_reply = g_strdup_printf("ping %s error: %s", addr, "Destination address required");
break;
case EADDRNOTAVAIL:
*str_reply = g_strdup_printf("ping %s error: %s", (addr) ? addr : "",
(addr) ? "Host not found" : "Host not defined");
break;
case EPFNOSUPPORT:
*str_reply = g_strdup_printf("ping %s error: %s", addr, "Unknown protocol family");
break;
default:
*str_reply = g_strdup_printf("ping %s error(%d)", addr, -res);
}
}
}
return res;
}
/**
* Help command
*/
int com_help(int argc, const char ** argv, char **str_reply)
{
if(argc > 1) {
const COMMAND *cmd = find_command(argv[1]);
if(cmd)
{
if(str_reply)
*str_reply = g_strdup(cmd->doc);
return 1;
}
if(str_reply)
*str_reply = g_strdup_printf("command \"%s\" not recognized", argv[1]);
}
if(str_reply)
*str_reply = g_strdup("command not defined, enter \"help <cmd name>\"");
return -1;
}