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/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 /*
    2  * Copyright (C) 1997 by Darren Reed.
    3  *
    4  * Redistribution and use in source and binary forms are permitted
    5  * provided that this notice is preserved and due credit is given
    6  * to the original author and the contributors.
    7  */
    8 #if !defined(lint)
    9 static const char rcsid[] = "@(#)$FreeBSD$";
   10 #endif
   11 
   12 #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
   13 # define        _KERNEL
   14 #endif
   15 
   16 #if !defined(_KERNEL) && !defined(KERNEL)
   17 # include <stdio.h>
   18 # include <string.h>
   19 # include <stdlib.h>
   20 #endif
   21 #include <sys/errno.h>
   22 #include <sys/types.h>
   23 #include <sys/param.h>
   24 #include <sys/time.h>
   25 #include <sys/file.h>
   26 #if !defined(__FreeBSD__)
   27 # include <sys/ioctl.h>
   28 #endif
   29 #include <sys/fcntl.h>
   30 #include <sys/uio.h>
   31 #ifndef linux
   32 # include <sys/protosw.h>
   33 #endif
   34 #include <sys/socket.h>
   35 #if defined(_KERNEL)
   36 # if !defined(linux)
   37 #  include <sys/systm.h>
   38 # else
   39 #  include <linux/string.h>
   40 # endif
   41 #endif
   42 #if !defined(__SVR4) && !defined(__svr4__)
   43 # ifndef linux
   44 #  include <sys/mbuf.h>
   45 # endif
   46 #else
   47 # include <sys/byteorder.h>
   48 # include <sys/dditypes.h>
   49 # include <sys/stream.h>
   50 # include <sys/kmem.h>
   51 #endif
   52 #if __FreeBSD__ > 2
   53 # include <sys/queue.h>
   54 # include <sys/malloc.h>
   55 #endif
   56 #include <net/if.h>
   57 #ifdef sun
   58 # include <net/af.h>
   59 #endif
   60 #include <net/route.h>
   61 #include <netinet/in.h>
   62 #include <netinet/in_systm.h>
   63 #include <netinet/ip.h>
   64 #ifndef linux
   65 # include <netinet/ip_var.h>
   66 #endif
   67 #include <netinet/tcp.h>
   68 #include <netinet/udp.h>
   69 #include <netinet/ip_icmp.h>
   70 #include "netinet/ip_compat.h"
   71 #include <netinet/tcpip.h>
   72 #include "netinet/ip_fil.h"
   73 #include "netinet/ip_proxy.h"
   74 #include "netinet/ip_nat.h"
   75 #include "netinet/ip_state.h"
   76 
   77 #ifndef MIN
   78 #define MIN(a,b)        (((a)<(b))?(a):(b))
   79 #endif
   80 
   81 static ap_session_t *ap_find __P((ip_t *, tcphdr_t *));
   82 static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *,
   83                                          fr_info_t *, nat_t *));
   84 
   85 static int ap_matchsrcdst __P((ap_session_t *aps, struct in_addr src,
   86                                struct in_addr dst, void *tcp, u_short sport,
   87                                u_short dport));
   88 
   89 #define AP_SESS_SIZE    53
   90 
   91 #if defined(_KERNEL) && !defined(linux)
   92 #include "netinet/ip_ftp_pxy.c"
   93 #endif
   94 
   95 ap_session_t    *ap_sess_tab[AP_SESS_SIZE];
   96 aproxy_t        ap_proxies[] = {
   97 #ifdef  IPF_FTP_PROXY
   98         { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_in, ippr_ftp_out },
   99 #endif
  100         { "", '\0', 0, 0, NULL, NULL }
  101 };
  102 
  103 
  104 int ap_ok(ip, tcp, nat)
  105 ip_t *ip;
  106 tcphdr_t *tcp;
  107 ipnat_t *nat;
  108 {
  109         aproxy_t *apr = nat->in_apr;
  110         u_short dport = nat->in_dport;
  111 
  112         if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
  113             (ip->ip_p != apr->apr_p))
  114                 return 0;
  115         if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
  116                 return 0;
  117         return 1;
  118 }
  119 
  120 
  121 static int
  122 ap_matchsrcdst(aps, src, dst, tcp, sport, dport)
  123 ap_session_t *aps;
  124 struct in_addr src, dst;
  125 void *tcp;
  126 u_short sport, dport;
  127 {
  128         if (aps->aps_dst.s_addr == dst.s_addr) {
  129                 if ((aps->aps_src.s_addr == src.s_addr) &&
  130                     (!tcp || (sport == aps->aps_sport) &&
  131                      (dport == aps->aps_dport)))
  132                         return 1;
  133         } else if (aps->aps_dst.s_addr == src.s_addr) {
  134                 if ((aps->aps_src.s_addr == dst.s_addr) &&
  135                     (!tcp || (sport == aps->aps_dport) &&
  136                      (dport == aps->aps_sport)))
  137                         return 1;
  138         }
  139         return 0;
  140 }
  141 
  142 
  143 static ap_session_t *ap_find(ip, tcp)
  144 ip_t *ip;
  145 tcphdr_t *tcp;
  146 {
  147         register u_char p = ip->ip_p;
  148         register ap_session_t *aps;
  149         register u_short sp, dp;
  150         register u_long hv;
  151         struct in_addr src, dst;
  152 
  153         src = ip->ip_src, dst = ip->ip_dst;
  154         sp = dp = 0;                    /* XXX gcc -Wunitialized */
  155 
  156         hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
  157         hv *= 651733;
  158         if (tcp) {
  159                 sp = tcp->th_sport;
  160                 dp = tcp->th_dport;
  161                 hv ^= (sp + dp);
  162                 hv *= 5;
  163         }
  164         hv %= AP_SESS_SIZE;
  165 
  166         for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next)
  167                 if ((aps->aps_p == p) &&
  168                     ap_matchsrcdst(aps, src, dst, tcp, sp, dp))
  169                         break;
  170         return aps;
  171 }
  172 
  173 
  174 /*
  175  * Allocate a new application proxy structure and fill it in with the
  176  * relevant details.  call the init function once complete, prior to
  177  * returning.
  178  */
  179 static ap_session_t *ap_new_session(apr, ip, tcp, fin, nat)
  180 aproxy_t *apr;
  181 ip_t *ip;
  182 tcphdr_t *tcp;
  183 fr_info_t *fin;
  184 nat_t *nat;
  185 {
  186         register ap_session_t *aps;
  187         u_short dport;
  188         u_long hv;
  189 
  190         if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
  191             (ip->ip_p != apr->apr_p))
  192                 return NULL;
  193         dport = nat->nat_ptr->in_dport;
  194         if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
  195                 return NULL;
  196 
  197         hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
  198         hv *= 651733;
  199         if (tcp) {
  200                 hv ^= (tcp->th_sport + tcp->th_dport);
  201                 hv *= 5;
  202         }
  203         hv %= AP_SESS_SIZE;
  204 
  205         KMALLOC(aps, ap_session_t *, sizeof(*aps));
  206         if (!aps)
  207                 return NULL;
  208         bzero((char *)aps, sizeof(*aps));
  209         aps->aps_apr = apr;
  210         aps->aps_src = ip->ip_src;
  211         aps->aps_dst = ip->ip_dst;
  212         aps->aps_p = ip->ip_p;
  213         aps->aps_tout = 1200;   /* XXX */
  214         if (tcp) {
  215                 aps->aps_sport = tcp->th_sport;
  216                 aps->aps_dport = tcp->th_dport;
  217         }
  218         aps->aps_data = NULL;
  219         aps->aps_psiz = 0;
  220         aps->aps_next = ap_sess_tab[hv];
  221         ap_sess_tab[hv] = aps;
  222         (void) (*apr->apr_init)(fin, ip, tcp, aps, nat);
  223         return aps;
  224 }
  225 
  226 
  227 /*
  228  * check to see if a packet should be passed through an active proxy routine
  229  * if one has been setup for it.
  230  */
  231 int ap_check(ip, tcp, fin, nat)
  232 ip_t *ip;
  233 tcphdr_t *tcp;
  234 fr_info_t *fin;
  235 nat_t *nat;
  236 {
  237         ap_session_t *aps;
  238         aproxy_t *apr;
  239         int err;
  240 
  241         if (!(fin->fin_fi.fi_fl & FI_TCPUDP))
  242                 tcp = NULL;
  243 
  244         if ((aps = ap_find(ip, tcp)) ||
  245             (aps = ap_new_session(nat->nat_ptr->in_apr, ip, tcp, fin, nat))) {
  246                 if (ip->ip_p == IPPROTO_TCP) {
  247                         /*
  248                          * verify that the checksum is correct.  If not, then
  249                          * don't do anything with this packet.
  250                          */
  251                         if (tcp->th_sum != fr_tcpsum(*(mb_t **)fin->fin_mp,
  252                                                      ip, tcp, ip->ip_len)) {
  253                                 frstats[fin->fin_out].fr_tcpbad++;
  254                                 return -1;
  255                         }
  256                         fr_tcp_age(&aps->aps_tout, aps->aps_state, ip, fin,
  257                                    tcp->th_sport == aps->aps_sport);
  258                 }
  259 
  260                 apr = aps->aps_apr;
  261                 err = 0;
  262                 if (fin->fin_out) {
  263                         if (apr->apr_outpkt)
  264                                 err = (*apr->apr_outpkt)(fin, ip, tcp,
  265                                                          aps, nat);
  266                 } else {
  267                         if (apr->apr_inpkt)
  268                                 err = (*apr->apr_inpkt)(fin, ip, tcp,
  269                                                         aps, nat);
  270                 }
  271                 if (err == 2) {
  272                         tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip,
  273                                                 tcp, ip->ip_len);
  274                         err = 0;
  275                 }
  276                 return err;
  277         }
  278         return -1;
  279 }
  280 
  281 
  282 aproxy_t *ap_match(pr, name)
  283 u_char pr;
  284 char *name;
  285 {
  286         aproxy_t *ap;
  287 
  288         for (ap = ap_proxies; ap->apr_p; ap++)
  289                 if ((ap->apr_p == pr) &&
  290                     !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
  291                         ap->apr_ref++;
  292                         return ap;
  293                 }
  294         return NULL;
  295 }
  296 
  297 
  298 void ap_free(ap)
  299 aproxy_t *ap;
  300 {
  301         ap->apr_ref--;
  302 }
  303 
  304 
  305 void aps_free(aps)
  306 ap_session_t *aps;
  307 {
  308         if (aps->aps_data && aps->aps_psiz)
  309                 KFREES(aps->aps_data, aps->aps_psiz);
  310         KFREE(aps);
  311 }
  312 
  313 
  314 void ap_unload()
  315 {
  316         ap_session_t *aps;
  317         int i;
  318 
  319         for (i = 0; i < AP_SESS_SIZE; i++)
  320                 while ((aps = ap_sess_tab[i])) {
  321                         ap_sess_tab[i] = aps->aps_next;
  322                         aps_free(aps);
  323                 }
  324 }
  325 
  326 
  327 void ap_expire()
  328 {
  329         ap_session_t *aps, **apsp;
  330         int i;
  331 
  332         for (i = 0; i < AP_SESS_SIZE; i++)
  333                 for (apsp = &ap_sess_tab[i]; (aps = *apsp); ) {
  334                         aps->aps_tout--;
  335                         if (!aps->aps_tout) {
  336                                 ap_sess_tab[i] = aps->aps_next;
  337                                 aps_free(aps);
  338                                 *apsp = aps->aps_next;
  339                         } else
  340                                 apsp = &aps->aps_next;
  341                 }
  342 }

Cache object: fb07c87468ef58af0bf603dd4e755dd8


[ 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.