Create the alias library. This is currently only used by

ppp (or will be shortly).  Natd can now be updated to use
this library rather than carrying its own version of the code.

Submitted by:	Charles Mott <cmott@srv.net>
This commit is contained in:
Brian Somers 1997-05-23 04:41:31 +00:00
parent 3f72ab23cd
commit 3b160b8b6e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/CMOTT/; revision=26026
16 changed files with 7968 additions and 0 deletions

11
lib/libalias/Makefile Normal file
View File

@ -0,0 +1,11 @@
LIB= alias
SHLIB_MAJOR= 2
SHLIB_MINOR= 1
CFLAGS+=-Wall -I${.CURDIR}
SRCS= alias.c alias_db.c alias_ftp.c alias_irc.c alias_util.c
beforeinstall:
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/alias.h \
${DESTDIR}/usr/include
.include <bsd.lib.mk>

1142
lib/libalias/alias.c Normal file

File diff suppressed because it is too large Load Diff

102
lib/libalias/alias.h Normal file
View File

@ -0,0 +1,102 @@
/*lint -save -library Flexelint comment for external headers */
/*
Alias.h defines the outside world interfaces for the packet
aliasing software.
This software is placed into the public domain with no restrictions
on its distribution.
*/
#ifndef _ALIAS_H_
#define _ALIAS_H_
/* Alias link representativei (incomplete struct) */
struct alias_link;
/* External interfaces (API) to packet aliasing engine */
extern int SaveFragmentPtr(char *);
extern char *GetNextFragmentPtr(char *);
extern void FragmentAliasIn(char *, char *);
extern int PacketAliasIn(char *, int maxpacketsize);
extern int PacketAliasOut(char *, int maxpacketsize);
extern int PacketAliasIn2(char *, struct in_addr, int maxpacketsize);
extern int PacketAliasOut2(char *, struct in_addr, int maxpacketsize);
extern void SetPacketAliasAddress(struct in_addr);
extern void InitPacketAlias(void);
extern void InitPacketAliasLog(void);
extern void UninitPacketAliasLog(void);
extern unsigned int SetPacketAliasMode(unsigned int, unsigned int);
extern struct alias_link *
PacketAliasRedirectPort(struct in_addr, u_short,
struct in_addr, u_short,
struct in_addr, u_short,
u_char);
extern int
PacketAliasPermanentLink(struct in_addr, u_short,
struct in_addr, u_short,
u_short, u_char);
extern struct alias_link *
PacketAliasRedirectAddr(struct in_addr,
struct in_addr);
void PacketAliasRedirectDelete(struct alias_link *);
/* InternetChecksum() is not specifically part of the
packet aliasing API, but is sometimes needed outside
the module. (~for instance, natd uses it to create
an ICMP error message when interface size is
exceeded.) */
extern u_short InternetChecksum(u_short *, int);
/********************** Mode flags ********************/
/* Set these flags using SetPacketAliasMode() */
/* If PKT_ALIAS_LOG is set, a message will be printed to
/var/log/alias.log every time a link is created or deleted. This
is useful for debugging */
#define PKT_ALIAS_LOG 1
/* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g.
to ftp, telnet or web servers will be prevented by the aliasing
mechanism. */
#define PKT_ALIAS_DENY_INCOMING 2
/* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from
the same port as they originated on. This allow eg rsh to work
*99% of the time*, but _not_ 100%. (It will be slightly flakey
instead of not working at all.) */
#define PKT_ALIAS_SAME_PORTS 4
/* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified
links (e.g. destination port and/or address is zero), the packet
aliasing engine will attempt to allocate a socket for the aliasing
port it chooses. This will avoid interference with the host
machine. Fully specified links do not require this. */
#define PKT_ALIAS_USE_SOCKETS 8
/* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with with
unregistered source addresses will be aliased (along with those
of the ppp host maching itself. Private addresses are those
in the following ranges:
10.0.0.0 -> 10.255.255.255
172.16.0.0 -> 172.31.255.255
192.168.0.0 -> 192.168.255.255 */
#define PKT_ALIAS_UNREGISTERED_ONLY 16
/* Return Codes */
#define PKT_ALIAS_ERROR -1
#define PKT_ALIAS_OK 1
#define PKT_ALIAS_IGNORED 2
#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
#define PKT_ALIAS_NEW_LINK 5
#endif
/*lint -restore */

1972
lib/libalias/alias_db.c Normal file

File diff suppressed because it is too large Load Diff

220
lib/libalias/alias_ftp.c Normal file
View File

