/* * Copyright (c) 2016 - 2018 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Bill Yuan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipfw3.h" #include "ipfw3sync.h" void sync_config_edge(int ac, char *av[]) { struct ipfw3_ioc_sync_edge ioc_edge; NEXT_ARG; if (isdigit(**av)) { ioc_edge.port = atoi(*av); if (ioc_edge.port == 0) { errx(EX_USAGE, "invalid edge port `%s'", *av); } NEXT_ARG; if (strcmp(*av, "all") == 0) { ioc_edge.hw_same = 1; } else { ioc_edge.hw_same = 0; } if(do_set_x(IP_FW_SYNC_EDGE_CONF, &ioc_edge, sizeof(ioc_edge)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_EDGE_CONF)"); } } else { errx(EX_USAGE, "invalid edge port `%s'", *av); } } void sync_config_centre(int ac, char *av[]) { struct ipfw3_ioc_sync_centre *centre; struct ipfw3_sync_edge *edge; struct in_addr addr; char *tok; char *str; int count = 0, step = 10, len, data_len; void *data = NULL; NEXT_ARG; tok = strtok(*av, ","); len = sizeof(int); data_len = len + step * LEN_SYNC_EDGE; data = malloc(data_len); centre = (struct ipfw3_ioc_sync_centre *)data; edge = centre->edges; while (tok != NULL) { str = strchr(tok,':'); if (str != NULL) { *(str++) = '\0'; edge->port = (u_short)strtoul(str, NULL, 0); if (edge->port == 0) { errx(EX_USAGE, "edge `%s:%s' invalid", tok, str); } } else { err(EX_UNAVAILABLE, "dst invalid"); } inet_aton(tok, &addr); edge->addr = addr.s_addr; if (count >= step) { step += 10; data_len = len + step * LEN_SYNC_EDGE; if ((data = realloc(data, data_len)) == NULL) { err(EX_OSERR, "realloc in config sync centre"); } } tok = strtok (NULL, ","); count++; edge++; } if (count > MAX_EDGES) { err(EX_OSERR,"too much edges"); } centre->count = count; len += count * LEN_SYNC_EDGE; if(do_set_x(IP_FW_SYNC_CENTRE_CONF, data, len) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_CENTRE_CONF)"); } } void sync_show_config(int ac, char *av[]) { void *data = NULL; int nalloc = 1000, nbytes; nbytes = nalloc; while (nbytes >= nalloc) { nalloc = nalloc * 2 + 321; nbytes = nalloc; if (data == NULL) { if ((data = malloc(nbytes)) == NULL) { err(EX_OSERR, "malloc"); } } else if ((data = realloc(data, nbytes)) == NULL) { err(EX_OSERR, "realloc"); } if (do_get_x(IP_FW_SYNC_SHOW_CONF, data, &nbytes) < 0) { err(EX_OSERR, "getsockopt(IP_FW_SYNC_SHOW_CONF)"); } } struct ipfw3_ioc_sync_context *sync_ctx; sync_ctx = (struct ipfw3_ioc_sync_context *)data; if (sync_ctx->edge_port != 0) { printf("ipfw3sync edge on %d %s\n", sync_ctx->edge_port, sync_ctx->hw_same == 1 ? "all" : ""); } if (sync_ctx->count > 0) { struct ipfw3_sync_edge *edge; int i; edge = sync_ctx->edges; printf("ipfw3sync centre to %d edge(s)\n", sync_ctx->count); for (i = 0; i < sync_ctx->count; i++) { struct in_addr in; in.s_addr = edge->addr; printf("edge on %s:%d\n", inet_ntoa(in), edge->port); edge++; } } } void sync_show_status(int ac, char *av[]) { int running, len; len = sizeof(running); if (do_get_x(IP_FW_SYNC_SHOW_STATUS, &running, &len) < 0) { err(EX_OSERR, "getsockopt(IP_FW_SYNC_SHOW_STATUS)"); } if (running & 1) { printf("edge is running\n"); } if (running & 2) { printf("centre is running\n"); } } void sync_edge_start(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_EDGE_START, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_EDGE_START)"); } } void sync_centre_start(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_CENTRE_START, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_CENTRE_START)"); } } void sync_edge_stop(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_EDGE_STOP, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_EDGE_STOP)"); } } void sync_centre_stop(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_CENTRE_STOP, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_CENTRE_STOP"); } } void sync_edge_clear(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_EDGE_CLEAR, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_EDGE_CLEAR)"); } } void sync_centre_clear(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_CENTRE_CLEAR, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_CENTRE_CLEAR)"); } } void sync_edge_test(int ac, char *av[]) { int i = 0; if(do_set_x(IP_FW_SYNC_EDGE_TEST, &i, sizeof(i)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_EDGE_CLEAR)"); } } void sync_centre_test(int ac, char *av[]) { int n; NEXT_ARG; if (!isdigit(**av)) { errx(EX_DATAERR, "invalid test number %s\n", *av); } n = atoi(*av); if(do_set_x(IP_FW_SYNC_CENTRE_TEST, &n, sizeof(n)) < 0) { err(EX_UNAVAILABLE, "do_set_x(IP_FW_SYNC_CENTRE_TEST)"); } printf("centre test %d sent\n", n); } void sync_main(int ac, char **av) { if (!strncmp(*av, "edge", strlen(*av))) { sync_config_edge(ac, av); } else if (!strncmp(*av, "centre", strlen(*av))) { sync_config_centre(ac, av); } else if (!strncmp(*av, "show", strlen(*av))) { NEXT_ARG; if (!strncmp(*av, "config", strlen(*av))) { sync_show_config(ac, av); } else if (!strncmp(*av, "status", strlen(*av))) { sync_show_status(ac, av); } else { errx(EX_USAGE, "bad show command `%s'", *av); } } else if (!strncmp(*av, "start", strlen(*av))) { NEXT_ARG; if (!strncmp(*av, "edge", strlen(*av))) { sync_edge_start(ac, av); } else if (!strncmp(*av, "centre", strlen(*av))) { sync_centre_start(ac, av); } } else if (!strncmp(*av, "stop", strlen(*av))) { NEXT_ARG; if (!strncmp(*av, "edge", strlen(*av))) { sync_edge_stop(ac, av); } else if (!strncmp(*av, "centre", strlen(*av))) { sync_centre_stop(ac, av); } } else if (!strncmp(*av, "clear", strlen(*av))) { NEXT_ARG; if (!strncmp(*av, "edge", strlen(*av))) { sync_edge_clear(ac, av); } else if (!strncmp(*av, "centre", strlen(*av))) { sync_centre_clear(ac, av); } } else if (!strncmp(*av, "test", strlen(*av))) { NEXT_ARG; if (!strncmp(*av, "edge", strlen(*av))) { sync_edge_test(ac, av); } else if (!strncmp(*av, "centre", strlen(*av))) { sync_centre_test(ac, av); } } else { errx(EX_USAGE, "bad ipfw sync command `%s'", *av); } }