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
This commit is contained in:
parent
72b7c8ddb1
commit
0511675327
@ -551,10 +551,6 @@ static void IncrementalCleanup(struct libalias *);
|
|||||||
|
|
||||||
static void DeleteLink(struct alias_link *);
|
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 *
|
static struct alias_link *
|
||||||
ReLink(struct alias_link *,
|
ReLink(struct alias_link *,
|
||||||
struct in_addr, struct in_addr, struct in_addr,
|
struct in_addr, struct in_addr, struct in_addr,
|
||||||
@ -572,9 +568,6 @@ static struct alias_link *
|
|||||||
#define ALIAS_PORT_MASK_EVEN 0x07ffe
|
#define ALIAS_PORT_MASK_EVEN 0x07ffe
|
||||||
#define GET_NEW_PORT_MAX_ATTEMPTS 20
|
#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
|
#define FIND_EVEN_ALIAS_BASE 1
|
||||||
|
|
||||||
/* GetNewPort() allocates port numbers. Note that if a port number
|
/* GetNewPort() allocates port numbers. Note that if a port number
|
||||||
@ -937,17 +930,12 @@ DeleteLink(struct alias_link *lnk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct alias_link *
|
struct alias_link *
|
||||||
AddLink(struct libalias *la, struct in_addr src_addr,
|
AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr,
|
||||||
struct in_addr dst_addr,
|
struct in_addr alias_addr, u_short src_port, u_short dst_port,
|
||||||
struct in_addr alias_addr,
|
int alias_port_param, int link_type)
|
||||||
u_short src_port,
|
{
|
||||||
u_short dst_port,
|
u_int start_point;
|
||||||
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 *lnk;
|
struct alias_link *lnk;
|
||||||
|
|
||||||
LIBALIAS_LOCK_ASSERT(la);
|
LIBALIAS_LOCK_ASSERT(la);
|
||||||
|
@ -100,38 +100,68 @@ __FBSDID("$FreeBSD$");
|
|||||||
#define FTP_CONTROL_PORT_NUMBER 21
|
#define FTP_CONTROL_PORT_NUMBER 21
|
||||||
|
|
||||||
static void
|
static void
|
||||||
AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
|
AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
|
||||||
int maxpacketsize);
|
int maxpacketsize);
|
||||||
|
static void
|
||||||
|
AliasHandleFtpIn(struct libalias *, struct ip *, struct alias_link *);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fingerprint(struct libalias *la, struct alias_data *ah)
|
fingerprint_out(struct libalias *la, struct alias_data *ah)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
|
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
|
||||||
ah->maxpktsize == 0)
|
ah->maxpktsize == 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER
|
if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
|
||||||
|| ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
|
ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
|
||||||
return (0);
|
return (0);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
|
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);
|
AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize);
|
||||||
return (0);
|
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[] = {
|
struct proto_handler handlers[] = {
|
||||||
{
|
{
|
||||||
.pri = 80,
|
.pri = 80,
|
||||||
.dir = OUT,
|
.dir = OUT,
|
||||||
.proto = TCP,
|
.proto = TCP,
|
||||||
.fingerprint = &fingerprint,
|
.fingerprint = &fingerprint_out,
|
||||||
.protohandler = &protohandler
|
.protohandler = &protohandler_out
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.pri = 80,
|
||||||
|
.dir = IN,
|
||||||
|
.proto = TCP,
|
||||||
|
.fingerprint = &fingerprint_in,
|
||||||
|
.protohandler = &protohandler_in
|
||||||
|
},
|
||||||
{ EOH }
|
{ 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
|
static int
|
||||||
ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
|
ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
|
||||||
{
|
{
|
||||||
@ -576,9 +657,10 @@ NewFtpMessage(struct libalias *la, struct ip *pip,
|
|||||||
if (la->true_port < IPPORT_RESERVED)
|
if (la->true_port < IPPORT_RESERVED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Establish link to address and port found in FTP control message. */
|
/* Establish link to address and port found in FTP control message. */
|
||||||
ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk),
|
ftp_lnk = AddLink(la, la->true_addr, GetDestAddress(lnk),
|
||||||
htons(la->true_port), 0, IPPROTO_TCP, 1);
|
GetAliasAddress(lnk), htons(la->true_port), 0, GET_ALIAS_PORT,
|
||||||
|
IPPROTO_TCP);
|
||||||
|
|
||||||
if (ftp_lnk != NULL) {
|
if (ftp_lnk != NULL) {
|
||||||
int slen, hlen, tlen, dlen;
|
int slen, hlen, tlen, dlen;
|
||||||
|
@ -67,6 +67,9 @@
|
|||||||
#define LINK_TABLE_OUT_SIZE 4001
|
#define LINK_TABLE_OUT_SIZE 4001
|
||||||
#define LINK_TABLE_IN_SIZE 4001
|
#define LINK_TABLE_IN_SIZE 4001
|
||||||
|
|
||||||
|
#define GET_ALIAS_PORT -1
|
||||||
|
#define GET_ALIAS_ID GET_ALIAS_PORT
|
||||||
|
|
||||||
struct proxy_entry;
|
struct proxy_entry;
|
||||||
|
|
||||||
struct libalias {
|
struct libalias {
|
||||||
@ -249,6 +252,10 @@ DifferentialChecksum(u_short * _cksum, void * _new, void * _old, int _n);
|
|||||||
|
|
||||||
/* Internal data access */
|
/* Internal data access */
|
||||||
struct alias_link *
|
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,
|
FindIcmpIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||||
u_short _id_alias, int _create);
|
u_short _id_alias, int _create);
|
||||||
struct alias_link *
|
struct alias_link *
|
||||||
|
@ -824,6 +824,17 @@ argument is the pointer to a header fragment used as a template, and
|
|||||||
is the pointer to the packet to be de-aliased.
|
is the pointer to the packet to be de-aliased.
|
||||||
.Ed
|
.Ed
|
||||||
.Sh MISCELLANEOUS FUNCTIONS
|
.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
|
.Ft void
|
||||||
.Fn LibAliasSetTarget "struct libalias *" "struct in_addr addr"
|
.Fn LibAliasSetTarget "struct libalias *" "struct in_addr addr"
|
||||||
.Bd -ragged -offset indent
|
.Bd -ragged -offset indent
|
||||||
|
Loading…
x
Reference in New Issue
Block a user