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