Makefile.defs: version set 3.4.0-dev2
[sip-router] / core_cmd.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2005 iptelorg GmbH
5  *
6  * This file is part of SIP-router, a free SIP server.
7  *
8  * SIP-router is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * SIP-router is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /** core rpcs.
24  * @file core_cmd.c
25  * @ingroup core
26  */
27
28
29 #include <time.h>
30 #include <sys/types.h>
31 #include <signal.h>
32 #include "ver.h"
33 #include "mem/mem.h"
34 #include "mem/shm_mem.h"
35 #include "sr_module.h"
36 #include "rpc_lookup.h"
37 #include "dprint.h"
38 #include "core_cmd.h"
39 #include "globals.h"
40 #include "forward.h"
41 #include "socket_info.h"
42 #include "name_alias.h"
43 #include "pt.h"
44 #include "ut.h"
45 #include "tcp_info.h"
46 #include "tcp_conn.h"
47 #include "tcp_options.h"
48 #include "core_cmd.h"
49 #include "cfg_core.h"
50 #ifdef USE_SCTP
51 #include "sctp_options.h"
52 #include "sctp_server.h"
53 #endif
54
55 #ifdef USE_DNS_CACHE
56 void dns_cache_debug(rpc_t* rpc, void* ctx);
57 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
58 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
59 void dns_cache_view(rpc_t* rpc, void* ctx);
60 void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx);
61 void dns_cache_delete_all(rpc_t* rpc, void* ctx);
62 void dns_cache_delete_all_force(rpc_t* rpc, void* ctx);
63 void dns_cache_add_a(rpc_t* rpc, void* ctx);
64 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx);
65 void dns_cache_add_srv(rpc_t* rpc, void* ctx);
66 void dns_cache_delete_a(rpc_t* rpc, void* ctx);
67 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx);
68 void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
69 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx);
70 void dns_cache_delete_cname(rpc_t* rpc, void* ctx);
71 void dns_cache_delete_txt(rpc_t* rpc, void* ctx);
72 void dns_cache_delete_ebl(rpc_t* rpc, void* ctx);
73 void dns_cache_delete_ptr(rpc_t* rpc, void* ctx);
74
75
76 static const char* dns_cache_mem_info_doc[] = {
77         "dns cache memory info.",    /* Documentation string */
78         0                      /* Method signature(s) */
79 };
80 static const char* dns_cache_debug_doc[] = {
81         "dns debug  info.",    /* Documentation string */
82         0                      /* Method signature(s) */
83 };
84
85 static const char* dns_cache_debug_all_doc[] = {
86         "complete dns debug  dump",    /* Documentation string */
87         0                              /* Method signature(s) */
88 };
89
90 static const char* dns_cache_view_doc[] = {
91         "dns cache dump in a human-readable format",
92         0
93 };
94
95 static const char* dns_cache_rpc_lookup_doc[] = {
96         "perform a dns lookup",
97         0
98 };
99
100 static const char* dns_cache_delete_all_doc[] = {
101         "deletes all the non-permanent entries from the DNS cache",
102         0
103 };
104
105 static const char* dns_cache_delete_all_force_doc[] = {
106         "deletes all the entries from the DNS cache including the permanent ones",
107         0
108 };
109
110 static const char* dns_cache_add_a_doc[] = {
111         "adds an A record to the DNS cache",
112         0
113 };
114
115 static const char* dns_cache_add_aaaa_doc[] = {
116         "adds an AAAA record to the DNS cache",
117         0
118 };
119 static const char* dns_cache_add_srv_doc[] = {
120         "adds an SRV record to the DNS cache",
121         0
122 };
123
124 static const char* dns_cache_delete_a_doc[] = {
125         "deletes an A record from the DNS cache",
126         0
127 };
128
129 static const char* dns_cache_delete_aaaa_doc[] = {
130         "deletes an AAAA record from the DNS cache",
131         0
132 };
133
134 static const char* dns_cache_delete_srv_doc[] = {
135         "deletes an SRV record from the DNS cache",
136         0
137 };
138
139 static const char* dns_cache_delete_naptr_doc[] = {
140         "deletes a NAPTR record from the DNS cache",
141         0
142 };
143
144 static const char* dns_cache_delete_cname_doc[] = {
145         "deletes a CNAME record from the DNS cache",
146         0
147 };
148
149 static const char* dns_cache_delete_txt_doc[] = {
150         "deletes a TXT record from the DNS cache",
151         0
152 };
153
154 static const char* dns_cache_delete_ebl_doc[] = {
155         "deletes an EBL record from the DNS cache",
156         0
157 };
158
159
160 static const char* dns_cache_delete_ptr_doc[] = {
161         "deletes an PTR record from the DNS cache",
162         0
163 };
164
165
166 #ifdef USE_DNS_CACHE_STATS
167 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
168
169 static const char* dns_cache_stats_get_doc[] = {
170         "returns the dns measurement counters.",
171         0
172 };
173 #endif /* USE_DNS_CACHE_STATS */
174 #ifdef DNS_WATCHDOG_SUPPORT
175 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
176
177 static const char* dns_set_server_state_doc[] = {
178         "sets the state of the DNS servers " \
179         "(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
180         0                              /* Method signature(s) */
181 };
182
183 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx);
184
185 static const char* dns_get_server_state_doc[] = {
186         "prints the state of the DNS servers " \
187         "(0: all the servers are down, 1: at least one server is up)",  /* Documentation string */
188         0                               /* Method signature(s) */
189 };
190
191 #endif /* DNS_WATCHDOG_SUPPORT */
192 #endif /* USE_DNS_CACHE */
193 #ifdef USE_DST_BLACKLIST
194 void dst_blst_debug(rpc_t* rpc, void* ctx);
195 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
196 void dst_blst_view(rpc_t* rpc, void* ctx);
197 void dst_blst_delete_all(rpc_t* rpc, void* ctx);
198 void dst_blst_add(rpc_t* rpc, void* ctx);
199
200 static const char* dst_blst_mem_info_doc[] = {
201         "dst blacklist memory usage info.",  /* Documentation string */
202         0                                    /* Method signature(s) */
203 };
204 static const char* dst_blst_debug_doc[] = {
205         "dst blacklist  debug  info.",  /* Documentation string */
206         0                               /* Method signature(s) */
207 };
208 static const char* dst_blst_view_doc[] = {
209         "dst blacklist dump in human-readable format.",  /* Documentation string */
210         0                               /* Method signature(s) */
211 };
212 static const char* dst_blst_delete_all_doc[] = {
213         "Deletes all the entries from the dst blacklist except the permanent ones.",  /* Documentation string */
214         0                               /* Method signature(s) */
215 };
216 static const char* dst_blst_add_doc[] = {
217         "Adds a new entry to the dst blacklist.",  /* Documentation string */
218         0                               /* Method signature(s) */
219 };
220 #ifdef USE_DST_BLACKLIST_STATS
221 void dst_blst_stats_get(rpc_t* rpc, void* ctx);
222
223 static const char* dst_blst_stats_get_doc[] = {
224         "returns the dst blacklist measurement counters.",
225         0
226 };
227 #endif /* USE_DST_BLACKLIST_STATS */
228
229 #endif
230
231
232
233 #define MAX_CTIME_LEN 128
234
235 /* up time */
236 static char up_since_ctime[MAX_CTIME_LEN];
237
238
239 static const char* system_listMethods_doc[] = {
240         "Lists all RPC methods supported by the server.",  /* Documentation string */
241         0                                                  /* Method signature(s) */
242 };
243
244 static void system_listMethods(rpc_t* rpc, void* c)
245 {
246         int i;
247         
248         for(i=0; i<rpc_sarray_crt_size; i++){
249                 if (rpc->add(c, "s", rpc_sarray[i]->name) < 0) return;
250         }
251 }
252
253 static const char* system_methodSignature_doc[] = {
254         "Returns signature of given method.",  /* Documentation string */
255         0                                      /* Method signature(s) */
256 };
257
258 static void system_methodSignature(rpc_t* rpc, void* c)
259 {
260         rpc->fault(c, 500, "Not Implemented Yet");
261 }
262
263
264 static const char* system_methodHelp_doc[] = {
265         "Print the help string for given method.",  /* Documentation string */
266         0                                           /* Method signature(s) */
267 };
268
269 static void system_methodHelp(rpc_t* rpc, void* c)
270 {
271         rpc_export_t* r;
272         char* name;
273
274         if (rpc->scan(c, "s", &name) < 1) {
275                 rpc->fault(c, 400, "Method Name Expected");
276                 return;
277         }
278         
279         r=rpc_lookup(name, strlen(name));
280         if (r==0){
281                 rpc->fault(c, 400, "command not found");
282         }else{
283                 if (r->doc_str && r->doc_str[0]) {
284                         rpc->add(c, "s", r->doc_str[0]);
285                 } else {
286                         rpc->add(c, "s", "undocumented");
287                 }
288         }
289         return;
290 }
291
292
293 static const char* core_prints_doc[] = {
294         "Returns the strings given as parameters.",   /* Documentation string */
295         0                                             /* Method signature(s) */
296 };
297
298
299 static void core_prints(rpc_t* rpc, void* c)
300 {
301         char* string = 0;
302         while((rpc->scan(c, "*s", &string)>0))
303                 rpc->add(c, "s", string);
304 }
305
306
307 static const char* core_printi_doc[] = {
308         "Returns the integers given as parameters.",  /* Documentation string */
309         0                                             /* Method signature(s) */
310 };
311
312
313 static void core_printi(rpc_t* rpc, void* c)
314 {
315         int i;
316         while((rpc->scan(c, "*d", &i)>0))
317                 rpc->add(c, "d", i);
318 }
319
320
321 static const char* core_echo_doc[] = {
322         "Returns back its parameters.",              /* Documentation string */
323         0                                             /* Method signature(s) */
324 };
325
326
327 static void core_echo(rpc_t* rpc, void* c)
328 {
329         char* string = 0;
330         while((rpc->scan(c, "*.s", &string)>0))
331                 rpc->add(c, "s", string);
332 }
333
334
335 static const char* core_version_doc[] = {
336         "Returns the version string of the server.", /* Documentation string */
337         0                                           /* Method signature(s) */
338 };
339
340 static void core_version(rpc_t* rpc, void* c)
341 {
342         rpc->add(c, "s", full_version);
343 }
344
345
346
347 static const char* core_flags_doc[] = {
348         "Returns the compile flags.", /* Documentation string */
349         0                             /* Method signature(s) */
350 };
351
352 static void core_flags(rpc_t* rpc, void* c)
353 {
354         rpc->add(c, "s", ver_flags);
355 }
356
357
358
359 static const char* core_info_doc[] = {
360         "Verbose info, including version number, compile flags, compiler,"
361         "repository hash a.s.o.",     /* Documentation string */
362         0                             /* Method signature(s) */
363 };
364
365 static void core_info(rpc_t* rpc, void* c)
366 {
367         void* s;
368         
369         if (rpc->add(c, "{", &s) < 0) return;
370         rpc->struct_printf(s, "version", "%s %s", ver_name, ver_version);
371         rpc->struct_add(s, "s", "id", ver_id);
372         rpc->struct_add(s, "s", "compiler", ver_compiler);
373         rpc->struct_add(s, "s", "compiled", ver_compiled_time);
374         rpc->struct_add(s, "s", "flags", ver_flags);
375 }
376
377
378
379 static const char* core_uptime_doc[] = {
380         "Returns uptime of SER server.",  /* Documentation string */
381         0                                 /* Method signature(s) */
382 };
383
384
385 static void core_uptime(rpc_t* rpc, void* c)
386 {
387         void* s;
388         time_t now;
389
390         time(&now);
391
392         if (rpc->add(c, "{", &s) < 0) return;
393         rpc->struct_add(s, "s", "now", ctime(&now));
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 SER 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 SER 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 SER 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 SER 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 SER.",  /* 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;
767
768         TCPCONN_LOCK;
769         for(i = 0; i < TCP_ID_HASH_SIZE; i++) {
770                 for (con = tcpconn_id_hash[i]; con; con = con->id_next) {
771                         rpc->add(c, "{", &handle);
772                         /* tcp data */
773                         if (con->rcv.proto == PROTO_TCP)
774                                 type = "TCP";
775                         else if (con->rcv.proto == PROTO_TCP)
776                                 type = "TLS";
777                         else
778                                 type = "UNKNOWN";
779
780                         if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip)))
781                                         == 0)
782                                 BUG("failed to convert source ip");
783                         src_ip[len] = 0;
784                         if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip)))
785                                         == 0)
786                                 BUG("failed to convert destination ip");
787                         dst_ip[len] = 0;
788                         timeout = TICKS_TO_S(con->timeout - get_ticks_raw());
789                         switch(con->state) {
790                                 case S_CONN_ERROR:
791                                         state = "CONN_ERROR";
792                                 break;
793                                 case S_CONN_BAD:
794                                         state = "CONN_BAD";
795                                 break;
796                                 case S_CONN_OK:
797                                         state = "CONN_OK";
798                                 break;
799                                 case S_CONN_INIT:
800                                         state = "CONN_INIT";
801                                 break;
802                                 case S_CONN_EOF:
803                                         state = "CONN_EOF";
804                                 break;
805                                 case S_CONN_ACCEPT:
806                                         state = "CONN_ACCEPT";
807                                 break;
808                                 case S_CONN_CONNECT:
809                                         state = "CONN_CONNECT";
810                                 break;
811                                 default:
812                                         state = "UNKNOWN";
813                         }
814                         rpc->struct_add(handle, "dssdsdsd",
815                                         "id", con->id,
816                                         "type", type,
817                                         "state", state,
818                                         "timeout", timeout,
819                                         "src_ip", src_ip,
820                                         "src_port", con->rcv.src_port,
821                                         "dst_ip", dst_ip,
822                                         "dst_port", con->rcv.dst_port);
823                 }
824         }
825         TCPCONN_UNLOCK;
826 #else
827         rpc->fault(c, 500, "tcp support not compiled");
828 #endif
829 }
830
831
832
833 static const char* core_sctp_options_doc[] = {
834         "Returns active sctp options. With one parameter"
835         " it returns the sctp options set in the kernel for a specific socket"
836         "(debugging), with 0 filled in for non-kernel related options."
837         " The parameter can be: \"default\" | \"first\" | address[:port] ."
838         " With no parameters it returns ser's idea of the current sctp options"
839          " (intended non-debugging use).",
840         /* Documentation string */
841         0                                 /* Method signature(s) */
842 };
843
844 static void core_sctp_options(rpc_t* rpc, void* c)
845 {
846 #ifdef USE_SCTP
847         void *handle;
848         struct cfg_group_sctp t;
849         char* param;
850         struct socket_info* si;
851         char* host;
852         str hs;
853         int hlen;
854         int port;
855         int proto;
856
857         param=0;
858         if (!sctp_disable){
859                 /* look for optional socket parameter */
860                 if (rpc->scan(c, "*s", &param)>0){
861                         si=0;
862                         if (strcasecmp(param, "default")==0){
863                                 si=sendipv4_sctp?sendipv4_sctp:sendipv6_sctp;
864                         }else if (strcasecmp(param, "first")==0){
865                                 si=sctp_listen;
866                         }else{
867                                 if (parse_phostport(param, &host, &hlen, &port, &proto)!=0){
868                                         rpc->fault(c, 500, "bad param (use address, address:port,"
869                                                                                 " default or first)");
870                                         return;
871                                 }
872                                 if (proto && proto!=PROTO_SCTP){
873                                         rpc->fault(c, 500, "bad protocol in param (only SCTP"
874                                                                                 " allowed)");
875                                         return;
876                                 }
877                                 hs.s=host;
878                                 hs.len=hlen;
879                                 si=grep_sock_info(&hs, port, PROTO_SCTP);
880                                 if (si==0){
881                                         rpc->fault(c, 500, "not listening on sctp %s", param);
882                                         return;
883                                 }
884                         }
885                         if (si==0 || si->socket==-1){
886                                 rpc->fault(c, 500, "could not find a sctp socket");
887                                 return;
888                         }
889                         memset(&t, 0, sizeof(t));
890                         if (sctp_get_cfg_from_sock(si->socket, &t)!=0){
891                                 rpc->fault(c, 500, "failed to get socket options");
892                                 return;
893                         }
894                 }else{
895                         sctp_options_get(&t);
896                 }
897                 rpc->add(c, "{", &handle);
898                 rpc->struct_add(handle, "ddddddddddddddddddd",
899                         "sctp_socket_rcvbuf",   t.so_rcvbuf,
900                         "sctp_socket_sndbuf",   t.so_sndbuf,
901                         "sctp_autoclose",               t.autoclose,
902                         "sctp_send_ttl",        t.send_ttl,
903                         "sctp_send_retries",    t.send_retries,
904                         "sctp_assoc_tracking",  t.assoc_tracking,
905                         "sctp_assoc_reuse",     t.assoc_reuse,
906                         "sctp_max_assocs", t.max_assocs,
907                         "sctp_srto_initial",    t.srto_initial,
908                         "sctp_srto_max",                t.srto_max,
909                         "sctp_srto_min",                t.srto_min,
910                         "sctp_asocmaxrxt",      t.asocmaxrxt,
911                         "sctp_init_max_attempts",       t.init_max_attempts,
912                         "sctp_init_max_timeo",t.init_max_timeo,
913                         "sctp_hbinterval",      t.hbinterval,
914                         "sctp_pathmaxrxt",      t.pathmaxrxt,
915                         "sctp_sack_delay",      t.sack_delay,
916                         "sctp_sack_freq",       t.sack_freq,
917                         "sctp_max_burst",       t.max_burst
918                 );
919         }else{
920                 rpc->fault(c, 500, "sctp support disabled");
921         }
922 #else
923         rpc->fault(c, 500, "sctp support not compiled");
924 #endif
925 }
926
927
928
929 static const char* core_sctpinfo_doc[] = {
930         "Returns sctp related info.",    /* Documentation string */
931         0                               /* Method signature(s) */
932 };
933
934 static void core_sctpinfo(rpc_t* rpc, void* c)
935 {
936 #ifdef USE_SCTP
937         void *handle;
938         struct sctp_gen_info i;
939
940         if (!sctp_disable){
941                 sctp_get_info(&i);
942                 rpc->add(c, "{", &handle);
943                 rpc->struct_add(handle, "ddd",
944                         "opened_connections", i.sctp_connections_no,
945                         "tracked_connections", i.sctp_tracked_no,
946                         "total_connections", i.sctp_total_connections
947                 );
948         }else{
949                 rpc->fault(c, 500, "sctp support disabled");
950         }
951 #else
952         rpc->fault(c, 500, "sctp support not compiled");
953 #endif
954 }
955
956
957
958
959 static const char* core_udp4rawinfo_doc[] = {
960         "Returns udp4_raw related info.",    /* Documentation string */
961         0                                     /* Method signature(s) */
962 };
963
964 static void core_udp4rawinfo(rpc_t* rpc, void* c)
965 {
966 #ifdef USE_RAW_SOCKS
967         void *handle;
968
969         rpc->add(c, "{", &handle);
970         rpc->struct_add(handle, "ddd",
971                 "udp4_raw", cfg_get(core, core_cfg, udp4_raw),
972                 "udp4_raw_mtu", cfg_get(core, core_cfg, udp4_raw_mtu),
973                 "udp4_raw_ttl", cfg_get(core, core_cfg, udp4_raw_ttl)
974         );
975 #else /* USE_RAW_SOCKS */
976         rpc->fault(c, 500, "udp4_raw mode support not compiled");
977 #endif /* USE_RAW_SOCKS */
978 }
979
980 /**
981  *
982  */
983 static const char* core_aliases_list_doc[] = {
984         "List local SIP server host aliases",    /* Documentation string */
985         0                                     /* Method signature(s) */
986 };
987
988 /**
989  * list the name aliases for SIP server
990  */
991 static void core_aliases_list(rpc_t* rpc, void* c)
992 {
993         void *hr;
994         void *ha;
995         struct host_alias* a;
996
997         rpc->add(c, "{", &hr);
998         rpc->struct_add(hr, "s",
999                         "myself_callbacks", is_check_self_func_list_set()?"yes":"no");
1000         for(a=aliases; a; a=a->next) {
1001                 rpc->struct_add(hr, "{", "alias", &ha);
1002                 rpc->struct_add(ha, "sS",
1003                                 "proto",  proto2a(a->proto),
1004                                 "address", &a->alias
1005                         );
1006                 if (a->port)
1007                         rpc->struct_add(ha, "d",
1008                                         "port", a->port);
1009                 else
1010                         rpc->struct_add(ha, "s",
1011                                         "port", "*");
1012         }
1013 }
1014
1015 /**
1016  *
1017  */
1018 static const char* core_sockets_list_doc[] = {
1019         "List local SIP server listen sockets",    /* Documentation string */
1020         0                                     /* Method signature(s) */
1021 };
1022
1023 /**
1024  * list listen sockets for SIP server
1025  */
1026 static void core_sockets_list(rpc_t* rpc, void* c)
1027 {
1028         void *hr;
1029         void *ha;
1030         struct socket_info *si;
1031         struct socket_info** list;
1032         struct addr_info* ai;
1033         unsigned short proto;
1034
1035         proto=PROTO_UDP;
1036         rpc->add(c, "{", &hr);
1037         do{
1038                 list=get_sock_info_list(proto);
1039                 for(si=list?*list:0; si; si=si->next){
1040                         rpc->struct_add(hr, "{", "socket", &ha);
1041                         if (si->addr_info_lst){
1042                                 rpc->struct_add(ha, "ss",
1043                                                 "proto", get_proto_name(proto),
1044                                                 "address", si->address_str.s);
1045                                 for (ai=si->addr_info_lst; ai; ai=ai->next)
1046                                         rpc->struct_add(ha, "ss",
1047                                                 "address", ai->address_str.s);
1048                                 rpc->struct_add(ha, "sss",
1049                                                 "proto", si->port_no_str.s,
1050                                                 "mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
1051                                                 "mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
1052                         } else {
1053                                 printf("             %s: %s",
1054                                                 get_proto_name(proto),
1055                                                 si->name.s);
1056                                 rpc->struct_add(ha, "ss",
1057                                                 "proto", get_proto_name(proto),
1058                                                 "address", si->name.s);
1059                                 if (!si->flags & SI_IS_IP)
1060                                         rpc->struct_add(ha, "ss",
1061                                                 "ipaddress", si->address_str.s);
1062                                 rpc->struct_add(ha, "sss",
1063                                                 "proto", si->port_no_str.s,
1064                                                 "mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
1065                                                 "mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
1066                         }
1067                 }
1068         } while((proto=next_proto(proto)));
1069 }
1070
1071
1072 /*
1073  * RPC Methods exported by this module
1074  */
1075 static rpc_export_t core_rpc_methods[] = {
1076         {"system.listMethods",     system_listMethods,     system_listMethods_doc,     RET_ARRAY},
1077         {"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0        },
1078         {"system.methodHelp",      system_methodHelp,      system_methodHelp_doc,      0        },
1079         {"core.prints",            core_prints,            core_prints_doc,
1080         RET_ARRAY},
1081         {"core.printi",            core_printi,            core_printi_doc,
1082         RET_ARRAY},
1083         {"core.echo",              core_echo,              core_echo_doc,
1084         RET_ARRAY},
1085         {"core.version",           core_version,           core_version_doc,
1086                 0        },
1087         {"core.flags",             core_flags,             core_flags_doc,
1088                 0        },
1089         {"core.info",              core_info,              core_info_doc,
1090                 0        },
1091         {"core.uptime",            core_uptime,            core_uptime_doc,            0        },
1092         {"core.ps",                core_ps,                core_ps_doc,                RET_ARRAY},
1093         {"core.psx",               core_psx,               core_psx_doc,                0},
1094         {"core.pwd",               core_pwd,               core_pwd_doc,               RET_ARRAY},
1095         {"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
1096         {"core.kill",              core_kill,              core_kill_doc,              0        },
1097         {"core.shmmem",            core_shmmem,            core_shmmem_doc,            0        },
1098 #if defined(SF_MALLOC) || defined(LL_MALLOC)
1099         {"core.sfmalloc",          core_sfmalloc,          core_sfmalloc_doc,   0},
1100 #endif
1101         {"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,    0},
1102         {"core.tcp_options",       core_tcp_options,       core_tcp_options_doc,0},
1103         {"core.tcp_list",          core_tcp_list,          core_tcp_list_doc,0},
1104         {"core.sctp_options",      core_sctp_options,      core_sctp_options_doc,
1105                 0},
1106         {"core.sctp_info",         core_sctpinfo,          core_sctpinfo_doc,   0},
1107         {"core.udp4_raw_info",     core_udp4rawinfo,       core_udp4rawinfo_doc,
1108                 0},
1109         {"core.aliases_list",      core_aliases_list,      core_aliases_list_doc,   0},
1110         {"core.sockets_list",      core_sockets_list,      core_sockets_list_doc,   0},
1111 #ifdef USE_DNS_CACHE
1112         {"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,
1113                 0       },
1114         {"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,
1115                 0       },
1116         {"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,
1117                 0       },
1118         {"dns.view",               dns_cache_view,        dns_cache_view_doc,
1119                 0       },
1120         {"dns.lookup",             dns_cache_rpc_lookup,  dns_cache_rpc_lookup_doc,
1121                 0       },
1122         {"dns.delete_all",         dns_cache_delete_all,  dns_cache_delete_all_doc,
1123                 0       },
1124         {"dns.delete_all_force",   dns_cache_delete_all_force, dns_cache_delete_all_force_doc,
1125                 0       },
1126         {"dns.add_a",              dns_cache_add_a,       dns_cache_add_a_doc,
1127                 0       },
1128         {"dns.add_aaaa",           dns_cache_add_aaaa,    dns_cache_add_aaaa_doc,
1129                 0       },
1130         {"dns.add_srv",            dns_cache_add_srv,     dns_cache_add_srv_doc,
1131                 0       },
1132         {"dns.delete_a",           dns_cache_delete_a,    dns_cache_delete_a_doc,
1133                 0       },
1134         {"dns.delete_aaaa",        dns_cache_delete_aaaa,
1135                 dns_cache_delete_aaaa_doc, 0    },
1136         {"dns.delete_srv",         dns_cache_delete_srv,
1137                 dns_cache_delete_srv_doc,  0    },
1138         {"dns.delete_naptr",         dns_cache_delete_naptr,
1139                 dns_cache_delete_naptr_doc,  0  },
1140         {"dns.delete_cname",         dns_cache_delete_cname,
1141                 dns_cache_delete_cname_doc,  0  },
1142         {"dns.delete_txt",         dns_cache_delete_txt,
1143                 dns_cache_delete_txt_doc,  0    },
1144         {"dns.delete_ebl",         dns_cache_delete_ebl,
1145                 dns_cache_delete_ebl_doc,  0    },
1146         {"dns.delete_ptr",         dns_cache_delete_ptr,
1147                 dns_cache_delete_ptr_doc,  0    },
1148 #ifdef USE_DNS_CACHE_STATS
1149         {"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,
1150                 0       },
1151 #endif /* USE_DNS_CACHE_STATS */
1152 #ifdef DNS_WATCHDOG_SUPPORT
1153         {"dns.set_server_state",   dns_set_server_state_rpc,
1154                 dns_set_server_state_doc, 0 },
1155         {"dns.get_server_state",   dns_get_server_state_rpc,
1156                 dns_get_server_state_doc, 0 },
1157 #endif
1158 #endif
1159 #ifdef USE_DST_BLACKLIST
1160         {"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,
1161                 0       },
1162         {"dst_blacklist.debug",    dst_blst_debug,         dst_blst_debug_doc,
1163                 0       },
1164         {"dst_blacklist.view",     dst_blst_view,         dst_blst_view_doc,
1165                 0       },
1166         {"dst_blacklist.delete_all", dst_blst_delete_all, dst_blst_delete_all_doc,
1167                 0       },
1168         {"dst_blacklist.add",      dst_blst_add,          dst_blst_add_doc,
1169                 0       },
1170 #ifdef USE_DST_BLACKLIST_STATS
1171         {"dst_blacklist.stats_get", dst_blst_stats_get, dst_blst_stats_get_doc, 0},
1172 #endif /* USE_DST_BLACKLIST_STATS */
1173 #endif
1174         {0, 0, 0, 0}
1175 };
1176
1177
1178
1179 int register_core_rpcs(void)
1180 {
1181         int i;
1182         
1183         i=rpc_register_array(core_rpc_methods);
1184         if (i<0){
1185                 BUG("failed to register core RPCs\n");
1186                 goto error;
1187         }else if (i>0){
1188                 ERR("%d duplicate RPCs name detected while registering core RPCs\n",
1189                          i);
1190                 goto error;
1191         }
1192         return 0;
1193 error:
1194         return -1;
1195 }
1196
1197
1198
1199 int rpc_init_time(void)
1200 {
1201         char *t;
1202         t=ctime(&up_since);
1203         if (strlen(t)+1>=MAX_CTIME_LEN) {
1204                 ERR("Too long data %d\n", (int)strlen(t));
1205                 return -1;
1206         }
1207         memcpy(up_since_ctime,t,strlen(t)+1);
1208         return 0;
1209 }