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