| version 1.4, 2022/07/11 15:59:42 | version 1.19, 2022/08/26 14:47:36 | 
| Line 1 | Line 1 | 
| /************************************************************************* | /*- | 
| * (C) 2022 CloudSigma AG - Sofia/Bulgaria | * SPDX-License-Identifier: BSD-2-Clause-FreeBSD | 
| *  by Michael Pounov <misho@elwix.org> | * | 
| **************************************************************************/ | * Copyright (c) 2022 Michael Pounov <misho@elwix.org>, CloudSigma AG | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 
|  | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
|  | * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
|  | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
|  | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
|  | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
|  | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
|  | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
|  | * SUCH DAMAGE. | 
|  | */ | 
 | #include "fwsync.h" | #include "fwsync.h" | 
 |  |  | 
 |  |  | 
 |  | int | 
 |  | fwsync_add_state(const struct fws_proto *pkt) | 
 |  | { | 
 |  | struct fws_sndpkt *p; | 
 |  |  | 
 |  | DTRACE(); | 
 |  |  | 
 |  | if (!pkt || pkt->fws_addrtype == 1) | 
 |  | return 0;       /* skip ethernet packet */ | 
 |  |  | 
 |  | p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO); | 
 |  | if (!p) { | 
 |  | return ENOMEM; | 
 |  | } else | 
 |  | memcpy(&p->sp_proto, pkt, sizeof(struct fws_proto)); | 
 |  |  | 
 |  | mtx_lock(&fws_mtx_u); | 
 |  | TAILQ_INSERT_TAIL(&fwsync_updpkt, p, sp_next); | 
 |  | mtx_unlock(&fws_mtx_u); | 
 |  | return 0; | 
 |  | } | 
 |  |  | 
 |  |  | 
 |  | int | 
 |  | fwsync_add_alias(const struct fws_proto *pkt) | 
 |  | { | 
 |  | struct fws_sndpkt *p; | 
 |  |  | 
 |  | DTRACE(); | 
 |  |  | 
 |  | if (!pkt || pkt->fws_addrtype == 1 || pkt->fws_addrtype == 6) | 
 |  | return 0;       /* skip packet */ | 
 |  |  | 
 |  | p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO); | 
 |  | if (!p) { | 
 |  | return ENOMEM; | 
 |  | } else | 
 |  | memcpy(&p->sp_proto, pkt, sizeof(struct fws_proto)); | 
 |  |  | 
 |  | mtx_lock(&fws_mtx_n); | 
 |  | TAILQ_INSERT_TAIL(&fwsync_natpkt, p, sp_next); | 
 |  | mtx_unlock(&fws_mtx_n); | 
 |  | return 0; | 
 |  | } | 
 |  |  | 
 |  |  | 
 | void | void | 
 | fwsync_sndpkt_handler(void *context, int pending) | fwsync_sndpkt_handler(void *context, int pending) | 
 | { | { | 
| Line 14  fwsync_sndpkt_handler(void *context, int pending) | Line 82  fwsync_sndpkt_handler(void *context, int pending) | 
 |  |  | 
 | DTRACE(); | DTRACE(); | 
 |  |  | 
 | printf("pending=%d\n", pending); |  | 
 |  |  | 
 | do { | do { | 
 | mtx_lock(&fws_mtx_c); | mtx_lock(&fws_mtx_c); | 
 | pkt = TAILQ_FIRST(&fwsync_sndpkt); | pkt = TAILQ_FIRST(&fwsync_sndpkt); | 
| Line 75  out: | Line 141  out: | 
 | } | } | 
 |  |  | 
 | int | int | 
| fwsync_state_handler(const void *arg) | fwsync_state_handler(const void *arg, const void *extdata) | 
 | { | { | 
 | const struct ipfw_flow_id *pkt = arg; | const struct ipfw_flow_id *pkt = arg; | 
 |  | const struct ipfw_dyn_hook_extdata *edata = extdata; | 
 | struct fws_proto *spkt; | struct fws_proto *spkt; | 
 | struct fws_sndpkt *p; | struct fws_sndpkt *p; | 
 |  |  | 
| Line 88  fwsync_state_handler(const void *arg) | Line 155  fwsync_state_handler(const void *arg) | 
 |  |  | 
 | mtx_lock(&fws_mtx_c); | mtx_lock(&fws_mtx_c); | 
 |  |  | 
| p = malloc(sizeof(struct fws_proto), M_FWSYNC, M_NOWAIT | M_ZERO); | p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO); | 
 | if (!p) { | if (!p) { | 
 | mtx_unlock(&fws_mtx_c); | mtx_unlock(&fws_mtx_c); | 
 | return 0; | return 0; | 
| Line 97  fwsync_state_handler(const void *arg) | Line 164  fwsync_state_handler(const void *arg) | 
 |  |  | 
 | spkt->fws_version = FWS_PKTVER_STATE; | spkt->fws_version = FWS_PKTVER_STATE; | 
 | spkt->fws_fib = pkt->fib; | spkt->fws_fib = pkt->fib; | 
 |  | spkt->fws_cmdtype = edata->cmdtype; | 
 |  | spkt->fws_kidx = edata->kidx; | 
 |  | spkt->fws_ruleid = edata->ruleid; | 
 |  | spkt->fws_rulenum = edata->rulenum; | 
 | spkt->fws_proto = pkt->proto; | spkt->fws_proto = pkt->proto; | 
 | spkt->fws_addrtype = pkt->addr_type; | spkt->fws_addrtype = pkt->addr_type; | 
 | spkt->fws_sport = pkt->src_port; | spkt->fws_sport = pkt->src_port; | 
| Line 121  fwsync_state_handler(const void *arg) | Line 192  fwsync_state_handler(const void *arg) | 
 |  |  | 
 | TAILQ_INSERT_TAIL(&fwsync_sndpkt, p, sp_next); | TAILQ_INSERT_TAIL(&fwsync_sndpkt, p, sp_next); | 
 |  |  | 
 |  | fws_acct.states[0]++; | 
 |  |  | 
 | mtx_unlock(&fws_mtx_c); | mtx_unlock(&fws_mtx_c); | 
 |  |  | 
 | taskqueue_enqueue(fws_tq, &fws_sndpkt_task); | taskqueue_enqueue(fws_tq, &fws_sndpkt_task); | 
| Line 128  fwsync_state_handler(const void *arg) | Line 201  fwsync_state_handler(const void *arg) | 
 | } | } | 
 |  |  | 
 | int | int | 
| fwsync_alias_handler(const void *arg) | fwsync_alias_handler(const void *arg, const void *extdata) | 
 | { | { | 
 | const struct alias_link *lnk = arg; | const struct alias_link *lnk = arg; | 
 | struct fws_proto *spkt; | struct fws_proto *spkt; | 
| Line 141  fwsync_alias_handler(const void *arg) | Line 214  fwsync_alias_handler(const void *arg) | 
 |  |  | 
 | mtx_lock(&fws_mtx_c); | mtx_lock(&fws_mtx_c); | 
 |  |  | 
| p = malloc(sizeof(struct fws_proto), M_FWSYNC, M_NOWAIT | M_ZERO); | p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO); | 
 | if (!p) { | if (!p) { | 
 | mtx_unlock(&fws_mtx_c); | mtx_unlock(&fws_mtx_c); | 
 | return 0; | return 0; | 
| Line 162  fwsync_alias_handler(const void *arg) | Line 235  fwsync_alias_handler(const void *arg) | 
 |  |  | 
 | TAILQ_INSERT_TAIL(&fwsync_sndpkt, p, sp_next); | TAILQ_INSERT_TAIL(&fwsync_sndpkt, p, sp_next); | 
 |  |  | 
 |  | fws_acct.aliases[0]++; | 
 |  |  | 
 | mtx_unlock(&fws_mtx_c); | mtx_unlock(&fws_mtx_c); | 
 |  |  | 
 | taskqueue_enqueue(fws_tq, &fws_sndpkt_task); | taskqueue_enqueue(fws_tq, &fws_sndpkt_task); | 
 |  | return 0; | 
 |  | } | 
 |  |  | 
 |  | int | 
 |  | fwsync_state_sync(const void *arg, const void *extdata) | 
 |  | { | 
 |  | struct fws_sndpkt *pkt; | 
 |  | struct ipfw_flow_id fid; | 
 |  | struct ip_fw *rule; | 
 |  | int f_pos; | 
 |  | struct ip_fw_chain *chain = &V_layer3_chain; | 
 |  |  | 
 |  | DTRACE(); | 
 |  |  | 
 |  | mtx_lock(&fws_mtx_u); | 
 |  | pkt = TAILQ_FIRST(&fwsync_updpkt); | 
 |  | if (pkt) { | 
 |  | TAILQ_REMOVE(&fwsync_updpkt, pkt, sp_next); | 
 |  | fws_acct.states[1]++; | 
 |  | } | 
 |  | mtx_unlock(&fws_mtx_u); | 
 |  |  | 
 |  | if (!pkt)       /* update queue is empty */ | 
 |  | return 0; | 
 |  |  | 
 |  | if (!(fws_cfg.cfg.on & CFG_SYNC_EDGE)) { | 
 |  | free(pkt, M_FWSYNC); | 
 |  | return EAGAIN; | 
 |  | } | 
 |  |  | 
 |  | memset(&fid, 0, sizeof fid); | 
 |  | fid.fib = pkt->sp_proto.fws_fib; | 
 |  | fid.proto = pkt->sp_proto.fws_proto; | 
 |  | fid.addr_type = pkt->sp_proto.fws_addrtype; | 
 |  | fid.src_port = pkt->sp_proto.fws_sport; | 
 |  | fid.dst_port = pkt->sp_proto.fws_dport; | 
 |  | switch (pkt->sp_proto.fws_addrtype) { | 
 |  | case 4: | 
 |  | fid.src_ip = pkt->sp_proto.fws_saddr.s_addr; | 
 |  | fid.dst_ip = pkt->sp_proto.fws_daddr.s_addr; | 
 |  | break; | 
 |  | case 6: | 
 |  | memcpy(&fid.src_ip6, &pkt->sp_proto.fws_saddr6, sizeof fid.src_ip6); | 
 |  | memcpy(&fid.dst_ip6, &pkt->sp_proto.fws_daddr6, sizeof fid.dst_ip6); | 
 |  | fid.flow_id6 = pkt->sp_proto.fws_scopeid; | 
 |  | break; | 
 |  | default: | 
 |  | free(pkt, M_FWSYNC); | 
 |  | return EINVAL; | 
 |  | } | 
 |  |  | 
 |  | f_pos = ipfw_find_rule(chain, pkt->sp_proto.fws_ruleid, pkt->sp_proto.fws_rulenum); | 
 |  | rule = chain->map[f_pos]; | 
 |  | ipfw_dyn_install_sync_state(&fid, rule, | 
 |  | pkt->sp_proto.fws_ruleid, pkt->sp_proto.fws_rulenum, | 
 |  | pkt->sp_proto.fws_kidx, pkt->sp_proto.fws_cmdtype); | 
 |  |  | 
 |  | free(pkt, M_FWSYNC); | 
 |  | return 0; | 
 |  | } | 
 |  |  | 
 |  | int | 
 |  | fwsync_alias_sync(const void *arg, const void *extdata) | 
 |  | { | 
 |  | struct fws_sndpkt *pkt; | 
 |  | const struct cfg_nat *t = arg; | 
 |  |  | 
 |  | DTRACE(); | 
 |  |  | 
 |  | mtx_lock(&fws_mtx_n); | 
 |  | while ((pkt = TAILQ_FIRST(&fwsync_natpkt))) { | 
 |  | TAILQ_REMOVE(&fwsync_natpkt, pkt, sp_next); | 
 |  | fws_acct.aliases[1]++; | 
 |  |  | 
 |  | if (!(fws_cfg.cfg.on & CFG_SYNC_EDGE)) { | 
 |  | free(pkt, M_FWSYNC); | 
 |  | continue; | 
 |  | } | 
 |  |  | 
 |  | if (t) { | 
 |  | LIBALIAS_LOCK(t->lib); | 
 |  | AddLink(t->lib, pkt->sp_proto.fws_saddr, | 
 |  | pkt->sp_proto.fws_daddr, | 
 |  | pkt->sp_proto.fws_aaddr, | 
 |  | pkt->sp_proto.fws_sport, | 
 |  | pkt->sp_proto.fws_dport, | 
 |  | pkt->sp_proto.fws_aport, | 
 |  | pkt->sp_proto.fws_linktype | LINK_SYNC_MASK); | 
 |  | LIBALIAS_UNLOCK(t->lib); | 
 |  | } | 
 |  |  | 
 |  | free(pkt, M_FWSYNC); | 
 |  | } | 
 |  | mtx_unlock(&fws_mtx_n); | 
 |  |  | 
 | return 0; | return 0; | 
 | } | } |