ip_proxy.c revision 227957
1169691Skan/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_proxy.c 227957 2011-11-24 21:23:58Z rmh $ */ 2169691Skan 3169691Skan/* 4169691Skan * Copyright (C) 1997-2003 by Darren Reed. 5169691Skan * 6169691Skan * See the IPFILTER.LICENCE file for details on licencing. 7169691Skan */ 8169691Skan#if defined(KERNEL) || defined(_KERNEL) 9169691Skan# undef KERNEL 10169691Skan# undef _KERNEL 11169691Skan# define KERNEL 1 12169691Skan# define _KERNEL 1 13169691Skan#endif 14169691Skan#include <sys/errno.h> 15169691Skan#include <sys/types.h> 16169691Skan#include <sys/param.h> 17169691Skan#include <sys/time.h> 18169691Skan#include <sys/file.h> 19169691Skan#if !defined(AIX) 20169691Skan# include <sys/fcntl.h> 21169691Skan#endif 22169691Skan#if !defined(_KERNEL) && !defined(__KERNEL__) 23169691Skan# include <stdio.h> 24169691Skan# include <string.h> 25169691Skan# include <stdlib.h> 26169691Skan# include <ctype.h> 27169691Skan# define _KERNEL 28169691Skan# ifdef __OpenBSD__ 29169691Skanstruct file; 30169691Skan# endif 31169691Skan# include <sys/uio.h> 32169691Skan# undef _KERNEL 33169691Skan#endif 34169691Skan#if !defined(linux) 35169691Skan# include <sys/protosw.h> 36169691Skan#endif 37169691Skan#include <sys/socket.h> 38169691Skan#if defined(_KERNEL) 39169691Skan# if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \ 40169691Skan !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \ 41169691Skan !defined(AIX) 42169691Skan# include <sys/ctype.h> 43169691Skan# endif 44169691Skan# include <sys/systm.h> 45169691Skan# if !defined(__SVR4) && !defined(__svr4__) 46169691Skan# include <sys/mbuf.h> 47169691Skan# endif 48169691Skan#endif 49169691Skan#if defined(_KERNEL) && (__FreeBSD_version >= 220000) 50169691Skan# include <sys/filio.h> 51169691Skan# include <sys/fcntl.h> 52169691Skan# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM) 53169691Skan# include "opt_ipfilter.h" 54169691Skan# endif 55169691Skan#else 56169691Skan# include <sys/ioctl.h> 57169691Skan#endif 58169691Skan#if defined(__SVR4) || defined(__svr4__) 59169691Skan# include <sys/byteorder.h> 60169691Skan# ifdef _KERNEL 61169691Skan# include <sys/dditypes.h> 62169691Skan# endif 63169691Skan# include <sys/stream.h> 64169691Skan# include <sys/kmem.h> 65169691Skan#endif 66169691Skan#if __FreeBSD_version >= 300000 67169691Skan# include <sys/queue.h> 68169691Skan#endif 69169691Skan#include <net/if.h> 70169691Skan#ifdef sun 71169691Skan# include <net/af.h> 72169691Skan#endif 73169691Skan#include <net/route.h> 74169691Skan#include <netinet/in.h> 75169691Skan#include <netinet/in_systm.h> 76169691Skan#include <netinet/ip.h> 77169691Skan#ifndef linux 78169691Skan# include <netinet/ip_var.h> 79169691Skan#endif 80169691Skan#include <netinet/tcp.h> 81169691Skan#include <netinet/udp.h> 82169691Skan#include <netinet/ip_icmp.h> 83169691Skan#include "netinet/ip_compat.h" 84169691Skan#include <netinet/tcpip.h> 85169691Skan#include "netinet/ip_fil.h" 86169691Skan#include "netinet/ip_nat.h" 87169691Skan#include "netinet/ip_state.h" 88169691Skan#include "netinet/ip_proxy.h" 89169691Skan#if (__FreeBSD_version >= 300000) 90169691Skan# include <sys/malloc.h> 91169691Skan#endif 92169691Skan 93169691Skan#include "netinet/ip_ftp_pxy.c" 94169691Skan#include "netinet/ip_rcmd_pxy.c" 95169691Skan# include "netinet/ip_pptp_pxy.c" 96169691Skan#if defined(_KERNEL) 97169691Skan# include "netinet/ip_irc_pxy.c" 98169691Skan# include "netinet/ip_raudio_pxy.c" 99169691Skan# include "netinet/ip_netbios_pxy.c" 100169691Skan#endif 101169691Skan#include "netinet/ip_ipsec_pxy.c" 102169691Skan#include "netinet/ip_rpcb_pxy.c" 103169691Skan 104169691Skan/* END OF INCLUDES */ 105169691Skan 106169691Skan#if !defined(lint) 107169691Skanstatic const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.21 2007/06/02 21:22:28 darrenr Exp $"; 108169691Skan#endif 109169691Skan 110169691Skanstatic int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); 111169691Skan 112169691Skan#define AP_SESS_SIZE 53 113169691Skan 114169691Skan#if defined(_KERNEL) 115169691Skanint ipf_proxy_debug = 0; 116169691Skan#else 117169691Skanint ipf_proxy_debug = 2; 118169691Skan#endif 119169691Skanap_session_t *ap_sess_tab[AP_SESS_SIZE]; 120169691Skanap_session_t *ap_sess_list = NULL; 121169691Skanaproxy_t *ap_proxylist = NULL; 122169691Skanaproxy_t ap_proxies[] = { 123169691Skan#ifdef IPF_FTP_PROXY 124169691Skan { NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_fini, 125169691Skan ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL, NULL }, 126169691Skan#endif 127169691Skan#ifdef IPF_IRC_PROXY 128169691Skan { NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini, 129169691Skan ippr_irc_new, NULL, NULL, ippr_irc_out, NULL, NULL }, 130169691Skan#endif 131169691Skan#ifdef IPF_RCMD_PROXY 132169691Skan { NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, ippr_rcmd_fini, 133169691Skan ippr_rcmd_new, NULL, ippr_rcmd_in, ippr_rcmd_out, NULL, NULL }, 134169691Skan#endif 135169691Skan#ifdef IPF_RAUDIO_PROXY 136169691Skan { NULL, "raudio", (char)IPPROTO_TCP, 0, 0, ippr_raudio_init, ippr_raudio_fini, 137169691Skan ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL, NULL }, 138169691Skan#endif 139169691Skan#ifdef IPF_MSNRPC_PROXY 140169691Skan { NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, ippr_msnrpc_init, ippr_msnrpc_fini, 141169691Skan ippr_msnrpc_new, NULL, ippr_msnrpc_in, ippr_msnrpc_out, NULL, NULL }, 142169691Skan#endif 143169691Skan#ifdef IPF_NETBIOS_PROXY 144169691Skan { NULL, "netbios", (char)IPPROTO_UDP, 0, 0, ippr_netbios_init, ippr_netbios_fini, 145169691Skan NULL, NULL, NULL, ippr_netbios_out, NULL, NULL }, 146169691Skan#endif 147169691Skan#ifdef IPF_IPSEC_PROXY 148169691Skan { NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 149169691Skan ippr_ipsec_init, ippr_ipsec_fini, ippr_ipsec_new, ippr_ipsec_del, 150169691Skan ippr_ipsec_inout, ippr_ipsec_inout, ippr_ipsec_match, NULL }, 151169691Skan#endif 152169691Skan#ifdef IPF_PPTP_PROXY 153169691Skan { NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 154169691Skan ippr_pptp_init, ippr_pptp_fini, ippr_pptp_new, ippr_pptp_del, 155169691Skan ippr_pptp_inout, ippr_pptp_inout, NULL, NULL }, 156169691Skan#endif 157169691Skan#ifdef IPF_H323_PROXY 158169691Skan { NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini, 159169691Skan ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL, NULL }, 160169691Skan { NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL, 161169691Skan ippr_h245_new, NULL, NULL, ippr_h245_out, NULL, NULL }, 162169691Skan#endif 163169691Skan#ifdef IPF_RPCB_PROXY 164169691Skan# if 0 165169691Skan { NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 166169691Skan ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del, 167169691Skan ippr_rpcb_in, ippr_rpcb_out, NULL, NULL }, 168169691Skan# endif 169169691Skan { NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 170169691Skan ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del, 171169691Skan ippr_rpcb_in, ippr_rpcb_out, NULL, NULL }, 172169691Skan#endif 173169691Skan { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } 174169691Skan}; 175169691Skan 176169691Skan/* 177169691Skan * Dynamically add a new kernel proxy. Ensure that it is unique in the 178169691Skan * collection compiled in and dynamically added. 179169691Skan */ 180169691Skanint appr_add(ap) 181169691Skanaproxy_t *ap; 182169691Skan{ 183169691Skan aproxy_t *a; 184169691Skan 185169691Skan for (a = ap_proxies; a->apr_p; a++) 186169691Skan if ((a->apr_p == ap->apr_p) && 187169691Skan !strncmp(a->apr_label, ap->apr_label, 188169691Skan sizeof(ap->apr_label))) { 189169691Skan if (ipf_proxy_debug > 1) 190169691Skan printf("appr_add: %s/%d already present (B)\n", 191169691Skan a->apr_label, a->apr_p); 192169691Skan return -1; 193169691Skan } 194169691Skan 195169691Skan for (a = ap_proxylist; (a != NULL); a = a->apr_next) 196169691Skan if ((a->apr_p == ap->apr_p) && 197169691Skan !strncmp(a->apr_label, ap->apr_label, 198169691Skan sizeof(ap->apr_label))) { 199169691Skan if (ipf_proxy_debug > 1) 200169691Skan printf("appr_add: %s/%d already present (D)\n", 201169691Skan a->apr_label, a->apr_p); 202169691Skan return -1; 203169691Skan } 204169691Skan ap->apr_next = ap_proxylist; 205169691Skan ap_proxylist = ap; 206169691Skan if (ap->apr_init != NULL) 207169691Skan return (*ap->apr_init)(); 208169691Skan return 0; 209169691Skan} 210169691Skan 211169691Skan 212169691Skan/* 213169691Skan * Check to see if the proxy this control request has come through for 214169691Skan * exists, and if it does and it has a control function then invoke that 215169691Skan * control function. 216169691Skan */ 217169691Skanint appr_ctl(ctl) 218169691Skanap_ctl_t *ctl; 219169691Skan{ 220169691Skan aproxy_t *a; 221169691Skan int error; 222169691Skan 223169691Skan a = appr_lookup(ctl->apc_p, ctl->apc_label); 224169691Skan if (a == NULL) { 225169691Skan if (ipf_proxy_debug > 1) 226169691Skan printf("appr_ctl: can't find %s/%d\n", 227169691Skan ctl->apc_label, ctl->apc_p); 228169691Skan error = ESRCH; 229169691Skan } else if (a->apr_ctl == NULL) { 230169691Skan if (ipf_proxy_debug > 1) 231169691Skan printf("appr_ctl: no ctl function for %s/%d\n", 232169691Skan ctl->apc_label, ctl->apc_p); 233169691Skan error = ENXIO; 234169691Skan } else { 235169691Skan error = (*a->apr_ctl)(a, ctl); 236169691Skan if ((error != 0) && (ipf_proxy_debug > 1)) 237169691Skan printf("appr_ctl: %s/%d ctl error %d\n", 238169691Skan a->apr_label, a->apr_p, error); 239169691Skan } 240169691Skan return error; 241169691Skan} 242169691Skan 243 244/* 245 * Delete a proxy that has been added dynamically from those available. 246 * If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 247 * if it cannot be matched. 248 */ 249int appr_del(ap) 250aproxy_t *ap; 251{ 252 aproxy_t *a, **app; 253 254 for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) 255 if (a == ap) { 256 a->apr_flags |= APR_DELETE; 257 *app = a->apr_next; 258 if (ap->apr_ref != 0) { 259 if (ipf_proxy_debug > 2) 260 printf("appr_del: orphaning %s/%d\n", 261 ap->apr_label, ap->apr_p); 262 return 1; 263 } 264 return 0; 265 } 266 if (ipf_proxy_debug > 1) 267 printf("appr_del: proxy %lx not found\n", (u_long)ap); 268 return -1; 269} 270 271 272/* 273 * Return 1 if the packet is a good match against a proxy, else 0. 274 */ 275int appr_ok(fin, tcp, nat) 276fr_info_t *fin; 277tcphdr_t *tcp; 278ipnat_t *nat; 279{ 280 aproxy_t *apr = nat->in_apr; 281 u_short dport = nat->in_dport; 282 283 if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || 284 (fin->fin_p != apr->apr_p)) 285 return 0; 286 if ((tcp == NULL) && dport) 287 return 0; 288 return 1; 289} 290 291 292int appr_ioctl(data, cmd, mode, ctx) 293caddr_t data; 294ioctlcmd_t cmd; 295int mode; 296void *ctx; 297{ 298 ap_ctl_t ctl; 299 u_char *ptr; 300 int error; 301 302 mode = mode; /* LINT */ 303 304 switch (cmd) 305 { 306 case SIOCPROXY : 307 error = BCOPYIN(data, &ctl, sizeof(ctl)); 308 if (error != 0) 309 return EFAULT; 310 ptr = NULL; 311 312 if (ctl.apc_dsize > 0) { 313 KMALLOCS(ptr, u_char *, ctl.apc_dsize); 314 if (ptr == NULL) 315 error = ENOMEM; 316 else { 317 error = copyinptr(ctl.apc_data, ptr, 318 ctl.apc_dsize); 319 if (error == 0) 320 ctl.apc_data = ptr; 321 } 322 } else { 323 ctl.apc_data = NULL; 324 error = 0; 325 } 326 327 if (error == 0) 328 error = appr_ctl(&ctl); 329 330 if (ptr != NULL) { 331 KFREES(ptr, ctl.apc_dsize); 332 } 333 break; 334 335 default : 336 error = EINVAL; 337 } 338 return error; 339} 340 341 342/* 343 * If a proxy has a match function, call that to do extended packet 344 * matching. 345 */ 346int appr_match(fin, nat) 347fr_info_t *fin; 348nat_t *nat; 349{ 350 aproxy_t *apr; 351 ipnat_t *ipn; 352 int result; 353 354 ipn = nat->nat_ptr; 355 if (ipf_proxy_debug > 8) 356 printf("appr_match(%lx,%lx) aps %lx ptr %lx\n", 357 (u_long)fin, (u_long)nat, (u_long)nat->nat_aps, 358 (u_long)ipn); 359 360 if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) { 361 if (ipf_proxy_debug > 0) 362 printf("appr_match: flx 0x%x (BAD|SHORT)\n", 363 fin->fin_flx); 364 return -1; 365 } 366 367 apr = ipn->in_apr; 368 if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) { 369 if (ipf_proxy_debug > 0) 370 printf("appr_match:apr %lx apr_flags 0x%x\n", 371 (u_long)apr, apr ? apr->apr_flags : 0); 372 return -1; 373 } 374 375 if (apr->apr_match != NULL) { 376 result = (*apr->apr_match)(fin, nat->nat_aps, nat); 377 if (result != 0) { 378 if (ipf_proxy_debug > 4) 379 printf("appr_match: result %d\n", result); 380 return -1; 381 } 382 } 383 return 0; 384} 385 386 387/* 388 * Allocate a new application proxy structure and fill it in with the 389 * relevant details. call the init function once complete, prior to 390 * returning. 391 */ 392int appr_new(fin, nat) 393fr_info_t *fin; 394nat_t *nat; 395{ 396 register ap_session_t *aps; 397 aproxy_t *apr; 398 399 if (ipf_proxy_debug > 8) 400 printf("appr_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); 401 402 if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) { 403 if (ipf_proxy_debug > 0) 404 printf("appr_new: nat_ptr %lx nat_aps %lx\n", 405 (u_long)nat->nat_ptr, (u_long)nat->nat_aps); 406 return -1; 407 } 408 409 apr = nat->nat_ptr->in_apr; 410 411 if ((apr->apr_flags & APR_DELETE) || 412 (fin->fin_p != apr->apr_p)) { 413 if (ipf_proxy_debug > 2) 414 printf("appr_new: apr_flags 0x%x p %d/%d\n", 415 apr->apr_flags, fin->fin_p, apr->apr_p); 416 return -1; 417 } 418 419 KMALLOC(aps, ap_session_t *); 420 if (!aps) { 421 if (ipf_proxy_debug > 0) 422 printf("appr_new: malloc failed (%lu)\n", 423 (u_long)sizeof(ap_session_t)); 424 return -1; 425 } 426 427 bzero((char *)aps, sizeof(*aps)); 428 aps->aps_p = fin->fin_p; 429 aps->aps_data = NULL; 430 aps->aps_apr = apr; 431 aps->aps_psiz = 0; 432 if (apr->apr_new != NULL) 433 if ((*apr->apr_new)(fin, aps, nat) == -1) { 434 if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) { 435 KFREES(aps->aps_data, aps->aps_psiz); 436 } 437 KFREE(aps); 438 if (ipf_proxy_debug > 2) 439 printf("appr_new: new(%lx) failed\n", 440 (u_long)apr->apr_new); 441 return -1; 442 } 443 aps->aps_nat = nat; 444 aps->aps_next = ap_sess_list; 445 ap_sess_list = aps; 446 nat->nat_aps = aps; 447 448 return 0; 449} 450 451 452/* 453 * Check to see if a packet should be passed through an active proxy routine 454 * if one has been setup for it. We don't need to check the checksum here if 455 * IPFILTER_CKSUM is defined because if it is, a failed check causes FI_BAD 456 * to be set. 457 */ 458int appr_check(fin, nat) 459fr_info_t *fin; 460nat_t *nat; 461{ 462#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) 463# if defined(ICK_VALID) 464 mb_t *m; 465# endif 466 int dosum = 1; 467#endif 468 tcphdr_t *tcp = NULL; 469 udphdr_t *udp = NULL; 470 ap_session_t *aps; 471 aproxy_t *apr; 472 ip_t *ip; 473 short rv; 474 int err; 475#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) 476 u_32_t s1, s2, sd; 477#endif 478 479 if (fin->fin_flx & FI_BAD) { 480 if (ipf_proxy_debug > 0) 481 printf("appr_check: flx 0x%x (BAD)\n", fin->fin_flx); 482 return -1; 483 } 484 485#ifndef IPFILTER_CKSUM 486 if ((fin->fin_out == 0) && (fr_checkl4sum(fin) == -1)) { 487 if (ipf_proxy_debug > 0) 488 printf("appr_check: l4 checksum failure %d\n", 489 fin->fin_p); 490 if (fin->fin_p == IPPROTO_TCP) 491 frstats[fin->fin_out].fr_tcpbad++; 492 return -1; 493 } 494#endif 495 496 aps = nat->nat_aps; 497 if ((aps != NULL) && (aps->aps_p == fin->fin_p)) { 498 /* 499 * If there is data in this packet to be proxied then try and 500 * get it all into the one buffer, else drop it. 501 */ 502#if defined(MENTAT) || defined(HAVE_M_PULLDOWN) 503 if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE)) 504 if (fr_coalesce(fin) == -1) { 505 if (ipf_proxy_debug > 0) 506 printf("appr_check: fr_coalesce failed %x\n", fin->fin_flx); 507 return -1; 508 } 509#endif 510 ip = fin->fin_ip; 511 512 switch (fin->fin_p) 513 { 514 case IPPROTO_TCP : 515 tcp = (tcphdr_t *)fin->fin_dp; 516 517#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) 518 m = fin->fin_qfm; 519 if (dohwcksum && (m->b_ick_flag == ICK_VALID)) 520 dosum = 0; 521#endif 522 /* 523 * Don't bother the proxy with these...or in fact, 524 * should we free up proxy stuff when seen? 525 */ 526 if ((fin->fin_tcpf & TH_RST) != 0) 527 break; 528 /*FALLTHROUGH*/ 529 case IPPROTO_UDP : 530 udp = (udphdr_t *)fin->fin_dp; 531 break; 532 default : 533 break; 534 } 535 536 apr = aps->aps_apr; 537 err = 0; 538 if (fin->fin_out != 0) { 539 if (apr->apr_outpkt != NULL) 540 err = (*apr->apr_outpkt)(fin, aps, nat); 541 } else { 542 if (apr->apr_inpkt != NULL) 543 err = (*apr->apr_inpkt)(fin, aps, nat); 544 } 545 546 rv = APR_EXIT(err); 547 if (((ipf_proxy_debug > 0) && (rv != 0)) || 548 (ipf_proxy_debug > 8)) 549 printf("appr_check: out %d err %x rv %d\n", 550 fin->fin_out, err, rv); 551 if (rv == 1) 552 return -1; 553 554 if (rv == 2) { 555 appr_free(apr); 556 nat->nat_aps = NULL; 557 return -1; 558 } 559 560 /* 561 * If err != 0 then the data size of the packet has changed 562 * so we need to recalculate the header checksums for the 563 * packet. 564 */ 565#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) 566 if (err != 0) { 567 short adjlen = err & 0xffff; 568 569 s1 = LONG_SUM(fin->fin_plen - adjlen); 570 s2 = LONG_SUM(fin->fin_plen); 571 CALC_SUMD(s1, s2, sd); 572 fix_outcksum(fin, &ip->ip_sum, sd); 573 } 574#endif 575 576 /* 577 * For TCP packets, we may need to adjust the sequence and 578 * acknowledgement numbers to reflect changes in size of the 579 * data stream. 580 * 581 * For both TCP and UDP, recalculate the layer 4 checksum, 582 * regardless, as we can't tell (here) if data has been 583 * changed or not. 584 */ 585 if (tcp != NULL) { 586 err = appr_fixseqack(fin, ip, aps, APR_INC(err)); 587#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) 588 if (dosum) 589 tcp->th_sum = fr_cksum(fin->fin_qfm, ip, 590 IPPROTO_TCP, tcp, 591 fin->fin_plen); 592#else 593 tcp->th_sum = fr_cksum(fin->fin_m, ip, 594 IPPROTO_TCP, tcp, 595 fin->fin_plen); 596#endif 597 } else if ((udp != NULL) && (udp->uh_sum != 0)) { 598#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) 599 if (dosum) 600 udp->uh_sum = fr_cksum(fin->fin_qfm, ip, 601 IPPROTO_UDP, udp, 602 fin->fin_plen); 603#else 604 udp->uh_sum = fr_cksum(fin->fin_m, ip, 605 IPPROTO_UDP, udp, 606 fin->fin_plen); 607#endif 608 } 609 aps->aps_bytes += fin->fin_plen; 610 aps->aps_pkts++; 611 return 1; 612 } 613 return 0; 614} 615 616 617/* 618 * Search for an proxy by the protocol it is being used with and its name. 619 */ 620aproxy_t *appr_lookup(pr, name) 621u_int pr; 622char *name; 623{ 624 aproxy_t *ap; 625 626 if (ipf_proxy_debug > 8) 627 printf("appr_lookup(%d,%s)\n", pr, name); 628 629 for (ap = ap_proxies; ap->apr_p; ap++) 630 if ((ap->apr_p == pr) && 631 !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { 632 ap->apr_ref++; 633 return ap; 634 } 635 636 for (ap = ap_proxylist; ap; ap = ap->apr_next) 637 if ((ap->apr_p == pr) && 638 !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { 639 ap->apr_ref++; 640 return ap; 641 } 642 if (ipf_proxy_debug > 2) 643 printf("appr_lookup: failed for %d/%s\n", pr, name); 644 return NULL; 645} 646 647 648void appr_free(ap) 649aproxy_t *ap; 650{ 651 ap->apr_ref--; 652} 653 654 655void aps_free(aps) 656ap_session_t *aps; 657{ 658 ap_session_t *a, **ap; 659 aproxy_t *apr; 660 661 if (!aps) 662 return; 663 664 for (ap = &ap_sess_list; ((a = *ap) != NULL); ap = &a->aps_next) 665 if (a == aps) { 666 *ap = a->aps_next; 667 break; 668 } 669 670 apr = aps->aps_apr; 671 if ((apr != NULL) && (apr->apr_del != NULL)) 672 (*apr->apr_del)(aps); 673 674 if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) 675 KFREES(aps->aps_data, aps->aps_psiz); 676 KFREE(aps); 677} 678 679 680/* 681 * returns 2 if ack or seq number in TCP header is changed, returns 0 otherwise 682 */ 683static int appr_fixseqack(fin, ip, aps, inc) 684fr_info_t *fin; 685ip_t *ip; 686ap_session_t *aps; 687int inc; 688{ 689 int sel, ch = 0, out, nlen; 690 u_32_t seq1, seq2; 691 tcphdr_t *tcp; 692 short inc2; 693 694 tcp = (tcphdr_t *)fin->fin_dp; 695 out = fin->fin_out; 696 /* 697 * fin->fin_plen has already been adjusted by 'inc'. 698 */ 699 nlen = fin->fin_plen; 700 nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2); 701 702 inc2 = inc; 703 inc = (int)inc2; 704 705 if (out != 0) { 706 seq1 = (u_32_t)ntohl(tcp->th_seq); 707 sel = aps->aps_sel[out]; 708 709 /* switch to other set ? */ 710 if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 711 (seq1 > aps->aps_seqmin[!sel])) { 712 if (ipf_proxy_debug > 7) 713 printf("proxy out switch set seq %d -> %d %x > %x\n", 714 sel, !sel, seq1, 715 aps->aps_seqmin[!sel]); 716 sel = aps->aps_sel[out] = !sel; 717 } 718 719 if (aps->aps_seqoff[sel]) { 720 seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel]; 721 if (seq1 > seq2) { 722 seq2 = aps->aps_seqoff[sel]; 723 seq1 += seq2; 724 tcp->th_seq = htonl(seq1); 725 ch = 1; 726 } 727 } 728 729 if (inc && (seq1 > aps->aps_seqmin[!sel])) { 730 aps->aps_seqmin[sel] = seq1 + nlen - 1; 731 aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc; 732 if (ipf_proxy_debug > 7) 733 printf("proxy seq set %d at %x to %d + %d\n", 734 sel, aps->aps_seqmin[sel], 735 aps->aps_seqoff[sel], inc); 736 } 737 738 /***/ 739 740 seq1 = ntohl(tcp->th_ack); 741 sel = aps->aps_sel[1 - out]; 742 743 /* switch to other set ? */ 744 if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 745 (seq1 > aps->aps_ackmin[!sel])) { 746 if (ipf_proxy_debug > 7) 747 printf("proxy out switch set ack %d -> %d %x > %x\n", 748 sel, !sel, seq1, 749 aps->aps_ackmin[!sel]); 750 sel = aps->aps_sel[1 - out] = !sel; 751 } 752 753 if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) { 754 seq2 = aps->aps_ackoff[sel]; 755 tcp->th_ack = htonl(seq1 - seq2); 756 ch = 1; 757 } 758 } else { 759 seq1 = ntohl(tcp->th_seq); 760 sel = aps->aps_sel[out]; 761 762 /* switch to other set ? */ 763 if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && 764 (seq1 > aps->aps_ackmin[!sel])) { 765 if (ipf_proxy_debug > 7) 766 printf("proxy in switch set ack %d -> %d %x > %x\n", 767 sel, !sel, seq1, aps->aps_ackmin[!sel]); 768 sel = aps->aps_sel[out] = !sel; 769 } 770 771 if (aps->aps_ackoff[sel]) { 772 seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel]; 773 if (seq1 > seq2) { 774 seq2 = aps->aps_ackoff[sel]; 775 seq1 += seq2; 776 tcp->th_seq = htonl(seq1); 777 ch = 1; 778 } 779 } 780 781 if (inc && (seq1 > aps->aps_ackmin[!sel])) { 782 aps->aps_ackmin[!sel] = seq1 + nlen - 1; 783 aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; 784 785 if (ipf_proxy_debug > 7) 786 printf("proxy ack set %d at %x to %d + %d\n", 787 !sel, aps->aps_seqmin[!sel], 788 aps->aps_seqoff[sel], inc); 789 } 790 791 /***/ 792 793 seq1 = ntohl(tcp->th_ack); 794 sel = aps->aps_sel[1 - out]; 795 796 /* switch to other set ? */ 797 if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && 798 (seq1 > aps->aps_seqmin[!sel])) { 799 if (ipf_proxy_debug > 7) 800 printf("proxy in switch set seq %d -> %d %x > %x\n", 801 sel, !sel, seq1, aps->aps_seqmin[!sel]); 802 sel = aps->aps_sel[1 - out] = !sel; 803 } 804 805 if (aps->aps_seqoff[sel] != 0) { 806 if (ipf_proxy_debug > 7) 807 printf("sel %d seqoff %d seq1 %x seqmin %x\n", 808 sel, aps->aps_seqoff[sel], seq1, 809 aps->aps_seqmin[sel]); 810 if (seq1 > aps->aps_seqmin[sel]) { 811 seq2 = aps->aps_seqoff[sel]; 812 tcp->th_ack = htonl(seq1 - seq2); 813 ch = 1; 814 } 815 } 816 } 817 818 if (ipf_proxy_debug > 8) 819 printf("appr_fixseqack: seq %x ack %x\n", 820 (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack)); 821 return ch ? 2 : 0; 822} 823 824 825/* 826 * Initialise hook for kernel application proxies. 827 * Call the initialise routine for all the compiled in kernel proxies. 828 */ 829int appr_init() 830{ 831 aproxy_t *ap; 832 int err = 0; 833 834 for (ap = ap_proxies; ap->apr_p; ap++) { 835 if (ap->apr_init != NULL) { 836 err = (*ap->apr_init)(); 837 if (err != 0) 838 break; 839 } 840 } 841 return err; 842} 843 844 845/* 846 * Unload hook for kernel application proxies. 847 * Call the finialise routine for all the compiled in kernel proxies. 848 */ 849void appr_unload() 850{ 851 aproxy_t *ap; 852 853 for (ap = ap_proxies; ap->apr_p; ap++) 854 if (ap->apr_fini != NULL) 855 (*ap->apr_fini)(); 856 for (ap = ap_proxylist; ap; ap = ap->apr_next) 857 if (ap->apr_fini != NULL) 858 (*ap->apr_fini)(); 859} 860