core_cmd.c
58c1870c
 /*
  * Copyright (C) 2005 iptelorg GmbH
  *
88693a29
  * This file is part of Kamailio, a free SIP server.
58c1870c
  *
88693a29
  * Kamailio is free software; you can redistribute it and/or modify
58c1870c
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
88693a29
  * Kamailio is distributed in the hope that it will be useful,
58c1870c
  * 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.
  *
566cde2d
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
58c1870c
  */
5a03489e
 
88693a29
 /** Kamailio Core :: core rpcs.
1ef55a09
  * @file core_cmd.c
  * @ingroup core
1d0661db
  */
 
58c1870c
 
 #include <time.h>
 #include <sys/types.h>
 #include <signal.h>
1ef55a09
 #include "ver.h"
58c1870c
 #include "mem/mem.h"
566cde2d
 #include "mem/shm_mem.h"
58c1870c
 #include "sr_module.h"
5099fd64
 #include "rpc_lookup.h"
58c1870c
 #include "dprint.h"
 #include "core_cmd.h"
 #include "globals.h"
a6c83dd4
 #include "forward.h"
 #include "socket_info.h"
 #include "name_alias.h"
58c1870c
 #include "pt.h"
 #include "ut.h"
d9515405
 #include "tcp_info.h"
e567b3fd
 #include "tcp_conn.h"
20c64cc6
 #include "tcp_options.h"
58c1870c
 #include "core_cmd.h"
27e652b7
 #include "cfg_core.h"
58c1870c
 
dcb59e67
 #ifdef USE_DNS_CACHE
 void dns_cache_debug(rpc_t* rpc, void* ctx);
 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
ba813ed5
 void dns_cache_view(rpc_t* rpc, void* ctx);
adc6fe8a
 void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx);
ba813ed5
 void dns_cache_delete_all(rpc_t* rpc, void* ctx);
ec79c28a
 void dns_cache_delete_all_force(rpc_t* rpc, void* ctx);
ba813ed5
 void dns_cache_add_a(rpc_t* rpc, void* ctx);
 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx);
 void dns_cache_add_srv(rpc_t* rpc, void* ctx);
 void dns_cache_delete_a(rpc_t* rpc, void* ctx);
 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx);
 void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
adc6fe8a
 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx);
 void dns_cache_delete_cname(rpc_t* rpc, void* ctx);
 void dns_cache_delete_txt(rpc_t* rpc, void* ctx);
2c2dd816
 void dns_cache_delete_ebl(rpc_t* rpc, void* ctx);
d354557c
 void dns_cache_delete_ptr(rpc_t* rpc, void* ctx);
ba813ed5
 
dcb59e67
 
 static const char* dns_cache_mem_info_doc[] = {
 	"dns cache memory info.",    /* Documentation string */
 	0                      /* Method signature(s) */
 };
 static const char* dns_cache_debug_doc[] = {
 	"dns debug  info.",    /* Documentation string */
 	0                      /* Method signature(s) */
 };
 
 static const char* dns_cache_debug_all_doc[] = {
 	"complete dns debug  dump",    /* Documentation string */
 	0                              /* Method signature(s) */
 };
f682fd71
 
ba813ed5
 static const char* dns_cache_view_doc[] = {
 	"dns cache dump in a human-readable format",
 	0
 };
 
adc6fe8a
 static const char* dns_cache_rpc_lookup_doc[] = {
 	"perform a dns lookup",
 	0
 };
 
ba813ed5
 static const char* dns_cache_delete_all_doc[] = {
ec79c28a
 	"deletes all the non-permanent entries from the DNS cache",
 	0
 };
 
 static const char* dns_cache_delete_all_force_doc[] = {
 	"deletes all the entries from the DNS cache including the permanent ones",
ba813ed5
 	0
 };
 
 static const char* dns_cache_add_a_doc[] = {
 	"adds an A record to the DNS cache",
 	0
 };
 
 static const char* dns_cache_add_aaaa_doc[] = {
 	"adds an AAAA record to the DNS cache",
 	0
 };
 static const char* dns_cache_add_srv_doc[] = {
 	"adds an SRV record to the DNS cache",
 	0
 };
 
 static const char* dns_cache_delete_a_doc[] = {
 	"deletes an A record from the DNS cache",
 	0
 };
 
 static const char* dns_cache_delete_aaaa_doc[] = {
 	"deletes an AAAA record from the DNS cache",
 	0
 };
 
 static const char* dns_cache_delete_srv_doc[] = {
 	"deletes an SRV record from the DNS cache",
 	0
 };
 
adc6fe8a
 static const char* dns_cache_delete_naptr_doc[] = {
 	"deletes a NAPTR record from the DNS cache",
 	0
 };
 
 static const char* dns_cache_delete_cname_doc[] = {
 	"deletes a CNAME record from the DNS cache",
 	0
 };
 
 static const char* dns_cache_delete_txt_doc[] = {
 	"deletes a TXT record from the DNS cache",
 	0
 };
 
