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 #include <sys/mplock2.h> 54 55 #include <net/if.h> 56 #include <net/route.h> 57 #include <net/pfil.h> 58 #include <net/netmsg2.h> 59 #include <net/ethernet.h> 60 61 #include <netinet/in.h> 62 #include <netinet/in_systm.h> 63 #include <netinet/in_var.h> 64 #include <netinet/in_pcb.h> 65 #include <netinet/ip.h> 66 #include <netinet/ip_var.h> 67 #include <netinet/ip_icmp.h> 68 #include <netinet/tcp.h> 69 #include <netinet/tcp_timer.h> 70 #include <netinet/tcp_var.h> 71 #include <netinet/tcpip.h> 72 #include <netinet/udp.h> 73 #include <netinet/udp_var.h> 74 #include <netinet/ip_divert.h> 75 #include <netinet/if_ether.h> 76 77 #include <net/ipfw3/ip_fw.h> 78 #include <net/ipfw3_basic/ip_fw3_sync.h> 79 80 #define LEN_IN_ADDR sizeof(struct in_addr) 81 82 MALLOC_DEFINE(M_IPFW3_SYNC, "IPFW3_SYNC", "mem for ipfw3sync"); 83 84 extern struct ipfw3_context *fw3_ctx[MAXCPU]; 85 extern struct ipfw3_sync_context fw3_sync_ctx; 86 ipfw_sync_send_state_t *ipfw_sync_send_state_prt = NULL; 87 ipfw_sync_install_state_t *ipfw_sync_install_state_prt = NULL; 88 89 90 91 void 92 ip_fw3_sync_install_state(struct cmd_send_state *cmd) 93 { 94 /* TODO */ 95 } 96 97 /* 98 * ipfw3sync show config 99 */ 100 int 101 ip_fw3_ctl_sync_show_conf(struct sockopt *sopt) 102 { 103 struct ipfw3_ioc_sync_context *tmp_sync_ctx; 104 int size; 105 106 size = 3 * sizeof(int) + fw3_sync_ctx.count * LEN_SYNC_EDGE; 107 if (sopt->sopt_valsize < size) { 108 /* sopt_val is not big enough */ 109 bzero(sopt->sopt_val, sopt->sopt_valsize); 110 return 0; 111 } 112 tmp_sync_ctx = (struct ipfw3_ioc_sync_context *)sopt->sopt_val; 113 tmp_sync_ctx->edge_port = fw3_sync_ctx.edge_port; 114 tmp_sync_ctx->hw_same = fw3_sync_ctx.hw_same; 115 tmp_sync_ctx->count = fw3_sync_ctx.count; 116 bcopy(fw3_sync_ctx.edges, tmp_sync_ctx->edges, 117 fw3_sync_ctx.count * LEN_SYNC_EDGE); 118 sopt->sopt_valsize = size; 119 return 0; 120 } 121 122 /* 123 * ipfw3sync show status 124 */ 125 int 126 ip_fw3_ctl_sync_show_status(struct sockopt *sopt) 127 { 128 int *running; 129 running = (int *)sopt->sopt_val; 130 *running = fw3_sync_ctx.running; 131 sopt->sopt_valsize = sizeof(int); 132 return 0; 133 } 134 /* 135 * ipfw3sync config centre 136 */ 137 int 138 ip_fw3_ctl_sync_centre_conf(struct sockopt *sopt) 139 { 140 struct ipfw3_ioc_sync_centre *ioc_centre; 141 int size; 142 143 ioc_centre = sopt->sopt_val; 144 size = ioc_centre->count * LEN_SYNC_EDGE; 145 if (fw3_sync_ctx.count == 0) { 146 fw3_sync_ctx.edges = kmalloc(size, M_IPFW3_SYNC, M_NOWAIT | M_ZERO); 147 } else { 148 fw3_sync_ctx.edges = krealloc(fw3_sync_ctx.edges, 149 size, M_TEMP, M_WAITOK); 150 } 151 fw3_sync_ctx.count = ioc_centre->count; 152 bcopy(ioc_centre->edges, fw3_sync_ctx.edges, 153 ioc_centre->count * LEN_SYNC_EDGE); 154 return 0; 155 } 156 157 /* 158 * ipfw3sync config edge 159 */ 160 int 161 ip_fw3_ctl_sync_edge_conf(struct sockopt *sopt) 162 { 163 struct ipfw3_ioc_sync_edge *ioc_edge; 164 struct thread *td; 165 size_t size; 166 int error; 167 168 size = sopt->sopt_valsize; 169 ioc_edge = sopt->sopt_val; 170 if (size != sizeof(struct ipfw3_ioc_sync_edge)) { 171 return EINVAL; 172 } 173 fw3_sync_ctx.edge_port = ioc_edge->port; 174 fw3_sync_ctx.hw_same = ioc_edge->hw_same; 175 176 td = curthread->td_proc ? curthread : &thread0; 177 error = socreate(AF_INET, &fw3_sync_ctx.edge_sock, 178 SOCK_DGRAM, IPPROTO_UDP, td); 179 if (error) { 180 kprintf("ipfw3sync edge socreate failed: %d\n", error); 181 return (error); 182 } 183 return 0; 184 } 185 186 void 187 ip_fw3_sync_edge_socket_handler(void *dummy) 188 { 189 struct socket *so; 190 struct sockbuf sio; 191 struct sockaddr_in sin; 192 struct mbuf *m; 193 struct sockaddr *sa; 194 int error, flags, *type; 195 196 so = fw3_sync_ctx.edge_sock; 197 flags = MSG_FBLOCKING; 198 199 bzero(&sin, sizeof(struct sockaddr_in)); 200 sin.sin_family = AF_INET; 201 sin.sin_port = htons(fw3_sync_ctx.edge_port); 202 sin.sin_len = LEN_IN_ADDR; 203 sa = (struct sockaddr *)&sin; 204 while (fw3_sync_ctx.running & 1) { 205 sbinit(&sio, 1000000000); 206 error = so_pru_soreceive(so, NULL, NULL, &sio, NULL, &flags); 207 if (error) 208 break; 209 m = sio.sb_mb; 210 type = (int *)m->m_data; 211 if (*type == SYNC_TYPE_SEND_TEST) { 212 struct cmd_send_test *cmd; 213 cmd = (struct cmd_send_test *)m->m_data; 214 kprintf("test received %d\n", cmd->num); 215 } else if (*type == SYNC_TYPE_SEND_STATE) { 216 struct cmd_send_state *cmd; 217 cmd = (struct cmd_send_state *)m->m_data; 218 if (ipfw_sync_install_state_prt != NULL) { 219 (*ipfw_sync_install_state_prt)(cmd); 220 } 221 } else if (*type == SYNC_TYPE_SEND_NAT) { 222 /* TODO sync NAT records */ 223 kprintf("nat received\n"); 224 } else { 225 kprintf("Error ignore\n"); 226 } 227 } 228 soshutdown(fw3_sync_ctx.edge_sock, SHUT_RD); 229 sofree(fw3_sync_ctx.edge_sock); 230 kthread_exit(); 231 } 232 233 int 234 ip_fw3_ctl_sync_edge_start(struct sockopt *sopt) 235 { 236 struct sockaddr_in sin; 237 struct thread *td; 238 int error; 239 240 if (fw3_sync_ctx.running & 1) { 241 return 0; 242 } 243 td = curthread->td_proc ? curthread : &thread0; 244 bzero(&sin, sizeof(struct sockaddr_in)); 245 sin.sin_family = AF_INET; 246 sin.sin_len = sizeof(struct sockaddr_in); 247 sin.sin_port = htons(fw3_sync_ctx.edge_port); 248 sin.sin_addr.s_addr = INADDR_ANY; 249 error = sobind(fw3_sync_ctx.edge_sock, (struct sockaddr *)&sin, td); 250 if (error) { 251 if (error != EADDRINUSE) { 252 kprintf("ipfw3sync edge sobind failed: %d\n", error); 253 } else { 254 kprintf("ipfw3sync edge address in use: %d\n", error); 255 } 256 return (error); 257 } 258 259 fw3_sync_ctx.running |= 1; 260 soreference(fw3_sync_ctx.edge_sock); 261 error = kthread_create(ip_fw3_sync_edge_socket_handler, NULL, 262 &fw3_sync_ctx.edge_td, "sync_edge_thread"); 263 if (error) { 264 panic("ip_fw3_sync_edge_socket_handler:error %d",error); 265 } 266 return 0; 267 } 268 269 int 270 ip_fw3_ctl_sync_centre_start(struct sockopt *sopt) 271 { 272 struct sockaddr_in sin; 273 struct thread *td; 274 struct ipfw3_sync_edge *edge; 275 int error, i; 276 277 fw3_sync_ctx.running |= 2; 278 td = curthread->td_proc ? curthread : &thread0; 279 280 for (i = 0; i < fw3_sync_ctx.count; i++) { 281 error = socreate(AF_INET, &fw3_sync_ctx.centre_socks[i], 282 SOCK_DGRAM, IPPROTO_UDP, td); 283 if (error) { 284 kprintf("ipfw3sync centre socreate failed: %d\n", 285 error); 286 return error; 287 } 288 edge = fw3_sync_ctx.edges; 289 290 bzero(&sin, sizeof(struct sockaddr_in)); 291 sin.sin_family = AF_INET; 292 sin.sin_port = htons(edge->port); 293 sin.sin_addr.s_addr = edge->addr; 294 sin.sin_len = sizeof(struct sockaddr_in); 295 error = soconnect(fw3_sync_ctx.centre_socks[i], 296 (struct sockaddr *)&sin, td, TRUE); 297 if (error) { 298 kprintf("ipfw3sync: centre soconnect failed: %d\n", 299 error); 300 return error; 301 } 302 } 303 304 return 0; 305 } 306 307 int 308 ip_fw3_ctl_sync_edge_test(struct sockopt *sopt) 309 { 310 return 0; 311 } 312 313 int 314 ip_fw3_ctl_sync_centre_test(struct sockopt *sopt) 315 { 316 struct cmd_send_test cmd; 317 struct mbuf *m; 318 struct thread *td; 319 int error, i, len, nsize, *num; 320 321 if (sopt->sopt_valsize != sizeof(int)) { 322 kprintf("ipfw3sync: invalid centre test parameter\n"); 323 return -1; 324 } 325 if ((fw3_sync_ctx.running & 2) == 0) { 326 kprintf("ipfw3sync: centre not running\n"); 327 return -1; 328 } 329 num = sopt->sopt_val; 330 len = sizeof(struct cmd_send_test); 331 m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize); 332 if (m == NULL) { 333 kprintf("ipfw3sync: MGET failed\n"); 334 return -1; 335 } 336 cmd.type = 0; 337 cmd.num = *num; 338 memcpy(m->m_data, &cmd, len); 339 340 m->m_len = len; 341 m->m_pkthdr.len = len; 342 343 td = curthread->td_proc ? curthread : &thread0; 344 for (i = 0; i < fw3_sync_ctx.count; i++) { 345 error = so_pru_sosend(fw3_sync_ctx.centre_socks[i], 346 NULL, NULL, m, NULL, 0 ,td); 347 if (error) { 348 kprintf("ipfw3sync: centre sosend failed: %d\n", error); 349 return -1; 350 } 351 } 352 m_free(m); 353 return 0; 354 } 355 int 356 ip_fw3_ctl_sync_edge_stop(struct sockopt *sopt) 357 { 358 if (fw3_sync_ctx.running & 1) { 359 fw3_sync_ctx.running &= 2; 360 soclose(fw3_sync_ctx.edge_sock, 0); 361 } 362 return 0; 363 } 364 365 int 366 ip_fw3_ctl_sync_centre_stop(struct sockopt *sopt) 367 { 368 int i; 369 370 if (fw3_sync_ctx.running & 2) { 371 fw3_sync_ctx.running &= 1; 372 for (i = 0; i < fw3_sync_ctx.count; i++) { 373 soclose(fw3_sync_ctx.centre_socks[i], 0); 374 } 375 } 376 return 0; 377 } 378 379 int 380 ip_fw3_ctl_sync_edge_clear(struct sockopt *sopt) 381 { 382 return 0; 383 } 384 385 int 386 ip_fw3_ctl_sync_centre_clear(struct sockopt *sopt) 387 { 388 return 0; 389 } 390 391 /* 392 * sockopt handler 393 */ 394 int 395 ip_fw3_ctl_sync_sockopt(struct sockopt *sopt) 396 { 397 int error = 0; 398 switch (sopt->sopt_name) { 399 case IP_FW_SYNC_EDGE_CONF: 400 error = ip_fw3_ctl_sync_edge_conf(sopt); 401 break; 402 case IP_FW_SYNC_CENTRE_CONF: 403 error = ip_fw3_ctl_sync_centre_conf(sopt); 404 break; 405 case IP_FW_SYNC_SHOW_CONF: 406 error = ip_fw3_ctl_sync_show_conf(sopt); 407 break; 408 case IP_FW_SYNC_SHOW_STATUS: 409 error = ip_fw3_ctl_sync_show_status(sopt); 410 break; 411 case IP_FW_SYNC_EDGE_START: 412 error = ip_fw3_ctl_sync_edge_start(sopt); 413 break; 414 case IP_FW_SYNC_CENTRE_START: 415 error = ip_fw3_ctl_sync_centre_start(sopt); 416 break; 417 case IP_FW_SYNC_EDGE_STOP: 418 error = ip_fw3_ctl_sync_edge_stop(sopt); 419 break; 420 case IP_FW_SYNC_CENTRE_STOP: 421 error = ip_fw3_ctl_sync_centre_stop(sopt); 422 break; 423 case IP_FW_SYNC_EDGE_CLEAR: 424 error = ip_fw3_ctl_sync_edge_clear(sopt); 425 break; 426 case IP_FW_SYNC_CENTRE_CLEAR: 427 error = ip_fw3_ctl_sync_centre_clear(sopt); 428 break; 429 case IP_FW_SYNC_EDGE_TEST: 430 error = ip_fw3_ctl_sync_edge_test(sopt); 431 break; 432 case IP_FW_SYNC_CENTRE_TEST: 433 error = ip_fw3_ctl_sync_centre_test(sopt); 434 break; 435 default: 436 kprintf("ipfw3 sync invalid socket option %d\n", 437 sopt->sopt_name); 438 } 439 return error; 440 } 441 442 void 443 ip_fw3_sync_send_state(struct ipfw3_state *state, int cpu, int hash) 444 { 445 struct mbuf *m; 446 struct thread *td; 447 int error, i, len, nsize; 448 struct cmd_send_state cmd; 449 450 len = sizeof(struct cmd_send_state); 451 m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize); 452 if (m == NULL) { 453 kprintf("ipfw3sync: MGET failed\n"); 454 return; 455 } 456 457 cmd.type = 1; 458 cmd.cpu = cpu; 459 cmd.hash = hash; 460 461 memcpy(m->m_data, &cmd, len); 462 463 m->m_len = len; 464 m->m_pkthdr.len = len; 465 466 td = curthread->td_proc ? curthread : &thread0; 467 for (i = 0; i < fw3_sync_ctx.count; i++) { 468 error = so_pru_sosend(fw3_sync_ctx.centre_socks[i], 469 NULL, NULL, m, NULL, 0 ,td); 470 if (error) { 471 kprintf("ipfw3sync: centre sosend failed: %d\n", error); 472 return; 473 } 474 } 475 return; 476 } 477 478 void 479 ip_fw3_sync_modevent(int type) 480 { 481 switch (type) { 482 case MOD_LOAD: 483 ipfw_sync_send_state_prt = ip_fw3_sync_send_state; 484 break; 485 case MOD_UNLOAD: 486 if (fw3_sync_ctx.edges != NULL) { 487 kfree(fw3_sync_ctx.edges, M_IPFW3_SYNC); 488 } 489 if (fw3_sync_ctx.running & 1) { 490 fw3_sync_ctx.running = 0; 491 soclose(fw3_sync_ctx.edge_sock, 0); 492 fw3_sync_ctx.edge_td = NULL; 493 } 494 if (fw3_sync_ctx.running & 2) { 495 int i; 496 for (i = 0; i < fw3_sync_ctx.count; i++) { 497 soclose(fw3_sync_ctx.centre_socks[i], 0); 498 } 499 } 500 break; 501 default: 502 break; 503 } 504 } 505