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/libalias/alias_ftp.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 /*
   33     Alias_ftp.c performs special processing for FTP sessions under
   34     TCP.  Specifically, when a PORT/EPRT command from the client
   35     side or 227/229 reply from the server is sent, it is intercepted
   36     and modified.  The address is changed to the gateway machine
   37     and an aliasing port is used.
   38 
   39     For this routine to work, the message must fit entirely into a
   40     single TCP packet.  This is typically the case, but exceptions
   41     can easily be envisioned under the actual specifications.
   42 
   43     Probably the most troubling aspect of the approach taken here is
   44     that the new message will typically be a different length, and
   45     this causes a certain amount of bookkeeping to keep track of the
   46     changes of sequence and acknowledgment numbers, since the client
   47     machine is totally unaware of the modification to the TCP stream.
   48 
   49     References: RFC 959, RFC 2428.
   50 
   51     Initial version:  August, 1996  (cjm)
   52 
   53     Version 1.6
   54          Brian Somers and Martin Renters identified an IP checksum
   55          error for modified IP packets.
   56 
   57     Version 1.7:  January 9, 1996 (cjm)
   58          Differential checksum computation for change
   59          in IP packet length.
   60 
   61     Version 2.1:  May, 1997 (cjm)
   62          Very minor changes to conform with
   63          local/global/function naming conventions
   64          within the packet aliasing module.
   65 
   66     Version 3.1:  May, 2000 (eds)
   67          Add support for passive mode, alias the 227 replies.
   68 
   69     See HISTORY file for record of revisions.
   70 */
   71 
   72 /* Includes */
   73 #ifdef _KERNEL
   74 #include <sys/param.h>
   75 #include <sys/ctype.h>
   76 #include <sys/systm.h>
   77 #include <sys/kernel.h>
   78 #include <sys/module.h>
   79 #else
   80 #include <ctype.h>
   81 #include <errno.h>
   82 #include <sys/types.h>
   83 #include <stdio.h>
   84 #include <string.h>
   85 #endif
   86 
   87 #include <netinet/in_systm.h>
   88 #include <netinet/in.h>
   89 #include <netinet/ip.h>
   90 #include <netinet/tcp.h>
   91 
   92 #ifdef _KERNEL
   93 #include <netinet/libalias/alias.h>
   94 #include <netinet/libalias/alias_local.h>
   95 #include <netinet/libalias/alias_mod.h>
   96 #else
   97 #include "alias_local.h"
   98 #include "alias_mod.h"
   99 #endif
  100 
  101 #define FTP_CONTROL_PORT_NUMBER 21
  102 
  103 static void
  104 AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
  105     int maxpacketsize);
  106 static void
  107 AliasHandleFtpIn(struct libalias *, struct ip *, struct alias_link *);
  108 
  109 static int
  110 fingerprint_out(struct libalias *la, struct alias_data *ah)
  111 {
  112         if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
  113             ah->maxpktsize == 0)
  114                 return (-1);
  115         if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
  116             ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
  117                 return (0);
  118         return (-1);
  119 }
  120 
  121 static int
  122 fingerprint_in(struct libalias *la, struct alias_data *ah)
  123 {
  124         if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
  125                 return (-1);
  126         if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
  127             ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
  128                 return (0);
  129         return (-1);
  130 }
  131 
  132 static int
  133 protohandler_out(struct libalias *la, struct ip *pip, struct alias_data *ah)
  134 {
  135         AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize);
  136         return (0);
  137 }
  138 
  139 static int
  140 protohandler_in(struct libalias *la, struct ip *pip, struct alias_data *ah)
  141 {
  142         AliasHandleFtpIn(la, pip, ah->lnk);
  143         return (0);
  144 }
  145 
  146 struct proto_handler handlers[] = {
  147         {
  148           .pri = 80,
  149           .dir = OUT,
  150           .proto = TCP,
  151           .fingerprint = &fingerprint_out,
  152           .protohandler = &protohandler_out
  153         },
  154         {
  155           .pri = 80,
  156           .dir = IN,
  157           .proto = TCP,
  158           .fingerprint = &fingerprint_in,
  159           .protohandler = &protohandler_in
  160         },
  161         { EOH }
  162 };
  163 
  164 static int
  165 mod_handler(module_t mod, int type, void *data)
  166 {
  167         int error;
  168 
  169         switch (type) {
  170         case MOD_LOAD:
  171                 error = 0;
  172                 LibAliasAttachHandlers(handlers);
  173                 break;
  174         case MOD_UNLOAD:
  175                 error = 0;
  176                 LibAliasDetachHandlers(handlers);
  177                 break;
  178         default:
  179                 error = EINVAL;
  180         }
  181         return (error);
  182 }
  183 
  184 #ifdef _KERNEL
  185 static
  186 #endif
  187 moduledata_t alias_mod = {
  188        "alias_ftp", mod_handler, NULL
  189 };
  190 
  191 #ifdef _KERNEL
  192 DECLARE_MODULE(alias_ftp, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
  193 MODULE_VERSION(alias_ftp, 1);
  194 MODULE_DEPEND(alias_ftp, libalias, 1, 1, 1);
  195 #endif
  196 
  197 #define FTP_CONTROL_PORT_NUMBER 21
  198 #define MAX_MESSAGE_SIZE        128
  199 
  200 /* FTP protocol flags. */
  201 #define WAIT_CRLF               0x01
  202 
  203 enum ftp_message_type {
  204         FTP_PORT_COMMAND,
  205         FTP_EPRT_COMMAND,
  206         FTP_227_REPLY,
  207         FTP_229_REPLY,
  208         FTP_UNKNOWN_MESSAGE
  209 };
  210 
  211 static int      ParseFtpPortCommand(struct libalias *la, char *, int);
  212 static int      ParseFtpEprtCommand(struct libalias *la, char *, int);
  213 static int      ParseFtp227Reply(struct libalias *la, char *, int);
  214 static int      ParseFtp229Reply(struct libalias *la, char *, int);
  215 static void     NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
  216 
  217 static void
  218 AliasHandleFtpOut(
  219     struct libalias *la,
  220     struct ip *pip,             /* IP packet to examine/patch */
  221     struct alias_link *lnk,     /* The link to go through (aliased port) */
  222     int maxpacketsize           /* The maximum size this packet can grow to
  223                                    (including headers) */ )
  224 {
  225         int hlen, tlen, dlen, pflags;
  226         char *sptr;
  227         struct tcphdr *tc;
  228         int ftp_message_type;
  229 
  230         /* Calculate data length of TCP packet */
  231         tc = (struct tcphdr *)ip_next(pip);
  232         hlen = (pip->ip_hl + tc->th_off) << 2;
  233         tlen = ntohs(pip->ip_len);
  234         dlen = tlen - hlen;
  235 
  236         /* Place string pointer and beginning of data */
  237         sptr = (char *)pip;
  238         sptr += hlen;
  239 
  240         /*
  241          * Check that data length is not too long and previous message was
  242          * properly terminated with CRLF.
  243          */
  244         pflags = GetProtocolFlags(lnk);
  245         if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) {
  246                 ftp_message_type = FTP_UNKNOWN_MESSAGE;
  247 
  248                 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) {
  249                         /* When aliasing a client, check for the PORT/EPRT command. */
  250                         if (ParseFtpPortCommand(la, sptr, dlen))
  251                                 ftp_message_type = FTP_PORT_COMMAND;
  252                         else if (ParseFtpEprtCommand(la, sptr, dlen))
  253                                 ftp_message_type = FTP_EPRT_COMMAND;
  254                 } else {
  255                         /* When aliasing a server, check for the 227/229 reply. */
  256                         if (ParseFtp227Reply(la, sptr, dlen))
  257                                 ftp_message_type = FTP_227_REPLY;
  258                         else if (ParseFtp229Reply(la, sptr, dlen)) {
  259                                 ftp_message_type = FTP_229_REPLY;
  260                                 la->true_addr.s_addr = pip->ip_src.s_addr;
  261                         }
  262                 }
  263 
  264                 if (ftp_message_type != FTP_UNKNOWN_MESSAGE)
  265                         NewFtpMessage(la, pip, lnk, maxpacketsize, ftp_message_type);
  266         }
  267 
  268         /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
  269         if (dlen) {                     /* only if there's data */
  270                 sptr = (char *)pip;     /* start over at beginning */
  271                 tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may have grown */
  272                 if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
  273                         pflags &= ~WAIT_CRLF;
  274                 else
  275                         pflags |= WAIT_CRLF;
  276                 SetProtocolFlags(lnk, pflags);
  277         }
  278 }
  279 
  280 static void
  281 AliasHandleFtpIn(struct libalias *la,
  282     struct ip *pip,             /* IP packet to examine/patch */
  283     struct alias_link *lnk)     /* The link to go through (aliased port) */
  284 {
  285         int hlen, tlen, dlen, pflags;
  286         char *sptr;
  287         struct tcphdr *tc;
  288 
  289         /* Calculate data length of TCP packet */
  290         tc = (struct tcphdr *)ip_next(pip);
  291         hlen = (pip->ip_hl + tc->th_off) << 2;
  292         tlen = ntohs(pip->ip_len);
  293         dlen = tlen - hlen;
  294 
  295         /* Place string pointer and beginning of data */
  296         sptr = (char *)pip;
  297         sptr += hlen;
  298 
  299         /*
  300          * Check that data length is not too long and previous message was
  301          * properly terminated with CRLF.
  302          */
  303         pflags = GetProtocolFlags(lnk);
  304         if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0 &&
  305             ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER &&
  306             (ParseFtpPortCommand(la, sptr, dlen) != 0 ||
  307                 ParseFtpEprtCommand(la, sptr, dlen) != 0)) {
  308                 /*
  309                  * Alias active mode client requesting data from server
  310                  * behind NAT.  We need to alias server->client connection
  311                  * to external address client is connecting to.
  312                  */
  313                 AddLink(la, GetOriginalAddress(lnk), la->true_addr,
  314                     GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1),
  315                     htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP);
  316         }
  317         /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
  318         if (dlen) {
  319                 sptr = (char *)pip;             /* start over at beginning */
  320                 tlen = ntohs(pip->ip_len);      /* recalc tlen, pkt may
  321                                                  * have grown. */
  322                 if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
  323                         pflags &= ~WAIT_CRLF;
  324                 else
  325                         pflags |= WAIT_CRLF;
  326                 SetProtocolFlags(lnk, pflags);
  327        }
  328 }
  329 
  330 static int
  331 ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
  332 {
  333         char ch;
  334         int i, state;
  335         u_int32_t addr;
  336         u_short port;
  337         u_int8_t octet;
  338 
  339         /* Format: "PORT A,D,D,R,PO,RT". */
  340 
  341         /* Return if data length is too short. */
  342         if (dlen < 18)
  343                 return (0);
  344 
  345         if (strncasecmp("PORT ", sptr, 5))
  346                 return (0);
  347 
  348         addr = port = octet = 0;
  349         state = 0;
  350         for (i = 5; i < dlen; i++) {
  351                 ch = sptr[i];
  352                 switch (state) {
  353                 case 0:
  354                         if (isspace(ch))
  355                                 break;
  356                         else
  357                                 state++;
  358                 case 1:
  359                 case 3:
  360                 case 5:
  361                 case 7:
  362                 case 9:
  363                 case 11:
  364                         if (isdigit(ch)) {
  365                                 octet = ch - '';
  366                                 state++;
  367                         } else
  368                                 return (0);
  369                         break;
  370                 case 2:
  371                 case 4:
  372                 case 6:
  373                 case 8:
  374                         if (isdigit(ch))
  375                                 octet = 10 * octet + ch - '';
  376                         else if (ch == ',') {
  377                                 addr = (addr << 8) + octet;
  378                                 state++;
  379                         } else
  380                                 return (0);
  381                         break;
  382                 case 10:
  383                 case 12:
  384                         if (isdigit(ch))
  385                                 octet = 10 * octet + ch - '';
  386                         else if (ch == ',' || state == 12) {
  387                                 port = (port << 8) + octet;
  388                                 state++;
  389                         } else
  390                                 return (0);
  391                         break;
  392                 }
  393         }
  394 
  395         if (state == 13) {
  396                 la->true_addr.s_addr = htonl(addr);
  397                 la->true_port = port;
  398                 return (1);
  399         } else
  400                 return (0);
  401 }
  402 
  403 static int
  404 ParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen)
  405 {
  406         char ch, delim;
  407         int i, state;
  408         u_int32_t addr;
  409         u_short port;
  410         u_int8_t octet;
  411 
  412         /* Format: "EPRT |1|A.D.D.R|PORT|". */
  413 
  414         /* Return if data length is too short. */
  415         if (dlen < 18)
  416                 return (0);
  417 
  418         if (strncasecmp("EPRT ", sptr, 5))
  419                 return (0);
  420 
  421         addr = port = octet = 0;
  422         delim = '|';            /* XXX gcc -Wuninitialized */
  423         state = 0;
  424         for (i = 5; i < dlen; i++) {
  425                 ch = sptr[i];
  426                 switch (state) {
  427                 case 0:
  428                         if (!isspace(ch)) {
  429                                 delim = ch;
  430                                 state++;
  431                         }
  432                         break;
  433                 case 1:
  434                         if (ch == '1')  /* IPv4 address */
  435                                 state++;
  436                         else
  437                                 return (0);
  438                         break;
  439                 case 2:
  440                         if (ch == delim)
  441                                 state++;
  442                         else
  443                                 return (0);
  444                         break;
  445                 case 3:
  446                 case 5:
  447                 case 7:
  448                 case 9:
  449                         if (isdigit(ch)) {
  450                                 octet = ch - '';
  451                                 state++;
  452                         } else
  453                                 return (0);
  454                         break;
  455                 case 4:
  456                 case 6:
  457                 case 8:
  458                 case 10:
  459                         if (isdigit(ch))
  460                                 octet = 10 * octet + ch - '';
  461                         else if (ch == '.' || state == 10) {
  462                                 addr = (addr << 8) + octet;
  463                                 state++;
  464                         } else
  465                                 return (0);
  466                         break;
  467                 case 11:
  468                         if (isdigit(ch)) {
  469                                 port = ch - '';
  470                                 state++;
  471                         } else
  472                                 return (0);
  473                         break;
  474                 case 12:
  475                         if (isdigit(ch))
  476                                 port = 10 * port + ch - '';
  477                         else if (ch == delim)
  478                                 state++;
  479                         else
  480                                 return (0);
  481                         break;
  482                 }
  483         }
  484 
  485         if (state == 13) {
  486                 la->true_addr.s_addr = htonl(addr);
  487                 la->true_port = port;
  488                 return (1);
  489         } else
  490                 return (0);
  491 }
  492 
  493 static int
  494 ParseFtp227Reply(struct libalias *la, char *sptr, int dlen)
  495 {
  496         char ch;
  497         int i, state;
  498         u_int32_t addr;
  499         u_short port;
  500         u_int8_t octet;
  501 
  502         /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */
  503 
  504         /* Return if data length is too short. */
  505         if (dlen < 17)
  506                 return (0);
  507 
  508         if (strncmp("227 ", sptr, 4))
  509                 return (0);
  510 
  511         addr = port = octet = 0;
  512 
  513         state = 0;
  514         for (i = 4; i < dlen; i++) {
  515                 ch = sptr[i];
  516                 switch (state) {
  517                 case 0:
  518                         if (ch == '(')
  519                                 state++;
  520                         break;
  521                 case 1:
  522                 case 3:
  523                 case 5:
  524                 case 7:
  525                 case 9:
  526                 case 11:
  527                         if (isdigit(ch)) {
  528                                 octet = ch - '';
  529                                 state++;
  530                         } else
  531                                 return (0);
  532                         break;
  533                 case 2:
  534                 case 4:
  535                 case 6:
  536                 case 8:
  537                         if (isdigit(ch))
  538                                 octet = 10 * octet + ch - '';
  539                         else if (ch == ',') {
  540                                 addr = (addr << 8) + octet;
  541                                 state++;
  542                         } else
  543                                 return (0);
  544                         break;
  545                 case 10:
  546                 case 12:
  547                         if (isdigit(ch))
  548                                 octet = 10 * octet + ch - '';
  549                         else if (ch == ',' || (state == 12 && ch == ')')) {
  550                                 port = (port << 8) + octet;
  551                                 state++;
  552                         } else
  553                                 return (0);
  554                         break;
  555                 }
  556         }
  557 
  558         if (state == 13) {
  559                 la->true_port = port;
  560                 la->true_addr.s_addr = htonl(addr);
  561                 return (1);
  562         } else
  563                 return (0);
  564 }
  565 
  566 static int
  567 ParseFtp229Reply(struct libalias *la, char *sptr, int dlen)
  568 {
  569         char ch, delim;
  570         int i, state;
  571         u_short port;
  572 
  573         /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */
  574 
  575         /* Return if data length is too short. */
  576         if (dlen < 11)
  577                 return (0);
  578 
  579         if (strncmp("229 ", sptr, 4))
  580                 return (0);
  581 
  582         port = 0;
  583         delim = '|';            /* XXX gcc -Wuninitialized */
  584 
  585         state = 0;
  586         for (i = 4; i < dlen; i++) {
  587                 ch = sptr[i];
  588                 switch (state) {
  589                 case 0:
  590                         if (ch == '(')
  591                                 state++;
  592                         break;
  593                 case 1:
  594                         delim = ch;
  595                         state++;
  596                         break;
  597                 case 2:
  598                 case 3:
  599                         if (ch == delim)
  600                                 state++;
  601                         else
  602                                 return (0);
  603                         break;
  604                 case 4:
  605                         if (isdigit(ch)) {
  606                                 port = ch - '';
  607                                 state++;
  608                         } else
  609                                 return (0);
  610                         break;
  611                 case 5:
  612                         if (isdigit(ch))
  613                                 port = 10 * port + ch - '';
  614                         else if (ch == delim)
  615                                 state++;
  616                         else
  617                                 return (0);
  618                         break;
  619                 case 6:
  620                         if (ch == ')')
  621                                 state++;
  622                         else
  623                                 return (0);
  624                         break;
  625                 }
  626         }
  627 
  628         if (state == 7) {
  629                 la->true_port = port;
  630                 return (1);
  631         } else
  632                 return (0);
  633 }
  634 
  635 static void
  636 NewFtpMessage(struct libalias *la, struct ip *pip,
  637     struct alias_link *lnk,
  638     int maxpacketsize,
  639     int ftp_message_type)
  640 {
  641         struct alias_link *ftp_lnk;
  642 
  643         /* Security checks. */
  644         if (pip->ip_src.s_addr != la->true_addr.s_addr)
  645                 return;
  646 
  647         if (la->true_port < IPPORT_RESERVED)
  648                 return;
  649 
  650         /* Establish link to address and port found in FTP control message. */
  651         ftp_lnk = AddLink(la, la->true_addr, GetDestAddress(lnk),
  652             GetAliasAddress(lnk), htons(la->true_port), 0, GET_ALIAS_PORT,
  653             IPPROTO_TCP);
  654 
  655         if (ftp_lnk != NULL) {
  656                 int slen, hlen, tlen, dlen;
  657                 struct tcphdr *tc;
  658 
  659 #ifndef NO_FW_PUNCH
  660                 /* Punch hole in firewall */
  661                 PunchFWHole(ftp_lnk);
  662 #endif
  663 
  664                 /* Calculate data length of TCP packet */
  665                 tc = (struct tcphdr *)ip_next(pip);
  666                 hlen = (pip->ip_hl + tc->th_off) << 2;
  667                 tlen = ntohs(pip->ip_len);
  668                 dlen = tlen - hlen;
  669 
  670                 /* Create new FTP message. */
  671                 {
  672                         char stemp[MAX_MESSAGE_SIZE + 1];
  673                         char *sptr;
  674                         u_short alias_port;
  675                         u_char *ptr;
  676                         int a1, a2, a3, a4, p1, p2;
  677                         struct in_addr alias_address;
  678 
  679                         /* Decompose alias address into quad format */
  680                         alias_address = GetAliasAddress(lnk);
  681                         ptr = (u_char *)&alias_address.s_addr;
  682                         a1 = *ptr++;
  683                         a2 = *ptr++;
  684                         a3 = *ptr++;
  685                         a4 = *ptr;
  686 
  687                         alias_port = GetAliasPort(ftp_lnk);
  688 
  689                         /* Prepare new command */
  690                         switch (ftp_message_type) {
  691                         case FTP_PORT_COMMAND:
  692                         case FTP_227_REPLY:
  693                                 /* Decompose alias port into pair format. */
  694                                 ptr = (char *)&alias_port;
  695                                 p1 = *ptr++;
  696                                 p2 = *ptr;
  697 
  698                                 if (ftp_message_type == FTP_PORT_COMMAND) {
  699                                         /* Generate PORT command string. */
  700                                         sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
  701                                             a1, a2, a3, a4, p1, p2);
  702                                 } else {
  703                                         /* Generate 227 reply string. */
  704                                         sprintf(stemp,
  705                                             "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
  706                                             a1, a2, a3, a4, p1, p2);
  707                                 }
  708                                 break;
  709                         case FTP_EPRT_COMMAND:
  710                                 /* Generate EPRT command string. */
  711                                 sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
  712                                     a1, a2, a3, a4, ntohs(alias_port));
  713                                 break;
  714                         case FTP_229_REPLY:
  715                                 /* Generate 229 reply string. */
  716                                 sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
  717                                     ntohs(alias_port));
  718                                 break;
  719                         }
  720 
  721                         /* Save string length for IP header modification */
  722                         slen = strlen(stemp);
  723 
  724                         /* Copy modified buffer into IP packet. */
  725                         sptr = (char *)pip;
  726                         sptr += hlen;
  727                         strncpy(sptr, stemp, maxpacketsize - hlen);
  728                 }
  729 
  730                 /* Save information regarding modified seq and ack numbers */
  731                 {
  732                         int delta;
  733 
  734                         SetAckModified(lnk);
  735                         tc = (struct tcphdr *)ip_next(pip);
  736                         delta = GetDeltaSeqOut(tc->th_seq, lnk);
  737                         AddSeq(lnk, delta + slen - dlen, pip->ip_hl,
  738                             pip->ip_len, tc->th_seq, tc->th_off);
  739                 }
  740 
  741                 /* Revise IP header */
  742                 {
  743                         u_short new_len;
  744 
  745                         new_len = htons(hlen +
  746                             MIN(slen, maxpacketsize - hlen));
  747                         DifferentialChecksum(&pip->ip_sum,
  748                             &new_len,
  749                             &pip->ip_len,
  750                             1);
  751                         pip->ip_len = new_len;
  752                 }
  753 
  754                 /* Compute TCP checksum for revised packet */
  755                 tc->th_sum = 0;
  756 #ifdef _KERNEL
  757                 tc->th_x2 = (TH_RES1 >> 8);
  758 #else
  759                 tc->th_sum = TcpChecksum(pip);
  760 #endif
  761         } else {
  762 #ifdef LIBALIAS_DEBUG
  763                 fprintf(stderr,
  764                     "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
  765 #endif
  766         }
  767 }

Cache object: 65bde58612a0db3d7c354a318798a343


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