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

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
                    215: ipfw_show_sync(int ac, char **av)
                    216: {
                    217:        ipfw_obj_header *oh;
                    218:        struct ipfw_sync_cfg *cfg;
                    219:        size_t sz;
                    220:        char show[BUFSIZ];
                    221:        int i;
                    222: 
                    223:        SYNC_SHIFT_ARG;
                    224: 
                    225:        sz = sizeof *oh + sizeof *cfg;
                    226:        while (42) {
                    227:                if (!(oh = malloc(sz)))
                    228:                        return;
                    229:                else
                    230:                        memset(oh, 0, sz);
                    231:                cfg = (struct ipfw_sync_cfg*) (oh + 1);
                    232:                oh->ntlv.head.length = sizeof(oh->ntlv);
                    233:                strlcpy(oh->ntlv.name, ac ? *av : "", sizeof(oh->ntlv.name));
                    234:                strlcpy(cfg->name, ac ? *av : "", sizeof(cfg->name));
                    235: 
                    236:                if (do_get3(IP_FW_SYNC_XGETCONFIG, &oh->opheader, &sz)) {
                    237:                        free(oh);
                    238:                        if (errno == ENOMEM)
                    239:                                continue;
                    240:                        return;
                    241:                }
                    242: 
                    243:                break;
                    244:        }
                    245: 
                    246:        i = strtol(cfg->name, NULL, 10);
                    247:        if (!ac || !strcmp(*av, "edge"))
                    248:                printf("ipfw sync %s edge\n", (i & CFG_SYNC_EDGE) ? "start" : "stop");
                    249:        if (!ac || !strcmp(*av, "collector"))
                    250:                printf("ipfw sync %s collector\n", (i & CFG_SYNC_COLLECTOR) ? "start" : "stop");
                    251:        if ((!ac || !strcmp(*av, "edge")) && cfg->mode & CFG_SYNC_EDGE)
                    252:                printf("ipfw sync config edge port %hu\n", ntohs(cfg->addr[0].ip4.sin_port));
                    253:        if ((!ac || !strcmp(*av, "collector")) && cfg->mode & CFG_SYNC_COLLECTOR) {
                    254:                printf("ipfw sync config collector");
                    255:                for (i = 1; i < cfg->addrs + 1; i++) {
                    256:                        if (cfg->addr[i].addr.sa_family == AF_INET)
                    257:                                printf(" %s,%hu", 
                    258:                                                inet_ntop(AF_INET, &cfg->addr[i].ip4.sin_addr, 
                    259:                                                        show, sizeof show), 
                    260:                                                ntohs(cfg->addr[i].ip4.sin_port));
                    261:                        else
                    262:                                printf(" %s,%hu", 
                    263:                                                inet_ntop(AF_INET6, &cfg->addr[i].ip6.sin6_addr, 
                    264:                                                        show, sizeof show), 
                    265:                                                ntohs(cfg->addr[i].ip6.sin6_port));
                    266:                }
                    267:                printf("\n");
                    268:        }
                    269: }
                    270: 
                    271: void
                    272: ipfw_start_sync(int ac, char **av)
                    273: {
                    274:        int *n;
                    275:        ipfw_obj_header *oh;
                    276:        size_t sz;
                    277:        char *buf;
                    278: 
                    279:        SYNC_SHIFT_ARG;
                    280: 
                    281:        sz = sizeof *oh + sizeof(int);
                    282:        buf = malloc(sz);
                    283:        if (!buf)
                    284:                errx(EX_OSERR, "malloc failed");
                    285:        else
                    286:                memset(buf, 0, sz);
                    287:        oh = (ipfw_obj_header*) buf;
                    288:        n = (int*) (oh + 1);
                    289:        oh->ntlv.head.length = sizeof(oh->ntlv);
                    290: 
                    291:        if (!ac || !strcmp(*av, "edge")) {
                    292:                *n = CFG_SYNC_EDGE;
                    293:        }
                    294:        if (!ac || !strcmp(*av, "collector")) {
                    295:                *n |= CFG_SYNC_COLLECTOR;
                    296:        }
                    297: 
                    298:        if (do_set3(IP_FW_SYNC_START, &oh->opheader, sz))
                    299:                err(1, "setsockopt(%s)", "IP_FW_SYNC_START");
                    300: 
                    301:        if (!g_co.do_quiet) {
                    302:                if (!ac || !strcmp(*av, "edge"))
                    303:                        printf("ipfw sync start edge\n");
                    304:                if (!ac || !strcmp(*av, "collector"))
                    305:                        printf("ipfw sync start collector\n");
                    306:        }
                    307: }
                    308: 
                    309: void
                    310: ipfw_stop_sync(int ac, char **av)
                    311: {
                    312:        int *n;
                    313:        ipfw_obj_header *oh;
                    314:        size_t sz;
                    315:        char *buf;
                    316: 
                    317:        SYNC_SHIFT_ARG;
                    318: 
                    319:        sz = sizeof *oh + sizeof(int);
                    320:        buf = malloc(sz);
                    321:        if (!buf)
                    322:                errx(EX_OSERR, "malloc failed");
                    323:        else
                    324:                memset(buf, 0, sz);
                    325:        oh = (ipfw_obj_header*) buf;
                    326:        n = (int*) (oh + 1);
                    327:        oh->ntlv.head.length = sizeof(oh->ntlv);
                    328: 
                    329:        if (!ac || !strcmp(*av, "edge")) {
                    330:                *n = CFG_SYNC_EDGE;
                    331:        }
                    332:        if (!ac || !strcmp(*av, "collector")) {
                    333:                *n |= CFG_SYNC_COLLECTOR;
                    334:        }
                    335: 
                    336:        if (do_set3(IP_FW_SYNC_STOP, &oh->opheader, sz))
                    337:                err(1, "setsockopt(%s)", "IP_FW_SYNC_STOP");
                    338: 
                    339:        if (!g_co.do_quiet) {
                    340:                if (!ac || !strcmp(*av, "edge"))
                    341:                        printf("ipfw sync stop edge\n");
                    342:                if (!ac || !strcmp(*av, "collector"))
                    343:                        printf("ipfw sync stop collector\n");
                    344:        }
                    345: }
                    346: 
                    347: void
                    348: ipfw_flush_sync(int ac, char **av)
                    349: {
                    350:        int *n;
                    351:        ipfw_obj_header *oh;
                    352:        size_t sz;
                    353:        char *buf;
                    354: 
                    355:        SYNC_SHIFT_ARG;
                    356: 
                    357:        sz = sizeof *oh + sizeof(int);
                    358:        buf = malloc(sz);
                    359:        if (!buf)
                    360:                errx(EX_OSERR, "malloc failed");
                    361:        else
                    362:                memset(buf, 0, sz);
                    363:        oh = (ipfw_obj_header*) buf;
                    364:        n = (int*) (oh + 1);
                    365:        oh->ntlv.head.length = sizeof(oh->ntlv);
                    366: 
                    367:        if (!ac || !strcmp(*av, "edge")) {
                    368:                *n = CFG_SYNC_EDGE;
                    369:        }
                    370:        if (!ac || !strcmp(*av, "collector")) {
                    371:                *n |= CFG_SYNC_COLLECTOR;
                    372:        }
                    373: 
                    374:        if (do_set3(IP_FW_SYNC_DESTROY, &oh->opheader, sz))
                    375:                err(1, "setsockopt(%s)", "IP_FW_SYNC_DESTROY");
                    376: 
                    377:        if (!g_co.do_quiet) {
                    378:                if (!ac || !strcmp(*av, "edge"))
                    379:                        printf("ipfw sync flush edge\n");
                    380:                if (!ac || !strcmp(*av, "collector"))
                    381:                        printf("ipfw sync flush collector\n");
                    382:        }
                    383: }

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