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