2c2dd816
 static const char* dns_cache_delete_ebl_doc[] = {
 	"deletes an EBL record from the DNS cache",
 	0
 };
 
adc6fe8a
 
d354557c
 static const char* dns_cache_delete_ptr_doc[] = {
 	"deletes an PTR record from the DNS cache",
 	0
 };
 
 
021e7e0e
 #ifdef USE_DNS_CACHE_STATS
 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
 
 static const char* dns_cache_stats_get_doc[] = {
 	"returns the dns measurement counters.",
 	0
 };
 #endif /* USE_DNS_CACHE_STATS */
f682fd71
 #ifdef DNS_WATCHDOG_SUPPORT
 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
 
 static const char* dns_set_server_state_doc[] = {
 	"sets the state of the DNS servers " \
 	"(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
 	0                              /* Method signature(s) */
 };
50152220
 
 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx);
 
 static const char* dns_get_server_state_doc[] = {
 	"prints the state of the DNS servers " \
 	"(0: all the servers are down, 1: at least one server is up)",	/* Documentation string */
 	0				/* Method signature(s) */
 };
 
f682fd71
 #endif /* DNS_WATCHDOG_SUPPORT */
 #endif /* USE_DNS_CACHE */
dcb59e67
 #ifdef USE_DST_BLACKLIST
 void dst_blst_debug(rpc_t* rpc, void* ctx);
 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
dfcbd08b
 void dst_blst_view(rpc_t* rpc, void* ctx);
 void dst_blst_delete_all(rpc_t* rpc, void* ctx);
 void dst_blst_add(rpc_t* rpc, void* ctx);
dcb59e67
 
 static const char* dst_blst_mem_info_doc[] = {
 	"dst blacklist memory usage info.",  /* Documentation string */
 	0                                    /* Method signature(s) */
 };
 static const char* dst_blst_debug_doc[] = {
 	"dst blacklist  debug  info.",  /* Documentation string */
 	0                               /* Method signature(s) */
 };
dfcbd08b
 static const char* dst_blst_view_doc[] = {
 	"dst blacklist dump in human-readable format.",  /* Documentation string */
 	0                               /* Method signature(s) */
 };
 static const char* dst_blst_delete_all_doc[] = {
 	"Deletes all the entries from the dst blacklist except the permanent ones.",  /* Documentation string */
 	0                               /* Method signature(s) */
 };
 static const char* dst_blst_add_doc[] = {
 	"Adds a new entry to the dst blacklist.",  /* Documentation string */
 	0                               /* Method signature(s) */
 };
021e7e0e
 #ifdef USE_DST_BLACKLIST_STATS
 void dst_blst_stats_get(rpc_t* rpc, void* ctx);
 
 static const char* dst_blst_stats_get_doc[] = {
 	"returns the dst blacklist measurement counters.",
 	0
 };
 #endif /* USE_DST_BLACKLIST_STATS */
dfcbd08b
 
dcb59e67
 #endif
 
 
58c1870c
 
 #define MAX_CTIME_LEN 128
 
 /* up time */
 static char up_since_ctime[MAX_CTIME_LEN];
 
 
 static const char* system_listMethods_doc[] = {
 	"Lists all RPC methods supported by the server.",  /* Documentation string */
 	0                                                  /* Method signature(s) */
 };
 
 static void system_listMethods(rpc_t* rpc, void* c)
 {
5099fd64
 	int i;
 	
 	for(i=0; i<rpc_sarray_crt_size; i++){
 		if (rpc->add(c, "s", rpc_sarray[i]->name) < 0) return;
58c1870c
 	}
 }
 
 static const char* system_methodSignature_doc[] = {
 	"Returns signature of given method.",  /* Documentation string */
 	0                                      /* Method signature(s) */
 };
 
 static void system_methodSignature(rpc_t* rpc, void* c)
 {
 	rpc->fault(c, 500, "Not Implemented Yet");
 }
 
 
 static const char* system_methodHelp_doc[] = {
 	"Print the help string for given method.",  /* Documentation string */
 	0                                           /* Method signature(s) */
 };
 
 static void system_methodHelp(rpc_t* rpc, void* c)
566cde2d
 {
5099fd64
 	rpc_export_t* r;
58c1870c
 	char* name;
 
dab2c420
 	if (rpc->scan(c, "s", &name) < 1) {
e46483c8
 		rpc->fault(c, 400, "Method Name Expected");
 		return;
 	}
5099fd64
 	
 	r=rpc_lookup(name, strlen(name));
 	if (r==0){
 		rpc->fault(c, 400, "command not found");
 	}else{
 		if (r->doc_str && r->doc_str[0]) {
 			rpc->add(c, "s", r->doc_str[0]);
 		} else {
 			rpc->add(c, "s", "undocumented");
58c1870c
 		}
 	}
5099fd64
 	return;
58c1870c
 }
 
 
 static const char* core_prints_doc[] = {
aafc8ea7
 	"Returns the strings given as parameters.",   /* Documentation string */
 	0                                             /* Method signature(s) */
58c1870c
 };
 
e46483c8
 
