diff --git a/babeld.man b/babeld.man index 814e1834..5f07d21c 100644 --- a/babeld.man +++ b/babeld.man @@ -607,18 +607,13 @@ replies with one or more lines of data terminated by one of or .BR bad . -The following requests are currently defined: -.IP \(bu 2 -any configuration file directive, including -.BR interface ; +All configuration file directives are valid socket requests, including: .IP \(bu -.BR "flush interface" ; +.BR "[flush] interface" .IP \(bu -.BR dump ; +.BR "dump [neighbour|route|xroute|interface]" .IP \(bu -.B monitor -and -.BR unmonitor ; +.BR "[un]monitor [neighbour|route|xroute|interface]" .IP \(bu .BR quit . .SH EXAMPLES diff --git a/configuration.c b/configuration.c index e9787267..c0bb0877 100644 --- a/configuration.c +++ b/configuration.c @@ -969,6 +969,40 @@ parse_option(int c, gnc_t gnc, void *closure, char *token) } +static int +parse_monitor_dump_filter(int *action_return, int c, gnc_t *gnc, void *closure) +{ + int filter = 0; + char *token = NULL; + + c = skip_whitespace(c, *gnc, closure); + c = getword(c, &token, *gnc, closure); + if(c < -1 || token == NULL) { + free(token); + return c; + } + + if(strcmp(token, "route") == 0) + filter = FILTER(ROUTE); + else if(strcmp(token, "interface") == 0) + filter = FILTER(INTERFACE); + else if(strcmp(token, "xroute") == 0) + filter = FILTER(XROUTE); + else if(strcmp(token, "neighbour") == 0) + filter = FILTER(NEIGHBOUR); + else + filter = FILTER_INVALID; + free(token); + + c = skip_eol(c, *gnc, closure); + if(filter < FILTER_INVALID) { + *action_return += filter; + if(!filter) // no (invalid) filters detected, show everything + return -1; + } + return -2; +} + static int parse_config_line(int c, gnc_t gnc, void *closure, int *action_return, const char **message_return) @@ -996,20 +1030,14 @@ parse_config_line(int c, gnc_t gnc, void *closure, goto fail; *action_return = CONFIG_ACTION_QUIT; } else if(strcmp(token, "dump") == 0) { - c = skip_eol(c, gnc, closure); - if(c < -1 || !action_return) - goto fail; - *action_return = CONFIG_ACTION_DUMP; + *action_return = CONFIG_ACTION_DUMP(0); + c = parse_monitor_dump_filter(action_return, c, &gnc, closure); } else if(strcmp(token, "monitor") == 0) { - c = skip_eol(c, gnc, closure); - if(c < -1 || !action_return) - goto fail; - *action_return = CONFIG_ACTION_MONITOR; + *action_return = CONFIG_ACTION_MONITOR(0); + c = parse_monitor_dump_filter(action_return, c, &gnc, closure); } else if(strcmp(token, "unmonitor") == 0) { - c = skip_eol(c, gnc, closure); - if(c < -1 || !action_return) - goto fail; - *action_return = CONFIG_ACTION_UNMONITOR; + *action_return = CONFIG_ACTION_UNMONITOR(0); + c = parse_monitor_dump_filter(action_return, c, &gnc, closure); } else if(config_finalised && !local_server_write) { /* The remaining directives are only allowed in read-write mode. */ c = skip_to_eol(c, gnc, closure); diff --git a/configuration.h b/configuration.h index 0ebfd481..a2ee4e00 100644 --- a/configuration.h +++ b/configuration.h @@ -20,14 +20,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Values returned by parse_config_from_string. */ +#define NEIGHBOUR 1 +#define ROUTE 2 +#define XROUTE 3 +#define INTERFACE 4 +/* Values returned by parse_config_from_string. */ #define CONFIG_ACTION_DONE 0 #define CONFIG_ACTION_QUIT 1 -#define CONFIG_ACTION_DUMP 2 -#define CONFIG_ACTION_MONITOR 3 -#define CONFIG_ACTION_UNMONITOR 4 -#define CONFIG_ACTION_NO 5 +#define CONFIG_ACTION_DUMP(thing) (2 + (thing)) +#define CONFIG_ACTION_NO 7 +#define CONFIG_ACTION_MONITOR(thing) (8 + (thing)) +#define CONFIG_ACTION_UNMONITOR(thing) (13 + (thing)) + +#define FILTER(thing) (thing) +#define FILTER_INVALID 255 struct filter_result { unsigned int add_metric; /* allow = 0, deny = INF, metric = <0..INF> */ diff --git a/local.c b/local.c index 45d07679..5040620a 100644 --- a/local.c +++ b/local.c @@ -42,6 +42,8 @@ THE SOFTWARE. #include "local.h" #include "version.h" +#define SHOW(thing) (1U << ((thing)-1)) + int local_server_socket = -1; struct local_socket local_sockets[MAX_LOCAL_SOCKETS]; int num_local_sockets = 0; @@ -133,7 +135,7 @@ local_notify_interface(struct interface *ifp, int kind) { int i; for(i = 0; i < num_local_sockets; i++) { - if(local_sockets[i].monitor) + if((local_sockets[i].monitor & SHOW(INTERFACE)) != 0) local_notify_interface_1(&local_sockets[i], ifp, kind); } } @@ -188,7 +190,7 @@ local_notify_neighbour(struct neighbour *neigh, int kind) { int i; for(i = 0; i < num_local_sockets; i++) { - if(local_sockets[i].monitor) + if((local_sockets[i].monitor & SHOW(NEIGHBOUR)) != 0) local_notify_neighbour_1(&local_sockets[i], neigh, kind); } } @@ -225,7 +227,7 @@ local_notify_xroute(struct xroute *xroute, int kind) { int i; for(i = 0; i < num_local_sockets; i++) { - if(local_sockets[i].monitor) + if((local_sockets[i].monitor & SHOW(XROUTE)) != 0) local_notify_xroute_1(&local_sockets[i], xroute, kind); } } @@ -270,26 +272,36 @@ local_notify_route(struct babel_route *route, int kind) { int i; for(i = 0; i < num_local_sockets; i++) { - if(local_sockets[i].monitor) + if((local_sockets[i].monitor & SHOW(ROUTE)) != 0) local_notify_route_1(&local_sockets[i], route, kind); } } + static void -local_notify_all_1(struct local_socket *s) +local_notify_all_neighbour_1(struct local_socket *s) { - struct interface *ifp; struct neighbour *neigh; - struct xroute_stream *xroutes; - struct route_stream *routes; + + FOR_ALL_NEIGHBOURS(neigh) { + local_notify_neighbour_1(s, neigh, LOCAL_ADD); + } +} + +static void +local_notify_all_interface_1(struct local_socket *s) +{ + struct interface *ifp; FOR_ALL_INTERFACES(ifp) { local_notify_interface_1(s, ifp, LOCAL_ADD); } +} - FOR_ALL_NEIGHBOURS(neigh) { - local_notify_neighbour_1(s, neigh, LOCAL_ADD); - } +static void +local_notify_all_xroute_1(struct local_socket *s) +{ + struct xroute_stream *xroutes; xroutes = xroute_stream(); if(xroutes) { @@ -301,6 +313,12 @@ local_notify_all_1(struct local_socket *s) } xroute_stream_done(xroutes); } +} + +static void +local_notify_all_route_1(struct local_socket *s) +{ + struct route_stream *routes; routes = route_stream(ROUTE_ALL); if(routes) { @@ -312,7 +330,56 @@ local_notify_all_1(struct local_socket *s) } route_stream_done(routes); } - return; +} + +static void +local_notify_all(struct local_socket *s, unsigned int mask) +{ + if((mask & SHOW(INTERFACE)) != 0) + local_notify_all_interface_1(s); + if((mask & SHOW(NEIGHBOUR)) != 0) + local_notify_all_neighbour_1(s); + if((mask & SHOW(ROUTE)) != 0) + local_notify_all_route_1(s); + if((mask & SHOW(XROUTE)) != 0) + local_notify_all_xroute_1(s); +} + +static void +local_notify_all_1(struct local_socket *s) +{ + local_notify_all_interface_1(s); + local_notify_all_neighbour_1(s); + local_notify_all_xroute_1(s); + local_notify_all_route_1(s); +} + +static unsigned int +show_flags_map(int rc) +{ + switch(rc) { + case CONFIG_ACTION_MONITOR(ROUTE): + case CONFIG_ACTION_UNMONITOR(ROUTE): + case CONFIG_ACTION_DUMP(ROUTE): + return SHOW(ROUTE); + case CONFIG_ACTION_MONITOR(INTERFACE): + case CONFIG_ACTION_UNMONITOR(INTERFACE): + case CONFIG_ACTION_DUMP(INTERFACE): + return SHOW(INTERFACE); + case CONFIG_ACTION_MONITOR(XROUTE): + case CONFIG_ACTION_UNMONITOR(XROUTE): + case CONFIG_ACTION_DUMP(XROUTE): + return SHOW(XROUTE); + case CONFIG_ACTION_MONITOR(NEIGHBOUR): + case CONFIG_ACTION_UNMONITOR(NEIGHBOUR): + case CONFIG_ACTION_DUMP(NEIGHBOUR): + return SHOW(NEIGHBOUR); + case CONFIG_ACTION_MONITOR(0): + case CONFIG_ACTION_UNMONITOR(0): + case CONFIG_ACTION_DUMP(0): + return ~0U; + } + return 0U; } int @@ -352,15 +419,32 @@ local_read(struct local_socket *s) shutdown(s->fd, 1); reply[0] = '\0'; break; - case CONFIG_ACTION_DUMP: - local_notify_all_1(s); + case CONFIG_ACTION_DUMP(INTERFACE): + case CONFIG_ACTION_DUMP(ROUTE): + case CONFIG_ACTION_DUMP(XROUTE): + case CONFIG_ACTION_DUMP(NEIGHBOUR): + case CONFIG_ACTION_DUMP(0): + local_notify_all(s, show_flags_map(rc)); break; - case CONFIG_ACTION_MONITOR: + case CONFIG_ACTION_MONITOR(0): + s->monitor = 0xff; local_notify_all_1(s); - s->monitor = 1; break; - case CONFIG_ACTION_UNMONITOR: - s->monitor = 0; + case CONFIG_ACTION_MONITOR(NEIGHBOUR): + case CONFIG_ACTION_MONITOR(INTERFACE): + case CONFIG_ACTION_MONITOR(ROUTE): + case CONFIG_ACTION_MONITOR(XROUTE): + s->monitor |= show_flags_map(rc); + local_notify_all(s, show_flags_map(rc)); + break; + case CONFIG_ACTION_UNMONITOR(NEIGHBOUR): + case CONFIG_ACTION_UNMONITOR(INTERFACE): + case CONFIG_ACTION_UNMONITOR(ROUTE): + case CONFIG_ACTION_UNMONITOR(XROUTE): + s->monitor &= ~show_flags_map(rc); + break; + case CONFIG_ACTION_UNMONITOR(0): + s->monitor = 0U; break; case CONFIG_ACTION_NO: snprintf(reply, sizeof(reply), "no%s%s\n", diff --git a/local.h b/local.h index 23161111..53d230c2 100644 --- a/local.h +++ b/local.h @@ -38,7 +38,7 @@ struct local_socket { int fd; char *buf; int n; - int monitor; + unsigned int monitor; }; extern int local_server_socket;