1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7 #if defined(KERNEL) || defined(_KERNEL) 8 # undef KERNEL 9 # undef _KERNEL 10 # define KERNEL 1 11 # define _KERNEL 1 12 #endif 13 #include <sys/errno.h> 14 #include <sys/types.h> 15 #include <sys/param.h> 16 #include <sys/time.h> 17 #include <sys/file.h> 18 # include <sys/fcntl.h> 19 #if !defined(_KERNEL) && !defined(__KERNEL__) 20 # include <stdio.h> 21 # include <string.h> 22 # include <stdlib.h> 23 # include <ctype.h> 24 # define _KERNEL 25 # include <sys/uio.h> 26 # undef _KERNEL 27 #endif 28 # include <sys/protosw.h> 29 #include <sys/socket.h> 30 #if defined(_KERNEL) 31 #ifdef __FreeBSD__ 32 # include <sys/ctype.h> 33 # endif 34 # include <sys/systm.h> 35 # if !defined(__SVR4) 36 # include <sys/mbuf.h> 37 # endif 38 #endif 39 #if defined(_KERNEL) && defined(__FreeBSD__) 40 # include <sys/filio.h> 41 # include <sys/fcntl.h> 42 #else 43 # include <sys/ioctl.h> 44 #endif 45 #if defined(__SVR4) 46 # include <sys/byteorder.h> 47 # ifdef _KERNEL 48 # include <sys/dditypes.h> 49 # endif 50 # include <sys/stream.h> 51 # include <sys/kmem.h> 52 #endif 53 #ifdef __FreeBSD__ 54 # include <sys/queue.h> 55 #endif 56 #include <net/if.h> 57 #if defined(__FreeBSD__) && defined(_KERNEL) 58 #include <net/vnet.h> 59 #else 60 #define CURVNET_SET(arg) 61 #define CURVNET_RESTORE() 62 #define VNET_DEFINE(_t, _v) _t _v 63 #define VNET_DECLARE(_t, _v) extern _t _v 64 #define VNET(arg) arg 65 #endif 66 #ifdef sun 67 # include <net/af.h> 68 #endif 69 #include <netinet/in.h> 70 #include <netinet/in_systm.h> 71 #include <netinet/ip.h> 72 # include <netinet/ip_var.h> 73 #include <netinet/tcp.h> 74 #include <netinet/udp.h> 75 #include <netinet/ip_icmp.h> 76 #include "netinet/ip_compat.h" 77 #include <netinet/tcpip.h> 78 #include "netinet/ip_fil.h" 79 #include "netinet/ip_nat.h" 80 #include "netinet/ip_state.h" 81 #include "netinet/ip_proxy.h" 82 #if defined(__FreeBSD__) 83 # include <sys/malloc.h> 84 #endif 85 86 /* END OF INCLUDES */ 87 88 #include "netinet/ip_ftp_pxy.c" 89 #include "netinet/ip_tftp_pxy.c" 90 #include "netinet/ip_rcmd_pxy.c" 91 #include "netinet/ip_pptp_pxy.c" 92 #if defined(_KERNEL) 93 # include "netinet/ip_irc_pxy.c" 94 # include "netinet/ip_raudio_pxy.c" 95 # include "netinet/ip_netbios_pxy.c" 96 #endif 97 #include "netinet/ip_ipsec_pxy.c" 98 #include "netinet/ip_rpcb_pxy.c" 99 100 101 #define AP_SESS_SIZE 53 102 103 static int ipf_proxy_fixseqack(fr_info_t *, ip_t *, ap_session_t *, int ); 104 static aproxy_t *ipf_proxy_create_clone(ipf_main_softc_t *, aproxy_t *); 105 106 typedef struct ipf_proxy_softc_s { 107 int ips_proxy_debug; 108 int ips_proxy_session_size; 109 ap_session_t **ips_sess_tab; 110 ap_session_t *ips_sess_list; 111 aproxy_t *ips_proxies; 112 int ips_init_run; 113 ipftuneable_t *ipf_proxy_tune; 114 } ipf_proxy_softc_t; 115 116 static ipftuneable_t ipf_proxy_tuneables[] = { 117 { { (void *)offsetof(ipf_proxy_softc_t, ips_proxy_debug) }, 118 "proxy_debug", 0, 0x1f, 119 stsizeof(ipf_proxy_softc_t, ips_proxy_debug), 120 0, NULL, NULL }, 121 { { NULL }, NULL, 0, 0, 122 0, 123 0, NULL, NULL} 124 }; 125 126 static aproxy_t *ap_proxylist = NULL; 127 static aproxy_t ips_proxies[] = { 128 #ifdef IPF_FTP_PROXY 129 { NULL, NULL, "ftp", (char)IPPROTO_TCP, 0, 0, 0, 130 ipf_p_ftp_main_load, ipf_p_ftp_main_unload, 131 ipf_p_ftp_soft_create, ipf_p_ftp_soft_destroy, 132 NULL, NULL, 133 ipf_p_ftp_new, ipf_p_ftp_del, ipf_p_ftp_in, ipf_p_ftp_out, NULL, 134 NULL, NULL, NULL, NULL }, 135 #endif 136 #ifdef IPF_TFTP_PROXY 137 { NULL, NULL, "tftp", (char)IPPROTO_UDP, 0, 0, 0, 138 ipf_p_tftp_main_load, ipf_p_tftp_main_unload, 139 ipf_p_tftp_soft_create, ipf_p_tftp_soft_destroy, 140 NULL, NULL, 141 ipf_p_tftp_new, ipf_p_tftp_del, 142 ipf_p_tftp_in, ipf_p_tftp_out, NULL, 143 NULL, NULL, NULL, NULL }, 144 #endif 145 #ifdef IPF_IRC_PROXY 146 { NULL, NULL, "irc", (char)IPPROTO_TCP, 0, 0, 0, 147 ipf_p_irc_main_load, ipf_p_irc_main_unload, 148 NULL, NULL, 149 NULL, NULL, 150 ipf_p_irc_new, NULL, NULL, ipf_p_irc_out, NULL, 151 NULL, NULL, NULL, NULL }, 152 #endif 153 #ifdef IPF_RCMD_PROXY 154 { NULL, NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, 0, 155 ipf_p_rcmd_main_load, ipf_p_rcmd_main_unload, 156 NULL, NULL, 157 NULL, NULL, 158 ipf_p_rcmd_new, ipf_p_rcmd_del, 159 ipf_p_rcmd_in, ipf_p_rcmd_out, NULL, 160 NULL, NULL, NULL, NULL }, 161 #endif 162 #ifdef IPF_RAUDIO_PROXY 163 { NULL, NULL, "raudio", (char)IPPROTO_TCP, 0, 0, 0, 164 ipf_p_raudio_main_load, ipf_p_raudio_main_unload, 165 NULL, NULL, 166 NULL, NULL, 167 ipf_p_raudio_new, NULL, ipf_p_raudio_in, ipf_p_raudio_out, NULL, 168 NULL, NULL, NULL, NULL }, 169 #endif 170 #ifdef IPF_MSNRPC_PROXY 171 { NULL, NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, 0, 172 ipf_p_msnrpc_init, ipf_p_msnrpc_fini, 173 NULL, NULL, 174 NULL, NULL, 175 ipf_p_msnrpc_new, NULL, ipf_p_msnrpc_in, ipf_p_msnrpc_out, NULL, 176 NULL, NULL, NULL, NULL }, 177 #endif 178 #ifdef IPF_NETBIOS_PROXY 179 { NULL, NULL, "netbios", (char)IPPROTO_UDP, 0, 0, 0, 180 ipf_p_netbios_main_load, ipf_p_netbios_main_unload, 181 NULL, NULL, 182 NULL, NULL, 183 NULL, NULL, NULL, ipf_p_netbios_out, NULL, 184 NULL, NULL, NULL, NULL }, 185 #endif 186 #ifdef IPF_IPSEC_PROXY 187 { NULL, NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 0, 188 NULL, NULL, 189 ipf_p_ipsec_soft_create, ipf_p_ipsec_soft_destroy, 190 ipf_p_ipsec_soft_init, ipf_p_ipsec_soft_fini, 191 ipf_p_ipsec_new, ipf_p_ipsec_del, 192 ipf_p_ipsec_inout, ipf_p_ipsec_inout, ipf_p_ipsec_match, 193 NULL, NULL, NULL, NULL }, 194 #endif 195 #ifdef IPF_DNS_PROXY 196 { NULL, NULL, "dns", (char)IPPROTO_UDP, 0, 0, 0, 197 NULL, NULL, 198 ipf_p_dns_soft_create, ipf_p_dns_soft_destroy, 199 NULL, NULL, 200 ipf_p_dns_new, ipf_p_ipsec_del, 201 ipf_p_dns_inout, ipf_p_dns_inout, ipf_p_dns_match, 202 ipf_p_dns_ctl, NULL, NULL, NULL }, 203 #endif 204 #ifdef IPF_PPTP_PROXY 205 { NULL, NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 0, 206 ipf_p_pptp_main_load, ipf_p_pptp_main_unload, 207 NULL, NULL, 208 NULL, NULL, 209 ipf_p_pptp_new, ipf_p_pptp_del, 210 ipf_p_pptp_inout, ipf_p_pptp_inout, NULL, 211 NULL, NULL, NULL, NULL }, 212 #endif 213 #ifdef IPF_RPCB_PROXY 214 # ifndef _KERNEL 215 { NULL, NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 0, 216 NULL, NULL, 217 NULL, NULL, 218 NULL, NULL, 219 ipf_p_rpcb_new, ipf_p_rpcb_del, 220 ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, 221 NULL, NULL, NULL, NULL }, 222 # endif 223 { NULL, NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 0, 224 ipf_p_rpcb_main_load, ipf_p_rpcb_main_unload, 225 NULL, NULL, 226 NULL, NULL, 227 ipf_p_rpcb_new, ipf_p_rpcb_del, 228 ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, 229 NULL, NULL, NULL, NULL }, 230 #endif 231 { NULL, NULL, "", '\0', 0, 0, 0, 232 NULL, NULL, 233 NULL, NULL, 234 NULL, NULL, 235 NULL, NULL, 236 NULL, NULL, NULL, 237 NULL, NULL, NULL, NULL } 238 }; 239 240 241 /* ------------------------------------------------------------------------ */ 242 /* Function: ipf_proxy_main_load */ 243 /* Returns: int - 0 == success, else failure. */ 244 /* Parameters: Nil */ 245 /* */ 246 /* Initialise hook for kernel application proxies. */ 247 /* Call the initialise routine for all the compiled in kernel proxies. */ 248 /* ------------------------------------------------------------------------ */ 249 int 250 ipf_proxy_main_load(void) 251 { 252 aproxy_t *ap; 253 254 for (ap = ips_proxies; ap->apr_p; ap++) { 255 if (ap->apr_load != NULL) 256 (*ap->apr_load)(); 257 } 258 return (0); 259 } 260 261 262 /* ------------------------------------------------------------------------ */ 263 /* Function: ipf_proxy_main_unload */ 264 /* Returns: int - 0 == success, else failure. */ 265 /* Parameters: Nil */ 266 /* */ 267 /* Unload hook for kernel application proxies. */ 268 /* Call the finialise routine for all the compiled in kernel proxies. */ 269 /* ------------------------------------------------------------------------ */ 270 int 271 ipf_proxy_main_unload(void) 272 { 273 aproxy_t *ap; 274 275 for (ap = ips_proxies; ap->apr_p; ap++) 276 if (ap->apr_unload != NULL) 277 (*ap->apr_unload)(); 278 for (ap = ap_proxylist; ap; ap = ap->apr_next) 279 if (ap->apr_unload != NULL) 280 (*ap->apr_unload)(); 281 282 return (0); 283 } 284 285 286 /* ------------------------------------------------------------------------ */ 287 /* Function: ipf_proxy_soft_create */ 288 /* Returns: void * - */ 289 /* Parameters: softc(I) - pointer to soft context main structure */ 290 /* */ 291 /* Build the structure to hold all of the run time data to support proxies. */ 292 /* ------------------------------------------------------------------------ */ 293 void * 294 ipf_proxy_soft_create(ipf_main_softc_t *softc) 295 { 296 ipf_proxy_softc_t *softp; 297 aproxy_t *last; 298 aproxy_t *apn; 299 aproxy_t *ap; 300 301 KMALLOC(softp, ipf_proxy_softc_t *); 302 if (softp == NULL) 303 return (softp); 304 305 bzero((char *)softp, sizeof(*softp)); 306 307 #if defined(_KERNEL) 308 softp->ips_proxy_debug = 0; 309 #else 310 softp->ips_proxy_debug = 2; 311 #endif 312 softp->ips_proxy_session_size = AP_SESS_SIZE; 313 314 softp->ipf_proxy_tune = ipf_tune_array_copy(softp, 315 sizeof(ipf_proxy_tuneables), 316 ipf_proxy_tuneables); 317 if (softp->ipf_proxy_tune == NULL) { 318 ipf_proxy_soft_destroy(softc, softp); 319 return (NULL); 320 } 321 if (ipf_tune_array_link(softc, softp->ipf_proxy_tune) == -1) { 322 ipf_proxy_soft_destroy(softc, softp); 323 return (NULL); 324 } 325 326 last = NULL; 327 for (ap = ips_proxies; ap->apr_p; ap++) { 328 apn = ipf_proxy_create_clone(softc, ap); 329 if (apn == NULL) 330 goto failed; 331 if (last != NULL) 332 last->apr_next = apn; 333 else 334 softp->ips_proxies = apn; 335 last = apn; 336 } 337 for (ap = ips_proxies; ap != NULL; ap = ap->apr_next) { 338 apn = ipf_proxy_create_clone(softc, ap); 339 if (apn == NULL) 340 goto failed; 341 if (last != NULL) 342 last->apr_next = apn; 343 else 344 softp->ips_proxies = apn; 345 last = apn; 346 } 347 348 return (softp); 349 failed: 350 ipf_proxy_soft_destroy(softc, softp); 351 return (NULL); 352 } 353 354 355 /* ------------------------------------------------------------------------ */ 356 /* Function: ipf_proxy_soft_create */ 357 /* Returns: void * - */ 358 /* Parameters: softc(I) - pointer to soft context main structure */ 359 /* orig(I) - pointer to proxy definition to copy */ 360 /* */ 361 /* This function clones a proxy definition given by orig and returns a */ 362 /* a pointer to that copy. */ 363 /* ------------------------------------------------------------------------ */ 364 static aproxy_t * 365 ipf_proxy_create_clone(ipf_main_softc_t *softc, aproxy_t *orig) 366 { 367 aproxy_t *apn; 368 369 KMALLOC(apn, aproxy_t *); 370 if (apn == NULL) 371 return (NULL); 372 373 bcopy((char *)orig, (char *)apn, sizeof(*apn)); 374 apn->apr_next = NULL; 375 apn->apr_soft = NULL; 376 377 if (apn->apr_create != NULL) { 378 apn->apr_soft = (*apn->apr_create)(softc); 379 if (apn->apr_soft == NULL) { 380 KFREE(apn); 381 return (NULL); 382 } 383 } 384 385 apn->apr_parent = orig; 386 orig->apr_clones++; 387 388 return (apn); 389 } 390 391 392 /* ------------------------------------------------------------------------ */ 393 /* Function: ipf_proxy_soft_create */ 394 /* Returns: int - 0 == success, else failure. */ 395 /* Parameters: softc(I) - pointer to soft context main structure */ 396 /* arg(I) - pointer to proxy contect data */ 397 /* */ 398 /* Initialise the proxy context and walk through each of the proxies and */ 399 /* call its initialisation function. This allows for proxies to do any */ 400 /* local setup prior to actual use. */ 401 /* ------------------------------------------------------------------------ */ 402 int 403 ipf_proxy_soft_init(ipf_main_softc_t *softc, void *arg) 404 { 405 ipf_proxy_softc_t *softp; 406 aproxy_t *ap; 407 u_int size; 408 int err; 409 410 softp = arg; 411 size = softp->ips_proxy_session_size * sizeof(ap_session_t *); 412 413 KMALLOCS(softp->ips_sess_tab, ap_session_t **, size); 414 415 if (softp->ips_sess_tab == NULL) 416 return (-1); 417 418 bzero(softp->ips_sess_tab, size); 419 420 for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { 421 if (ap->apr_init != NULL) { 422 err = (*ap->apr_init)(softc, ap->apr_soft); 423 if (err != 0) 424 return (-2); 425 } 426 } 427 softp->ips_init_run = 1; 428 429 return (0); 430 } 431 432 433 /* ------------------------------------------------------------------------ */ 434 /* Function: ipf_proxy_soft_create */ 435 /* Returns: int - 0 == success, else failure. */ 436 /* Parameters: softc(I) - pointer to soft context main structure */ 437 /* arg(I) - pointer to proxy contect data */ 438 /* */ 439 /* This function should always succeed. It is responsible for ensuring that */ 440 /* the proxy context can be safely called when ipf_proxy_soft_destroy is */ 441 /* called and suring all of the proxies have similarly been instructed. */ 442 /* ------------------------------------------------------------------------ */ 443 int 444 ipf_proxy_soft_fini(ipf_main_softc_t *softc, void *arg) 445 { 446 ipf_proxy_softc_t *softp = arg; 447 aproxy_t *ap; 448 449 for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { 450 if (ap->apr_fini != NULL) { 451 (*ap->apr_fini)(softc, ap->apr_soft); 452 } 453 } 454 455 if (softp->ips_sess_tab != NULL) { 456 KFREES(softp->ips_sess_tab, 457 softp->ips_proxy_session_size * sizeof(ap_session_t *)); 458 softp->ips_sess_tab = NULL; 459 } 460 softp->ips_init_run = 0; 461 462 return (0); 463 } 464 465 466 /* ------------------------------------------------------------------------ */ 467 /* Function: ipf_proxy_soft_destroy */ 468 /* Returns: Nil */ 469 /* Parameters: softc(I) - pointer to soft context main structure */ 470 /* arg(I) - pointer to proxy contect data */ 471 /* */ 472 /* Free up all of the local data structures allocated during creation. */ 473 /* ------------------------------------------------------------------------ */ 474 void 475 ipf_proxy_soft_destroy(ipf_main_softc_t *softc, void *arg) 476 { 477 ipf_proxy_softc_t *softp = arg; 478 aproxy_t *ap; 479 480 while ((ap = softp->ips_proxies) != NULL) { 481 softp->ips_proxies = ap->apr_next; 482 if (ap->apr_destroy != NULL) 483 (*ap->apr_destroy)(softc, ap->apr_soft); 484 ap->apr_parent->apr_clones--; 485 KFREE(ap); 486 } 487 488 if (softp->ipf_proxy_tune != NULL) { 489 ipf_tune_array_unlink(softc, softp->ipf_proxy_tune); 490 KFREES(softp->ipf_proxy_tune, sizeof(ipf_proxy_tuneables)); 491 softp->ipf_proxy_tune = NULL; 492 } 493 494 KFREE(softp); 495 } 496 497 498 /* ------------------------------------------------------------------------ */ 499 /* Function: ipf_proxy_flush */ 500 /* Returns: Nil */ 501 /* Parameters: arg(I) - pointer to proxy contect data */ 502 /* how(I) - indicates the type of flush operation */ 503 /* */ 504 /* Walk through all of the proxies and pass on the flush command as either */ 505 /* a flush or a clear. */ 506 /* ------------------------------------------------------------------------ */ 507 void 508 ipf_proxy_flush(void *arg, int how) 509 { 510 ipf_proxy_softc_t *softp = arg; 511 aproxy_t *ap; 512 513 switch (how) 514 { 515 case 0 : 516 for (ap = softp->ips_proxies; ap; ap = ap->apr_next) 517 if (ap->apr_flush != NULL) 518 (*ap->apr_flush)(ap, how); 519 break; 520 case 1 : 521 for (ap = softp->ips_proxies; ap; ap = ap->apr_next) 522 if (ap->apr_clear != NULL) 523 (*ap->apr_clear)(ap); 524 break; 525 default : 526 break; 527 } 528 } 529 530 531 /* ------------------------------------------------------------------------ */ 532 /* Function: ipf_proxy_add */ 533 /* Returns: int - 0 == success, else failure. */ 534 /* Parameters: ap(I) - pointer to proxy structure */ 535 /* */ 536 /* Dynamically add a new kernel proxy. Ensure that it is unique in the */ 537 /* collection compiled in and dynamically added. */ 538 /* ------------------------------------------------------------------------ */ 539 int 540 ipf_proxy_add(void *arg, aproxy_t *ap) 541 { 542 ipf_proxy_softc_t *softp = arg; 543 544 aproxy_t *a; 545 546 for (a = ips_proxies; a->apr_p; a++) 547 if ((a->apr_p == ap->apr_p) && 548 !strncmp(a->apr_label, ap->apr_label, 549 sizeof(ap->apr_label))) { 550 if (softp->ips_proxy_debug & 0x01) 551 printf("ipf_proxy_add: %s/%d present (B)\n", 552 a->apr_label, a->apr_p); 553 return (-1); 554 } 555 556 for (a = ap_proxylist; (a != NULL); a = a->apr_next) 557 if ((a->apr_p == ap->apr_p) && 558 !strncmp(a->apr_label, ap->apr_label, 559 sizeof(ap->apr_label))) { 560 if (softp->ips_proxy_debug & 0x01) 561 printf("ipf_proxy_add: %s/%d present (D)\n", 562 a->apr_label, a->apr_p); 563 return (-1); 564 } 565 ap->apr_next = ap_proxylist; 566 ap_proxylist = ap; 567 if (ap->apr_load != NULL) 568 (*ap->apr_load)(); 569 return (0); 570 } 571 572 573 /* ------------------------------------------------------------------------ */ 574 /* Function: ipf_proxy_ctl */ 575 /* Returns: int - 0 == success, else error */ 576 /* Parameters: softc(I) - pointer to soft context main structure */ 577 /* arg(I) - pointer to proxy context */ 578 /* ctl(I) - pointer to proxy control structure */ 579 /* */ 580 /* Check to see if the proxy this control request has come through for */ 581 /* exists, and if it does and it has a control function then invoke that */ 582 /* control function. */ 583 /* ------------------------------------------------------------------------ */ 584 int 585 ipf_proxy_ctl(ipf_main_softc_t *softc, void *arg, ap_ctl_t *ctl) 586 { 587 ipf_proxy_softc_t *softp = arg; 588 aproxy_t *a; 589 int error; 590 591 a = ipf_proxy_lookup(arg, ctl->apc_p, ctl->apc_label); 592 if (a == NULL) { 593 if (softp->ips_proxy_debug & 0x01) 594 printf("ipf_proxy_ctl: can't find %s/%d\n", 595 ctl->apc_label, ctl->apc_p); 596 IPFERROR(80001); 597 error = ESRCH; 598 } else if (a->apr_ctl == NULL) { 599 if (softp->ips_proxy_debug & 0x01) 600 printf("ipf_proxy_ctl: no ctl function for %s/%d\n", 601 ctl->apc_label, ctl->apc_p); 602 IPFERROR(80002); 603 error = ENXIO; 604 } else { 605 error = (*a->apr_ctl)(softc, a->apr_soft, ctl); 606 if ((error != 0) && (softp->ips_proxy_debug & 0x02)) 607 printf("ipf_proxy_ctl: %s/%d ctl error %d\n", 608 a->apr_label, a->apr_p, error); 609 } 610 return (error); 611 } 612 613 614 /* ------------------------------------------------------------------------ */ 615 /* Function: ipf_proxy_del */ 616 /* Returns: int - 0 == success, else failure. */ 617 /* Parameters: ap(I) - pointer to proxy structure */ 618 /* */ 619 /* Delete a proxy that has been added dynamically from those available. */ 620 /* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 */ 621 /* if it cannot be matched. */ 622 /* ------------------------------------------------------------------------ */ 623 int 624 ipf_proxy_del(aproxy_t *ap) 625 { 626 aproxy_t *a, **app; 627 628 for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) { 629 if (a == ap) { 630 a->apr_flags |= APR_DELETE; 631 if (ap->apr_ref == 0 && ap->apr_clones == 0) { 632 *app = a->apr_next; 633 return (0); 634 } 635 return (1); 636 } 637 } 638 639 return (-1); 640 } 641 642 643 /* ------------------------------------------------------------------------ */ 644 /* Function: ipf_proxy_ok */ 645 /* Returns: int - 1 == good match else not. */ 646 /* Parameters: fin(I) - pointer to packet information */ 647 /* tcp(I) - pointer to TCP/UDP header */ 648 /* nat(I) - pointer to current NAT session */ 649 /* */ 650 /* This function extends the NAT matching to ensure that a packet that has */ 651 /* arrived matches the proxy information attached to the NAT rule. Notably, */ 652 /* if the proxy is scheduled to be deleted then packets will not match the */ 653 /* rule even if the rule is still active. */ 654 /* ------------------------------------------------------------------------ */ 655 int 656 ipf_proxy_ok(fr_info_t *fin, tcphdr_t *tcp, ipnat_t *np) 657 { 658 aproxy_t *apr = np->in_apr; 659 u_short dport = np->in_odport; 660 661 if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || 662 (fin->fin_p != apr->apr_p)) 663 return (0); 664 if ((tcp == NULL) && dport) 665 return (0); 666 return (1); 667 } 668 669 670 /* ------------------------------------------------------------------------ */ 671 /* Function: ipf_proxy_ioctl */ 672 /* Returns: int - 0 == success, else error */ 673 /* Parameters: softc(I) - pointer to soft context main structure */ 674 /* data(I) - pointer to ioctl data */ 675 /* cmd(I) - ioctl command */ 676 /* mode(I) - mode bits for device */ 677 /* ctx(I) - pointer to context information */ 678 /* */ 679 /* ------------------------------------------------------------------------ */ 680 int 681 ipf_proxy_ioctl(ipf_main_softc_t *softc, caddr_t data, ioctlcmd_t cmd, 682 int mode, void *ctx) 683 { 684 ap_ctl_t ctl; 685 caddr_t ptr; 686 int error; 687 688 mode = mode; /* LINT */ 689 690 switch (cmd) 691 { 692 case SIOCPROXY : 693 error = ipf_inobj(softc, data, NULL, &ctl, IPFOBJ_PROXYCTL); 694 if (error != 0) { 695 return (error); 696 } 697 ptr = NULL; 698 699 if (ctl.apc_dsize > 0) { 700 KMALLOCS(ptr, caddr_t, ctl.apc_dsize); 701 if (ptr == NULL) { 702 IPFERROR(80003); 703 error = ENOMEM; 704 } else { 705 error = copyinptr(softc, ctl.apc_data, ptr, 706 ctl.apc_dsize); 707 if (error == 0) 708 ctl.apc_data = ptr; 709 } 710 } else { 711 ctl.apc_data = NULL; 712 error = 0; 713 } 714 715 if (error == 0) 716 error = ipf_proxy_ctl(softc, softc->ipf_proxy_soft, 717 &ctl); 718 719 if ((error != 0) && (ptr != NULL)) { 720 KFREES(ptr, ctl.apc_dsize); 721 } 722 break; 723 724 default : 725 IPFERROR(80004); 726 error = EINVAL; 727 } 728 return (error); 729 } 730 731 732 /* ------------------------------------------------------------------------ */ 733 /* Function: ipf_proxy_match */ 734 /* Returns: int - 0 == success, else error */ 735 /* Parameters: fin(I) - pointer to packet information */ 736 /* nat(I) - pointer to current NAT session */ 737 /* */ 738 /* If a proxy has a match function, call that to do extended packet */ 739 /* matching. Whilst other parts of the NAT code are rather lenient when it */ 740 /* comes to the quality of the packet that it will transform, the proxy */ 741 /* matching is not because they need to work with data, not just headers. */ 742 /* ------------------------------------------------------------------------ */ 743 int 744 ipf_proxy_match(fr_info_t *fin, nat_t *nat) 745 { 746 ipf_main_softc_t *softc = fin->fin_main_soft; 747 ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 748 aproxy_t *apr; 749 ipnat_t *ipn; 750 int result; 751 752 ipn = nat->nat_ptr; 753 if (softp->ips_proxy_debug & 0x04) 754 printf("ipf_proxy_match(%lx,%lx) aps %lx ptr %lx\n", 755 (u_long)fin, (u_long)nat, (u_long)nat->nat_aps, 756 (u_long)ipn); 757 758 if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) { 759 if (softp->ips_proxy_debug & 0x08) 760 printf("ipf_proxy_match: flx 0x%x (BAD|SHORT)\n", 761 fin->fin_flx); 762 return (-1); 763 } 764 765 apr = ipn->in_apr; 766 if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) { 767 if (softp->ips_proxy_debug & 0x08) 768 printf("ipf_proxy_match:apr %lx apr_flags 0x%x\n", 769 (u_long)apr, apr ? apr->apr_flags : 0); 770 return (-1); 771 } 772 773 if (apr->apr_match != NULL) { 774 result = (*apr->apr_match)(fin, nat->nat_aps, nat); 775 if (result != 0) { 776 if (softp->ips_proxy_debug & 0x08) 777 printf("ipf_proxy_match: result %d\n", result); 778 return (-1); 779 } 780 } 781 return (0); 782 } 783 784 785 /* ------------------------------------------------------------------------ */ 786 /* Function: ipf_proxy_new */ 787 /* Returns: int - 0 == success, else error */ 788 /* Parameters: fin(I) - pointer to packet information */ 789 /* nat(I) - pointer to current NAT session */ 790 /* */ 791 /* Allocate a new application proxy structure and fill it in with the */ 792 /* relevant details. call the init function once complete, prior to */ 793 /* returning. */ 794 /* ------------------------------------------------------------------------ */ 795 int 796 ipf_proxy_new(fr_info_t *fin, nat_t *nat) 797 { 798 ipf_main_softc_t *softc = fin->fin_main_soft; 799 ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 800 register ap_session_t *aps; 801 aproxy_t *apr; 802 803 if (softp->ips_proxy_debug & 0x04) 804 printf("ipf_proxy_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); 805 806 if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) { 807 if (softp->ips_proxy_debug & 0x08) 808 printf("ipf_proxy_new: nat_ptr %lx nat_aps %lx\n", 809 (u_long)nat->nat_ptr, (u_long)nat->nat_aps); 810 return (-1); 811 } 812 813 apr = nat->nat_ptr->in_apr; 814 815 if ((apr->apr_flags & APR_DELETE) || 816 (fin->fin_p != apr->apr_p)) { 817 if (softp->ips_proxy_debug & 0x08) 818 printf("ipf_proxy_new: apr_flags 0x%x p %d/%d\n", 819 apr->apr_flags, fin->fin_p, apr->apr_p); 820 return (-1); 821 } 822 823 KMALLOC(aps, ap_session_t *); 824 if (!aps) { 825 if (softp->ips_proxy_debug & 0x08) 826 printf("ipf_proxy_new: malloc failed (%lu)\n", 827 (u_long)sizeof(ap_session_t)); 828 return (-1); 829 } 830 831 bzero((char *)aps, sizeof(*aps)); 832 aps->aps_data = NULL; 833 aps->aps_apr = apr; 834 aps->aps_psiz = 0; 835 if (apr->apr_new != NULL) 836 if ((*apr->apr_new)(apr->apr_soft, fin, aps, nat) == -1) { 837 if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) { 838 KFREES(aps->aps_data, aps->aps_psiz); 839 } 840 KFREE(aps); 841 if (softp->ips_proxy_debug & 0x08) 842 printf("ipf_proxy_new: new(%lx) failed\n", 843 (u_long)apr->apr_new); 844 return (-1); 845 } 846 aps->aps_nat = nat; 847 aps->aps_next = softp->ips_sess_list; 848 softp->ips_sess_list = aps; 849 nat->nat_aps = aps; 850 851 return (0); 852 } 853 854 855 /* ------------------------------------------------------------------------ */ 856 /* Function: ipf_proxy_check */ 857 /* Returns: int - -1 == error, 1 == success */ 858 /* Parameters: fin(I) - pointer to packet information */ 859 /* nat(I) - pointer to current NAT session */ 860 /* */ 861 /* Check to see if a packet should be passed through an active proxy */ 862 /* routine if one has been setup for it. We don't need to check the */ 863 /* checksum here if IPFILTER_CKSUM is defined because if it is, a failed */ 864 /* check causes FI_BAD to be set. */ 865 /* ------------------------------------------------------------------------ */ 866 int 867 ipf_proxy_check(fr_info_t *fin, nat_t *nat) 868 { 869 ipf_main_softc_t *softc = fin->fin_main_soft; 870 ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 871 #if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) 872 mb_t *m; 873 #endif 874 tcphdr_t *tcp = NULL; 875 udphdr_t *udp = NULL; 876 ap_session_t *aps; 877 aproxy_t *apr; 878 short adjlen; 879 int dosum; 880 ip_t *ip; 881 short rv; 882 int err; 883 #if !defined(_KERNEL) || SOLARIS || defined(__FreeBSD__) 884 u_32_t s1, s2, sd; 885 #endif 886 887 if (fin->fin_flx & FI_BAD) { 888 if (softp->ips_proxy_debug & 0x08) 889 printf("ipf_proxy_check: flx 0x%x (BAD)\n", 890 fin->fin_flx); 891 return (-1); 892 } 893 894 #ifndef IPFILTER_CKSUM 895 if ((fin->fin_out == 0) && (ipf_checkl4sum(fin) == -1)) { 896 if (softp->ips_proxy_debug & 0x08) 897 printf("ipf_proxy_check: l4 checksum failure %d\n", 898 fin->fin_p); 899 if (fin->fin_p == IPPROTO_TCP) 900 softc->ipf_stats[fin->fin_out].fr_tcpbad++; 901 return (-1); 902 } 903 #endif 904 905 aps = nat->nat_aps; 906 if (aps != NULL) { 907 /* 908 * If there is data in this packet to be proxied then try and 909 * get it all into the one buffer, else drop it. 910 */ 911 #if SOLARIS || defined(HAVE_M_PULLDOWN) 912 if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE)) 913 if (ipf_coalesce(fin) == -1) { 914 if (softp->ips_proxy_debug & 0x08) 915 printf("ipf_proxy_check: %s %x\n", 916 "coalesce failed", fin->fin_flx); 917 return (-1); 918 } 919 #endif 920 ip = fin->fin_ip; 921 if (fin->fin_cksum > FI_CK_SUMOK) 922 dosum = 0; 923 else 924 dosum = 1; 925 926 switch (fin->fin_p) 927 { 928 case IPPROTO_TCP : 929 tcp = (tcphdr_t *)fin->fin_dp; 930 #if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) 931 m = fin->fin_qfm; 932 if (dohwcksum && (m->b_ick_flag == ICK_VALID)) 933 dosum = 0; 934 #endif 935 break; 936 case IPPROTO_UDP : 937 udp = (udphdr_t *)fin->fin_dp; 938 break; 939 default : 940 break; 941 } 942 943 apr = aps->aps_apr; 944 err = 0; 945 if (fin->fin_out != 0) { 946 if (apr->apr_outpkt != NULL) 947 err = (*apr->apr_outpkt)(apr->apr_soft, fin, 948 aps, nat); 949 } else { 950 if (apr->apr_inpkt != NULL) 951 err = (*apr->apr_inpkt)(apr->apr_soft, fin, 952 aps, nat); 953 } 954 955 rv = APR_EXIT(err); 956 if (((softp->ips_proxy_debug & 0x08) && (rv != 0)) || 957 (softp->ips_proxy_debug & 0x04)) 958 printf("ipf_proxy_check: out %d err %x rv %d\n", 959 fin->fin_out, err, rv); 960 if (rv == 1) 961 return (-1); 962 963 if (rv == 2) { 964 ipf_proxy_deref(apr); 965 nat->nat_aps = NULL; 966 return (-1); 967 } 968 969 /* 970 * If err != 0 then the data size of the packet has changed 971 * so we need to recalculate the header checksums for the 972 * packet. 973 */ 974 adjlen = APR_INC(err); 975 #if !defined(_KERNEL) || SOLARIS || defined(__FreeBSD__) 976 s1 = LONG_SUM(fin->fin_plen - adjlen); 977 s2 = LONG_SUM(fin->fin_plen); 978 CALC_SUMD(s1, s2, sd); 979 if ((err != 0) && (fin->fin_cksum < FI_CK_L4PART) && 980 fin->fin_v == 4) 981 ipf_fix_outcksum(0, &ip->ip_sum, sd, 0); 982 #endif 983 if (fin->fin_flx & FI_DOCKSUM) 984 dosum = 1; 985 986 /* 987 * For TCP packets, we may need to adjust the sequence and 988 * acknowledgement numbers to reflect changes in size of the 989 * data stream. 990 * 991 * For both TCP and UDP, recalculate the layer 4 checksum, 992 * regardless, as we can't tell (here) if data has been 993 * changed or not. 994 */ 995 if (tcp != NULL) { 996 err = ipf_proxy_fixseqack(fin, ip, aps, adjlen); 997 if (fin->fin_cksum == FI_CK_L4PART) { 998 u_short sum = ntohs(tcp->th_sum); 999 sum += adjlen; 1000 tcp->th_sum = htons(sum); 1001 } else if (fin->fin_cksum < FI_CK_L4PART) { 1002 tcp->th_sum = fr_cksum(fin, ip, 1003 IPPROTO_TCP, tcp); 1004 } 1005 } else if ((udp != NULL) && (udp->uh_sum != 0)) { 1006 if (fin->fin_cksum == FI_CK_L4PART) { 1007 u_short sum = ntohs(udp->uh_sum); 1008 sum += adjlen; 1009 udp->uh_sum = htons(sum); 1010 } else if (dosum) { 1011 udp->uh_sum = fr_cksum(fin, ip, 1012 IPPROTO_UDP, udp); 1013 } 1014 } 1015 aps->aps_bytes += fin->fin_plen; 1016 aps->aps_pkts++; 1017 } 1018 return (1); 1019 } 1020 1021 1022 /* ------------------------------------------------------------------------ */ 1023 /* Function: ipf_proxy_lookup */ 1024 /* Returns: int - -1 == error, 0 == success */ 1025 /* Parameters: arg(I) - pointer to proxy context information */ 1026 /* pr(I) - protocol number for proxy */ 1027 /* name(I) - proxy name */ 1028 /* */ 1029 /* Search for a proxy by the protocol being used and by its name. */ 1030 /* ------------------------------------------------------------------------ */ 1031 aproxy_t * 1032 ipf_proxy_lookup(void *arg, u_int pr, char *name) 1033 { 1034 ipf_proxy_softc_t *softp = arg; 1035 aproxy_t *ap; 1036 1037 if (softp->ips_proxy_debug & 0x04) 1038 printf("ipf_proxy_lookup(%d,%s)\n", pr, name); 1039 1040 for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) 1041 if ((ap->apr_p == pr) && 1042 !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { 1043 ap->apr_ref++; 1044 return (ap); 1045 } 1046 1047 if (softp->ips_proxy_debug & 0x08) 1048 printf("ipf_proxy_lookup: failed for %d/%s\n", pr, name); 1049 return (NULL); 1050 } 1051 1052 1053 /* ------------------------------------------------------------------------ */ 1054 /* Function: ipf_proxy_deref */ 1055 /* Returns: Nil */ 1056 /* Parameters: ap(I) - pointer to proxy structure */ 1057 /* */ 1058 /* Drop the reference counter associated with the proxy. */ 1059 /* ------------------------------------------------------------------------ */ 1060 void 1061 ipf_proxy_deref(aproxy_t *ap) 1062 { 1063 ap->apr_ref--; 1064 } 1065 1066 1067 /* ------------------------------------------------------------------------ */ 1068 /* Function: ipf_proxy_free */ 1069 /* Returns: Nil */ 1070 /* Parameters: softc(I) - pointer to soft context main structure */ 1071 /* aps(I) - pointer to current proxy session */ 1072 /* Locks Held: ipf_nat_new, ipf_nat(W) */ 1073 /* */ 1074 /* Free up proxy session information allocated to be used with a NAT */ 1075 /* session. */ 1076 /* ------------------------------------------------------------------------ */ 1077 void 1078 ipf_proxy_free(ipf_main_softc_t *softc, ap_session_t *aps) 1079 { 1080 ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 1081 ap_session_t *a, **ap; 1082 aproxy_t *apr; 1083 1084 if (!aps) 1085 return; 1086 1087 for (ap = &softp->ips_sess_list; ((a = *ap) != NULL); ap = &a->aps_next) 1088 if (a == aps) { 1089 *ap = a->aps_next; 1090 break; 1091 } 1092 1093 apr = aps->aps_apr; 1094 if ((apr != NULL) && (apr->apr_del != NULL)) 1095 (*apr->apr_del)(softc, aps); 1096 1097 if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) 1098 KFREES(aps->aps_data, aps->aps_psiz); 1099 KFREE(aps); 1100 } 1101 1102 1103 /* ------------------------------------------------------------------------ */ 1104 /* Function: ipf_proxy_fixseqack */ 1105 /* Returns: int - 2 if TCP ack/seq is changed, else 0 */ 1106 /* Parameters: fin(I) - pointer to packet information */ 1107 /* ip(I) - pointer to IP header */ 1108 /* nat(I) - pointer to current NAT session */ 1109 /* inc(I) - delta to apply to TCP sequence numbering */ 1110 /* */ 1111 /* Adjust the TCP sequence/acknowledge numbers in the TCP header based on */ 1112 /* whether or not the new header is past the point at which an adjustment */ 1113 /* occurred. This might happen because of (say) an FTP string being changed */ 1114 /* and the new string being a different length to the old. */ 1115 /* ------------------------------------------------------------------------ */ 1116 static int 1117 ipf_proxy_fixseqack(fr_info_t *fin, ip_t *ip, ap_session_t *aps, int inc) 1118 { 1119 ipf_main_softc_t *softc = fin->fin_main_soft; 1120 ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 1121 int sel, ch = 0, out, nlen; 1122 u_32_t seq1, seq2; 1123 tcphdr_t *tcp; 1124 short inc2; 1125 1126 tcp = (tcphdr_t *)fin->fin_dp; 1127 out = fin->fin_out; 1128 /* 1129 * ip_len has already been adjusted by 'inc'. 1130 */ 1131 nlen = fin->fin_dlen; 1132 nlen -= (TCP_OFF(tcp) << 2); 1133 1134 inc2 = inc; 1135 inc = (int)inc2; 1136 1137 if (out != 0) { 1138 seq1 = (u_32_t)ntohl(tcp->th_seq); 1139 sel = aps->aps_sel[out]; 1140 1141 /* switch to other set ? */ 1142 if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 1143 (seq1 > aps->aps_seqmin[!sel])) { 1144 if (softp->ips_proxy_debug & 0x10) 1145 printf("proxy out switch set seq %d -> %d %x > %x\n", 1146 sel, !sel, seq1, 1147 aps->aps_seqmin[!sel]); 1148 sel = aps->aps_sel[out] = !sel; 1149 } 1150 1151 if (aps->aps_seqoff[sel]) { 1152 seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel]; 1153 if (seq1 > seq2) { 1154 seq2 = aps->aps_seqoff[sel]; 1155 seq1 += seq2; 1156 tcp->th_seq = htonl(seq1); 1157 ch = 1; 1158 } 1159 } 1160 1161 if (inc && (seq1 > aps->aps_seqmin[!sel])) { 1162 aps->aps_seqmin[sel] = seq1 + nlen - 1; 1163 aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc; 1164 if (softp->ips_proxy_debug & 0x10) 1165 printf("proxy seq set %d at %x to %d + %d\n", 1166 sel, aps->aps_seqmin[sel], 1167 aps->aps_seqoff[sel], inc); 1168 } 1169 1170 /***/ 1171 1172 seq1 = ntohl(tcp->th_ack); 1173 sel = aps->aps_sel[1 - out]; 1174 1175 /* switch to other set ? */ 1176 if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 1177 (seq1 > aps->aps_ackmin[!sel])) { 1178 if (softp->ips_proxy_debug & 0x10) 1179 printf("proxy out switch set ack %d -> %d %x > %x\n", 1180 sel, !sel, seq1, 1181 aps->aps_ackmin[!sel]); 1182 sel = aps->aps_sel[1 - out] = !sel; 1183 } 1184 1185 if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) { 1186 seq2 = aps->aps_ackoff[sel]; 1187 tcp->th_ack = htonl(seq1 - seq2); 1188 ch = 1; 1189 } 1190 } else { 1191 seq1 = ntohl(tcp->th_seq); 1192 sel = aps->aps_sel[out]; 1193 1194 /* switch to other set ? */ 1195 if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 1196 (seq1 > aps->aps_ackmin[!sel])) { 1197 if (softp->ips_proxy_debug & 0x10) 1198 printf("proxy in switch set ack %d -> %d %x > %x\n", 1199 sel, !sel, seq1, aps->aps_ackmin[!sel]); 1200 sel = aps->aps_sel[out] = !sel; 1201 } 1202 1203 if (aps->aps_ackoff[sel]) { 1204 seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel]; 1205 if (seq1 > seq2) { 1206 seq2 = aps->aps_ackoff[sel]; 1207 seq1 += seq2; 1208 tcp->th_seq = htonl(seq1); 1209 ch = 1; 1210 } 1211 } 1212 1213 if (inc && (seq1 > aps->aps_ackmin[!sel])) { 1214 aps->aps_ackmin[!sel] = seq1 + nlen - 1; 1215 aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; 1216 1217 if (softp->ips_proxy_debug & 0x10) 1218 printf("proxy ack set %d at %x to %d + %d\n", 1219 !sel, aps->aps_seqmin[!sel], 1220 aps->aps_seqoff[sel], inc); 1221 } 1222 1223 /***/ 1224 1225 seq1 = ntohl(tcp->th_ack); 1226 sel = aps->aps_sel[1 - out]; 1227 1228 /* switch to other set ? */ 1229 if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 1230 (seq1 > aps->aps_seqmin[!sel])) { 1231 if (softp->ips_proxy_debug & 0x10) 1232 printf("proxy in switch set seq %d -> %d %x > %x\n", 1233 sel, !sel, seq1, aps->aps_seqmin[!sel]); 1234 sel = aps->aps_sel[1 - out] = !sel; 1235 } 1236 1237 if (aps->aps_seqoff[sel] != 0) { 1238 if (softp->ips_proxy_debug & 0x10) 1239 printf("sel %d seqoff %d seq1 %x seqmin %x\n", 1240 sel, aps->aps_seqoff[sel], seq1, 1241 aps->aps_seqmin[sel]); 1242 if (seq1 > aps->aps_seqmin[sel]) { 1243 seq2 = aps->aps_seqoff[sel]; 1244 tcp->th_ack = htonl(seq1 - seq2); 1245 ch = 1; 1246 } 1247 } 1248 } 1249 1250 if (softp->ips_proxy_debug & 0x10) 1251 printf("ipf_proxy_fixseqack: seq %u ack %u\n", 1252 (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack)); 1253 return (ch ? 2 : 0); 1254 } 1255 1256 1257 /* ------------------------------------------------------------------------ */ 1258 /* Function: ipf_proxy_rule_rev */ 1259 /* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ 1260 /* Parameters: nat(I) - pointer to NAT session to create rule from */ 1261 /* */ 1262 /* This function creates a NAT rule that is based upon the reverse packet */ 1263 /* flow associated with this NAT session. Thus if this NAT session was */ 1264 /* created with a map rule then this function will create a rdr rule. */ 1265 /* Only address fields and network interfaces are assigned in this function */ 1266 /* and the address fields are formed such that an exact is required. If the */ 1267 /* original rule had a netmask, that is not replicated here not is it */ 1268 /* desired. The ultimate goal here is to create a NAT rule to support a NAT */ 1269 /* session being created that does not have a user configured rule. The */ 1270 /* classic example is supporting the FTP proxy, where a data channel needs */ 1271 /* to be setup, based on the addresses used for the control connection. In */ 1272 /* that case, this function is used to handle creating NAT rules to support */ 1273 /* data connections with the PORT and EPRT commands. */ 1274 /* ------------------------------------------------------------------------ */ 1275 ipnat_t * 1276 ipf_proxy_rule_rev(nat_t *nat) 1277 { 1278 ipnat_t *old; 1279 ipnat_t *ipn; 1280 int size; 1281 1282 old = nat->nat_ptr; 1283 size = old->in_size; 1284 1285 KMALLOCS(ipn, ipnat_t *, size); 1286 if (ipn == NULL) 1287 return (NULL); 1288 1289 bzero((char *)ipn, size); 1290 1291 ipn->in_use = 1; 1292 ipn->in_hits = 1; 1293 ipn->in_ippip = 1; 1294 ipn->in_apr = NULL; 1295 ipn->in_size = size; 1296 ipn->in_pr[0] = old->in_pr[1]; 1297 ipn->in_pr[1] = old->in_pr[0]; 1298 ipn->in_v[0] = old->in_v[1]; 1299 ipn->in_v[1] = old->in_v[0]; 1300 ipn->in_ifps[0] = old->in_ifps[1]; 1301 ipn->in_ifps[1] = old->in_ifps[0]; 1302 ipn->in_flags = (old->in_flags | IPN_PROXYRULE); 1303 1304 ipn->in_nsrcip6 = nat->nat_odst6; 1305 ipn->in_osrcip6 = nat->nat_ndst6; 1306 1307 if ((old->in_redir & NAT_REDIRECT) != 0) { 1308 ipn->in_redir = NAT_MAP; 1309 if (ipn->in_v[0] == 4) { 1310 ipn->in_snip = ntohl(nat->nat_odstaddr); 1311 ipn->in_dnip = ntohl(nat->nat_nsrcaddr); 1312 #ifdef USE_INET6 1313 } else { 1314 ipn->in_snip6 = nat->nat_odst6; 1315 ipn->in_dnip6 = nat->nat_nsrc6; 1316 #endif 1317 } 1318 ipn->in_ndstip6 = nat->nat_nsrc6; 1319 ipn->in_odstip6 = nat->nat_osrc6; 1320 } else { 1321 ipn->in_redir = NAT_REDIRECT; 1322 if (ipn->in_v[0] == 4) { 1323 ipn->in_snip = ntohl(nat->nat_odstaddr); 1324 ipn->in_dnip = ntohl(nat->nat_osrcaddr); 1325 #ifdef USE_INET6 1326 } else { 1327 ipn->in_snip6 = nat->nat_odst6; 1328 ipn->in_dnip6 = nat->nat_osrc6; 1329 #endif 1330 } 1331 ipn->in_ndstip6 = nat->nat_osrc6; 1332 ipn->in_odstip6 = nat->nat_nsrc6; 1333 } 1334 1335 IP6_SETONES(&ipn->in_osrcmsk6); 1336 IP6_SETONES(&ipn->in_nsrcmsk6); 1337 IP6_SETONES(&ipn->in_odstmsk6); 1338 IP6_SETONES(&ipn->in_ndstmsk6); 1339 1340 ipn->in_namelen = old->in_namelen; 1341 ipn->in_ifnames[0] = old->in_ifnames[1]; 1342 ipn->in_ifnames[1] = old->in_ifnames[0]; 1343 bcopy(old->in_names, ipn->in_names, ipn->in_namelen); 1344 MUTEX_INIT(&ipn->in_lock, "ipnat rev rule lock"); 1345 1346 return (ipn); 1347 } 1348 1349 1350 /* ------------------------------------------------------------------------ */ 1351 /* Function: ipf_proxy_rule_fwd */ 1352 /* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ 1353 /* Parameters: nat(I) - pointer to NAT session to create rule from */ 1354 /* */ 1355 /* The purpose and rationale of this function is much the same as the above */ 1356 /* function, ipf_proxy_rule_rev, except that a rule is created that matches */ 1357 /* the same direction as that of the existing NAT session. Thus if this NAT */ 1358 /* session was created with a map rule then this function will also create */ 1359 /* a data structure to represent a map rule. Whereas ipf_proxy_rule_rev is */ 1360 /* used to support PORT/EPRT, this function supports PASV/EPSV. */ 1361 /* ------------------------------------------------------------------------ */ 1362 ipnat_t * 1363 ipf_proxy_rule_fwd(nat_t *nat) 1364 { 1365 ipnat_t *old; 1366 ipnat_t *ipn; 1367 int size; 1368 1369 old = nat->nat_ptr; 1370 size = old->in_size; 1371 1372 KMALLOCS(ipn, ipnat_t *, size); 1373 if (ipn == NULL) 1374 return (NULL); 1375 1376 bzero((char *)ipn, size); 1377 1378 ipn->in_use = 1; 1379 ipn->in_hits = 1; 1380 ipn->in_ippip = 1; 1381 ipn->in_apr = NULL; 1382 ipn->in_size = size; 1383 ipn->in_pr[0] = old->in_pr[0]; 1384 ipn->in_pr[1] = old->in_pr[1]; 1385 ipn->in_v[0] = old->in_v[0]; 1386 ipn->in_v[1] = old->in_v[1]; 1387 ipn->in_ifps[0] = nat->nat_ifps[0]; 1388 ipn->in_ifps[1] = nat->nat_ifps[1]; 1389 ipn->in_flags = (old->in_flags | IPN_PROXYRULE); 1390 1391 ipn->in_nsrcip6 = nat->nat_nsrc6; 1392 ipn->in_osrcip6 = nat->nat_osrc6; 1393 ipn->in_ndstip6 = nat->nat_ndst6; 1394 ipn->in_odstip6 = nat->nat_odst6; 1395 ipn->in_redir = old->in_redir; 1396 1397 if (ipn->in_v[0] == 4) { 1398 ipn->in_snip = ntohl(nat->nat_nsrcaddr); 1399 ipn->in_dnip = ntohl(nat->nat_ndstaddr); 1400 #ifdef USE_INET6 1401 } else { 1402 ipn->in_snip6 = nat->nat_nsrc6; 1403 ipn->in_dnip6 = nat->nat_ndst6; 1404 #endif 1405 } 1406 1407 IP6_SETONES(&ipn->in_osrcmsk6); 1408 IP6_SETONES(&ipn->in_nsrcmsk6); 1409 IP6_SETONES(&ipn->in_odstmsk6); 1410 IP6_SETONES(&ipn->in_ndstmsk6); 1411 1412 ipn->in_namelen = old->in_namelen; 1413 ipn->in_ifnames[0] = old->in_ifnames[0]; 1414 ipn->in_ifnames[1] = old->in_ifnames[1]; 1415 bcopy(old->in_names, ipn->in_names, ipn->in_namelen); 1416 MUTEX_INIT(&ipn->in_lock, "ipnat fwd rule lock"); 1417 1418 return (ipn); 1419 } 1420