58c1870c
 static void core_prints(rpc_t* rpc, void* c)
 {
e46483c8
 	char* string = 0;
aafc8ea7
 	while((rpc->scan(c, "*s", &string)>0))
 		rpc->add(c, "s", string);
 }
 
 
 static const char* core_printi_doc[] = {
 	"Returns the integers given as parameters.",  /* Documentation string */
 	0                                             /* Method signature(s) */
 };
 
 
 static void core_printi(rpc_t* rpc, void* c)
 {
 	int i;
 	while((rpc->scan(c, "*d", &i)>0))
 		rpc->add(c, "d", i);
 }
 
 
 static const char* core_echo_doc[] = {
 	"Returns back its parameters.",              /* Documentation string */
 	0                                             /* Method signature(s) */
 };
 
 
 static void core_echo(rpc_t* rpc, void* c)
 {
 	char* string = 0;
 	while((rpc->scan(c, "*.s", &string)>0))
8abbb5e4
 		rpc->add(c, "s", string);
58c1870c
 }
 
 
 static const char* core_version_doc[] = {
 	"Returns the version string of the server.", /* Documentation string */
 	0                                           /* Method signature(s) */
 };
 
 static void core_version(rpc_t* rpc, void* c)
 {
1ef55a09
 	rpc->add(c, "s", full_version);
58c1870c
 }
 
 
 
20fd4b8b
 static const char* core_flags_doc[] = {
 	"Returns the compile flags.", /* Documentation string */
 	0                             /* Method signature(s) */
 };
 
 static void core_flags(rpc_t* rpc, void* c)
 {
 	rpc->add(c, "s", ver_flags);
 }
 
 
 
 static const char* core_info_doc[] = {
 	"Verbose info, including version number, compile flags, compiler,"
 	"repository hash a.s.o.",     /* Documentation string */
 	0                             /* Method signature(s) */
 };
 
 static void core_info(rpc_t* rpc, void* c)
 {
 	void* s;
 	
 	if (rpc->add(c, "{", &s) < 0) return;
 	rpc->struct_printf(s, "version", "%s %s", ver_name, ver_version);
 	rpc->struct_add(s, "s", "id", ver_id);
 	rpc->struct_add(s, "s", "compiler", ver_compiler);
 	rpc->struct_add(s, "s", "compiled", ver_compiled_time);
 	rpc->struct_add(s, "s", "flags", ver_flags);
 }
 
 
 
58c1870c
 static const char* core_uptime_doc[] = {
 	"Returns uptime of SER server.",  /* Documentation string */
 	0                                 /* Method signature(s) */
 };
 
 
 static void core_uptime(rpc_t* rpc, void* c)
 {
1abf9a2d
 	void* s;
58c1870c
 	time_t now;
 
 	time(&now);
566cde2d
 
1abf9a2d
 	if (rpc->add(c, "{", &s) < 0) return;
 	rpc->struct_add(s, "s", "now", ctime(&now));
 	rpc->struct_add(s, "s", "up_since", up_since_ctime);
a74b76d8
 	/* no need for a float here (unless you're concerned that your uptime)
 	rpc->struct_add(s, "f", "uptime",  difftime(now, up_since));
 	*/
 	/* on posix system we can substract time_t directly */
 	rpc->struct_add(s, "d", "uptime",  (int)(now-up_since));
58c1870c
 }
 
 
 static const char* core_ps_doc[] = {
 	"Returns the description of running SER processes.",  /* Documentation string */
 	0                                                     /* Method signature(s) */
 };
 
 
 static void core_ps(rpc_t* rpc, void* c)
 {
 	int p;
 
37209e14
 	for (p=0; p<*process_count;p++) {
1abf9a2d
 		rpc->add(c, "d", pt[p].pid);
 		rpc->add(c, "s", pt[p].desc);
58c1870c
 	}
 }
 
d381b69c
 static const char* core_psx_doc[] = {
 	"Returns the detailed description of running SER processes.",
 		/* Documentation string */
 	0	/* Method signature(s) */
 };
 
 
 static void core_psx(rpc_t* rpc, void* c)
 {
 	int p;
 	void *handle;
 
 	for (p=0; p<*process_count;p++) {
 		rpc->add(c, "{", &handle);
 		rpc->struct_add(handle, "dds",
 				"IDX", p,
 				"PID", pt[p].pid,
 				"DSC", pt[p].desc);
 	}
 }
 
