(core|modules/kex): improve RPC method listing
[sip-router] / src / core / core_cmd.c
1 /*
2  * Copyright (C) 2005 iptelorg GmbH
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 /** Kamailio Core :: core rpcs.
22  * @file core_cmd.c
23  * @ingroup core
24  */
25
26
27 #include <time.h>
28 #include <sys/types.h>
29 #include <signal.h>
30 #include "ver.h"
31 #include "mem/mem.h"
32 #include "mem/shm_mem.h"
33 #include "sr_module.h"
34 #include "rpc_lookup.h"
35 #include "dprint.h"
36 #include "core_cmd.h"
37 #include "globals.h"
38 #include "forward.h"
39 #include "socket_info.h"
40 #include "name_alias.h"
41 #include "pt.h"
42 #include "ut.h"
43 #include "tcp_info.h"
44 #include "tcp_conn.h"
45 #include "tcp_options.h"
46 #include "core_cmd.h"
47 #include "cfg_core.h"
48
49 #ifdef USE_DNS_CACHE
50 void dns_cache_debug(rpc_t* rpc, void* ctx);
51 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
52 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
53 void dns_cache_view(rpc_t* rpc, void* ctx);
54 void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx);
55 void dns_cache_delete_all(rpc_t* rpc, void* ctx);
56 void dns_cache_delete_all_force(rpc_t* rpc, void* ctx);
57 void dns_cache_add_a(rpc_t* rpc, void* ctx);
58 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx);
59 void dns_cache_add_srv(rpc_t* rpc, void* ctx);
60 void dns_cache_delete_a(rpc_t* rpc, void* ctx);
61 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx);
62 void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
63 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx);
64 void dns_cache_delete_cname(rpc_t* rpc, void* ctx);
65 void dns_cache_delete_txt(rpc_t* rpc, void* ctx);
66 void dns_cache_delete_ebl(rpc_t* rpc, void* ctx);
67 void dns_cache_delete_ptr(rpc_t* rpc, void* ctx);
68
69
70 static const char* dns_cache_mem_info_doc[] = {
71         "dns cache memory info.",    /* Documentation string */
72         0                      /* Method signature(s) */
73 };
74 static const char* dns_cache_debug_doc[] = {
75         "dns debug info.",    /* Documentation string */
76         0                      /* Method signature(s) */
77 };
78
79 static const char* dns_cache_debug_all_doc[] = {
80         "complete dns debug dump",    /* Documentation string */
81         0                              /* Method signature(s) */
82 };
83
84 static const char* dns_cache_view_doc[] = {
85         "dns cache dump in a human-readable format",
86         0
87 };
88
89 static const char* dns_cache_rpc_lookup_doc[] = {
90         "perform a dns lookup",
91         0
92 };
93
94 static const char* dns_cache_delete_all_doc[] = {
95         "deletes all the non-permanent entries from the DNS cache",
96         0
97 };
98
99 static const char* dns_cache_delete_all_force_doc[] = {
100         "deletes all the entries from the DNS cache including the permanent ones",
101         0
102 };
103
104 static const char* dns_cache_add_a_doc[] = {
105         "adds an A record to the DNS cache",
106         0
107 };
108
109 static const char* dns_cache_add_aaaa_doc[] = {
110         "adds an AAAA record to the DNS cache",
111         0
112 };
113 static const char* dns_cache_add_srv_doc[] = {
114         "adds an SRV record to the DNS cache",
115         0
116 };
117
118 static const char* dns_cache_delete_a_doc[] = {
119         "deletes an A record from the DNS cache",
120         0
121 };
122
123 static const char* dns_cache_delete_aaaa_doc[] = {
124         "deletes an AAAA record from the DNS cache",
125         0
126 };
127
128 static const char* dns_cache_delete_srv_doc[] = {
129         "deletes an SRV record from the DNS cache",
130         0
131 };
132
133 static const char* dns_cache_delete_naptr_doc[] = {
134         "deletes a NAPTR record from the DNS cache",
135         0
136 };
137
138 static const char* dns_cache_delete_cname_doc[] = {
139         "deletes a CNAME record from the DNS cache",
140         0
141 };
142
143 static const char* dns_cache_delete_txt_doc[] = {
144         "deletes a TXT record from the DNS cache",
145         0
146 };
147
148 static const char* dns_cache_delete_ebl_doc[] = {
149         "deletes an EBL record from the DNS cache",
150         0
151 };
152
153
154 static const char* dns_cache_delete_ptr_doc[] = {
155         "deletes an PTR record from the DNS cache",
156         0
157 };
158
159
160 #ifdef USE_DNS_CACHE_STATS
161 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
162
163 static const char* dns_cache_stats_get_doc[] = {
164         "returns the dns measurement counters.",
165         0
166 };
167 #endif /* USE_DNS_CACHE_STATS */
168 #ifdef DNS_WATCHDOG_SUPPORT
169 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
170
171 static const char* dns_set_server_state_doc[] = {
172         "sets the state of the DNS servers " \
173         "(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
174         0                              /* Method signature(s) */
175 };
176
177 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx);
178
179 static const char* dns_get_server_state_doc[] = {
180         "prints the state of the DNS servers " \
181         "(0: all the servers are down, 1: at least one server is up)",  /* Documentation string */
182         0                               /* Method signature(s) */
183 };
184
185 #endif /* DNS_WATCHDOG_SUPPORT */
186 #endif /* USE_DNS_CACHE */
187 #ifdef USE_DST_BLACKLIST
188 void dst_blst_debug(rpc_t* rpc, void* ctx);
189 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
190 void dst_blst_view(rpc_t* rpc, void* ctx);
191 void dst_blst_delete_all(rpc_t* rpc, void* ctx);
192 void dst_blst_add(rpc_t* rpc, void* ctx);
193
194 static const char* dst_blst_mem_info_doc[] = {
195         "dst blacklist memory usage info.",  /* Documentation string */
196         0                                    /* Method signature(s) */
197 };
198 static const char* dst_blst_debug_doc[] = {
199         "dst blacklist debug info.",  /* Documentation string */
200         0                               /* Method signature(s) */
201 };
202 static const char* dst_blst_view_doc[] = {
203         "dst blacklist dump in human-readable format.",  /* Documentation string */
204         0                               /* Method signature(s) */
205 };
206 static const char* dst_blst_delete_all_doc[] = {
207         "Deletes all the entries from the dst blacklist except the permanent ones.",  /* Documentation string */
208         0                               /* Method signature(s) */
209 };
210 static const char* dst_blst_add_doc[] = {
211         "Adds a new entry to the dst blacklist.",  /* Documentation string */
212         0                               /* Method signature(s) */
213 };
214 #ifdef USE_DST_BLACKLIST_STATS
215 void dst_blst_stats_get(rpc_t* rpc, void* ctx);
216
217 static const char* dst_blst_stats_get_doc[] = {
218         "returns the dst blacklist measurement counters.",
219         0
220 };
221 #endif /* USE_DST_BLACKLIST_STATS */
222
223 #endif
224
225
226
227 #define MAX_CTIME_LEN 128
228
229 /* up time */
230 static char up_since_ctime[MAX_CTIME_LEN];
231
232
233 static const char* system_listMethods_doc[] = {
234         "Lists all RPC methods supported by the server.",  /* Documentation string */
235         0                                                  /* Method signature(s) */
236 };
237
238 static void system_listMethods(rpc_t* rpc, void* c)
239 {
240         int i;
241
242         for(i=0; i<rpc_sarray_crt_size; i++){
243                 if (rpc->add(c, "s", rpc_sarray[i]->name) < 0) return;
244         }
245 }
246
247 static const char* system_methodSignature_doc[] = {
248         "Returns signature of given method.",  /* Documentation string */
249         0                                      /* Method signature(s) */
250 };
251
252 static void system_methodSignature(rpc_t* rpc, void* c)
253 {
254         rpc->fault(c, 500, "Not Implemented Yet");
255 }
256
257
258 static const char* system_methodHelp_doc[] = {
259         "Print the help string for given method.",  /* Documentation string */
260         0                                           /* Method signature(s) */
261 };
262
263 static void system_methodHelp(rpc_t* rpc, void* c)
264 {
265         rpc_export_t* r;
266         char* name;
267
268         if (rpc->scan(c, "s", &name) < 1) {
269                 rpc->fault(c, 400, "Method Name Expected");
270                 return;
271         }
272         
273         r=rpc_lookup(name, strlen(name));
274         if (r==0){
275                 rpc->fault(c, 400, "command not found");
276         }else{
277                 if (r->doc_str && r->doc_str[0]) {
278                         rpc->add(c, "s", r->doc_str[0]);
279                 } else {
280                         rpc->add(c, "s", "undocumented");
281                 }
282         }
283         return;
284 }
285
286
287 static const char* core_prints_doc[] = {
288         "Returns the strings given as parameters.",   /* Documentation string */
289         0                                             /* Method signature(s) */
290 };
291
292
293 static void core_prints(rpc_t* rpc, void* c)
294 {
295         char* string = 0;
296         while((rpc->scan(c, "*s", &string)>0))
297                 rpc->add(c, "s", string);
298 }
299
300
301 static const char* core_printi_doc[] = {
302         "Returns the integers given as parameters.",  /* Documentation string */
303         0                                             /* Method signature(s) */
304 };
305
306
307 static void core_printi(rpc_t* rpc, void* c)
308 {
309         int i;
310         while((rpc->scan(c, "*d", &i)>0))
311                 rpc->add(c, "d", i);
312 }
313
314
315 static const char* core_echo_doc[] = {
316         "Returns back its parameters.",              /* Documentation string */
317         0                                             /* Method signature(s) */
318 };
319
320
321 static void core_echo(rpc_t* rpc, void* c)
322 {
323         char* string = 0;
324         while((rpc->scan(c, "*.s", &string)>0))
325                 rpc->add(c, "s", string);
326 }
327
328
329 static const char* core_version_doc[] = {
330         "Returns the version string of the server.", /* Documentation string */
331         0                                           /* Method signature(s) */
332 };
333
334 static void core_version(rpc_t* rpc, void* c)
335 {
336         rpc->add(c, "s", full_version);
337 }
338
339
340
341 static const char* core_flags_doc[] = {
342         "Returns the compile flags.", /* Documentation string */
343         0                             /* Method signature(s) */
344 };
345
346 static void core_flags(rpc_t* rpc, void* c)
347 {
348         rpc->add(c, "s", ver_flags);
349 }
350
351
352
353 static const char* core_info_doc[] = {
354         "Verbose info, including version number, compile flags, compiler,"
355         "repository hash a.s.o.",     /* Documentation string */
356         0                             /* Method signature(s) */
357 };
358
359 static void core_info(rpc_t* rpc, void* c)
360 {
361         void* s;
362
363         if (rpc->add(c, "{", &s) < 0) return;
364         rpc->struct_printf(s, "version", "%s %s", ver_name, ver_version);
365         rpc->struct_add(s, "s", "id", ver_id);
366         rpc->struct_add(s, "s", "compiler", ver_compiler);
367         rpc->struct_add(s, "s", "compiled", ver_compiled_time);
368         rpc->struct_add(s, "s", "flags", ver_flags);
369 }
370
371
372
373 static const char* core_uptime_doc[] = {
374         "Returns uptime of SIP server.",  /* Documentation string */
375         0                                 /* Method signature(s) */
376 };
377
378
379 static void core_uptime(rpc_t* rpc, void* c)
380 {
381         void* s;
382         time_t now;
383         str snow;
384
385         time(&now);
386
387         if (rpc->add(c, "{", &s) < 0) return;
388         snow.s = ctime(&now);
389         if(snow.s) {
390                 snow.len = strlen(snow.s);
391                 if(snow.len>2 && snow.s[snow.len-1]=='\n') snow.len--;
392                 rpc->struct_add(s, "S", "now", &snow);
393         }
394         rpc->struct_add(s, "s", "up_since", up_since_ctime);
395         /* no need for a float here (unless you're concerned that your uptime)
396         rpc->struct_add(s, "f", "uptime",  difftime(now, up_since));
397         */
398         /* on posix system we can substract time_t directly */
399         rpc->struct_add(s, "d", "uptime",  (int)(now-up_since));
400 }
401
402
403 static const char* core_ps_doc[] = {
404         "Returns the description of running processes.",  /* Documentation string */
405         0                                                     /* Method signature(s) */
406 };
407
408
409 static void core_ps(rpc_t* rpc, void* c)
410 {
411         int p;
412
413         for (p=0; p<*process_count;p++) {
414                 rpc->add(c, "d", pt[p].pid);
415                 rpc->add(c, "s", pt[p].desc);
416         }
417 }
418
419 static const char* core_psx_doc[] = {
420         "Returns the detailed description of running processes.",
421                 /* Documentation string */
422         0       /* Method signature(s) */
423 };
424
425
426 static void core_psx(rpc_t* rpc, void* c)
427 {
428         int p;
429         void *handle;
430
431         for (p=0; p<*process_count;p++) {
432                 rpc->add(c, "{", &handle);
433                 rpc->struct_add(handle, "dds",
434                                 "IDX", p,
435                                 "PID", pt[p].pid,
436                                 "DSC", pt[p].desc);
437         }
438 }
439
440
441 static const char* core_pwd_doc[] = {
442         "Returns the working directory of server.",    /* Documentation string */
443         0                                              /* Method signature(s) */
444 };
445
446
447 static void core_pwd(rpc_t* rpc, void* c)
448 {
449         char *cwd_buf;
450         int max_len;
451
452         max_len = pathmax();
453         cwd_buf = pkg_malloc(max_len);
454         if (!cwd_buf) {
455                 ERR("core_pwd: No memory left\n");
456                 rpc->fault(c, 500, "Server Ran Out of Memory");
457                 return;
458         }
459
460         if (getcwd(cwd_buf, max_len)) {
461                 rpc->add(c, "s", cwd_buf);
462         } else {
463                 rpc->fault(c, 500, "getcwd Failed");
464         }
465         pkg_free(cwd_buf);
466 }
467
468
469 static const char* core_arg_doc[] = {
470         "Returns the list of command line arguments used on startup.",  /* Documentation string */
471         0                                                               /* Method signature(s) */
472 };
473
474
475 static void core_arg(rpc_t* rpc, void* c)
476 {
477         int p;
478
479         for (p = 0; p < my_argc; p++) {
480                 if (rpc->add(c, "s", my_argv[p]) < 0) return;
481         }
482 }
483
484
485 static const char* core_kill_doc[] = {
486         "Sends the given signal to server.",  /* Documentation string */
487         0                                     /* Method signature(s) */
488 };
489
490
491 static void core_kill(rpc_t* rpc, void* c)
492 {
493         int sig_no = 15;
494         rpc->scan(c, "d", &sig_no);
495         rpc->send(c);
496         kill(0, sig_no);
497 }
498
499 static void core_shmmem(rpc_t* rpc, void* c)
500 {
501         struct mem_info mi;
502         void *handle;
503         char* param;
504         long rs;
505
506         rs=0;
507         /* look for optional size/divisor parameter */
508         if (rpc->scan(c, "*s", &param)>0){
509                 switch(*param){
510                         case 'b':
511                         case 'B':
512                                 rs=0;
513                                 break;
514                         case 'k':
515                         case 'K':
516                                 rs=10; /* K -> 1024 */
517                                 break;
518                         case 'm':
519                         case 'M':
520                                 rs=20; /* M -> 1048576 */
521                                 break;
522                         case 'g':
523                         case 'G':
524                                 rs=30; /* G -> 1024M */
525                                 break;
526                         default:
527                                 rpc->fault(c, 500, "bad param, (use b|k|m|g)");
528                                 return;
529                 }
530                 if (param[1] && ((param[1]!='b' && param[1]!='B') || param[2])){
531                                 rpc->fault(c, 500, "bad param, (use b|k|m|g)");
532                                 return;
533                 }
534         }
535         shm_info(&mi);
536         rpc->add(c, "{", &handle);
537         rpc->struct_add(handle, "dddddd",
538                 "total", (unsigned int)(mi.total_size>>rs),
539                 "free", (unsigned int)(mi.free>>rs),
540                 "used", (unsigned int)(mi.used>>rs),
541                 "real_used",(unsigned int)(mi.real_used>>rs),
542                 "max_used", (unsigned int)(mi.max_used>>rs),
543                 "fragments", (unsigned int)mi.total_frags
544         );
545 }
546
547 static const char* core_shmmem_doc[] = {
548         "Returns shared memory info. It has an optional parameter that specifies"
549         " the measuring unit: b - bytes (default), k or kb, m or mb, g or gb. "
550         "Note: when using something different from bytes, the value is truncated.",
551         0                               /* Method signature(s) */
552 };
553
554
555 #if defined(SF_MALLOC) || defined(LL_MALLOC)
556 static void core_sfmalloc(rpc_t* rpc, void* c)
557 {
558         void *handle;
559         int i,r;
560         unsigned long frags, main_s_frags, main_b_frags, pool_frags;
561         unsigned long misses;
562         unsigned long max_misses;
563         unsigned long max_frags;
564         unsigned long max_mem;
565         int max_frags_pool, max_frags_hash;
566         int max_misses_pool, max_misses_hash;
567         int max_mem_pool, max_mem_hash;
568         unsigned long mem;
569
570         if (rpc->scan(c, "d", &r) >= 1) {
571                 if (r>=(int)SF_HASH_POOL_SIZE){
572                         rpc->fault(c, 500, "invalid hash number %d (max %d)",
573                                                                 r, (unsigned int)SF_HASH_POOL_SIZE-1);
574                         return;
575                 }else if (r<0) goto all;
576                 rpc->add(c, "{", &handle);
577                 rpc->struct_add(handle, "dd",
578                                 "hash  ", r,
579                                 "size  ", r*SF_ROUNDTO);
580                 for (i=0; i<SFM_POOLS_NO; i++){
581                         rpc->struct_add(handle, "dddd",
582                                 "pool  ", i,
583                                 "frags ", (unsigned int)shm_block->pool[i].pool_hash[r].no,
584                                 "misses", (unsigned int)shm_block->pool[i].pool_hash[r].misses,
585                                 "mem   ",   (unsigned int)shm_block->pool[i].pool_hash[r].no *
586                                                         r*SF_ROUNDTO
587                         );
588                 }
589         }
590         return;
591 all:
592         max_frags=max_misses=max_mem=0;
593         max_frags_pool=max_frags_hash=0;
594         max_misses_pool=max_misses_hash=0;
595         max_mem_pool=max_mem_hash=0;
596         pool_frags=0;
597         for (i=0; i<SFM_POOLS_NO; i++){
598                 frags=0;
599                 misses=0;
600                 mem=0;
601                 for (r=0; r<SF_HASH_POOL_SIZE; r++){
602                         frags+=shm_block->pool[i].pool_hash[r].no;
603                         misses+=shm_block->pool[i].pool_hash[r].misses;
604                         mem+=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
605                         if (shm_block->pool[i].pool_hash[r].no>max_frags){
606                                 max_frags=shm_block->pool[i].pool_hash[r].no;
607                                 max_frags_pool=i;
608                                 max_frags_hash=r;
609                         }
610                         if (shm_block->pool[i].pool_hash[r].misses>max_misses){
611                                 max_misses=shm_block->pool[i].pool_hash[r].misses;
612                                 max_misses_pool=i;
613                                 max_misses_hash=r;
614                         }
615                         if (shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO>max_mem){
616                                 max_mem=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
617                                 max_mem_pool=i;
618                                 max_mem_hash=r;
619                         }
620                 }
621                 rpc->add(c, "{", &handle);
622                 rpc->struct_add(handle, "dddddd",
623                         "pool  ", i,
624                         "frags ", (unsigned int)frags,
625                         "t. misses", (unsigned int)misses,
626                         "mem   ", (unsigned int)mem,
627                         "missed", (unsigned int)shm_block->pool[i].missed,
628                         "hits",   (unsigned int)shm_block->pool[i].hits
629                 );
630                 pool_frags+=frags;
631         }
632         main_s_frags=0;
633         for (r=0; r<SF_HASH_POOL_SIZE; r++){
634                 main_s_frags+=shm_block->free_hash[r].no;
635         }
636         main_b_frags=0;
637         for (; r<SF_HASH_SIZE; r++){
638                 main_b_frags+=shm_block->free_hash[r].no;
639         }
640         rpc->add(c, "{", &handle);
641         rpc->struct_add(handle, "ddddddddddddd",
642                 "max_frags      ", (unsigned int)max_frags,
643                 "max_frags_pool ", max_frags_pool,
644                 "max_frags_hash", max_frags_hash,
645                 "max_misses     ", (unsigned int)max_misses,
646                 "max_misses_pool", max_misses_pool,
647                 "max_misses_hash", max_misses_hash,
648                 "max_mem        ", (unsigned int)max_mem,
649                 "max_mem_pool   ", max_mem_pool,
650                 "max_mem_hash   ", max_mem_hash,
651                 "in_pools_frags ", (unsigned int)pool_frags,
652                 "main_s_frags   ", (unsigned int)main_s_frags,
653                 "main_b_frags   ", (unsigned int)main_b_frags,
654                 "main_frags     ", (unsigned int)(main_b_frags+main_s_frags)
655         );
656 }
657
658
659
660 static const char* core_sfmalloc_doc[] = {
661         "Returns sfmalloc debugging info.",  /* Documentation string */
662         0                                     /* Method signature(s) */
663 };
664
665 #endif
666
667
668
669 static const char* core_tcpinfo_doc[] = {
670         "Returns tcp related info.",    /* Documentation string */
671         0                               /* Method signature(s) */
672 };
673
674 static void core_tcpinfo(rpc_t* rpc, void* c)
675 {
676 #ifdef USE_TCP
677         void *handle;
678         struct tcp_gen_info ti;
679
680         if (!tcp_disable){
681                 tcp_get_info(&ti);
682                 rpc->add(c, "{", &handle);
683                 rpc->struct_add(handle, "dddddd",
684                         "readers", ti.tcp_readers,
685                         "max_connections", ti.tcp_max_connections,
686                         "max_tls_connections", ti.tls_max_connections,
687                         "opened_connections", ti.tcp_connections_no,
688                         "opened_tls_connections", ti.tls_connections_no,
689                         "write_queued_bytes", ti.tcp_write_queued
690                 );
691         }else{
692                 rpc->fault(c, 500, "tcp support disabled");
693         }
694 #else
695         rpc->fault(c, 500, "tcp support not compiled");
696 #endif
697 }
698
699
700
701 static const char* core_tcp_options_doc[] = {
702         "Returns active tcp options.",    /* Documentation string */
703         0                                 /* Method signature(s) */
704 };
705
706 static void core_tcp_options(rpc_t* rpc, void* c)
707 {
708 #ifdef USE_TCP
709         void *handle;
710         struct cfg_group_tcp t;
711
712         if (!tcp_disable){
713                 tcp_options_get(&t);
714                 rpc->add(c, "{", &handle);
715                 rpc->struct_add(handle, "ddddddddddddddddddddddd",
716                         "connect_timeout", t.connect_timeout_s,
717                         "send_timeout",  TICKS_TO_S(t.send_timeout),
718                         "connection_lifetime",  TICKS_TO_S(t.con_lifetime),
719                         "max_connections(soft)", t.max_connections,
720                         "max_tls_connections(soft)", t.max_tls_connections,
721                         "no_connect",   t.no_connect,
722                         "fd_cache",             t.fd_cache,
723                         "async",                t.async,
724                         "connect_wait", t.tcp_connect_wait,
725                         "conn_wq_max",  t.tcpconn_wq_max,
726                         "wq_max",               t.tcp_wq_max,
727                         "defer_accept", t.defer_accept,
728                         "delayed_ack",  t.delayed_ack,
729                         "syncnt",               t.syncnt,
730                         "linger2",              t.linger2,
731                         "keepalive",    t.keepalive,
732                         "keepidle",             t.keepidle,
733                         "keepintvl",    t.keepintvl,
734                         "keepcnt",              t.keepcnt,
735                         "crlf_ping",    t.crlf_ping,
736                         "accept_aliases", t.accept_aliases,
737                         "alias_flags",  t.alias_flags,
738                         "new_conn_alias_flags", t.new_conn_alias_flags
739                 );
740         }else{
741                 rpc->fault(c, 500, "tcp support disabled");
742         }
743 #else
744         rpc->fault(c, 500, "tcp support not compiled");
745 #endif
746 }
747
748
749 static const char* core_tcp_list_doc[] = {
750         "Returns tcp connections details.",    /* Documentation string */
751         0                               /* Method signature(s) */
752 };
753
754 extern gen_lock_t* tcpconn_lock;
755 extern struct tcp_connection** tcpconn_id_hash;
756
757 static void core_tcp_list(rpc_t* rpc, void* c)
758 {
759 #ifdef USE_TCP
760         char src_ip[IP_ADDR_MAX_STR_SIZE];
761         char dst_ip[IP_ADDR_MAX_STR_SIZE];
762         void* handle;
763         char* state;
764         char* type;
765         struct tcp_connection* con;
766         int i, len, timeout, lifetime;
767
768         if (tcp_disable) {
769                 rpc->fault(c, 500, "tcp support disabled");
770                 return;
771         }
772
773         TCPCONN_LOCK;
774         for(i = 0; i < TCP_ID_HASH_SIZE; i++) {
775                 for (con = tcpconn_id_hash[i]; con; con = con->id_next) {
776                         rpc->add(c, "{", &handle);
777                         /* tcp data */
778                         if (con->rcv.proto == PROTO_TCP)
779                                 type = "TCP";
780                         else if (con->rcv.proto == PROTO_TLS)
781                                 type = "TLS";
782                         else if (con->rcv.proto == PROTO_WSS)
783                                 type = "WSS";
784                         else if (con->rcv.proto == PROTO_WS)
785                                 type = "WS";
786                         else
787                                 type = "UNKNOWN";
788
789                         if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip)))
790                                         == 0)
791                                 BUG("failed to convert source ip");
792                         src_ip[len] = 0;
793                         if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip)))
794                                         == 0)
795                                 BUG("failed to convert destination ip");
796                         dst_ip[len] = 0;
797                         timeout = TICKS_TO_S(con->timeout - get_ticks_raw());
798                         lifetime = TICKS_TO_S(con->lifetime);
799                         switch(con->state) {
800                                 case S_CONN_ERROR:
801                                         state = "CONN_ERROR";
802                                 break;
803                                 case S_CONN_BAD:
804                                         state = "CONN_BAD";
805                                 break;
806                                 case S_CONN_OK:
807                                         state = "CONN_OK";
808                                 break;
809                                 case S_CONN_INIT:
810                                         state = "CONN_INIT";
811                                 break;
812                                 case S_CONN_EOF:
813                                         state = "CONN_EOF";
814                                 break;
815                                 case S_CONN_ACCEPT:
816                                         state = "CONN_ACCEPT";
817                                 break;
818                                 case S_CONN_CONNECT:
819                                         state = "CONN_CONNECT";
820                                 break;
821                                 default:
822                                         state = "UNKNOWN";
823                         }
824                         rpc->struct_add(handle, "dssdddsdsd",
825                                         "id", con->id,
826                                         "type", type,
827                                         "state", state,
828                                         "timeout", timeout,
829                                         "lifetime", lifetime,
830                                         "ref_count", con->refcnt,
831                                         "src_ip", src_ip,
832                                         "src_port", con->rcv.src_port,
833                                         "dst_ip", dst_ip,
834                                         "dst_port", con->rcv.dst_port);
835                 }
836         }
837         TCPCONN_UNLOCK;
838 #else
839         rpc->fault(c, 500, "tcp support not compiled");
840 #endif
841 }
842
843
844 static const char* core_udp4rawinfo_doc[] = {
845         "Returns udp4_raw related info.",    /* Documentation string */
846         0                                     /* Method signature(s) */
847 };
848
849 static void core_udp4rawinfo(rpc_t* rpc, void* c)
850 {
851 #ifdef USE_RAW_SOCKS
852         void *handle;
853
854         rpc->add(c, "{", &handle);
855         rpc->struct_add(handle, "ddd",
856                 "udp4_raw", cfg_get(core, core_cfg, udp4_raw),
857                 "udp4_raw_mtu", cfg_get(core, core_cfg, udp4_raw_mtu),
858                 "udp4_raw_ttl", cfg_get(core, core_cfg, udp4_raw_ttl)
859         );
860 #else /* USE_RAW_SOCKS */
861         rpc->fault(c, 500, "udp4_raw mode support not compiled");
862 #endif /* USE_RAW_SOCKS */
863 }
864
865 /**
866  *
867  */
868 static const char* core_aliases_list_doc[] = {
869         "List local SIP server host aliases",    /* Documentation string */
870         0                                     /* Method signature(s) */
871 };
872
873 /**
874  * list the name aliases for SIP server
875  */
876 static void core_aliases_list(rpc_t* rpc, void* c)
877 {
878         void *hr;
879         void *hs;
880         void *ha;
881         struct host_alias* a;
882
883         rpc->add(c, "{", &hr);
884         rpc->struct_add(hr, "s",
885                         "myself_callbacks", is_check_self_func_list_set()?"yes":"no");
886         rpc->struct_add(hr, "[", "aliases", &hs);
887         for(a=aliases; a; a=a->next) {
888                 rpc->struct_add(hs, "{", "alias", &ha);
889                 rpc->struct_add(ha, "sS",
890                                 "proto",  proto2a(a->proto),
891                                 "address", &a->alias
892                         );
893                 if (a->port)
894                         rpc->struct_add(ha, "d",
895                                         "port", a->port);
896                 else
897                         rpc->struct_add(ha, "s",
898                                         "port", "*");
899         }
900 }
901
902 /**
903  *
904  */
905 static const char* core_sockets_list_doc[] = {
906         "List local SIP server listen sockets",    /* Documentation string */
907         0                                          /* Method signature(s) */
908 };
909
910 /**
911  * list listen sockets for SIP server
912  */
913 static void core_sockets_list(rpc_t* rpc, void* c)
914 {
915         void *hr;
916         void *ha;
917         struct socket_info *si;
918         struct socket_info** list;
919         struct addr_info* ai;
920         unsigned short proto;
921
922         proto=PROTO_UDP;
923         rpc->add(c, "[", &hr);
924         do{
925                 list=get_sock_info_list(proto);
926                 for(si=list?*list:0; si; si=si->next){
927                         rpc->struct_add(hr, "{", "socket", &ha);
928                         if (si->addr_info_lst){
929                                 rpc->struct_add(ha, "ss",
930                                                 "proto", get_proto_name(proto),
931                                                 "address", si->address_str.s);
932                                 for (ai=si->addr_info_lst; ai; ai=ai->next)
933                                         rpc->struct_add(ha, "ss",
934                                                 "address", ai->address_str.s);
935                                 rpc->struct_add(ha, "sss",
936                                                 "port", si->port_no_str.s,
937                                                 "mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
938                                                 "mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
939                         } else {
940                                 printf("             %s: %s",
941                                                 get_proto_name(proto),
942                                                 si->name.s);
943                                 rpc->struct_add(ha, "ss",
944                                                 "proto", get_proto_name(proto),
945                                                 "address", si->name.s);
946                                 if (!si->flags & SI_IS_IP)
947                                         rpc->struct_add(ha, "s",
948                                                 "ipaddress", si->address_str.s);
949                                 rpc->struct_add(ha, "sss",
950                                                 "port", si->port_no_str.s,
951                                                 "mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
952                                                 "mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
953                         }
954                 }
955         } while((proto=next_proto(proto)));
956 }
957
958
959 /*
960  * RPC Methods exported by core
961  */
962 static rpc_export_t core_rpc_methods[] = {
963         {"system.listMethods",     system_listMethods,     system_listMethods_doc,     RET_ARRAY},
964         {"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0        },
965         {"system.methodHelp",      system_methodHelp,      system_methodHelp_doc,      0        },
966         {"core.prints",            core_prints,            core_prints_doc,
967         RET_ARRAY},
968         {"core.printi",            core_printi,            core_printi_doc,
969         RET_ARRAY},
970         {"core.echo",              core_echo,              core_echo_doc,
971         RET_ARRAY},
972         {"core.version",           core_version,           core_version_doc,
973                 0        },
974         {"core.flags",             core_flags,             core_flags_doc,
975                 0        },
976         {"core.info",              core_info,              core_info_doc,
977                 0        },
978         {"core.uptime",            core_uptime,            core_uptime_doc,            0        },
979         {"core.ps",                core_ps,                core_ps_doc,                RET_ARRAY},
980         {"core.psx",               core_psx,               core_psx_doc,               RET_ARRAY},
981         {"core.pwd",               core_pwd,               core_pwd_doc,               RET_ARRAY},
982         {"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
983         {"core.kill",              core_kill,              core_kill_doc,              0        },
984         {"core.shmmem",            core_shmmem,            core_shmmem_doc,            0        },
985 #if defined(SF_MALLOC) || defined(LL_MALLOC)
986         {"core.sfmalloc",          core_sfmalloc,          core_sfmalloc_doc,   0},
987 #endif
988         {"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,    0},
989         {"core.tcp_options",       core_tcp_options,       core_tcp_options_doc,0},
990         {"core.tcp_list",          core_tcp_list,          core_tcp_list_doc,0},
991         {"core.udp4_raw_info",     core_udp4rawinfo,       core_udp4rawinfo_doc,
992                 0},
993         {"core.aliases_list",      core_aliases_list,      core_aliases_list_doc,   0},
994         {"core.sockets_list",      core_sockets_list,      core_sockets_list_doc,   0},
995 #ifdef USE_DNS_CACHE
996         {"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,
997                 0       },
998         {"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,
999                 0       },
1000         {"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,
1001                 0       },
1002         {"dns.view",               dns_cache_view,        dns_cache_view_doc,
1003                 0       },
1004         {"dns.lookup",             dns_cache_rpc_lookup,  dns_cache_rpc_lookup_doc,
1005                 0       },
1006         {"dns.delete_all",         dns_cache_delete_all,  dns_cache_delete_all_doc,
1007                 0       },
1008         {"dns.delete_all_force",   dns_cache_delete_all_force, dns_cache_delete_all_force_doc,
1009                 0       },
1010         {"dns.add_a",              dns_cache_add_a,       dns_cache_add_a_doc,
1011                 0       },
1012         {"dns.add_aaaa",           dns_cache_add_aaaa,    dns_cache_add_aaaa_doc,
1013                 0       },
1014         {"dns.add_srv",            dns_cache_add_srv,     dns_cache_add_srv_doc,
1015                 0       },
1016         {"dns.delete_a",           dns_cache_delete_a,    dns_cache_delete_a_doc,
1017                 0       },
1018         {"dns.delete_aaaa",        dns_cache_delete_aaaa,
1019                 dns_cache_delete_aaaa_doc, 0    },
1020         {"dns.delete_srv",         dns_cache_delete_srv,
1021                 dns_cache_delete_srv_doc,  0    },
1022         {"dns.delete_naptr",         dns_cache_delete_naptr,
1023                 dns_cache_delete_naptr_doc,  0  },
1024         {"dns.delete_cname",         dns_cache_delete_cname,
1025                 dns_cache_delete_cname_doc,  0  },
1026         {"dns.delete_txt",         dns_cache_delete_txt,
1027                 dns_cache_delete_txt_doc,  0    },
1028         {"dns.delete_ebl",         dns_cache_delete_ebl,
1029                 dns_cache_delete_ebl_doc,  0    },
1030         {"dns.delete_ptr",         dns_cache_delete_ptr,
1031                 dns_cache_delete_ptr_doc,  0    },
1032 #ifdef USE_DNS_CACHE_STATS
1033         {"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,
1034                 0       },
1035 #endif /* USE_DNS_CACHE_STATS */
1036 #ifdef DNS_WATCHDOG_SUPPORT
1037         {"dns.set_server_state",   dns_set_server_state_rpc,
1038                 dns_set_server_state_doc, 0 },
1039         {"dns.get_server_state",   dns_get_server_state_rpc,
1040                 dns_get_server_state_doc, 0 },
1041 #endif
1042 #endif
1043 #ifdef USE_DST_BLACKLIST
1044         {"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,
1045                 0       },
1046         {"dst_blacklist.debug",    dst_blst_debug,         dst_blst_debug_doc,
1047                 0       },
1048         {"dst_blacklist.view",     dst_blst_view,         dst_blst_view_doc,
1049                 0       },
1050         {"dst_blacklist.delete_all", dst_blst_delete_all, dst_blst_delete_all_doc,
1051                 0       },
1052         {"dst_blacklist.add",      dst_blst_add,          dst_blst_add_doc,
1053                 0       },
1054 #ifdef USE_DST_BLACKLIST_STATS
1055         {"dst_blacklist.stats_get", dst_blst_stats_get, dst_blst_stats_get_doc, 0},
1056 #endif /* USE_DST_BLACKLIST_STATS */
1057 #endif
1058         {0, 0, 0, 0}
1059 };
1060
1061
1062
1063 int register_core_rpcs(void)
1064 {
1065         int i;
1066
1067         i=rpc_register_array(core_rpc_methods);
1068         if (i<0){
1069                 BUG("failed to register core RPCs\n");
1070                 goto error;
1071         }else if (i>0){
1072                 ERR("%d duplicate RPCs name detected while registering core RPCs\n",
1073                          i);
1074                 goto error;
1075         }
1076         return 0;
1077 error:
1078         return -1;
1079 }
1080
1081
1082
1083 int rpc_init_time(void)
1084 {
1085         char *t;
1086         t=ctime(&up_since);
1087         if (strlen(t)+1>=MAX_CTIME_LEN) {
1088                 ERR("Too long data %d\n", (int)strlen(t));
1089                 return -1;
1090         }
1091         strcpy(up_since_ctime, t);
1092         t = up_since_ctime + strlen(up_since_ctime);
1093         while(t>up_since_ctime) {
1094                 if(*t=='\0' || *t=='\r' || *t=='\n') {
1095                         *t = '\0';
1096                 } else {
1097                         break;
1098                 }
1099                 t--;
1100         }
1101         return 0;
1102 }