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 if (m == NULL) { 332 kprintf("ipfw3sync: MGET failed\n"); 333 return -1; 334 } 335 cmd.type = 0; 336 cmd.num = *num; 337 memcpy(m->m_data, &cmd, len); 338 339 m->m_len = len; 340 m->m_pkthdr.len = len; 341 342 td = curthread->td_proc ? curthread : &thread0; 343 for (i = 0; i < fw3_sync_ctx.count; i++) { 344 error = so_pru_sosend(fw3_sync_ctx.centre_socks[i], 345 NULL, NULL, m, NULL, 0 ,td); 346 if (error) { 347 kprintf("ipfw3sync: centre sosend failed: %d\n", error); 348 return -1; 349 } 350 } 351 m_free(m); 352 return 0; 353 } 354 int 355 ip_fw3_ctl_sync_edge_stop(struct sockopt *sopt) 356 { 357 if (fw3_sync_ctx.running & 1) { 358 fw3_sync_ctx.running &= 2; 359 soclose(fw3_sync_ctx.edge_sock, 0); 360 } 361 return 0; 362 } 363 364 int 365 ip_fw3_ctl_sync_centre_stop(struct sockopt *sopt) 366 { 367 int i; 368 369 if (fw3_sync_ctx.running & 2) { 370 fw3_sync_ctx.running &= 1; 371 for (i = 0; i < fw3_sync_ctx.count; i++) { 372 soclose(fw3_sync_ctx.centre_socks[i], 0); 373 } 374 } 375 return 0; 376 } 377 378 int 379 ip_fw3_ctl_sync_edge_clear(struct sockopt *sopt) 380 { 381 return 0; 382 } 383 384 int 385 ip_fw3_ctl_sync_centre_clear(struct sockopt *sopt) 386 { 387 return 0; 388 } 389 390 /* 391 * sockopt handler 392 */ 393 int 394 ip_fw3_ctl_sync_sockopt(struct sockopt *sopt) 395 { 396 int error = 0; 397 switch (sopt->sopt_name) { 398 case IP_FW_SYNC_EDGE_CONF: 399 error = ip_fw3_ctl_sync_edge_conf(sopt); 400 break; 401 case IP_FW_SYNC_CENTRE_CONF: 402 error = ip_fw3_ctl_sync_centre_conf(sopt); 403 break; 404 case IP_FW_SYNC_SHOW_CONF: 405 error = ip_fw3_ctl_sync_show_conf(sopt); 406 break; 407 case IP_FW_SYNC_SHOW_STATUS: 408 error = ip_fw3_ctl_sync_show_status(sopt); 409 break; 410 case IP_FW_SYNC_EDGE_START: 411 error = ip_fw3_ctl_sync_edge_start(sopt); 412 break; 413 case IP_FW_SYNC_CENTRE_START: 414 error = ip_fw3_ctl_sync_centre_start(sopt); 415 break; 416 case IP_FW_SYNC_EDGE_STOP: 417 error = ip_fw3_ctl_sync_edge_stop(sopt); 418 break; 419 case IP_FW_SYNC_CENTRE_STOP: 420 error = ip_fw3_ctl_sync_centre_stop(sopt); 421 break; 422 case IP_FW_SYNC_EDGE_CLEAR: 423 error = ip_fw3_ctl_sync_edge_clear(sopt); 424 break; 425 case IP_FW_SYNC_CENTRE_CLEAR: 426 error = ip_fw3_ctl_sync_centre_clear(sopt); 427 break; 428 case IP_FW_SYNC_EDGE_TEST: 429 error = ip_fw3_ctl_sync_edge_test(sopt); 430 break; 431 case IP_FW_SYNC_CENTRE_TEST: 432 error = ip_fw3_ctl_sync_centre_test(sopt); 433 break; 434 default: 435 kprintf("ipfw3 sync invalid socket option %d\n", 436 sopt->sopt_name); 437 } 438 return error; 439 } 440 441 void 442 ip_fw3_sync_send_state(struct ipfw3_state *state, int cpu, int hash) 443 { 444 struct mbuf *m; 445 struct thread *td; 446 int error, i, len, nsize; 447 struct cmd_send_state cmd; 448 449 len = sizeof(struct cmd_send_state); 450 m = m_getl(len, M_WAITOK, MT_DATA, M_PKTHDR, &nsize); 451 if (m == NULL) { 452 kprintf("ipfw3sync: MGET failed\n"); 453 return; 454 } 455 456 cmd.type = 1; 457 cmd.cpu = cpu; 458 cmd.hash = hash; 459 460 memcpy(m->m_data, &cmd, len); 461 462 m->m_len = len; 463 m->m_pkthdr.len = len; 464 465 td = curthread->td_proc ? curthread : &thread0; 466 for (i = 0; i < fw3_sync_ctx.count; i++) { 467 error = so_pru_sosend(fw3_sync_ctx.centre_socks[i], 468 NULL, NULL, m, NULL, 0 ,td); 469 if (error) { 470 kprintf("ipfw3sync: centre sosend failed: %d\n", error); 471 return; 472 } 473 } 474 return; 475 } 476 477 void 478 ip_fw3_sync_modevent(int type) 479 { 480 switch (type) { 481 case MOD_LOAD: 482 ipfw_sync_send_state_prt = ip_fw3_sync_send_state; 483 break; 484 case MOD_UNLOAD: 485 if (fw3_sync_ctx.edges != NULL) { 486 kfree(fw3_sync_ctx.edges, M_IPFW3_SYNC); 487 } 488 if (fw3_sync_ctx.running & 1) { 489 fw3_sync_ctx.running = 0; 490 soclose(fw3_sync_ctx.edge_sock, 0); 491 fw3_sync_ctx.edge_td = NULL; 492 } 493 if (fw3_sync_ctx.running & 2) { 494 int i; 495 for (i = 0; i < fw3_sync_ctx.count; i++) { 496 soclose(fw3_sync_ctx.centre_socks[i], 0); 497 } 498 } 499 break; 500 default: 501 break; 502 } 503 } 504