Annotation of fwsync/driver/fwsync.c, revision 1.2

1.1       misho       1: /*************************************************************************
                      2: * (C) 2022 CloudSigma AG - Sofia/Bulgaria
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: **************************************************************************/
                      5: #include "fwsync.h"
                      6: 
                      7: 
                      8: static intptr_t fwsync_wchan;
                      9: 
                     10: 
                     11: static void
                     12: fwsync_edge_proc(void *arg)
                     13: {
                     14:        int e, rcvflg;
                     15:        struct uio uio;
                     16:        struct mbuf *m = NULL;
                     17: 
                     18:        DTRACE();
                     19: 
                     20:        memset(&uio, 0, sizeof uio);
                     21:        uio.uio_resid = 1000000000;
                     22:        uio.uio_td = curthread;
                     23: 
                     24:        fws_ctx.config |= CTX_EDGE_ONLINE;
                     25:        while ((fws_cfg.cfg.on & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_EDGE_READY)) {
                     26:                if (m)
                     27:                        m_freem(m);
                     28:                m = NULL;
                     29:                rcvflg = MSG_DONTWAIT;
                     30:                e = soreceive(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], NULL, &uio, &m, NULL, &rcvflg);
                     31:                if (e) {
                     32:                        if (e != EAGAIN)
                     33:                                printf("error in edge handler #%d\n", e);
                     34:                        tsleep(&fwsync_wchan, 0, "edge_handler", hz);
                     35:                        continue;
                     36:                }
                     37: 
                     38:                printf("%u...-> %s\n", m->m_len, m->m_data);
                     39:        }
                     40:        fws_ctx.config &= ~CTX_EDGE_ONLINE;
                     41: 
                     42:        kproc_exit(0);
                     43: }
                     44: 
                     45: int
                     46: fwsync_cfg(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
                     47: {
                     48:        ipfw_obj_header *oh;
                     49:        struct ipfw_sync_cfg *ucfg;
                     50:        size_t sz;
                     51:        int e;
                     52: 
                     53:        DTRACE();
                     54: 
                     55:        sz = sizeof(*oh) + sizeof(*ucfg);
                     56:        /* Check minimum header size */
                     57:        if (sd->valsize < sz)
                     58:                return (EINVAL);
                     59: 
                     60:        oh = (ipfw_obj_header*) sd->kbuf;
                     61: 
                     62:        /* Basic length checks for TLVs */
                     63:        if (oh->ntlv.head.length != sizeof(oh->ntlv))
                     64:                return (EINVAL);
                     65: 
                     66:        ucfg = (struct ipfw_sync_cfg*) (oh + 1);
                     67: 
                     68:        /* Check if name is properly terminated */
                     69:        if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
                     70:                return (EINVAL);
                     71: 
                     72:        if (ucfg->mode == CFG_SYNC_EDGE && !fws_cfg.cfg.edge && !(fws_ctx.config & CTX_CFG_EDGE) && 
                     73:                        !strcmp(ucfg->name, "edge") && ucfg->addrs == 1) {
                     74:                fws_cfg.cfg.edge = 1;
                     75:                memcpy(&fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE], &ucfg->addr[CFG_SYNC_ADDR_EDGE], 
                     76:                                sizeof fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE]);
                     77:                fws_ctx.config |= CTX_CFG_EDGE;
                     78: 
                     79:                e = socreate((fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE].addr.sa_family == AF_INET) ? AF_INET : AF_INET6, 
                     80:                                &fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, curthread);
                     81:                if (e) {
                     82:                        printf("fwsync edge socreate failed #%d\n", e);
                     83:                        return e;
                     84:                }
                     85: 
                     86:                e = sobind(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], &fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE].addr, curthread);
                     87:                if (e) {
                     88:                        if (e != EADDRINUSE)
                     89:                                printf("fwsync edge sobind failed #%d\n", e);
                     90:                        else
                     91:                                printf("fwsync edge address in use!\n");
                     92:                        return e;
                     93:                } else
                     94:                        fws_ctx.config |= CTX_EDGE_READY;
                     95:        } else if (ucfg->mode == CFG_SYNC_COLLECTOR && !(fws_ctx.config & CTX_CFG_COLLECTOR_1) && 
                     96:                        !strcmp(ucfg->name, "collector") && ucfg->addrs > 0 && ucfg->addrs < 3) {
                     97:                fws_cfg.cfg.collector = 1;
                     98:                fws_cfg.cfg.addrs = ucfg->addrs;
                     99:                memcpy(&fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1], &ucfg->addr[CFG_SYNC_ADDR_COLLECTOR_1], 
                    100:                                sizeof fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1]);
                    101: 
                    102:                fws_ctx.config |= CTX_CFG_COLLECTOR_1;
                    103: 
                    104:                e = socreate((fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1].addr.sa_family == AF_INET) ? AF_INET : AF_INET6, 
                    105:                                &fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_1], SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, curthread);
                    106:                if (e) {
                    107:                        printf("fwsync collector %d socreate failed #%d\n", e, CFG_SYNC_ADDR_COLLECTOR_1);
                    108:                        return e;
                    109:                } else
                    110:                        fws_ctx.config |= CTX_COLLECTOR_1_READY;
                    111: 
                    112:                if (fws_cfg.cfg.addrs > 1) {
                    113:                        memcpy(&fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2], &ucfg->addr[CFG_SYNC_ADDR_COLLECTOR_2], 
                    114:                                        sizeof fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2]);
                    115: 
                    116:                        fws_ctx.config |= CTX_CFG_COLLECTOR_2;
                    117: 
                    118:                        e = socreate((fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2].addr.sa_family == AF_INET) ? AF_INET : AF_INET6, 
                    119:                                        &fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_2], SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, curthread);
                    120:                        if (e) {
                    121:                                printf("fwsync collector %d socreate failed #%d\n", e, CFG_SYNC_ADDR_COLLECTOR_2);
                    122:                                return e;
                    123:                        } else
                    124:                                fws_ctx.config |= CTX_COLLECTOR_2_READY;
                    125:                }
                    126:        } else
                    127:                return (EINVAL);
                    128: 
                    129:        return 0;
                    130: }
                    131: 
                    132: int
                    133: fwsync_destroy(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
                    134: {
                    135:        int *n;
                    136:        ipfw_obj_header *oh;
                    137:        size_t sz;
                    138: 
                    139:        DTRACE();
                    140: 
                    141:        sz = sizeof(*oh) + sizeof(int);
                    142:        /* Check minimum header size */
                    143:        if (sd->valsize < sz)
                    144:                return (EINVAL);
                    145: 
                    146:        oh = (ipfw_obj_header*) sd->kbuf;
                    147: 
                    148:        /* Basic length checks for TLVs */
                    149:        if (oh->ntlv.head.length != sizeof(oh->ntlv))
                    150:                return (EINVAL);
                    151: 
                    152:        n = (int*) (oh + 1);
                    153:        if (*n & CFG_SYNC_EDGE) {
                    154:                fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
                    155:                fws_cfg.cfg.edge = 0;
                    156:                fws_cfg.cfg.addrs = 0;
                    157:                memset(fws_cfg.cfg_addr, 0, sizeof fws_cfg.cfg_addr[0]);
                    158: 
                    159:                if (fws_ctx.config & CTX_EDGE_READY) {
                    160:                        soshutdown(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], SHUT_RD);
                    161:                        tsleep(&fwsync_wchan, 0, "fwsedge_kill", 2 * hz);
                    162:                        soclose(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE]);
                    163:                }
                    164:        }
                    165:        if (*n & CFG_SYNC_COLLECTOR) {
                    166:                if (fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE)) {
                    167:                        ipfw_unregister_state_hook();
                    168:                        ipfw_unregister_alias_hook();
                    169:                }
                    170: 
                    171:                fws_cfg.cfg.on &= ~CFG_SYNC_COLLECTOR;
                    172:                fws_cfg.cfg.collector = 0;
                    173:                fws_cfg.cfg.addrs = 0;
                    174:                memset(fws_cfg.cfg_addr + 1, 0, sizeof fws_cfg.cfg_addr[0] * 2);
                    175: 
                    176:                if (fws_ctx.config & CTX_COLLECTOR_2_READY)
                    177:                        soclose(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_2]);
                    178:                if (fws_ctx.config & CTX_COLLECTOR_1_READY)
                    179:                        soclose(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_1]);
                    180:        }
                    181: 
                    182:        fws_ctx.config ^= fws_ctx.config;
                    183: 
                    184:        return 0;
                    185: }
                    186: 
                    187: int
                    188: fwsync_get_cfg(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
                    189: {
                    190:        ipfw_obj_header *oh;
                    191:        struct ipfw_sync_cfg *ucfg;
                    192:        size_t sz;
                    193: 
                    194:        DTRACE();
                    195: 
                    196:        sz = sizeof(*oh) + sizeof(*ucfg);
                    197:        /* Check minimum header size */
                    198:        if (sd->valsize < sz)
                    199:                return (EINVAL);
                    200: 
                    201:        oh = (struct _ipfw_obj_header*) ipfw_get_sopt_header(sd, sz);
                    202: 
                    203:        /* Basic length checks for TLVs */
                    204:        if (oh->ntlv.head.length != sizeof(oh->ntlv))
                    205:                return (EINVAL);
                    206: 
                    207:        ucfg = (struct ipfw_sync_cfg*) (oh + 1);
                    208: 
                    209:        /* Check if name is properly terminated */
                    210:        if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
                    211:                return (EINVAL);
                    212: 
                    213:        snprintf(ucfg->name, sizeof ucfg->name, "%d", fws_cfg.cfg.on);
                    214:        ucfg->mode = 0;
                    215:        if (fws_cfg.cfg.edge)
                    216:                ucfg->mode |= CFG_SYNC_EDGE;
                    217:        if (fws_cfg.cfg.collector)
                    218:                ucfg->mode |= CFG_SYNC_COLLECTOR;
                    219:        ucfg->addrs = (fws_cfg.cfg.addrs != 1) ? fws_cfg.cfg.addrs : 1;
                    220:        memcpy(ucfg->addr, fws_cfg.cfg_addr, sizeof ucfg->addr);
                    221: 
                    222:        return 0;
                    223: }
                    224: 
                    225: int
                    226: fwsync_list(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
                    227: {
                    228:        DTRACE();
                    229: 
                    230:        return 0;
                    231: }
                    232: 
                    233: int
                    234: fwsync_start(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
                    235: {
                    236:        int *n, e;
                    237:        ipfw_obj_header *oh;
                    238:        size_t sz;
                    239: 
                    240:        DTRACE();
                    241: 
                    242:        sz = sizeof(*oh) + sizeof(int);
                    243:        /* Check minimum header size */
                    244:        if (sd->valsize < sz)
                    245:                return (EINVAL);
                    246: 
                    247:        oh = (ipfw_obj_header*) sd->kbuf;
                    248: 
                    249:        /* Basic length checks for TLVs */
                    250:        if (oh->ntlv.head.length != sizeof(oh->ntlv))
                    251:                return (EINVAL);
                    252: 
                    253:        n = (int*) (oh + 1);
                    254: 
                    255:        if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_EDGE_READY)) {
                    256:                fws_cfg.cfg.on |= CFG_SYNC_EDGE;
                    257: 
                    258:                e = kproc_create(fwsync_edge_proc, NULL, &fws_ctx.procz[CFG_SYNC_ADDR_EDGE], 
                    259:                                0, 0, "fwsync_edge");
                    260:                if (e) {
                    261:                        printf("fwsync fwsync_edge failed #%d\n", e);
                    262:                        return e;
                    263:                }
                    264:        }
                    265: 
                    266:        if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_1_READY)) {
                    267:                fws_cfg.cfg.on |= CFG_SYNC_COLLECTOR;
                    268: 
                    269:                if (!(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
                    270:                        ipfw_register_state_hook(fwsync_state_handler);
                    271:                        ipfw_register_alias_hook(fwsync_alias_handler);
                    272:                }
                    273: 
                    274:                fws_ctx.config |= CTX_COLLECTOR_1_ONLINE;
                    275:        }
                    276: 
                    277:        if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_2_READY)) {
                    278:                fws_cfg.cfg.on |= CFG_SYNC_COLLECTOR;
                    279: 
                    280:                if (!(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
                    281:                        ipfw_register_state_hook(fwsync_state_handler);
                    282:                        ipfw_register_alias_hook(fwsync_alias_handler);
                    283:                }
                    284: 
                    285:                fws_ctx.config |= CTX_COLLECTOR_2_ONLINE;
                    286:        }
                    287: 
                    288:        return 0;
                    289: }
                    290: 
                    291: int
                    292: fwsync_stop(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
                    293: {
                    294:        int *n;
                    295:        ipfw_obj_header *oh;
                    296:        size_t sz;
                    297: 
                    298:        DTRACE();
                    299: 
                    300:        sz = sizeof(*oh) + sizeof(int);
                    301:        /* Check minimum header size */
                    302:        if (sd->valsize < sz)
                    303:                return (EINVAL);
                    304: 
                    305:        oh = (ipfw_obj_header*) sd->kbuf;
                    306: 
                    307:        /* Basic length checks for TLVs */
                    308:        if (oh->ntlv.head.length != sizeof(oh->ntlv))
                    309:                return (EINVAL);
                    310: 
                    311:        n = (int*) (oh + 1);
                    312: 
                    313:        if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_CFG_EDGE))
                    314:                fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
                    315: 
                    316:        if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_2_ONLINE))
                    317:                fws_ctx.config &= ~CTX_COLLECTOR_2_ONLINE;
                    318:        if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_1_ONLINE))
                    319:                fws_ctx.config &= ~CTX_COLLECTOR_1_ONLINE;
                    320: 
                    321:        if ((*n & CFG_SYNC_COLLECTOR) && 
                    322:                        !(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
                    323:                fws_cfg.cfg.on &= ~CFG_SYNC_COLLECTOR;
                    324: 
                    325:                ipfw_unregister_state_hook();
                    326:                ipfw_unregister_alias_hook();
                    327:        }
                    328: 
                    329:        return 0;
                    330: }

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