@ -0,0 +1,220 @@
/*
Alias_ftp.c performs special processing for FTP sessions under
TCP. Specifically, when a PORT command from the client side
is sent, it is intercepted and modified. The address is changed
to the gateway machine and an aliasing port is used.
For this routine to work, the PORT command must fit entirely
into a single TCP packet. This is typically the case, but exceptions
can easily be envisioned under the actual specifications.
Probably the most troubling aspect of the approach taken here is
that the new PORT command will typically be a different length, and
this causes a certain amount of bookkeeping to keep track of the
changes of sequence and acknowledgment numbers, since the client
machine is totally unaware of the modification to the TCP stream.
This software is placed into the public domain with no restrictions
on its distribution.
Initial version: August, 1996 (cjm)
Version 1.6
Brian Somers and Martin Renters identified an IP checksum
error for modified IP packets.
Version 1.7: January 9, 1996 (cjm)
Differental checksum computation for change
in IP packet length.
Version 2.1: May, 1997 (cjm)
Very minor changes to conform with
local/global/function naming conventions
withing the packet alising module.
*/
/* Includes */
#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, /* IP packet to examine/patch */
struct alias_link *link, /* The link to go through (aliased port) */
int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
{
int hlen, tlen, dlen;
struct in_addr true_addr;
u_short true_port;
char *sptr;
struct tcphdr *tc;
/* Calculate data length of TCP packet */
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;
/* Return is data length is too long or too short */
if (dlen<10 || dlen>80)
return;
/* Place string pointer and beginning of data */
sptr = (char *) pip;
sptr += hlen;
/* Parse through string using state diagram method */
{
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;
/* Establish link to address and port found in PORT command */
ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
true_port, 0, IPPROTO_TCP);
if (ftp_link != NULL)
{
int slen, hlen, tlen, dlen;
struct tcphdr *tc;
/* Calculate data length of TCP packet */
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;
/* Create new PORT command */
{
char stemp[80];
char *sptr;
u_short alias_port;
u_char *ptr;
int a1, a2, a3, a4, p1, p2;
struct in_addr alias_address;
/* Decompose alias address into quad format */
alias_address = GetAliasAddress(link);
ptr = (char *) &alias_address;
a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
/* Decompose alias port into pair format */
alias_port = GetAliasPort(ftp_link);
ptr = (char *) &alias_port;
p1 = *ptr++; p2=*ptr;
/* Generate command string */
sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
a1,a2,a3,a4,p1,p2);
/* Save string length for IP header modification */
slen = strlen(stemp);
/* Copy into IP packet */
sptr = (char *) pip; sptr += hlen;
strncpy(sptr, stemp, maxpacketsize-hlen);
}
/* Save information regarding modified seq and ack numbers */
{
int delta;
SetAckModified(link);
delta = GetDeltaSeqOut(pip, link);
AddSeq(pip, link, delta+slen-dlen);
}
/* Revise IP header */
{
u_short new_len;
new_len = htons(hlen + slen);
DifferentialChecksum(&pip->ip_sum,
&new_len,
&pip->ip_len,
1);
pip->ip_len = new_len;
}
/* Compute TCP checksum for revised packet */
tc->th_sum = 0;
tc->th_sum = TcpChecksum(pip);
}
else
{
fprintf(stderr,
"PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
}
}

311
lib/libalias/alias_irc.c Normal file
View File

