1    | /******************
2    |   Copyright (c) 1999,2000,2001,2002               RIPE NCC
3    |  
4    |   All Rights Reserved
5    |   
6    |   Permission to use, copy, modify, and distribute this software and its
7    |   documentation for any purpose and without fee is hereby granted,
8    |   provided that the above copyright notice appear in all copies and that
9    |   both that copyright notice and this permission notice appear in
10   |   supporting documentation, and that the name of the author not be
11   |   used in advertising or publicity pertaining to distribution of the
12   |   software without specific, written prior permission.
13   |   
14   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
16   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
17   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
18   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20   |   ***************************************/
21   | 
22   | #include "rip.h"
23   | 
24   | /* this is for purify - to display the memory allocation records */
25   | extern void purify_new_inuse(void);
26   | 
27   | 
28   | /*++++++++++++++++++++++++++++++++++++++
29   |   
30   |   All functions in this file share the same interface: they take the
31   |   arguments to the command given by the user, pointer to a dynamic
32   |   GString to which the command output should be appended and the
33   |   connection data, so that some things can be displayed directly to it,
34   |   bypassing the GString.
35   |   
36   |   int <command_something>     return code. 0 indicates success.
37   |                               PC_RET_QUIT is a reserved code
38   |                               that indicates that the connection
39   | 			      should be closed. 
40   | 
41   |   char *input                 command arguments
42   | 
43   |   GString *output             (dynamic) output string
44   | 
45   |   sk_conn_st *condat          connection data
46   | 
47   |   ++++++++++++++++++++++++++++++++++++++*/
48   | 
49   | /*++++++++++++++++++++++++++++++++++++++
50   |       
51   |   Relay functions for composed commands (eg. "set counter").
52   | 
53   |   They run the second word as a command from a specific array
54   |   (show/set/stop/whatever). The hardcoded text is used only for help
55   |   messages, printed in case the command is wrong as 
56   | 
57   |  "<hardcoded> commands are: <list of possible commands>".
58   | 
59   |  ++++++++++++++++++++++++++++++++++++++*/
60   | int command_save(char *input, GString *output, sk_conn_st *condat) {
61   |   return command_execute(save, "save ", input, output, condat);
62   | }
63   | 
64   | int command_show(char *input, GString *output, sk_conn_st *condat) {
65   |   return command_execute(show, "show ", input, output, condat);
66   | }
67   | 
68   | int command_set( char *input, GString *output, sk_conn_st *condat) {
69   |   return command_execute(set,  "set ",  input, output, condat);
70   | }
71   | 
72   | int command_stop(char *input, GString *output, sk_conn_st *condat) {
73   |   return command_execute(stop, "stop ", input, output, condat);
74   | }
75   | 
76   | 
77   | /*++++++++++++++++++++++++++++++++++++++
78   |   
79   |   Display available commands.
80   |   
81   |   ++++++++++++++++++++++++++++++++++++++*/
82   | int command_help(char *input, GString *output, sk_conn_st *condat) 
83   | {
84   |   /* by the time it came here, the "help" bit is already taken away. */
85   |   return show_commands(command, "", output);
86   | 
87   | }
88   | 
89   | 
90   | /*++++++++++++++++++++++++++++++++++++++
91   |   
92   |   Quit the config session.
93   | 
94   |   ++++++++++++++++++++++++++++++++++++++*/
95   | int command_quit(char *input, GString *output, sk_conn_st *condat) {
96   |     /* Administrator wishes to quit. */
97   |   return PC_RET_QUIT;
98   | } /* command_quit() */
99   | 
100  | /*++++++++++++++++++++++++++++++++++++++
101  |   
102  |   Display the memory allocation records of purify(tm).
103  |   The #define must be changed to activate this.
104  |   The program will link only with purify.
105  | 
106  |   ++++++++++++++++++++++++++++++++++++++*/
107  | int command_purify(char *input, GString *output, sk_conn_st *condat)
108  | {
109  | #if 0
110  |   purify_new_inuse();
111  | #else 
112  |   g_string_append(output, "NOP");
113  | #endif
114  |   
115  |   return 0;
116  | }
117  | 
118  | int save_access_tree(char *input, GString *output, sk_conn_st *condat) {
119  |   er_ret_t ret_err;
120  | 
121  |   ret_err = AC_persistence_save();
122  | 
123  |   switch (ret_err) {
124  |   case AC_OK:
125  |     g_string_append(output, "Save successful");
126  |     break;
127  |   case AC_SAVING:
128  |     g_string_append(output, "Already saving");
129  |     break;
130  |   default:
131  |     g_string_append(output, "Unknown error");
132  |     return PC_RET_ERR;
133  |   }
134  |   return 0;
135  | }
136  | 
137  | /*++++++++++++++++++++++++++++++++++++++
138  |   
139  |   Display a specific constant of the CO module.
140  | 
141  |   Argument: name of the constant.
142  | 
143  |   ++++++++++++++++++++++++++++++++++++++*/
144  | int show_const(char *input, GString *output, sk_conn_st *condat) {
145  |   /* Administrator wishes to show constants. */
146  |   char *result, *name, *cursor;
147  |   int res = 0;
148  |   
149  |   if( strlen(input) > 0 ) {
150  |     cursor = input;
151  |     name = (char *)strsep(&cursor, " ");
152  | 
153  |     if( (result = CO_const_to_string(name)) != NULL ) {
154  |       g_string_append(output, result);
155  |       UT_free(result);
156  |     }
157  |     else {
158  |       g_string_append(output,  "unknown constant");
159  |       res = PC_RET_ERR;
160  |     }
161  |   }
162  |   else {
163  |     g_string_append(output,  "name required");
164  |     res = PC_RET_ERR;
165  |   }
166  |  
167  |   return res;
168  | 
169  | } /* show_const() */
170  | 
171  | 
172  | /*++++++++++++++++++++++++++++++++++++++
173  |   
174  |   Display all the constants of the CO module.
175  | 
176  |   ++++++++++++++++++++++++++++++++++++++*/
177  | int show_consts(char *input, GString *output, sk_conn_st *condat) 
178  | {
179  |   /* Administrator wishes to show constants. */
180  |   char *s =  CO_to_string();
181  |   g_string_append(output, s);
182  |   UT_free(s);
183  |   return 0;
184  | } /* show_consts() */
185  | 
186  | 
187  | /*++++++++++++++++++++++++++++++++++++++
188  |   
189  |   Display all the properties of the PR module.
190  | 
191  |   ++++++++++++++++++++++++++++++++++++++*/
192  | int show_props(char *input, GString *output, sk_conn_st *condat) 
193  | {
194  |   /* Administrator wishes to show properties. */
195  |   char *s =  PR_to_string();
196  |   g_string_append(output, s);
197  |   UT_free(s);  
198  |   return 0;
199  | } /* show_props() */
200  | 
201  | 
202  | /*++++++++++++++++++++++++++++++++++++++
203  |   
204  |   Display all running threads registered with the TA module.
205  | 
206  |   ++++++++++++++++++++++++++++++++++++++*/
207  | int show_threads(char *input, GString *output, sk_conn_st *condat) 
208  | {
209  |   /* Administrator wishes to show thread information. */
210  |   char *s = TA_tostring();
211  |   g_string_append(output, s);
212  |   UT_free(s);  
213  |   return 0;
214  | } /* show_thread() */
215  | 
216  | 
217  | /*++++++++++++++++++++++++++++++++++++++
218  |   
219  |   Switch the session to a whois session.
220  | 
221  |   ++++++++++++++++++++++++++++++++++++++*/
222  | int show_whois(char *input, GString *output, sk_conn_st *condat) 
223  | {
224  |   /*  Go to whois mode */
225  |   PW_interact(condat->sock);
226  |   return 0;
227  | } /* show_whois() */
228  | 
229  | 
230  | /*++++++++++++++++++++++++++++++++++++++
231  |   
232  |   Display the statistics about the server.
233  | 
234  |   ++++++++++++++++++++++++++++++++++++++*/
235  | int show_uptime(char *input, GString *output, sk_conn_st *condat) 
236  | {
237  |   char timestring[26];
238  |   extern time_t SV_starttime;
239  |   
240  |   ctime_r(&SV_starttime, timestring); 
241  |   SK_cd_printf( condat, 
242  | 	       "System running since %sUptime in seconds: %ld \n\n",
243  | 	       timestring,		  
244  | 	       time(NULL) - SV_starttime);
245  |   
246  |   return 0;
247  | } 
248  | 
249  | /*++++++++++++++++++++++++++++++++++++++
250  |   
251  |   Display the whois access statistics from the AC module.
252  | 
253  |   ++++++++++++++++++++++++++++++++++++++*/
254  | int show_access(char *input, GString *output, sk_conn_st *condat) 
255  | {  
256  |   int cnt = AC_print_access(output);
257  |   
258  |   g_string_sprintfa(output, "Found %d nodes\n", cnt);
259  | 
260  |   return 0;
261  | } /* show_access() */
262  | 
263  | 
264  | /*++++++++++++++++++++++++++++++++++++++
265  |   
266  |   Display the whois access control list from the AC module.
267  | 
268  |   ++++++++++++++++++++++++++++++++++++++*/
269  | int show_acl(char *input, GString *output, sk_conn_st *condat) 
270  | {
271  |   int cnt = AC_print_acl(output);
272  | 
273  |   g_string_sprintfa(output, "Found %d nodes\n", cnt);
274  | 
275  |   return 0;
276  | } /* show_acl() */
277  | 
278  | /*++++++++++++++++++++++++++++++++++++++
279  |   
280  |   Display the access tree auto save state.
281  | 
282  |   ++++++++++++++++++++++++++++++++++++++*/
283  | int show_auto_save(char *input, GString *output, sk_conn_st *condat) 
284  | {
285  |   g_string_sprintfa(output, "Auto save is %d\n", ac_auto_save);
286  | 
287  |   return 0;
288  | } /* show_auto_save() */
289  | 
290  | 
291  | /*++++++++++++++++++++++++++++++++++++++
292  |   
293  |   Modify the whois access control list in the AC module.
294  | 
295  |   Arguments: IP[/prefixlength] column=value,column=value...
296  | 
297  |   Column names as in acl display. Unset columns are inherited.
298  | 
299  |   ++++++++++++++++++++++++++++++++++++++*/
300  | int set_acl(char *input, GString *output, sk_conn_st *condat)
301  | {
302  |   int res = 0;
303  |   
304  |   /* first 8 characters ("set acl ") are already skipped */
305  |   if( ! NOERR( AC_asc_acl_command_set( input, "Manual"))) {
306  |     g_string_append(output, "Error!\n");
307  |     res = PC_RET_ERR;
308  |   }
309  |   return res;
310  | }
311  | 
312  | /*++++++++++++++++++++++++++++++++++++++
313  |   
314  |   Sets the auto save status of the access tree.
315  | 
316  |   Arguments: 0 = don't auto save, 1 = auto save
317  | 
318  |   ++++++++++++++++++++++++++++++++++++++*/
319  | int set_auto_save(char *input, GString *output, sk_conn_st *condat)
320  | {
321  |   int res = 0;
322  |   
323  |   /* Lame */
324  |   switch (input[0]) {
325  |   case '0':
326  |     ac_auto_save  = 0;
327  | printf("0\n");
328  |     break;
329  |   case '1':
330  |     ac_auto_save  = 1;
331  | printf("1\n");
332  |     break;
333  |   default:
334  | printf("X\n");
335  |     res = PC_RET_ERR;
336  |   }
337  |   return res;
338  | }
339  | 
340  | /*++++++++++++++++++++++++++++++++++++++
341  |   
342  |   Reset the deny counter in the access tree to 0 (after reenabling) 
343  |   (AC module).
344  | 
345  |   Argument: IP address.
346  | 
347  |   ++++++++++++++++++++++++++++++++++++++*/
348  | int set_nodeny(char *input, GString *output, sk_conn_st *condat) {
349  |   
350  |   /* first 11 characters ("set nodeny ")  are already skipped */
351  | 
352  |   if( ! NOERR( AC_asc_set_nodeny(input) )) {
353  |     g_string_append(output, "Error\n");
354  |     return PC_RET_ERR;
355  |   }
356  |   else {
357  |     return 0;
358  |   }
359  |   
360  | } /* set_nodeny() */
361  | 
362  | 
363  | /*++++++++++++++++++++++++++++++++++++++
364  |   
365  |   Pause/resume update capability of the UD module.
366  | 
367  |   Argument: the word "pause" or "resume".
368  | 
369  |   ++++++++++++++++++++++++++++++++++++++*/
370  | int set_updates(char *input, GString *output, sk_conn_st *condat) 
371  | {
372  |   char argstr[17];
373  |   int pause=0, resume=0;
374  |   int res = 0;
375  |  
376  |   if( sscanf(input, "%16s", argstr) == 1) {
377  |     pause = (strcmp(argstr,"pause") == 0);
378  |     resume = (strcmp(argstr,"resume") == 0);
379  |   }
380  |   
381  |   if( !pause && !resume ) {
382  |     g_string_append(output,  "syntax error.");
383  |     res = PC_RET_ERR;
384  |   }
385  |   else {
386  |     /* all params ok. just set the property */
387  |     char *value = pause ? "0" : "1";
388  |     
389  |     if (CO_set_const("UD.do_update", value) == 0) {
390  |       g_string_append(output, "Constant successfully set\n");
391  |     }
392  |     else {
393  |       g_string_append(output, "Could not set\n");
394  |       res = PC_RET_ERR;
395  |     }
396  |   }
397  |   return res;
398  | }
399  | /*++++++++++++++++++++++++++++++++++++++
400  |   
401  |   Pause/resume queries.
402  | 
403  |   Argument: the word "pause" or "resume".
404  | 
405  |   ++++++++++++++++++++++++++++++++++++++*/
406  | int set_queries(char *input, GString *output, sk_conn_st *condat) 
407  | {
408  |   char argstr[17];
409  |   int pause=0, resume=0;
410  |   int res = 0;
411  |  
412  |   if( sscanf(input, "%16s", argstr) == 1) {
413  |     pause = (strcmp(argstr,"pause") == 0);
414  |     resume = (strcmp(argstr,"resume") == 0);
415  |   }
416  |   
417  |   if( !pause && !resume ) {
418  |     g_string_append(output,  "syntax error.");
419  |     res = PC_RET_ERR;
420  |   }
421  |   else {
422  |    
423  |     if(pause){
424  | 	    PW_stopqueries();
425  | 	    g_string_append(output, "Queries are stopped\n");
426  |     }else {
427  | 	    PW_startqueries();
428  | 	    g_string_append(output, "Queries are unblocked\n");
429  |     }
430  |   }
431  |   return res;
432  | }
433  | 
434  | 
435  | /*++++++++++++++++++++++++++++++++++++++
436  |   
437  |   Reset the source.
438  | 
439  |   Reloads the radix tree.
440  | 
441  |   Argument: the source name.
442  | 
443  |   ++++++++++++++++++++++++++++++++++++++*/
444  | int set_initrx(char *input, GString *output, sk_conn_st *condat) 
445  | {
446  | ca_dbSource_t *source_hdl;
447  | int res = 0;
448  |  
449  | 	source_hdl = ca_get_SourceHandleByName(input); 
450  |         if (source_hdl == NULL){
451  | 		g_string_append(output,  "Unknown source");
452  | 		res = PC_RET_ERR;
453  | 	}
454  | 	else if(RP_init_trees( source_hdl ) != RP_OK ) {
455  | 		g_string_append(output, "Could not re-initialize radix trees");
456  |                 res = PC_RET_ERR;
457  | 	}
458  | 	else if(RP_sql_load_reg( source_hdl ) != RP_OK ) {
459  | 		g_string_append(output, "Could not load radix trees");
460  |                 res = PC_RET_ERR;
461  | 	}
462  |         else {
463  |          g_string_append(output, "radix trees reloaded successfully\n");		
464  |         }
465  |  return res;
466  | }
467  | /*++++++++++++++++++++++++++++++++++++++
468  |   
469  |   Reset the "session time" and "# of tasks" 
470  |   of a specific thread registered with the TA module.
471  | 
472  |   ++++++++++++++++++++++++++++++++++++++*/
473  | #if 0
474  | 
475  | /*
476  | XXX:
477  | I've removed this function because it is supposed to pass a pthread_t 
478  | to the TA_reset_counters() function.  But pthread_t is an opaque
479  | type - on FreeBSD it is a pointer to a structure, so you can't simply
480  | use sscanf() to get one!
481  | 
482  | Shane
483  | 2001-09-05
484  | 
485  | int set_counter(char *input, GString *output, sk_conn_st *condat) 
486  | {
487  |   unsigned thr_id;
488  |   
489  |   if( sscanf(input, "%d", &thr_id) == 1) {
490  |     TA_reset_counters(thr_id);
491  |   }
492  |   return 0;
493  | }
494  | */
495  | #endif /* 0 */
496  | 
497  | 
498  | 
499  | /*++++++++++++++++++++++++++++++++++++++
500  |   
501  |   Execute a command in the ER path processor of the ER module.
502  |   (first subject to macro expansion of the first word).
503  | 
504  |   Argument is passed entirely to ER_macro_spec().
505  | 
506  |   ++++++++++++++++++++++++++++++++++++++*/
507  | int set_err(char *input, GString *output, sk_conn_st *condat) 
508  | {
509  |   char *erret = NULL;
510  |   int res;
511  | 
512  |   res = ER_macro_spec(input, &erret);
513  |   g_string_append(output, erret);
514  |   UT_free(erret);
515  | 
516  |   return res;
517  | }
518  | 
519  | 
520  | /*++++++++++++++++++++++++++++++++++++++
521  |   
522  |   Show the current setup of the ER path system of the ER module.
523  |   
524  |   ++++++++++++++++++++++++++++++++++++++*/
525  | int show_err(char *input, GString *output, sk_conn_st *condat) 
526  | {
527  |   char *erret = NULL;
528  | 
529  |   er_print_paths(&erret);
530  |   g_string_append(output, erret);
531  |   UT_free(erret);
532  | 
533  |   return 0;
534  | }
535  | 
536  | 
537  | /*++++++++++++++++++++++++++++++++++++++
538  |   
539  |   Show the currently defined macros for the ER path system of the ER module.
540  | 
541  |   ++++++++++++++++++++++++++++++++++++++*/
542  | int show_macros(char *input, GString *output, sk_conn_st *condat)
543  | {
544  |   ER_macro_list(condat);
545  |   return 0;
546  | }
547  | 
548  | 
549  | 
550  | /*++++++++++++++++++++++++++++++++++++++
551  |   
552  |   (re)define a macro for the ER path processor.
553  | 
554  |   Arguments: The first word is treated as a macro name. 
555  |   The rest of the line is treated as a macro definition.
556  | 
557  |   ++++++++++++++++++++++++++++++++++++++*/
558  | int set_macro(char *input, GString *output, sk_conn_st *condat)
559  | {
560  |   char *name, *body;
561  |   
562  |   if( strlen(input) > 0 ) {
563  |     body = input;
564  |     name = (char *)strsep(&body, " "); 
565  |     
566  |     ER_make_macro( name, body );
567  |   }
568  | 
569  |   return 0;
570  | }
571  | 
572  | 
573  | 
574  | 
575  | /*++++++++++++++++++++++++++++++++++++++
576  |   
577  |   Trigger running of the socket watchdog actions for a specific thread
578  |   (typically resulting in shutting down of a query thread). 
579  |   
580  |   Arguments are "<socket_id> <thread_id>" as in the output of "show threads".
581  | 
582  |   Assumes the command is like "stop query 11 17". 
583  |   This is to limit ambiguities (a new thread on the same socket, for example).
584  | . 
585  |   ++++++++++++++++++++++++++++++++++++++*/
586  | #if 0
587  | /*
588  | XXX:
589  | I've removed this function because it is supposed to pass a pthread_t 
590  | to the TA_trigger() function.  But pthread_t is an opaque
591  | type - on FreeBSD it is a pointer to a structure, so you can't simply
592  | use sscanf() to get one!
593  | 
594  | Shane
595  | 2001-09-05
596  | 
597  | int stop_query(char *input, GString *output, sk_conn_st *condat) 
598  | {
599  |   int fd;
600  |   unsigned thr;
601  | 
602  |   
603  |   if( sscanf(input, "%d %ud", &fd, &thr) < 2 ) {
604  |     g_string_append(output,"error!!");
605  |     return PC_RET_ERR;
606  |   }
607  |   else {
608  |     TA_trigger("whois", fd, thr);
609  |     return 0;
610  |   }
611  | }
612  | */
613  | #endif /* 0 */