xref: /dflybsd-src/sys/net/ipfw3_basic/ip_fw3_sync.c (revision fb1dde20d596d2938b7c0e3b7c31acf4a7cb4d0a)
14408d548SBill Yuan /*
24408d548SBill Yuan  * Copyright (c) 2016 - 2018 The DragonFly Project.  All rights reserved.
34408d548SBill Yuan  *
44408d548SBill Yuan  * This code is derived from software contributed to The DragonFly Project
54408d548SBill Yuan  * by Bill Yuan <bycn82@dragonflybsd.org>
64408d548SBill Yuan  *
74408d548SBill Yuan  * Redistribution and use in source and binary forms, with or without
84408d548SBill Yuan  * modification, are permitted provided that the following conditions
94408d548SBill Yuan  * are met:
104408d548SBill Yuan  *
114408d548SBill Yuan  * 1. Redistributions of source code must retain the above copyright
124408d548SBill Yuan  *    notice, this list of conditions and the following disclaimer.
134408d548SBill Yuan  * 2. Redistributions in binary form must reproduce the above copyright
144408d548SBill Yuan  *    notice, this list of conditions and the following disclaimer in
154408d548SBill Yuan  *    the documentation and/or other materials provided with the
164408d548SBill Yuan  *    distribution.
174408d548SBill Yuan  * 3. Neither the name of The DragonFly Project nor the names of its
184408d548SBill Yuan  *    contributors may be used to endorse or promote products derived
194408d548SBill Yuan  *    from this software without specific, prior written permission.
204408d548SBill Yuan  *
214408d548SBill Yuan  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
224408d548SBill Yuan  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
234408d548SBill Yuan  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
244408d548SBill Yuan  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
254408d548SBill Yuan  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
264408d548SBill Yuan  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
274408d548SBill Yuan  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
284408d548SBill Yuan  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
294408d548SBill Yuan  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
304408d548SBill Yuan  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
314408d548SBill Yuan  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
324408d548SBill Yuan  * SUCH DAMAGE.
334408d548SBill Yuan  *
344408d548SBill Yuan  */
354408d548SBill Yuan 
364408d548SBill Yuan #include <sys/types.h>
374408d548SBill Yuan #include <sys/param.h>
384408d548SBill Yuan #include <sys/systm.h>
394408d548SBill Yuan #include <sys/malloc.h>
404408d548SBill Yuan #include <sys/mbuf.h>
414408d548SBill Yuan #include <sys/kernel.h>
424408d548SBill Yuan #include <sys/proc.h>
434408d548SBill Yuan #include <sys/socket.h>
444408d548SBill Yuan #include <sys/socketvar.h>
454408d548SBill Yuan #include <sys/socketvar2.h>
464408d548SBill Yuan #include <sys/socketops.h>
474408d548SBill Yuan #include <sys/sysctl.h>
484408d548SBill Yuan #include <sys/syslog.h>
494408d548SBill Yuan #include <sys/ucred.h>
504408d548SBill Yuan #include <sys/in_cksum.h>
514408d548SBill Yuan #include <sys/lock.h>
524408d548SBill Yuan #include <sys/kthread.h>
534408d548SBill Yuan 
54*bff82488SAaron LI #include <net/if.h>
55*bff82488SAaron LI #include <net/route.h>
56*bff82488SAaron LI #include <net/pfil.h>
57*bff82488SAaron LI #include <net/netmsg2.h>
58*bff82488SAaron LI #include <net/ethernet.h>
59*bff82488SAaron LI 
604408d548SBill Yuan #include <netinet/in.h>
614408d548SBill Yuan #include <netinet/in_systm.h>
624408d548SBill Yuan #include <netinet/in_var.h>
634408d548SBill Yuan #include <netinet/in_pcb.h>
644408d548SBill Yuan #include <netinet/ip.h>
654408d548SBill Yuan #include <netinet/ip_var.h>
664408d548SBill Yuan #include <netinet/ip_icmp.h>
674408d548SBill Yuan #include <netinet/tcp.h>
684408d548SBill Yuan #include <netinet/tcp_timer.h>
694408d548SBill Yuan #include <netinet/tcp_var.h>
704408d548SBill Yuan #include <netinet/tcpip.h>
714408d548SBill Yuan #include <netinet/udp.h>
724408d548SBill Yuan #include <netinet/udp_var.h>
734408d548SBill Yuan #include <netinet/ip_divert.h>
744408d548SBill Yuan #include <netinet/if_ether.h>
754408d548SBill Yuan 
764408d548SBill Yuan #include <net/ipfw3/ip_fw.h>
774408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_sync.h>
784408d548SBill Yuan 
794408d548SBill Yuan #define LEN_IN_ADDR		sizeof(struct in_addr)
804408d548SBill Yuan 
814408d548SBill Yuan MALLOC_DEFINE(M_IPFW3_SYNC, "IPFW3_SYNC", "mem for ipfw3sync");
824408d548SBill Yuan 
834408d548SBill Yuan extern struct ipfw3_context		*fw3_ctx[MAXCPU];
844408d548SBill Yuan extern struct ipfw3_sync_context	fw3_sync_ctx;
854408d548SBill Yuan ipfw_sync_send_state_t			*ipfw_sync_send_state_prt = NULL;
864408d548SBill Yuan ipfw_sync_install_state_t		*ipfw_sync_install_state_prt = NULL;
874408d548SBill Yuan 
884408d548SBill Yuan 
894408d548SBill Yuan 
904408d548SBill Yuan void
ip_fw3_sync_install_state(struct cmd_send_state * cmd)914408d548SBill Yuan ip_fw3_sync_install_state(struct cmd_send_state *cmd)
924408d548SBill Yuan {
934408d548SBill Yuan 	/* TODO */
944408d548SBill Yuan }
954408d548SBill Yuan 
964408d548SBill Yuan /*
974408d548SBill Yuan  * ipfw3sync show config
984408d548SBill Yuan  */
994408d548SBill Yuan int
ip_fw3_ctl_sync_show_conf(struct sockopt * sopt)1004408d548SBill Yuan ip_fw3_ctl_sync_show_conf(struct sockopt *sopt)
1014408d548SBill Yuan {
1024408d548SBill Yuan 	struct ipfw3_ioc_sync_context *tmp_sync_ctx;
1034408d548SBill Yuan 	int size;
1044408d548SBill Yuan 
1054408d548SBill Yuan 	size = 3 * sizeof(int) + fw3_sync_ctx.count * LEN_SYNC_EDGE;
1064408d548SBill Yuan 	if (sopt->sopt_valsize < size) {
1074408d548SBill Yuan 		/* sopt_val is not big enough */
1084408d548SBill Yuan 		bzero(sopt->sopt_val, sopt->sopt_valsize);
1094408d548SBill Yuan 		return 0;
1104408d548SBill Yuan 	}
1114408d548SBill Yuan 	tmp_sync_ctx = (struct ipfw3_ioc_sync_context *)sopt->sopt_val;
1124408d548SBill Yuan 	tmp_sync_ctx->edge_port = fw3_sync_ctx.edge_port;
1134408d548SBill Yuan 	tmp_sync_ctx->hw_same = fw3_sync_ctx.hw_same;
1144408d548SBill Yuan 	tmp_sync_ctx->count = fw3_sync_ctx.count;
1154408d548SBill Yuan 	bcopy(fw3_sync_ctx.edges, tmp_sync_ctx->edges,
1164408d548SBill Yuan 			fw3_sync_ctx.count * LEN_SYNC_EDGE);
1174408d548SBill Yuan 	sopt->sopt_valsize = size;
1184408d548SBill Yuan 	return 0;
1194408d548SBill Yuan }
1204408d548SBill Yuan 
1214408d548SBill Yuan /*
1224408d548SBill Yuan  * ipfw3sync show status
1234408d548SBill Yuan  */
1244408d548SBill Yuan int
ip_fw3_ctl_sync_show_status(struct sockopt * sopt)1254408d548SBill Yuan ip_fw3_ctl_sync_show_status(struct sockopt *sopt)
1264408d548SBill Yuan {
1274408d548SBill Yuan 	int *running;
1284408d548SBill Yuan 	running = (int *)sopt->sopt_val;
1294408d548SBill Yuan 	*running = fw3_sync_ctx.running;
1304408d548SBill Yuan 	sopt->sopt_valsize = sizeof(int);
1314408d548SBill Yuan 	return 0;
1324408d548SBill Yuan }
1334408d548SBill Yuan /*
1344408d548SBill Yuan  * ipfw3sync config centre
1354408d548SBill Yuan  */
1364408d548SBill Yuan int
ip_fw3_ctl_sync_centre_conf(struct sockopt * sopt)1374408d548SBill Yuan ip_fw3_ctl_sync_centre_conf(struct sockopt *sopt)
1384408d548SBill Yuan {
1394408d548SBill Yuan 	struct ipfw3_ioc_sync_centre *ioc_centre;
1404408d548SBill Yuan 	int size;
1414408d548SBill Yuan 
1424408d548SBill Yuan 	ioc_centre = sopt->sopt_val;
1434408d548SBill Yuan 	size = ioc_centre->count * LEN_SYNC_EDGE;
1444408d548SBill Yuan 	if (fw3_sync_ctx.count == 0) {
1454408d548SBill Yuan 		fw3_sync_ctx.edges = kmalloc(size, M_IPFW3_SYNC, M_NOWAIT | M_ZERO);
1464408d548SBill Yuan 	} else {
1474408d548SBill Yuan 		fw3_sync_ctx.edges = krealloc(fw3_sync_ctx.edges,
1484408d548SBill Yuan 				size, M_TEMP, M_WAITOK);
1494408d548SBill Yuan 	}
1504408d548SBill Yuan 	fw3_sync_ctx.count = ioc_centre->count;
1514408d548SBill Yuan 	bcopy(ioc_centre->edges, fw3_sync_ctx.edges,
1524408d548SBill Yuan 			ioc_centre->count * LEN_SYNC_EDGE);
1534408d548SBill Yuan 	return 0;
1544408d548SBill Yuan }
1554408d548SBill Yuan 
1564408d548SBill Yuan /*
1574408d548SBill Yuan  * ipfw3sync config edge
1584408d548SBill Yuan  */
1594408d548SBill Yuan int
ip_fw3_ctl_sync_edge_conf(struct sockopt * sopt)1604408d548SBill Yuan ip_fw3_ctl_sync_edge_conf(struct sockopt *sopt)
1614408d548SBill Yuan {
1624408d548SBill Yuan 	struct ipfw3_ioc_sync_edge *ioc_edge;
1634408d548SBill Yuan 	struct thread *td;
1644408d548SBill Yuan 	size_t size;
1654408d548SBill Yuan 	int error;
1664408d548SBill Yuan 
1674408d548SBill Yuan 	size = sopt->sopt_valsize;
1684408d548SBill Yuan 	ioc_edge = sopt->sopt_val;
1694408d548SBill Yuan 	if (size != sizeof(struct ipfw3_ioc_sync_edge)) {
1704408d548SBill Yuan 		return EINVAL;
1714408d548SBill Yuan 	}
1724408d548SBill Yuan 	fw3_sync_ctx.edge_port = ioc_edge->port;
1734408d548SBill Yuan 	fw3_sync_ctx.hw_same = ioc_edge->hw_same;
1744408d548SBill Yuan 
1754408d548SBill Yuan 	td = curthread->td_proc ? curthread : &thread0;
1764408d548SBill Yuan 	error = socreate(AF_INET, &fw3_sync_ctx.edge_sock,
1774408d548SBill Yuan 			SOCK_DGRAM, IPPROTO_UDP, td);
1784408d548SBill Yuan 	if (error) {
1794408d548SBill Yuan 		kprintf("ipfw3sync edge socreate failed: %d\n", error);
1804408d548SBill Yuan 		return (error);
1814408d548SBill Yuan 	}
1824408d548SBill Yuan 	return 0;
1834408d548SBill Yuan }
1844408d548SBill Yuan 
1854408d548SBill Yuan void
ip_fw3_sync_edge_socket_handler(void * dummy)1864408d548SBill Yuan ip_fw3_sync_edge_socket_handler(void *dummy)
1874408d548SBill Yuan {
1884408d548SBill Yuan 	struct socket *so;
1894408d548SBill Yuan 	struct sockbuf sio;
1904408d548SBill Yuan 	struct sockaddr_in sin;
1914408d548SBill Yuan 	struct mbuf *m;
1924408d548SBill Yuan 	struct sockaddr *sa;
1934408d548SBill Yuan 	int error, flags, *type;
1944408d548SBill Yuan 
1954408d548SBill Yuan 	so = fw3_sync_ctx.edge_sock;
1964408d548SBill Yuan 	flags = MSG_FBLOCKING;
1974408d548SBill Yuan 
1984408d548SBill Yuan 	bzero(&sin, sizeof(struct sockaddr_in));
1994408d548SBill Yuan 	sin.sin_family = AF_INET;
2004408d548SBill Yuan 	sin.sin_port = htons(fw3_sync_ctx.edge_port);
2014408d548SBill Yuan 	sin.sin_len = LEN_IN_ADDR;
2024408d548SBill Yuan 	sa = (struct sockaddr *)&sin;
2034408d548SBill Yuan 	while (fw3_sync_ctx.running & 1) {
2044408d548SBill Yuan 		sbinit(&sio, 1000000000);
2054408d548SBill Yuan 		error = so_pru_soreceive(so, NULL, NULL, &sio, NULL, &flags);
2064408d548SBill Yuan 		if (error)
2074408d548SBill Yuan 			break;
2084408d548SBill Yuan 		m = sio.sb_mb;
2094408d548SBill Yuan 		type = (int *)m->m_data;
2104408d548SBill Yuan 		if (*type == SYNC_TYPE_SEND_TEST) {
2114408d548SBill Yuan 			struct cmd_send_test *cmd;
2124408d548SBill Yuan 			cmd = (struct cmd_send_test *)m->m_data;
2134408d548SBill Yuan 			kprintf("test received %d\n", cmd->num);
2144408d548SBill Yuan 		} else if (*type == SYNC_TYPE_SEND_STATE) {
2154408d548SBill Yuan 			struct cmd_send_state *cmd;
2164408d548SBill Yuan 			cmd = (struct cmd_send_state *)m->m_data;
2174408d548SBill Yuan 			if (ipfw_sync_install_state_prt != NULL) {
2184408d548SBill Yuan 				(*ipfw_sync_install_state_prt)(cmd);
2194408d548SBill Yuan 			}
2204408d548SBill Yuan 		} else if (*type == SYNC_TYPE_SEND_NAT) {
2214408d548SBill Yuan 			/* TODO sync NAT records */
2224408d548SBill Yuan 			kprintf("nat received\n");
2234408d548SBill Yuan 		} else {
2244408d548SBill Yuan 			kprintf("Error ignore\n");
2254408d548SBill Yuan 		}
2264408d548SBill Yuan 	}
2274408d548SBill Yuan 	soshutdown(fw3_sync_ctx.edge_sock, SHUT_RD);
2284408d548SBill Yuan 	sofree(fw3_sync_ctx.edge_sock);
2294408d548SBill Yuan 	kthread_exit();
2304408d548SBill Yuan }
2314408d548SBill Yuan 
2324408d548SBill Yuan int
ip_fw3_ctl_sync_edge_start(struct sockopt * sopt)2334408d548SBill Yuan ip_fw3_ctl_sync_edge_start(struct sockopt *sopt)
2344408d548SBill Yuan {
2354408d548SBill Yuan 	struct sockaddr_in sin;
2364408d548SBill Yuan 	struct thread *td;
2374408d548SBill Yuan 	int error;
2384408d548SBill Yuan 
2394408d548SBill Yuan 	if (fw3_sync_ctx.running & 1) {
2404408d548SBill Yuan 		return 0;
2414408d548SBill Yuan 	}
2424408d548SBill Yuan 	td = curthread->td_proc ? curthread : &thread0;
2434408d548SBill Yuan 	bzero(&sin, sizeof(struct sockaddr_in));
2444408d548SBill Yuan 	sin.sin_family = AF_INET;
2454408d548SBill Yuan 	sin.sin_len = sizeof(struct sockaddr_in);
2464408d548SBill Yuan 	sin.sin_port = htons(fw3_sync_ctx.edge_port);
2474408d548SBill Yuan 	sin.sin_addr.s_addr = INADDR_ANY;
2484408d548SBill Yuan 	error = sobind(fw3_sync_ctx.edge_sock, (struct sockaddr *)&sin, td);
2494408d548SBill Yuan 	if (error) {
2504408d548SBill Yuan 		if (error != EADDRINUSE) {
2514408d548SBill Yuan 			kprintf("ipfw3sync edge sobind failed: %d\n", error);
2524408d548SBill Yuan 		} else {
2534408d548SBill Yuan 			kprintf("ipfw3sync edge address in use: %d\n", error);
2544408d548SBill Yuan 		}
2554408d548SBill Yuan 		return (error);
2564408d548SBill Yuan 	}
2574408d548SBill Yuan 
2584408d548SBill Yuan 	fw3_sync_ctx.running |= 1;
2594408d548SBill Yuan 	soreference(fw3_sync_ctx.edge_sock);
2604408d548SBill Yuan 	error = kthread_create(ip_fw3_sync_edge_socket_handler, NULL,
2614408d548SBill Yuan 			&fw3_sync_ctx.edge_td, "sync_edge_thread");
2624408d548SBill Yuan 	if (error) {
2634408d548SBill Yuan 		panic("ip_fw3_sync_edge_socket_handler:error %d",error);
2644408d548SBill Yuan 	}
2654408d548SBill Yuan 	return 0;
2664408d548SBill Yuan }
2674408d548SBill Yuan 
2684408d548SBill Yuan int
ip_fw3_ctl_sync_centre_start(struct sockopt * sopt)2694408d548SBill Yuan ip_fw3_ctl_sync_centre_start(struct sockopt *sopt)
2704408d548SBill Yuan {
2714408d548SBill Yuan 	struct sockaddr_in sin;
2724408d548SBill Yuan 	struct thread *td;
2734408d548SBill Yuan 	struct ipfw3_sync_edge *edge;
2744408d548SBill Yuan 	int error, i;
2754408d548SBill Yuan 
2764408d548SBill Yuan 	fw3_sync_ctx.running |= 2;
2774408d548SBill Yuan 	td = curthread->td_proc ? curthread : &thread0;
2784408d548SBill Yuan 
2794408d548SBill Yuan 	for (i = 0; i < fw3_sync_ctx.count; i++) {
2804408d548SBill Yuan 		error = socreate(AF_INET, &fw3_sync_ctx.centre_socks[i],
2814408d548SBill Yuan 				SOCK_DGRAM, IPPROTO_UDP, td);
2824408d548SBill Yuan 		if (error) {
2834408d548SBill Yuan 			kprintf("ipfw3sync centre socreate failed: %d\n",
2844408d548SBill Yuan 					error);
2854408d548SBill Yuan 			return error;
2864408d548SBill Yuan 		}
2874408d548SBill Yuan 		edge = fw3_sync_ctx.edges;
2884408d548SBill Yuan 
2894408d548SBill Yuan 		bzero(&sin, sizeof(struct sockaddr_in));
2904408d548SBill Yuan 		sin.sin_family = AF_INET;
2914408d548SBill Yuan 		sin.sin_port = htons(edge->port);
2924408d548SBill Yuan 		sin.sin_addr.s_addr = edge->addr;
2934408d548SBill Yuan 		sin.sin_len = sizeof(struct sockaddr_in);
2944408d548SBill Yuan 		error = soconnect(fw3_sync_ctx.centre_socks[i],
2954408d548SBill Yuan 				(struct sockaddr *)&sin, td, TRUE);
2964408d548SBill Yuan 		if (error) {
2974408d548SBill Yuan 			kprintf("ipfw3sync: centre soconnect failed: %d\n",
2984408d548SBill Yuan 					error);
2994408d548SBill Yuan 			return error;
3004408d548SBill Yuan 		}
3014408d548SBill Yuan 	}
3024408d548SBill Yuan 
3034408d548SBill Yuan 	return 0;
3044408d548SBill Yuan }
3054408d548SBill Yuan 
3064408d548SBill Yuan int
ip_fw3_ctl_sync_edge_test(struct sockopt * sopt)3074408d548SBill Yuan ip_fw3_ctl_sync_edge_test(struct sockopt *sopt)
3084408d548SBill Yuan {
3094408d548SBill Yuan 	return 0;
3104408d548SBill Yuan }
3114408d548SBill Yuan 
3124408d548SBill Yuan int
ip_fw3_ctl_sync_centre_test(struct sockopt * sopt)3134408d548SBill Yuan ip_fw3_ctl_sync_centre_test(struct sockopt *sopt)
3144408d548SBill Yuan {
3154408d548SBill Yuan 	struct cmd_send_test cmd;
3164408d548SBill Yuan 	struct mbuf *m;
3174408d548SBill Yuan 	struct thread *td;
3184408d548SBill Yuan 	int error, i, len, nsize, *num;
3194408d548SBill Yuan 
3204408d548SBill Yuan 	if (sopt->sopt_valsize != sizeof(int)) {
3214408d548SBill Yuan 		kprintf("ipfw3sync: invalid centre test parameter\n");
3224408d548SBill Yuan 		return -1;
3234408d548SBill Yuan 	}
3244408d548SBill Yuan 	if ((fw3_sync_ctx.running & 2) == 0) {
3254408d548SBill Yuan 		kprintf("ipfw3sync: centre not running\n");
3264408d548SBill Yuan 		return -1;
3274408d548SBill Yuan 	}
3284408d548SBill Yuan 	num = sopt->sopt_val;
3294408d548SBill Yuan 	len = sizeof(struct cmd_send_test);
3304408d548SBill Yuan 	m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize);
3314408d548SBill Yuan 	cmd.type = 0;
3324408d548SBill Yuan 	cmd.num = *num;
3334408d548SBill Yuan 	memcpy(m->m_data, &cmd, len);
3344408d548SBill Yuan 
3354408d548SBill Yuan 	m->m_len = len;
3364408d548SBill Yuan 	m->m_pkthdr.len = len;
3374408d548SBill Yuan 
3384408d548SBill Yuan 	td = curthread->td_proc ? curthread : &thread0;
3394408d548SBill Yuan 	for (i = 0; i < fw3_sync_ctx.count; i++) {
3404408d548SBill Yuan 		error = so_pru_sosend(fw3_sync_ctx.centre_socks[i],
3414408d548SBill Yuan 				NULL, NULL, m, NULL, 0 ,td);
3424408d548SBill Yuan 		if (error) {
3434408d548SBill Yuan 			kprintf("ipfw3sync: centre sosend failed: %d\n", error);
3444408d548SBill Yuan 			return -1;
3454408d548SBill Yuan 		}
3464408d548SBill Yuan 	}
3474408d548SBill Yuan 	m_free(m);
3484408d548SBill Yuan 	return 0;
3494408d548SBill Yuan }
3504408d548SBill Yuan int
ip_fw3_ctl_sync_edge_stop(struct sockopt * sopt)3514408d548SBill Yuan ip_fw3_ctl_sync_edge_stop(struct sockopt *sopt)
3524408d548SBill Yuan {
3534408d548SBill Yuan 	if (fw3_sync_ctx.running & 1) {
3544408d548SBill Yuan 		fw3_sync_ctx.running &= 2;
3554408d548SBill Yuan 		soclose(fw3_sync_ctx.edge_sock, 0);
3564408d548SBill Yuan 	}
3574408d548SBill Yuan 	return 0;
3584408d548SBill Yuan }
3594408d548SBill Yuan 
3604408d548SBill Yuan int
ip_fw3_ctl_sync_centre_stop(struct sockopt * sopt)3614408d548SBill Yuan ip_fw3_ctl_sync_centre_stop(struct sockopt *sopt)
3624408d548SBill Yuan {
3634408d548SBill Yuan 	int i;
3644408d548SBill Yuan 
3654408d548SBill Yuan 	if (fw3_sync_ctx.running & 2) {
3664408d548SBill Yuan 		fw3_sync_ctx.running &= 1;
3674408d548SBill Yuan 		for (i = 0; i < fw3_sync_ctx.count; i++) {
3684408d548SBill Yuan 			soclose(fw3_sync_ctx.centre_socks[i], 0);
3694408d548SBill Yuan 		}
3704408d548SBill Yuan 	}
3714408d548SBill Yuan 	return 0;
3724408d548SBill Yuan }
3734408d548SBill Yuan 
3744408d548SBill Yuan int
ip_fw3_ctl_sync_edge_clear(struct sockopt * sopt)3754408d548SBill Yuan ip_fw3_ctl_sync_edge_clear(struct sockopt *sopt)
3764408d548SBill Yuan {
3774408d548SBill Yuan 	return 0;
3784408d548SBill Yuan }
3794408d548SBill Yuan 
3804408d548SBill Yuan int
ip_fw3_ctl_sync_centre_clear(struct sockopt * sopt)3814408d548SBill Yuan ip_fw3_ctl_sync_centre_clear(struct sockopt *sopt)
3824408d548SBill Yuan {
3834408d548SBill Yuan 	return 0;
3844408d548SBill Yuan }
3854408d548SBill Yuan 
3864408d548SBill Yuan /*
3874408d548SBill Yuan  * sockopt handler
3884408d548SBill Yuan  */
3894408d548SBill Yuan int
ip_fw3_ctl_sync_sockopt(struct sockopt * sopt)3904408d548SBill Yuan ip_fw3_ctl_sync_sockopt(struct sockopt *sopt)
3914408d548SBill Yuan {
3924408d548SBill Yuan 	int error = 0;
3934408d548SBill Yuan 	switch (sopt->sopt_name) {
3944408d548SBill Yuan 		case IP_FW_SYNC_EDGE_CONF:
3954408d548SBill Yuan 			error = ip_fw3_ctl_sync_edge_conf(sopt);
3964408d548SBill Yuan 			break;
3974408d548SBill Yuan 		case IP_FW_SYNC_CENTRE_CONF:
3984408d548SBill Yuan 			error = ip_fw3_ctl_sync_centre_conf(sopt);
3994408d548SBill Yuan 			break;
4004408d548SBill Yuan 		case IP_FW_SYNC_SHOW_CONF:
4014408d548SBill Yuan 			error = ip_fw3_ctl_sync_show_conf(sopt);
4024408d548SBill Yuan 			break;
4034408d548SBill Yuan 		case IP_FW_SYNC_SHOW_STATUS:
4044408d548SBill Yuan 			error = ip_fw3_ctl_sync_show_status(sopt);
4054408d548SBill Yuan 			break;
4064408d548SBill Yuan 		case IP_FW_SYNC_EDGE_START:
4074408d548SBill Yuan 			error = ip_fw3_ctl_sync_edge_start(sopt);
4084408d548SBill Yuan 			break;
4094408d548SBill Yuan 		case IP_FW_SYNC_CENTRE_START:
4104408d548SBill Yuan 			error = ip_fw3_ctl_sync_centre_start(sopt);
4114408d548SBill Yuan 			break;
4124408d548SBill Yuan 		case IP_FW_SYNC_EDGE_STOP:
4134408d548SBill Yuan 			error = ip_fw3_ctl_sync_edge_stop(sopt);
4144408d548SBill Yuan 			break;
4154408d548SBill Yuan 		case IP_FW_SYNC_CENTRE_STOP:
4164408d548SBill Yuan 			error = ip_fw3_ctl_sync_centre_stop(sopt);
4174408d548SBill Yuan 			break;
4184408d548SBill Yuan 		case IP_FW_SYNC_EDGE_CLEAR:
4194408d548SBill Yuan 			error = ip_fw3_ctl_sync_edge_clear(sopt);
4204408d548SBill Yuan 			break;
4214408d548SBill Yuan 		case IP_FW_SYNC_CENTRE_CLEAR:
4224408d548SBill Yuan 			error = ip_fw3_ctl_sync_centre_clear(sopt);
4234408d548SBill Yuan 			break;
4244408d548SBill Yuan 		case IP_FW_SYNC_EDGE_TEST:
4254408d548SBill Yuan 			error = ip_fw3_ctl_sync_edge_test(sopt);
4264408d548SBill Yuan 			break;
4274408d548SBill Yuan 		case IP_FW_SYNC_CENTRE_TEST:
4284408d548SBill Yuan 			error = ip_fw3_ctl_sync_centre_test(sopt);
4294408d548SBill Yuan 			break;
4304408d548SBill Yuan 		default:
4314408d548SBill Yuan 			kprintf("ipfw3 sync invalid socket option %d\n",
4324408d548SBill Yuan 					sopt->sopt_name);
4334408d548SBill Yuan 	}
4344408d548SBill Yuan 	return error;
4354408d548SBill Yuan }
4364408d548SBill Yuan 
4374408d548SBill Yuan void
ip_fw3_sync_send_state(struct ipfw3_state * state,int cpu,int hash)4384408d548SBill Yuan ip_fw3_sync_send_state(struct ipfw3_state *state, int cpu, int hash)
4394408d548SBill Yuan {
4404408d548SBill Yuan 	struct mbuf *m;
4414408d548SBill Yuan 	struct thread *td;
4424408d548SBill Yuan 	int error, i, len, nsize;
4434408d548SBill Yuan 	struct cmd_send_state cmd;
4444408d548SBill Yuan 
4454408d548SBill Yuan 	len = sizeof(struct cmd_send_state);
4464408d548SBill Yuan 	m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize);
4474408d548SBill Yuan 
4484408d548SBill Yuan 	cmd.type = 1;
4494408d548SBill Yuan 	cmd.cpu = cpu;
4504408d548SBill Yuan 	cmd.hash = hash;
4514408d548SBill Yuan 
4524408d548SBill Yuan 	memcpy(m->m_data, &cmd, len);
4534408d548SBill Yuan 
4544408d548SBill Yuan 	m->m_len = len;
4554408d548SBill Yuan 	m->m_pkthdr.len = len;
4564408d548SBill Yuan 
4574408d548SBill Yuan 	td = curthread->td_proc ? curthread : &thread0;
4584408d548SBill Yuan 	for (i = 0; i < fw3_sync_ctx.count; i++) {
4594408d548SBill Yuan 		error = so_pru_sosend(fw3_sync_ctx.centre_socks[i],
4604408d548SBill Yuan 				NULL, NULL, m, NULL, 0 ,td);
4614408d548SBill Yuan 		if (error) {
4624408d548SBill Yuan 			kprintf("ipfw3sync: centre sosend failed: %d\n", error);
4634408d548SBill Yuan 			return;
4644408d548SBill Yuan 		}
4654408d548SBill Yuan 	}
4664408d548SBill Yuan 	return;
4674408d548SBill Yuan }
4684408d548SBill Yuan 
4694408d548SBill Yuan void
ip_fw3_sync_modevent(int type)4704408d548SBill Yuan ip_fw3_sync_modevent(int type)
4714408d548SBill Yuan {
4724408d548SBill Yuan 	switch (type) {
4734408d548SBill Yuan 		case MOD_LOAD:
4744408d548SBill Yuan 			ipfw_sync_send_state_prt = ip_fw3_sync_send_state;
4754408d548SBill Yuan 			break;
4764408d548SBill Yuan 		case MOD_UNLOAD:
4774408d548SBill Yuan 			if (fw3_sync_ctx.edges != NULL) {
4784408d548SBill Yuan 				kfree(fw3_sync_ctx.edges, M_IPFW3_SYNC);
4794408d548SBill Yuan 			}
4804408d548SBill Yuan 			if (fw3_sync_ctx.running & 1) {
4814408d548SBill Yuan 				fw3_sync_ctx.running = 0;
4824408d548SBill Yuan 				soclose(fw3_sync_ctx.edge_sock, 0);
4834408d548SBill Yuan 				fw3_sync_ctx.edge_td = NULL;
4844408d548SBill Yuan 			}
4854408d548SBill Yuan 			if (fw3_sync_ctx.running & 2) {
4864408d548SBill Yuan 				int i;
4874408d548SBill Yuan 				for (i = 0; i < fw3_sync_ctx.count; i++) {
4884408d548SBill Yuan 					soclose(fw3_sync_ctx.centre_socks[i], 0);
4894408d548SBill Yuan 				}
4904408d548SBill Yuan 			}
4914408d548SBill Yuan 			break;
4924408d548SBill Yuan 		default:
4934408d548SBill Yuan 			break;
4944408d548SBill Yuan 	}
4954408d548SBill Yuan }
496