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