1145522Sdarrenr/* $FreeBSD: releng/11.0/sys/contrib/ipfilter/netinet/ip_proxy.c 302298 2016-06-30 15:01:07Z bz $ */ 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> 67302298Sbz#if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000) && defined(_KERNEL) 68302298Sbz#include <net/vnet.h> 69302298Sbz#else 70302298Sbz#define CURVNET_SET(arg) 71302298Sbz#define CURVNET_RESTORE() 72302298Sbz#define VNET_DEFINE(_t, _v) _t _v 73302298Sbz#define VNET_DECLARE(_t, _v) extern _t _v 74302298Sbz#define VNET(arg) arg 75302298Sbz#endif 7653642Sguido#ifdef sun 7753642Sguido# include <net/af.h> 7853642Sguido#endif 7953642Sguido#include <netinet/in.h> 8053642Sguido#include <netinet/in_systm.h> 8153642Sguido#include <netinet/ip.h> 8253642Sguido#ifndef linux 8353642Sguido# include <netinet/ip_var.h> 8453642Sguido#endif 8553642Sguido#include <netinet/tcp.h> 8653642Sguido#include <netinet/udp.h> 8753642Sguido#include <netinet/ip_icmp.h> 8853642Sguido#include "netinet/ip_compat.h" 8953642Sguido#include <netinet/tcpip.h> 9053642Sguido#include "netinet/ip_fil.h" 9153642Sguido#include "netinet/ip_nat.h" 9253642Sguido#include "netinet/ip_state.h" 9392685Sdarrenr#include "netinet/ip_proxy.h" 9453642Sguido#if (__FreeBSD_version >= 300000) 9553642Sguido# include <sys/malloc.h> 9653642Sguido#endif 9753642Sguido 98255332Scy/* END OF INCLUDES */ 99255332Scy 100145522Sdarrenr#include "netinet/ip_ftp_pxy.c" 101255332Scy#include "netinet/ip_tftp_pxy.c" 102145522Sdarrenr#include "netinet/ip_rcmd_pxy.c" 103255332Scy#include "netinet/ip_pptp_pxy.c" 104145522Sdarrenr#if defined(_KERNEL) 105145522Sdarrenr# include "netinet/ip_irc_pxy.c" 106145522Sdarrenr# include "netinet/ip_raudio_pxy.c" 107145522Sdarrenr# include "netinet/ip_netbios_pxy.c" 10880482Sdarrenr#endif 109145522Sdarrenr#include "netinet/ip_ipsec_pxy.c" 110145522Sdarrenr#include "netinet/ip_rpcb_pxy.c" 11153642Sguido 112145522Sdarrenr#if !defined(lint) 113255332Scystatic const char rcsid[] = "@(#)$Id$"; 11492685Sdarrenr#endif 11580482Sdarrenr 11653642Sguido#define AP_SESS_SIZE 53 11753642Sguido 118255332Scystatic int ipf_proxy_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); 119255332Scystatic aproxy_t *ipf_proxy_create_clone __P((ipf_main_softc_t *, aproxy_t *)); 120255332Scy 121255332Scytypedef struct ipf_proxy_softc_s { 122255332Scy int ips_proxy_debug; 123255332Scy int ips_proxy_session_size; 124255332Scy ap_session_t **ips_sess_tab; 125255332Scy ap_session_t *ips_sess_list; 126255332Scy aproxy_t *ips_proxies; 127255332Scy int ips_init_run; 128255332Scy ipftuneable_t *ipf_proxy_tune; 129255332Scy} ipf_proxy_softc_t; 130255332Scy 131255332Scystatic ipftuneable_t ipf_proxy_tuneables[] = { 132255332Scy { { (void *)offsetof(ipf_proxy_softc_t, ips_proxy_debug) }, 133255332Scy "proxy_debug", 0, 0x1f, 134255332Scy stsizeof(ipf_proxy_softc_t, ips_proxy_debug), 135255332Scy 0, NULL, NULL }, 136255332Scy { { NULL }, NULL, 0, 0, 137255332Scy 0, 138255332Scy 0, NULL, NULL} 139255332Scy}; 140255332Scy 141255332Scystatic aproxy_t *ap_proxylist = NULL; 142255332Scystatic aproxy_t ips_proxies[] = { 14353642Sguido#ifdef IPF_FTP_PROXY 144255332Scy { NULL, NULL, "ftp", (char)IPPROTO_TCP, 0, 0, 0, 145255332Scy ipf_p_ftp_main_load, ipf_p_ftp_main_unload, 146255332Scy ipf_p_ftp_soft_create, ipf_p_ftp_soft_destroy, 147255332Scy NULL, NULL, 148255332Scy ipf_p_ftp_new, ipf_p_ftp_del, ipf_p_ftp_in, ipf_p_ftp_out, NULL, 149255332Scy NULL, NULL, NULL, NULL }, 15053642Sguido#endif 151255332Scy#ifdef IPF_TFTP_PROXY 152255332Scy { NULL, NULL, "tftp", (char)IPPROTO_UDP, 0, 0, 0, 153255332Scy ipf_p_tftp_main_load, ipf_p_tftp_main_unload, 154255332Scy ipf_p_tftp_soft_create, ipf_p_tftp_soft_destroy, 155255332Scy NULL, NULL, 156255332Scy ipf_p_tftp_new, ipf_p_tftp_del, 157255332Scy ipf_p_tftp_in, ipf_p_tftp_out, NULL, 158255332Scy NULL, NULL, NULL, NULL }, 159255332Scy#endif 160145522Sdarrenr#ifdef IPF_IRC_PROXY 161255332Scy { NULL, NULL, "irc", (char)IPPROTO_TCP, 0, 0, 0, 162255332Scy ipf_p_irc_main_load, ipf_p_irc_main_unload, 163255332Scy NULL, NULL, 164255332Scy NULL, NULL, 165255332Scy ipf_p_irc_new, NULL, NULL, ipf_p_irc_out, NULL, 166255332Scy NULL, NULL, NULL, NULL }, 167145522Sdarrenr#endif 16853642Sguido#ifdef IPF_RCMD_PROXY 169255332Scy { NULL, NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, 0, 170255332Scy ipf_p_rcmd_main_load, ipf_p_rcmd_main_unload, 171255332Scy NULL, NULL, 172255332Scy NULL, NULL, 173255332Scy ipf_p_rcmd_new, ipf_p_rcmd_del, 174255332Scy ipf_p_rcmd_in, ipf_p_rcmd_out, NULL, 175255332Scy NULL, NULL, NULL, NULL }, 17653642Sguido#endif 17753642Sguido#ifdef IPF_RAUDIO_PROXY 178255332Scy { NULL, NULL, "raudio", (char)IPPROTO_TCP, 0, 0, 0, 179255332Scy ipf_p_raudio_main_load, ipf_p_raudio_main_unload, 180255332Scy NULL, NULL, 181255332Scy NULL, NULL, 182255332Scy ipf_p_raudio_new, NULL, ipf_p_raudio_in, ipf_p_raudio_out, NULL, 183255332Scy NULL, NULL, NULL, NULL }, 18453642Sguido#endif 185145522Sdarrenr#ifdef IPF_MSNRPC_PROXY 186255332Scy { NULL, NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, 0, 187255332Scy ipf_p_msnrpc_init, ipf_p_msnrpc_fini, 188255332Scy NULL, NULL, 189255332Scy NULL, NULL, 190255332Scy ipf_p_msnrpc_new, NULL, ipf_p_msnrpc_in, ipf_p_msnrpc_out, NULL, 191255332Scy NULL, NULL, NULL, NULL }, 19292685Sdarrenr#endif 19392685Sdarrenr#ifdef IPF_NETBIOS_PROXY 194255332Scy { NULL, NULL, "netbios", (char)IPPROTO_UDP, 0, 0, 0, 195255332Scy ipf_p_netbios_main_load, ipf_p_netbios_main_unload, 196255332Scy NULL, NULL, 197255332Scy NULL, NULL, 198255332Scy NULL, NULL, NULL, ipf_p_netbios_out, NULL, 199255332Scy NULL, NULL, NULL, NULL }, 20092685Sdarrenr#endif 201145522Sdarrenr#ifdef IPF_IPSEC_PROXY 202255332Scy { NULL, NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 0, 203255332Scy NULL, NULL, 204255332Scy ipf_p_ipsec_soft_create, ipf_p_ipsec_soft_destroy, 205255332Scy ipf_p_ipsec_soft_init, ipf_p_ipsec_soft_fini, 206255332Scy ipf_p_ipsec_new, ipf_p_ipsec_del, 207255332Scy ipf_p_ipsec_inout, ipf_p_ipsec_inout, ipf_p_ipsec_match, 208255332Scy NULL, NULL, NULL, NULL }, 209145522Sdarrenr#endif 210255332Scy#ifdef IPF_DNS_PROXY 211255332Scy { NULL, NULL, "dns", (char)IPPROTO_UDP, 0, 0, 0, 212255332Scy NULL, NULL, 213255332Scy ipf_p_dns_soft_create, ipf_p_dns_soft_destroy, 214255332Scy NULL, NULL, 215255332Scy ipf_p_dns_new, ipf_p_ipsec_del, 216255332Scy ipf_p_dns_inout, ipf_p_dns_inout, ipf_p_dns_match, 217255332Scy ipf_p_dns_ctl, NULL, NULL, NULL }, 218255332Scy#endif 219145522Sdarrenr#ifdef IPF_PPTP_PROXY 220255332Scy { NULL, NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 0, 221255332Scy ipf_p_pptp_main_load, ipf_p_pptp_main_unload, 222255332Scy NULL, NULL, 223255332Scy NULL, NULL, 224255332Scy ipf_p_pptp_new, ipf_p_pptp_del, 225255332Scy ipf_p_pptp_inout, ipf_p_pptp_inout, NULL, 226255332Scy NULL, NULL, NULL, NULL }, 227145522Sdarrenr#endif 228145522Sdarrenr#ifdef IPF_RPCB_PROXY 229255332Scy# ifndef _KERNEL 230255332Scy { NULL, NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 0, 231255332Scy NULL, NULL, 232255332Scy NULL, NULL, 233255332Scy NULL, NULL, 234255332Scy ipf_p_rpcb_new, ipf_p_rpcb_del, 235255332Scy ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, 236255332Scy NULL, NULL, NULL, NULL }, 237145522Sdarrenr# endif 238255332Scy { NULL, NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 0, 239255332Scy ipf_p_rpcb_main_load, ipf_p_rpcb_main_unload, 240255332Scy NULL, NULL, 241255332Scy NULL, NULL, 242255332Scy ipf_p_rpcb_new, ipf_p_rpcb_del, 243255332Scy ipf_p_rpcb_in, ipf_p_rpcb_out, NULL, 244255332Scy NULL, NULL, NULL, NULL }, 245145522Sdarrenr#endif 246255332Scy { NULL, NULL, "", '\0', 0, 0, 0, 247255332Scy NULL, NULL, 248255332Scy NULL, NULL, 249255332Scy NULL, NULL, 250255332Scy NULL, NULL, 251255332Scy NULL, NULL, NULL, 252255332Scy NULL, NULL, NULL, NULL } 25353642Sguido}; 25453642Sguido 255255332Scy 256255332Scy/* ------------------------------------------------------------------------ */ 257255332Scy/* Function: ipf_proxy_main_load */ 258255332Scy/* Returns: int - 0 == success, else failure. */ 259255332Scy/* Parameters: Nil */ 260255332Scy/* */ 261255332Scy/* Initialise hook for kernel application proxies. */ 262255332Scy/* Call the initialise routine for all the compiled in kernel proxies. */ 263255332Scy/* ------------------------------------------------------------------------ */ 264255332Scyint 265255332Scyipf_proxy_main_load() 26660855Sdarrenr{ 267255332Scy aproxy_t *ap; 268255332Scy 269255332Scy for (ap = ips_proxies; ap->apr_p; ap++) { 270255332Scy if (ap->apr_load != NULL) 271255332Scy (*ap->apr_load)(); 272255332Scy } 273255332Scy return 0; 274255332Scy} 275255332Scy 276255332Scy 277255332Scy/* ------------------------------------------------------------------------ */ 278255332Scy/* Function: ipf_proxy_main_unload */ 279255332Scy/* Returns: int - 0 == success, else failure. */ 280255332Scy/* Parameters: Nil */ 281255332Scy/* */ 282255332Scy/* Unload hook for kernel application proxies. */ 283255332Scy/* Call the finialise routine for all the compiled in kernel proxies. */ 284255332Scy/* ------------------------------------------------------------------------ */ 285255332Scyint 286255332Scyipf_proxy_main_unload() 287255332Scy{ 288255332Scy aproxy_t *ap; 289255332Scy 290255332Scy for (ap = ips_proxies; ap->apr_p; ap++) 291255332Scy if (ap->apr_unload != NULL) 292255332Scy (*ap->apr_unload)(); 293255332Scy for (ap = ap_proxylist; ap; ap = ap->apr_next) 294255332Scy if (ap->apr_unload != NULL) 295255332Scy (*ap->apr_unload)(); 296255332Scy 297255332Scy return 0; 298255332Scy} 299255332Scy 300255332Scy 301255332Scy/* ------------------------------------------------------------------------ */ 302255332Scy/* Function: ipf_proxy_soft_create */ 303255332Scy/* Returns: void * - */ 304255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 305255332Scy/* */ 306255332Scy/* Build the structure to hold all of the run time data to support proxies. */ 307255332Scy/* ------------------------------------------------------------------------ */ 308255332Scyvoid * 309255332Scyipf_proxy_soft_create(softc) 310255332Scy ipf_main_softc_t *softc; 311255332Scy{ 312255332Scy ipf_proxy_softc_t *softp; 313255332Scy aproxy_t *last; 314255332Scy aproxy_t *apn; 315255332Scy aproxy_t *ap; 316255332Scy 317255332Scy KMALLOC(softp, ipf_proxy_softc_t *); 318255332Scy if (softp == NULL) 319255332Scy return softp; 320255332Scy 321255332Scy bzero((char *)softp, sizeof(*softp)); 322255332Scy 323255332Scy#if defined(_KERNEL) 324255332Scy softp->ips_proxy_debug = 0; 325255332Scy#else 326255332Scy softp->ips_proxy_debug = 2; 327255332Scy#endif 328255332Scy softp->ips_proxy_session_size = AP_SESS_SIZE; 329255332Scy 330255332Scy softp->ipf_proxy_tune = ipf_tune_array_copy(softp, 331255332Scy sizeof(ipf_proxy_tuneables), 332255332Scy ipf_proxy_tuneables); 333255332Scy if (softp->ipf_proxy_tune == NULL) { 334255332Scy ipf_proxy_soft_destroy(softc, softp); 335255332Scy return NULL; 336255332Scy } 337255332Scy if (ipf_tune_array_link(softc, softp->ipf_proxy_tune) == -1) { 338255332Scy ipf_proxy_soft_destroy(softc, softp); 339255332Scy return NULL; 340255332Scy } 341255332Scy 342255332Scy last = NULL; 343255332Scy for (ap = ips_proxies; ap->apr_p; ap++) { 344255332Scy apn = ipf_proxy_create_clone(softc, ap); 345255332Scy if (apn == NULL) 346255332Scy goto failed; 347255332Scy if (last != NULL) 348255332Scy last->apr_next = apn; 349255332Scy else 350255332Scy softp->ips_proxies = apn; 351255332Scy last = apn; 352255332Scy } 353255332Scy for (ap = ips_proxies; ap != NULL; ap = ap->apr_next) { 354255332Scy apn = ipf_proxy_create_clone(softc, ap); 355255332Scy if (apn == NULL) 356255332Scy goto failed; 357255332Scy if (last != NULL) 358255332Scy last->apr_next = apn; 359255332Scy else 360255332Scy softp->ips_proxies = apn; 361255332Scy last = apn; 362255332Scy } 363255332Scy 364255332Scy return softp; 365255332Scyfailed: 366255332Scy ipf_proxy_soft_destroy(softc, softp); 367255332Scy return NULL; 368255332Scy} 369255332Scy 370255332Scy 371255332Scy/* ------------------------------------------------------------------------ */ 372255332Scy/* Function: ipf_proxy_soft_create */ 373255332Scy/* Returns: void * - */ 374255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 375255332Scy/* orig(I) - pointer to proxy definition to copy */ 376255332Scy/* */ 377255332Scy/* This function clones a proxy definition given by orig and returns a */ 378255332Scy/* a pointer to that copy. */ 379255332Scy/* ------------------------------------------------------------------------ */ 380255332Scystatic aproxy_t * 381255332Scyipf_proxy_create_clone(softc, orig) 382255332Scy ipf_main_softc_t *softc; 383255332Scy aproxy_t *orig; 384255332Scy{ 385255332Scy aproxy_t *apn; 386255332Scy 387255332Scy KMALLOC(apn, aproxy_t *); 388255332Scy if (apn == NULL) 389255332Scy return NULL; 390255332Scy 391255332Scy bcopy((char *)orig, (char *)apn, sizeof(*apn)); 392255332Scy apn->apr_next = NULL; 393255332Scy apn->apr_soft = NULL; 394255332Scy 395255332Scy if (apn->apr_create != NULL) { 396255332Scy apn->apr_soft = (*apn->apr_create)(softc); 397255332Scy if (apn->apr_soft == NULL) { 398255332Scy KFREE(apn); 399255332Scy return NULL; 400255332Scy } 401255332Scy } 402255332Scy 403255332Scy apn->apr_parent = orig; 404255332Scy orig->apr_clones++; 405255332Scy 406255332Scy return apn; 407255332Scy} 408255332Scy 409255332Scy 410255332Scy/* ------------------------------------------------------------------------ */ 411255332Scy/* Function: ipf_proxy_soft_create */ 412255332Scy/* Returns: int - 0 == success, else failure. */ 413255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 414255332Scy/* arg(I) - pointer to proxy contect data */ 415255332Scy/* */ 416255332Scy/* Initialise the proxy context and walk through each of the proxies and */ 417255332Scy/* call its initialisation function. This allows for proxies to do any */ 418255332Scy/* local setup prior to actual use. */ 419255332Scy/* ------------------------------------------------------------------------ */ 420255332Scyint 421255332Scyipf_proxy_soft_init(softc, arg) 422255332Scy ipf_main_softc_t *softc; 423255332Scy void *arg; 424255332Scy{ 425255332Scy ipf_proxy_softc_t *softp; 426255332Scy aproxy_t *ap; 427255332Scy u_int size; 428255332Scy int err; 429255332Scy 430255332Scy softp = arg; 431255332Scy size = softp->ips_proxy_session_size * sizeof(ap_session_t *); 432255332Scy 433255332Scy KMALLOCS(softp->ips_sess_tab, ap_session_t **, size); 434255332Scy 435255332Scy if (softp->ips_sess_tab == NULL) 436255332Scy return -1; 437255332Scy 438255332Scy bzero(softp->ips_sess_tab, size); 439255332Scy 440255332Scy for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { 441255332Scy if (ap->apr_init != NULL) { 442255332Scy err = (*ap->apr_init)(softc, ap->apr_soft); 443255332Scy if (err != 0) 444255332Scy return -2; 445255332Scy } 446255332Scy } 447255332Scy softp->ips_init_run = 1; 448255332Scy 449255332Scy return 0; 450255332Scy} 451255332Scy 452255332Scy 453255332Scy/* ------------------------------------------------------------------------ */ 454255332Scy/* Function: ipf_proxy_soft_create */ 455255332Scy/* Returns: int - 0 == success, else failure. */ 456255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 457255332Scy/* arg(I) - pointer to proxy contect data */ 458255332Scy/* */ 459255332Scy/* This function should always succeed. It is responsible for ensuring that */ 460255332Scy/* the proxy context can be safely called when ipf_proxy_soft_destroy is */ 461255332Scy/* called and suring all of the proxies have similarly been instructed. */ 462255332Scy/* ------------------------------------------------------------------------ */ 463255332Scyint 464255332Scyipf_proxy_soft_fini(softc, arg) 465255332Scy ipf_main_softc_t *softc; 466255332Scy void *arg; 467255332Scy{ 468255332Scy ipf_proxy_softc_t *softp = arg; 469255332Scy aproxy_t *ap; 470255332Scy 471255332Scy for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) { 472255332Scy if (ap->apr_fini != NULL) { 473255332Scy (*ap->apr_fini)(softc, ap->apr_soft); 474255332Scy } 475255332Scy } 476255332Scy 477255332Scy if (softp->ips_sess_tab != NULL) { 478255332Scy KFREES(softp->ips_sess_tab, 479255332Scy softp->ips_proxy_session_size * sizeof(ap_session_t *)); 480255332Scy softp->ips_sess_tab = NULL; 481255332Scy } 482255332Scy softp->ips_init_run = 0; 483255332Scy 484255332Scy return 0; 485255332Scy} 486255332Scy 487255332Scy 488255332Scy/* ------------------------------------------------------------------------ */ 489255332Scy/* Function: ipf_proxy_soft_destroy */ 490255332Scy/* Returns: Nil */ 491255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 492255332Scy/* arg(I) - pointer to proxy contect data */ 493255332Scy/* */ 494255332Scy/* Free up all of the local data structures allocated during creation. */ 495255332Scy/* ------------------------------------------------------------------------ */ 496255332Scyvoid 497255332Scyipf_proxy_soft_destroy(softc, arg) 498255332Scy ipf_main_softc_t *softc; 499255332Scy void *arg; 500255332Scy{ 501255332Scy ipf_proxy_softc_t *softp = arg; 502255332Scy aproxy_t *ap; 503255332Scy 504255332Scy while ((ap = softp->ips_proxies) != NULL) { 505255332Scy softp->ips_proxies = ap->apr_next; 506255332Scy if (ap->apr_destroy != NULL) 507255332Scy (*ap->apr_destroy)(softc, ap->apr_soft); 508255332Scy ap->apr_parent->apr_clones--; 509255332Scy KFREE(ap); 510255332Scy } 511255332Scy 512255332Scy if (softp->ipf_proxy_tune != NULL) { 513255332Scy ipf_tune_array_unlink(softc, softp->ipf_proxy_tune); 514255332Scy KFREES(softp->ipf_proxy_tune, sizeof(ipf_proxy_tuneables)); 515255332Scy softp->ipf_proxy_tune = NULL; 516255332Scy } 517255332Scy 518255332Scy KFREE(softp); 519255332Scy} 520255332Scy 521255332Scy 522255332Scy/* ------------------------------------------------------------------------ */ 523255332Scy/* Function: ipf_proxy_flush */ 524255332Scy/* Returns: Nil */ 525255332Scy/* Parameters: arg(I) - pointer to proxy contect data */ 526255332Scy/* how(I) - indicates the type of flush operation */ 527255332Scy/* */ 528255332Scy/* Walk through all of the proxies and pass on the flush command as either */ 529255332Scy/* a flush or a clear. */ 530255332Scy/* ------------------------------------------------------------------------ */ 531255332Scyvoid 532255332Scyipf_proxy_flush(arg, how) 533255332Scy void *arg; 534255332Scy int how; 535255332Scy{ 536255332Scy ipf_proxy_softc_t *softp = arg; 537255332Scy aproxy_t *ap; 538255332Scy 539255332Scy switch (how) 540255332Scy { 541255332Scy case 0 : 542255332Scy for (ap = softp->ips_proxies; ap; ap = ap->apr_next) 543255332Scy if (ap->apr_flush != NULL) 544255332Scy (*ap->apr_flush)(ap, how); 545255332Scy break; 546255332Scy case 1 : 547255332Scy for (ap = softp->ips_proxies; ap; ap = ap->apr_next) 548255332Scy if (ap->apr_clear != NULL) 549255332Scy (*ap->apr_clear)(ap); 550255332Scy break; 551255332Scy default : 552255332Scy break; 553255332Scy } 554255332Scy} 555255332Scy 556255332Scy 557255332Scy/* ------------------------------------------------------------------------ */ 558255332Scy/* Function: ipf_proxy_add */ 559255332Scy/* Returns: int - 0 == success, else failure. */ 560255332Scy/* Parameters: ap(I) - pointer to proxy structure */ 561255332Scy/* */ 562255332Scy/* Dynamically add a new kernel proxy. Ensure that it is unique in the */ 563255332Scy/* collection compiled in and dynamically added. */ 564255332Scy/* ------------------------------------------------------------------------ */ 565255332Scyint 566255332Scyipf_proxy_add(arg, ap) 567255332Scy void *arg; 568255332Scy aproxy_t *ap; 569255332Scy{ 570255332Scy ipf_proxy_softc_t *softp = arg; 571255332Scy 57260855Sdarrenr aproxy_t *a; 57360855Sdarrenr 574255332Scy for (a = ips_proxies; a->apr_p; a++) 57560855Sdarrenr if ((a->apr_p == ap->apr_p) && 57660855Sdarrenr !strncmp(a->apr_label, ap->apr_label, 577145522Sdarrenr sizeof(ap->apr_label))) { 578255332Scy if (softp->ips_proxy_debug & 0x01) 579255332Scy printf("ipf_proxy_add: %s/%d present (B)\n", 580145522Sdarrenr a->apr_label, a->apr_p); 58160855Sdarrenr return -1; 582145522Sdarrenr } 58360855Sdarrenr 584170268Sdarrenr for (a = ap_proxylist; (a != NULL); a = a->apr_next) 58560855Sdarrenr if ((a->apr_p == ap->apr_p) && 58660855Sdarrenr !strncmp(a->apr_label, ap->apr_label, 587145522Sdarrenr sizeof(ap->apr_label))) { 588255332Scy if (softp->ips_proxy_debug & 0x01) 589255332Scy printf("ipf_proxy_add: %s/%d present (D)\n", 590145522Sdarrenr a->apr_label, a->apr_p); 59160855Sdarrenr return -1; 592145522Sdarrenr } 59360855Sdarrenr ap->apr_next = ap_proxylist; 59460855Sdarrenr ap_proxylist = ap; 595255332Scy if (ap->apr_load != NULL) 596255332Scy (*ap->apr_load)(); 597145522Sdarrenr return 0; 59860855Sdarrenr} 59960855Sdarrenr 60060855Sdarrenr 601255332Scy/* ------------------------------------------------------------------------ */ 602255332Scy/* Function: ipf_proxy_ctl */ 603255332Scy/* Returns: int - 0 == success, else error */ 604255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 605255332Scy/* arg(I) - pointer to proxy context */ 606255332Scy/* ctl(I) - pointer to proxy control structure */ 607255332Scy/* */ 608255332Scy/* Check to see if the proxy this control request has come through for */ 609255332Scy/* exists, and if it does and it has a control function then invoke that */ 610255332Scy/* control function. */ 611255332Scy/* ------------------------------------------------------------------------ */ 612255332Scyint 613255332Scyipf_proxy_ctl(softc, arg, ctl) 614255332Scy ipf_main_softc_t *softc; 615255332Scy void *arg; 616255332Scy ap_ctl_t *ctl; 617145522Sdarrenr{ 618255332Scy ipf_proxy_softc_t *softp = arg; 619145522Sdarrenr aproxy_t *a; 620145522Sdarrenr int error; 621145522Sdarrenr 622255332Scy a = ipf_proxy_lookup(arg, ctl->apc_p, ctl->apc_label); 623145522Sdarrenr if (a == NULL) { 624255332Scy if (softp->ips_proxy_debug & 0x01) 625255332Scy printf("ipf_proxy_ctl: can't find %s/%d\n", 626145522Sdarrenr ctl->apc_label, ctl->apc_p); 627255332Scy IPFERROR(80001); 628145522Sdarrenr error = ESRCH; 629145522Sdarrenr } else if (a->apr_ctl == NULL) { 630255332Scy if (softp->ips_proxy_debug & 0x01) 631255332Scy printf("ipf_proxy_ctl: no ctl function for %s/%d\n", 632145522Sdarrenr ctl->apc_label, ctl->apc_p); 633255332Scy IPFERROR(80002); 634145522Sdarrenr error = ENXIO; 635145522Sdarrenr } else { 636255332Scy error = (*a->apr_ctl)(softc, a->apr_soft, ctl); 637255332Scy if ((error != 0) && (softp->ips_proxy_debug & 0x02)) 638255332Scy printf("ipf_proxy_ctl: %s/%d ctl error %d\n", 639145522Sdarrenr a->apr_label, a->apr_p, error); 640145522Sdarrenr } 641145522Sdarrenr return error; 642145522Sdarrenr} 643145522Sdarrenr 644145522Sdarrenr 645255332Scy/* ------------------------------------------------------------------------ */ 646255332Scy/* Function: ipf_proxy_del */ 647255332Scy/* Returns: int - 0 == success, else failure. */ 648255332Scy/* Parameters: ap(I) - pointer to proxy structure */ 649255332Scy/* */ 650255332Scy/* Delete a proxy that has been added dynamically from those available. */ 651255332Scy/* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 */ 652255332Scy/* if it cannot be matched. */ 653255332Scy/* ------------------------------------------------------------------------ */ 654255332Scyint 655255332Scyipf_proxy_del(ap) 656255332Scy aproxy_t *ap; 65760855Sdarrenr{ 65860855Sdarrenr aproxy_t *a, **app; 65960855Sdarrenr 660255332Scy for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) { 66160855Sdarrenr if (a == ap) { 66292685Sdarrenr a->apr_flags |= APR_DELETE; 663255332Scy if (ap->apr_ref == 0 && ap->apr_clones == 0) { 664255332Scy *app = a->apr_next; 665255332Scy return 0; 666145522Sdarrenr } 667255332Scy return 1; 66860855Sdarrenr } 669255332Scy } 670255332Scy 67160855Sdarrenr return -1; 67260855Sdarrenr} 67360855Sdarrenr 67460855Sdarrenr 675255332Scy/* ------------------------------------------------------------------------ */ 676255332Scy/* Function: ipf_proxy_ok */ 677255332Scy/* Returns: int - 1 == good match else not. */ 678255332Scy/* Parameters: fin(I) - pointer to packet information */ 679255332Scy/* tcp(I) - pointer to TCP/UDP header */ 680255332Scy/* nat(I) - pointer to current NAT session */ 681255332Scy/* */ 682255332Scy/* This function extends the NAT matching to ensure that a packet that has */ 683255332Scy/* arrived matches the proxy information attached to the NAT rule. Notably, */ 684255332Scy/* if the proxy is scheduled to be deleted then packets will not match the */ 685255332Scy/* rule even if the rule is still active. */ 686255332Scy/* ------------------------------------------------------------------------ */ 687255332Scyint 688255332Scyipf_proxy_ok(fin, tcp, np) 689255332Scy fr_info_t *fin; 690255332Scy tcphdr_t *tcp; 691255332Scy ipnat_t *np; 69253642Sguido{ 693255332Scy aproxy_t *apr = np->in_apr; 694255332Scy u_short dport = np->in_odport; 69553642Sguido 69692685Sdarrenr if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || 697145522Sdarrenr (fin->fin_p != apr->apr_p)) 69853642Sguido return 0; 699145522Sdarrenr if ((tcp == NULL) && dport) 70053642Sguido return 0; 70153642Sguido return 1; 70253642Sguido} 70353642Sguido 70453642Sguido 705255332Scy/* ------------------------------------------------------------------------ */ 706255332Scy/* Function: ipf_proxy_ioctl */ 707255332Scy/* Returns: int - 0 == success, else error */ 708255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 709255332Scy/* data(I) - pointer to ioctl data */ 710255332Scy/* cmd(I) - ioctl command */ 711255332Scy/* mode(I) - mode bits for device */ 712255332Scy/* ctx(I) - pointer to context information */ 713255332Scy/* */ 714255332Scy/* ------------------------------------------------------------------------ */ 715255332Scyint 716255332Scyipf_proxy_ioctl(softc, data, cmd, mode, ctx) 717255332Scy ipf_main_softc_t *softc; 718255332Scy caddr_t data; 719255332Scy ioctlcmd_t cmd; 720255332Scy int mode; 721255332Scy void *ctx; 722145522Sdarrenr{ 723145522Sdarrenr ap_ctl_t ctl; 724255332Scy caddr_t ptr; 725145522Sdarrenr int error; 726145522Sdarrenr 727145522Sdarrenr mode = mode; /* LINT */ 728145522Sdarrenr 729145522Sdarrenr switch (cmd) 730145522Sdarrenr { 731145522Sdarrenr case SIOCPROXY : 732255332Scy error = ipf_inobj(softc, data, NULL, &ctl, IPFOBJ_PROXYCTL); 733255332Scy if (error != 0) { 734255332Scy return error; 735255332Scy } 736145522Sdarrenr ptr = NULL; 737145522Sdarrenr 738145522Sdarrenr if (ctl.apc_dsize > 0) { 739255332Scy KMALLOCS(ptr, caddr_t, ctl.apc_dsize); 740255332Scy if (ptr == NULL) { 741255332Scy IPFERROR(80003); 742145522Sdarrenr error = ENOMEM; 743255332Scy } else { 744255332Scy error = copyinptr(softc, ctl.apc_data, ptr, 745145522Sdarrenr ctl.apc_dsize); 746145522Sdarrenr if (error == 0) 747145522Sdarrenr ctl.apc_data = ptr; 748145522Sdarrenr } 749145522Sdarrenr } else { 750145522Sdarrenr ctl.apc_data = NULL; 751145522Sdarrenr error = 0; 752145522Sdarrenr } 753145522Sdarrenr 754145522Sdarrenr if (error == 0) 755255332Scy error = ipf_proxy_ctl(softc, softc->ipf_proxy_soft, 756255332Scy &ctl); 757145522Sdarrenr 758255332Scy if ((error != 0) && (ptr != NULL)) { 759145522Sdarrenr KFREES(ptr, ctl.apc_dsize); 760145522Sdarrenr } 761145522Sdarrenr break; 762145522Sdarrenr 763145522Sdarrenr default : 764255332Scy IPFERROR(80004); 765145522Sdarrenr error = EINVAL; 766145522Sdarrenr } 767145522Sdarrenr return error; 768145522Sdarrenr} 769145522Sdarrenr 770145522Sdarrenr 771255332Scy/* ------------------------------------------------------------------------ */ 772255332Scy/* Function: ipf_proxy_match */ 773255332Scy/* Returns: int - 0 == success, else error */ 774255332Scy/* Parameters: fin(I) - pointer to packet information */ 775255332Scy/* nat(I) - pointer to current NAT session */ 776255332Scy/* */ 777255332Scy/* If a proxy has a match function, call that to do extended packet */ 778255332Scy/* matching. Whilst other parts of the NAT code are rather lenient when it */ 779255332Scy/* comes to the quality of the packet that it will transform, the proxy */ 780255332Scy/* matching is not because they need to work with data, not just headers. */ 781255332Scy/* ------------------------------------------------------------------------ */ 782255332Scyint 783255332Scyipf_proxy_match(fin, nat) 784255332Scy fr_info_t *fin; 785255332Scy nat_t *nat; 78692685Sdarrenr{ 787255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 788255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 78992685Sdarrenr aproxy_t *apr; 79092685Sdarrenr ipnat_t *ipn; 791145522Sdarrenr int result; 79292685Sdarrenr 79392685Sdarrenr ipn = nat->nat_ptr; 794255332Scy if (softp->ips_proxy_debug & 0x04) 795255332Scy printf("ipf_proxy_match(%lx,%lx) aps %lx ptr %lx\n", 796145522Sdarrenr (u_long)fin, (u_long)nat, (u_long)nat->nat_aps, 797145522Sdarrenr (u_long)ipn); 798145522Sdarrenr 799145522Sdarrenr if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) { 800255332Scy if (softp->ips_proxy_debug & 0x08) 801255332Scy printf("ipf_proxy_match: flx 0x%x (BAD|SHORT)\n", 802145522Sdarrenr fin->fin_flx); 80392685Sdarrenr return -1; 804145522Sdarrenr } 805145522Sdarrenr 80692685Sdarrenr apr = ipn->in_apr; 807145522Sdarrenr if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) { 808255332Scy if (softp->ips_proxy_debug & 0x08) 809255332Scy printf("ipf_proxy_match:apr %lx apr_flags 0x%x\n", 810145522Sdarrenr (u_long)apr, apr ? apr->apr_flags : 0); 81192685Sdarrenr return -1; 812145522Sdarrenr } 813145522Sdarrenr 814145522Sdarrenr if (apr->apr_match != NULL) { 815145522Sdarrenr result = (*apr->apr_match)(fin, nat->nat_aps, nat); 816145522Sdarrenr if (result != 0) { 817255332Scy if (softp->ips_proxy_debug & 0x08) 818255332Scy printf("ipf_proxy_match: result %d\n", result); 81992685Sdarrenr return -1; 820145522Sdarrenr } 821145522Sdarrenr } 82292685Sdarrenr return 0; 82392685Sdarrenr} 82492685Sdarrenr 82592685Sdarrenr 826255332Scy/* ------------------------------------------------------------------------ */ 827255332Scy/* Function: ipf_proxy_new */ 828255332Scy/* Returns: int - 0 == success, else error */ 829255332Scy/* Parameters: fin(I) - pointer to packet information */ 830255332Scy/* nat(I) - pointer to current NAT session */ 831255332Scy/* */ 832255332Scy/* Allocate a new application proxy structure and fill it in with the */ 833255332Scy/* relevant details. call the init function once complete, prior to */ 834255332Scy/* returning. */ 835255332Scy/* ------------------------------------------------------------------------ */ 836255332Scyint 837255332Scyipf_proxy_new(fin, nat) 838255332Scy fr_info_t *fin; 839255332Scy nat_t *nat; 84053642Sguido{ 841255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 842255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 84353642Sguido register ap_session_t *aps; 84492685Sdarrenr aproxy_t *apr; 84553642Sguido 846255332Scy if (softp->ips_proxy_debug & 0x04) 847255332Scy printf("ipf_proxy_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); 848145522Sdarrenr 849145522Sdarrenr if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) { 850255332Scy if (softp->ips_proxy_debug & 0x08) 851255332Scy printf("ipf_proxy_new: nat_ptr %lx nat_aps %lx\n", 852145522Sdarrenr (u_long)nat->nat_ptr, (u_long)nat->nat_aps); 85392685Sdarrenr return -1; 854145522Sdarrenr } 85592685Sdarrenr 85692685Sdarrenr apr = nat->nat_ptr->in_apr; 85792685Sdarrenr 858145522Sdarrenr if ((apr->apr_flags & APR_DELETE) || 859145522Sdarrenr (fin->fin_p != apr->apr_p)) { 860255332Scy if (softp->ips_proxy_debug & 0x08) 861255332Scy printf("ipf_proxy_new: apr_flags 0x%x p %d/%d\n", 862145522Sdarrenr apr->apr_flags, fin->fin_p, apr->apr_p); 86392685Sdarrenr return -1; 864145522Sdarrenr } 86553642Sguido 86653642Sguido KMALLOC(aps, ap_session_t *); 867145522Sdarrenr if (!aps) { 868255332Scy if (softp->ips_proxy_debug & 0x08) 869255332Scy printf("ipf_proxy_new: malloc failed (%lu)\n", 870145522Sdarrenr (u_long)sizeof(ap_session_t)); 87192685Sdarrenr return -1; 872145522Sdarrenr } 873145522Sdarrenr 87453642Sguido bzero((char *)aps, sizeof(*aps)); 87553642Sguido aps->aps_data = NULL; 87653642Sguido aps->aps_apr = apr; 87753642Sguido aps->aps_psiz = 0; 87860855Sdarrenr if (apr->apr_new != NULL) 879255332Scy if ((*apr->apr_new)(apr->apr_soft, fin, aps, nat) == -1) { 88092685Sdarrenr if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) { 88192685Sdarrenr KFREES(aps->aps_data, aps->aps_psiz); 88292685Sdarrenr } 88360855Sdarrenr KFREE(aps); 884255332Scy if (softp->ips_proxy_debug & 0x08) 885255332Scy printf("ipf_proxy_new: new(%lx) failed\n", 886145522Sdarrenr (u_long)apr->apr_new); 88792685Sdarrenr return -1; 88860855Sdarrenr } 88960855Sdarrenr aps->aps_nat = nat; 890255332Scy aps->aps_next = softp->ips_sess_list; 891255332Scy softp->ips_sess_list = aps; 89292685Sdarrenr nat->nat_aps = aps; 89392685Sdarrenr 89492685Sdarrenr return 0; 89553642Sguido} 89653642Sguido 89753642Sguido 898255332Scy/* ------------------------------------------------------------------------ */ 899255332Scy/* Function: ipf_proxy_check */ 900255332Scy/* Returns: int - -1 == error, 0 == success */ 901255332Scy/* Parameters: fin(I) - pointer to packet information */ 902255332Scy/* nat(I) - pointer to current NAT session */ 903255332Scy/* */ 904255332Scy/* Check to see if a packet should be passed through an active proxy */ 905255332Scy/* routine if one has been setup for it. We don't need to check the */ 906255332Scy/* checksum here if IPFILTER_CKSUM is defined because if it is, a failed */ 907255332Scy/* check causes FI_BAD to be set. */ 908255332Scy/* ------------------------------------------------------------------------ */ 909255332Scyint 910255332Scyipf_proxy_check(fin, nat) 911255332Scy fr_info_t *fin; 912255332Scy nat_t *nat; 91353642Sguido{ 914255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 915255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 916255332Scy#if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) 917145522Sdarrenr mb_t *m; 91880482Sdarrenr#endif 91980482Sdarrenr tcphdr_t *tcp = NULL; 920145522Sdarrenr udphdr_t *udp = NULL; 92153642Sguido ap_session_t *aps; 92253642Sguido aproxy_t *apr; 923255332Scy short adjlen; 924255332Scy int dosum; 925145522Sdarrenr ip_t *ip; 92660855Sdarrenr short rv; 92753642Sguido int err; 928145522Sdarrenr#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) 929145522Sdarrenr u_32_t s1, s2, sd; 930145522Sdarrenr#endif 93153642Sguido 932145522Sdarrenr if (fin->fin_flx & FI_BAD) { 933255332Scy if (softp->ips_proxy_debug & 0x08) 934255332Scy printf("ipf_proxy_check: flx 0x%x (BAD)\n", 935255332Scy fin->fin_flx); 936145522Sdarrenr return -1; 937145522Sdarrenr } 938145522Sdarrenr 939145522Sdarrenr#ifndef IPFILTER_CKSUM 940255332Scy if ((fin->fin_out == 0) && (ipf_checkl4sum(fin) == -1)) { 941255332Scy if (softp->ips_proxy_debug & 0x08) 942255332Scy printf("ipf_proxy_check: l4 checksum failure %d\n", 943145522Sdarrenr fin->fin_p); 944145522Sdarrenr if (fin->fin_p == IPPROTO_TCP) 945255332Scy softc->ipf_stats[fin->fin_out].fr_tcpbad++; 946145522Sdarrenr return -1; 947145522Sdarrenr } 948145522Sdarrenr#endif 949145522Sdarrenr 95053642Sguido aps = nat->nat_aps; 951255332Scy if (aps != NULL) { 952145522Sdarrenr /* 953145522Sdarrenr * If there is data in this packet to be proxied then try and 954145522Sdarrenr * get it all into the one buffer, else drop it. 955145522Sdarrenr */ 956145522Sdarrenr#if defined(MENTAT) || defined(HAVE_M_PULLDOWN) 957145522Sdarrenr if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE)) 958255332Scy if (ipf_coalesce(fin) == -1) { 959255332Scy if (softp->ips_proxy_debug & 0x08) 960255332Scy printf("ipf_proxy_check: %s %x\n", 961255332Scy "coalesce failed", fin->fin_flx); 962145522Sdarrenr return -1; 963145522Sdarrenr } 964145522Sdarrenr#endif 965145522Sdarrenr ip = fin->fin_ip; 966255332Scy if (fin->fin_cksum > FI_CK_SUMOK) 967255332Scy dosum = 0; 968255332Scy else 969255332Scy dosum = 1; 970145522Sdarrenr 971145522Sdarrenr switch (fin->fin_p) 972145522Sdarrenr { 973145522Sdarrenr case IPPROTO_TCP : 97453642Sguido tcp = (tcphdr_t *)fin->fin_dp; 975255332Scy#if SOLARIS && defined(_KERNEL) && defined(ICK_VALID) 976145522Sdarrenr m = fin->fin_qfm; 977145522Sdarrenr if (dohwcksum && (m->b_ick_flag == ICK_VALID)) 97880482Sdarrenr dosum = 0; 97953642Sguido#endif 980255332Scy break; 981145522Sdarrenr case IPPROTO_UDP : 982145522Sdarrenr udp = (udphdr_t *)fin->fin_dp; 983145522Sdarrenr break; 984145522Sdarrenr default : 985145522Sdarrenr break; 98653642Sguido } 98753642Sguido 98853642Sguido apr = aps->aps_apr; 98953642Sguido err = 0; 99053642Sguido if (fin->fin_out != 0) { 99153642Sguido if (apr->apr_outpkt != NULL) 992255332Scy err = (*apr->apr_outpkt)(apr->apr_soft, fin, 993255332Scy aps, nat); 99453642Sguido } else { 99553642Sguido if (apr->apr_inpkt != NULL) 996255332Scy err = (*apr->apr_inpkt)(apr->apr_soft, fin, 997255332Scy aps, nat); 99853642Sguido } 99953642Sguido 100060855Sdarrenr rv = APR_EXIT(err); 1001255332Scy if (((softp->ips_proxy_debug & 0x08) && (rv != 0)) || 1002255332Scy (softp->ips_proxy_debug & 0x04)) 1003255332Scy printf("ipf_proxy_check: out %d err %x rv %d\n", 1004145522Sdarrenr fin->fin_out, err, rv); 1005145522Sdarrenr if (rv == 1) 100692685Sdarrenr return -1; 1007145522Sdarrenr 100892685Sdarrenr if (rv == 2) { 1009255332Scy ipf_proxy_deref(apr); 101092685Sdarrenr nat->nat_aps = NULL; 101192685Sdarrenr return -1; 101292685Sdarrenr } 101360855Sdarrenr 1014145522Sdarrenr /* 1015145522Sdarrenr * If err != 0 then the data size of the packet has changed 1016145522Sdarrenr * so we need to recalculate the header checksums for the 1017145522Sdarrenr * packet. 1018145522Sdarrenr */ 1019255332Scy adjlen = APR_INC(err); 1020145522Sdarrenr#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) 1021255332Scy s1 = LONG_SUM(fin->fin_plen - adjlen); 1022255332Scy s2 = LONG_SUM(fin->fin_plen); 1023255332Scy CALC_SUMD(s1, s2, sd); 1024255332Scy if ((err != 0) && (fin->fin_cksum < FI_CK_L4PART) && 1025255332Scy fin->fin_v == 4) 1026255332Scy ipf_fix_outcksum(0, &ip->ip_sum, sd, 0); 1027145522Sdarrenr#endif 1028255332Scy if (fin->fin_flx & FI_DOCKSUM) 1029255332Scy dosum = 1; 1030145522Sdarrenr 1031145522Sdarrenr /* 1032145522Sdarrenr * For TCP packets, we may need to adjust the sequence and 1033145522Sdarrenr * acknowledgement numbers to reflect changes in size of the 1034145522Sdarrenr * data stream. 1035145522Sdarrenr * 1036145522Sdarrenr * For both TCP and UDP, recalculate the layer 4 checksum, 1037145522Sdarrenr * regardless, as we can't tell (here) if data has been 1038145522Sdarrenr * changed or not. 1039145522Sdarrenr */ 104053642Sguido if (tcp != NULL) { 1041255332Scy err = ipf_proxy_fixseqack(fin, ip, aps, adjlen); 1042255332Scy if (fin->fin_cksum == FI_CK_L4PART) { 1043255332Scy u_short sum = ntohs(tcp->th_sum); 1044255332Scy sum += adjlen; 1045255332Scy tcp->th_sum = htons(sum); 1046255332Scy } else if (fin->fin_cksum < FI_CK_L4PART) { 1047255332Scy tcp->th_sum = fr_cksum(fin, ip, 1048255332Scy IPPROTO_TCP, tcp); 1049255332Scy } 1050145522Sdarrenr } else if ((udp != NULL) && (udp->uh_sum != 0)) { 1051255332Scy if (fin->fin_cksum == FI_CK_L4PART) { 1052255332Scy u_short sum = ntohs(udp->uh_sum); 1053255332Scy sum += adjlen; 1054255332Scy udp->uh_sum = htons(sum); 1055255332Scy } else if (dosum) { 1056255332Scy udp->uh_sum = fr_cksum(fin, ip, 1057255332Scy IPPROTO_UDP, udp); 1058255332Scy } 105953642Sguido } 1060145522Sdarrenr aps->aps_bytes += fin->fin_plen; 106153642Sguido aps->aps_pkts++; 106260855Sdarrenr return 1; 106353642Sguido } 106460855Sdarrenr return 0; 106553642Sguido} 106653642Sguido 106753642Sguido 1068255332Scy/* ------------------------------------------------------------------------ */ 1069255332Scy/* Function: ipf_proxy_lookup */ 1070255332Scy/* Returns: int - -1 == error, 0 == success */ 1071255332Scy/* Parameters: arg(I) - pointer to proxy context information */ 1072255332Scy/* pr(I) - protocol number for proxy */ 1073255332Scy/* name(I) - proxy name */ 1074255332Scy/* */ 1075255332Scy/* Search for an proxy by the protocol it is being used with and its name. */ 1076255332Scy/* ------------------------------------------------------------------------ */ 1077255332Scyaproxy_t * 1078255332Scyipf_proxy_lookup(arg, pr, name) 1079255332Scy void *arg; 1080255332Scy u_int pr; 1081255332Scy char *name; 108253642Sguido{ 1083255332Scy ipf_proxy_softc_t *softp = arg; 108453642Sguido aproxy_t *ap; 108553642Sguido 1086255332Scy if (softp->ips_proxy_debug & 0x04) 1087255332Scy printf("ipf_proxy_lookup(%d,%s)\n", pr, name); 1088145522Sdarrenr 1089255332Scy for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) 109053642Sguido if ((ap->apr_p == pr) && 109153642Sguido !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { 109253642Sguido ap->apr_ref++; 109353642Sguido return ap; 109453642Sguido } 109560855Sdarrenr 1096255332Scy if (softp->ips_proxy_debug & 0x08) 1097255332Scy printf("ipf_proxy_lookup: failed for %d/%s\n", pr, name); 109853642Sguido return NULL; 109953642Sguido} 110053642Sguido 110153642Sguido 1102255332Scy/* ------------------------------------------------------------------------ */ 1103255332Scy/* Function: ipf_proxy_deref */ 1104255332Scy/* Returns: Nil */ 1105255332Scy/* Parameters: ap(I) - pointer to proxy structure */ 1106255332Scy/* */ 1107255332Scy/* Drop the reference counter associated with the proxy. */ 1108255332Scy/* ------------------------------------------------------------------------ */ 1109255332Scyvoid 1110255332Scyipf_proxy_deref(ap) 1111255332Scy aproxy_t *ap; 111253642Sguido{ 111353642Sguido ap->apr_ref--; 111453642Sguido} 111553642Sguido 111653642Sguido 1117255332Scy/* ------------------------------------------------------------------------ */ 1118255332Scy/* Function: ipf_proxy_free */ 1119255332Scy/* Returns: Nil */ 1120255332Scy/* Parameters: softc(I) - pointer to soft context main structure */ 1121255332Scy/* aps(I) - pointer to current proxy session */ 1122255332Scy/* Locks Held: ipf_nat_new, ipf_nat(W) */ 1123255332Scy/* */ 1124255332Scy/* Free up proxy session information allocated to be used with a NAT */ 1125255332Scy/* session. */ 1126255332Scy/* ------------------------------------------------------------------------ */ 1127255332Scyvoid 1128255332Scyipf_proxy_free(softc, aps) 1129255332Scy ipf_main_softc_t *softc; 1130255332Scy ap_session_t *aps; 113153642Sguido{ 1132255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 113353642Sguido ap_session_t *a, **ap; 113492685Sdarrenr aproxy_t *apr; 113553642Sguido 113653642Sguido if (!aps) 113753642Sguido return; 113853642Sguido 1139255332Scy for (ap = &softp->ips_sess_list; ((a = *ap) != NULL); ap = &a->aps_next) 114053642Sguido if (a == aps) { 114153642Sguido *ap = a->aps_next; 114253642Sguido break; 114353642Sguido } 114453642Sguido 114592685Sdarrenr apr = aps->aps_apr; 114692685Sdarrenr if ((apr != NULL) && (apr->apr_del != NULL)) 1147255332Scy (*apr->apr_del)(softc, aps); 1148110916Sdarrenr 114960855Sdarrenr if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) 115060855Sdarrenr KFREES(aps->aps_data, aps->aps_psiz); 115160855Sdarrenr KFREE(aps); 115253642Sguido} 115353642Sguido 115453642Sguido 1155255332Scy/* ------------------------------------------------------------------------ */ 1156255332Scy/* Function: ipf_proxy_fixseqack */ 1157255332Scy/* Returns: int - 2 if TCP ack/seq is changed, else 0 */ 1158255332Scy/* Parameters: fin(I) - pointer to packet information */ 1159255332Scy/* ip(I) - pointer to IP header */ 1160255332Scy/* nat(I) - pointer to current NAT session */ 1161255332Scy/* inc(I) - delta to apply to TCP sequence numbering */ 1162255332Scy/* */ 1163255332Scy/* Adjust the TCP sequence/acknowledge numbers in the TCP header based on */ 1164255332Scy/* whether or not the new header is past the point at which an adjustment */ 1165255332Scy/* occurred. This might happen because of (say) an FTP string being changed */ 1166255332Scy/* and the new string being a different length to the old. */ 1167255332Scy/* ------------------------------------------------------------------------ */ 1168255332Scystatic int 1169255332Scyipf_proxy_fixseqack(fin, ip, aps, inc) 1170255332Scy fr_info_t *fin; 1171255332Scy ip_t *ip; 1172255332Scy ap_session_t *aps; 1173255332Scy int inc; 117453642Sguido{ 1175255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 1176255332Scy ipf_proxy_softc_t *softp = softc->ipf_proxy_soft; 117753642Sguido int sel, ch = 0, out, nlen; 117853642Sguido u_32_t seq1, seq2; 117953642Sguido tcphdr_t *tcp; 118098004Sdarrenr short inc2; 118153642Sguido 118253642Sguido tcp = (tcphdr_t *)fin->fin_dp; 118353642Sguido out = fin->fin_out; 1184102520Sdarrenr /* 1185255332Scy * ip_len has already been adjusted by 'inc'. 1186102520Sdarrenr */ 1187255332Scy nlen = fin->fin_dlen; 1188255332Scy nlen -= (TCP_OFF(tcp) << 2); 1189102520Sdarrenr 119098004Sdarrenr inc2 = inc; 119198004Sdarrenr inc = (int)inc2; 119253642Sguido 119353642Sguido if (out != 0) { 119453642Sguido seq1 = (u_32_t)ntohl(tcp->th_seq); 119553642Sguido sel = aps->aps_sel[out]; 119653642Sguido 119753642Sguido /* switch to other set ? */ 119853642Sguido if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 1199102520Sdarrenr (seq1 > aps->aps_seqmin[!sel])) { 1200255332Scy if (softp->ips_proxy_debug & 0x10) 1201145522Sdarrenr printf("proxy out switch set seq %d -> %d %x > %x\n", 1202145522Sdarrenr sel, !sel, seq1, 1203145522Sdarrenr aps->aps_seqmin[!sel]); 120453642Sguido sel = aps->aps_sel[out] = !sel; 1205110916Sdarrenr } 120653642Sguido 120753642Sguido if (aps->aps_seqoff[sel]) { 120853642Sguido seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel]; 120953642Sguido if (seq1 > seq2) { 121053642Sguido seq2 = aps->aps_seqoff[sel]; 121153642Sguido seq1 += seq2; 121253642Sguido tcp->th_seq = htonl(seq1); 121353642Sguido ch = 1; 121453642Sguido } 121553642Sguido } 121653642Sguido 121753642Sguido if (inc && (seq1 > aps->aps_seqmin[!sel])) { 1218102520Sdarrenr aps->aps_seqmin[sel] = seq1 + nlen - 1; 1219102520Sdarrenr aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc; 1220255332Scy if (softp->ips_proxy_debug & 0x10) 1221145522Sdarrenr printf("proxy seq set %d at %x to %d + %d\n", 1222145522Sdarrenr sel, aps->aps_seqmin[sel], 1223145522Sdarrenr aps->aps_seqoff[sel], inc); 122453642Sguido } 122553642Sguido 122653642Sguido /***/ 122753642Sguido 122853642Sguido seq1 = ntohl(tcp->th_ack); 122953642Sguido sel = aps->aps_sel[1 - out]; 123053642Sguido 123153642Sguido /* switch to other set ? */ 123253642Sguido if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 1233102520Sdarrenr (seq1 > aps->aps_ackmin[!sel])) { 1234255332Scy if (softp->ips_proxy_debug & 0x10) 1235145522Sdarrenr printf("proxy out switch set ack %d -> %d %x > %x\n", 1236145522Sdarrenr sel, !sel, seq1, 1237145522Sdarrenr aps->aps_ackmin[!sel]); 123853642Sguido sel = aps->aps_sel[1 - out] = !sel; 1239110916Sdarrenr } 124053642Sguido 124153642Sguido if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) { 124253642Sguido seq2 = aps->aps_ackoff[sel]; 124353642Sguido tcp->th_ack = htonl(seq1 - seq2); 124453642Sguido ch = 1; 124553642Sguido } 124653642Sguido } else { 124753642Sguido seq1 = ntohl(tcp->th_seq); 124853642Sguido sel = aps->aps_sel[out]; 124953642Sguido 125053642Sguido /* switch to other set ? */ 125153642Sguido if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 1252102520Sdarrenr (seq1 > aps->aps_ackmin[!sel])) { 1253255332Scy if (softp->ips_proxy_debug & 0x10) 1254145522Sdarrenr printf("proxy in switch set ack %d -> %d %x > %x\n", 1255145522Sdarrenr sel, !sel, seq1, aps->aps_ackmin[!sel]); 125653642Sguido sel = aps->aps_sel[out] = !sel; 1257110916Sdarrenr } 125853642Sguido 125953642Sguido if (aps->aps_ackoff[sel]) { 1260102520Sdarrenr seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel]; 126153642Sguido if (seq1 > seq2) { 126253642Sguido seq2 = aps->aps_ackoff[sel]; 126353642Sguido seq1 += seq2; 126453642Sguido tcp->th_seq = htonl(seq1); 126553642Sguido ch = 1; 126653642Sguido } 126753642Sguido } 126853642Sguido 126953642Sguido if (inc && (seq1 > aps->aps_ackmin[!sel])) { 127053642Sguido aps->aps_ackmin[!sel] = seq1 + nlen - 1; 127153642Sguido aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; 1272145522Sdarrenr 1273255332Scy if (softp->ips_proxy_debug & 0x10) 1274145522Sdarrenr printf("proxy ack set %d at %x to %d + %d\n", 1275145522Sdarrenr !sel, aps->aps_seqmin[!sel], 1276145522Sdarrenr aps->aps_seqoff[sel], inc); 127753642Sguido } 127853642Sguido 127953642Sguido /***/ 128053642Sguido 128153642Sguido seq1 = ntohl(tcp->th_ack); 128253642Sguido sel = aps->aps_sel[1 - out]; 128353642Sguido 128453642Sguido /* switch to other set ? */ 128553642Sguido if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 1286102520Sdarrenr (seq1 > aps->aps_seqmin[!sel])) { 1287255332Scy if (softp->ips_proxy_debug & 0x10) 1288145522Sdarrenr printf("proxy in switch set seq %d -> %d %x > %x\n", 1289145522Sdarrenr sel, !sel, seq1, aps->aps_seqmin[!sel]); 129053642Sguido sel = aps->aps_sel[1 - out] = !sel; 1291110916Sdarrenr } 129253642Sguido 1293102520Sdarrenr if (aps->aps_seqoff[sel] != 0) { 1294255332Scy if (softp->ips_proxy_debug & 0x10) 1295145522Sdarrenr printf("sel %d seqoff %d seq1 %x seqmin %x\n", 1296145522Sdarrenr sel, aps->aps_seqoff[sel], seq1, 1297145522Sdarrenr aps->aps_seqmin[sel]); 1298102520Sdarrenr if (seq1 > aps->aps_seqmin[sel]) { 1299102520Sdarrenr seq2 = aps->aps_seqoff[sel]; 1300102520Sdarrenr tcp->th_ack = htonl(seq1 - seq2); 1301102520Sdarrenr ch = 1; 1302102520Sdarrenr } 130353642Sguido } 130453642Sguido } 1305145522Sdarrenr 1306255332Scy if (softp->ips_proxy_debug & 0x10) 1307255332Scy printf("ipf_proxy_fixseqack: seq %u ack %u\n", 1308170268Sdarrenr (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack)); 130953642Sguido return ch ? 2 : 0; 131053642Sguido} 131153642Sguido 131253642Sguido 1313255332Scy/* ------------------------------------------------------------------------ */ 1314255332Scy/* Function: ipf_proxy_rule_rev */ 1315255332Scy/* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ 1316255332Scy/* Parameters: nat(I) - pointer to NAT session to create rule from */ 1317255332Scy/* */ 1318255332Scy/* This function creates a NAT rule that is based upon the reverse packet */ 1319255332Scy/* flow associated with this NAT session. Thus if this NAT session was */ 1320255332Scy/* created with a map rule then this function will create a rdr rule. */ 1321255332Scy/* Only address fields and network interfaces are assigned in this function */ 1322255332Scy/* and the address fields are formed such that an exact is required. If the */ 1323255332Scy/* original rule had a netmask, that is not replicated here not is it */ 1324255332Scy/* desired. The ultimate goal here is to create a NAT rule to support a NAT */ 1325255332Scy/* session being created that does not have a user configured rule. The */ 1326255332Scy/* classic example is supporting the FTP proxy, where a data channel needs */ 1327255332Scy/* to be setup, based on the addresses used for the control connection. In */ 1328255332Scy/* that case, this function is used to handle creating NAT rules to support */ 1329255332Scy/* data connections with the PORT and EPRT commands. */ 1330255332Scy/* ------------------------------------------------------------------------ */ 1331255332Scyipnat_t * 1332255332Scyipf_proxy_rule_rev(nat) 1333255332Scy nat_t *nat; 133453642Sguido{ 1335255332Scy ipnat_t *old; 1336255332Scy ipnat_t *ipn; 1337255332Scy int size; 133853642Sguido 1339255332Scy old = nat->nat_ptr; 1340255332Scy size = old->in_size; 1341255332Scy 1342255332Scy KMALLOCS(ipn, ipnat_t *, size); 1343255332Scy if (ipn == NULL) 1344255332Scy return NULL; 1345255332Scy 1346255332Scy bzero((char *)ipn, size); 1347255332Scy 1348255332Scy ipn->in_use = 1; 1349255332Scy ipn->in_hits = 1; 1350255332Scy ipn->in_ippip = 1; 1351255332Scy ipn->in_apr = NULL; 1352255332Scy ipn->in_size = size; 1353255332Scy ipn->in_pr[0] = old->in_pr[1]; 1354255332Scy ipn->in_pr[1] = old->in_pr[0]; 1355255332Scy ipn->in_v[0] = old->in_v[1]; 1356255332Scy ipn->in_v[1] = old->in_v[0]; 1357255332Scy ipn->in_ifps[0] = old->in_ifps[1]; 1358255332Scy ipn->in_ifps[1] = old->in_ifps[0]; 1359255332Scy ipn->in_flags = (old->in_flags | IPN_PROXYRULE); 1360255332Scy 1361255332Scy ipn->in_nsrcip6 = nat->nat_odst6; 1362255332Scy ipn->in_osrcip6 = nat->nat_ndst6; 1363255332Scy 1364255332Scy if ((old->in_redir & NAT_REDIRECT) != 0) { 1365255332Scy ipn->in_redir = NAT_MAP; 1366255332Scy if (ipn->in_v[0] == 4) { 1367255332Scy ipn->in_snip = ntohl(nat->nat_odstaddr); 1368255332Scy ipn->in_dnip = ntohl(nat->nat_nsrcaddr); 1369255332Scy } else { 1370255332Scy#ifdef USE_INET6 1371255332Scy ipn->in_snip6 = nat->nat_odst6; 1372255332Scy ipn->in_dnip6 = nat->nat_nsrc6; 1373255332Scy#endif 1374145522Sdarrenr } 1375255332Scy ipn->in_ndstip6 = nat->nat_nsrc6; 1376255332Scy ipn->in_odstip6 = nat->nat_osrc6; 1377255332Scy } else { 1378255332Scy ipn->in_redir = NAT_REDIRECT; 1379255332Scy if (ipn->in_v[0] == 4) { 1380255332Scy ipn->in_snip = ntohl(nat->nat_odstaddr); 1381255332Scy ipn->in_dnip = ntohl(nat->nat_osrcaddr); 1382255332Scy } else { 1383255332Scy#ifdef USE_INET6 1384255332Scy ipn->in_snip6 = nat->nat_odst6; 1385255332Scy ipn->in_dnip6 = nat->nat_osrc6; 1386255332Scy#endif 1387255332Scy } 1388255332Scy ipn->in_ndstip6 = nat->nat_osrc6; 1389255332Scy ipn->in_odstip6 = nat->nat_nsrc6; 139053642Sguido } 1391255332Scy 1392255332Scy IP6_SETONES(&ipn->in_osrcmsk6); 1393255332Scy IP6_SETONES(&ipn->in_nsrcmsk6); 1394255332Scy IP6_SETONES(&ipn->in_odstmsk6); 1395255332Scy IP6_SETONES(&ipn->in_ndstmsk6); 1396255332Scy 1397255332Scy ipn->in_namelen = old->in_namelen; 1398255332Scy ipn->in_ifnames[0] = old->in_ifnames[1]; 1399255332Scy ipn->in_ifnames[1] = old->in_ifnames[0]; 1400255332Scy bcopy(old->in_names, ipn->in_names, ipn->in_namelen); 1401255332Scy MUTEX_INIT(&ipn->in_lock, "ipnat rev rule lock"); 1402255332Scy 1403255332Scy return ipn; 140453642Sguido} 140560855Sdarrenr 140660855Sdarrenr 1407255332Scy/* ------------------------------------------------------------------------ */ 1408255332Scy/* Function: ipf_proxy_rule_fwd */ 1409255332Scy/* Returns: ipnat_t * - NULL = failure, else pointer to new rule */ 1410255332Scy/* Parameters: nat(I) - pointer to NAT session to create rule from */ 1411255332Scy/* */ 1412255332Scy/* The purpose and rationale of this function is much the same as the above */ 1413255332Scy/* function, ipf_proxy_rule_rev, except that a rule is created that matches */ 1414255332Scy/* the same direction as that of the existing NAT session. Thus if this NAT */ 1415255332Scy/* session was created with a map rule then this function will also create */ 1416255332Scy/* a data structure to represent a map rule. Whereas ipf_proxy_rule_rev is */ 1417255332Scy/* used to support PORT/EPRT, this function supports PASV/EPSV. */ 1418255332Scy/* ------------------------------------------------------------------------ */ 1419255332Scyipnat_t * 1420255332Scyipf_proxy_rule_fwd(nat) 1421255332Scy nat_t *nat; 142260855Sdarrenr{ 1423255332Scy ipnat_t *old; 1424255332Scy ipnat_t *ipn; 1425255332Scy int size; 142660855Sdarrenr 1427255332Scy old = nat->nat_ptr; 1428255332Scy size = old->in_size; 1429255332Scy 1430255332Scy KMALLOCS(ipn, ipnat_t *, size); 1431255332Scy if (ipn == NULL) 1432255332Scy return NULL; 1433255332Scy 1434255332Scy bzero((char *)ipn, size); 1435255332Scy 1436255332Scy ipn->in_use = 1; 1437255332Scy ipn->in_hits = 1; 1438255332Scy ipn->in_ippip = 1; 1439255332Scy ipn->in_apr = NULL; 1440255332Scy ipn->in_size = size; 1441255332Scy ipn->in_pr[0] = old->in_pr[0]; 1442255332Scy ipn->in_pr[1] = old->in_pr[1]; 1443255332Scy ipn->in_v[0] = old->in_v[0]; 1444255332Scy ipn->in_v[1] = old->in_v[1]; 1445255332Scy ipn->in_ifps[0] = nat->nat_ifps[0]; 1446255332Scy ipn->in_ifps[1] = nat->nat_ifps[1]; 1447255332Scy ipn->in_flags = (old->in_flags | IPN_PROXYRULE); 1448255332Scy 1449255332Scy ipn->in_nsrcip6 = nat->nat_nsrc6; 1450255332Scy ipn->in_osrcip6 = nat->nat_osrc6; 1451255332Scy ipn->in_ndstip6 = nat->nat_ndst6; 1452255332Scy ipn->in_odstip6 = nat->nat_odst6; 1453255332Scy ipn->in_redir = old->in_redir; 1454255332Scy 1455255332Scy if (ipn->in_v[0] == 4) { 1456255332Scy ipn->in_snip = ntohl(nat->nat_nsrcaddr); 1457255332Scy ipn->in_dnip = ntohl(nat->nat_ndstaddr); 1458255332Scy } else { 1459255332Scy#ifdef USE_INET6 1460255332Scy ipn->in_snip6 = nat->nat_nsrc6; 1461255332Scy ipn->in_dnip6 = nat->nat_ndst6; 1462255332Scy#endif 1463255332Scy } 1464255332Scy 1465255332Scy IP6_SETONES(&ipn->in_osrcmsk6); 1466255332Scy IP6_SETONES(&ipn->in_nsrcmsk6); 1467255332Scy IP6_SETONES(&ipn->in_odstmsk6); 1468255332Scy IP6_SETONES(&ipn->in_ndstmsk6); 1469255332Scy 1470255332Scy ipn->in_namelen = old->in_namelen; 1471255332Scy ipn->in_ifnames[0] = old->in_ifnames[0]; 1472255332Scy ipn->in_ifnames[1] = old->in_ifnames[1]; 1473255332Scy bcopy(old->in_names, ipn->in_names, ipn->in_namelen); 1474255332Scy MUTEX_INIT(&ipn->in_lock, "ipnat fwd rule lock"); 1475255332Scy 1476255332Scy return ipn; 147760855Sdarrenr} 1478