@ -0,0 +1,311 @@
/* Alias_irc.c intercepts packages contain IRC CTCP commands, and
changes DCC commands to export a port on the aliasing host instead
of an aliased host.
For this routine to work, the DCC command must fit entirely into a
single TCP packet. This will usually happen, but is not
guaranteed.
The interception is likely to change the length of the packet.
The handling of this is copied more-or-less verbatim from
ftp_alias.c
This software is placed into the public domain with no restrictions
on its distribution.
Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
Version 2.1: May, 1997 (cjm)
Very minor changes to conform with
local/global/function naming conventions
withing the packet alising module.
*/
/* Includes */
#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 <limits.h>
#include "alias_local.h"
/* Local defines */
#define DBprintf(a)
void
AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */
struct alias_link *link, /* Which link are we on? */
int maxsize /* Maximum size of IP packet including headers */
)
{
int hlen, tlen, dlen;
struct in_addr true_addr;
u_short true_port;
char *sptr;
struct tcphdr *tc;
int i; /* Iterator through the source */
/* Calculate data length of TCP packet */
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;
/* Return if data length is too short - assume an entire PRIVMSG in each packet. */
if (dlen<sizeof(":A!a@n.n PRIVMSG A :aDCC 1 1a")-1)
return;
/* Place string pointer at beginning of data */
sptr = (char *) pip;
sptr += hlen;
maxsize -= hlen; /* We're interested in maximum size of data, not packet */
/* Search for a CTCP command [Note 1] */
for( i=0; i<dlen; i++ ) {
if(sptr[i]=='\001')
goto lFOUND_CTCP;
}
return; /* No CTCP commands in */
/* Handle CTCP commands - the buffer may have to be copied */
lFOUND_CTCP:
{
char newpacket[65536]; /* Estimate of maximum packet size :) */
int copyat = i; /* Same */
int iCopy = 0; /* How much data have we written to copy-back string? */
unsigned long org_addr; /* Original IP address */
unsigned short org_port; /* Original source port address */
lCTCP_START:
if( i >= dlen || iCopy >= sizeof(newpacket) )
goto lPACKET_DONE;
newpacket[iCopy++] = sptr[i++]; /* Copy the CTCP start character */
/* Start of a CTCP */
if( i+4 >= dlen ) /* Too short for DCC */
goto lBAD_CTCP;
if( sptr[i+0] != 'D' )
goto lBAD_CTCP;
if( sptr[i+1] != 'C' )
goto lBAD_CTCP;
if( sptr[i+2] != 'C' )
goto lBAD_CTCP;
if( sptr[i+3] != ' ' )
goto lBAD_CTCP;
/* We have a DCC command - handle it! */
i+= 4; /* Skip "DCC " */
if( iCopy+4 > sizeof(newpacket) )
goto lPACKET_DONE;
newpacket[iCopy++] = 'D';
newpacket[iCopy++] = 'C';
newpacket[iCopy++] = 'C';
newpacket[iCopy++] = ' ';
DBprintf(("Found DCC\n"));
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway */
while(sptr[i] == ' ') {
if( ++i >= dlen) {
DBprintf(("DCC packet terminated in just spaces\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Transferring command...\n"));
while(sptr[i] != ' ') {
newpacket[iCopy++] = sptr[i];
if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
DBprintf(("DCC packet terminated during command\n"));
goto lPACKET_DONE;
}
}
/* Copy _one_ space */
if( i+1 < dlen && iCopy < sizeof(newpacket) )
newpacket[iCopy++] = sptr[i++];
DBprintf(("Done command - removing spaces\n"));
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway */
while(sptr[i] == ' ') {
if( ++i >= dlen ) {
DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Transferring filename...\n"));
while(sptr[i] != ' ') {
newpacket[iCopy++] = sptr[i];
if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
DBprintf(("DCC packet terminated during filename\n"));
goto lPACKET_DONE;
}
}
/* Copy _one_ space */
if( i+1 < dlen && iCopy < sizeof(newpacket) )
newpacket[iCopy++] = sptr[i++];
DBprintf(("Done filename - removing spaces\n"));
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway */
while(sptr[i] == ' ') {
if( ++i >= dlen ) {
DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Fetching IP address\n"));
/* Fetch IP address */
org_addr = 0;
while(i<dlen && isdigit(sptr[i])) {
if( org_addr > ULONG_MAX/10UL ) { /* Terminate on overflow */
DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
goto lBAD_CTCP;
}
org_addr *= 10;
org_addr += sptr[i++]-'0';
}
DBprintf(("Skipping space\n"));
if( i+1 >= dlen || sptr[i] != ' ' ) {
DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i+1, dlen, sptr[i]));
goto lBAD_CTCP;
}
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway, so we might
as well play it safe */
while(sptr[i] == ' ') {
if( ++i >= dlen ) {
DBprintf(("Packet failure - space overflow.\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Fetching port number\n"));
/* Fetch source port */
org_port = 0;
while(i<dlen && isdigit(sptr[i])) {
if( org_port > 6554 ) { /* Terminate on overflow (65536/10 rounded up*/
DBprintf(("DCC: port number overflow\n"));
goto lBAD_CTCP;
}
org_port *= 10;
org_port += sptr[i++]-'0';
}
/* Skip illegal addresses (or early termination) */
if( i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ') ) {
DBprintf(("Bad port termination\n"));
goto lBAD_CTCP;
}
DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));
/* We've got the address and port - now alias it */
{
struct alias_link *dcc_link;
struct in_addr destaddr;
true_port = htons(org_port);
true_addr.s_addr = htonl(org_addr);
destaddr.s_addr = 0;
/* Steal the FTP_DATA_PORT - it doesn't really matter, and this
would probably allow it through at least _some_
firewalls. */
dcc_link = FindUdpTcpOut (true_addr,
destaddr,
true_port,
0, IPPROTO_TCP);
DBprintf(("Got a DCC link\n"));
if ( dcc_link ) {
struct in_addr alias_address; /* Address from aliasing */
u_short alias_port; /* Port given by aliasing */
alias_address = GetAliasAddress(link);
iCopy += snprintf(&newpacket[iCopy],
sizeof(newpacket)-iCopy,
"%lu ", htonl(alias_address.s_addr));
if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */
DBprintf(("DCC constructed packet overflow.\n"));
goto lBAD_CTCP;
}
alias_port = GetAliasPort(dcc_link);
iCopy += snprintf(&newpacket[iCopy],
sizeof(newpacket)-iCopy,
"%u", htons(alias_port) );
/* Done - truncated cases will be taken care of by lBAD_CTCP */
DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
}
}
/* An uninteresting CTCP - state entered right after '\001' has
been pushed. Also used to copy the rest of a DCC, after IP
address and port has been handled */
lBAD_CTCP:
for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
if(sptr[i] == '\001') {
goto lNORMAL_TEXT;
}
}
goto lPACKET_DONE;
/* Normal text */
lNORMAL_TEXT:
for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
if(sptr[i] == '\001') {
goto lCTCP_START;
}
}
/* Handle the end of a packet */
lPACKET_DONE:
iCopy = iCopy > maxsize-copyat ? maxsize-copyat : iCopy;
memcpy(sptr+copyat, newpacket, iCopy);
/* Save information regarding modified seq and ack numbers */
{
int delta;
SetAckModified(link);
delta = GetDeltaSeqOut(pip, link);
AddSeq(pip, link, delta+copyat+iCopy-dlen);
}
/* Revise IP header */
{
u_short new_len;
new_len = htons(hlen + iCopy + copyat);
DifferentialChecksum(&pip->ip_sum,
&new_len,
&pip->ip_len,
1);
pip->ip_len = new_len;
}
/* Compute TCP checksum for revised packet */
tc->th_sum = 0;
tc->th_sum = TcpChecksum(pip);
return;
}
}
/* Notes:
[Note 1]
The initial search will most often fail; it could be replaced with a 32-bit specific search.
Such a search would be done for 32-bit unsigned value V:
V ^= 0x01010101; (Search is for null bytes)
if( ((V-0x01010101)^V) & 0x80808080 ) {
(found a null bytes which was a 01 byte)
}
To assert that the processor is 32-bits, do
extern int ircdccar[32]; (32 bits)
extern int ircdccar[CHAR_BIT*sizeof(unsigned int)];
which will generate a type-error on all but 32-bit machines.
[Note 2] This routine really ought to be replaced with one that
creates a transparent proxy on the aliasing host, to allow arbitary
changes in the TCP stream. This should not be too difficult given
this base; I (ee) will try to do this some time later.
*/

