The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netpfil/ipfilter/netinet/ip_proxy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 5d8c5f2242f8ccebe836d8c5ceac946c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.