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

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

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