Annotation of fwsync/patches/sync.c, revision 1.3.2.1

1.1       misho       1: /*-
1.3       misho       2:  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
1.1       misho       3:  *
1.3       misho       4:  * Copyright (c) 2022 Michael Pounov <misho@elwix.org>, CloudSigma AG
1.1       misho       5:  *
1.3       misho       6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
1.1       misho      14:  *
1.3       misho      15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     16:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     17:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
1.1       misho      26:  *
                     27:  * command line interface for sync state of IP firewall
                     28:  */
                     29: #include <stdio.h>
                     30: #include <stdlib.h>
                     31: #include <string.h>
                     32: #include <unistd.h>
                     33: #include <errno.h>
                     34: #include <sys/socket.h>
                     35: #include <sys/un.h>
                     36: #include <sys/param.h>
                     37: #include <netinet/in.h>
                     38: #include <net/if.h>
                     39: #include <net/if_dl.h>
                     40: #include <arpa/inet.h>
                     41: #include <netinet/ip_fw.h>
                     42: #include <err.h>
                     43: #include <sysexits.h>
                     44: 
                     45: #include "ipfw2.h"
                     46: 
                     47: typedef union {
                     48:        struct sockaddr_storage ss;
                     49:        struct sockaddr         sa;
                     50:        struct sockaddr_un      sun;
                     51:        struct sockaddr_in      sin;
                     52:        struct sockaddr_in6     sin6;
                     53:        struct sockaddr_dl      sdl;
                     54: } sockaddr_t;
                     55: #define E_SOCKADDR_INIT        { .ss = { 0 } }
                     56: #define E_SOCKADDR_MAX MIN(sizeof(sockaddr_t), 0xff)
                     57: 
                     58: #define SYNC_SHIFT_ARG { ac--; av++; }
                     59: #define DEF_SYNC_PORT  20611
                     60: 
                     61: void
                     62: ipfw_config_sync(int ac, char **av)
                     63: {
                     64:        u_short port;
                     65:        sockaddr_t *sa = NULL;
                     66:        int len, j, i = 0;
                     67:        char *str, *buf, show[BUFSIZ], host[64];
                     68:        void *ptr;
                     69:        ipfw_obj_header *oh;
                     70:        struct ipfw_sync_cfg *cfg;
                     71: 
                     72:        SYNC_SHIFT_ARG;
                     73: 
                     74:        len = sizeof(*oh) + sizeof(*cfg);
                     75:        buf = malloc(len);
                     76:        if (!buf)
                     77:                errx(EX_OSERR, "malloc failed");
                     78:        else
                     79:                memset(buf, 0, len);
                     80:        oh = (ipfw_obj_header*) buf;
                     81:        cfg = (struct ipfw_sync_cfg*) (oh + 1);
                     82:        oh->ntlv.head.length = sizeof(oh->ntlv);
                     83: 
                     84:        if (ac && !strcmp(*av, "edge")) {
                     85:                SYNC_SHIFT_ARG;
                     86:                if (ac && !strcmp(*av, "port"))
                     87:                        SYNC_SHIFT_ARG;
                     88:                if (!ac)
                     89:                        errx(EX_DATAERR, "missing edge port\n");
                     90: 
                     91:                strlcpy(host, *av, sizeof host);
                     92:                if ((str = strchr(host, ','))) {
                     93:                        *str++ = 0;
                     94:                        port = strtol(str, NULL, 10);
                     95:                        if (!port)
                     96:                                errx(EX_DATAERR, "incorrect port number\n");
                     97:                } else {
                     98:                        port = strtol(host, NULL, 10);
                     99:                        if (!port)
                    100:                                errx(EX_DATAERR, "incorrect port number\n");
                    101:                        strlcpy(host, "0.0.0.0", sizeof host);
                    102:                }
                    103: 
                    104:                strlcpy(oh->ntlv.name, "edge", sizeof(oh->ntlv.name));
                    105:                strlcpy(cfg->name, "edge", sizeof(cfg->name));
                    106:                cfg->mode = CFG_SYNC_EDGE;
                    107:                cfg->addrs = 1;
                    108:                cfg->addr[0].addr.sa_family = strchr(host, ':') ? AF_INET6 : AF_INET;
                    109:                if (cfg->addr[0].addr.sa_family == AF_INET) {
                    110:                                cfg->addr[0].ip4.sin_len = sizeof cfg->addr[0].ip4;
                    111:                                cfg->addr[0].ip4.sin_port = htons(port);
                    112:                                if (inet_pton(AF_INET, host, &cfg->addr[0].ip4.sin_addr) != 1)
                    113:                                        errx(EX_DATAERR, "invalid edge IPv4 address\n");
                    114:                } else {
                    115:                                cfg->addr[0].ip6.sin6_len = sizeof cfg->addr[0].ip6;
                    116:                                cfg->addr[0].ip6.sin6_port = htons(port);
                    117:                                if (inet_pton(AF_INET6, host, &cfg->addr[0].ip6.sin6_addr) != 1)
                    118:                                        errx(EX_DATAERR, "invalid edge IPv6 address\n");
                    119:                }
1.2       misho     120:        } else if (ac && !strcmp(*av, "collector")) {
1.1       misho     121:                SYNC_SHIFT_ARG;
                    122:                if (!ac)
                    123:                        errx(EX_DATAERR, "missing destination(s) address[,port]\n");
                    124:                while (ac && *av) {
                    125:                        ptr = realloc(sa, E_SOCKADDR_MAX * (i + 1));
                    126:                        if (!ptr) {
                    127:                                free(sa);
                    128:                                errx(EX_DATAERR, "not enough memory for collectors\n");
                    129:                        } else
                    130:                                sa = ptr;
                    131:                        memset(sa + i, 0, E_SOCKADDR_MAX);
                    132:                        if ((str = strchr(*av, ','))) {
                    133:                                *str++ = 0;
                    134:                                port = strtol(str, NULL, 10);
                    135:                                if (!port) {
                    136:                                        free(sa);
                    137:                                        errx(EX_DATAERR, "incorrect port number\n");
                    138:                                }
                    139:                        } else
                    140:                                port = DEF_SYNC_PORT;
                    141:                        sa[i].sa.sa_family = strchr(*av, ':') ? AF_INET6 : AF_INET;
                    142:                        if (sa[i].sa.sa_family == AF_INET) {
                    143:                                sa[i].sa.sa_len = sizeof sa[i].sin;
                    144:                                sa[i].sin.sin_port = htons(port);
                    145:                                if (inet_pton(AF_INET, *av, &sa[i].sin.sin_addr) != 1) {
                    146:                                        free(sa);
                    147:                                        errx(EX_DATAERR, "invalid collector address\n");
                    148:                                }
                    149: 
                    150:                                cfg->addr[1 + i].ip4.sin_len = sizeof cfg->addr[1 + i].ip4;
                    151:                                cfg->addr[1 + i].ip4.sin_family = AF_INET;
                    152:                                cfg->addr[1 + i].ip4.sin_port = htons(port);
                    153:                                memcpy(&cfg->addr[1 + i].ip4.sin_addr, &sa[i].sin.sin_addr, 
                    154:                                                sizeof cfg->addr[1 + i].ip4.sin_addr);
                    155:                        } else {
                    156:                                sa[i].sa.sa_len = sizeof sa[i].sin6;
                    157:                                sa[i].sin6.sin6_port = htons(port);
                    158:                                if (inet_pton(AF_INET6, *av, &sa[i].sin6.sin6_addr) != 1) {
                    159:                                        free(sa);
                    160:                                        errx(EX_DATAERR, "invalid collector address\n");
                    161:                                }
                    162: 
                    163:                                cfg->addr[1 + i].ip6.sin6_len = sizeof cfg->addr[1 + i].ip6;
                    164:                                cfg->addr[1 + i].ip6.sin6_family = AF_INET6;
                    165:                                cfg->addr[1 + i].ip6.sin6_port = htons(port);
                    166:                                memcpy(&cfg->addr[1 + i].ip6.sin6_addr, &sa[i].sin6.sin6_addr, 
                    167:                                                sizeof cfg->addr[1 + i].ip6.sin6_addr);
                    168:                        }
                    169: 
                    170:                        i++;
                    171:                        SYNC_SHIFT_ARG;
                    172: 
                    173:                        if (i == 2)     /* maximum 2 collectors at same time */
                    174:                                break;
                    175:                }
                    176:                free(sa);
                    177: 
                    178:                strlcpy(oh->ntlv.name, "collector", sizeof(oh->ntlv.name));
                    179:                strlcpy(cfg->name, "collector", sizeof(cfg->name));
                    180:                cfg->mode = CFG_SYNC_COLLECTOR;
                    181:                cfg->addrs = MIN(i, 2);
                    182:        } else
                    183:                errx(EX_DATAERR, "missing type of service edge or collector\n");
                    184: 
                    185:        i = do_set3(IP_FW_SYNC_XCONFIG, &oh->opheader, len);
                    186:        if (i)
                    187:                err(1, "setsockopt(%s)", "IP_FW_SYNC_XCONFIG");
                    188: 
                    189:        if (!g_co.do_quiet) {
                    190:                /* After every modification, we show the resultant rule. */
                    191:                if (cfg->mode == CFG_SYNC_EDGE) {
                    192:                        printf("edge port %hu\n", ntohs(cfg->addr[0].ip4.sin_port));
                    193:                } else {
                    194:                        printf("collector");
                    195:                        for (j = 1; j < cfg->addrs + 1; j++) {
                    196:                                if (cfg->addr[j].addr.sa_family == AF_INET)
                    197:                                        printf(" %s,%hu", 
                    198:                                                        inet_ntop(AF_INET, &cfg->addr[j].ip4.sin_addr, 
                    199:                                                                show, sizeof show), 
                    200:                                                        ntohs(cfg->addr[j].ip4.sin_port));
                    201:                                else
                    202:                                        printf(" %s,%hu", 
                    203:                                                        inet_ntop(AF_INET6, &cfg->addr[j].ip6.sin6_addr, 
                    204:                                                                show, sizeof show), 
                    205:                                                        ntohs(cfg->addr[j].ip6.sin6_port));
                    206:                        }
                    207:                        printf("\n");
                    208:                }
                    209:        }
                    210: 
                    211:        free(buf);
                    212: }
                    213: 
                    214: void
