1    | #include "mysql_driver.h"
2    | #include "access_control.h"
3    | #include "thread.h"
4    | #include "constants.h"
5    | #include "properties.h"
6    | #include "protocol_config.h"
7    | #include "protocol_whois.h"
8    | #include "ta.h"
9    | #include "pc_commands.h"
10   | 
11   | #include "ca_defs.h"
12   | #include "ca_configFns.h"
13   | 
14   | #include "rp.h"
15   | 
16   | 
17   | #include "er_paths.h"
18   | #include "er_macro.h"
19   | 
20   | /* this is for purify - to display the memory allocation records */
21   | extern void purify_new_inuse(void);
22   | 
23   | 
24   | 
25   | /*++++++++++++++++++++++++++++++++++++++
26   |   
27   |   All functions in this file share the same interface: they take the
28   |   arguments to the command given by the user, pointer to a dynamic
29   |   GString to which the command output should be appended and the
30   |   connection data, so that some things can be displayed directly to it,
31   |   bypassing the GString.
32   |   
33   |   int <command_something>     return code. 0 indicates success.
34   |                               PC_RET_QUIT is a reserved code
35   |                               that indicates that the connection
36   | 			      should be closed. 
37   | 
38   |   char *input                 command arguments
39   | 
40   |   GString *output             (dynamic) output string
41   | 
42   |   sk_conn_st *condat          connection data
43   | 
44   |   ++++++++++++++++++++++++++++++++++++++*/
45   | 
46   | /*++++++++++++++++++++++++++++++++++++++
47   |       
48   |   Relay functions for composed commands (eg. "set counter").
49   | 
50   |   They run the second word as a command from a specific array
51   |   (show/set/stop/whatever). The hardcoded text is used only for help
52   |   messages, printed in case the command is wrong as 
53   | 
54   |  "<hardcoded> commands are: <list of possible commands>".
55   | 
56   |  ++++++++++++++++++++++++++++++++++++++*/
57   | int command_show(char *input, GString *output, sk_conn_st *condat) {
58   |   return command_execute(show, "show ", input, output, condat);
59   | }
60   | 
61   | int command_set( char *input, GString *output, sk_conn_st *condat) {
62   |   return command_execute(set,  "set ",  input, output, condat);
63   | }
64   | 
65   | int command_stop(char *input, GString *output, sk_conn_st *condat) {
66   |   return command_execute(stop, "stop ", input, output, condat);
67   | }
68   | 
69   | 
70   | /*++++++++++++++++++++++++++++++++++++++
71   |   
72   |   Display available commands.
73   |   
74   |   ++++++++++++++++++++++++++++++++++++++*/
75   | int command_help(char *input, GString *output, sk_conn_st *condat) 
76   | {
77   |   /* by the time it came here, the "help" bit is already taken away. */
78   |   return show_commands(command, "", output);
79   | 
80   | }
81   | 
82   | 
83   | /*++++++++++++++++++++++++++++++++++++++
84   |   
85   |   Quit the config session.
86   | 
87   |   ++++++++++++++++++++++++++++++++++++++*/
88   | int command_quit(char *input, GString *output, sk_conn_st *condat) {
89   |     /* Administrator wishes to quit. */
90   |   return PC_RET_QUIT;
91   | } /* command_quit() */
92   | 
93   | /*++++++++++++++++++++++++++++++++++++++
94   |   
95   |   Display the memory allocation records of purify(tm).
96   |   The #define must be changed to activate this.
97   |   The program will link only with purify.
98   | 
99   |   ++++++++++++++++++++++++++++++++++++++*/
100  | int command_purify(char *input, GString *output, sk_conn_st *condat)
101  | {
102  | #if 0
103  |   purify_new_inuse();
104  | #else 
105  |   g_string_append(output, "NOP");
106  | #endif
107  |   
108  |   return 0;
109  | }
110  | 
111  | 
112  | /*++++++++++++++++++++++++++++++++++++++
113  |   
114  |   Display a specific constant of the CO module.
115  | 
116  |   Argument: name of the constant.
117  | 
118  |   ++++++++++++++++++++++++++++++++++++++*/
119  | int show_const(char *input, GString *output, sk_conn_st *condat) {
120  |   /* Administrator wishes to show constants. */
121  |   char *result, *name, *cursor;
122  |   int res = 0;
123  |   
124  |   if( strlen(input) > 0 ) {
125  |     cursor = input;
126  |     name = (char *)strsep(&cursor, " ");
127  | 
128  |     if( (result = CO_const_to_string(name)) != NULL ) {
129  |       g_string_append(output, result);
130  |       wr_free(result);
131  |     }
132  |     else {
133  |       g_string_append(output,  "unknown constant");
134  |       res = PC_RET_ERR;
135  |     }
136  |   }
137  |   else {
138  |     g_string_append(output,  "name required");
139  |     res = PC_RET_ERR;
140  |   }
141  |  
142  |   return res;
143  | 
144  | } /* show_const() */
145  | 
146  | 
147  | /*++++++++++++++++++++++++++++++++++++++
148  |   
149  |   Display all the constants of the CO module.
150  | 
151  |   ++++++++++++++++++++++++++++++++++++++*/
152  | int show_consts(char *input, GString *output, sk_conn_st *condat) 
153  | {
154  |   /* Administrator wishes to show constants. */
155  |   char *s =  CO_to_string();
156  |   g_string_append(output, s);
157  |   free(s);
158  |   return 0;
159  | } /* show_consts() */
160  | 
161  | 
162  | /*++++++++++++++++++++++++++++++++++++++
163  |   
164  |   Display all the properties of the PR module.
165  | 
166  |   ++++++++++++++++++++++++++++++++++++++*/
167  | int show_props(char *input, GString *output, sk_conn_st *condat) 
168  | {
169  |   /* Administrator wishes to show properties. */
170  |   char *s =  PR_to_string();
171  |   g_string_append(output, s);
172  |   free(s);  
173  |   return 0;
174  | } /* show_props() */
175  | 
176  | 
177  | /*++++++++++++++++++++++++++++++++++++++
178  |   
179  |   Display all running threads registered with the TA module.
180  | 
181  |   ++++++++++++++++++++++++++++++++++++++*/
182  | int show_threads(char *input, GString *output, sk_conn_st *condat) 
183  | {
184  |   /* Administrator wishes to show thread information. */
185  |   char *s = TA_tostring();
186  |   g_string_append(output, s);
187  |   free(s);  
188  |   return 0;
189  | } /* show_thread() */
190  | 
191  | 
192  | /*++++++++++++++++++++++++++++++++++++++
193  |   
194  |   Switch the session to a whois session.
195  | 
196  |   ++++++++++++++++++++++++++++++++++++++*/
197  | int show_whois(char *input, GString *output, sk_conn_st *condat) 
198  | {
199  |   /*  Go to whois mode */
200  |   PW_interact(condat->sock);
201  |   return 0;
202  | } /* show_whois() */
203  | 
204  | 
205  | /*++++++++++++++++++++++++++++++++++++++
206  |   
207  |   Display the statistics about the server.
208  | 
209  |   ++++++++++++++++++++++++++++++++++++++*/
210  | int show_uptime(char *input, GString *output, sk_conn_st *condat) 
211  | {
212  |   char timestring[26];
213  |   extern time_t SV_starttime;
214  |   
215  |   ctime_r(&SV_starttime, timestring); 
216  |   SK_cd_printf( condat, 
217  | 	       "System running since %sUptime in seconds: %ld \n\n",
218  | 	       timestring,		  
219  | 	       time(NULL) - SV_starttime);
220  |   
221  |   return 0;
222  | } 
223  | 
224  | /*++++++++++++++++++++++++++++++++++++++
225  |   
226  |   Display the whois access statistics from the AC module.
227  | 
228  |   ++++++++++++++++++++++++++++++++++++++*/
229  | int show_access(char *input, GString *output, sk_conn_st *condat) 
230  | {  
231  |   int cnt = AC_print_access(output);
232  |   
233  |   g_string_sprintfa(output, "Found %d nodes\n", cnt);
234  | 
235  |   return 0;
236  | } /* show_access() */
237  | 
238  | 
239  | /*++++++++++++++++++++++++++++++++++++++
240  |   
241  |   Display the whois access control list from the AC module.
242  | 
243  |   ++++++++++++++++++++++++++++++++++++++*/
244  | int show_acl(char *input, GString *output, sk_conn_st *condat) 
245  | {
246  |   int cnt = AC_print_acl(output);
247  | 
248  |   g_string_sprintfa(output, "Found %d nodes\n", cnt);
249  | 
250  |   return 0;
251  | } /* show_acl() */
252  | 
253  | 
254  | /*++++++++++++++++++++++++++++++++++++++
255  |   
256  |   Modify the whois access control list in the AC module.
257  | 
258  |   Arguments: IP[/prefixlength] column=value,column=value...
259  | 
260  |   Column names as in acl display. Unset columns are inherited.
261  | 
262  |   ++++++++++++++++++++++++++++++++++++++*/
263  | int set_acl(char *input, GString *output, sk_conn_st *condat)
264  | {
265  |   int res = 0;
266  |   
267  |   /* first 8 characters ("set acl ") are already skipped */
268  |   if( ! NOERR( AC_asc_acl_command_set( input, "Manual"))) {
269  |     g_string_append(output, "Error!\n");
270  |     res = PC_RET_ERR;
271  |   }
272  |   return res;
273  | }
274  | 
275  | /*++++++++++++++++++++++++++++++++++++++
276  |   
277  |   Reset the deny counter in the access tree to 0 (after reenabling) 
278  |   (AC module).
279  | 
280  |   Argument: IP address.
281  | 
282  |   ++++++++++++++++++++++++++++++++++++++*/
283  | int set_nodeny(char *input, GString *output, sk_conn_st *condat) {
284  |   
285  |   /* first 11 characters ("set nodeny ")  are already skipped */
286  | 
287  |   if( ! NOERR( AC_asc_set_nodeny(input) )) {
288  |     g_string_append(output, "Error\n");
289  |     return PC_RET_ERR;
290  |   }
291  |   else {
292  |     return 0;
293  |   }
294  |   
295  | } /* set_nodeny() */
296  | 
297  | 
298  | /*++++++++++++++++++++++++++++++++++++++
299  |   
300  |   Pause/resume update capability of the UD module.
301  | 
302  |   Argument: the word "pause" or "resume".
303  | 
304  |   ++++++++++++++++++++++++++++++++++++++*/
305  | int set_updates(char *input, GString *output, sk_conn_st *condat) 
306  | {
307  |   char argstr[17];
308  |   int pause=0, resume=0;
309  |   int res = 0;
310  |  
311  |   if( sscanf(input, "%16s", argstr) == 1) {
312  |     pause = (strcmp(argstr,"pause") == 0);
313  |     resume = (strcmp(argstr,"resume") == 0);
314  |   }
315  |   
316  |   if( !pause && !resume ) {
317  |     g_string_append(output,  "syntax error.");
318  |     res = PC_RET_ERR;
319  |   }
320  |   else {
321  |     /* all params ok. just set the property */
322  |     char *value = pause ? "0" : "1";
323  |     
324  |     if (CO_set_const("UD.do_update", value) == 0) {
325  |       g_string_append(output, "Constant successfully set\n");
326  |     }
327  |     else {
328  |       g_string_append(output, "Could not set\n");
329  |       res = PC_RET_ERR;
330  |     }
331  |   }
332  |   return res;
333  | }
334  | /*++++++++++++++++++++++++++++++++++++++
335  |   
336  |   Pause/resume queries.
337  | 
338  |   Argument: the word "pause" or "resume".
339  | 
340  |   ++++++++++++++++++++++++++++++++++++++*/
341  | int set_queries(char *input, GString *output, sk_conn_st *condat) 
342  | {
343  |   char argstr[17];
344  |   int pause=0, resume=0;
345  |   int res = 0;
346  |  
347  |   if( sscanf(input, "%16s", argstr) == 1) {
348  |     pause = (strcmp(argstr,"pause") == 0);
349  |     resume = (strcmp(argstr,"resume") == 0);
350  |   }
351  |   
352  |   if( !pause && !resume ) {
353  |     g_string_append(output,  "syntax error.");
354  |     res = PC_RET_ERR;
355  |   }
356  |   else {
357  |    
358  |     if(pause){
359  | 	    PW_stopqueries();
360  | 	    g_string_append(output, "Queries are stopped\n");
361  |     }else {
362  | 	    PW_startqueries();
363  | 	    g_string_append(output, "Queries are unblocked\n");
364  |     }
365  |   }
366  |   return res;
367  | }
368  | 
369  | 
370  | /*++++++++++++++++++++++++++++++++++++++
371  |   
372  |   Reset the source.
373  | 
374  |   Stops updates for a given source and reloads the radix tree.
375  | 
376  |   Argument: the source name.
377  | 
378  |   ++++++++++++++++++++++++++++++++++++++*/
379  | int set_initrx(char *input, GString *output, sk_conn_st *condat) 
380  | {
381  | ca_dbSource_t *source_hdl;
382  | int res = 0;
383  |  
384  | 	source_hdl = ca_get_SourceHandleByName(input); 
385  |         if (source_hdl == NULL){
386  | 		g_string_append(output,  "Unknown source");
387  | 		res = PC_RET_ERR;
388  | 	}
389  | 	else if (CO_set_const("UD.do_update", "0") != 0) {
390  |                 g_string_append(output, "Could not stop updates");
391  |                 res = PC_RET_ERR;
392  |         }
393  | 	else if(RP_init_trees( source_hdl ) != RP_OK ) {
394  | 		g_string_append(output, "Could not re-initialize radix trees");
395  |                 res = PC_RET_ERR;
396  | 	}
397  | 	else if(RP_sql_load_reg( source_hdl ) != RP_OK ) {
398  | 		g_string_append(output, "Could not load radix trees");
399  |                 res = PC_RET_ERR;
400  | 	}
401  |         else {
402  |          g_string_append(output, "radix trees reloaded successfully\nplease resume updates");		
403  |         }
404  |  return res;
405  | }
406  | /*++++++++++++++++++++++++++++++++++++++
407  |   
408  |   Reset the "session time" and "# of tasks" 
409  |   of a specific thread registered with the TA module.
410  | 
411  |   ++++++++++++++++++++++++++++++++++++++*/
412  | int set_counter(char *input, GString *output, sk_conn_st *condat) 
413  | {
414  |   unsigned thr_id;
415  |   
416  |   if( sscanf(input, "%d", &thr_id) == 1) {
417  |     TA_reset_counters(thr_id);
418  |   }
419  |   return 0;
420  | }
421  | 
422  | 
423  | 
424  | /*++++++++++++++++++++++++++++++++++++++
425  |   
426  |   Execute a command in the ER path processor of the ER module.
427  |   (first subject to macro expansion of the first word).
428  | 
429  |   Argument is passed entirely to ER_macro_spec().
430  | 
431  |   ++++++++++++++++++++++++++++++++++++++*/
432  | int set_err(char *input, GString *output, sk_conn_st *condat) 
433  | {
434  |   char *erret = NULL;
435  |   int res;
436  | 
437  |   res = ER_macro_spec(input, &erret);
438  |   g_string_append(output, erret);
439  |   free(erret);
440  | 
441  |   return res;
442  | }
443  | 
444  | 
445  | /*++++++++++++++++++++++++++++++++++++++
446  |   
447  |   Show the current setup of the ER path system of the ER module.
448  |   
449  |   ++++++++++++++++++++++++++++++++++++++*/
450  | int show_err(char *input, GString *output, sk_conn_st *condat) 
451  | {
452  |   char *erret = NULL;
453  | 
454  |   er_print_paths(&erret);
455  |   g_string_append(output, erret);
456  |   free(erret);
457  | 
458  |   return 0;
459  | }
460  | 
461  | 
462  | /*++++++++++++++++++++++++++++++++++++++
463  |   
464  |   Show the currently defined macros for the ER path system of the ER module.
465  | 
466  |   ++++++++++++++++++++++++++++++++++++++*/
467  | int show_macros(char *input, GString *output, sk_conn_st *condat)
468  | {
469  |   ER_macro_list(condat);
470  |   return 0;
471  | }
472  | 
473  | 
474  | 
475  | /*++++++++++++++++++++++++++++++++++++++
476  |   
477  |   (re)define a macro for the ER path processor.
478  | 
479  |   Arguments: The first word is treated as a macro name. 
480  |   The rest of the line is treated as a macro definition.
481  | 
482  |   ++++++++++++++++++++++++++++++++++++++*/
483  | int set_macro(char *input, GString *output, sk_conn_st *condat)
484  | {
485  |   char *name, *body;
486  |   
487  |   if( strlen(input) > 0 ) {
488  |     body = input;
489  |     name = (char *)strsep(&body, " "); 
490  |     
491  |     ER_make_macro( name, body );
492  |   }
493  | 
494  |   return 0;
495  | }
496  | 
497  | 
498  | 
499  | 
500  | /*++++++++++++++++++++++++++++++++++++++
501  |   
502  |   Trigger running of the socket watchdog actions for a specific thread
503  |   (typically resulting in shutting down of a query thread). 
504  |   
505  |   Arguments are "<socket_id> <thread_id>" as in the output of "show threads".
506  | 
507  |   Assumes the command is like "stop query 11 17". 
508  |   This is to limit ambiguities (a new thread on the same socket, for example).
509  | . 
510  |   ++++++++++++++++++++++++++++++++++++++*/
511  | int stop_query(char *input, GString *output, sk_conn_st *condat) 
512  | {
513  |   int fd;
514  |   unsigned thr;
515  | 
516  |   
517  |   if( sscanf(input, "%d %ud", &fd, &thr) < 2 ) {
518  |     g_string_append(output,"error!!");
519  |     return PC_RET_ERR;
520  |   }
521  |   else {
522  |     TA_trigger("whois", fd, thr);
523  |     return 0;
524  |   }
525  | }