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