eventscript: check that internal script events are being invoked correctly
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 24 Nov 2009 00:53:13 +0000 (11:23 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 24 Nov 2009 00:53:13 +0000 (11:23 +1030)
This is not as good as a compile-time check, but at least we count the
number of arguments are correct.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
server/eventscript.c

index 8ca3be1b76b283f847648e0bf05b4badbe546784..8814858f26939f9a213285c61cea6580eed416f7 100644 (file)
@@ -744,6 +744,45 @@ static int event_script_destructor(struct ctdb_event_script_state *state)
        return 0;
 }
 
+static unsigned int count_words(const char *options)
+{
+       unsigned int words = 0;
+
+       options += strspn(options, " \t");
+       while (*options) {
+               words++;
+               options += strcspn(options, " \t");
+               options += strspn(options, " \t");
+       }
+       return words;
+}
+
+static bool check_options(enum ctdb_eventscript_call call, const char *options)
+{
+       switch (call) {
+       /* These all take no arguments. */
+       case CTDB_EVENT_STARTUP:
+       case CTDB_EVENT_START_RECOVERY:
+       case CTDB_EVENT_RECOVERED:
+       case CTDB_EVENT_STOPPED:
+       case CTDB_EVENT_MONITOR:
+       case CTDB_EVENT_STATUS:
+       case CTDB_EVENT_SHUTDOWN:
+               return count_words(options) == 0;
+
+       case CTDB_EVENT_TAKE_IP: /* interface, IP address, netmask bits. */
+       case CTDB_EVENT_RELEASE_IP:
+               return count_words(options) == 3;
+
+       case CTDB_EVENT_UNKNOWN:
+               return true;
+
+       default:
+               DEBUG(DEBUG_ERR,(__location__ "Unknown ctdb_eventscript_call %u\n", call));
+               return false;
+       }
+}
+
 /*
   run the event script in the background, calling the callback when 
   finished
@@ -805,6 +844,12 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
                talloc_free(state);
                return -1;
        }
+       if (!check_options(state->call, state->options)) {
+               DEBUG(DEBUG_ERR, ("Bad eventscript options '%s' for %s\n",
+                                 call_names[state->call], state->options));
+               talloc_free(state);
+               return -1;
+       }
 
        DEBUG(DEBUG_INFO,(__location__ " Starting eventscript %s %s\n",
                          call_names[state->call], state->options));