View File

@ -0,0 +1,91 @@
/* -*- mode: c; tab-width: 3; c-basic-offset: 3; -*-
Alias_local.h contains the function prototypes for alias.c,
alias_db.c, alias_util.c and alias_ftp.c, alias_irc.c (as well
as any future add-ons). It is intended to be used only within
the aliasing software. Outside world interfaces are defined
in alias.h
This software is placed into the public domain with no restrictions
on its distribution.
Initial version: August, 1996 (cjm)
<updated several times by original author and Eivind Eiklund>
*/
extern int packetAliasMode;
struct alias_link;
/* General utilities */
u_short IpChecksum(struct ip *);
u_short TcpChecksum(struct ip *);
void DifferentialChecksum(u_short *, u_short *, u_short *, int);
/* Internal data access */
struct alias_link *
FindIcmpIn(struct in_addr, struct in_addr, u_short);
struct alias_link *
FindIcmpOut(struct in_addr, struct in_addr, u_short);
struct alias_link *
FindFragmentIn1(struct in_addr, struct in_addr, u_short);
struct alias_link *
FindFragmentIn2(struct in_addr, struct in_addr, u_short);
struct alias_link *
AddFragmentPtrLink(struct in_addr, u_short);
struct alias_link *
FindFragmentPtr(struct in_addr, u_short);
struct alias_link *
FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
struct alias_link *
FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
struct in_addr
FindOriginalAddress(struct in_addr);
struct in_addr
FindAliasAddress(struct in_addr);
/* External data access/modification */
void GetFragmentAddr(struct alias_link *, struct in_addr *);
void SetFragmentAddr(struct alias_link *, struct in_addr);
void GetFragmentPtr(struct alias_link *, char **);
void SetFragmentPtr(struct alias_link *, char *);
void SetStateIn(struct alias_link *, int);
void SetStateOut(struct alias_link *, int);
int GetStateIn(struct alias_link *);
int GetStateOut(struct alias_link *);
struct in_addr GetOriginalAddress(struct alias_link *);
struct in_addr GetDestAddress(struct alias_link *);
struct in_addr GetAliasAddress(struct alias_link *);
struct in_addr GetDefaultAliasAddress(void);
void SetDefaultAliasAddress(struct in_addr);
void SetDefaultTargetAddress(struct in_addr);
void ClearDefaultTargetAddress(void);
u_short GetOriginalPort(struct alias_link *);
u_short GetAliasPort(struct alias_link *);
void SetAckModified(struct alias_link *);
int GetAckModified(struct alias_link *);
int GetDeltaAckIn(struct ip *, struct alias_link *);
int GetDeltaSeqOut(struct ip *, struct alias_link *);
void AddSeq(struct ip *, struct alias_link *, int);
void SetExpire(struct alias_link *, int);
void ClearNewDefaultLink(void);
int CheckNewDefaultLink(void);
/* Housekeeping function */
void HouseKeeping(void);
/* Tcp specfic routines */
/*lint -save -library Suppress flexelint warnings */
void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
/*lint -restore */

135
lib/libalias/alias_util.c Normal file
View File

