1: /*************************************************************************
2: * (C) 2022 CloudSigma AG - Sofia/Bulgaria
3: * by Michael Pounov <misho@elwix.org>
4: **************************************************************************/
5: #include "fwsync.h"
6:
7:
8: static int
9: fwsync_add_state_4(struct ipfw_flow_id *fid, u_int ruleid, u_short rulenum,
10: u_short kidx, u_char cmdtype)
11: {
12: struct ip_fw *rule = NULL;
13:
14: DTRACE();
15:
16: return ipfw_dyn_install_sync_state(fid, rule, ruleid, rulenum, kidx, cmdtype);
17: }
18:
19: static int
20: fwsync_add_state_6(struct ipfw_flow_id *fid, u_int ruleid, u_short rulenum,
21: u_short kidx, u_char cmdtype)
22: {
23: DTRACE();
24:
25: return 0;
26: }
27:
28: int
29: fwsync_add_state(const struct fws_proto *pkt)
30: {
31: struct fws_sndpkt *p;
32:
33: DTRACE();
34:
35: if (!pkt || pkt->fws_addrtype == 1)
36: return 0; /* skip ethernet packet */
37:
38: p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO);
39: if (!p) {
40: return ENOMEM;
41: } else
42: memcpy(&p->sp_proto, pkt, sizeof(struct fws_proto));
43:
44: mtx_lock(&fws_mtx_u);
45: TAILQ_INSERT_TAIL(&fwsync_updpkt, p, sp_next);
46: mtx_unlock(&fws_mtx_u);
47: return 0;
48: }
49:
50:
51: int
52: fwsync_add_alias(const struct fws_proto *pkt)
53: {
54: DTRACE();
55:
56: return 0;
57: }
58:
59:
60: void
61: fwsync_sndpkt_handler(void *context, int pending)
62: {
63: struct fws_sndpkt *pkt;
64: struct mbuf *m2, *m;
65: int e;
66:
67: DTRACE();
68:
69: do {
70: mtx_lock(&fws_mtx_c);
71: pkt = TAILQ_FIRST(&fwsync_sndpkt);
72: if (pkt)
73: TAILQ_REMOVE(&fwsync_sndpkt, pkt, sp_next);
74: mtx_unlock(&fws_mtx_c);
75:
76: if (!pkt) /* sending queue is empty */
77: break;
78:
79: if (!(fws_cfg.cfg.on & CFG_SYNC_COLLECTOR)) {
80: free(pkt, M_FWSYNC);
81: continue;
82: }
83:
84: m = m_gethdr(M_NOWAIT, MT_DATA);
85: if (!m) {
86: free(pkt, M_FWSYNC);
87: continue;
88: }
89:
90: memcpy(mtod(m, struct fws_proto *), &pkt->sp_proto, sizeof pkt->sp_proto);
91: m->m_len = sizeof pkt->sp_proto;
92: m_fixhdr(m);
93:
94: if ((fws_ctx.config & (CTX_COLLECTOR_2_ONLINE | CTX_COLLECTOR_2_READY)) ==
95: (CTX_COLLECTOR_2_ONLINE | CTX_COLLECTOR_2_READY)) {
96: m2 = m_copypacket(m, M_NOWAIT);
97: if (!m2) {
98: printf("error in copypacket for second collector\n");
99: goto out;
100: }
101: e = sosend(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_2],
102: &fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2].addr, NULL,
103: m2, NULL, 0, curthread);
104: if (e && e != EAGAIN)
105: printf("error in collector %d handler #%d\n", CFG_SYNC_ADDR_COLLECTOR_2, e);
106: }
107:
108: if ((fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_1_READY)) ==
109: (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_1_READY)) {
110: m2 = m_copypacket(m, M_NOWAIT);
111: if (!m2) {
112: printf("error in copypacket for first collector\n");
113: goto out;
114: }
115: e = sosend(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_1],
116: &fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1].addr, NULL,
117: m2, NULL, 0, curthread);
118: if (e && e != EAGAIN)
119: printf("error in collector %d handler #%d\n", CFG_SYNC_ADDR_COLLECTOR_1, e);
120: }
121: out:
122: m_freem(m);
123: free(pkt, M_FWSYNC);
124: } while (--pending);
125: }
126:
127: int
128: fwsync_state_handler(const void *arg, const void *extdata)
129: {
130: const struct ipfw_flow_id *pkt = arg;
131: const struct ipfw_dyn_hook_extdata *edata = extdata;
132: struct fws_proto *spkt;
133: struct fws_sndpkt *p;
134:
135: DTRACE();
136:
137: if (!pkt || pkt->addr_type == 1)
138: return 0; /* skip ethernet packet */
139:
140: mtx_lock(&fws_mtx_c);
141:
142: p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO);
143: if (!p) {
144: mtx_unlock(&fws_mtx_c);
145: return 0;
146: } else
147: spkt = &p->sp_proto;
148:
149: spkt->fws_version = FWS_PKTVER_STATE;
150: spkt->fws_fib = pkt->fib;
151: spkt->fws_cmdtype = edata->cmdtype;
152: spkt->fws_kidx = edata->kidx;
153: spkt->fws_ruleid = edata->ruleid;
154: spkt->fws_rulenum = edata->rulenum;
155: spkt->fws_proto = pkt->proto;
156: spkt->fws_addrtype = pkt->addr_type;
157: spkt->fws_sport = pkt->src_port;
158: spkt->fws_dport = pkt->dst_port;
159:
160: switch (pkt->addr_type) {
161: case 4:
162: spkt->fws_saddr.s_addr = pkt->src_ip;
163: spkt->fws_daddr.s_addr = pkt->dst_ip;
164: spkt->fws_scopeid = 0;
165: break;
166: case 6:
167: memcpy(&spkt->fws_saddr6, &pkt->src_ip6, sizeof spkt->fws_saddr6);
168: memcpy(&spkt->fws_daddr6, &pkt->dst_ip6, sizeof spkt->fws_daddr6);
169: spkt->fws_scopeid = pkt->flow_id6;
170: break;
171: default:
172: free(p, M_FWSYNC);
173: mtx_unlock(&fws_mtx_c);
174: return EINVAL;
175: }
176:
177: TAILQ_INSERT_TAIL(&fwsync_sndpkt, p, sp_next);
178:
179: mtx_unlock(&fws_mtx_c);
180:
181: taskqueue_enqueue(fws_tq, &fws_sndpkt_task);
182: return 0;
183: }
184:
185: int
186: fwsync_alias_handler(const void *arg, const void *extdata)
187: {
188: const struct alias_link *lnk = arg;
189: struct fws_proto *spkt;
190: struct fws_sndpkt *p;
191:
192: DTRACE();
193:
194: if (!lnk || lnk->link_type >= IPPROTO_MAX)
195: return 0;
196:
197: mtx_lock(&fws_mtx_c);
198:
199: p = malloc(sizeof(struct fws_sndpkt), M_FWSYNC, M_NOWAIT | M_ZERO);
200: if (!p) {
201: mtx_unlock(&fws_mtx_c);
202: return 0;
203: } else
204: spkt = &p->sp_proto;
205:
206: spkt->fws_version = FWS_PKTVER_ALIAS;
207: spkt->fws_proto = lnk->link_type;
208: spkt->fws_addrtype = 4;
209: spkt->fws_sport = lnk->src_port;
210: spkt->fws_dport = lnk->dst_port;
211: spkt->fws_aport = lnk->alias_port;
212: spkt->fws_pport = lnk->proxy_port;
213: spkt->fws_saddr.s_addr = lnk->src_addr.s_addr;
214: spkt->fws_daddr.s_addr = lnk->dst_addr.s_addr;
215: spkt->fws_aaddr.s_addr = lnk->alias_addr.s_addr;
216: spkt->fws_paddr.s_addr = lnk->proxy_addr.s_addr;
217:
218: TAILQ_INSERT_TAIL(&fwsync_sndpkt, p, sp_next);
219:
220: mtx_unlock(&fws_mtx_c);
221:
222: taskqueue_enqueue(fws_tq, &fws_sndpkt_task);
223: return 0;
224: }
225:
226: int
227: fwsync_state_sync(const void *arg, const void *extdata)
228: {
229: struct fws_sndpkt *pkt;
230: struct ipfw_flow_id fid;
231:
232: DTRACE();
233:
234: mtx_lock(&fws_mtx_u);
235: pkt = TAILQ_FIRST(&fwsync_updpkt);
236: if (pkt)
237: TAILQ_REMOVE(&fwsync_updpkt, pkt, sp_next);
238: mtx_unlock(&fws_mtx_u);
239:
240: if (!pkt) /* update queue is empty */
241: return 0;
242:
243: if (!(fws_cfg.cfg.on & CFG_SYNC_EDGE)) {
244: free(pkt, M_FWSYNC);
245: return EAGAIN;
246: }
247:
248: memset(&fid, 0, sizeof fid);
249: fid.fib = pkt->sp_proto.fws_fib;
250: fid.proto = pkt->sp_proto.fws_proto;
251: fid.addr_type = pkt->sp_proto.fws_addrtype;
252: fid.src_port = pkt->sp_proto.fws_sport;
253: fid.dst_port = pkt->sp_proto.fws_dport;
254: switch (pkt->sp_proto.fws_addrtype) {
255: case 4:
256: fid.src_ip = pkt->sp_proto.fws_saddr.s_addr;
257: fid.dst_ip = pkt->sp_proto.fws_daddr.s_addr;
258: break;
259: case 6:
260: memcpy(&fid.src_ip6, &pkt->sp_proto.fws_saddr6, sizeof fid.src_ip6);
261: memcpy(&fid.dst_ip6, &pkt->sp_proto.fws_daddr6, sizeof fid.dst_ip6);
262: fid.flow_id6 = pkt->sp_proto.fws_scopeid;
263: break;
264: default:
265: free(pkt, M_FWSYNC);
266: return EINVAL;
267: }
268:
269: if (pkt->sp_proto.fws_addrtype == 4)
270: fwsync_add_state_4(&fid, pkt->sp_proto.fws_ruleid, pkt->sp_proto.fws_rulenum,
271: pkt->sp_proto.fws_kidx, pkt->sp_proto.fws_cmdtype);
272: else if (pkt->sp_proto.fws_addrtype == 6)
273: fwsync_add_state_6(&fid, pkt->sp_proto.fws_ruleid, pkt->sp_proto.fws_rulenum,
274: pkt->sp_proto.fws_kidx, pkt->sp_proto.fws_cmdtype);
275:
276: free(pkt, M_FWSYNC);
277: return 0;
278: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>