#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include "alias_local.h"
static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int);
void
AliasHandleFtpOut(
struct ip *pip,
struct alias_link *link,
int maxpacketsize )
{
int hlen, tlen, dlen;
struct in_addr true_addr;
u_short true_port;
char *sptr;
struct tcphdr *tc;
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
hlen = (pip->ip_hl + tc->th_off) << 2;
tlen = ntohs(pip->ip_len);
dlen = tlen - hlen;
if (dlen<10 || dlen>80)
return;
sptr = (char *) pip;
sptr += hlen;
{
char ch, zero;
int i, state;
u_long a1, a2, a3, a4;
u_short p1, p2;
a1=0; a2=0; a3=0; a4=0; p1=0; p2=0;
zero = '0';
state=-4;
for (i=0; i<dlen; i++)
{
ch = sptr[i];
switch (state)
{
case -4: if (ch == 'P') state=-3; else return; break;
case -3: if (ch == 'O') state=-2; else return; break;
case -2: if (ch == 'R') state=-1; else return; break;
case -1: if (ch == 'T') state= 0; else return; break;
case 0 :
if (isdigit(ch)) {a1=ch-zero; state=1 ;} break;
case 1 :
if (isdigit(ch)) a1=10*a1+ch-zero; else state=2 ; break;
case 2 :
if (isdigit(ch)) {a2=ch-zero; state=3 ;} break;
case 3 :
if (isdigit(ch)) a2=10*a2+ch-zero; else state=4 ; break;
case 4 :
if (isdigit(ch)) {a3=ch-zero; state=5 ;} break;
case 5 :
if (isdigit(ch)) a3=10*a3+ch-zero; else state=6 ; break;
case 6 :
if (isdigit(ch)) {a4=ch-zero; state=7 ;} break;
case 7 :
if (isdigit(ch)) a4=10*a4+ch-zero; else state=8 ; break;
case 8 :
if (isdigit(ch)) {p1=ch-zero; state=9 ;} break;
case 9 :
if (isdigit(ch)) p1=10*p1+ch-zero; else state=10; break;
case 10:
if (isdigit(ch)) {p2=ch-zero; state=11;} break;
case 11:
if (isdigit(ch)) p2=10*p2+ch-zero; break;
}
}
if (state == 11)
{
true_port = htons((p1<<8) + p2);
true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize);
}
}
}
static void
NewFtpPortCommand(struct ip *pip,
struct alias_link *link,
struct in_addr true_addr,
u_short true_port,
int maxpacketsize)
{
struct alias_link *ftp_link;
ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
true_port, 0, IPPROTO_TCP);
if (ftp_link != NULL)
{
int slen, hlen, tlen, dlen;
struct tcphdr *tc;
#ifndef NO_FW_PUNCH
PunchFWHole(ftp_link);
#endif
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
hlen = (pip->ip_hl + tc->th_off) << 2;
tlen = ntohs(pip->ip_len);
dlen = tlen - hlen;
{
char stemp[80];
char *sptr;
u_short alias_port;
u_char *ptr;
int a1, a2, a3, a4, p1, p2;
struct in_addr alias_address;
alias_address = GetAliasAddress(link);
ptr = (u_char *) &alias_address.s_addr;
a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
alias_port = GetAliasPort(ftp_link);
ptr = (char *) &alias_port;
p1 = *ptr++; p2=*ptr;
sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
a1,a2,a3,a4,p1,p2);
slen = strlen(stemp);
sptr = (char *) pip; sptr += hlen;
strncpy(sptr, stemp, maxpacketsize-hlen);
}
{
int delta;
SetAckModified(link);
delta = GetDeltaSeqOut(pip, link);
AddSeq(pip, link, delta+slen-dlen);
}
{
u_short new_len;
new_len = htons(hlen + slen);
DifferentialChecksum(&pip->ip_sum,
&new_len,
&pip->ip_len,
1);
pip->ip_len = new_len;
}
tc->th_sum = 0;
tc->th_sum = TcpChecksum(pip);
}
else
{
#ifdef DEBUG
fprintf(stderr,
"PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
#endif
}
}