58c1870c
 
 static const char* core_pwd_doc[] = {
 	"Returns the working directory of SER server.",    /* Documentation string */
 	0                                                  /* Method signature(s) */
 };
 
 
 static void core_pwd(rpc_t* rpc, void* c)
 {
         char *cwd_buf;
         int max_len;
 
         max_len = pathmax();
         cwd_buf = pkg_malloc(max_len);
         if (!cwd_buf) {
                 ERR("core_pwd: No memory left\n");
                 rpc->fault(c, 500, "Server Ran Out of Memory");
 		return;
         }
 
         if (getcwd(cwd_buf, max_len)) {
 		rpc->add(c, "s", cwd_buf);
         } else {
 		rpc->fault(c, 500, "getcwd Failed");
         }
         pkg_free(cwd_buf);
 }
 
 
 static const char* core_arg_doc[] = {
 	"Returns the list of command line arguments used on SER startup.",  /* Documentation string */
 	0                                                                   /* Method signature(s) */
 };
 
 
 static void core_arg(rpc_t* rpc, void* c)
 {
         int p;
 
         for (p = 0; p < my_argc; p++) {
 		if (rpc->add(c, "s", my_argv[p]) < 0) return;
         }
 }
 
 
 static const char* core_kill_doc[] = {
 	"Sends the given signal to SER.",  /* Documentation string */
 	0                                  /* Method signature(s) */
 };
 
 
 static void core_kill(rpc_t* rpc, void* c)
 {
e46483c8
 	int sig_no = 15;
 	rpc->scan(c, "d", &sig_no);
58c1870c
 	rpc->send(c);
 	kill(0, sig_no);
 }
 
566cde2d
 static void core_shmmem(rpc_t* rpc, void* c)
 {
 	struct mem_info mi;
 	void *handle;
02eec212
 	char* param;
 	long rs;
 
 	rs=0;
 	/* look for optional size/divisor parameter */
 	if (rpc->scan(c, "*s", &param)>0){
 		switch(*param){
 			case 'b':
 			case 'B':
 				rs=0;
 				break;
 			case 'k':
 			case 'K':
 				rs=10; /* K -> 1024 */
 				break;
 			case 'm':
 			case 'M':
 				rs=20; /* M -> 1048576 */
 				break;
 			case 'g':
 			case 'G':
 				rs=30; /* G -> 1024M */
 				break;
 			default:
 				rpc->fault(c, 500, "bad param, (use b|k|m|g)");
 				return;
 		}
 		if (param[1] && ((param[1]!='b' && param[1]!='B') || param[2])){
 				rpc->fault(c, 500, "bad param, (use b|k|m|g)");
 				return;
 		}
 	}
566cde2d
 	shm_info(&mi);
 	rpc->add(c, "{", &handle);
61551c02
 	rpc->struct_add(handle, "dddddd",
02eec212
 		"total", (unsigned int)(mi.total_size>>rs),
 		"free", (unsigned int)(mi.free>>rs),
 		"used", (unsigned int)(mi.used>>rs),
 		"real_used",(unsigned int)(mi.real_used>>rs),
 		"max_used", (unsigned int)(mi.max_used>>rs),
71a0a583
 		"fragments", (unsigned int)mi.total_frags
566cde2d
 	);
 }
 
 static const char* core_shmmem_doc[] = {
02eec212
 	"Returns shared memory info. It has an optional parameter that specifies"
 	" the measuring unit: b - bytes (default), k or kb, m or mb, g or gb. "
 	"Note: when using something different from bytes, the value is truncated.",
566cde2d
 	0                               /* Method signature(s) */
e46483c8
 };
 
58c1870c
 
