ip_proxy.c revision 255332
1145522Sdarrenr/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_proxy.c 255332 2013-09-06 23:11:19Z cy $ */ 2145522Sdarrenr 353642Sguido/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 553642Sguido * 680482Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 753642Sguido */ 8145522Sdarrenr#if defined(KERNEL) || defined(_KERNEL) 9145522Sdarrenr# undef KERNEL 10145522Sdarrenr# undef _KERNEL 11145522Sdarrenr# define KERNEL 1 12145522Sdarrenr# define _KERNEL 1 1353642Sguido#endif 1453642Sguido#include <sys/errno.h> 1553642Sguido#include <sys/types.h> 1653642Sguido#include <sys/param.h> 1753642Sguido#include <sys/time.h> 1853642Sguido#include <sys/file.h> 19153876Sguido#if !defined(AIX) 20153876Sguido# include <sys/fcntl.h> 21153876Sguido#endif 22145522Sdarrenr#if !defined(_KERNEL) && !defined(__KERNEL__) 2353642Sguido# include <stdio.h> 2453642Sguido# include <string.h> 2553642Sguido# include <stdlib.h> 26145522Sdarrenr# include <ctype.h> 27145522Sdarrenr# define _KERNEL 28145522Sdarrenr# ifdef __OpenBSD__ 29145522Sdarrenrstruct file; 30145522Sdarrenr# endif 31145522Sdarrenr# include <sys/uio.h> 32145522Sdarrenr# undef _KERNEL 3353642Sguido#endif 34145522Sdarrenr#if !defined(linux) 3553642Sguido# include <sys/protosw.h> 3653642Sguido#endif 3753642Sguido#include <sys/socket.h> 3853642Sguido#if defined(_KERNEL) 39145522Sdarrenr# if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \ 40153876Sguido !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \ 41153876Sguido !defined(AIX) 42145522Sdarrenr# include <sys/ctype.h> 4353642Sguido# endif 44145522Sdarrenr# include <sys/systm.h> 45145522Sdarrenr# if !defined(__SVR4) && !defined(__svr4__) 4653642Sguido# include <sys/mbuf.h> 4753642Sguido# endif 48145522Sdarrenr#endif 49145522Sdarrenr#if defined(_KERNEL) && (__FreeBSD_version >= 220000) 50145522Sdarrenr# include <sys/filio.h> 51145522Sdarrenr# include <sys/fcntl.h> 5253642Sguido#else 53145522Sdarrenr# include <sys/ioctl.h> 54145522Sdarrenr#endif 55145522Sdarrenr#if defined(__SVR4) || defined(__svr4__) 5653642Sguido# include <sys/byteorder.h> 5753642Sguido# ifdef _KERNEL 5853642Sguido# include <sys/dditypes.h> 5953642Sguido# endif 6053642Sguido# include <sys/stream.h> 6153642Sguido# include <sys/kmem.h> 6253642Sguido#endif 63227957Srmh#if __FreeBSD_version >= 300000 6453642Sguido# include <sys/queue.h> 6553642Sguido#endif 6653642Sguido#include <net/if.h> 6753642Sguido#ifdef sun 6853642Sguido# include <net/af.h> 6953642Sguido#endif 7053642Sguido#include <netinet/in.h> 7153642Sguido#include <netinet/in_systm.h> 7253642Sguido#include <netinet/ip.h> 7353642Sguido#ifndef linux 7453642Sguido# include <netinet/ip_var.h> 7553642Sguido#endif 7653642Sguido#include <netinet/tcp.h> 7753642Sguido#include <netinet/udp.h> 7853642Sguido#include <netinet/ip_icmp.h> 7953642Sguido#include "netinet/ip_compat.h" 8053642Sguido#include <netinet/tcpip.h> 8153642Sguido#include "netinet/ip_fil.h" 8253642Sguido#include "netinet/ip_nat.h" 8353642Sguido#include "netinet/ip_state.h" 8492685Sdarrenr#include "netinet/ip_proxy.h" 8553642Sguido#if (__FreeBSD_version >= 300000) 8653642Sguido# include <sys/malloc.h> 8753642Sguido#endif 8853642Sguido 89255332Scy/* END OF INCLUDES */ 90255332Scy 91145522Sdarrenr#include "netinet/ip_ftp_pxy.c" 92255332Scy#include "netinet/ip_tftp_pxy.c" 93145522Sdarrenr#include "netinet/ip_rcmd_pxy.c" 94255332Scy#include "netinet/ip_pptp_pxy.c" 95145522Sdarrenr#if defined(_KERNEL) 96145522Sdarrenr# include "netinet/ip_irc_pxy.c" 97145522Sdarrenr# include "netinet/ip_raudio_pxy.c" 98145522Sdarrenr# include "netinet/ip_netbios_pxy.c" 9980482Sdarrenr#endif 100145522Sdarrenr#include "netinet/ip_ipsec_pxy.c" 101145522Sdarrenr#include "netinet/ip_rpcb_pxy.c" 10253642Sguido 103145522Sdarrenr#if !defined(lint) 104255332Scystatic const char rcsid[] = "@(#)$Id$"; 10592685Sdarrenr#endif 10680482Sdarrenr 10753642Sguido#define AP_SESS_SIZE 53 10853642Sguido 109255332Scystatic int ipf_proxy_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); 110255332Scystatic aproxy_t *ipf_proxy_create_clone __P((ipf_main_softc_t *, aproxy_t *)); 111255332Scy 112255332Scytypedef struct ipf_proxy_softc_s { 113255332Scy int ips_proxy_debug; 114255332Scy int ips_proxy_session_size; 115255332Scy ap_session_t **ips_sess_tab; 116255332Scy ap_session_t *ips_sess_list; 117255332Scy aproxy_t *ips_proxies; 118255332Scy int ips_init_run; 119255332Scy ipftuneable_t *ipf_proxy_tune; 120255332Scy} ipf_proxy_softc_t; 121255332Scy 122255332Scystatic ipftuneable_t ipf_proxy_tuneables[] = { 123255332Scy { { (void *)offsetof(ipf_proxy_softc_t, ips_proxy_debug) }, 124255332Scy "proxy_debug", 0, 0x1f, 125255332Scy stsizeof(ipf_proxy_softc_t, ips_proxy_debug), 126255332Scy 0, NULL, NULL }, 127255332Scy { { NULL }, NULL, 0, 0, 128255332Scy 0, 129255332Scy 0, NULL, NULL} 130255332Scy}; 131255332Scy 132255332Scystatic aproxy_t *ap_proxylist = NULL; 133255332Scystatic aproxy_t ips_proxies[] = { 13453642Sguido#ifdef IPF_FTP_PROXY 135255332Scy { NULL, NULL, "ftp", (char)IPPROTO_TCP, 0, 0, 0, 136255332Scy ipf_p_ftp_main_load, ipf_p_ftp_main_unload, 137255332Scy ipf_p_ftp_soft_create, ipf_p_ftp_soft_destroy, 138255332Scy NULL, NULL, 139255332Scy ipf_p_ftp_new, ipf_p_ftp_del, ipf_p_ftp_in, ipf_p_ftp_out, NULL, 140255332Scy NULL, NULL, NULL, NULL }, 14153642Sguido#endif 142255332Scy#ifdef IPF_TFTP_PROXY 143255332Scy { NULL, NULL, "tftp", (char)IPPROTO_UDP, 0, 0, 0, 144255332Scy ipf_p_tftp_main_load, ipf_p_tftp_main_unload, 145255332Scy ipf_p_tftp_soft_create, ipf_p_tftp_soft_destroy, 146255332Scy NULL, NULL, 147255332Scy ipf_p_tftp_new, ipf_p_tftp_del, 148255332Scy ipf_p_tftp_in, ipf_p_tftp_out, NULL, 149255332Scy NULL, NULL, NULL, NULL }, 150255332Scy#endif 151145522Sdarrenr#ifdef IPF_IRC_PROXY 152255332Scy { NULL, NULL, "irc", (char)IPPROTO_TCP, 0, 0, 0, 153255332Scy ipf_p_irc_main_load, ipf_p_irc_main_unload, 154255332Scy NULL, NULL, 155255332Scy NULL, NULL, 156255332Scy ipf_p_irc_new, NULL, NULL, ipf_p_irc_out, NULL, 157255332Scy NULL, NULL, NULL, NULL }, 158145522Sdarrenr#endif 15953642Sguido#ifdef IPF_RCMD_PROXY 160255332Scy { NULL, NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, 0, 161255332Scy ipf_p_rcmd_main_load, ipf_p_rcmd_main_unload, 162255332Scy NULL, NULL, 163255332Scy NULL, NULL, 164255332Scy ipf_p_rcmd_new, ipf_p_rcmd_del, 165255332Scy ipf_p_rcmd_in, ipf_p_rcmd_out, NULL, 166255332Scy NULL, NULL, NULL, NULL }, 16753642Sguido#endif 16853642Sguido#ifdef IPF_RAUDIO_PROXY 169255332Scy { NULL, NULL, "raudio", (char)IPPROTO_TCP, 0, 0, 0, 170255332Scy ipf_p_raudio_main_load, ipf_p_raudio_main_unload, 171255332Scy NULL, NULL, 172255332Scy NULL, NULL, 173255332Scy ipf_p_raudio_new, NULL, ipf_p_raudio_in, ipf_p_raudio_out, NULL, 174255332Scy NULL, NULL, NULL, NULL }, 17553642Sguido#endif 176145522Sdarrenr#ifdef IPF_MSNRPC_PROXY 177255332Scy { NULL, NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, 0, 178255332Scy ipf_p_msnrpc_init, ipf_p_msnrpc_fini, 179255332Scy NULL, NULL, 180255332Scy NULL, NULL, 181255332Scy ipf_p_msnrpc_new, NULL, ipf_p_msnrpc_in, ipf_p_msnrpc_out, NULL, 182255332Scy NULL, NULL, NULL, NULL }, 18392685Sdarrenr#endif 18492685Sdarrenr#ifdef IPF_NETBIOS_PROXY 185255332Scy { NULL, NULL, "netbios", (char)IPPROTO_UDP, 0, 0, 0, 186255332Scy ipf_p_netbios_main_load, ipf_p_netbios_main_unload, 187255332Scy NULL, NULL, 188255332Scy NULL, NULL, 189255332Scy NULL, NULL, NULL, ipf_p_netbios_out, NULL, 190255332Scy NULL, NULL, NULL, NULL }, 19192685Sdarrenr#endif 192145522Sdarrenr#ifdef IPF_IPSEC_PROXY 193255332Scy { NULL, NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 0, 194255332Scy NULL, NULL, 195255332Scy ipf_p_ipsec_soft_create, ipf_p_ipsec_soft_destroy, 196255332Scy ipf_p_ipsec_soft_init, ipf_p_ipsec_soft_fini, 197255332Scy ipf_p_ipsec_new, ipf_p_ipsec_del, 198255332Scy ipf_p_ipsec_inout, ipf_p_ipsec_inout, ipf_p_ipsec_match, 199255332Scy NULL, NULL, NULL, NULL }, 200145522Sdarrenr#endif 201255332Scy#ifdef IPF_DNS_PROXY 202255332Scy { NULL, NULL, "dns", (char)IPPROTO_UDP, 0, 0, 0, 203255332Scy NULL, NULL, 204255332Scy ipf_p_dns_soft_create, ipf_p_dns_soft_destroy, 205255332Scy NULL, NULL, 206255332Scy ipf_p_dns_new, ipf_p_ipsec_del, 207255332Scy ipf_p_dns_inout, ipf_p_dns_inout, ipf_p_dns_match, 208255332Scy ipf_p_dns_ctl, NULL, NULL, NULL }, 209255332Scy#endif 210145522Sdarrenr#ifdef IPF_PPTP_PROXY 211255332Scy { NULL, NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 0, 212255332Scy ipf_p_pptp_main_load, ipf_p_pptp_main_unload, 213255332Scy NULL, NULL, 214255332Scy NULL, NULL, 215255332Scy ipf_p_pptp_new, ipf_p_pptp_del, 216255332Scy ipf_p_pptp_inout, ipf_p_pptp_inout, NULL, 217255332Scy NULL, NULL, NULL, NULL }, 218145522Sdarrenr#endif 219145522Sdarrenr#ifdef IPF_RPCB_PROXY 220255332Scy# ifndef _KERNEL 221255332Scy { NULL, NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 0, 222255332Scy NULL, NULL, 223255332Scy NULL, NULL, 224255332Scy NULL, NULL, 225255332Scy ipf_p_rpcb_new, ipf_p_rpcb_del, 226255332Scy ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, 227255332Scy NULL, NULL, NULL, NULL }, 228145522Sdarrenr# endif 229255332Scy { NULL, NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 0, 230255332Scy ipf_p_rpcb_main_load, ipf_p_rpcb_main_unload, 231255332Scy NULL, NULL, 232255332Scy NULL, NULL, 233255332Scy ipf_p_rpcb_new, ipf_p_rpcb_del, 234255332Scy ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, 235255332Scy NULL, NULL, NULL, NULL }, 236145522Sdarrenr#endif 237255332Scy { NULL, NULL, "", '\0', 0, 0, 0, 238255332Scy NULL, NULL, 239255332Scy NULL, NULL, 240255332Scy NULL, NULL, 241255332Scy NULL, NULL, 242255332Scy NULL, NULL, NULL, 243255332Scy NULL, NULL, NULL, NULL } 24453642Sguido}; 24553642Sguido 246255332Scy 247255332Scy/* ------------------------------------------------------------------------ */ 248255332Scy/* Function: ipf_proxy_main_load */ 249255332Scy/* Returns: int - 0 == success, else failure. */ 250255332Scy/* Parameters: Nil */ 251255332Scy/* */ 252255332Scy/* Initialise hook for kernel application proxies. */ 253255332Scy/* Call the initialise routine for all the compiled in kernel proxies. */ 254255332Scy/* ------------------------------------------------------------------------ */ 255255332Scyint 256255332Scyipf_proxy_main_load() 25760855Sdarrenr{ 258255332Scy aproxy_t *ap; 259255332Scy 260255332Scy for (ap = ips_proxies; ap->apr_p; ap++) { 261255332Scy if (ap->apr_load != NULL) 262255332Scy (*ap->apr_load)(); 263255332Scy } 264255332Scy return 0; 265255332Scy} 266255332Scy 267255332Scy 268255332Scy/* ------------------------------------------------------------------------ */ 269255332Scy/* Function: ipf_proxy_main_unload */ 270255332Scy/* Returns: int - 0 == success, else failure. */ 271255332Scy/* Parameters: Nil */ 272255332Scy/* */ 273255332Scy/* Unload hook for kernel application proxies. */ 274255332Scy/* Call the finialise routine for all the compiled in kernel proxies. */ 275255332Scy/* ------------------------------------------------------------------------ */ 276255332Scyint 277255332Scyipf_proxy_main_unload() 278255332Scy{ 279255332Scy aproxy_t *ap; 280255332Scy 281255332Scy for (ap = ips_proxies; ap->apr_p; ap++) 282255332Scy if (ap->apr_unload != NULL) 283255332Scy (*ap->apr_unload)(); 284255332Scy for (ap = ap_proxylist; ap; ap = ap->apr_next) 285255332Scy if (ap->apr_unload != NULL) 286255332Scy (*ap->apr_unload)(); 287255332Scy 288255332Scy return 0; 289255332Scy} 290255332Scy 291255332Scy 292255332Scy/* ------------------------------------------------------------------------ */ 293255332Scy/* Function: ipf_proxy_soft_create */ 294255332Scy/* Returns: void * - */ 295255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 296255332Scy/* */ 297255332Scy/* Build the structure to hold all of the run time data to support proxies. */ 298255332Scy/* ------------------------------------------------------------------------ */ 299255332Scyvoid * 300255332Scyipf_proxy_soft_create(softc) 301255332Scy ipf_main_softc_t *softc; 302255332Scy{ 303255332Scy ipf_proxy_softc_t *softp; 304255332Scy aproxy_t *last; 305255332Scy aproxy_t *apn; 306255332Scy aproxy_t *ap; 307255332Scy 308255332Scy KMALLOC(softp, ipf_proxy_softc_t *); 309255332Scy if (softp == NULL) 310255332Scy return softp; 311255332Scy 312255332Scy bzero((char *)softp, sizeof(*softp)); 313255332Scy 314255332Scy#if defined(_KERNEL) 315255332Scy softp->ips_proxy_debug = 0; 316255332Scy#else 317255332Scy softp->ips_proxy_debug = 2; 318255332Scy#endif 319255332Scy softp->ips_proxy_session_size = AP_SESS_SIZE; 320255332Scy 321255332Scy softp->ipf_proxy_tune = ipf_tune_array_copy(softp, 322255332Scy sizeof(ipf_proxy_tuneables), 323255332Scy ipf_proxy_tuneables); 324255332Scy if (softp->ipf_proxy_tune == NULL) { 325255332Scy ipf_proxy_soft_destroy(softc, softp); 326255332Scy return NULL; 327255332Scy } 328255332Scy if (ipf_tune_array_link(softc, softp->ipf_proxy_tune) == -1) { 329255332Scy ipf_proxy_soft_destroy(softc, softp); 330255332Scy return NULL; 331255332Scy } 332255332Scy 333255332Scy last = NULL; 334255332Scy for (ap = ips_proxies; ap->apr_p; ap++) { 335255332Scy apn = ipf_proxy_create_clone(softc, ap); 336255332Scy if (apn == NULL) 337255332Scy goto failed; 338255332Scy if (last != NULL) 339255332Scy last->apr_next = apn; 340255332Scy else 341255332Scy softp->ips_proxies = apn; 342255332Scy last = apn; 343255332Scy } 344255332Scy for (ap = ips_proxies; ap != NULL; ap = ap->apr_next) { 345255332Scy apn = ipf_proxy_create_clone(softc, ap); 346255332Scy if (apn == NULL) 347255332Scy goto failed; 348255332Scy if (last != NULL) 349255332Scy last->apr_next = apn; 350255332Scy else 351255332Scy softp->ips_proxies = apn; 352255332Scy last = apn; 353255332Scy } 354255332Scy 355255332Scy return softp; 356255332Scyfailed: 357255332Scy ipf_proxy_soft_destroy(softc, softp); 358255332Scy return NULL; 359255332Scy} 360255332Scy 361255332Scy 362255332Scy/* ------------------------------------------------------------------------ */ 363255332Scy/* Function: ipf_proxy_soft_create */ 364255332Scy/* Returns: void * - */ 365255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 366255332Scy/* orig(I) - pointer to proxy definition to copy */ 367255332Scy/* */ 368255332Scy/* This function clones a proxy definition given by orig and returns a */ 369255332Scy/* a pointer to that copy. */ 370255332Scy/* ------------------------------------------------------------------------ */ 371255332Scystatic aproxy_t * 372255332Scyipf_proxy_create_clone(softc, orig) 373255332Scy ipf_main_softc_t *softc; 374255332Scy aproxy_t *orig; 375255332Scy{ 376255332Scy aproxy_t *apn; 377255332Scy 378255332Scy KMALLOC(apn, aproxy_t *); 379255332Scy if (apn == NULL) 380255332Scy return NULL; 381255332Scy 382255332Scy bcopy((char *)orig, (char *)apn, sizeof(*apn)); 383255332Scy apn->apr_next = NULL; 384255332Scy apn->apr_soft = NULL; 385255332Scy 386255332Scy if (apn->apr_create != NULL) { 387255332Scy apn->apr_soft = (*apn->apr_create)(softc); 388255332Scy if (apn->apr_soft == NULL) { 389255332Scy KFREE(apn); 390255332Scy return NULL; 391255332Scy } 392255332Scy } 393255332Scy 394255332Scy apn->apr_parent = orig; 395255332Scy orig->apr_clones++; 396255332Scy 397255332Scy return apn; 398255332Scy} 399255332Scy 400255332Scy 401255332Scy/* ------------------------------------------------------------------------ */ 402255332Scy/* Function: ipf_proxy_soft_create */ 403255332Scy/* Returns: int - 0 == success, else failure. */ 404255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 405255332Scy/* arg(I) - pointer to proxy contect data */ 406255332Scy/* */ 407255332Scy/* Initialise the proxy context and walk through each of the proxies and */ 408255332Scy/* call its initialisation function. This allows for proxies to do any */ 409255332Scy/* local setup prior to actual use. */ 410255332Scy/* ------------------------------------------------------------------------ */ 411255332Scyint 412255332Scyipf_proxy_soft_init(softc, arg) 413255332Scy ipf_main_softc_t *softc; 414255332Scy void *arg; 415255332Scy{ 416255332Scy ipf_proxy_softc_t *softp; 417255332Scy aproxy_t *ap; 418255332Scy u_int size; 419255332Scy int err; 420255332Scy 421255332Scy softp = arg; 422255332Scy size = softp->ips_proxy_session_size * sizeof(ap_session_t *); 423255332Scy 424255332Scy KMALLOCS(softp->ips_sess_tab, ap_session_t **, size); 425255332Scy 426255332Scy if (softp->ips_sess_tab == NULL) 427255332Scy return -1; 428255332Scy 429255332Scy bzero(softp->ips_sess_tab, size); 430255332Scy 431255332Scy for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { 432255332Scy if (ap->apr_init != NULL) { 433255332Scy err = (*ap->apr_init)(softc, ap->apr_soft); 434255332Scy if (err != 0) 435255332Scy return -2; 436255332Scy } 437255332Scy } 438255332Scy softp->ips_init_run = 1; 439255332Scy 440255332Scy return 0; 441255332Scy} 442255332Scy 443255332Scy 444255332Scy/* ------------------------------------------------------------------------ */ 445255332Scy/* Function: ipf_proxy_soft_create */ 446255332Scy/* Returns: int - 0 == success, else failure. */ 447255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 448255332Scy/* arg(I) - pointer to proxy contect data */ 449255332Scy/* */ 450255332Scy/* This function should always succeed. It is responsible for ensuring that */ 451255332Scy/* the proxy context can be safely called when ipf_proxy_soft_destroy is */ 452255332Scy/* called and suring all of the proxies have similarly been instructed. */ 453255332Scy/* ------------------------------------------------------------------------ */ 454255332Scyint 455255332Scyipf_proxy_soft_fini(softc, arg) 456255332Scy ipf_main_softc_t *softc; 457255332Scy void *arg; 458255332Scy{ 459255332Scy ipf_proxy_softc_t *softp = arg; 460255332Scy aproxy_t *ap; 461255332Scy 462255332Scy for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { 463255332Scy if (ap->apr_fini != NULL) { 464255332Scy (*ap->apr_fini)(softc, ap->apr_soft); 465255332Scy } 466255332Scy } 467255332Scy 468255332Scy if (softp->ips_sess_tab != NULL) { 469255332Scy KFREES(softp->ips_sess_tab, 470255332Scy softp->ips_proxy_session_size * sizeof(ap_session_t *)); 471255332Scy softp->ips_sess_tab = NULL; 472255332Scy } 473255332Scy softp->ips_init_run = 0; 474255332Scy 475255332Scy return 0; 476255332Scy} 477255332Scy 478255332Scy 479255332Scy/* ------------------------------------------------------------------------ */ 480255332Scy/* Function: ipf_proxy_soft_destroy */ 481255332Scy/* Returns: Nil */ 482255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 483255332Scy/* arg(I) - pointer to proxy contect data */ 484255332Scy/* */ 485255332Scy/* Free up all of the local data structures allocated during creation. */ 486255332Scy/* ------------------------------------------------------------------------ */ 487255332Scyvoid 488255332Scyipf_proxy_soft_destroy(softc, arg) 489255332Scy ipf_main_softc_t *softc; 490255332Scy void *arg; 491255332Scy{ 492255332Scy ipf_proxy_softc_t *softp = arg; 493255332Scy aproxy_t *ap; 494255332Scy 495255332Scy while ((ap = softp->ips_proxies) != NULL) { 496255332Scy softp->ips_proxies = ap->apr_next; 497255332Scy if (ap->apr_destroy != NULL) 498255332Scy (*ap->apr_destroy)(softc, ap->apr_soft); 499255332Scy ap->apr_parent->apr_clones--; 500255332Scy KFREE(ap); 501255332Scy } 502255332Scy 503255332Scy if (softp->ipf_proxy_tune != NULL) { 504255332Scy ipf_tune_array_unlink(softc, softp->ipf_proxy_tune); 505255332Scy KFREES(softp->ipf_proxy_tune, sizeof(ipf_proxy_tuneables)); 506255332Scy softp->ipf_proxy_tune = NULL; 507255332Scy } 508255332Scy 509255332Scy KFREE(softp); 510255332Scy} 511255332Scy 512255332Scy 513255332Scy/* ------------------------------------------------------------------------ */ 514255332Scy/* Function: ipf_proxy_flush */ 515255332Scy/* Returns: Nil */ 516255332Scy/* Parameters: arg(I) - pointer to proxy contect data */ 517255332Scy/* how(I) - indicates the type of flush operation */ 518255332Scy/* */ 519255332Scy/* Walk through all of the proxies and pass on the flush command as either */ 520255332Scy/* a flush or a clear. */ 521255332Scy/* ------------------------------------------------------------------------ */ 522255332Scyvoid 523255332Scyipf_proxy_flush(arg, how) 524255332Scy void *arg; 525255332Scy int how; 526255332Scy{ 527255332Scy ipf_proxy_softc_t *softp = arg; 528255332Scy aproxy_t *ap; 529255332Scy 530255332Scy switch (how) 531255332Scy { 532255332Scy case 0 : 533255332Scy for (ap = softp->ips_proxies; ap; ap = ap->apr_next) 534255332Scy if (ap->apr_flush != NULL) 535255332Scy (*ap->apr_flush)(ap, how); 536255332Scy break; 537255332Scy case 1 : 538255332Scy for (ap = softp->ips_proxies; ap; ap = ap->apr_next) 539255332Scy if (ap->apr_clear != NULL) 540255332Scy (*ap->apr_clear)(ap); 541255332Scy break; 542255332Scy default : 543255332Scy break; 544255332Scy } 545255332Scy} 546255332Scy 547255332Scy 548255332Scy/* ------------------------------------------------------------------------ */ 549255332Scy/* Function: ipf_proxy_add */ 550255332Scy/* Returns: int - 0 == success, else failure. */ 551255332Scy/* Parameters: ap(I) - pointer to proxy structure */ 552255332Scy/* */ 553255332Scy/* Dynamically add a new kernel proxy. Ensure that it is unique in the */ 554255332Scy/* collection compiled in and dynamically added. */ 555255332Scy/* ------------------------------------------------------------------------ */ 556255332Scyint 557255332Scyipf_proxy_add(arg, ap) 558255332Scy void *arg; 559255332Scy aproxy_t *ap; 560255332Scy{ 561255332Scy ipf_proxy_softc_t *softp = arg; 562255332Scy 56360855Sdarrenr aproxy_t *a; 56460855Sdarrenr 565255332Scy for (a = ips_proxies; a->apr_p; a++) 56660855Sdarrenr if ((a->apr_p == ap->apr_p) && 56760855Sdarrenr !strncmp(a->apr_label, ap->apr_label, 568145522Sdarrenr sizeof(ap->apr_label))) { 569255332Scy if (softp->ips_proxy_debug & 0x01) 570255332Scy printf("ipf_proxy_add: %s/%d present (B)\n", 571145522Sdarrenr a->apr_label, a->apr_p); 57260855Sdarrenr return -1; 573145522Sdarrenr } 57460855Sdarrenr 575170268Sdarrenr for (a = ap_proxylist; (a != NULL); a = a->apr_next) 57660855Sdarrenr if ((a->apr_p == ap->apr_p) && 57760855Sdarrenr !strncmp(a->apr_label, ap->apr_label, 578145522Sdarrenr sizeof(ap->apr_label))) { 579255332Scy if (softp->ips_proxy_debug & 0x01) 580255332Scy printf("ipf_proxy_add: %s/%d present (D)\n", 581145522Sdarrenr a->apr_label, a->apr_p); 58260855Sdarrenr return -1; 583145522Sdarrenr } 58460855Sdarrenr ap->apr_next = ap_proxylist; 58560855Sdarrenr ap_proxylist = ap; 586255332Scy if (ap->apr_load != NULL) 587255332Scy (*ap->apr_load)(); 588145522Sdarrenr return 0; 58960855Sdarrenr} 59060855Sdarrenr 59160855Sdarrenr 592255332Scy/* ------------------------------------------------------------------------ */ 593255332Scy/* Function: ipf_proxy_ctl */ 594255332Scy/* Returns: int - 0 == success, else error */ 595255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 596255332Scy/* arg(I) - pointer to proxy context */ 597255332Scy/* ctl(I) - pointer to proxy control structure */ 598255332Scy/* */ 599255332Scy/* Check to see if the proxy this control request has come through for */ 600255332Scy/* exists, and if it does and it has a control function then invoke that */ 601255332Scy/* control function. */ 602255332Scy/* ------------------------------------------------------------------------ */ 603255332Scyint 604255332Scyipf_proxy_ctl(softc, arg, ctl) 605255332Scy ipf_main_softc_t *softc; 606255332Scy void *arg; 607255332Scy ap_ctl_t *ctl; 608145522Sdarrenr{ 609255332Scy ipf_proxy_softc_t *softp = arg; 610145522Sdarrenr aproxy_t *a; 611145522Sdarrenr int error; 612145522Sdarrenr 613255332Scy a = ipf_proxy_lookup(arg, ctl->apc_p, ctl->apc_label); 614145522Sdarrenr if (a == NULL) { 615255332Scy if (softp->ips_proxy_debug & 0x01) 616255332Scy printf("ipf_proxy_ctl: can't find %s/%d\n", 617145522Sdarrenr ctl->apc_label, ctl->apc_p); 618255332Scy IPFERROR(80001); 619145522Sdarrenr error = ESRCH; 620145522Sdarrenr } else if (a->apr_ctl == NULL) { 621255332Scy if (softp->ips_proxy_debug & 0x01) 622255332Scy printf("ipf_proxy_ctl: no ctl function for %s/%d\n", 623145522Sdarrenr ctl->apc_label, ctl->apc_p); 624255332Scy IPFERROR(80002); 625145522Sdarrenr error = ENXIO; 626145522Sdarrenr } else { 627255332Scy error = (*a->apr_ctl)(softc, a->apr_soft, ctl); 628255332Scy if ((error != 0) && (softp->ips_proxy_debug & 0x02)) 629255332Scy printf("ipf_proxy_ctl: %s/%d ctl error %d\n", 630145522Sdarrenr a->apr_label, a->apr_p, error); 631145522Sdarrenr } 632145522Sdarrenr return error; 633145522Sdarrenr} 634145522Sdarrenr 635145522Sdarrenr 636255332Scy/* ------------------------------------------------------------------------ */ 637255332Scy/* Function: ipf_proxy_del */ 638255332Scy/* Returns: int - 0 == success, else failure. */ 639255332Scy/* Parameters: ap(I) - pointer to proxy structure */ 640255332Scy/* */ 641255332Scy/* Delete a proxy that has been added dynamically from those available. */ 642255332Scy/* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 */ 643255332Scy/* if it cannot be matched. */ 644255332Scy/* ------------------------------------------------------------------------ */ 645255332Scyint 646255332Scyipf_proxy_del(ap) 647255332Scy aproxy_t *ap; 64860855Sdarrenr{ 64960855Sdarrenr aproxy_t *a, **app; 65060855Sdarrenr 651255332Scy for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) { 65260855Sdarrenr if (a == ap) { 65392685Sdarrenr a->apr_flags |= APR_DELETE; 654255332Scy if (ap->apr_ref == 0 && ap->apr_clones == 0) { 655255332Scy *app = a->apr_next; 656255332Scy return 0; 657145522Sdarrenr } 658255332Scy return 1; 65960855Sdarrenr } 660255332Scy } 661255332Scy 66260855Sdarrenr return -1; 66360855Sdarrenr} 66460855Sdarrenr 66560855Sdarrenr 666255332Scy/* ------------------------------------------------------------------------ */ 667255332Scy/* Function: ipf_proxy_ok */ 668255332Scy/* Returns: int - 1 == good match else not. */ 669255332Scy/* Parameters: fin(I) - pointer to packet information */ 670255332Scy/* tcp(I) - pointer to TCP/UDP header */ 671255332Scy/* nat(I) - pointer to current NAT session */ 672255332Scy/* */ 673255332Scy/* This function extends the NAT matching to ensure that a packet that has */ 674255332Scy/* arrived matches the proxy information attached to the NAT rule. Notably, */ 675255332Scy/* if the proxy is scheduled to be deleted then packets will not match the */ 676255332Scy/* rule even if the rule is still active. */ 677255332Scy/* ------------------------------------------------------------------------ */ 678255332Scyint 679255332Scyipf_proxy_ok(fin, tcp, np) 680255332Scy fr_info_t *fin; 681255332Scy tcphdr_t *tcp; 682255332Scy ipnat_t *np; 68353642Sguido{ 684255332Scy aproxy_t *apr = np->in_apr; 685255332Scy u_short dport = np->in_odport; 68653642Sguido 68792685Sdarrenr if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || 688145522Sdarrenr (fin->fin_p != apr->apr_p)) 68953642Sguido return 0; 690145522Sdarrenr if ((tcp == NULL) && dport) 69153642Sguido return 0; 69253642Sguido return 1; 69353642Sguido} 69453642Sguido 69553642Sguido 696255332Scy/* ------------------------------------------------------------------------ */ 697255332Scy/* Function: ipf_proxy_ioctl */ 698255332Scy/* Returns: int - 0 == success, else error */ 699255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 700255332Scy/* data(I) - pointer to ioctl data */ 701255332Scy/* cmd(I) - ioctl command */ 702255332Scy/* mode(I) - mode bits for device */ 703255332Scy/* ctx(I) - pointer to context information */ 704255332Scy/* */ 705255332Scy/* ------------------------------------------------------------------------ */ 706255332Scyint 707255332Scyipf_proxy_ioctl(softc, data, cmd, mode, ctx) 708255332Scy ipf_main_softc_t *softc; 709255332Scy caddr_t data; 710255332Scy ioctlcmd_t cmd; 711255332Scy int mode; 712255332Scy void *ctx; 713145522Sdarrenr{ 714145522Sdarrenr ap_ctl_t ctl; 715255332Scy caddr_t ptr; 716145522Sdarrenr int error; 717145522Sdarrenr 718145522Sdarrenr mode = mode; /* LINT */ 719145522Sdarrenr 720145522Sdarrenr switch (cmd) 721145522Sdarrenr { 722145522Sdarrenr case SIOCPROXY : 723255332Scy error = ipf_inobj(softc, data, NULL, &ctl, IPFOBJ_PROXYCTL); 724255332Scy if (error != 0) { 725255332Scy return error; 726255332Scy } 727145522Sdarrenr ptr = NULL; 728145522Sdarrenr 729145522Sdarrenr if (ctl.apc_dsize > 0) { 730255332Scy KMALLOCS(ptr, caddr_t, ctl.apc_dsize); 731255332Scy if (ptr == NULL) { 732255332Scy IPFERROR(80003); 733145522Sdarrenr error = ENOMEM; 734255332Scy } else { 735255332Scy error = copyinptr(softc, ctl.apc_data, ptr, 736145522Sdarrenr ctl.apc_dsize); 737145522Sdarrenr if (error == 0) 738145522Sdarrenr ctl.apc_data = ptr; 739145522Sdarrenr } 740145522Sdarrenr } else { 741145522Sdarrenr ctl.apc_data = NULL; 742145522Sdarrenr error = 0; 743145522Sdarrenr } 744145522Sdarrenr 745145522Sdarrenr if (error == 0) 746255332Scy error = ipf_proxy_ctl(softc, softc->ipf_proxy_soft, 747255332Scy &ctl); 748145522Sdarrenr 749255332Scy if ((error != 0) && (ptr != NULL)) { 750145522Sdarrenr KFREES(ptr, ctl.apc_dsize); 751145522Sdarrenr } 752145522Sdarrenr break; 753145522Sdarrenr 754145522Sdarrenr default : 755255332Scy IPFERROR(80004); 756145522Sdarrenr error = EINVAL; 757145522Sdarrenr } 758145522Sdarrenr return error; 759145522Sdarrenr} 760145522Sdarrenr 761145522Sdarrenr 762255332Scy/* ------------------------------------------------------------------------ */ 763255332Scy/* Function: ipf_proxy_match */ 764255332Scy/* Returns: int - 0 == success, else error */ 765255332Scy/* Parameters: fin(I) - pointer to packet information */ 766255332Scy/* nat(I) - pointer to current NAT session */ 767255332Scy/* */ 768255332Scy/* If a proxy has a match function, call that to do extended packet */ 769255332Scy/* matching. Whilst other parts of the NAT code are rather lenient when it */ 770255332Scy/* comes to the quality of the packet that it will transform, the proxy */ 771255332Scy/* matching is not because they need to work with data, not just headers. */ 772255332Scy/* ------------------------------------------------------------------------ */ 773255332Scyint 774255332Scyipf_proxy_match(fin, nat) 775255332Scy fr_info_t *fin; 776255332Scy nat_t *nat; 77792685Sdarrenr{ 778255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 779255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 78092685Sdarrenr aproxy_t *apr; 78192685Sdarrenr ipnat_t *ipn; 782145522Sdarrenr int result; 78392685Sdarrenr 78492685Sdarrenr ipn = nat->nat_ptr; 785255332Scy if (softp->ips_proxy_debug & 0x04) 786255332Scy printf("ipf_proxy_match(%lx,%lx) aps %lx ptr %lx\n", 787145522Sdarrenr (u_long)fin, (u_long)nat, (u_long)nat->nat_aps, 788145522Sdarrenr (u_long)ipn); 789145522Sdarrenr 790145522Sdarrenr if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) { 791255332Scy if (softp->ips_proxy_debug & 0x08) 792255332Scy printf("ipf_proxy_match: flx 0x%x (BAD|SHORT)\n", 793145522Sdarrenr fin->fin_flx); 79492685Sdarrenr return -1; 795145522Sdarrenr } 796145522Sdarrenr 79792685Sdarrenr apr = ipn->in_apr; 798145522Sdarrenr if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) { 799255332Scy if (softp->ips_proxy_debug & 0x08) 800255332Scy printf("ipf_proxy_match:apr %lx apr_flags 0x%x\n", 801145522Sdarrenr (u_long)apr, apr ? apr->apr_flags : 0); 80292685Sdarrenr return -1; 803145522Sdarrenr } 804145522Sdarrenr 805145522Sdarrenr if (apr->apr_match != NULL) { 806145522Sdarrenr result = (*apr->apr_match)(fin, nat->nat_aps, nat); 807145522Sdarrenr if (result != 0) { 808255332Scy if (softp->ips_proxy_debug & 0x08) 809255332Scy printf("ipf_proxy_match: result %d\n", result); 81092685Sdarrenr return -1; 811145522Sdarrenr } 812145522Sdarrenr } 81392685Sdarrenr return 0; 81492685Sdarrenr} 81592685Sdarrenr 81692685Sdarrenr 817255332Scy/* ------------------------------------------------------------------------ */ 818255332Scy/* Function: ipf_proxy_new */ 819255332Scy/* Returns: int - 0 == success, else error */ 820255332Scy/* Parameters: fin(I) - pointer to packet information */ 821255332Scy/* nat(I) - pointer to current NAT session */ 822255332Scy/* */ 823255332Scy/* Allocate a new application proxy structure and fill it in with the */ 824255332Scy/* relevant details. call the init function once complete, prior to */ 825255332Scy/* returning. */ 826255332Scy/* ------------------------------------------------------------------------ */ 827255332Scyint 828255332Scyipf_proxy_new(fin, nat) 829255332Scy fr_info_t *fin; 830255332Scy nat_t *nat; 83153642Sguido{ 832255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 833255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 83453642Sguido register ap_session_t *aps; 83592685Sdarrenr aproxy_t *apr; 83653642Sguido 837255332Scy if (softp->ips_proxy_debug & 0x04) 838255332Scy printf("ipf_proxy_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); 839145522Sdarrenr 840145522Sdarrenr if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) { 841255332Scy if (softp->ips_proxy_debug & 0x08) 842255332Scy printf("ipf_proxy_new: nat_ptr %lx nat_aps %lx\n", 843145522Sdarrenr (u_long)nat->nat_ptr, (u_long)nat->nat_aps); 84492685Sdarrenr return -1; 845145522Sdarrenr } 84692685Sdarrenr 84792685Sdarrenr apr = nat->nat_ptr->in_apr; 84892685Sdarrenr 849145522Sdarrenr if ((apr->apr_flags & APR_DELETE) || 850145522Sdarrenr (fin->fin_p != apr->apr_p)) { 851255332Scy if (softp->ips_proxy_debug & 0x08) 852255332Scy printf("ipf_proxy_new: apr_flags 0x%x p %d/%d\n", 853145522Sdarrenr apr->apr_flags, fin->fin_p, apr->apr_p); 85492685Sdarrenr return -1; 855145522Sdarrenr } 85653642Sguido 85753642Sguido KMALLOC(aps, ap_session_t *); 858145522Sdarrenr if (!aps) { 859255332Scy if (softp->ips_proxy_debug & 0x08) 860255332Scy printf("ipf_proxy_new: malloc failed (%lu)\n", 861145522Sdarrenr (u_long)sizeof(ap_session_t)); 86292685Sdarrenr return -1; 863145522Sdarrenr } 864145522Sdarrenr 86553642Sguido bzero((char *)aps, sizeof(*aps)); 86653642Sguido aps->aps_data = NULL; 86753642Sguido aps->aps_apr = apr; 86853642Sguido aps->aps_psiz = 0; 86960855Sdarrenr if (apr->apr_new != NULL) 870255332Scy if ((*apr->apr_new)(apr->apr_soft, fin, aps, nat) == -1) { 87192685Sdarrenr if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) { 87292685Sdarrenr KFREES(aps->aps_data, aps->aps_psiz); 87392685Sdarrenr } 87460855Sdarrenr KFREE(aps); 875255332Scy if (softp->ips_proxy_debug & 0x08) 876255332Scy printf("ipf_proxy_new: new(%lx) failed\n", 877145522Sdarrenr (u_long)apr->apr_new); 87892685Sdarrenr return -1; 87960855Sdarrenr } 88060855Sdarrenr aps->aps_nat = nat; 881255332Scy aps->aps_next = softp->ips_sess_list; 882255332Scy softp->ips_sess_list = aps; 88392685Sdarrenr nat->nat_aps = aps; 88492685Sdarrenr 88592685Sdarrenr return 0; 88653642Sguido} 88753642Sguido 88853642Sguido 889255332Scy/* ------------------------------------------------------------------------ */ 890255332Scy/* Function: ipf_proxy_check */ 891255332Scy/* Returns: int - -1 == error, 0 == success */ 892255332Scy/* Parameters: fin(I) - pointer to packet information */ 893255332Scy/* nat(I) - pointer to current NAT session */ 894255332Scy/* */ 895255332Scy/* Check to see if a packet should be passed through an active proxy */ 896255332Scy/* routine if one has been setup for it. We don't need to check the */ 897255332Scy/* checksum here if IPFILTER_CKSUM is defined because if it is, a failed */ 898255332Scy/* check causes FI_BAD to be set. */ 899255332Scy/* ------------------------------------------------------------------------ */ 900255332Scyint 901255332Scyipf_proxy_check(fin, nat) 902255332Scy fr_info_t *fin; 903255332Scy nat_t *nat; 90453642Sguido{ 905255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 906255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 907255332Scy#if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) 908145522Sdarrenr mb_t *m; 90980482Sdarrenr#endif 91080482Sdarrenr tcphdr_t *tcp = NULL; 911145522Sdarrenr udphdr_t *udp = NULL; 91253642Sguido ap_session_t *aps; 91353642Sguido aproxy_t *apr; 914255332Scy short adjlen; 915255332Scy int dosum; 916145522Sdarrenr ip_t *ip; 91760855Sdarrenr short rv; 91853642Sguido int err; 919145522Sdarrenr#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) 920145522Sdarrenr u_32_t s1, s2, sd; 921145522Sdarrenr#endif 92253642Sguido 923145522Sdarrenr if (fin->fin_flx & FI_BAD) { 924255332Scy if (softp->ips_proxy_debug & 0x08) 925255332Scy printf("ipf_proxy_check: flx 0x%x (BAD)\n", 926255332Scy fin->fin_flx); 927145522Sdarrenr return -1; 928145522Sdarrenr } 929145522Sdarrenr 930145522Sdarrenr#ifndef IPFILTER_CKSUM 931255332Scy if ((fin->fin_out == 0) && (ipf_checkl4sum(fin) == -1)) { 932255332Scy if (softp->ips_proxy_debug & 0x08) 933255332Scy printf("ipf_proxy_check: l4 checksum failure %d\n", 934145522Sdarrenr fin->fin_p); 935145522Sdarrenr if (fin->fin_p == IPPROTO_TCP) 936255332Scy softc->ipf_stats[fin->fin_out].fr_tcpbad++; 937145522Sdarrenr return -1; 938145522Sdarrenr } 939145522Sdarrenr#endif 940145522Sdarrenr 94153642Sguido aps = nat->nat_aps; 942255332Scy if (aps != NULL) { 943145522Sdarrenr /* 944145522Sdarrenr * If there is data in this packet to be proxied then try and 945145522Sdarrenr * get it all into the one buffer, else drop it. 946145522Sdarrenr */ 947145522Sdarrenr#if defined(MENTAT) || defined(HAVE_M_PULLDOWN) 948145522Sdarrenr if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE)) 949255332Scy if (ipf_coalesce(fin) == -1) { 950255332Scy if (softp->ips_proxy_debug & 0x08) 951255332Scy printf("ipf_proxy_check: %s %x\n", 952255332Scy "coalesce failed", fin->fin_flx); 953145522Sdarrenr return -1; 954145522Sdarrenr } 955145522Sdarrenr#endif 956145522Sdarrenr ip = fin->fin_ip; 957255332Scy if (fin->fin_cksum > FI_CK_SUMOK) 958255332Scy dosum = 0; 959255332Scy else 960255332Scy dosum = 1; 961145522Sdarrenr 962145522Sdarrenr switch (fin->fin_p) 963145522Sdarrenr { 964145522Sdarrenr case IPPROTO_TCP : 96553642Sguido tcp = (tcphdr_t *)fin->fin_dp; 966255332Scy#if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) 967145522Sdarrenr m = fin->fin_qfm; 968145522Sdarrenr if (dohwcksum && (m->b_ick_flag == ICK_VALID)) 96980482Sdarrenr dosum = 0; 97053642Sguido#endif 971255332Scy break; 972145522Sdarrenr case IPPROTO_UDP : 973145522Sdarrenr udp = (udphdr_t *)fin->fin_dp; 974145522Sdarrenr break; 975145522Sdarrenr default : 976145522Sdarrenr break; 97753642Sguido } 97853642Sguido 97953642Sguido apr = aps->aps_apr; 98053642Sguido err = 0; 98153642Sguido if (fin->fin_out != 0) { 98253642Sguido if (apr->apr_outpkt != NULL) 983255332Scy err = (*apr->apr_outpkt)(apr->apr_soft, fin, 984255332Scy aps, nat); 98553642Sguido } else { 98653642Sguido if (apr->apr_inpkt != NULL) 987255332Scy err = (*apr->apr_inpkt)(apr->apr_soft, fin, 988255332Scy aps, nat); 98953642Sguido } 99053642Sguido 99160855Sdarrenr rv = APR_EXIT(err); 992255332Scy if (((softp->ips_proxy_debug & 0x08) && (rv != 0)) || 993255332Scy (softp->ips_proxy_debug & 0x04)) 994255332Scy printf("ipf_proxy_check: out %d err %x rv %d\n", 995145522Sdarrenr fin->fin_out, err, rv); 996145522Sdarrenr if (rv == 1) 99792685Sdarrenr return -1; 998145522Sdarrenr 99992685Sdarrenr if (rv == 2) { 1000255332Scy ipf_proxy_deref(apr); 100192685Sdarrenr nat->nat_aps = NULL; 100292685Sdarrenr return -1; 100392685Sdarrenr } 100460855Sdarrenr 1005145522Sdarrenr /* 1006145522Sdarrenr * If err != 0 then the data size of the packet has changed 1007145522Sdarrenr * so we need to recalculate the header checksums for the 1008145522Sdarrenr * packet. 1009145522Sdarrenr */ 1010255332Scy adjlen = APR_INC(err); 1011145522Sdarrenr#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) 1012255332Scy s1 = LONG_SUM(fin->fin_plen - adjlen); 1013255332Scy s2 = LONG_SUM(fin->fin_plen); 1014255332Scy CALC_SUMD(s1, s2, sd); 1015255332Scy if ((err != 0) && (fin->fin_cksum < FI_CK_L4PART) && 1016255332Scy fin->fin_v == 4) 1017255332Scy ipf_fix_outcksum(0, &ip->ip_sum, sd, 0); 1018145522Sdarrenr#endif 1019255332Scy if (fin->fin_flx & FI_DOCKSUM) 1020255332Scy dosum = 1; 1021145522Sdarrenr 1022145522Sdarrenr /* 1023145522Sdarrenr * For TCP packets, we may need to adjust the sequence and 1024145522Sdarrenr * acknowledgement numbers to reflect changes in size of the 1025145522Sdarrenr * data stream. 1026145522Sdarrenr * 1027145522Sdarrenr * For both TCP and UDP, recalculate the layer 4 checksum, 1028145522Sdarrenr * regardless, as we can't tell (here) if data has been 1029145522Sdarrenr * changed or not. 1030145522Sdarrenr */ 103153642Sguido if (tcp != NULL) { 1032255332Scy err = ipf_proxy_fixseqack(fin, ip, aps, adjlen); 1033255332Scy if (fin->fin_cksum == FI_CK_L4PART) { 1034255332Scy u_short sum = ntohs(tcp->th_sum); 1035255332Scy sum += adjlen; 1036255332Scy tcp->th_sum = htons(sum); 1037255332Scy } else if (fin->fin_cksum < FI_CK_L4PART) { 1038255332Scy tcp->th_sum = fr_cksum(fin, ip, 1039255332Scy IPPROTO_TCP, tcp); 1040255332Scy } 1041145522Sdarrenr } else if ((udp != NULL) && (udp->uh_sum != 0)) { 1042255332Scy if (fin->fin_cksum == FI_CK_L4PART) { 1043255332Scy u_short sum = ntohs(udp->uh_sum); 1044255332Scy sum += adjlen; 1045255332Scy udp->uh_sum = htons(sum); 1046255332Scy } else if (dosum) { 1047255332Scy udp->uh_sum = fr_cksum(fin, ip, 1048255332Scy IPPROTO_UDP, udp); 1049255332Scy } 105053642Sguido } 1051145522Sdarrenr aps->aps_bytes += fin->fin_plen; 105253642Sguido aps->aps_pkts++; 105360855Sdarrenr return 1; 105453642Sguido } 105560855Sdarrenr return 0; 105653642Sguido} 105753642Sguido 105853642Sguido 1059255332Scy/* ------------------------------------------------------------------------ */ 1060255332Scy/* Function: ipf_proxy_lookup */ 1061255332Scy/* Returns: int - -1 == error, 0 == success */ 1062255332Scy/* Parameters: arg(I) - pointer to proxy context information */ 1063255332Scy/* pr(I) - protocol number for proxy */ 1064255332Scy/* name(I) - proxy name */ 1065255332Scy/* */ 1066255332Scy/* Search for an proxy by the protocol it is being used with and its name. */ 1067255332Scy/* ------------------------------------------------------------------------ */ 1068255332Scyaproxy_t * 1069255332Scyipf_proxy_lookup(arg, pr, name) 1070255332Scy void *arg; 1071255332Scy u_int pr; 1072255332Scy char *name; 107353642Sguido{ 1074255332Scy ipf_proxy_softc_t *softp = arg; 107553642Sguido aproxy_t *ap; 107653642Sguido 1077255332Scy if (softp->ips_proxy_debug & 0x04) 1078255332Scy printf("ipf_proxy_lookup(%d,%s)\n", pr, name); 1079145522Sdarrenr 1080255332Scy for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) 108153642Sguido if ((ap->apr_p == pr) && 108253642Sguido !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { 108353642Sguido ap->apr_ref++; 108453642Sguido return ap; 108553642Sguido } 108660855Sdarrenr 1087255332Scy if (softp->ips_proxy_debug & 0x08) 1088255332Scy printf("ipf_proxy_lookup: failed for %d/%s\n", pr, name); 108953642Sguido return NULL; 109053642Sguido} 109153642Sguido 109253642Sguido 1093255332Scy/* ------------------------------------------------------------------------ */ 1094255332Scy/* Function: ipf_proxy_deref */ 1095255332Scy/* Returns: Nil */ 1096255332Scy/* Parameters: ap(I) - pointer to proxy structure */ 1097255332Scy/* */ 1098255332Scy/* Drop the reference counter associated with the proxy. */ 1099255332Scy/* ------------------------------------------------------------------------ */ 1100255332Scyvoid 1101255332Scyipf_proxy_deref(ap) 1102255332Scy aproxy_t *ap; 110353642Sguido{ 110453642Sguido ap->apr_ref--; 110553642Sguido} 110653642Sguido 110753642Sguido 1108255332Scy/* ------------------------------------------------------------------------ */ 1109255332Scy/* Function: ipf_proxy_free */ 1110255332Scy/* Returns: Nil */ 1111255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1112255332Scy/* aps(I) - pointer to current proxy session */ 1113255332Scy/* Locks Held: ipf_nat_new, ipf_nat(W) */ 1114255332Scy/* */ 1115255332Scy/* Free up proxy session information allocated to be used with a NAT */ 1116255332Scy/* session. */ 1117255332Scy/* ------------------------------------------------------------------------ */ 1118255332Scyvoid 1119255332Scyipf_proxy_free(softc, aps) 1120255332Scy ipf_main_softc_t *softc; 1121255332Scy ap_session_t *aps; 112253642Sguido{ 1123255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 112453642Sguido ap_session_t *a, **ap; 112592685Sdarrenr aproxy_t *apr; 112653642Sguido 112753642Sguido if (!aps) 112853642Sguido return; 112953642Sguido 1130255332Scy for (ap = &softp->ips_sess_list; ((a = *ap) != NULL); ap = &a->aps_next) 113153642Sguido if (a == aps) { 113253642Sguido *ap = a->aps_next; 113353642Sguido break; 113453642Sguido } 113553642Sguido 113692685Sdarrenr apr = aps->aps_apr; 113792685Sdarrenr if ((apr != NULL) && (apr->apr_del != NULL)) 1138255332Scy (*apr->apr_del)(softc, aps); 1139110916Sdarrenr 114060855Sdarrenr if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) 114160855Sdarrenr KFREES(aps->aps_data, aps->aps_psiz); 114260855Sdarrenr KFREE(aps); 114353642Sguido} 114453642Sguido 114553642Sguido 1146255332Scy/* ------------------------------------------------------------------------ */ 1147255332Scy/* Function: ipf_proxy_fixseqack */ 1148255332Scy/* Returns: int - 2 if TCP ack/seq is changed, else 0 */ 1149255332Scy/* Parameters: fin(I) - pointer to packet information */ 1150255332Scy/* ip(I) - pointer to IP header */ 1151255332Scy/* nat(I) - pointer to current NAT session */ 1152255332Scy/* inc(I) - delta to apply to TCP sequence numbering */ 1153255332Scy/* */ 1154255332Scy/* Adjust the TCP sequence/acknowledge numbers in the TCP header based on */ 1155255332Scy/* whether or not the new header is past the point at which an adjustment */ 1156255332Scy/* occurred. This might happen because of (say) an FTP string being changed */ 1157255332Scy/* and the new string being a different length to the old. */ 1158255332Scy/* ------------------------------------------------------------------------ */ 1159255332Scystatic int 1160255332Scyipf_proxy_fixseqack(fin, ip, aps, inc) 1161255332Scy fr_info_t *fin; 1162255332Scy ip_t *ip; 1163255332Scy ap_session_t *aps; 1164255332Scy int inc; 116553642Sguido{ 1166255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 1167255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 116853642Sguido int sel, ch = 0, out, nlen; 116953642Sguido u_32_t seq1, seq2; 117053642Sguido tcphdr_t *tcp; 117198004Sdarrenr short inc2; 117253642Sguido 117353642Sguido tcp = (tcphdr_t *)fin->fin_dp; 117453642Sguido out = fin->fin_out; 1175102520Sdarrenr /* 1176255332Scy * ip_len has already been adjusted by 'inc'. 1177102520Sdarrenr */ 1178255332Scy nlen = fin->fin_dlen; 1179255332Scy nlen -= (TCP_OFF(tcp) << 2); 1180102520Sdarrenr 118198004Sdarrenr inc2 = inc; 118298004Sdarrenr inc = (int)inc2; 118353642Sguido 118453642Sguido if (out != 0) { 118553642Sguido seq1 = (u_32_t)ntohl(tcp->th_seq); 118653642Sguido sel = aps->aps_sel[out]; 118753642Sguido 118853642Sguido /* switch to other set ? */ 118953642Sguido if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 1190102520Sdarrenr (seq1 > aps->aps_seqmin[!sel])) { 1191255332Scy if (softp->ips_proxy_debug & 0x10) 1192145522Sdarrenr printf("proxy out switch set seq %d -> %d %x > %x\n", 1193145522Sdarrenr sel, !sel, seq1, 1194145522Sdarrenr aps->aps_seqmin[!sel]); 119553642Sguido sel = aps->aps_sel[out] = !sel; 1196110916Sdarrenr } 119753642Sguido 119853642Sguido if (aps->aps_seqoff[sel]) { 119953642Sguido seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel]; 120053642Sguido if (seq1 > seq2) { 120153642Sguido seq2 = aps->aps_seqoff[sel]; 120253642Sguido seq1 += seq2; 120353642Sguido tcp->th_seq = htonl(seq1); 120453642Sguido ch = 1; 120553642Sguido } 120653642Sguido } 120753642Sguido 120853642Sguido if (inc && (seq1 > aps->aps_seqmin[!sel])) { 1209102520Sdarrenr aps->aps_seqmin[sel] = seq1 + nlen - 1; 1210102520Sdarrenr aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc; 1211255332Scy if (softp->ips_proxy_debug & 0x10) 1212145522Sdarrenr printf("proxy seq set %d at %x to %d + %d\n", 1213145522Sdarrenr sel, aps->aps_seqmin[sel], 1214145522Sdarrenr aps->aps_seqoff[sel], inc); 121553642Sguido } 121653642Sguido 121753642Sguido /***/ 121853642Sguido 121953642Sguido seq1 = ntohl(tcp->th_ack); 122053642Sguido sel = aps->aps_sel[1 - out]; 122153642Sguido 122253642Sguido /* switch to other set ? */ 122353642Sguido if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 1224102520Sdarrenr (seq1 > aps->aps_ackmin[!sel])) { 1225255332Scy if (softp->ips_proxy_debug & 0x10) 1226145522Sdarrenr printf("proxy out switch set ack %d -> %d %x > %x\n", 1227145522Sdarrenr sel, !sel, seq1, 1228145522Sdarrenr aps->aps_ackmin[!sel]); 122953642Sguido sel = aps->aps_sel[1 - out] = !sel; 1230110916Sdarrenr } 123153642Sguido 123253642Sguido if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) { 123353642Sguido seq2 = aps->aps_ackoff[sel]; 123453642Sguido tcp->th_ack = htonl(seq1 - seq2); 123553642Sguido ch = 1; 123653642Sguido } 123753642Sguido } else { 123853642Sguido seq1 = ntohl(tcp->th_seq); 123953642Sguido sel = aps->aps_sel[out]; 124053642Sguido 124153642Sguido /* switch to other set ? */ 124253642Sguido if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 1243102520Sdarrenr (seq1 > aps->aps_ackmin[!sel])) { 1244255332Scy if (softp->ips_proxy_debug & 0x10) 1245145522Sdarrenr printf("proxy in switch set ack %d -> %d %x > %x\n", 1246145522Sdarrenr sel, !sel, seq1, aps->aps_ackmin[!sel]); 124753642Sguido sel = aps->aps_sel[out] = !sel; 1248110916Sdarrenr } 124953642Sguido 125053642Sguido if (aps->aps_ackoff[sel]) { 1251102520Sdarrenr seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel]; 125253642Sguido if (seq1 > seq2) { 125353642Sguido seq2 = aps->aps_ackoff[sel]; 125453642Sguido seq1 += seq2; 125553642Sguido tcp->th_seq = htonl(seq1); 125653642Sguido ch = 1; 125753642Sguido } 125853642Sguido } 125953642Sguido 126053642Sguido if (inc && (seq1 > aps->aps_ackmin[!sel])) { 126153642Sguido aps->aps_ackmin[!sel] = seq1 + nlen - 1; 126253642Sguido aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; 1263145522Sdarrenr 1264255332Scy if (softp->ips_proxy_debug & 0x10) 1265145522Sdarrenr printf("proxy ack set %d at %x to %d + %d\n", 1266145522Sdarrenr !sel, aps->aps_seqmin[!sel], 1267145522Sdarrenr aps->aps_seqoff[sel], inc); 126853642Sguido } 126953642Sguido 127053642Sguido /***/ 127153642Sguido 127253642Sguido seq1 = ntohl(tcp->th_ack); 127353642Sguido sel = aps->aps_sel[1 - out]; 127453642Sguido 127553642Sguido /* switch to other set ? */ 127653642Sguido if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 1277102520Sdarrenr (seq1 > aps->aps_seqmin[!sel])) { 1278255332Scy if (softp->ips_proxy_debug & 0x10) 1279145522Sdarrenr printf("proxy in switch set seq %d -> %d %x > %x\n", 1280145522Sdarrenr sel, !sel, seq1, aps->aps_seqmin[!sel]); 128153642Sguido sel = aps->aps_sel[1 - out] = !sel; 1282110916Sdarrenr } 128353642Sguido 1284102520Sdarrenr if (aps->aps_seqoff[sel] != 0) { 1285255332Scy if (softp->ips_proxy_debug & 0x10) 1286145522Sdarrenr printf("sel %d seqoff %d seq1 %x seqmin %x\n", 1287145522Sdarrenr sel, aps->aps_seqoff[sel], seq1, 1288145522Sdarrenr aps->aps_seqmin[sel]); 1289102520Sdarrenr if (seq1 > aps->aps_seqmin[sel]) { 1290102520Sdarrenr seq2 = aps->aps_seqoff[sel]; 1291102520Sdarrenr tcp->th_ack = htonl(seq1 - seq2); 1292102520Sdarrenr ch = 1; 1293102520Sdarrenr } 129453642Sguido } 129553642Sguido } 1296145522Sdarrenr 1297255332Scy if (softp->ips_proxy_debug & 0x10) 1298255332Scy printf("ipf_proxy_fixseqack: seq %u ack %u\n", 1299170268Sdarrenr (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack)); 130053642Sguido return ch ? 2 : 0; 130153642Sguido} 130253642Sguido 130353642Sguido 1304255332Scy/* ------------------------------------------------------------------------ */ 1305255332Scy/* Function: ipf_proxy_rule_rev */ 1306255332Scy/* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ 1307255332Scy/* Parameters: nat(I) - pointer to NAT session to create rule from */ 1308255332Scy/* */ 1309255332Scy/* This function creates a NAT rule that is based upon the reverse packet */ 1310255332Scy/* flow associated with this NAT session. Thus if this NAT session was */ 1311255332Scy/* created with a map rule then this function will create a rdr rule. */ 1312255332Scy/* Only address fields and network interfaces are assigned in this function */ 1313255332Scy/* and the address fields are formed such that an exact is required. If the */ 1314255332Scy/* original rule had a netmask, that is not replicated here not is it */ 1315255332Scy/* desired. The ultimate goal here is to create a NAT rule to support a NAT */ 1316255332Scy/* session being created that does not have a user configured rule. The */ 1317255332Scy/* classic example is supporting the FTP proxy, where a data channel needs */ 1318255332Scy/* to be setup, based on the addresses used for the control connection. In */ 1319255332Scy/* that case, this function is used to handle creating NAT rules to support */ 1320255332Scy/* data connections with the PORT and EPRT commands. */ 1321255332Scy/* ------------------------------------------------------------------------ */ 1322255332Scyipnat_t * 1323255332Scyipf_proxy_rule_rev(nat) 1324255332Scy nat_t *nat; 132553642Sguido{ 1326255332Scy ipnat_t *old; 1327255332Scy ipnat_t *ipn; 1328255332Scy int size; 132953642Sguido 1330255332Scy old = nat->nat_ptr; 1331255332Scy size = old->in_size; 1332255332Scy 1333255332Scy KMALLOCS(ipn, ipnat_t *, size); 1334255332Scy if (ipn == NULL) 1335255332Scy return NULL; 1336255332Scy 1337255332Scy bzero((char *)ipn, size); 1338255332Scy 1339255332Scy ipn->in_use = 1; 1340255332Scy ipn->in_hits = 1; 1341255332Scy ipn->in_ippip = 1; 1342255332Scy ipn->in_apr = NULL; 1343255332Scy ipn->in_size = size; 1344255332Scy ipn->in_pr[0] = old->in_pr[1]; 1345255332Scy ipn->in_pr[1] = old->in_pr[0]; 1346255332Scy ipn->in_v[0] = old->in_v[1]; 1347255332Scy ipn->in_v[1] = old->in_v[0]; 1348255332Scy ipn->in_ifps[0] = old->in_ifps[1]; 1349255332Scy ipn->in_ifps[1] = old->in_ifps[0]; 1350255332Scy ipn->in_flags = (old->in_flags | IPN_PROXYRULE); 1351255332Scy 1352255332Scy ipn->in_nsrcip6 = nat->nat_odst6; 1353255332Scy ipn->in_osrcip6 = nat->nat_ndst6; 1354255332Scy 1355255332Scy if ((old->in_redir & NAT_REDIRECT) != 0) { 1356255332Scy ipn->in_redir = NAT_MAP; 1357255332Scy if (ipn->in_v[0] == 4) { 1358255332Scy ipn->in_snip = ntohl(nat->nat_odstaddr); 1359255332Scy ipn->in_dnip = ntohl(nat->nat_nsrcaddr); 1360255332Scy } else { 1361255332Scy#ifdef USE_INET6 1362255332Scy ipn->in_snip6 = nat->nat_odst6; 1363255332Scy ipn->in_dnip6 = nat->nat_nsrc6; 1364255332Scy#endif 1365145522Sdarrenr } 1366255332Scy ipn->in_ndstip6 = nat->nat_nsrc6; 1367255332Scy ipn->in_odstip6 = nat->nat_osrc6; 1368255332Scy } else { 1369255332Scy ipn->in_redir = NAT_REDIRECT; 1370255332Scy if (ipn->in_v[0] == 4) { 1371255332Scy ipn->in_snip = ntohl(nat->nat_odstaddr); 1372255332Scy ipn->in_dnip = ntohl(nat->nat_osrcaddr); 1373255332Scy } else { 1374255332Scy#ifdef USE_INET6 1375255332Scy ipn->in_snip6 = nat->nat_odst6; 1376255332Scy ipn->in_dnip6 = nat->nat_osrc6; 1377255332Scy#endif 1378255332Scy } 1379255332Scy ipn->in_ndstip6 = nat->nat_osrc6; 1380255332Scy ipn->in_odstip6 = nat->nat_nsrc6; 138153642Sguido } 1382255332Scy 1383255332Scy IP6_SETONES(&ipn->in_osrcmsk6); 1384255332Scy IP6_SETONES(&ipn->in_nsrcmsk6); 1385255332Scy IP6_SETONES(&ipn->in_odstmsk6); 1386255332Scy IP6_SETONES(&ipn->in_ndstmsk6); 1387255332Scy 1388255332Scy ipn->in_namelen = old->in_namelen; 1389255332Scy ipn->in_ifnames[0] = old->in_ifnames[1]; 1390255332Scy ipn->in_ifnames[1] = old->in_ifnames[0]; 1391255332Scy bcopy(old->in_names, ipn->in_names, ipn->in_namelen); 1392255332Scy MUTEX_INIT(&ipn->in_lock, "ipnat rev rule lock"); 1393255332Scy 1394255332Scy return ipn; 139553642Sguido} 139660855Sdarrenr 139760855Sdarrenr 1398255332Scy/* ------------------------------------------------------------------------ */ 1399255332Scy/* Function: ipf_proxy_rule_fwd */ 1400255332Scy/* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ 1401255332Scy/* Parameters: nat(I) - pointer to NAT session to create rule from */ 1402255332Scy/* */ 1403255332Scy/* The purpose and rationale of this function is much the same as the above */ 1404255332Scy/* function, ipf_proxy_rule_rev, except that a rule is created that matches */ 1405255332Scy/* the same direction as that of the existing NAT session. Thus if this NAT */ 1406255332Scy/* session was created with a map rule then this function will also create */ 1407255332Scy/* a data structure to represent a map rule. Whereas ipf_proxy_rule_rev is */ 1408255332Scy/* used to support PORT/EPRT, this function supports PASV/EPSV. */ 1409255332Scy/* ------------------------------------------------------------------------ */ 1410255332Scyipnat_t * 1411255332Scyipf_proxy_rule_fwd(nat) 1412255332Scy nat_t *nat; 141360855Sdarrenr{ 1414255332Scy ipnat_t *old; 1415255332Scy ipnat_t *ipn; 1416255332Scy int size; 141760855Sdarrenr 1418255332Scy old = nat->nat_ptr; 1419255332Scy size = old->in_size; 1420255332Scy 1421255332Scy KMALLOCS(ipn, ipnat_t *, size); 1422255332Scy if (ipn == NULL) 1423255332Scy return NULL; 1424255332Scy 1425255332Scy bzero((char *)ipn, size); 1426255332Scy 1427255332Scy ipn->in_use = 1; 1428255332Scy ipn->in_hits = 1; 1429255332Scy ipn->in_ippip = 1; 1430255332Scy ipn->in_apr = NULL; 1431255332Scy ipn->in_size = size; 1432255332Scy ipn->in_pr[0] = old->in_pr[0]; 1433255332Scy ipn->in_pr[1] = old->in_pr[1]; 1434255332Scy ipn->in_v[0] = old->in_v[0]; 1435255332Scy ipn->in_v[1] = old->in_v[1]; 1436255332Scy ipn->in_ifps[0] = nat->nat_ifps[0]; 1437255332Scy ipn->in_ifps[1] = nat->nat_ifps[1]; 1438255332Scy ipn->in_flags = (old->in_flags | IPN_PROXYRULE); 1439255332Scy 1440255332Scy ipn->in_nsrcip6 = nat->nat_nsrc6; 1441255332Scy ipn->in_osrcip6 = nat->nat_osrc6; 1442255332Scy ipn->in_ndstip6 = nat->nat_ndst6; 1443255332Scy ipn->in_odstip6 = nat->nat_odst6; 1444255332Scy ipn->in_redir = old->in_redir; 1445255332Scy 1446255332Scy if (ipn->in_v[0] == 4) { 1447255332Scy ipn->in_snip = ntohl(nat->nat_nsrcaddr); 1448255332Scy ipn->in_dnip = ntohl(nat->nat_ndstaddr); 1449255332Scy } else { 1450255332Scy#ifdef USE_INET6 1451255332Scy ipn->in_snip6 = nat->nat_nsrc6; 1452255332Scy ipn->in_dnip6 = nat->nat_ndst6; 1453255332Scy#endif 1454255332Scy } 1455255332Scy 1456255332Scy IP6_SETONES(&ipn->in_osrcmsk6); 1457255332Scy IP6_SETONES(&ipn->in_nsrcmsk6); 1458255332Scy IP6_SETONES(&ipn->in_odstmsk6); 1459255332Scy IP6_SETONES(&ipn->in_ndstmsk6); 1460255332Scy 1461255332Scy ipn->in_namelen = old->in_namelen; 1462255332Scy ipn->in_ifnames[0] = old->in_ifnames[0]; 1463255332Scy ipn->in_ifnames[1] = old->in_ifnames[1]; 1464255332Scy bcopy(old->in_names, ipn->in_names, ipn->in_namelen); 1465255332Scy MUTEX_INIT(&ipn->in_lock, "ipnat fwd rule lock"); 1466255332Scy 1467255332Scy return ipn; 146860855Sdarrenr} 1469