mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-28 12:07:10 +01:00
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:
parent
3f72ab23cd
commit
3b160b8b6e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/CMOTT/; revision=26026
11
lib/libalias/Makefile
Normal file
11
lib/libalias/Makefile
Normal 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
1142
lib/libalias/alias.c
Normal file
File diff suppressed because it is too large
Load Diff
102
lib/libalias/alias.h
Normal file
102
lib/libalias/alias.h
Normal 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
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
220
lib/libalias/alias_ftp.c
Normal 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
311
lib/libalias/alias_irc.c
Normal 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.
|
||||
*/
|
91
lib/libalias/alias_local.h
Normal file
91
lib/libalias/alias_local.h
Normal 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
135
lib/libalias/alias_util.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
11
sys/netinet/libalias/Makefile
Normal file
11
sys/netinet/libalias/Makefile
Normal 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
1142
sys/netinet/libalias/alias.c
Normal file
File diff suppressed because it is too large
Load Diff
102
sys/netinet/libalias/alias.h
Normal file
102
sys/netinet/libalias/alias.h
Normal 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
sys/netinet/libalias/alias_db.c
Normal file
1972
sys/netinet/libalias/alias_db.c
Normal file
File diff suppressed because it is too large
Load Diff
220
sys/netinet/libalias/alias_ftp.c
Normal file
220
sys/netinet/libalias/alias_ftp.c
Normal 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
sys/netinet/libalias/alias_irc.c
Normal file
311
sys/netinet/libalias/alias_irc.c
Normal 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.
|
||||
*/
|
91
sys/netinet/libalias/alias_local.h
Normal file
91
sys/netinet/libalias/alias_local.h
Normal 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
sys/netinet/libalias/alias_util.c
Normal file
135
sys/netinet/libalias/alias_util.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user