61551c02
 #if defined(SF_MALLOC) || defined(LL_MALLOC)
 static void core_sfmalloc(rpc_t* rpc, void* c)
 {
 	void *handle;
 	int i,r;
 	unsigned long frags, main_s_frags, main_b_frags, pool_frags;
 	unsigned long misses;
 	unsigned long max_misses;
 	unsigned long max_frags;
 	unsigned long max_mem;
 	int max_frags_pool, max_frags_hash;
 	int max_misses_pool, max_misses_hash;
 	int max_mem_pool, max_mem_hash;
 	unsigned long mem;
 
 	if (rpc->scan(c, "d", &r) >= 1) {
 		if (r>=(int)SF_HASH_POOL_SIZE){
 			rpc->fault(c, 500, "invalid hash number %d (max %d)",
 								r, (unsigned int)SF_HASH_POOL_SIZE-1);
 			return;
 		}else if (r<0) goto all;
 		rpc->add(c, "{", &handle);
 		rpc->struct_add(handle, "dd",
 				"hash  ", r,
 				"size  ", r*SF_ROUNDTO);
 		for (i=0; i<SFM_POOLS_NO; i++){
 			rpc->struct_add(handle, "dddd",
 				"pool  ", i,
 				"frags ", (unsigned int)shm_block->pool[i].pool_hash[r].no,
 				"misses", (unsigned int)shm_block->pool[i].pool_hash[r].misses,
 				"mem   ",   (unsigned int)shm_block->pool[i].pool_hash[r].no *
 							r*SF_ROUNDTO
 			);
 		}
 	}
 	return;
 all:
 	max_frags=max_misses=max_mem=0;
 	max_frags_pool=max_frags_hash=0;
 	max_misses_pool=max_misses_hash=0;
 	max_mem_pool=max_mem_hash=0;
 	pool_frags=0;
 	for (i=0; i<SFM_POOLS_NO; i++){
 		frags=0;
 		misses=0;
 		mem=0;
 		for (r=0; r<SF_HASH_POOL_SIZE; r++){
 			frags+=shm_block->pool[i].pool_hash[r].no;
 			misses+=shm_block->pool[i].pool_hash[r].misses;
 			mem+=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
 			if (shm_block->pool[i].pool_hash[r].no>max_frags){
 				max_frags=shm_block->pool[i].pool_hash[r].no;
 				max_frags_pool=i;
 				max_frags_hash=r;
 			}
 			if (shm_block->pool[i].pool_hash[r].misses>max_misses){
 				max_misses=shm_block->pool[i].pool_hash[r].misses;
 				max_misses_pool=i;
 				max_misses_hash=r;
 			}
 			if (shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO>max_mem){
 				max_mem=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
 				max_mem_pool=i;
 				max_mem_hash=r;
 			}
 		}
 		rpc->add(c, "{", &handle);
20c64cc6
 		rpc->struct_add(handle, "dddddd",
61551c02
 			"pool  ", i,
 			"frags ", (unsigned int)frags,
 			"t. misses", (unsigned int)misses,
 			"mem   ", (unsigned int)mem,
 			"missed", (unsigned int)shm_block->pool[i].missed,
 			"hits",   (unsigned int)shm_block->pool[i].hits
 		);
 		pool_frags+=frags;
 	}
 	main_s_frags=0;
 	for (r=0; r<SF_HASH_POOL_SIZE; r++){
 		main_s_frags+=shm_block->free_hash[r].no;
 	}
 	main_b_frags=0;
 	for (; r<SF_HASH_SIZE; r++){
 		main_b_frags+=shm_block->free_hash[r].no;
 	}
 	rpc->add(c, "{", &handle);
20c64cc6
 	rpc->struct_add(handle, "ddddddddddddd",
61551c02
 		"max_frags      ", (unsigned int)max_frags,
 		"max_frags_pool ", max_frags_pool,
 		"max_frags_hash", max_frags_hash,
 		"max_misses     ", (unsigned int)max_misses,
 		"max_misses_pool", max_misses_pool,
 		"max_misses_hash", max_misses_hash,
 		"max_mem        ", (unsigned int)max_mem,
 		"max_mem_pool   ", max_mem_pool,
 		"max_mem_hash   ", max_mem_hash,
 		"in_pools_frags ", (unsigned int)pool_frags,
 		"main_s_frags   ", (unsigned int)main_s_frags,
 		"main_b_frags   ", (unsigned int)main_b_frags,
20c64cc6
 		"main_frags     ", (unsigned int)(main_b_frags+main_s_frags)
61551c02
 	);
 }
 
 
 
 static const char* core_sfmalloc_doc[] = {
 	"Returns sfmalloc debugging  info.",  /* Documentation string */
 	0                                     /* Method signature(s) */
 };
021e7e0e
 
61551c02
 #endif
 
 
 
d9515405
 static const char* core_tcpinfo_doc[] = {
 	"Returns tcp related info.",    /* Documentation string */
 	0                               /* Method signature(s) */
 };
 
 static void core_tcpinfo(rpc_t* rpc, void* c)
 {
 #ifdef USE_TCP
7ad18de8
 	void *handle;
d9515405
 	struct tcp_gen_info ti;
021e7e0e
 
d9515405
 	if (!tcp_disable){
 		tcp_get_info(&ti);
 		rpc->add(c, "{", &handle);
61f8b970
 		rpc->struct_add(handle, "dddddd",
d9515405
 			"readers", ti.tcp_readers,
 			"max_connections", ti.tcp_max_connections,
61f8b970
 			"max_tls_connections", ti.tls_max_connections,
885b9f62
 			"opened_connections", ti.tcp_connections_no,
61f8b970
 			"opened_tls_connections", ti.tls_connections_no,
885b9f62
 			"write_queued_bytes", ti.tcp_write_queued
d9515405
 		);
 	}else{
 		rpc->fault(c, 500, "tcp support disabled");
 	}
 #else
 	rpc->fault(c, 500, "tcp support not compiled");
 #endif
 }
 
