1 /* 2 * Copyright (c) 2016 - 2018 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Bill Yuan <bycn82@dragonflybsd.org> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/types.h> 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/malloc.h> 40 #include <sys/mbuf.h> 41 #include <sys/kernel.h> 42 #include <sys/proc.h> 43 #include <sys/socket.h> 44 #include <sys/socketvar.h> 45 #include <sys/socketvar2.h> 46 #include <sys/socketops.h> 47 #include <sys/sysctl.h> 48 #include <sys/syslog.h> 49 #include <sys/ucred.h> 50 #include <sys/in_cksum.h> 51 #include <sys/lock.h> 52 #include <sys/kthread.h> 53 54 #include <net/if.h> 55 #include <net/route.h> 56 #include <net/pfil.h> 57 #include <net/netmsg2.h> 58 #include <net/ethernet.h> 59 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/in_var.h> 63 #include <netinet/in_pcb.h> 64 #include <netinet/ip.h> 65 #include <netinet/ip_var.h> 66 #include <netinet/ip_icmp.h> 67 #include <netinet/tcp.h> 68 #include <netinet/tcp_timer.h> 69 #include <netinet/tcp_var.h> 70 #include <netinet/tcpip.h> 71 #include <netinet/udp.h> 72 #include <netinet/udp_var.h> 73 #include <netinet/ip_divert.h> 74 #include <netinet/if_ether.h> 75 76 #include <net/ipfw3/ip_fw.h> 77 #include <net/ipfw3_basic/ip_fw3_sync.h> 78 79 #define LEN_IN_ADDR sizeof(struct in_addr) 80 81 MALLOC_DEFINE(M_IPFW3_SYNC, "IPFW3_SYNC", "mem for ipfw3sync"); 82 83 extern struct ipfw3_context *fw3_ctx[MAXCPU]; 84 extern struct ipfw3_sync_context fw3_sync_ctx; 85 ipfw_sync_send_state_t *ipfw_sync_send_state_prt = NULL; 86 ipfw_sync_install_state_t *ipfw_sync_install_state_prt = NULL; 87 88 89 90 void 91 ip_fw3_sync_install_state(struct cmd_send_state *cmd) 92 { 93 /* TODO */ 94 } 95 96 /* 97 * ipfw3sync show config 98 */ 99 int 100 ip_fw3_ctl_sync_show_conf(struct sockopt *sopt) 101 { 102 struct ipfw3_ioc_sync_context *tmp_sync_ctx; 103 int size; 104 105 size = 3 * sizeof(int) + fw3_sync_ctx.count * LEN_SYNC_EDGE; 106 if (sopt->sopt_valsize < size) { 107 /* sopt_val is not big enough */ 108 bzero(sopt->sopt_val, sopt->sopt_valsize); 109 return 0; 110 } 111 tmp_sync_ctx = (struct ipfw3_ioc_sync_context *)sopt->sopt_val; 112 tmp_sync_ctx->edge_port = fw3_sync_ctx.edge_port; 113 tmp_sync_ctx->hw_same = fw3_sync_ctx.hw_same; 114 tmp_sync_ctx->count = fw3_sync_ctx.count; 115 bcopy(fw3_sync_ctx.edges, tmp_sync_ctx->edges, 116 fw3_sync_ctx.count * LEN_SYNC_EDGE); 117 sopt->sopt_valsize = size; 118 return 0; 119 } 120 121 /* 122 * ipfw3sync show status 123 */ 124 int 125 ip_fw3_ctl_sync_show_status(struct sockopt *sopt) 126 { 127 int *running; 128 running = (int *)sopt->sopt_val; 129 *running = fw3_sync_ctx.running; 130 sopt->sopt_valsize = sizeof(int); 131 return 0; 132 } 133 /* 134 * ipfw3sync config centre 135 */ 136 int 137 ip_fw3_ctl_sync_centre_conf(struct sockopt *sopt) 138 { 139 struct ipfw3_ioc_sync_centre *ioc_centre; 140 int size; 141 142 ioc_centre = sopt->sopt_val; 143 size = ioc_centre->count * LEN_SYNC_EDGE; 144 if (fw3_sync_ctx.count == 0) { 145 fw3_sync_ctx.edges = kmalloc(size, M_IPFW3_SYNC, M_NOWAIT | M_ZERO); 146 } else { 147 fw3_sync_ctx.edges = krealloc(fw3_sync_ctx.edges, 148 size, M_TEMP, M_WAITOK); 149 } 150 fw3_sync_ctx.count = ioc_centre->count; 151 bcopy(ioc_centre->edges, fw3_sync_ctx.edges, 152 ioc_centre->count * LEN_SYNC_EDGE); 153 return 0; 154 } 155 156 /* 157 * ipfw3sync config edge 158 */ 159 int 160 ip_fw3_ctl_sync_edge_conf(struct sockopt *sopt) 161 { 162 struct ipfw3_ioc_sync_edge *ioc_edge; 163 struct thread *td; 164 size_t size; 165 int error; 166 167 size = sopt->sopt_valsize; 168 ioc_edge = sopt->sopt_val; 169 if (size != sizeof(struct ipfw3_ioc_sync_edge)) { 170 return EINVAL; 171 } 172 fw3_sync_ctx.edge_port = ioc_edge->port; 173 fw3_sync_ctx.hw_same = ioc_edge->hw_same; 174 175 td = curthread->td_proc ? curthread : &thread0; 176 error = socreate(AF_INET, &fw3_sync_ctx.edge_sock, 177 SOCK_DGRAM, IPPROTO_UDP, td); 178 if (error) { 179 kprintf("ipfw3sync edge socreate failed: %d\n", error); 180 return (error); 181 } 182 return 0; 183 } 184 185 void 186 ip_fw3_sync_edge_socket_handler(void *dummy) 187 { 188 struct socket *so; 189 struct sockbuf sio; 190 struct sockaddr_in sin; 191 struct mbuf *m; 192 struct sockaddr *sa; 193 int error, flags, *type; 194 195 so = fw3_sync_ctx.edge_sock; 196 flags = MSG_FBLOCKING; 197 198 bzero(&sin, sizeof(struct sockaddr_in)); 199 sin.sin_family = AF_INET; 200 sin.sin_port = htons(fw3_sync_ctx.edge_port); 201 sin.sin_len = LEN_IN_ADDR; 202 sa = (struct sockaddr *)&sin; 203 while (fw3_sync_ctx.running & 1) { 204 sbinit(&sio, 1000000000); 205 error = so_pru_soreceive(so, NULL, NULL, &sio, NULL, &flags); 206 if (error) 207 break; 208 m = sio.sb_mb; 209 type = (int *)m->m_data; 210 if (*type == SYNC_TYPE_SEND_TEST) { 211 struct cmd_send_test *cmd; 212 cmd = (struct cmd_send_test *)m->m_data; 213 kprintf("test received %d\n", cmd->num); 214 } else if (*type == SYNC_TYPE_SEND_STATE) { 215 struct cmd_send_state *cmd; 216 cmd = (struct cmd_send_state *)m->m_data; 217 if (ipfw_sync_install_state_prt != NULL) { 218 (*ipfw_sync_install_state_prt)(cmd); 219 } 220 } else if (*type == SYNC_TYPE_SEND_NAT) { 221 /* TODO sync NAT records */ 222 kprintf("nat received\n"); 223 } else { 224 kprintf("Error ignore\n"); 225 } 226 } 227 soshutdown(fw3_sync_ctx.edge_sock, SHUT_RD); 228 sofree(fw3_sync_ctx.edge_sock); 229 kthread_exit(); 230 } 231 232 int 233 ip_fw3_ctl_sync_edge_start(struct sockopt *sopt) 234 { 235 struct sockaddr_in sin; 236 struct thread *td; 237 int error; 238 239 if (fw3_sync_ctx.running & 1) { 240 return 0; 241 } 242 td = curthread->td_proc ? curthread : &thread0; 243 bzero(&sin, sizeof(struct sockaddr_in)); 244 sin.sin_family = AF_INET; 245 sin.sin_len = sizeof(struct sockaddr_in); 246 sin.sin_port = htons(fw3_sync_ctx.edge_port); 247 sin.sin_addr.s_addr = INADDR_ANY; 248 error = sobind(fw3_sync_ctx.edge_sock, (struct sockaddr *)&sin, td); 249 if (error) { 250 if (error != EADDRINUSE) { 251 kprintf("ipfw3sync edge sobind failed: %d\n", error); 252 } else { 253 kprintf("ipfw3sync edge address in use: %d\n", error); 254 } 255 return (error); 256 } 257 258 fw3_sync_ctx.running |= 1; 259 soreference(fw3_sync_ctx.edge_sock); 260 error = kthread_create(ip_fw3_sync_edge_socket_handler, NULL, 261 &fw3_sync_ctx.edge_td, "sync_edge_thread"); 262 if (error) { 263 panic("ip_fw3_sync_edge_socket_handler:error %d",error); 264 } 265 return 0; 266 } 267 268 int 269 ip_fw3_ctl_sync_centre_start(struct sockopt *sopt) 270 { 271 struct sockaddr_in sin; 272 struct thread *td; 273 struct ipfw3_sync_edge *edge; 274 int error, i; 275 276 fw3_sync_ctx.running |= 2; 277 td = curthread->td_proc ? curthread : &thread0; 278 279 for (i = 0; i < fw3_sync_ctx.count; i++) { 280 error = socreate(AF_INET, &fw3_sync_ctx.centre_socks[i], 281 SOCK_DGRAM, IPPROTO_UDP, td); 282 if (error) { 283 kprintf("ipfw3sync centre socreate failed: %d\n", 284 error); 285 return error; 286 } 287 edge = fw3_sync_ctx.edges; 288 289 bzero(&sin, sizeof(struct sockaddr_in)); 290 sin.sin_family = AF_INET; 291 sin.sin_port = htons(edge->port); 292 sin.sin_addr.s_addr = edge->addr; 293 sin.sin_len = sizeof(struct sockaddr_in); 294 error = soconnect(fw3_sync_ctx.centre_socks[i], 295 (struct sockaddr *)&sin, td, TRUE); 296 if (error) { 297 kprintf("ipfw3sync: centre soconnect failed: %d\n", 298 error); 299 return error; 300 } 301 } 302 303 return 0; 304 } 305 306 int 307 ip_fw3_ctl_sync_edge_test(struct sockopt *sopt) 308 { 309 return 0; 310 } 311 312 int 313 ip_fw3_ctl_sync_centre_test(struct sockopt *sopt) 314 { 315 struct cmd_send_test cmd; 316 struct mbuf *m; 317 struct thread *td; 318 int error, i, len, nsize, *num; 319 320 if (sopt->sopt_valsize != sizeof(int)) { 321 kprintf("ipfw3sync: invalid centre test parameter\n"); 322 return -1; 323 } 324 if ((fw3_sync_ctx.running & 2) == 0) { 325 kprintf("ipfw3sync: centre not running\n"); 326 return -1; 327 } 328 num = sopt->sopt_val; 329 len = sizeof(struct cmd_send_test); 330 m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize); 331 cmd.type = 0; 332 cmd.num = *num; 333 memcpy(m->m_data, &cmd, len); 334 335 m->m_len = len; 336 m->m_pkthdr.len = len; 337 338 td = curthread->td_proc ? curthread : &thread0; 339 for (i = 0; i < fw3_sync_ctx.count; i++) { 340 error = so_pru_sosend(fw3_sync_ctx.centre_socks[i], 341 NULL, NULL, m, NULL, 0 ,td); 342 if (error) { 343 kprintf("ipfw3sync: centre sosend failed: %d\n", error); 344 return -1; 345 } 346 } 347 m_free(m); 348 return 0; 349 } 350 int 351 ip_fw3_ctl_sync_edge_stop(struct sockopt *sopt) 352 { 353 if (fw3_sync_ctx.running & 1) { 354 fw3_sync_ctx.running &= 2; 355 soclose(fw3_sync_ctx.edge_sock, 0); 356 } 357 return 0; 358 } 359 360 int 361 ip_fw3_ctl_sync_centre_stop(struct sockopt *sopt) 362 { 363 int i; 364 365 if (fw3_sync_ctx.running & 2) { 366 fw3_sync_ctx.running &= 1; 367 for (i = 0; i < fw3_sync_ctx.count; i++) { 368 soclose(fw3_sync_ctx.centre_socks[i], 0); 369 } 370 } 371 return 0; 372 } 373 374 int 375 ip_fw3_ctl_sync_edge_clear(struct sockopt *sopt) 376 { 377 return 0; 378 } 379 380 int 381 ip_fw3_ctl_sync_centre_clear(struct sockopt *sopt) 382 { 383 return 0; 384 } 385 386 /* 387 * sockopt handler 388 */ 389 int 390 ip_fw3_ctl_sync_sockopt(struct sockopt *sopt) 391 { 392 int error = 0; 393 switch (sopt->sopt_name) { 394 case IP_FW_SYNC_EDGE_CONF: 395 error = ip_fw3_ctl_sync_edge_conf(sopt); 396 break; 397 case IP_FW_SYNC_CENTRE_CONF: 398 error = ip_fw3_ctl_sync_centre_conf(sopt); 399 break; 400 case IP_FW_SYNC_SHOW_CONF: 401 error = ip_fw3_ctl_sync_show_conf(sopt); 402 break; 403 case IP_FW_SYNC_SHOW_STATUS: 404 error = ip_fw3_ctl_sync_show_status(sopt); 405 break; 406 case IP_FW_SYNC_EDGE_START: 407 error = ip_fw3_ctl_sync_edge_start(sopt); 408 break; 409 case IP_FW_SYNC_CENTRE_START: 410 error = ip_fw3_ctl_sync_centre_start(sopt); 411 break; 412 case IP_FW_SYNC_EDGE_STOP: 413 error = ip_fw3_ctl_sync_edge_stop(sopt); 414 break; 415 case IP_FW_SYNC_CENTRE_STOP: 416 error = ip_fw3_ctl_sync_centre_stop(sopt); 417 break; 418 case IP_FW_SYNC_EDGE_CLEAR: 419 error = ip_fw3_ctl_sync_edge_clear(sopt); 420 break; 421 case IP_FW_SYNC_CENTRE_CLEAR: 422 error = ip_fw3_ctl_sync_centre_clear(sopt); 423 break; 424 case IP_FW_SYNC_EDGE_TEST: 425 error = ip_fw3_ctl_sync_edge_test(sopt); 426 break; 427 case IP_FW_SYNC_CENTRE_TEST: 428 error = ip_fw3_ctl_sync_centre_test(sopt); 429 break; 430 default: 431 kprintf("ipfw3 sync invalid socket option %d\n", 432 sopt->sopt_name); 433 } 434 return error; 435 } 436 437 void 438 ip_fw3_sync_send_state(struct ipfw3_state *state, int cpu, int hash) 439 { 440 struct mbuf *m; 441 struct thread *td; 442 int error, i, len, nsize; 443 struct cmd_send_state cmd; 444 445 len = sizeof(struct cmd_send_state); 446 m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize); 447 448 cmd.type = 1; 449 cmd.cpu = cpu; 450 cmd.hash = hash; 451 452 memcpy(m->m_data, &cmd, len); 453 454 m->m_len = len; 455 m->m_pkthdr.len = len; 456 457 td = curthread->td_proc ? curthread : &thread0; 458 for (i = 0; i < fw3_sync_ctx.count; i++) { 459 error = so_pru_sosend(fw3_sync_ctx.centre_socks[i], 460 NULL, NULL, m, NULL, 0 ,td); 461 if (error) { 462 kprintf("ipfw3sync: centre sosend failed: %d\n", error); 463 return; 464 } 465 } 466 return; 467 } 468 469 void 470 ip_fw3_sync_modevent(int type) 471 { 472 switch (type) { 473 case MOD_LOAD: 474 ipfw_sync_send_state_prt = ip_fw3_sync_send_state; 475 break; 476 case MOD_UNLOAD: 477 if (fw3_sync_ctx.edges != NULL) { 478 kfree(fw3_sync_ctx.edges, M_IPFW3_SYNC); 479 } 480 if (fw3_sync_ctx.running & 1) { 481 fw3_sync_ctx.running = 0; 482 soclose(fw3_sync_ctx.edge_sock, 0); 483 fw3_sync_ctx.edge_td = NULL; 484 } 485 if (fw3_sync_ctx.running & 2) { 486 int i; 487 for (i = 0; i < fw3_sync_ctx.count; i++) { 488 soclose(fw3_sync_ctx.centre_socks[i], 0); 489 } 490 } 491 break; 492 default: 493 break; 494 } 495 } 496