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

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

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