20c64cc6
 
 
 static const char* core_tcp_options_doc[] = {
 	"Returns active tcp options.",    /* Documentation string */
 	0                                 /* Method signature(s) */
 };
 
 static void core_tcp_options(rpc_t* rpc, void* c)
 {
 #ifdef USE_TCP
7ad18de8
 	void *handle;
22db42e4
 	struct cfg_group_tcp t;
20c64cc6
 
 	if (!tcp_disable){
 		tcp_options_get(&t);
 		rpc->add(c, "{", &handle);
61f8b970
 		rpc->struct_add(handle, "ddddddddddddddddddddddd",
c0c298d5
 			"connect_timeout", t.connect_timeout_s,
ffc72fcf
 			"send_timeout",  TICKS_TO_S(t.send_timeout),
9a74e06a
 			"connection_lifetime",  TICKS_TO_S(t.con_lifetime),
c0c298d5
 			"max_connections(soft)", t.max_connections,
61f8b970
 			"max_tls_connections(soft)", t.max_tls_connections,
de223f01
 			"no_connect",	t.no_connect,
20c64cc6
 			"fd_cache",		t.fd_cache,
76cb799e
 			"async",		t.async,
c0c298d5
 			"connect_wait",	t.tcp_connect_wait,
 			"conn_wq_max",	t.tcpconn_wq_max,
 			"wq_max",		t.tcp_wq_max,
20c64cc6
 			"defer_accept",	t.defer_accept,
 			"delayed_ack",	t.delayed_ack,
 			"syncnt",		t.syncnt,
 			"linger2",		t.linger2,
 			"keepalive",	t.keepalive,
 			"keepidle",		t.keepidle,
 			"keepintvl",	t.keepintvl,
c7337a27
 			"keepcnt",		t.keepcnt,
c0c298d5
 			"crlf_ping",	t.crlf_ping,
 			"accept_aliases", t.accept_aliases,
 			"alias_flags",	t.alias_flags,
 			"new_conn_alias_flags",	t.new_conn_alias_flags
20c64cc6
 		);
 	}else{
 		rpc->fault(c, 500, "tcp support disabled");
 	}
 #else
 	rpc->fault(c, 500, "tcp support not compiled");
 #endif
 }
 
 
e567b3fd
 static const char* core_tcp_list_doc[] = {
 	"Returns tcp connections details.",    /* Documentation string */
 	0                               /* Method signature(s) */
 };
 
 extern gen_lock_t* tcpconn_lock;
 extern struct tcp_connection** tcpconn_id_hash;
 
 static void core_tcp_list(rpc_t* rpc, void* c)
 {
 #ifdef USE_TCP
 	char src_ip[IP_ADDR_MAX_STR_SIZE];
 	char dst_ip[IP_ADDR_MAX_STR_SIZE];
 	void* handle;
 	char* state;
 	char* type;
 	struct tcp_connection* con;
2f14564f
 	int i, len, timeout, lifetime;
e567b3fd
 
7bc2efb3
 	if (tcp_disable) {
 		rpc->fault(c, 500, "tcp support disabled");
 		return;
 	}
 
e567b3fd
 	TCPCONN_LOCK;
 	for(i = 0; i < TCP_ID_HASH_SIZE; i++) {
 		for (con = tcpconn_id_hash[i]; con; con = con->id_next) {
 			rpc->add(c, "{", &handle);
 			/* tcp data */
 			if (con->rcv.proto == PROTO_TCP)
 				type = "TCP";
fb4dc4b7
 			else if (con->rcv.proto == PROTO_TLS)
e567b3fd
 				type = "TLS";
fb4dc4b7
 			else if (con->rcv.proto == PROTO_WSS)
 				type = "WSS";
 			else if (con->rcv.proto == PROTO_WS)
 				type = "WS";
e567b3fd
 			else
 				type = "UNKNOWN";
 
 			if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip)))
 					== 0)
 				BUG("failed to convert source ip");
 			src_ip[len] = 0;
 			if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip)))
 					== 0)
 				BUG("failed to convert destination ip");
 			dst_ip[len] = 0;
 			timeout = TICKS_TO_S(con->timeout - get_ticks_raw());
2f14564f
 			lifetime = TICKS_TO_S(con->lifetime);
e567b3fd
 			switch(con->state) {
 				case S_CONN_ERROR:
 					state = "CONN_ERROR";
 				break;
 				case S_CONN_BAD:
 					state = "CONN_BAD";
 				break;
 				case S_CONN_OK:
 					state = "CONN_OK";
 				break;
 				case S_CONN_INIT:
 					state = "CONN_INIT";
 				break;
 				case S_CONN_EOF:
 					state = "CONN_EOF";
 				break;
 				case S_CONN_ACCEPT:
 					state = "CONN_ACCEPT";
 				break;
 				case S_CONN_CONNECT:
 					state = "CONN_CONNECT";
 				break;
 				default:
 					state = "UNKNOWN";
 			}
2f14564f
 			rpc->struct_add(handle, "dssdddsdsd",
e567b3fd
 					"id", con->id,
 					"type", type,
 					"state", state,
 					"timeout", timeout,
2f14564f
 					"lifetime", lifetime,
fb4dc4b7
 					"ref_count", con->refcnt,
e567b3fd
 					"src_ip", src_ip,
 					"src_port", con->rcv.src_port,
 					"dst_ip", dst_ip,
 					"dst_port", con->rcv.dst_port);
 		}
 	}
 	TCPCONN_UNLOCK;
 #else
 	rpc->fault(c, 500, "tcp support not compiled");
 #endif
 }
 
 
27e652b7
 static const char* core_udp4rawinfo_doc[] = {
 	"Returns udp4_raw related info.",    /* Documentation string */
 	0                                     /* Method signature(s) */
 };
 
 static void core_udp4rawinfo(rpc_t* rpc, void* c)
 {
 #ifdef USE_RAW_SOCKS
 	void *handle;
 
 	rpc->add(c, "{", &handle);
 	rpc->struct_add(handle, "ddd",
 		"udp4_raw", cfg_get(core, core_cfg, udp4_raw),
 		"udp4_raw_mtu", cfg_get(core, core_cfg, udp4_raw_mtu),
 		"udp4_raw_ttl", cfg_get(core, core_cfg, udp4_raw_ttl)
 	);
 #else /* USE_RAW_SOCKS */
 	rpc->fault(c, 500, "udp4_raw mode support not compiled");
 #endif /* USE_RAW_SOCKS */
 }
 
