From owner-svn-src-all@FreeBSD.ORG Thu Jul 28 10:16:31 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 68ABB106564A; Thu, 28 Jul 2011 10:16:31 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1F5F88FC0C; Thu, 28 Jul 2011 10:16:31 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p6SAGVIU095838; Thu, 28 Jul 2011 10:16:31 GMT (envelope-from ae@svn.freebsd.org) Received: (from ae@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p6SAGUN3095833; Thu, 28 Jul 2011 10:16:30 GMT (envelope-from ae@svn.freebsd.org) Message-Id: <201107281016.p6SAGUN3095833@svn.freebsd.org> From: "Andrey V. Elsukov" Date: Thu, 28 Jul 2011 10:16:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r224474 - stable/8/sys/netinet/libalias X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Jul 2011 10:16:31 -0000 Author: ae Date: Thu Jul 28 10:16:30 2011 New Revision: 224474 URL: http://svn.freebsd.org/changeset/base/224474 Log: MFC r223437: Export AddLink() function from libalias. It can be used when custom alias address needs to be specified. Add inbound handler to the alias_ftp module. It helps handle active FTP transfer mode for the case with external clients and FTP server behind NAT. Fix passive FTP transfer case for server behind NAT using redirect with external IP address different from NAT ip address. PR: kern/157957 Submitted by: Alexander V. Chernikov Modified: stable/8/sys/netinet/libalias/alias_db.c stable/8/sys/netinet/libalias/alias_ftp.c stable/8/sys/netinet/libalias/alias_local.h stable/8/sys/netinet/libalias/libalias.3 Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/geom/label/ (props changed) Modified: stable/8/sys/netinet/libalias/alias_db.c ============================================================================== --- stable/8/sys/netinet/libalias/alias_db.c Thu Jul 28 10:10:39 2011 (r224473) +++ stable/8/sys/netinet/libalias/alias_db.c Thu Jul 28 10:16:30 2011 (r224474) @@ -552,10 +552,6 @@ static void IncrementalCleanup(struct li static void DeleteLink(struct alias_link *); static struct alias_link * -AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr, - u_short, u_short, int, int); - -static struct alias_link * ReLink(struct alias_link *, struct in_addr, struct in_addr, struct in_addr, u_short, u_short, int, int); @@ -572,9 +568,6 @@ static struct alias_link * #define ALIAS_PORT_MASK_EVEN 0x07ffe #define GET_NEW_PORT_MAX_ATTEMPTS 20 -#define GET_ALIAS_PORT -1 -#define GET_ALIAS_ID GET_ALIAS_PORT - #define FIND_EVEN_ALIAS_BASE 1 /* GetNewPort() allocates port numbers. Note that if a port number @@ -937,17 +930,12 @@ DeleteLink(struct alias_link *lnk) } -static struct alias_link * -AddLink(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - struct in_addr alias_addr, - u_short src_port, - u_short dst_port, - int alias_port_param, /* if less than zero, alias */ - int link_type) -{ /* port will be automatically *//* chosen. - * If greater than */ - u_int start_point; /* zero, equal to alias port */ +struct alias_link * +AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, + struct in_addr alias_addr, u_short src_port, u_short dst_port, + int alias_port_param, int link_type) +{ + u_int start_point; struct alias_link *lnk; LIBALIAS_LOCK_ASSERT(la); Modified: stable/8/sys/netinet/libalias/alias_ftp.c ============================================================================== --- stable/8/sys/netinet/libalias/alias_ftp.c Thu Jul 28 10:10:39 2011 (r224473) +++ stable/8/sys/netinet/libalias/alias_ftp.c Thu Jul 28 10:16:30 2011 (r224474) @@ -100,38 +100,68 @@ __FBSDID("$FreeBSD$"); #define FTP_CONTROL_PORT_NUMBER 21 static void -AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *, - int maxpacketsize); +AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *, + int maxpacketsize); +static void +AliasHandleFtpIn(struct libalias *, struct ip *, struct alias_link *); -static int -fingerprint(struct libalias *la, struct alias_data *ah) +static int +fingerprint_out(struct libalias *la, struct alias_data *ah) { - if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || - ah->maxpktsize == 0) + if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || + ah->maxpktsize == 0) return (-1); - if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER - || ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER) + if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER || + ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER) return (0); return (-1); } -static int -protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) +static int +fingerprint_in(struct libalias *la, struct alias_data *ah) +{ + + if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL) + return (-1); + if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER || + ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER) + return (0); + return (-1); +} + +static int +protohandler_out(struct libalias *la, struct ip *pip, struct alias_data *ah) { - + AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize); return (0); } + +static int +protohandler_in(struct libalias *la, struct ip *pip, struct alias_data *ah) +{ + + AliasHandleFtpIn(la, pip, ah->lnk); + return (0); +} + struct proto_handler handlers[] = { - { - .pri = 80, - .dir = OUT, - .proto = TCP, - .fingerprint = &fingerprint, - .protohandler = &protohandler - }, + { + .pri = 80, + .dir = OUT, + .proto = TCP, + .fingerprint = &fingerprint_out, + .protohandler = &protohandler_out + }, + { + .pri = 80, + .dir = IN, + .proto = TCP, + .fingerprint = &fingerprint_in, + .protohandler = &protohandler_in + }, { EOH } }; @@ -256,6 +286,57 @@ AliasHandleFtpOut( } } +static void +AliasHandleFtpIn(struct libalias *la, + struct ip *pip, /* IP packet to examine/patch */ + struct alias_link *lnk) /* The link to go through (aliased port) */ +{ + int hlen, tlen, dlen, pflags; + char *sptr; + struct tcphdr *tc; + + /* Calculate data length of TCP packet */ + tc = (struct tcphdr *)ip_next(pip); + hlen = (pip->ip_hl + tc->th_off) << 2; + tlen = ntohs(pip->ip_len); + dlen = tlen - hlen; + + /* Place string pointer and beginning of data */ + sptr = (char *)pip; + sptr += hlen; + + /* + * Check that data length is not too long and previous message was + * properly terminated with CRLF. + */ + pflags = GetProtocolFlags(lnk); + if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0 && + ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER && + (ParseFtpPortCommand(la, sptr, dlen) != 0 || + ParseFtpEprtCommand(la, sptr, dlen) != 0)) { + /* + * Alias active mode client requesting data from server + * behind NAT. We need to alias server->client connection + * to external address client is connecting to. + */ + AddLink(la, GetOriginalAddress(lnk), la->true_addr, + GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1), + htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP); + } + /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */ + if (dlen) { + sptr = (char *)pip; /* start over at beginning */ + tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may + * have grown. + */ + if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n') + pflags &= ~WAIT_CRLF; + else + pflags |= WAIT_CRLF; + SetProtocolFlags(lnk, pflags); + } +} + static int ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen) { @@ -576,9 +657,10 @@ NewFtpMessage(struct libalias *la, struc if (la->true_port < IPPORT_RESERVED) return; -/* Establish link to address and port found in FTP control message. */ - ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk), - htons(la->true_port), 0, IPPROTO_TCP, 1); + /* Establish link to address and port found in FTP control message. */ + ftp_lnk = AddLink(la, la->true_addr, GetDestAddress(lnk), + GetAliasAddress(lnk), htons(la->true_port), 0, GET_ALIAS_PORT, + IPPROTO_TCP); if (ftp_lnk != NULL) { int slen, hlen, tlen, dlen; Modified: stable/8/sys/netinet/libalias/alias_local.h ============================================================================== --- stable/8/sys/netinet/libalias/alias_local.h Thu Jul 28 10:10:39 2011 (r224473) +++ stable/8/sys/netinet/libalias/alias_local.h Thu Jul 28 10:16:30 2011 (r224474) @@ -67,6 +67,9 @@ #define LINK_TABLE_OUT_SIZE 4001 #define LINK_TABLE_IN_SIZE 4001 +#define GET_ALIAS_PORT -1 +#define GET_ALIAS_ID GET_ALIAS_PORT + struct proxy_entry; struct libalias { @@ -249,6 +252,10 @@ DifferentialChecksum(u_short * _cksum, v /* Internal data access */ struct alias_link * +AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, + struct in_addr alias_addr, u_short src_port, u_short dst_port, + int alias_param, int link_type); +struct alias_link * FindIcmpIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr, u_short _id_alias, int _create); struct alias_link * Modified: stable/8/sys/netinet/libalias/libalias.3 ============================================================================== --- stable/8/sys/netinet/libalias/libalias.3 Thu Jul 28 10:10:39 2011 (r224473) +++ stable/8/sys/netinet/libalias/libalias.3 Thu Jul 28 10:16:30 2011 (r224474) @@ -812,6 +812,17 @@ argument is the pointer to a header frag is the pointer to the packet to be de-aliased. .Ed .Sh MISCELLANEOUS FUNCTIONS +.Ft struct alias_link * +.Fn AddLink "struct libalias *" "struct in_addr src_addr" "struct in_addr dst_addr" \ +"struct in_addr alias_addr" "u_short src_port" "u_short dst_port" \ +"int alias_param" "int link_type" +.Bd -ragged -offset indent +This function adds new state to instance hash table. +Zero can be specified instead of dst_address and/or dst port. +This makes link partially specified dynamic. +However due to hashing method such links can be resolved on inbound (ext -> int) only. +.Ed +.Pp .Ft void .Fn LibAliasSetTarget "struct libalias *" "struct in_addr addr" .Bd -ragged -offset indent