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_ftp_pxy.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  * Simple FTP transparent proxy for in-kernel use.  For use with the NAT
    3  * code.
    4  */
    5 
    6 #define isdigit(x)      ((x) >= '' && (x) <= '9')
    7 
    8 #define IPF_FTP_PROXY
    9 
   10 #define IPF_MINPORTLEN  18
   11 #define IPF_MAXPORTLEN  30
   12 
   13 
   14 int ippr_ftp_init __P((fr_info_t *, ip_t *, tcphdr_t *,
   15                        ap_session_t *, nat_t *));
   16 int ippr_ftp_in __P((fr_info_t *, ip_t *, tcphdr_t *,
   17                        ap_session_t *, nat_t *));
   18 int ippr_ftp_out __P((fr_info_t *, ip_t *, tcphdr_t *,
   19                        ap_session_t *, nat_t *));
   20 u_short ipf_ftp_atoi __P((char **));
   21 
   22 
   23 /*
   24  * FTP application proxy initialization.
   25  */
   26 int ippr_ftp_init(fin, ip, tcp, aps, nat)
   27 fr_info_t *fin;
   28 ip_t *ip;
   29 tcphdr_t *tcp;
   30 ap_session_t *aps;
   31 nat_t *nat;
   32 {
   33         aps->aps_sport = tcp->th_sport;
   34         aps->aps_dport = tcp->th_dport;
   35         return 0;
   36 }
   37 
   38 
   39 int ippr_ftp_in(fin, ip, tcp, aps, nat)
   40 fr_info_t *fin;
   41 ip_t *ip;
   42 tcphdr_t *tcp;
   43 ap_session_t *aps;
   44 nat_t *nat;
   45 {
   46         u_32_t  sum1, sum2;
   47         short sel;
   48 
   49         if (tcp->th_sport == aps->aps_dport) {
   50                 sum2 = (u_32_t)ntohl(tcp->th_ack);
   51                 sel = aps->aps_sel;
   52                 if ((aps->aps_after[!sel] > aps->aps_after[sel]) &&
   53                         (sum2 > aps->aps_after[!sel])) {
   54                         sel = aps->aps_sel = !sel; /* switch to other set */
   55                 }
   56                 if (aps->aps_seqoff[sel] && (sum2 > aps->aps_after[sel])) {
   57                         sum1 = (u_32_t)aps->aps_seqoff[sel];
   58                         tcp->th_ack = htonl(sum2 - sum1);
   59                         return 2;
   60                 }
   61         }
   62         return 0;
   63 }
   64 
   65 
   66 /*
   67  * ipf_ftp_atoi - implement a version of atoi which processes numbers in
   68  * pairs separated by commas (which are expected to be in the range 0 - 255),
   69  * returning a 16 bit number combining either side of the , as the MSB and
   70  * LSB.
   71  */
   72 u_short ipf_ftp_atoi(ptr)
   73 char **ptr;
   74 {
   75         register char *s = *ptr, c;
   76         register u_char i = 0, j = 0;
   77 
   78         while ((c = *s++) && isdigit(c)) {
   79                 i *= 10;
   80                 i += c - '';
   81         }
   82         if (c != ',') {
   83                 *ptr = NULL;
   84                 return 0;
   85         }
   86         while ((c = *s++) && isdigit(c)) {
   87                 j *= 10;
   88                 j += c - '';
   89         }
   90         *ptr = s;
   91         return (i << 8) | j;
   92 }
   93 
   94 
   95 int ippr_ftp_out(fin, ip, tcp, aps, nat)
   96 fr_info_t *fin;
   97 ip_t *ip;
   98 tcphdr_t *tcp;
   99 ap_session_t *aps;
  100 nat_t *nat;
  101 {
  102         register u_32_t sum1, sum2;
  103         char    newbuf[IPF_MAXPORTLEN+1];
  104         char    portbuf[IPF_MAXPORTLEN+1], *s;
  105         int     ch = 0, off = (ip->ip_hl << 2) + (tcp->th_off << 2);
  106         u_int   a1, a2, a3, a4;
  107         u_short a5, a6;
  108         int     olen, dlen, nlen = 0, inc = 0;
  109         tcphdr_t tcph, *tcp2 = &tcph;
  110         void    *savep;
  111         nat_t   *ipn;
  112         struct  in_addr swip;
  113         mb_t *m = *(mb_t **)fin->fin_mp;
  114 
  115 #if     SOLARIS
  116         mb_t *m1;
  117 
  118         /* skip any leading M_PROTOs */
  119         while(m && (MTYPE(m) != M_DATA))
  120                 m = m->b_cont;
  121         PANIC((!m),("ippr_ftp_out: no M_DATA"));
  122 
  123         dlen = msgdsize(m) - off;
  124         bzero(portbuf, sizeof(portbuf));
  125         copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
  126 #else
  127         dlen = mbufchainlen(m) - off;
  128         bzero(portbuf, sizeof(portbuf));
  129         m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
  130 #endif
  131         portbuf[IPF_MAXPORTLEN] = '\0';
  132 
  133         if ((dlen < IPF_MINPORTLEN) || strncmp(portbuf, "PORT ", 5))
  134                 goto adjust_seqack;
  135 
  136         /*
  137          * Skip the PORT command + space
  138          */
  139         s = portbuf + 5;
  140         /*
  141          * Pick out the address components, two at a time.
  142          */
  143         (void) ipf_ftp_atoi(&s);
  144         if (!s)
  145                 goto adjust_seqack;
  146         (void) ipf_ftp_atoi(&s);
  147         if (!s)
  148                 goto adjust_seqack;
  149         a5 = ipf_ftp_atoi(&s);
  150         if (!s)
  151                 goto adjust_seqack;
  152         /*
  153          * check for CR-LF at the end.
  154          */
  155         if (*s != '\n' || *(s - 1) != '\r')
  156                 goto adjust_seqack;
  157         a6 = a5 & 0xff;
  158         a5 >>= 8;
  159         /*
  160          * Calculate new address parts for PORT command
  161          */
  162         a1 = ntohl(ip->ip_src.s_addr);
  163         a2 = (a1 >> 16) & 0xff;
  164         a3 = (a1 >> 8) & 0xff;
  165         a4 = a1 & 0xff;
  166         a1 >>= 24;
  167         olen = s - portbuf + 1;
  168         (void) snprintf(newbuf, sizeof(newbuf), "PORT %d,%d,%d,%d,%d,%d\r\n",
  169                 a1, a2, a3, a4, a5, a6);
  170         nlen = strlen(newbuf);
  171         inc = nlen - olen;
  172 #if SOLARIS
  173         for (m1 = m; m1->b_cont; m1 = m1->b_cont)
  174                 ;
  175         if (inc > 0) {
  176                 mblk_t *nm;
  177 
  178                 /* alloc enough to keep same trailer space for lower driver */
  179                 nm = allocb(nlen + m1->b_datap->db_lim - m1->b_wptr, BPRI_MED);
  180                 PANIC((!nm),("ippr_ftp_out: allocb failed"));
  181 
  182                 nm->b_band = m1->b_band;
  183                 nm->b_wptr += nlen;
  184 
  185                 m1->b_wptr -= olen;
  186                 PANIC((m1->b_wptr < m1->b_rptr),("ippr_ftp_out: cannot handle fragmented data block"));
  187 
  188                 linkb(m1, nm);
  189         } else {
  190                 m1->b_wptr += inc;
  191         }
  192         copyin_mblk(m, off, nlen, newbuf);
  193 #else
  194         if (inc < 0)
  195                 m_adj(m, inc);
  196         /* the mbuf chain will be extended if necessary by m_copyback() */
  197         m_copyback(m, off, nlen, newbuf);
  198 #endif
  199         if (inc) {
  200 #if SOLARIS || defined(__sgi)
  201                 sum1 = ip->ip_len;
  202                 sum2 = ip->ip_len + inc;
  203 
  204                 /* Because ~1 == -2, We really need ~1 == -1 */
  205                 if (sum1 > sum2)
  206                         sum2--;
  207                 sum2 -= sum1;
  208                 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
  209 
  210                 fix_outcksum(&ip->ip_sum, sum2);
  211 #endif
  212                 ip->ip_len += inc;
  213         }
  214         ch = 1;
  215 
  216         /*
  217          * Add skeleton NAT entry for connection which will come back the
  218          * other way.
  219          */
  220         savep = fin->fin_dp;
  221         fin->fin_dp = (char *)tcp2;
  222         bzero((char *)tcp2, sizeof(*tcp2));
  223         tcp2->th_sport = htons(a5 << 8 | a6);
  224         tcp2->th_dport = htons(20);
  225         swip = ip->ip_src;
  226         ip->ip_src = nat->nat_inip;
  227         if ((ipn = nat_new(nat->nat_ptr, ip, fin, IPN_TCP, NAT_OUTBOUND)))
  228                 ipn->nat_age = fr_defnatage;
  229         (void) fr_addstate(ip, fin, FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE);
  230         ip->ip_src = swip;
  231         fin->fin_dp = (char *)savep;
  232 
  233 adjust_seqack:
  234         if (tcp->th_dport == aps->aps_dport) {
  235                 sum2 = (u_32_t)ntohl(tcp->th_seq);
  236                 off = aps->aps_sel;
  237                 if ((aps->aps_after[!off] > aps->aps_after[off]) &&
  238                         (sum2 > aps->aps_after[!off])) {
  239                         off = aps->aps_sel = !off; /* switch to other set */
  240                 }
  241                 if (aps->aps_seqoff[off]) {
  242                         sum1 = (u_32_t)aps->aps_after[off] -
  243                                aps->aps_seqoff[off];
  244                         if (sum2 > sum1) {
  245                                 sum1 = (u_32_t)aps->aps_seqoff[off];
  246                                 sum2 += sum1;
  247                                 tcp->th_seq = htonl(sum2);
  248                                 ch = 1;
  249                         }
  250                 }
  251 
  252                 if (inc && (sum2 > aps->aps_after[!off])) {
  253                         aps->aps_after[!off] = sum2 + nlen - 1;
  254                         aps->aps_seqoff[!off] = aps->aps_seqoff[off] + inc;
  255                 }
  256         }
  257         return ch ? 2 : 0;
  258 }

Cache object: 74cfea0658ace9d3349abb099f33cc75


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