- core sctp support
[sip-router] / core_cmd.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2005 iptelorg GmbH
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser 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  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #include <time.h>
29 #include <sys/types.h>
30 #include <signal.h>
31 #include "mem/mem.h"
32 #include "mem/shm_mem.h"
33 #include "sr_module.h"
34 #include "dprint.h"
35 #include "core_cmd.h"
36 #include "globals.h"
37 #include "pt.h"
38 #include "ut.h"
39 #include "tcp_info.h"
40 #include "tcp_options.h"
41 #include "core_cmd.h"
42 #ifdef USE_SCTP
43 #include "sctp_options.h"
44 #endif
45
46 #ifdef USE_DNS_CACHE
47 void dns_cache_debug(rpc_t* rpc, void* ctx);
48 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
49 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
50 void dns_cache_view(rpc_t* rpc, void* ctx);
51 void dns_cache_delete_all(rpc_t* rpc, void* ctx);
52 void dns_cache_add_a(rpc_t* rpc, void* ctx);
53 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx);
54 void dns_cache_add_srv(rpc_t* rpc, void* ctx);
55 void dns_cache_delete_a(rpc_t* rpc, void* ctx);
56 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx);
57 void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
58
59
60 static const char* dns_cache_mem_info_doc[] = {
61         "dns cache memory info.",    /* Documentation string */
62         0                      /* Method signature(s) */
63 };
64 static const char* dns_cache_debug_doc[] = {
65         "dns debug  info.",    /* Documentation string */
66         0                      /* Method signature(s) */
67 };
68
69 static const char* dns_cache_debug_all_doc[] = {
70         "complete dns debug  dump",    /* Documentation string */
71         0                              /* Method signature(s) */
72 };
73
74 static const char* dns_cache_view_doc[] = {
75         "dns cache dump in a human-readable format",
76         0
77 };
78
79 static const char* dns_cache_delete_all_doc[] = {
80         "deletes all the entries from the DNS cache",
81         0
82 };
83
84 static const char* dns_cache_add_a_doc[] = {
85         "adds an A record to the DNS cache",
86         0
87 };
88
89 static const char* dns_cache_add_aaaa_doc[] = {
90         "adds an AAAA record to the DNS cache",
91         0
92 };
93 static const char* dns_cache_add_srv_doc[] = {
94         "adds an SRV record to the DNS cache",
95         0
96 };
97
98 static const char* dns_cache_delete_a_doc[] = {
99         "deletes an A record from the DNS cache",
100         0
101 };
102
103 static const char* dns_cache_delete_aaaa_doc[] = {
104         "deletes an AAAA record from the DNS cache",
105         0
106 };
107
108 static const char* dns_cache_delete_srv_doc[] = {
109         "deletes an SRV record from the DNS cache",
110         0
111 };
112
113 #ifdef USE_DNS_CACHE_STATS
114 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
115
116 static const char* dns_cache_stats_get_doc[] = {
117         "returns the dns measurement counters.",
118         0
119 };
120 #endif /* USE_DNS_CACHE_STATS */
121 #ifdef DNS_WATCHDOG_SUPPORT
122 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
123
124 static const char* dns_set_server_state_doc[] = {
125         "sets the state of the DNS servers " \
126         "(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
127         0                              /* Method signature(s) */
128 };
129
130 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx);
131
132 static const char* dns_get_server_state_doc[] = {
133         "prints the state of the DNS servers " \
134         "(0: all the servers are down, 1: at least one server is up)",  /* Documentation string */
135         0                               /* Method signature(s) */
136 };
137
138 #endif /* DNS_WATCHDOG_SUPPORT */
139 #endif /* USE_DNS_CACHE */
140 #ifdef USE_DST_BLACKLIST
141 void dst_blst_debug(rpc_t* rpc, void* ctx);
142 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
143 void dst_blst_view(rpc_t* rpc, void* ctx);
144 void dst_blst_delete_all(rpc_t* rpc, void* ctx);
145 void dst_blst_add(rpc_t* rpc, void* ctx);
146
147 static const char* dst_blst_mem_info_doc[] = {
148         "dst blacklist memory usage info.",  /* Documentation string */
149         0                                    /* Method signature(s) */
150 };
151 static const char* dst_blst_debug_doc[] = {
152         "dst blacklist  debug  info.",  /* Documentation string */
153         0                               /* Method signature(s) */
154 };
155 static const char* dst_blst_view_doc[] = {
156         "dst blacklist dump in human-readable format.",  /* Documentation string */
157         0                               /* Method signature(s) */
158 };
159 static const char* dst_blst_delete_all_doc[] = {
160         "Deletes all the entries from the dst blacklist except the permanent ones.",  /* Documentation string */
161         0                               /* Method signature(s) */
162 };
163 static const char* dst_blst_add_doc[] = {
164         "Adds a new entry to the dst blacklist.",  /* Documentation string */
165         0                               /* Method signature(s) */
166 };
167 #ifdef USE_DST_BLACKLIST_STATS
168 void dst_blst_stats_get(rpc_t* rpc, void* ctx);
169
170 static const char* dst_blst_stats_get_doc[] = {
171         "returns the dst blacklist measurement counters.",
172         0
173 };
174 #endif /* USE_DST_BLACKLIST_STATS */
175
176 #endif
177
178
179
180 #define MAX_CTIME_LEN 128
181
182 /* up time */
183 static char up_since_ctime[MAX_CTIME_LEN];
184
185
186 static const char* system_listMethods_doc[] = {
187         "Lists all RPC methods supported by the server.",  /* Documentation string */
188         0                                                  /* Method signature(s) */
189 };
190
191 static void system_listMethods(rpc_t* rpc, void* c)
192 {
193         struct sr_module* t;
194         rpc_export_t* ptr;
195
196         for(ptr = core_rpc_methods; ptr && ptr->name; ptr++) {
197                 if (rpc->add(c, "s", ptr->name) < 0) return;
198         }
199
200         for(t = modules; t; t = t->next) {
201                 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
202                         if (rpc->add(c, "s", ptr->name) < 0) return;
203                 }
204         }
205 }
206
207 static const char* system_methodSignature_doc[] = {
208         "Returns signature of given method.",  /* Documentation string */
209         0                                      /* Method signature(s) */
210 };
211
212 static void system_methodSignature(rpc_t* rpc, void* c)
213 {
214         rpc->fault(c, 500, "Not Implemented Yet");
215 }
216
217
218 static const char* system_methodHelp_doc[] = {
219         "Print the help string for given method.",  /* Documentation string */
220         0                                           /* Method signature(s) */
221 };
222
223 static void system_methodHelp(rpc_t* rpc, void* c)
224 {
225         struct sr_module* t;
226         rpc_export_t* ptr;
227         char* name;
228
229         if (rpc->scan(c, "s", &name) < 1) {
230                 rpc->fault(c, 400, "Method Name Expected");
231                 return;
232         }
233
234         for(t = modules; t; t = t->next) {
235                 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
236                         if (strcmp(name, ptr->name) == 0) {
237                                 if (ptr->doc_str && ptr->doc_str[0]) {
238                                         rpc->add(c, "s", ptr->doc_str[0]);
239                                 } else {
240                                         rpc->add(c, "s", "undocumented");
241                                 }
242                                 return;
243                         }
244                 }
245         }
246         /* try the core methods too */
247         for (ptr=core_rpc_methods;ptr && ptr->name; ptr++){
248                         if (strcmp(name, ptr->name) == 0) {
249                                 if (ptr->doc_str && ptr->doc_str[0]) {
250                                         rpc->add(c, "s", ptr->doc_str[0]);
251                                 } else {
252                                         rpc->add(c, "s", "undocumented");
253                                 }
254                                 return;
255                         }
256         }
257         rpc->fault(c, 400, "command not found");
258 }
259
260
261 static const char* core_prints_doc[] = {
262         "Returns the string given as parameter.",   /* Documentation string */
263         0                                           /* Method signature(s) */
264 };
265
266
267 static void core_prints(rpc_t* rpc, void* c)
268 {
269         char* string = 0;
270         if (rpc->scan(c, "s", &string)>0)
271                 rpc->add(c, "s", string);
272 }
273
274
275 static const char* core_version_doc[] = {
276         "Returns the version string of the server.", /* Documentation string */
277         0                                           /* Method signature(s) */
278 };
279
280 static void core_version(rpc_t* rpc, void* c)
281 {
282         rpc->add(c, "s", SERVER_HDR);
283 }
284
285
286
287 static const char* core_uptime_doc[] = {
288         "Returns uptime of SER server.",  /* Documentation string */
289         0                                 /* Method signature(s) */
290 };
291
292
293 static void core_uptime(rpc_t* rpc, void* c)
294 {
295         void* s;
296         time_t now;
297
298         time(&now);
299
300         if (rpc->add(c, "{", &s) < 0) return;
301         rpc->struct_add(s, "s", "now", ctime(&now));
302         rpc->struct_add(s, "s", "up_since", up_since_ctime);
303         /* no need for a float here (unless you're concerned that your uptime)
304         rpc->struct_add(s, "f", "uptime",  difftime(now, up_since));
305         */
306         /* on posix system we can substract time_t directly */
307         rpc->struct_add(s, "d", "uptime",  (int)(now-up_since));
308 }
309
310
311 static const char* core_ps_doc[] = {
312         "Returns the description of running SER processes.",  /* Documentation string */
313         0                                                     /* Method signature(s) */
314 };
315
316
317 static void core_ps(rpc_t* rpc, void* c)
318 {
319         int p;
320
321         for (p=0; p<*process_count;p++) {
322                 rpc->add(c, "d", pt[p].pid);
323                 rpc->add(c, "s", pt[p].desc);
324         }
325 }
326
327
328 static const char* core_pwd_doc[] = {
329         "Returns the working directory of SER server.",    /* Documentation string */
330         0                                                  /* Method signature(s) */
331 };
332
333
334 static void core_pwd(rpc_t* rpc, void* c)
335 {
336         char *cwd_buf;
337         int max_len;
338
339         max_len = pathmax();
340         cwd_buf = pkg_malloc(max_len);
341         if (!cwd_buf) {
342                 ERR("core_pwd: No memory left\n");
343                 rpc->fault(c, 500, "Server Ran Out of Memory");
344                 return;
345         }
346
347         if (getcwd(cwd_buf, max_len)) {
348                 rpc->add(c, "s", cwd_buf);
349         } else {
350                 rpc->fault(c, 500, "getcwd Failed");
351         }
352         pkg_free(cwd_buf);
353 }
354
355
356 static const char* core_arg_doc[] = {
357         "Returns the list of command line arguments used on SER startup.",  /* Documentation string */
358         0                                                                   /* Method signature(s) */
359 };
360
361
362 static void core_arg(rpc_t* rpc, void* c)
363 {
364         int p;
365
366         for (p = 0; p < my_argc; p++) {
367                 if (rpc->add(c, "s", my_argv[p]) < 0) return;
368         }
369 }
370
371
372 static const char* core_kill_doc[] = {
373         "Sends the given signal to SER.",  /* Documentation string */
374         0                                  /* Method signature(s) */
375 };
376
377
378 static void core_kill(rpc_t* rpc, void* c)
379 {
380         int sig_no = 15;
381         rpc->scan(c, "d", &sig_no);
382         rpc->send(c);
383         kill(0, sig_no);
384 }
385
386 static void core_shmmem(rpc_t* rpc, void* c)
387 {
388         struct mem_info mi;
389         void *handle;
390
391         shm_info(&mi);
392         rpc->add(c, "{", &handle);
393         rpc->struct_add(handle, "dddddd",
394                 "total", (unsigned int)mi.total_size,
395                 "free", (unsigned int)mi.free,
396                 "used", (unsigned int)mi.used,
397                 "real_used",(unsigned int)mi.real_used,
398                 "max_used", (unsigned int)mi.max_used,
399                 "fragments", (unsigned int)mi.total_frags
400         );
401 }
402
403 static const char* core_shmmem_doc[] = {
404         "Returns shared memory info.",  /* Documentation string */
405         0                               /* Method signature(s) */
406 };
407
408
409 #if defined(SF_MALLOC) || defined(LL_MALLOC)
410 static void core_sfmalloc(rpc_t* rpc, void* c)
411 {
412         void *handle;
413         int i,r;
414         unsigned long frags, main_s_frags, main_b_frags, pool_frags;
415         unsigned long misses;
416         unsigned long max_misses;
417         unsigned long max_frags;
418         unsigned long max_mem;
419         int max_frags_pool, max_frags_hash;
420         int max_misses_pool, max_misses_hash;
421         int max_mem_pool, max_mem_hash;
422         unsigned long mem;
423
424         if (rpc->scan(c, "d", &r) >= 1) {
425                 if (r>=(int)SF_HASH_POOL_SIZE){
426                         rpc->fault(c, 500, "invalid hash number %d (max %d)",
427                                                                 r, (unsigned int)SF_HASH_POOL_SIZE-1);
428                         return;
429                 }else if (r<0) goto all;
430                 rpc->add(c, "{", &handle);
431                 rpc->struct_add(handle, "dd",
432                                 "hash  ", r,
433                                 "size  ", r*SF_ROUNDTO);
434                 for (i=0; i<SFM_POOLS_NO; i++){
435                         rpc->struct_add(handle, "dddd",
436                                 "pool  ", i,
437                                 "frags ", (unsigned int)shm_block->pool[i].pool_hash[r].no,
438                                 "misses", (unsigned int)shm_block->pool[i].pool_hash[r].misses,
439                                 "mem   ",   (unsigned int)shm_block->pool[i].pool_hash[r].no *
440                                                         r*SF_ROUNDTO
441                         );
442                 }
443         }
444         return;
445 all:
446         max_frags=max_misses=max_mem=0;
447         max_frags_pool=max_frags_hash=0;
448         max_misses_pool=max_misses_hash=0;
449         max_mem_pool=max_mem_hash=0;
450         pool_frags=0;
451         for (i=0; i<SFM_POOLS_NO; i++){
452                 frags=0;
453                 misses=0;
454                 mem=0;
455                 for (r=0; r<SF_HASH_POOL_SIZE; r++){
456                         frags+=shm_block->pool[i].pool_hash[r].no;
457                         misses+=shm_block->pool[i].pool_hash[r].misses;
458                         mem+=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
459                         if (shm_block->pool[i].pool_hash[r].no>max_frags){
460                                 max_frags=shm_block->pool[i].pool_hash[r].no;
461                                 max_frags_pool=i;
462                                 max_frags_hash=r;
463                         }
464                         if (shm_block->pool[i].pool_hash[r].misses>max_misses){
465                                 max_misses=shm_block->pool[i].pool_hash[r].misses;
466                                 max_misses_pool=i;
467                                 max_misses_hash=r;
468                         }
469                         if (shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO>max_mem){
470                                 max_mem=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
471                                 max_mem_pool=i;
472                                 max_mem_hash=r;
473                         }
474                 }
475                 rpc->add(c, "{", &handle);
476                 rpc->struct_add(handle, "dddddd",
477                         "pool  ", i,
478                         "frags ", (unsigned int)frags,
479                         "t. misses", (unsigned int)misses,
480                         "mem   ", (unsigned int)mem,
481                         "missed", (unsigned int)shm_block->pool[i].missed,
482                         "hits",   (unsigned int)shm_block->pool[i].hits
483                 );
484                 pool_frags+=frags;
485         }
486         main_s_frags=0;
487         for (r=0; r<SF_HASH_POOL_SIZE; r++){
488                 main_s_frags+=shm_block->free_hash[r].no;
489         }
490         main_b_frags=0;
491         for (; r<SF_HASH_SIZE; r++){
492                 main_b_frags+=shm_block->free_hash[r].no;
493         }
494         rpc->add(c, "{", &handle);
495         rpc->struct_add(handle, "ddddddddddddd",
496                 "max_frags      ", (unsigned int)max_frags,
497                 "max_frags_pool ", max_frags_pool,
498                 "max_frags_hash", max_frags_hash,
499                 "max_misses     ", (unsigned int)max_misses,
500                 "max_misses_pool", max_misses_pool,
501                 "max_misses_hash", max_misses_hash,
502                 "max_mem        ", (unsigned int)max_mem,
503                 "max_mem_pool   ", max_mem_pool,
504                 "max_mem_hash   ", max_mem_hash,
505                 "in_pools_frags ", (unsigned int)pool_frags,
506                 "main_s_frags   ", (unsigned int)main_s_frags,
507                 "main_b_frags   ", (unsigned int)main_b_frags,
508                 "main_frags     ", (unsigned int)(main_b_frags+main_s_frags)
509         );
510 }
511
512
513
514 static const char* core_sfmalloc_doc[] = {
515         "Returns sfmalloc debugging  info.",  /* Documentation string */
516         0                                     /* Method signature(s) */
517 };
518
519 #endif
520
521
522
523 static const char* core_tcpinfo_doc[] = {
524         "Returns tcp related info.",    /* Documentation string */
525         0                               /* Method signature(s) */
526 };
527
528 static void core_tcpinfo(rpc_t* rpc, void* c)
529 {
530 #ifdef USE_TCP
531         void *handle;
532         struct tcp_gen_info ti;
533
534         if (!tcp_disable){
535                 tcp_get_info(&ti);
536                 rpc->add(c, "{", &handle);
537                 rpc->struct_add(handle, "dddd",
538                         "readers", ti.tcp_readers,
539                         "max_connections", ti.tcp_max_connections,
540                         "opened_connections", ti.tcp_connections_no,
541                         "write_queued_bytes", ti.tcp_write_queued
542                 );
543         }else{
544                 rpc->fault(c, 500, "tcp support disabled");
545         }
546 #else
547         rpc->fault(c, 500, "tcp support not compiled");
548 #endif
549 }
550
551
552
553 static const char* core_tcp_options_doc[] = {
554         "Returns active tcp options.",    /* Documentation string */
555         0                                 /* Method signature(s) */
556 };
557
558 static void core_tcp_options(rpc_t* rpc, void* c)
559 {
560 #ifdef USE_TCP
561         void *handle;
562         struct tcp_cfg_options t;
563
564         if (!tcp_disable){
565                 tcp_options_get(&t);
566                 rpc->add(c, "{", &handle);
567                 rpc->struct_add(handle, "ddddddddddddddd",
568                         "fd_cache",             t.fd_cache,
569                         "tcp_buf_write",        t.tcp_buf_write,
570                         "tcp_connect_wait",     t.tcp_connect_wait,
571                         "tcpconn_wq_max",       t.tcpconn_wq_max,
572                         "tcp_wq_max",   t.tcp_wq_max,
573                         "tcp_wq_timeout",       TICKS_TO_S(t.tcp_wq_timeout),
574                         
575                         "defer_accept", t.defer_accept,
576                         "delayed_ack",  t.delayed_ack,
577                         "syncnt",               t.syncnt,
578                         "linger2",              t.linger2,
579                         "keepalive",    t.keepalive,
580                         "keepidle",             t.keepidle,
581                         "keepintvl",    t.keepintvl,
582                         "keepcnt",              t.keepcnt,
583                         "crlf_ping",    t.crlf_ping
584                 );
585         }else{
586                 rpc->fault(c, 500, "tcp support disabled");
587         }
588 #else
589         rpc->fault(c, 500, "tcp support not compiled");
590 #endif
591 }
592
593
594
595 static const char* core_sctp_options_doc[] = {
596         "Returns active sctp options.",    /* Documentation string */
597         0                                 /* Method signature(s) */
598 };
599
600 static void core_sctp_options(rpc_t* rpc, void* c)
601 {
602 #ifdef USE_SCTP
603         void *handle;
604         struct sctp_cfg_options t;
605
606         if (!sctp_disable){
607                 sctp_options_get(&t);
608                 rpc->add(c, "{", &handle);
609                 rpc->struct_add(handle, "dddd",
610                         "sctp_autoclose",               t.sctp_autoclose,
611                         "sctp_send_ttl",        t.sctp_autoclose,
612                         "sctp_socket_rcvbuf",   t.sctp_so_rcvbuf,
613                         "sctp_socket_sndbuf",   t.sctp_so_sndbuf
614                 );
615         }else{
616                 rpc->fault(c, 500, "sctp support disabled");
617         }
618 #else
619         rpc->fault(c, 500, "sctp support not compiled");
620 #endif
621 }
622
623
624
625 /*
626  * RPC Methods exported by this module
627  */
628 rpc_export_t core_rpc_methods[] = {
629         {"system.listMethods",     system_listMethods,     system_listMethods_doc,     RET_ARRAY},
630         {"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0        },
631         {"system.methodHelp",      system_methodHelp,      system_methodHelp_doc,      0        },
632         {"core.prints",            core_prints,            core_prints_doc,            0        },
633         {"core.version",           core_version,           core_version_doc,           0        },
634         {"core.uptime",            core_uptime,            core_uptime_doc,            0        },
635         {"core.ps",                core_ps,                core_ps_doc,                RET_ARRAY},
636         {"core.pwd",               core_pwd,               core_pwd_doc,               RET_ARRAY},
637         {"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
638         {"core.kill",              core_kill,              core_kill_doc,              0        },
639         {"core.shmmem",            core_shmmem,            core_shmmem_doc,            0        },
640 #if defined(SF_MALLOC) || defined(LL_MALLOC)
641         {"core.sfmalloc",          core_sfmalloc,          core_sfmalloc_doc,   0},
642 #endif
643         {"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,    0},
644         {"core.tcp_options",       core_tcp_options,       core_tcp_options_doc,0},
645         {"core.sctp_options",      core_sctp_options,      core_sctp_options_doc,
646                 0},
647 #ifdef USE_DNS_CACHE
648         {"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0 },
649         {"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0 },
650         {"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0     },
651         {"dns.view",               dns_cache_view,        dns_cache_view_doc,        0  },
652         {"dns.delete_all",         dns_cache_delete_all,  dns_cache_delete_all_doc,  0  },
653         {"dns.add_a",              dns_cache_add_a,       dns_cache_add_a_doc,       0  },
654         {"dns.add_aaaa",           dns_cache_add_aaaa,    dns_cache_add_aaaa_doc,    0  },
655         {"dns.add_srv",            dns_cache_add_srv,     dns_cache_add_srv_doc,     0  },
656         {"dns.delete_a",           dns_cache_delete_a,    dns_cache_delete_a_doc,    0  },
657         {"dns.delete_aaaa",        dns_cache_delete_aaaa, dns_cache_delete_aaaa_doc, 0  },
658         {"dns.delete_srv",         dns_cache_delete_srv,  dns_cache_delete_srv_doc,  0  },
659 #ifdef USE_DNS_CACHE_STATS
660         {"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,        0   },
661 #endif /* USE_DNS_CACHE_STATS */
662 #ifdef DNS_WATCHDOG_SUPPORT
663         {"dns.set_server_state",   dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
664         {"dns.get_server_state",   dns_get_server_state_rpc, dns_get_server_state_doc, 0 },
665 #endif
666 #endif
667 #ifdef USE_DST_BLACKLIST
668         {"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,     0 },
669         {"dst_blacklist.debug",    dst_blst_debug,         dst_blst_debug_doc,        0 },
670         {"dst_blacklist.view",     dst_blst_view,         dst_blst_view_doc,         0  },
671         {"dst_blacklist.delete_all", dst_blst_delete_all, dst_blst_delete_all_doc,   0  },
672         {"dst_blacklist.add",      dst_blst_add,          dst_blst_add_doc,          0  },
673 #ifdef USE_DST_BLACKLIST_STATS
674         {"dst_blacklist.stats_get", dst_blst_stats_get, dst_blst_stats_get_doc, 0 },
675 #endif /* USE_DST_BLACKLIST_STATS */
676 #endif
677         {0, 0, 0, 0}
678 };
679
680 int rpc_init_time(void)
681 {
682         char *t;
683         t=ctime(&up_since);
684         if (strlen(t)+1>=MAX_CTIME_LEN) {
685                 ERR("Too long data %d\n", (int)strlen(t));
686                 return -1;
687         }
688         memcpy(up_since_ctime,t,strlen(t)+1);
689         return 0;
690 }