1.3.2.1 ! misho     215: ipfw_list_sync(int ac, char **av)
        !           216: {
        !           217:        ipfw_obj_header *oh;
        !           218:        struct ipfw_sync_cfg *cfg;
        !           219:        size_t sz;
        !           220: 
        !           221:        SYNC_SHIFT_ARG;
        !           222: 
        !           223:        sz = sizeof *oh + sizeof *cfg;
        !           224:        while (42) {
        !           225:                if (!(oh = malloc(sz)))
        !           226:                        return;
        !           227:                else
        !           228:                        memset(oh, 0, sz);
        !           229:                cfg = (struct ipfw_sync_cfg*) (oh + 1);
        !           230:                oh->ntlv.head.length = sizeof(oh->ntlv);
        !           231:                strlcpy(oh->ntlv.name, ac ? *av : "", sizeof(oh->ntlv.name));
        !           232:                strlcpy(cfg->name, ac ? *av : "", sizeof(cfg->name));
        !           233: 
        !           234:                if (do_get3(IP_FW_SYNC_LIST, &oh->opheader, &sz)) {
        !           235:                        free(oh);
        !           236:                        if (errno == ENOMEM)
        !           237:                                continue;
        !           238:                        return;
        !           239:                }
        !           240: 
        !           241:                break;
        !           242:        }
        !           243: 
        !           244:        if (!ac || !strcmp(*av, "edge"))
        !           245:                printf("sync edge states %lu aliases %lu\n", 
        !           246:                                *(uint64_t*) (cfg->addr[0].ip6.sin6_addr.s6_addr + 8), 
        !           247:                                *(uint64_t*) (cfg->addr[1].ip6.sin6_addr.s6_addr + 8));
        !           248:        if (!ac || !strcmp(*av, "collector"))
        !           249:                printf("sync collector states %lu aliases %lu\n", 
        !           250:                                *(uint64_t*) cfg->addr[0].ip6.sin6_addr.s6_addr, 
        !           251:                                *(uint64_t*) cfg->addr[1].ip6.sin6_addr.s6_addr);
        !           252: }
        !           253: 
        !           254: void