@ -0,0 +1,135 @@
/*
Alias_util.h contains general utilities used by other functions
in the packet aliasing module. At the moment, there are functions
for computing IP header and TCP packet checksums.
The checksum routines are based upon example code in a Unix networking
text written by Stevens (sorry, I can't remember the title -- but
at least this is a good author).
Initial Version: August, 1996 (cjm)
Version 1.7: January 9, 1997
Added differential checksum update function.
*/
/*
Note: the checksum routines assume that the actual checksum word has
been zeroed out. If the checksum workd is filled with the proper value,
then these routines will give a result of zero (useful for testing
purposes);
*/
#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"
u_short
InternetChecksum(u_short *ptr, int nbytes)
{
int sum, oddbyte;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
u_short
IpChecksum(struct ip *pip)
{
return( InternetChecksum((u_short *) pip, (pip->ip_hl << 2)) );
}
u_short
TcpChecksum(struct ip *pip)
{
u_short *ptr;
struct tcphdr *tc;
int nhdr, ntcp, nbytes;
int sum, oddbyte;
nhdr = pip->ip_hl << 2;
ntcp = ntohs(pip->ip_len) - nhdr;
tc = (struct tcphdr *) ((char *) pip + nhdr);
ptr = (u_short *) tc;
/* Add up TCP header and data */
nbytes = ntcp;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
/* "Pseudo-header" data */
ptr = (u_short *) &(pip->ip_dst);
sum += *ptr++;
sum += *ptr;
ptr = (u_short *) &(pip->ip_src);
sum += *ptr++;
sum += *ptr;
sum += htons((u_short) ntcp);
sum += htons((u_short) pip->ip_p);
/* Roll over carry bits */
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
/* Return checksum */
return((u_short) ~sum);
}
void
DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
{
int i;
int accumulate;
accumulate = *cksum;
for (i=0; i<n; i++)
{
accumulate -= *new++;
accumulate += *old++;
}
if (accumulate < 0)
{
accumulate = -accumulate;
accumulate = (accumulate >> 16) + (accumulate & 0xffff);
accumulate += accumulate >> 16;
*cksum = (u_short) ~accumulate;
}
else
{
accumulate = (accumulate >> 16) + (accumulate & 0xffff);
accumulate += accumulate >> 16;
*cksum = (u_short) accumulate;
}
}

View File

@ -0,0 +1,11 @@
LIB= alias
SHLIB_MAJOR= 2
SHLIB_MINOR= 1
CFLAGS+=-Wall -I${.CURDIR}
SRCS= alias.c alias_db.c alias_ftp.c alias_irc.c alias_util.c
beforeinstall:
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/alias.h \
${DESTDIR}/usr/include
.include <bsd.lib.mk>

1142
sys/netinet/libalias/alias.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
/*lint -save -library Flexelint comment for external headers */
/*
Alias.h defines the outside world interfaces for the packet
aliasing software.
This software is placed into the public domain with no restrictions
on its distribution.
*/
#ifndef _ALIAS_H_
#define _ALIAS_H_
/* Alias link representativei (incomplete struct) */
struct alias_link;
/* External interfaces (API) to packet aliasing engine */
extern int SaveFragmentPtr(char *);
extern char *GetNextFragmentPtr(char *);
extern void FragmentAliasIn(char *, char *);
extern int PacketAliasIn(char *, int maxpacketsize);
extern int PacketAliasOut(char *, int maxpacketsize);
extern int PacketAliasIn2(char *, struct in_addr, int maxpacketsize);
extern int PacketAliasOut2(char *, struct in_addr, int maxpacketsize);
extern void SetPacketAliasAddress(struct in_addr);
extern void InitPacketAlias(void);
extern void InitPacketAliasLog(void);
extern void UninitPacketAliasLog(void);
extern unsigned int SetPacketAliasMode(unsigned int, unsigned int);
extern struct alias_link *
PacketAliasRedirectPort(struct in_addr, u_short,
struct in_addr, u_short,
struct in_addr, u_short,
u_char);
extern int
PacketAliasPermanentLink(struct in_addr, u_short,
struct in_addr, u_short,
u_short, u_char);
extern struct alias_link *
PacketAliasRedirectAddr(struct in_addr,
struct in_addr);
void PacketAliasRedirectDelete(struct alias_link *);
/* InternetChecksum() is not specifically part of the
packet aliasing API, but is sometimes needed outside
the module. (~for instance, natd uses it to create
an ICMP error message when interface size is
exceeded.) */
extern u_short InternetChecksum(u_short *, int);
/********************** Mode flags ********************/
/* Set these flags using SetPacketAliasMode() */
/* If PKT_ALIAS_LOG is set, a message will be printed to
/var/log/alias.log every time a link is created or deleted. This
is useful for debugging */
#define PKT_ALIAS_LOG 1
/* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g.
to ftp, telnet or web servers will be prevented by the aliasing
mechanism. */
#define PKT_ALIAS_DENY_INCOMING 2
/* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from
the same port as they originated on. This allow eg rsh to work
*99% of the time*, but _not_ 100%. (It will be slightly flakey
instead of not working at all.) */
#define PKT_ALIAS_SAME_PORTS 4
/* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified
links (e.g. destination port and/or address is zero), the packet
aliasing engine will attempt to allocate a socket for the aliasing
port it chooses. This will avoid interference with the host
machine. Fully specified links do not require this. */
#define PKT_ALIAS_USE_SOCKETS 8
/* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with with
unregistered source addresses will be aliased (along with those
of the ppp host maching itself. Private addresses are those
in the following ranges:
10.0.0.0 -> 10.255.255.255
172.16.0.0 -> 172.31.255.255
192.168.0.0 -> 192.168.255.255 */
#define PKT_ALIAS_UNREGISTERED_ONLY 16
/* Return Codes */
#define PKT_ALIAS_ERROR -1
#define PKT_ALIAS_OK 1
#define PKT_ALIAS_IGNORED 2
#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
#define PKT_ALIAS_NEW_LINK 5
#endif
/*lint -restore */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
/*
Alias_ftp.c performs special processing for FTP sessions under
TCP. Specifically, when a PORT command from the client side
is sent, it is intercepted and modified. The address is changed
to the gateway machine and an aliasing port is used.
For this routine to work, the PORT command must fit entirely
into a single TCP packet. This is typically the case, but exceptions
can easily be envisioned under the actual specifications.
Probably the most troubling aspect of the approach taken here is
that the new PORT command will typically be a different length, and
this causes a certain amount of bookkeeping to keep track of the
changes of sequence and acknowledgment numbers, since the client
machine is totally unaware of the modification to the TCP stream.
This software is placed into the public domain with no restrictions
on its distribution.
Initial version: August, 1996 (cjm)
Version 1.6
Brian Somers and Martin Renters identified an IP checksum
error for modified IP packets.
Version 1.7: January 9, 1996 (cjm)
Differental checksum computation for change
in IP packet length.
Version 2.1: May, 1997 (cjm)
Very minor changes to conform with
local/global/function naming conventions
withing the packet alising module.
*/
/* Includes */
#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, /* IP packet to examine/patch */
struct alias_link *link, /* The link to go through (aliased port) */
int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
{
int hlen, tlen, dlen;
struct in_addr true_addr;
u_short true_port;
char *sptr;
struct tcphdr *tc;
/* Calculate data length of TCP packet */
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;
/* Return is data length is too long or too short */
if (dlen<10 || dlen>80)
return;
/* Place string pointer and beginning of data */
sptr = (char *) pip;
sptr += hlen;
/* Parse through string using state diagram method */
{
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;
/* Establish link to address and port found in PORT command */
ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
true_port, 0, IPPROTO_TCP);
if (ftp_link != NULL)
{
int slen, hlen, tlen, dlen;
struct tcphdr *tc;
/* Calculate data length of TCP packet */
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;
/* Create new PORT command */
{
char stemp[80];
char *sptr;
u_short alias_port;
u_char *ptr;
int a1, a2, a3, a4, p1, p2;
struct in_addr alias_address;
/* Decompose alias address into quad format */
alias_address = GetAliasAddress(link);
ptr = (char *) &alias_address;
a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
/* Decompose alias port into pair format */
alias_port = GetAliasPort(ftp_link);
ptr = (char *) &alias_port;
p1 = *ptr++; p2=*ptr;
/* Generate command string */
sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
a1,a2,a3,a4,p1,p2);
/* Save string length for IP header modification */
slen = strlen(stemp);
/* Copy into IP packet */
sptr = (char *) pip; sptr += hlen;
strncpy(sptr, stemp, maxpacketsize-hlen);
}
/* Save information regarding modified seq and ack numbers */
{
int delta;
SetAckModified(link);
delta = GetDeltaSeqOut(pip, link);
AddSeq(pip, link, delta+slen-dlen);
}
/* Revise IP header */
{
u_short new_len;
new_len = htons(hlen + slen);
DifferentialChecksum(&pip->ip_sum,
&new_len,
&pip->ip_len,
1);
pip->ip_len = new_len;
}
/* Compute TCP checksum for revised packet */
tc->th_sum = 0;
tc->th_sum = TcpChecksum(pip);
}
else
{
fprintf(stderr,
"PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
}
}

View File

@ -0,0 +1,311 @@
/* Alias_irc.c intercepts packages contain IRC CTCP commands, and
changes DCC commands to export a port on the aliasing host instead
of an aliased host.
For this routine to work, the DCC command must fit entirely into a
single TCP packet. This will usually happen, but is not
guaranteed.
The interception is likely to change the length of the packet.
The handling of this is copied more-or-less verbatim from
ftp_alias.c
This software is placed into the public domain with no restrictions
on its distribution.
Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
Version 2.1: May, 1997 (cjm)
Very minor changes to conform with
local/global/function naming conventions
withing the packet alising module.
*/
/* Includes */
#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 <limits.h>
#include "alias_local.h"
/* Local defines */
#define DBprintf(a)
void
AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */
struct alias_link *link, /* Which link are we on? */
int maxsize /* Maximum size of IP packet including headers */
)
{
int hlen, tlen, dlen;
struct in_addr true_addr;
u_short true_port;
char *sptr;
struct tcphdr *tc;
int i; /* Iterator through the source */
/* Calculate data length of TCP packet */
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;
/* Return if data length is too short - assume an entire PRIVMSG in each packet. */
if (dlen<sizeof(":A!a@n.n PRIVMSG A :aDCC 1 1a")-1)
return;
/* Place string pointer at beginning of data */
sptr = (char *) pip;
sptr += hlen;
maxsize -= hlen; /* We're interested in maximum size of data, not packet */
/* Search for a CTCP command [Note 1] */
for( i=0; i<dlen; i++ ) {
if(sptr[i]=='\001')
goto lFOUND_CTCP;
}
return; /* No CTCP commands in */
/* Handle CTCP commands - the buffer may have to be copied */
lFOUND_CTCP:
{
char newpacket[65536]; /* Estimate of maximum packet size :) */
int copyat = i; /* Same */
int iCopy = 0; /* How much data have we written to copy-back string? */
unsigned long org_addr; /* Original IP address */
unsigned short org_port; /* Original source port address */
lCTCP_START:
if( i >= dlen || iCopy >= sizeof(newpacket) )
goto lPACKET_DONE;
newpacket[iCopy++] = sptr[i++]; /* Copy the CTCP start character */
/* Start of a CTCP */
if( i+4 >= dlen ) /* Too short for DCC */
goto lBAD_CTCP;
if( sptr[i+0] != 'D' )
goto lBAD_CTCP;
if( sptr[i+1] != 'C' )
goto lBAD_CTCP;
if( sptr[i+2] != 'C' )
goto lBAD_CTCP;
if( sptr[i+3] != ' ' )
goto lBAD_CTCP;
/* We have a DCC command - handle it! */
i+= 4; /* Skip "DCC " */
if( iCopy+4 > sizeof(newpacket) )
goto lPACKET_DONE;
newpacket[iCopy++] = 'D';
newpacket[iCopy++] = 'C';
newpacket[iCopy++] = 'C';
newpacket[iCopy++] = ' ';
DBprintf(("Found DCC\n"));
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway */
while(sptr[i] == ' ') {
if( ++i >= dlen) {
DBprintf(("DCC packet terminated in just spaces\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Transferring command...\n"));
while(sptr[i] != ' ') {
newpacket[iCopy++] = sptr[i];
if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
DBprintf(("DCC packet terminated during command\n"));
goto lPACKET_DONE;
}
}
/* Copy _one_ space */
if( i+1 < dlen && iCopy < sizeof(newpacket) )
newpacket[iCopy++] = sptr[i++];
DBprintf(("Done command - removing spaces\n"));
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway */
while(sptr[i] == ' ') {
if( ++i >= dlen ) {
DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Transferring filename...\n"));
while(sptr[i] != ' ') {
newpacket[iCopy++] = sptr[i];
if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
DBprintf(("DCC packet terminated during filename\n"));
goto lPACKET_DONE;
}
}
/* Copy _one_ space */
if( i+1 < dlen && iCopy < sizeof(newpacket) )
newpacket[iCopy++] = sptr[i++];
DBprintf(("Done filename - removing spaces\n"));
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway */
while(sptr[i] == ' ') {
if( ++i >= dlen ) {
DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Fetching IP address\n"));
/* Fetch IP address */
org_addr = 0;
while(i<dlen && isdigit(sptr[i])) {
if( org_addr > ULONG_MAX/10UL ) { /* Terminate on overflow */
DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
goto lBAD_CTCP;
}
org_addr *= 10;
org_addr += sptr[i++]-'0';
}
DBprintf(("Skipping space\n"));
if( i+1 >= dlen || sptr[i] != ' ' ) {
DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i+1, dlen, sptr[i]));
goto lBAD_CTCP;
}
/* Skip any extra spaces (should not occur according to
protocol, but DCC breaks CTCP protocol anyway, so we might
as well play it safe */
while(sptr[i] == ' ') {
if( ++i >= dlen ) {
DBprintf(("Packet failure - space overflow.\n"));
goto lPACKET_DONE;
}
}
DBprintf(("Fetching port number\n"));
/* Fetch source port */
org_port = 0;
while(i<dlen && isdigit(sptr[i])) {
if( org_port > 6554 ) { /* Terminate on overflow (65536/10 rounded up*/
DBprintf(("DCC: port number overflow\n"));
goto lBAD_CTCP;
}
org_port *= 10;
org_port += sptr[i++]-'0';
}
/* Skip illegal addresses (or early termination) */
if( i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ') ) {
DBprintf(("Bad port termination\n"));
goto lBAD_CTCP;
}
DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));
/* We've got the address and port - now alias it */
{
struct alias_link *dcc_link;
struct in_addr destaddr;
true_port = htons(org_port);
true_addr.s_addr = htonl(org_addr);
destaddr.s_addr = 0;
/* Steal the FTP_DATA_PORT - it doesn't really matter, and this
would probably allow it through at least _some_
firewalls. */
dcc_link = FindUdpTcpOut (true_addr,
destaddr,
true_port,
0, IPPROTO_TCP);
DBprintf(("Got a DCC link\n"));
if ( dcc_link ) {
struct in_addr alias_address; /* Address from aliasing */
u_short alias_port; /* Port given by aliasing */
alias_address = GetAliasAddress(link);
iCopy += snprintf(&newpacket[iCopy],
sizeof(newpacket)-iCopy,
"%lu ", htonl(alias_address.s_addr));
if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */
DBprintf(("DCC constructed packet overflow.\n"));
goto lBAD_CTCP;
}
alias_port = GetAliasPort(dcc_link);
iCopy += snprintf(&newpacket[iCopy],
sizeof(newpacket)-iCopy,
"%u", htons(alias_port) );
/* Done - truncated cases will be taken care of by lBAD_CTCP */
DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
}
}
/* An uninteresting CTCP - state entered right after '\001' has
been pushed. Also used to copy the rest of a DCC, after IP
address and port has been handled */
lBAD_CTCP:
for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
if(sptr[i] == '\001') {
goto lNORMAL_TEXT;
}
}
goto lPACKET_DONE;
/* Normal text */
lNORMAL_TEXT:
for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
if(sptr[i] == '\001') {
goto lCTCP_START;
}
}
/* Handle the end of a packet */
lPACKET_DONE:
iCopy = iCopy > maxsize-copyat ? maxsize-copyat : iCopy;
memcpy(sptr+copyat, newpacket, iCopy);
/* Save information regarding modified seq and ack numbers */
{
int delta;
SetAckModified(link);
delta = GetDeltaSeqOut(pip, link);
AddSeq(pip, link, delta+copyat+iCopy-dlen);
}
/* Revise IP header */
{
u_short new_len;
new_len = htons(hlen + iCopy + copyat);
DifferentialChecksum(&pip->ip_sum,
&new_len,
&pip->ip_len,
1);
pip->ip_len = new_len;
}
/* Compute TCP checksum for revised packet */
tc->th_sum = 0;
tc->th_sum = TcpChecksum(pip);
return;
}
}
/* Notes:
[Note 1]
The initial search will most often fail; it could be replaced with a 32-bit specific search.
Such a search would be done for 32-bit unsigned value V:
V ^= 0x01010101; (Search is for null bytes)
if( ((V-0x01010101)^V) & 0x80808080 ) {
(found a null bytes which was a 01 byte)
}
To assert that the processor is 32-bits, do
extern int ircdccar[32]; (32 bits)
extern int ircdccar[CHAR_BIT*sizeof(unsigned int)];
which will generate a type-error on all but 32-bit machines.
[Note 2] This routine really ought to be replaced with one that
creates a transparent proxy on the aliasing host, to allow arbitary
changes in the TCP stream. This should not be too difficult given
this base; I (ee) will try to do this some time later.
*/