a6c83dd4
 /**
  *
  */
 static const char* core_aliases_list_doc[] = {
 	"List local SIP server host aliases",    /* Documentation string */
 	0                                     /* Method signature(s) */
 };
 
 /**
  * list the name aliases for SIP server
  */
 static void core_aliases_list(rpc_t* rpc, void* c)
 {
 	void *hr;
 	void *ha;
 	struct host_alias* a;
 
 	rpc->add(c, "{", &hr);
 	rpc->struct_add(hr, "s",
 			"myself_callbacks", is_check_self_func_list_set()?"yes":"no");
 	for(a=aliases; a; a=a->next) {
 		rpc->struct_add(hr, "{", "alias", &ha);
 		rpc->struct_add(ha, "sS",
 				"proto",  proto2a(a->proto),
 				"address", &a->alias
 			);
 		if (a->port)
 			rpc->struct_add(ha, "d",
 					"port", a->port);
 		else
 			rpc->struct_add(ha, "s",
 					"port", "*");
 	}
 }
 
 /**
  *
  */
 static const char* core_sockets_list_doc[] = {
 	"List local SIP server listen sockets",    /* Documentation string */
 	0                                     /* Method signature(s) */
 };
 
 /**
  * list listen sockets for SIP server
  */
 static void core_sockets_list(rpc_t* rpc, void* c)
 {
 	void *hr;
 	void *ha;
 	struct socket_info *si;
 	struct socket_info** list;
 	struct addr_info* ai;
 	unsigned short proto;
 
 	proto=PROTO_UDP;
 	rpc->add(c, "{", &hr);
 	do{
 		list=get_sock_info_list(proto);
 		for(si=list?*list:0; si; si=si->next){
 			rpc->struct_add(hr, "{", "socket", &ha);
 			if (si->addr_info_lst){
 				rpc->struct_add(ha, "ss",
 						"proto", get_proto_name(proto),
 						"address", si->address_str.s);
 				for (ai=si->addr_info_lst; ai; ai=ai->next)
 					rpc->struct_add(ha, "ss",
 						"address", ai->address_str.s);
 				rpc->struct_add(ha, "sss",
03b955ef
 						"port", si->port_no_str.s,
a6c83dd4
 						"mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
 						"mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
 			} else {
 				printf("             %s: %s",
 						get_proto_name(proto),
 						si->name.s);
 				rpc->struct_add(ha, "ss",
 						"proto", get_proto_name(proto),
 						"address", si->name.s);
 				if (!si->flags & SI_IS_IP)
1c715b1a
 					rpc->struct_add(ha, "s",
a6c83dd4
 						"ipaddress", si->address_str.s);
 				rpc->struct_add(ha, "sss",
03b955ef
 						"port", si->port_no_str.s,
a6c83dd4
 						"mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
 						"mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
 			}
 		}
 	} while((proto=next_proto(proto)));
 }
27e652b7
 
 
566cde2d
 /*
  * RPC Methods exported by this module
58c1870c
  */
5099fd64
 static rpc_export_t core_rpc_methods[] = {
58c1870c
 	{"system.listMethods",     system_listMethods,     system_listMethods_doc,     RET_ARRAY},
e46483c8
 	{"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0        },
 	{"system.methodHelp",      system_methodHelp,      system_methodHelp_doc,      0        },
aafc8ea7
 	{"core.prints",            core_prints,            core_prints_doc,
 	RET_ARRAY},
 	{"core.printi",            core_printi,            core_printi_doc,
 	RET_ARRAY},
 	{"core.echo",              core_echo,              core_echo_doc,
 	RET_ARRAY},
20fd4b8b
 	{"core.version",           core_version,           core_version_doc,
 		0        },
 	{"core.flags",             core_flags,             core_flags_doc,
 		0        },
 	{"core.info",              core_info,              core_info_doc,
 		0        },
e46483c8
 	{"core.uptime",            core_uptime,            core_uptime_doc,            0        },
58c1870c
 	{"core.ps",                core_ps,                core_ps_doc,                RET_ARRAY},
73fb0285
 	{"core.psx",               core_psx,               core_psx_doc,               RET_ARRAY},
e46483c8
 	{"core.pwd",               core_pwd,               core_pwd_doc,               RET_ARRAY},
58c1870c
 	{"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
e46483c8
 	{"core.kill",              core_kill,              core_kill_doc,              0        },
566cde2d
 	{"core.shmmem",            core_shmmem,            core_shmmem_doc,            0	},
61551c02
 #if defined(SF_MALLOC) || defined(LL_MALLOC)
 	{"core.sfmalloc",          core_sfmalloc,          core_sfmalloc_doc,   0},
 #endif
20c64cc6
 	{"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,    0},
 	{"core.tcp_options",       core_tcp_options,       core_tcp_options_doc,0},
e567b3fd
 	{"core.tcp_list",          core_tcp_list,          core_tcp_list_doc,0},
27e652b7
 	{"core.udp4_raw_info",     core_udp4rawinfo,       core_udp4rawinfo_doc,
 		0},
a6c83dd4
 	{"core.aliases_list",      core_aliases_list,      core_aliases_list_doc,   0},
 	{"core.sockets_list",      core_sockets_list,      core_sockets_list_doc,   0},
dcb59e67
 #ifdef USE_DNS_CACHE
adc6fe8a
 	{"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,
 		0	},
 	{"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,
 		0	},
 	{"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,
 		0	},
 	{"dns.view",               dns_cache_view,        dns_cache_view_doc,
 		0	},
 	{"dns.lookup",             dns_cache_rpc_lookup,  dns_cache_rpc_lookup_doc,
 		0	},
 	{"dns.delete_all",         dns_cache_delete_all,  dns_cache_delete_all_doc,
 		0	},
ec79c28a
 	{"dns.delete_all_force",   dns_cache_delete_all_force, dns_cache_delete_all_force_doc,
 		0	},
adc6fe8a
 	{"dns.add_a",              dns_cache_add_a,       dns_cache_add_a_doc,
 		0	},
 	{"dns.add_aaaa",           dns_cache_add_aaaa,    dns_cache_add_aaaa_doc,
 		0	},
 	{"dns.add_srv",            dns_cache_add_srv,     dns_cache_add_srv_doc,
 		0	},
 	{"dns.delete_a",           dns_cache_delete_a,    dns_cache_delete_a_doc,
 		0	},
 	{"dns.delete_aaaa",        dns_cache_delete_aaaa,
 		dns_cache_delete_aaaa_doc, 0	},
 	{"dns.delete_srv",         dns_cache_delete_srv,
 		dns_cache_delete_srv_doc,  0	},
 	{"dns.delete_naptr",         dns_cache_delete_naptr,
 		dns_cache_delete_naptr_doc,  0	},
 	{"dns.delete_cname",         dns_cache_delete_cname,
 		dns_cache_delete_cname_doc,  0	},
 	{"dns.delete_txt",         dns_cache_delete_txt,
 		dns_cache_delete_txt_doc,  0	},
2c2dd816
 	{"dns.delete_ebl",         dns_cache_delete_ebl,
 		dns_cache_delete_ebl_doc,  0	},
d354557c
 	{"dns.delete_ptr",         dns_cache_delete_ptr,
 		dns_cache_delete_ptr_doc,  0	},
021e7e0e
 #ifdef USE_DNS_CACHE_STATS
adc6fe8a
 	{"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,
 		0	},
021e7e0e
 #endif /* USE_DNS_CACHE_STATS */
f682fd71
 #ifdef DNS_WATCHDOG_SUPPORT
adc6fe8a
 	{"dns.set_server_state",   dns_set_server_state_rpc,
 		dns_set_server_state_doc, 0 },
 	{"dns.get_server_state",   dns_get_server_state_rpc,
 		dns_get_server_state_doc, 0 },
f682fd71
 #endif
dcb59e67
 #endif
 #ifdef USE_DST_BLACKLIST
adc6fe8a
 	{"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,
 		0	},
 	{"dst_blacklist.debug",    dst_blst_debug,         dst_blst_debug_doc,
 		0	},
 	{"dst_blacklist.view",     dst_blst_view,         dst_blst_view_doc,
 		0	},
 	{"dst_blacklist.delete_all", dst_blst_delete_all, dst_blst_delete_all_doc,
 		0	},
 	{"dst_blacklist.add",      dst_blst_add,          dst_blst_add_doc,
 		0	},
021e7e0e
 #ifdef USE_DST_BLACKLIST_STATS
adc6fe8a
 	{"dst_blacklist.stats_get", dst_blst_stats_get, dst_blst_stats_get_doc, 0},
021e7e0e
 #endif /* USE_DST_BLACKLIST_STATS */
dcb59e67
 #endif
58c1870c
 	{0, 0, 0, 0}
 };
 
5099fd64
 
 
 int register_core_rpcs(void)
 {
 	int i;
 	
 	i=rpc_register_array(core_rpc_methods);
 	if (i<0){
 		BUG("failed to register core RPCs\n");
 		goto error;
 	}else if (i>0){
 		ERR("%d duplicate RPCs name detected while registering core RPCs\n",
 			 i);
 		goto error;
 	}
 	return 0;
 error:
 	return -1;
 }
 
 
 
58c1870c
 int rpc_init_time(void)
 {
 	char *t;
 	t=ctime(&up_since);
 	if (strlen(t)+1>=MAX_CTIME_LEN) {
 		ERR("Too long data %d\n", (int)strlen(t));
 		return -1;
 	}
 	memcpy(up_since_ctime,t,strlen(t)+1);
 	return 0;
 }