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