View File

@ -0,0 +1,91 @@
/* -*- mode: c; tab-width: 3; c-basic-offset: 3; -*-
Alias_local.h contains the function prototypes for alias.c,
alias_db.c, alias_util.c and alias_ftp.c, alias_irc.c (as well
as any future add-ons). It is intended to be used only within
the aliasing software. Outside world interfaces are defined
in alias.h
This software is placed into the public domain with no restrictions
on its distribution.
Initial version: August, 1996 (cjm)
<updated several times by original author and Eivind Eiklund>
*/
extern int packetAliasMode;
struct alias_link;
/* General utilities */
u_short IpChecksum(struct ip *);
u_short TcpChecksum(struct ip *);
void DifferentialChecksum(u_short *, u_short *, u_short *, int);
/* Internal data access */
struct alias_link *
FindIcmpIn(struct in_addr, struct in_addr, u_short);
struct alias_link *
FindIcmpOut(struct in_addr, struct in_addr, u_short);
struct alias_link *
FindFragmentIn1(struct in_addr, struct in_addr, u_short);
struct alias_link *
FindFragmentIn2(struct in_addr, struct in_addr, u_short);
struct alias_link *
AddFragmentPtrLink(struct in_addr, u_short);
struct alias_link *
FindFragmentPtr(struct in_addr, u_short);
struct alias_link *
FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
struct alias_link *
FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
struct in_addr
FindOriginalAddress(struct in_addr);
struct in_addr
FindAliasAddress(struct in_addr);
/* External data access/modification */
void GetFragmentAddr(struct alias_link *, struct in_addr *);
void SetFragmentAddr(struct alias_link *, struct in_addr);
void GetFragmentPtr(struct alias_link *, char **);
void SetFragmentPtr(struct alias_link *, char *);
void SetStateIn(struct alias_link *, int);
void SetStateOut(struct alias_link *, int);
int GetStateIn(struct alias_link *);
int GetStateOut(struct alias_link *);
struct in_addr GetOriginalAddress(struct alias_link *);
struct in_addr GetDestAddress(struct alias_link *);
struct in_addr GetAliasAddress(struct alias_link *);
struct in_addr GetDefaultAliasAddress(void);
void SetDefaultAliasAddress(struct in_addr);
void SetDefaultTargetAddress(struct in_addr);
void ClearDefaultTargetAddress(void);
u_short GetOriginalPort(struct alias_link *);
u_short GetAliasPort(struct alias_link *);
void SetAckModified(struct alias_link *);
int GetAckModified(struct alias_link *);
int GetDeltaAckIn(struct ip *, struct alias_link *);
int GetDeltaSeqOut(struct ip *, struct alias_link *);
void AddSeq(struct ip *, struct alias_link *, int);
void SetExpire(struct alias_link *, int);
void ClearNewDefaultLink(void);
int CheckNewDefaultLink(void);
/* Housekeeping function */
void HouseKeeping(void);
/* Tcp specfic routines */
/*lint -save -library Suppress flexelint warnings */
void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
/*lint -restore */