1.1       misho     255: ipfw_show_sync(int ac, char **av)
                    256: {
                    257:        ipfw_obj_header *oh;
                    258:        struct ipfw_sync_cfg *cfg;
                    259:        size_t sz;
                    260:        char show[BUFSIZ];
                    261:        int i;
                    262: 
                    263:        SYNC_SHIFT_ARG;
                    264: 
                    265:        sz = sizeof *oh + sizeof *cfg;
                    266:        while (42) {
                    267:                if (!(oh = malloc(sz)))
                    268:                        return;
                    269:                else
                    270:                        memset(oh, 0, sz);
                    271:                cfg = (struct ipfw_sync_cfg*) (oh + 1);
                    272:                oh->ntlv.head.length = sizeof(oh->ntlv);
                    273:                strlcpy(oh->ntlv.name, ac ? *av : "", sizeof(oh->ntlv.name));
                    274:                strlcpy(cfg->name, ac ? *av : "", sizeof(cfg->name));
                    275: 
                    276:                if (do_get3(IP_FW_SYNC_XGETCONFIG, &oh->opheader, &sz)) {
                    277:                        free(oh);
                    278:                        if (errno == ENOMEM)
                    279:                                continue;
                    280:                        return;
                    281:                }
                    282: 
                    283:                break;
                    284:        }
                    285: 
                    286:        i = strtol(cfg->name, NULL, 10);
                    287:        if (!ac || !strcmp(*av, "edge"))
                    288:                printf("ipfw sync %s edge\n", (i & CFG_SYNC_EDGE) ? "start" : "stop");
                    289:        if (!ac || !strcmp(*av, "collector"))
                    290:                printf("ipfw sync %s collector\n", (i & CFG_SYNC_COLLECTOR) ? "start" : "stop");
                    291:        if ((!ac || !strcmp(*av, "edge")) && cfg->mode & CFG_SYNC_EDGE)
                    292:                printf("ipfw sync config edge port %hu\n", ntohs(cfg->addr[0].ip4.sin_port));
                    293:        if ((!ac || !strcmp(*av, "collector")) && cfg->mode & CFG_SYNC_COLLECTOR) {
                    294:                printf("ipfw sync config collector");
                    295:                for (i = 1; i < cfg->addrs + 1; i++) {
                    296:                        if (cfg->addr[i].addr.sa_family == AF_INET)
                    297:                                printf(" %s,%hu", 
                    298:                                                inet_ntop(AF_INET, &cfg->addr[i].ip4.sin_addr, 
                    299:                                                        show, sizeof show), 
                    300:                                                ntohs(cfg->addr[i].ip4.sin_port));
                    301:                        else
                    302:                                printf(" %s,%hu", 
                    303:                                                inet_ntop(AF_INET6, &cfg->addr[i].ip6.sin6_addr, 
                    304:                                                        show, sizeof show), 
                    305:                                                ntohs(cfg->addr[i].ip6.sin6_port));
                    306:                }
                    307:                printf("\n");
                    308:        }
                    309: }
                    310: 
                    311: void
                    312: ipfw_start_sync(int ac, char **av)
                    313: {
                    314:        int *n;
                    315:        ipfw_obj_header *oh;
                    316:        size_t sz;
                    317:        char *buf;
                    318: 
                    319:        SYNC_SHIFT_ARG;
                    320: 
                    321:        sz = sizeof *oh + sizeof(int);
                    322:        buf = malloc(sz);
                    323:        if (!buf)
                    324:                errx(EX_OSERR, "malloc failed");
                    325:        else
                    326:                memset(buf, 0, sz);
                    327:        oh = (ipfw_obj_header*) buf;
                    328:        n = (int*) (oh + 1);
                    329:        oh->ntlv.head.length = sizeof(oh->ntlv);
                    330: 
                    331:        if (!ac || !strcmp(*av, "edge")) {
                    332:                *n = CFG_SYNC_EDGE;
                    333:        }
                    334:        if (!ac || !strcmp(*av, "collector")) {
                    335:                *n |= CFG_SYNC_COLLECTOR;
                    336:        }
                    337: 
                    338:        if (do_set3(IP_FW_SYNC_START, &oh->opheader, sz))
                    339:                err(1, "setsockopt(%s)", "IP_FW_SYNC_START");
                    340: 
                    341:        if (!g_co.do_quiet) {
                    342:                if (!ac || !strcmp(*av, "edge"))
                    343:                        printf("ipfw sync start edge\n");
                    344:                if (!ac || !strcmp(*av, "collector"))
                    345:                        printf("ipfw sync start collector\n");
                    346:        }
                    347: }
                    348: 
                    349: void
                    350: ipfw_stop_sync(int ac, char **av)
                    351: {
                    352:        int *n;
                    353:        ipfw_obj_header *oh;
                    354:        size_t sz;
                    355:        char *buf;
                    356: 
                    357:        SYNC_SHIFT_ARG;
                    358: 
                    359:        sz = sizeof *oh + sizeof(int);
                    360:        buf = malloc(sz);
                    361:        if (!buf)
                    362:                errx(EX_OSERR, "malloc failed");
                    363:        else
                    364:                memset(buf, 0, sz);
                    365:        oh = (ipfw_obj_header*) buf;
                    366:        n = (int*) (oh + 1);
                    367:        oh->ntlv.head.length = sizeof(oh->ntlv);
                    368: 
                    369:        if (!ac || !strcmp(*av, "edge")) {
                    370:                *n = CFG_SYNC_EDGE;
                    371:        }
                    372:        if (!ac || !strcmp(*av, "collector")) {
                    373:                *n |= CFG_SYNC_COLLECTOR;
                    374:        }
                    375: 
                    376:        if (do_set3(IP_FW_SYNC_STOP, &oh->opheader, sz))
                    377:                err(1, "setsockopt(%s)", "IP_FW_SYNC_STOP");
                    378: 
                    379:        if (!g_co.do_quiet) {
                    380:                if (!ac || !strcmp(*av, "edge"))
                    381:                        printf("ipfw sync stop edge\n");
                    382:                if (!ac || !strcmp(*av, "collector"))
                    383:                        printf("ipfw sync stop collector\n");
                    384:        }
                    385: }
                    386: 
                    387: void
                    388: ipfw_flush_sync(int ac, char **av)
                    389: {
                    390:        int *n;
                    391:        ipfw_obj_header *oh;
                    392:        size_t sz;
                    393:        char *buf;
                    394: 
                    395:        SYNC_SHIFT_ARG;
                    396: 
                    397:        sz = sizeof *oh + sizeof(int);
                    398:        buf = malloc(sz);
                    399:        if (!buf)
                    400:                errx(EX_OSERR, "malloc failed");
                    401:        else
                    402:                memset(buf, 0, sz);
                    403:        oh = (ipfw_obj_header*) buf;
                    404:        n = (int*) (oh + 1);
                    405:        oh->ntlv.head.length = sizeof(oh->ntlv);
                    406: 
                    407:        if (!ac || !strcmp(*av, "edge")) {
                    408:                *n = CFG_SYNC_EDGE;
                    409:        }
                    410:        if (!ac || !strcmp(*av, "collector")) {
                    411:                *n |= CFG_SYNC_COLLECTOR;
                    412:        }
                    413: 
                    414:        if (do_set3(IP_FW_SYNC_DESTROY, &oh->opheader, sz))
                    415:                err(1, "setsockopt(%s)", "IP_FW_SYNC_DESTROY");
                    416: 
                    417:        if (!g_co.do_quiet) {
                    418:                if (!ac || !strcmp(*av, "edge"))
                    419:                        printf("ipfw sync flush edge\n");
                    420:                if (!ac || !strcmp(*av, "collector"))
                    421:                        printf("ipfw sync flush collector\n");
                    422:        }
                    423: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>