#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <stdio.h>
#include "alias_local.h"
#include "alias.h"
#define NETBIOS_NS_PORT_NUMBER 137
#define NETBIOS_DGM_PORT_NUMBER 138
#define FTP_CONTROL_PORT_NUMBER 21
#define IRC_CONTROL_PORT_NUMBER_1 6667
#define IRC_CONTROL_PORT_NUMBER_2 6668
#define CUSEEME_PORT_NUMBER 7648
#define RTSP_CONTROL_PORT_NUMBER_1 554
#define RTSP_CONTROL_PORT_NUMBER_2 7070
#define PPTP_CONTROL_PORT_NUMBER 1723
static void TcpMonitorIn(struct ip *, struct alias_link *);
static void TcpMonitorOut(struct ip *, struct alias_link *);
static u_short packetAliasMSS;
void PacketAliasClampMSS(u_short mss)
{
packetAliasMSS = mss;
}
static void DoMSSClamp(struct tcphdr *tc)
{
u_char *option = (u_char *) tc + sizeof(*tc);
u_char *optionEnd = option + ((tc->th_off << 2) - sizeof(*tc));
while (optionEnd > option)
{
switch (option[0])
{
case TCPOPT_EOL:
option = optionEnd;
break;
case TCPOPT_NOP:
++option;
break;
case TCPOPT_MAXSEG:
if (option[1] == 4)
{
u_short *mssPtr = (u_short *) option + 1;
u_short mssVal = ntohs(*mssPtr);
if (packetAliasMSS < mssVal)
{
int accumulate = mssVal;
accumulate -= packetAliasMSS;
*mssPtr = htons(packetAliasMSS);
ADJUST_CHECKSUM(accumulate, tc->th_sum);
}
option = optionEnd;
}
break;
default:
option += option[1];
break;
}
}
}
static void
TcpMonitorIn(struct ip *pip, struct alias_link *link)
{
struct tcphdr *tc;
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
switch (GetStateIn(link))
{
case ALIAS_TCP_STATE_NOT_CONNECTED:
if (tc->th_flags & TH_RST)
SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
else if (tc->th_flags & TH_SYN)
{
SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
if (packetAliasMSS)
DoMSSClamp(tc);
}
break;
case ALIAS_TCP_STATE_CONNECTED:
if (tc->th_flags & (TH_FIN | TH_RST))
SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
break;
}
}
static void
TcpMonitorOut(struct ip *pip, struct alias_link *link)
{
struct tcphdr *tc;
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
switch (GetStateOut(link))
{
case ALIAS_TCP_STATE_NOT_CONNECTED:
if (tc->th_flags & TH_RST)
SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
else if (tc->th_flags & TH_SYN)
{
SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
if (packetAliasMSS)
DoMSSClamp(tc);
}
break;
case ALIAS_TCP_STATE_CONNECTED:
if (tc->th_flags & (TH_FIN | TH_RST))
SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
break;
}
}
static int IcmpAliasIn1(struct ip *);
static int IcmpAliasIn2(struct ip *);
static int IcmpAliasIn (struct ip *);
static int IcmpAliasOut1(struct ip *);
static int IcmpAliasOut2(struct ip *);
static int IcmpAliasOut (struct ip *);
static int ProtoAliasIn(struct ip *);
static int ProtoAliasOut(struct ip *);
static int UdpAliasOut(struct ip *);
static int UdpAliasIn (struct ip *);
static int TcpAliasOut(struct ip *, int);
static int TcpAliasIn (struct ip *);
static int
IcmpAliasIn1(struct ip *pip)
{
struct alias_link *link;
struct icmp *ic;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
if (link != NULL)
{
u_short original_id;
int accumulate;
original_id = GetOriginalPort(link);
accumulate = ic->icmp_id;
accumulate -= original_id;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
ic->icmp_id = original_id;
{
struct in_addr original_address;
original_address = GetOriginalAddress(link);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
}
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
IcmpAliasIn2(struct ip *pip)
{
struct ip *ip;
struct icmp *ic, *ic2;
struct udphdr *ud;
struct tcphdr *tc;
struct alias_link *link;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
ip = &ic->icmp_ip;
ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
tc = (struct tcphdr *) ud;
ic2 = (struct icmp *) ud;
if (ip->ip_p == IPPROTO_UDP)
link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
ud->uh_dport, ud->uh_sport,
IPPROTO_UDP, 0);
else if (ip->ip_p == IPPROTO_TCP)
link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
tc->th_dport, tc->th_sport,
IPPROTO_TCP, 0);
else if (ip->ip_p == IPPROTO_ICMP) {
if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
else
link = NULL;
} else
link = NULL;
if (link != NULL)
{
if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
{
u_short *sptr;
int accumulate;
struct in_addr original_address;
u_short original_port;
original_address = GetOriginalAddress(link);
original_port = GetOriginalPort(link);
sptr = (u_short *) &(ip->ip_src);
accumulate = *sptr++;
accumulate += *sptr;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
accumulate += ud->uh_sport;
accumulate -= original_port;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
ip->ip_src = original_address;
ud->uh_sport = original_port;
}
else if (ip->ip_p == IPPROTO_ICMP)
{
u_short *sptr;
int accumulate;
struct in_addr original_address;
u_short original_id;
original_address = GetOriginalAddress(link);
original_id = GetOriginalPort(link);
sptr = (u_short *) &(ip->ip_src);
accumulate = *sptr++;
accumulate += *sptr;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
accumulate += ic2->icmp_id;
accumulate -= original_id;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
ip->ip_src = original_address;
ic2->icmp_id = original_id;
}
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
IcmpAliasIn(struct ip *pip)
{
int iresult;
struct icmp *ic;
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
return PKT_ALIAS_OK;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
iresult = PKT_ALIAS_IGNORED;
switch (ic->icmp_type)
{
case ICMP_ECHOREPLY:
case ICMP_TSTAMPREPLY:
if (ic->icmp_code == 0)
{
iresult = IcmpAliasIn1(pip);
}
break;
case ICMP_UNREACH:
case ICMP_SOURCEQUENCH:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
iresult = IcmpAliasIn2(pip);
break;
case ICMP_ECHO:
case ICMP_TSTAMP:
iresult = IcmpAliasIn1(pip);
break;
}
return(iresult);
}
static int
IcmpAliasOut1(struct ip *pip)
{
struct alias_link *link;
struct icmp *ic;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
if (link != NULL)
{
u_short alias_id;
int accumulate;
alias_id = GetAliasPort(link);
accumulate = ic->icmp_id;
accumulate -= alias_id;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
ic->icmp_id = alias_id;
{
struct in_addr alias_address;
alias_address = GetAliasAddress(link);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &alias_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = alias_address;
}
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
IcmpAliasOut2(struct ip *pip)
{
struct ip *ip;
struct icmp *ic, *ic2;
struct udphdr *ud;
struct tcphdr *tc;
struct alias_link *link;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
ip = &ic->icmp_ip;
ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
tc = (struct tcphdr *) ud;
ic2 = (struct icmp *) ud;
if (ip->ip_p == IPPROTO_UDP)
link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
ud->uh_dport, ud->uh_sport,
IPPROTO_UDP, 0);
else if (ip->ip_p == IPPROTO_TCP)
link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
tc->th_dport, tc->th_sport,
IPPROTO_TCP, 0);
else if (ip->ip_p == IPPROTO_ICMP) {
if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
else
link = NULL;
} else
link = NULL;
if (link != NULL)
{
if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
{
u_short *sptr;
int accumulate;
struct in_addr alias_address;
u_short alias_port;
alias_address = GetAliasAddress(link);
alias_port = GetAliasPort(link);
sptr = (u_short *) &(ip->ip_dst);
accumulate = *sptr++;
accumulate += *sptr;
sptr = (u_short *) &alias_address;
accumulate -= *sptr++;
accumulate -= *sptr;
accumulate += ud->uh_dport;
accumulate -= alias_port;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
DifferentialChecksum(&pip->ip_sum,
(u_short *) &alias_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = alias_address;
}
ip->ip_dst = alias_address;
ud->uh_dport = alias_port;
}
else if (ip->ip_p == IPPROTO_ICMP)
{
u_short *sptr;
int accumulate;
struct in_addr alias_address;
u_short alias_id;
alias_address = GetAliasAddress(link);
alias_id = GetAliasPort(link);
sptr = (u_short *) &(ip->ip_dst);
accumulate = *sptr++;
accumulate += *sptr;
sptr = (u_short *) &alias_address;
accumulate -= *sptr++;
accumulate -= *sptr;
accumulate += ic2->icmp_id;
accumulate -= alias_id;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
DifferentialChecksum(&pip->ip_sum,
(u_short *) &alias_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = alias_address;
}
ip->ip_dst = alias_address;
ic2->icmp_id = alias_id;
}
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
IcmpAliasOut(struct ip *pip)
{
int iresult;
struct icmp *ic;
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
return PKT_ALIAS_OK;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
iresult = PKT_ALIAS_IGNORED;
switch (ic->icmp_type)
{
case ICMP_ECHO:
case ICMP_TSTAMP:
if (ic->icmp_code == 0)
{
iresult = IcmpAliasOut1(pip);
}
break;
case ICMP_UNREACH:
case ICMP_SOURCEQUENCH:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
iresult = IcmpAliasOut2(pip);
break;
case ICMP_ECHOREPLY:
case ICMP_TSTAMPREPLY:
iresult = IcmpAliasOut1(pip);
}
return(iresult);
}
static int
ProtoAliasIn(struct ip *pip)
{
struct alias_link *link;
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
return PKT_ALIAS_OK;
link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
if (link != NULL)
{
struct in_addr original_address;
original_address = GetOriginalAddress(link);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
ProtoAliasOut(struct ip *pip)
{
struct alias_link *link;
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
return PKT_ALIAS_OK;
link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
if (link != NULL)
{
struct in_addr alias_address;
alias_address = GetAliasAddress(link);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &alias_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = alias_address;
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
UdpAliasIn(struct ip *pip)
{
struct udphdr *ud;
struct alias_link *link;
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
return PKT_ALIAS_OK;
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
ud->uh_sport, ud->uh_dport,
IPPROTO_UDP, 1);
if (link != NULL)
{
struct in_addr alias_address;
struct in_addr original_address;
u_short alias_port;
int accumulate;
u_short *sptr;
int r = 0;
alias_address = GetAliasAddress(link);
original_address = GetOriginalAddress(link);
alias_port = ud->uh_dport;
ud->uh_dport = GetOriginalPort(link);
if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
AliasHandleCUSeeMeIn(pip, original_address);
else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
|| ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
|| ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
&original_address, &ud->uh_dport);
if (ud->uh_sum != 0)
{
accumulate = alias_port;
accumulate -= ud->uh_dport;
sptr = (u_short *) &alias_address;
accumulate += *sptr++;
accumulate += *sptr;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
ADJUST_CHECKSUM(accumulate, ud->uh_sum);
}
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
if (r < 0)
return(PKT_ALIAS_IGNORED);
else
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
UdpAliasOut(struct ip *pip)
{
struct udphdr *ud;
struct alias_link *link;
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
return PKT_ALIAS_OK;
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
ud->uh_sport, ud->uh_dport,
IPPROTO_UDP, 1);
if (link != NULL)
{
u_short alias_port;
struct in_addr alias_address;
alias_address = GetAliasAddress(link);
alias_port = GetAliasPort(link);
if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
AliasHandleCUSeeMeOut(pip, link);
else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
|| ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
|| ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
&alias_address, &alias_port);
if (ud->uh_sum != 0)
{
int accumulate;
u_short *sptr;
accumulate = ud->uh_sport;
accumulate -= alias_port;
sptr = (u_short *) &(pip->ip_src);
accumulate += *sptr++;
accumulate += *sptr;
sptr = (u_short *) &alias_address;
accumulate -= *sptr++;
accumulate -= *sptr;
ADJUST_CHECKSUM(accumulate, ud->uh_sum);
}
ud->uh_sport = alias_port;
DifferentialChecksum(&pip->ip_sum,
(u_short *) &alias_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = alias_address;
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
TcpAliasIn(struct ip *pip)
{
struct tcphdr *tc;
struct alias_link *link;
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
tc->th_sport, tc->th_dport,
IPPROTO_TCP,
!(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
if (link != NULL)
{
struct in_addr alias_address;
struct in_addr original_address;
struct in_addr proxy_address;
u_short alias_port;
u_short proxy_port;
int accumulate;
u_short *sptr;
if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
|| ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
AliasHandlePptpIn(pip, link);
alias_address = GetAliasAddress(link);
original_address = GetOriginalAddress(link);
proxy_address = GetProxyAddress(link);
alias_port = tc->th_dport;
tc->th_dport = GetOriginalPort(link);
proxy_port = GetProxyPort(link);
accumulate = alias_port;
accumulate -= tc->th_dport;
sptr = (u_short *) &alias_address;
accumulate += *sptr++;
accumulate += *sptr;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
if (proxy_port != 0)
{
accumulate += tc->th_sport;
tc->th_sport = proxy_port;
accumulate -= tc->th_sport;
sptr = (u_short *) &pip->ip_src;
accumulate += *sptr++;
accumulate += *sptr;
sptr = (u_short *) &proxy_address;
accumulate -= *sptr++;
accumulate -= *sptr;
}
if (GetAckModified(link) == 1)
{
int delta;
delta = GetDeltaAckIn(pip, link);
if (delta != 0)
{
sptr = (u_short *) &tc->th_ack;
accumulate += *sptr++;
accumulate += *sptr;
tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
sptr = (u_short *) &tc->th_ack;
accumulate -= *sptr++;
accumulate -= *sptr;
}
}
ADJUST_CHECKSUM(accumulate, tc->th_sum);
sptr = (u_short *) &pip->ip_dst;
accumulate = *sptr++;
accumulate += *sptr;
pip->ip_dst = original_address;
sptr = (u_short *) &pip->ip_dst;
accumulate -= *sptr++;
accumulate -= *sptr;
if (proxy_address.s_addr != 0)
{
sptr = (u_short *) &pip->ip_src;
accumulate += *sptr++;
accumulate += *sptr;
pip->ip_src = proxy_address;
sptr = (u_short *) &pip->ip_src;
accumulate -= *sptr++;
accumulate -= *sptr;
}
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
TcpMonitorIn(pip, link);
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int
TcpAliasOut(struct ip *pip, int maxpacketsize)
{
int proxy_type;
u_short dest_port;
u_short proxy_server_port;
struct in_addr dest_address;
struct in_addr proxy_server_address;
struct tcphdr *tc;
struct alias_link *link;
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
return PKT_ALIAS_OK;
dest_port = tc->th_dport;
dest_address = pip->ip_dst;
if (proxy_type != 0)
{
int accumulate;
u_short *sptr;
accumulate = tc->th_dport;
tc->th_dport = proxy_server_port;
accumulate -= tc->th_dport;
sptr = (u_short *) &(pip->ip_dst);
accumulate += *sptr++;
accumulate += *sptr;
sptr = (u_short *) &proxy_server_address;
accumulate -= *sptr++;
accumulate -= *sptr;
ADJUST_CHECKSUM(accumulate, tc->th_sum);
sptr = (u_short *) &(pip->ip_dst);
accumulate = *sptr++;
accumulate += *sptr;
pip->ip_dst = proxy_server_address;
sptr = (u_short *) &(pip->ip_dst);
accumulate -= *sptr++;
accumulate -= *sptr;
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
}
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
tc->th_sport, tc->th_dport,
IPPROTO_TCP, 1);
if (link !=NULL)
{
u_short alias_port;
struct in_addr alias_address;
int accumulate;
u_short *sptr;
if (proxy_type != 0)
{
SetProxyPort(link, dest_port);
SetProxyAddress(link, dest_address);
ProxyModify(link, pip, maxpacketsize, proxy_type);
}
alias_port = GetAliasPort(link);
alias_address = GetAliasAddress(link);
TcpMonitorOut(pip, link);
if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
|| ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
AliasHandleFtpOut(pip, link, maxpacketsize);
else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
|| ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
AliasHandleIrcOut(pip, link, maxpacketsize);
else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
|| ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
|| ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
|| ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
AliasHandleRtspOut(pip, link, maxpacketsize);
else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
|| ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
AliasHandlePptpOut(pip, link);
accumulate = tc->th_sport;
tc->th_sport = alias_port;
accumulate -= tc->th_sport;
sptr = (u_short *) &(pip->ip_src);
accumulate += *sptr++;
accumulate += *sptr;
sptr = (u_short *) &alias_address;
accumulate -= *sptr++;
accumulate -= *sptr;
if (GetAckModified(link) == 1)
{
int delta;
delta = GetDeltaSeqOut(pip, link);
if (delta != 0)
{
sptr = (u_short *) &tc->th_seq;
accumulate += *sptr++;
accumulate += *sptr;
tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
sptr = (u_short *) &tc->th_seq;
accumulate -= *sptr++;
accumulate -= *sptr;
}
}
ADJUST_CHECKSUM(accumulate, tc->th_sum);
sptr = (u_short *) &(pip->ip_src);
accumulate = *sptr++;
accumulate += *sptr;
pip->ip_src = alias_address;
sptr = (u_short *) &(pip->ip_src);
accumulate -= *sptr++;
accumulate -= *sptr;
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
static int FragmentIn(struct ip *);
static int FragmentOut(struct ip *);
static int
FragmentIn(struct ip *pip)
{
struct alias_link *link;
link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
if (link != NULL)
{
struct in_addr original_address;
GetFragmentAddr(link, &original_address);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
}
static int
FragmentOut(struct ip *pip)
{
struct in_addr alias_address;
alias_address = FindAliasAddress(pip->ip_src);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &alias_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = alias_address;
return(PKT_ALIAS_OK);
}
int
PacketAliasSaveFragment(char *ptr)
{
int iresult;
struct alias_link *link;
struct ip *pip;
pip = (struct ip *) ptr;
link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
iresult = PKT_ALIAS_ERROR;
if (link != NULL)
{
SetFragmentPtr(link, ptr);
iresult = PKT_ALIAS_OK;
}
return(iresult);
}
char *
PacketAliasGetFragment(char *ptr)
{
struct alias_link *link;
char *fptr;
struct ip *pip;
pip = (struct ip *) ptr;
link = FindFragmentPtr(pip->ip_src, pip->ip_id);
if (link != NULL)
{
GetFragmentPtr(link, &fptr);
SetFragmentPtr(link, NULL);
SetExpire(link, 0);
return(fptr);
}
else
{
return(NULL);
}
}
void
PacketAliasFragmentIn(char *ptr,
char *ptr_fragment
)
{
struct ip *pip;
struct ip *fpip;
pip = (struct ip *) ptr;
fpip = (struct ip *) ptr_fragment;
DifferentialChecksum(&fpip->ip_sum,
(u_short *) &pip->ip_dst,
(u_short *) &fpip->ip_dst,
2);
fpip->ip_dst = pip->ip_dst;
}
int
PacketAliasIn(char *ptr, int maxpacketsize)
{
struct in_addr alias_addr;
struct ip *pip;
int iresult;
if (packetAliasMode & PKT_ALIAS_REVERSE) {
packetAliasMode &= ~PKT_ALIAS_REVERSE;
iresult = PacketAliasOut(ptr, maxpacketsize);
packetAliasMode |= PKT_ALIAS_REVERSE;
return iresult;
}
HouseKeeping();
ClearCheckNewLink();
pip = (struct ip *) ptr;
alias_addr = pip->ip_dst;
if (ntohs(pip->ip_len) > maxpacketsize
|| (pip->ip_hl<<2) > maxpacketsize)
return PKT_ALIAS_IGNORED;
iresult = PKT_ALIAS_IGNORED;
if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
{
switch (pip->ip_p)
{
case IPPROTO_ICMP:
iresult = IcmpAliasIn(pip);
break;
case IPPROTO_UDP:
iresult = UdpAliasIn(pip);
break;
case IPPROTO_TCP:
iresult = TcpAliasIn(pip);
break;
case IPPROTO_GRE:
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
AliasHandlePptpGreIn(pip) == 0)
iresult = PKT_ALIAS_OK;
else
iresult = ProtoAliasIn(pip);
break;
default:
iresult = ProtoAliasIn(pip);
break;
}
if (ntohs(pip->ip_off) & IP_MF)
{
struct alias_link *link;
link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
if (link != NULL)
{
iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
SetFragmentAddr(link, pip->ip_dst);
}
else
{
iresult = PKT_ALIAS_ERROR;
}
}
}
else
{
iresult = FragmentIn(pip);
}
return(iresult);
}
#define UNREG_ADDR_A_LOWER 0x0a000000
#define UNREG_ADDR_A_UPPER 0x0affffff
#define UNREG_ADDR_B_LOWER 0xac100000
#define UNREG_ADDR_B_UPPER 0xac1fffff
#define UNREG_ADDR_C_LOWER 0xc0a80000
#define UNREG_ADDR_C_UPPER 0xc0a8ffff
int
PacketAliasOut(char *ptr,
int maxpacketsize
)
{
int iresult;
struct in_addr addr_save;
struct ip *pip;
if (packetAliasMode & PKT_ALIAS_REVERSE) {
packetAliasMode &= ~PKT_ALIAS_REVERSE;
iresult = PacketAliasIn(ptr, maxpacketsize);
packetAliasMode |= PKT_ALIAS_REVERSE;
return iresult;
}
HouseKeeping();
ClearCheckNewLink();
pip = (struct ip *) ptr;
if (ntohs(pip->ip_len) > maxpacketsize
|| (pip->ip_hl<<2) > maxpacketsize)
return PKT_ALIAS_IGNORED;
addr_save = GetDefaultAliasAddress();
if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
{
u_long addr;
int iclass;
iclass = 0;
addr = ntohl(pip->ip_src.s_addr);
if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
iclass = 3;
else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
iclass = 2;
else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
iclass = 1;
if (iclass == 0)
{
SetDefaultAliasAddress(pip->ip_src);
}
}
iresult = PKT_ALIAS_IGNORED;
if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
{
switch (pip->ip_p)
{
case IPPROTO_ICMP:
iresult = IcmpAliasOut(pip);
break;
case IPPROTO_UDP:
iresult = UdpAliasOut(pip);
break;
case IPPROTO_TCP:
iresult = TcpAliasOut(pip, maxpacketsize);
break;
case IPPROTO_GRE:
if (AliasHandlePptpGreOut(pip) == 0)
iresult = PKT_ALIAS_OK;
else
iresult = ProtoAliasOut(pip);
break;
default:
iresult = ProtoAliasOut(pip);
break;
}
}
else
{
iresult = FragmentOut(pip);
}
SetDefaultAliasAddress(addr_save);
return(iresult);
}
int
PacketUnaliasOut(char *ptr,
int maxpacketsize
)
{
struct ip *pip;
struct icmp *ic;
struct udphdr *ud;
struct tcphdr *tc;
struct alias_link *link;
int iresult = PKT_ALIAS_IGNORED;
pip = (struct ip *) ptr;
if (ntohs(pip->ip_len) > maxpacketsize
|| (pip->ip_hl<<2) > maxpacketsize)
return(iresult);
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
tc = (struct tcphdr *) ud;
ic = (struct icmp *) ud;
if (pip->ip_p == IPPROTO_UDP)
link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
ud->uh_dport, ud->uh_sport,
IPPROTO_UDP, 0);
else if (pip->ip_p == IPPROTO_TCP)
link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
tc->th_dport, tc->th_sport,
IPPROTO_TCP, 0);
else if (pip->ip_p == IPPROTO_ICMP)
link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
else
link = NULL;
if (link != NULL)
{
if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
{
u_short *sptr;
int accumulate;
struct in_addr original_address;
u_short original_port;
original_address = GetOriginalAddress(link);
original_port = GetOriginalPort(link);
sptr = (u_short *) &(pip->ip_src);
accumulate = *sptr++;
accumulate += *sptr;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
if (pip->ip_p == IPPROTO_UDP) {
accumulate += ud->uh_sport;
accumulate -= original_port;
ADJUST_CHECKSUM(accumulate, ud->uh_sum);
} else {
accumulate += tc->th_sport;
accumulate -= original_port;
ADJUST_CHECKSUM(accumulate, tc->th_sum);
}
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = original_address;
if (pip->ip_p == IPPROTO_UDP)
ud->uh_sport = original_port;
else
tc->th_sport = original_port;
iresult = PKT_ALIAS_OK;
} else if (pip->ip_p == IPPROTO_ICMP) {
u_short *sptr;
int accumulate;
struct in_addr original_address;
u_short original_id;
original_address = GetOriginalAddress(link);
original_id = GetOriginalPort(link);
sptr = (u_short *) &(pip->ip_src);
accumulate = *sptr++;
accumulate += *sptr;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
accumulate += ic->icmp_id;
accumulate -= original_id;
ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
DifferentialChecksum(&pip->ip_sum,
(u_short *) &original_address,
(u_short *) &pip->ip_src,
2);
pip->ip_src = original_address;
ic->icmp_id = original_id;
iresult = PKT_ALIAS_OK;
}
}
return(iresult);
}