View File

@ -0,0 +1,135 @@
/*
Alias_util.h contains general utilities used by other functions
in the packet aliasing module. At the moment, there are functions
for computing IP header and TCP packet checksums.
The checksum routines are based upon example code in a Unix networking
text written by Stevens (sorry, I can't remember the title -- but
at least this is a good author).
Initial Version: August, 1996 (cjm)
Version 1.7: January 9, 1997
Added differential checksum update function.
*/
/*
Note: the checksum routines assume that the actual checksum word has
been zeroed out. If the checksum workd is filled with the proper value,
then these routines will give a result of zero (useful for testing
purposes);
*/
#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"
u_short
InternetChecksum(u_short *ptr, int nbytes)
{
int sum, oddbyte;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
u_short
IpChecksum(struct ip *pip)
{
return( InternetChecksum((u_short *) pip, (pip->ip_hl << 2)) );
}
u_short
TcpChecksum(struct ip *pip)
{
u_short *ptr;
struct tcphdr *tc;
int nhdr, ntcp, nbytes;
int sum, oddbyte;
nhdr = pip->ip_hl << 2;
ntcp = ntohs(pip->ip_len) - nhdr;
tc = (struct tcphdr *) ((char *) pip + nhdr);
ptr = (u_short *) tc;
/* Add up TCP header and data */
nbytes = ntcp;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *) &oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
/* "Pseudo-header" data */
ptr = (u_short *) &(pip->ip_dst);
sum += *ptr++;
sum += *ptr;
ptr = (u_short *) &(pip->ip_src);
sum += *ptr++;
sum += *ptr;
sum += htons((u_short) ntcp);
sum += htons((u_short) pip->ip_p);
/* Roll over carry bits */
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
/* Return checksum */
return((u_short) ~sum);
}
void
DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
{
int i;
int accumulate;
accumulate = *cksum;
for (i=0; i<n; i++)
{
accumulate -= *new++;
accumulate += *old++;
}
if (accumulate < 0)
{
accumulate = -accumulate;
accumulate = (accumulate >> 16) + (accumulate & 0xffff);
accumulate += accumulate >> 16;
*cksum = (u_short) ~accumulate;
}
else
{
accumulate = (accumulate >> 16) + (accumulate & 0xffff);
accumulate += accumulate >> 16;
*cksum = (u_short) accumulate;
}
}